diff options
Diffstat (limited to 'backend/unittests/Target')
| -rw-r--r-- | backend/unittests/Target/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVCallLoweringTest.cpp | 73 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVCodeGenTest.cpp | 279 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVFrameLoweringTest.cpp | 4 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVLateCodeGenTest.cpp | 2 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVRegisterAllocationTest.cpp | 2 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVSSAExitTest.cpp | 2 |
7 files changed, 171 insertions, 201 deletions
diff --git a/backend/unittests/Target/CMakeLists.txt b/backend/unittests/Target/CMakeLists.txt index 0b4ed74..3377f82 100644 --- a/backend/unittests/Target/CMakeLists.txt +++ b/backend/unittests/Target/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later +include_directories("${RCC_BACKEND_SOURCE_DIR}/lib/Target/RISCV") + add_library(RCCBackendTestTarget TestTarget.cpp) add_library(RCCBackend::TestTarget ALIAS RCCBackendTestTarget) @@ -34,10 +36,6 @@ target_link_libraries(RCCBackendRISCVCodeGenTests PRIVATE RCCBackend::RISCV RCCB add_test(NAME RCCBackendRISCVCodeGenTests COMMAND RCCBackendRISCVCodeGenTests) add_executable(RCCBackendRISCVSSAExitTests RISCVSSAExitTest.cpp) -target_include_directories( - RCCBackendRISCVSSAExitTests - PRIVATE "${RCC_BACKEND_SOURCE_DIR}/lib/Target/RISCV" -) rcc_backend_configure_target(RCCBackendRISCVSSAExitTests) target_link_libraries(RCCBackendRISCVSSAExitTests PRIVATE RCCBackend::RISCV RCCBackend::CodeGen) add_test(NAME RCCBackendRISCVSSAExitTests COMMAND RCCBackendRISCVSSAExitTests) @@ -65,10 +63,6 @@ add_test( ) add_executable(RCCBackendRISCVLateCodeGenTests RISCVLateCodeGenTest.cpp) -target_include_directories( - RCCBackendRISCVLateCodeGenTests - PRIVATE "${RCC_BACKEND_SOURCE_DIR}/lib/Target/RISCV" -) rcc_backend_configure_target(RCCBackendRISCVLateCodeGenTests) target_link_libraries( RCCBackendRISCVLateCodeGenTests diff --git a/backend/unittests/Target/RISCVCallLoweringTest.cpp b/backend/unittests/Target/RISCVCallLoweringTest.cpp index 33723b1..eee10ab 100644 --- a/backend/unittests/Target/RISCVCallLoweringTest.cpp +++ b/backend/unittests/Target/RISCVCallLoweringTest.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -#include "rcc/Target/RISCV/RISCVCallLowering.h" +#include "GISel/RISCVCallLowering.h" #include "rcc/CodeGen/GenericOpcodes.h" #include "rcc/CodeGen/MachineBasicBlock.h" @@ -11,6 +11,7 @@ #include "rcc/CodeGen/MachineMemOperand.h" #include "rcc/CodeGen/MachineOperand.h" #include "rcc/CodeGen/MachineVerifier.h" +#include "rcc/Target/RISCV/RISCVSubtarget.h" #include "rcc/Target/RISCV/RISCVTarget.h" #include <algorithm> @@ -29,6 +30,9 @@ namespace { +const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc()); +const rcc::TargetCallLowering &CallLowering = *Subtarget.getCallLowering(); + class TestContext final { public: void expect(bool Condition, std::string_view Message) { @@ -186,7 +190,7 @@ abiValue(rcc::LLT Type, std::uint32_t OriginalValue, rcc::Register Value = plann void testIntegerAndFloatingAssignments(TestContext &Context) { auto Integers = callRequest(integerValues(9), 9); - auto IntegerPlan = rcc::riscv::callLowering().planCall(Integers); + auto IntegerPlan = CallLowering.planCall(Integers); Context.expect(IntegerPlan.has_value(), "nine integer arguments must produce an LP64D call plan"); if (!IntegerPlan) return; @@ -207,7 +211,7 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { "LP64D integer arguments must use a0-a7 before a 16-byte stack area"); auto Floats = callRequest(floatingValues(17), 17); - auto FloatPlan = rcc::riscv::callLowering().planCall(Floats); + auto FloatPlan = CallLowering.planCall(Floats); Context.expect(FloatPlan.has_value(), "seventeen floating arguments must produce an LP64D call plan"); if (!FloatPlan) @@ -228,7 +232,7 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { auto Single = callRequest({abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)}, 1); Single.Results = {abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)}; - auto SinglePlan = rcc::riscv::callLowering().planCall(Single); + auto SinglePlan = CallLowering.planCall(Single); Context.expect(SinglePlan && SinglePlan->argumentAssignments().size() == 1 && SinglePlan->returnAssignments().size() == 1 && isLocation(SinglePlan->argumentAssignments()[0], @@ -246,7 +250,7 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { IntegerFragment.FragmentOffsetBytes = 8; IntegerFragment.OriginalAlignment = align(16); auto Mixed = callRequest({FloatFragment, IntegerFragment}, 1); - auto MixedPlan = rcc::riscv::callLowering().planCall(Mixed); + auto MixedPlan = CallLowering.planCall(Mixed); Context.expect(MixedPlan && MixedPlan->argumentAssignments().size() == 2 && isLocation(MixedPlan->argumentAssignments()[0], argumentFPR(0)) && isLocation(MixedPlan->argumentAssignments()[1], argumentGPR(0)), @@ -254,7 +258,7 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { auto GenericScalar = callRequest({abiValue(anyScalar(64), 0)}, 1); GenericScalar.Results = {abiValue(anyScalar(64), 0)}; - auto GenericScalarPlan = rcc::riscv::callLowering().planCall(GenericScalar); + auto GenericScalarPlan = CallLowering.planCall(GenericScalar); Context.expect(GenericScalarPlan && GenericScalarPlan->argumentAssignments().size() == 1 && GenericScalarPlan->returnAssignments().size() == 1 && GenericScalarPlan->argumentAssignments()[0].ValueType == anyScalar(64) && @@ -264,7 +268,7 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { auto LP64Float = callRequest({abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0)}, 1); LP64Float.Convention = rcc::riscv::callingConventionID(rcc::riscv::CallingConvention::LP64); LP64Float.Results = {abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0)}; - auto LP64Plan = rcc::riscv::callLowering().planCall(LP64Float); + auto LP64Plan = CallLowering.planCall(LP64Float); const auto LP64Mask = rcc::riscv::createCallPreservedMask(rcc::riscv::CallingConvention::LP64); Context.expect( LP64Plan && LP64Plan->argumentAssignments().size() == 1 && @@ -279,11 +283,11 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { auto Narrow = abiValue(integer(32), 0); auto InvalidNarrow = callRequest({Narrow}, 1); - Context.expect(!rcc::riscv::callLowering().planCall(InvalidNarrow), + Context.expect(!CallLowering.planCall(InvalidNarrow), "a narrow integer without an explicit ABI extension must be rejected"); Narrow.Extension = rcc::ABIExtensionKind::SignExtend; auto ExtendedNarrow = callRequest({Narrow}, 1); - auto NarrowPlan = rcc::riscv::callLowering().planCall(ExtendedNarrow); + auto NarrowPlan = CallLowering.planCall(ExtendedNarrow); Context.expect(NarrowPlan && NarrowPlan->argumentAssignments()[0].LocationType == integer(64) && NarrowPlan->argumentAssignments()[0].Extension == rcc::ABIExtensionKind::SignExtend, @@ -294,7 +298,7 @@ void testVariadicAssignments(TestContext &Context) { auto FixedFloat = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0); auto VariableFloat = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 1); auto Request = callRequest({FixedFloat, VariableFloat}, 1, true); - auto Plan = rcc::riscv::callLowering().planCall(Request); + auto Plan = CallLowering.planCall(Request); Context.expect( Plan && isLocation(Plan->argumentAssignments()[0], argumentFPR(0)) && isLocation(Plan->argumentAssignments()[1], argumentGPR(0)) && @@ -312,7 +316,7 @@ void testVariadicAssignments(TestContext &Context) { PairHigh.FragmentOffsetBytes = 8; PairHigh.OriginalAlignment = align(16); auto PairRequest = callRequest({FixedInteger, PairLow, PairHigh}, 1, true); - auto PairPlan = rcc::riscv::callLowering().planCall(PairRequest); + auto PairPlan = CallLowering.planCall(PairRequest); Context.expect(PairPlan && isLocation(PairPlan->argumentAssignments()[0], argumentGPR(0)) && isLocation(PairPlan->argumentAssignments()[1], argumentGPR(2)) && isLocation(PairPlan->argumentAssignments()[2], argumentGPR(3)), @@ -323,7 +327,7 @@ void testVariadicAssignments(TestContext &Context) { Formal.Arguments = {FixedInteger}; Formal.FixedArgumentCount = 1; Formal.IsVariadic = true; - auto FormalPlan = rcc::riscv::callLowering().planFormalArguments(Formal); + auto FormalPlan = CallLowering.planFormalArguments(Formal); Context.expect(FormalPlan && FormalPlan->varArgs().IsVariadic && FormalPlan->varArgs().FirstUnallocatedIntegerRegister == 1 && FormalPlan->varArgs().RegisterSaveAreaSizeBytes == 56 && @@ -341,7 +345,7 @@ void testSpecialArgumentsAndReturns(TestContext &Context) { ByVal.ByValSizeBytes = 24; ByVal.ByValAlignment = align(16); auto ByValRequest = callRequest({ByVal}, 1); - auto ByValPlan = rcc::riscv::callLowering().planCall(ByValRequest); + auto ByValPlan = CallLowering.planCall(ByValRequest); Context.expect( ByValPlan && ByValPlan->byValCopies().size() == 1 && ByValPlan->byValCopies()[0].StackOffsetBytes == 0 && @@ -351,23 +355,23 @@ void testSpecialArgumentsAndReturns(TestContext &Context) { auto SRet = abiValue(pointer(), 0); SRet.Flags.set(rcc::ABIValueFlag::StructReturn); - auto SRetPlan = rcc::riscv::callLowering().planCall(callRequest({SRet}, 1)); + auto SRetPlan = CallLowering.planCall(callRequest({SRet}, 1)); Context.expect( SRetPlan && isLocation(SRetPlan->argumentAssignments()[0], argumentGPR(0)) && SRetPlan->argumentAssignments()[0].CustomFlags.has(rcc::CCAssignmentFlag::StructReturn), "sret must be carried as the first integer argument"); auto SRetWithDirectResult = callRequest({SRet}, 1); SRetWithDirectResult.Results = {abiValue(integer(64), 0)}; - Context.expect(!rcc::riscv::callLowering().planCall(SRetWithDirectResult), + Context.expect(!CallLowering.planCall(SRetWithDirectResult), "an sret call cannot also expose direct ABI return registers"); auto Plain = abiValue(integer(64), 0); SRet.OriginalValue = 1; - Context.expect(!rcc::riscv::callLowering().planCall(callRequest({Plain, SRet}, 2)), + Context.expect(!CallLowering.planCall(callRequest({Plain, SRet}, 2)), "sret outside the first argument position must be rejected"); auto Indirect = abiValue(pointer(), 0); Indirect.Flags.set(rcc::ABIValueFlag::Indirect); - auto IndirectPlan = rcc::riscv::callLowering().planCall(callRequest({Indirect}, 1)); + auto IndirectPlan = CallLowering.planCall(callRequest({Indirect}, 1)); Context.expect( IndirectPlan && IndirectPlan->argumentAssignments()[0].LocationKind == rcc::CCLocationKind::Indirect && @@ -376,14 +380,14 @@ void testSpecialArgumentsAndReturns(TestContext &Context) { auto InRegister = integerValues(9); InRegister.back().Flags.set(rcc::ABIValueFlag::InRegister); - Context.expect(!rcc::riscv::callLowering().planCall(callRequest(std::move(InRegister), 9)), + Context.expect(!CallLowering.planCall(callRequest(std::move(InRegister), 9)), "an inreg argument that would spill to the stack must be rejected"); rcc::ReturnLoweringRequest Return; Return.Convention = convention(); Return.Values = {abiValue(integer(64), 0), abiValue(floating(rcc::FloatSemantics::IEEEDouble), 1)}; - auto ReturnPlan = rcc::riscv::callLowering().planReturn(Return); + auto ReturnPlan = CallLowering.planReturn(Return); Context.expect(ReturnPlan && ReturnPlan->returnAssignments().size() == 2 && isLocation(ReturnPlan->returnAssignments()[0], returnGPR(0)) && isLocation(ReturnPlan->returnAssignments()[1], returnFPR(0)), @@ -402,14 +406,14 @@ void testTailCalls(TestContext &Context) { auto Tail = callRequest({}, 0); Tail.TailKind = rcc::TailCallKind::Tail; Tail.TailContext = emptyTailContext(); - auto TailPlan = rcc::riscv::callLowering().planCall(Tail); + auto TailPlan = CallLowering.planCall(Tail); Context.expect(TailPlan && TailPlan->tailDecision() == rcc::TailCallKind::Tail && TailPlan->callFrame().ReusesIncomingArea && !TailPlan->callFrame().EmitSetup, "an ABI-compatible tail call must reuse the incoming argument area"); auto Fallback = callRequest({}, 0); Fallback.TailKind = rcc::TailCallKind::Tail; - auto FallbackPlan = rcc::riscv::callLowering().planCall(Fallback); + auto FallbackPlan = CallLowering.planCall(Fallback); Context.expect(FallbackPlan && FallbackPlan->tailDecision() == rcc::TailCallKind::NotTail && !FallbackPlan->tailRejectionReason().empty() && FallbackPlan->callFrame().EmitSetup, @@ -417,7 +421,7 @@ void testTailCalls(TestContext &Context) { auto MustTail = callRequest({}, 0); MustTail.TailKind = rcc::TailCallKind::MustTail; - auto MustTailPlan = rcc::riscv::callLowering().planCall(MustTail); + auto MustTailPlan = CallLowering.planCall(MustTail); Context.expect(!MustTailPlan && MustTailPlan.error().code() == rcc::ErrorCode::Unsupported, "an incompatible musttail call must fail instead of falling back"); @@ -427,7 +431,7 @@ void testTailCalls(TestContext &Context) { StackContext.CallerFixedArgumentCount = 9; StackContext.ReusableIncomingArgumentBytes = 16; StackTail.TailContext = std::move(StackContext); - auto StackTailPlan = rcc::riscv::callLowering().planCall(StackTail); + auto StackTailPlan = CallLowering.planCall(StackTail); Context.expect(StackTailPlan && StackTailPlan->tailDecision() == rcc::TailCallKind::Tail && StackTailPlan->callFrame().SizeBytes == 16, "a tail call may reuse a sufficiently large incoming stack argument area"); @@ -506,7 +510,7 @@ void testOrdinaryAndIndirectEmission(TestContext &Context) { rcc::MachineIRBuilder Builder(*Function, *Target); Context.expect(Builder.setInsertPoint(*Block).has_value(), "ordinary-call insertion point must be valid"); - auto Lowered = rcc::riscv::callLowering().lowerCall(Builder, Request); + auto Lowered = CallLowering.lowerCall(Builder, Request); Context.expect(Lowered.has_value(), "ordinary direct call emission must succeed"); if (!Lowered) return; @@ -602,7 +606,7 @@ void testOrdinaryAndIndirectEmission(TestContext &Context) { rcc::MachineIRBuilder IndirectBuilder(*IndirectFunction, *Target); if (!IndirectBuilder.setInsertPoint(*IndirectBlock)) return; - auto IndirectLowered = rcc::riscv::callLowering().lowerCall(IndirectBuilder, IndirectRequest); + auto IndirectLowered = CallLowering.lowerCall(IndirectBuilder, IndirectRequest); rcc::MachineInstr *IndirectCall = findInstruction(*IndirectBlock, rcc::riscv::InstructionOpcode::PseudoCALL); Context.expect(IndirectLowered && IndirectCall != nullptr && @@ -632,7 +636,7 @@ void testStackAndByValEmission(TestContext &Context) { rcc::MachineIRBuilder Builder(*Function, *Target); if (!Builder.setInsertPoint(*Block)) return; - auto Lowered = rcc::riscv::callLowering().lowerCall(Builder, Request); + auto Lowered = CallLowering.lowerCall(Builder, Request); rcc::MachineInstr *ByValCopy = findInstruction(*Block, rcc::riscv::InstructionOpcode::PseudoBYVAL_COPY); rcc::MachineInstr *StackStore = @@ -679,7 +683,7 @@ void testFormalReturnAndTailEmission(TestContext &Context) { rcc::MachineIRBuilder FormalBuilder(*FormalFunction, *Target); if (!FormalBuilder.setInsertPoint(*FormalBlock)) return; - auto FormalLowered = rcc::riscv::callLowering().lowerFormalArguments(FormalBuilder, Formal); + auto FormalLowered = CallLowering.lowerFormalArguments(FormalBuilder, Formal); std::size_t SaveStores = 0; for (rcc::MachineInstr *Instruction : instructions(*FormalBlock)) { if (Instruction->opcode() == opcode(rcc::riscv::InstructionOpcode::PseudoSTORE_STACK_ARG)) @@ -713,7 +717,7 @@ void testFormalReturnAndTailEmission(TestContext &Context) { rcc::MachineIRBuilder ReturnBuilder(*ReturnFunction, *Target); if (!ReturnBuilder.setInsertPoint(*ReturnBlock)) return; - auto ReturnLowered = rcc::riscv::callLowering().lowerReturn(ReturnBuilder, Return); + auto ReturnLowered = CallLowering.lowerReturn(ReturnBuilder, Return); rcc::MachineInstr *ReturnPseudo = findInstruction(*ReturnBlock, rcc::riscv::InstructionOpcode::PseudoRET); bool HasReturnRegister = false; @@ -738,7 +742,7 @@ void testFormalReturnAndTailEmission(TestContext &Context) { rcc::MachineIRBuilder TailBuilder(*TailFunction, *Target); if (!TailBuilder.setInsertPoint(*TailBlock)) return; - auto TailLowered = rcc::riscv::callLowering().lowerCall(TailBuilder, Tail); + auto TailLowered = CallLowering.lowerCall(TailBuilder, Tail); Context.expect(TailLowered && instructions(*TailBlock).size() == 1 && TailBlock->firstInstruction()->opcode() == opcode(rcc::riscv::InstructionOpcode::PseudoTAIL) && @@ -767,7 +771,7 @@ void testFormalReturnAndTailEmission(TestContext &Context) { rcc::MachineIRBuilder StackTailBuilder(*StackTailFunction, *Target); if (!StackTailBuilder.setInsertPoint(*StackTailBlock)) return; - auto StackTailLowered = rcc::riscv::callLowering().lowerCall(StackTailBuilder, StackTail); + auto StackTailLowered = CallLowering.lowerCall(StackTailBuilder, StackTail); Context.expect( StackTailLowered && findInstruction(*StackTailBlock, rcc::riscv::InstructionOpcode::PseudoSTORE_STACK_ARG) != @@ -802,7 +806,7 @@ void testFormalStackAlignmentAndPreflight(TestContext &Context) { rcc::MachineIRBuilder StackBuilder(*StackFunction, *Target); if (!StackBuilder.setInsertPoint(*StackBlock)) return; - auto StackLowered = rcc::riscv::callLowering().lowerFormalArguments(StackBuilder, StackRequest); + auto StackLowered = CallLowering.lowerFormalArguments(StackBuilder, StackRequest); bool HasIncomingObject = false; for (const rcc::StackObject &Object : StackFunction->frameInfo().objects()) { const rcc::StackObjectDesc *Description = Object.description(); @@ -840,8 +844,7 @@ void testFormalStackAlignmentAndPreflight(TestContext &Context) { rcc::MachineIRBuilder ConflictBuilder(*ConflictFunction, *Target); if (!ConflictBuilder.setInsertPoint(*ConflictBlock)) return; - auto ConflictLowered = - rcc::riscv::callLowering().lowerFormalArguments(ConflictBuilder, ConflictRequest); + auto ConflictLowered = CallLowering.lowerFormalArguments(ConflictBuilder, ConflictRequest); Context.expect( !ConflictLowered && ConflictBlock->instructionCount() == 0 && ConflictFunction->allInstructions().empty() && @@ -862,7 +865,7 @@ void testPlanningFailureDoesNotMutate(TestContext &Context) { rcc::MachineIRBuilder Builder(*Function, *Target); if (!Builder.setInsertPoint(*Block)) return; - auto Lowered = rcc::riscv::callLowering().lowerCall(Builder, Request); + auto Lowered = CallLowering.lowerCall(Builder, Request); auto UnknownPhysical = rcc::PhysicalRegister::create(999); auto UnknownRequest = UnknownPhysical @@ -870,7 +873,7 @@ void testPlanningFailureDoesNotMutate(TestContext &Context) { 1) : rcc::CallLoweringRequest{}; auto UnknownLowered = UnknownPhysical - ? rcc::riscv::callLowering().lowerCall(Builder, UnknownRequest) + ? CallLowering.lowerCall(Builder, UnknownRequest) : rcc::Expected<void>{std::unexpected(UnknownPhysical.error())}; Context.expect(!Lowered && !UnknownLowered && Block->instructionCount() == 0 && Function->allInstructions().empty() && diff --git a/backend/unittests/Target/RISCVCodeGenTest.cpp b/backend/unittests/Target/RISCVCodeGenTest.cpp index ddacb1b..c5fc10a 100644 --- a/backend/unittests/Target/RISCVCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVCodeGenTest.cpp @@ -1,14 +1,16 @@ // SPDX-License-Identifier: GPL-3.0-or-later -#include "rcc/Target/RISCV/RISCVCodeGen.h" - +#include "RISCV.h" #include "rcc/CodeGen/GenericOpcodes.h" +#include "rcc/CodeGen/GlobalISel/InstructionSelector.h" +#include "rcc/CodeGen/GlobalISel/LegalizerInfo.h" #include "rcc/CodeGen/MachineBasicBlock.h" #include "rcc/CodeGen/MachineFunction.h" #include "rcc/CodeGen/MachineIRBuilder.h" #include "rcc/CodeGen/MachineInstr.h" #include "rcc/CodeGen/MachineMemOperand.h" #include "rcc/CodeGen/MachineOperand.h" +#include "rcc/Target/RISCV/RISCVSubtarget.h" #include "rcc/Target/RISCV/RISCVTarget.h" #include <array> @@ -22,6 +24,14 @@ namespace { +struct RISCVGISelTestComponents final { + rcc::riscv::RISCVSubtarget Subtarget{rcc::riscv::RISCVSubtargetFeatures::rv64gc()}; + const rcc::LegalizerInfo &Legalizer{*Subtarget.getLegalizerInfo()}; + const rcc::InstructionSelector *Selector{Subtarget.getInstructionSelector()}; +}; + +const RISCVGISelTestComponents GISel; + class TestContext final { public: void expect(bool Condition, std::string_view Message) { @@ -262,32 +272,24 @@ void testClassification(TestContext &Context) { "RISC-V integer test instructions must be constructible"); if (Add32.Instruction == nullptr || Add64.Instruction == nullptr) return; - auto Add32Action = - rcc::riscv::legalizerInfo().classify(*Add32.Instruction, *Add32.Function, *Target); - auto Add64Action = - rcc::riscv::legalizerInfo().classify(*Add64.Instruction, *Add64.Function, *Target); + auto Add32Action = GISel.Legalizer.classify(*Add32.Instruction, *Add32.Function, *Target); + auto Add64Action = GISel.Legalizer.classify(*Add64.Instruction, *Add64.Function, *Target); Context.expect(Add32Action && *Add32Action == rcc::LegalizationAction::Legal, "RV64GC legalizer must accept i32 arithmetic"); Context.expect(Add64Action && *Add64Action == rcc::LegalizationAction::Legal, "RV64GC legalizer must accept i64 arithmetic"); - Context.expect(rcc::riscv::instructionSelector() - .canSelect(*Add32.Instruction, *Add32.Function, *Target) - .has_value(), - "RV64GC selector must pre-match i32 arithmetic"); - Context.expect(rcc::riscv::instructionSelector() - .canSelect(*Add64.Instruction, *Add64.Function, *Target) - .has_value(), - "RV64GC selector must pre-match i64 arithmetic"); - Context.expect(rcc::riscv::instructionSelector() - .select(*Add32.Instruction, *Add32.Function, *Target) - .has_value(), + Context.expect( + (*GISel.Selector).canSelect(*Add32.Instruction, *Add32.Function, *Target).has_value(), + "RV64GC selector must pre-match i32 arithmetic"); + Context.expect( + (*GISel.Selector).canSelect(*Add64.Instruction, *Add64.Function, *Target).has_value(), + "RV64GC selector must pre-match i64 arithmetic"); + Context.expect((*GISel.Selector).select(*Add32.Instruction, *Add32.Function, *Target).has_value(), "RV64GC selector must lower i32 arithmetic"); Context.expect(Add32.Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::ADDW)), "i32 G_ADD must select ADDW"); - Context.expect(rcc::riscv::instructionSelector() - .select(*Add64.Instruction, *Add64.Function, *Target) - .has_value(), + Context.expect((*GISel.Selector).select(*Add64.Instruction, *Add64.Function, *Target).has_value(), "RV64GC selector must lower i64 arithmetic"); Context.expect(Add64.Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::ADD)), @@ -377,16 +379,14 @@ void testClassification(TestContext &Context) { "floating constant instructions must remain in layout order"); if (F32Instruction == nullptr || F64Instruction == nullptr) return; - auto F32Action = rcc::riscv::legalizerInfo().classify(*F32Instruction, **FloatFunction, *Target); - auto F64Action = rcc::riscv::legalizerInfo().classify(*F64Instruction, **FloatFunction, *Target); + auto F32Action = GISel.Legalizer.classify(*F32Instruction, **FloatFunction, *Target); + auto F64Action = GISel.Legalizer.classify(*F64Instruction, **FloatFunction, *Target); Context.expect(F32Action && *F32Action == rcc::LegalizationAction::Legal, "RV64GC legalizer must accept f32 constants"); Context.expect(F64Action && *F64Action == rcc::LegalizationAction::Legal, "RV64GC legalizer must accept f64 constants"); - auto F32Selection = - rcc::riscv::instructionSelector().select(*F32Instruction, **FloatFunction, *Target); - auto F64Selection = - rcc::riscv::instructionSelector().select(*F64Instruction, **FloatFunction, *Target); + auto F32Selection = (*GISel.Selector).select(*F32Instruction, **FloatFunction, *Target); + auto F64Selection = (*GISel.Selector).select(*F64Instruction, **FloatFunction, *Target); Context.expect(F32Selection.has_value(), "RV64GC selector must lower f32 constants"); Context.expect(F64Selection.has_value(), "RV64GC selector must lower f64 constants"); bool HasFMVWX = false; @@ -425,12 +425,10 @@ void testNarrowIntegerSelection(TestContext &Context) { Context.expect(false, "narrow integer fixture must be constructible"); continue; } - auto Action = - rcc::riscv::legalizerInfo().classify(*Fixture.Instruction, *Fixture.Function, *Target); + auto Action = GISel.Legalizer.classify(*Fixture.Instruction, *Fixture.Function, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Legal, "i1-i24 scalar operations must be legal on RV64GC GPR containers"); - auto Selection = - rcc::riscv::instructionSelector().select(*Fixture.Instruction, *Fixture.Function, *Target); + auto Selection = (*GISel.Selector).select(*Fixture.Instruction, *Fixture.Function, *Target); Context.expect(Selection.has_value(), "narrow integer operation must select"); bool FoundRequiredOpcode = false; for (const rcc::MachineInstr *Instruction : Fixture.Function->allInstructions()) { @@ -453,18 +451,16 @@ void testNarrowIntegerSelection(TestContext &Context) { rcc::FloatingPredicate::AlwaysFalse); if (Compare && Compare->firstBlock()->firstInstruction() != nullptr) { rcc::MachineInstr *Instruction = Compare->firstBlock()->firstInstruction(); - auto Action = rcc::riscv::legalizerInfo().classify(*Instruction, *Compare, *Target); - auto Lowered = Action - ? rcc::riscv::legalizerInfo().lower(*Instruction, *Compare, *Target, *Action) - : rcc::Expected<void>(std::unexpected(Action.error())); - auto LegalAction = rcc::riscv::legalizerInfo().classify(*Instruction, *Compare, *Target); + auto Action = GISel.Legalizer.classify(*Instruction, *Compare, *Target); + auto Lowered = Action ? GISel.Legalizer.lower(*Instruction, *Compare, *Target, *Action) + : rcc::Expected<void>(std::unexpected(Action.error())); + auto LegalAction = GISel.Legalizer.classify(*Instruction, *Compare, *Target); bool Selected = Lowered && LegalAction && *LegalAction == rcc::LegalizationAction::Legal && constrainVirtualRegisters(*Compare); const auto Instructions = Compare->allInstructions(); for (rcc::MachineInstr *Candidate : Instructions) { if (Selected && rcc::isGenericOpcode(Candidate->opcode())) - Selected = - rcc::riscv::instructionSelector().select(*Candidate, *Compare, *Target).has_value(); + Selected = (*GISel.Selector).select(*Candidate, *Compare, *Target).has_value(); } Context.expect(Action && *Action == rcc::LegalizationAction::Custom && Selected, "signed i7 comparisons must legalize to RV64 containers and select"); @@ -475,8 +471,8 @@ void testNarrowIntegerSelection(TestContext &Context) { auto Extension = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_SEXT, *I24, *I7); if (Extension && Extension->firstBlock()->firstInstruction() != nullptr) { rcc::MachineInstr *Instruction = Extension->firstBlock()->firstInstruction(); - auto Action = rcc::riscv::legalizerInfo().classify(*Instruction, *Extension, *Target); - auto Selection = rcc::riscv::instructionSelector().select(*Instruction, *Extension, *Target); + auto Action = GISel.Legalizer.classify(*Instruction, *Extension, *Target); + auto Selection = (*GISel.Selector).select(*Instruction, *Extension, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Legal && Selection, "i7-to-i24 sign extension must select through a 32-bit container"); Context.expect(Selection && validatesSelectedFunction(*Target, *Extension), @@ -485,8 +481,8 @@ void testNarrowIntegerSelection(TestContext &Context) { auto UnsupportedMulHigh = createBinary(Context, *Target, rcc::GenericOpcode::G_SMULH, 16); if (UnsupportedMulHigh.Function && UnsupportedMulHigh.Instruction != nullptr) { - auto Action = rcc::riscv::legalizerInfo().classify(*UnsupportedMulHigh.Instruction, - *UnsupportedMulHigh.Function, *Target); + auto Action = GISel.Legalizer.classify(*UnsupportedMulHigh.Instruction, + *UnsupportedMulHigh.Function, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Unsupported, "non-native multiply-high widths must be explicitly unsupported"); } @@ -519,7 +515,7 @@ void testScalarSelection(TestContext &Context) { if (Entry.first == nullptr) continue; auto *Instruction = Entry.first->firstBlock()->firstInstruction(); - auto Selection = rcc::riscv::instructionSelector().select(*Instruction, *Entry.first, *Target); + auto Selection = (*GISel.Selector).select(*Instruction, *Entry.first, *Target); const std::string_view Name = Entry.second == rcc::GenericOpcode::G_ANYEXT ? "anyext" : Entry.second == rcc::GenericOpcode::G_SEXT ? "sext" : Entry.second == rcc::GenericOpcode::G_ZEXT ? "zext" @@ -557,45 +553,40 @@ void testScalarSelection(TestContext &Context) { auto Bitcast = createUnaryFunction(Context, *Target, rcc::GenericOpcode::G_BITCAST, *I32, *F32); if (FPExt) { auto *Instruction = FPExt->firstBlock()->firstInstruction(); - Context.expect( - rcc::riscv::instructionSelector().select(*Instruction, *FPExt, *Target).has_value(), - "fpext must select"); + Context.expect((*GISel.Selector).select(*Instruction, *FPExt, *Target).has_value(), + "fpext must select"); Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FCVT_D_S)), "fpext must select FCVT.D.S"); } if (FPTrunc) { auto *Instruction = FPTrunc->firstBlock()->firstInstruction(); - Context.expect( - rcc::riscv::instructionSelector().select(*Instruction, *FPTrunc, *Target).has_value(), - "fptrunc must select"); + Context.expect((*GISel.Selector).select(*Instruction, *FPTrunc, *Target).has_value(), + "fptrunc must select"); Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FCVT_S_D)), "fptrunc must select FCVT.S.D"); } if (FPToSI) { auto *Instruction = FPToSI->firstBlock()->firstInstruction(); - Context.expect( - rcc::riscv::instructionSelector().select(*Instruction, *FPToSI, *Target).has_value(), - "fptosi must select"); + Context.expect((*GISel.Selector).select(*Instruction, *FPToSI, *Target).has_value(), + "fptosi must select"); Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FCVT_L_S)), "fptosi must select FCVT.L.S"); } if (SIToFP) { auto *Instruction = SIToFP->firstBlock()->firstInstruction(); - Context.expect( - rcc::riscv::instructionSelector().select(*Instruction, *SIToFP, *Target).has_value(), - "sitofp must select"); + Context.expect((*GISel.Selector).select(*Instruction, *SIToFP, *Target).has_value(), + "sitofp must select"); Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FCVT_D_W)), "sitofp must select FCVT.D.W"); } if (Bitcast) { auto *Instruction = Bitcast->firstBlock()->firstInstruction(); - Context.expect( - rcc::riscv::instructionSelector().select(*Instruction, *Bitcast, *Target).has_value(), - "float-to-integer bitcast must select"); + Context.expect((*GISel.Selector).select(*Instruction, *Bitcast, *Target).has_value(), + "float-to-integer bitcast must select"); Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FMV_X_W)), "float-to-integer bitcast must select FMV.X.W"); @@ -633,15 +624,14 @@ void testComparisonsAndControl(TestContext &Context) { auto BuiltExtension = Extension->build(); if (!BuiltExtension) return; - auto Action = rcc::riscv::legalizerInfo().classify(*Instruction, *Equal, *Target); - auto Lowered = Action - ? rcc::riscv::legalizerInfo().lower(*Instruction, *Equal, *Target, *Action) - : rcc::Expected<void>(std::unexpected(Action.error())); + auto Action = GISel.Legalizer.classify(*Instruction, *Equal, *Target); + auto Lowered = Action ? GISel.Legalizer.lower(*Instruction, *Equal, *Target, *Action) + : rcc::Expected<void>(std::unexpected(Action.error())); const rcc::Register *LegalResult = Instruction->operandAt(0)->getIf<rcc::Register>(); Context.expect(Lowered && (*BuiltExtension)->parent() == nullptr && LegalResult != nullptr && *LegalResult == *WideResult, "RV64 integer comparison legalization must fold a single result extension"); - auto Selection = rcc::riscv::instructionSelector().select(*Instruction, *Equal, *Target); + auto Selection = (*GISel.Selector).select(*Instruction, *Equal, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Custom && Lowered && Selection, "integer equality must legalize its result container and select"); rcc::MachineInstr *FirstSelected = Equal->firstBlock()->firstInstruction(); @@ -659,13 +649,12 @@ void testComparisonsAndControl(TestContext &Context) { } if (LessEqual) { auto *Instruction = LessEqual->firstBlock()->firstInstruction(); - auto Action = rcc::riscv::legalizerInfo().classify(*Instruction, *LessEqual, *Target); - auto Lowered = - Action ? rcc::riscv::legalizerInfo().lower(*Instruction, *LessEqual, *Target, *Action) - : rcc::Expected<void>(std::unexpected(Action.error())); + auto Action = GISel.Legalizer.classify(*Instruction, *LessEqual, *Target); + auto Lowered = Action ? GISel.Legalizer.lower(*Instruction, *LessEqual, *Target, *Action) + : rcc::Expected<void>(std::unexpected(Action.error())); Context.expect(Action && *Action == rcc::LegalizationAction::Custom && Lowered && constrainVirtualRegisters(*LessEqual) && - rcc::riscv::instructionSelector().select(*Instruction, *LessEqual, *Target), + (*GISel.Selector).select(*Instruction, *LessEqual, *Target), "signed less-equal must legalize its result container and select"); Context.expect(LessEqual->allInstructions().size() == 2, "signed less-equal must emit compare and inversion"); @@ -679,18 +668,15 @@ void testComparisonsAndControl(TestContext &Context) { rcc::IntegerPredicate::Equal, rcc::FloatingPredicate::UnorderedEqual); if (Ordered) { auto *Instruction = Ordered->firstBlock()->firstInstruction(); - Context.expect( - rcc::riscv::instructionSelector().select(*Instruction, *Ordered, *Target).has_value(), - "ordered floating equality must select"); + Context.expect((*GISel.Selector).select(*Instruction, *Ordered, *Target).has_value(), + "ordered floating equality must select"); Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FEQ_S)), "ordered floating equality must select FEQ.S"); } if (UnorderedEqual) { auto *Instruction = UnorderedEqual->firstBlock()->firstInstruction(); - Context.expect(rcc::riscv::instructionSelector() - .select(*Instruction, *UnorderedEqual, *Target) - .has_value(), + Context.expect((*GISel.Selector).select(*Instruction, *UnorderedEqual, *Target).has_value(), "unordered floating equality must select"); Context.expect(UnorderedEqual->allInstructions().size() == 4, "unordered floating equality must emit ordered compare sequence"); @@ -699,9 +685,8 @@ void testComparisonsAndControl(TestContext &Context) { auto FMin = createFloatBinaryFunction(Context, *Target, rcc::GenericOpcode::G_FMINNUM, *F32); if (FMin) { auto *Instruction = FMin->firstBlock()->firstInstruction(); - Context.expect( - rcc::riscv::instructionSelector().select(*Instruction, *FMin, *Target).has_value(), - "floating minnum must select"); + Context.expect((*GISel.Selector).select(*Instruction, *FMin, *Target).has_value(), + "floating minnum must select"); Context.expect(Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FMIN_S)), "floating minnum must select FMIN.S"); @@ -728,25 +713,21 @@ void testComparisonsAndControl(TestContext &Context) { !Fence->addImmediate(7) || !Fence->addImmediate(0) || !Fence->build() || !Trap->build()) return; auto *IndirectInstruction = (*ControlFunction)->firstBlock()->firstInstruction(); - Context.expect(rcc::riscv::instructionSelector() - .select(*IndirectInstruction, **ControlFunction, *Target) - .has_value(), - "indirect branch must select"); + Context.expect( + (*GISel.Selector).select(*IndirectInstruction, **ControlFunction, *Target).has_value(), + "indirect branch must select"); Context.expect(IndirectInstruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::JALR)), "indirect branch must select JALR"); auto *FenceInstruction = IndirectInstruction->next(); - Context.expect(rcc::riscv::instructionSelector() - .select(*FenceInstruction, **ControlFunction, *Target) - .has_value(), - "fence must select"); + Context.expect( + (*GISel.Selector).select(*FenceInstruction, **ControlFunction, *Target).has_value(), + "fence must select"); Context.expect(FenceInstruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::FENCE)), "fence must select FENCE"); auto *TrapInstruction = FenceInstruction->next(); - Context.expect(rcc::riscv::instructionSelector() - .select(*TrapInstruction, **ControlFunction, *Target) - .has_value(), + Context.expect((*GISel.Selector).select(*TrapInstruction, **ControlFunction, *Target).has_value(), "trap must select"); Context.expect(TrapInstruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::EBREAK)), @@ -786,10 +767,10 @@ void testCompositeScalarSelection(TestContext &Context) { if (Function == nullptr) continue; rcc::MachineInstr *Instruction = Function->firstBlock()->firstInstruction(); - auto Classification = rcc::riscv::legalizerInfo().classify(*Instruction, *Function, *Target); + auto Classification = GISel.Legalizer.classify(*Instruction, *Function, *Target); Context.expect(Classification && *Classification == rcc::LegalizationAction::Legal, "composite scalar operation must be legal on RV64GC"); - auto Selection = rcc::riscv::instructionSelector().select(*Instruction, *Function, *Target); + auto Selection = (*GISel.Selector).select(*Instruction, *Function, *Target); Context.expect(Selection.has_value(), "composite scalar operation must select on RV64GC"); Context.expect(Selection && validatesSelectedFunction(*Target, *Function), "composite scalar selection must satisfy all target descriptors"); @@ -840,7 +821,7 @@ void testOverflowSelection(TestContext &Context) { if (!Function) continue; rcc::MachineInstr *Instruction = Function->firstBlock()->firstInstruction(); - auto Selection = rcc::riscv::instructionSelector().select(*Instruction, *Function, *Target); + auto Selection = (*GISel.Selector).select(*Instruction, *Function, *Target); Context.expect(Selection.has_value(), "RV64GC overflow operation must select"); Context.expect(Selection && validatesSelectedFunction(*Target, *Function), "overflow sequence must satisfy all target descriptors"); @@ -856,7 +837,7 @@ void testOverflowSelection(TestContext &Context) { if (!Function) continue; rcc::MachineInstr *Instruction = Function->firstBlock()->firstInstruction(); - auto Selection = rcc::riscv::instructionSelector().select(*Instruction, *Function, *Target); + auto Selection = (*GISel.Selector).select(*Instruction, *Function, *Target); Context.expect(Selection.has_value(), "extended RV64GC overflow operation must select"); Context.expect(Selection && validatesSelectedFunction(*Target, *Function), "extended overflow sequence must satisfy all target descriptors"); @@ -923,10 +904,9 @@ void testAtomicCompareExchangeLegalization(TestContext &Context) { if (!BuiltExtension) return; - auto Action = rcc::riscv::legalizerInfo().classify(**BuiltAtomic, **Function, *Target); - auto Lowered = - Action ? rcc::riscv::legalizerInfo().lower(**BuiltAtomic, **Function, *Target, *Action) - : rcc::Expected<void>(std::unexpected(Action.error())); + auto Action = GISel.Legalizer.classify(**BuiltAtomic, **Function, *Target); + auto Lowered = Action ? GISel.Legalizer.lower(**BuiltAtomic, **Function, *Target, *Action) + : rcc::Expected<void>(std::unexpected(Action.error())); Context.expect(Action && *Action == rcc::LegalizationAction::Custom && Lowered.has_value(), "narrow RV64 compare-exchange must use the widening legalizer rule"); if (!Lowered) @@ -940,7 +920,7 @@ void testAtomicCompareExchangeLegalization(TestContext &Context) { ? rcc::Expected<std::reference_wrapper<const rcc::VirtualRegisterInfo>>(std::unexpected( rcc::Error(rcc::ErrorCode::InvalidArgument, "missing compare-exchange result"))) : (*Function)->registerInfo().virtualRegisterInfo(*AtomicResult); - auto LegalAction = rcc::riscv::legalizerInfo().classify(**BuiltAtomic, **Function, *Target); + auto LegalAction = GISel.Legalizer.classify(**BuiltAtomic, **Function, *Target); Context.expect(CompareInfo && CompareInfo->get().Type == *I64 && NewValueInfo && NewValueInfo->get().Type == *I64 && AtomicResultInfo && AtomicResultInfo->get().Type == *I64 && @@ -967,11 +947,10 @@ void testAtomicCompareExchangeLegalization(TestContext &Context) { auto BuiltFallback = Fallback->build(); if (!BuiltFallback) return; - auto FallbackAction = rcc::riscv::legalizerInfo().classify(**BuiltFallback, **Function, *Target); + auto FallbackAction = GISel.Legalizer.classify(**BuiltFallback, **Function, *Target); auto FallbackLowered = - FallbackAction - ? rcc::riscv::legalizerInfo().lower(**BuiltFallback, **Function, *Target, *FallbackAction) - : rcc::Expected<void>(std::unexpected(FallbackAction.error())); + FallbackAction ? GISel.Legalizer.lower(**BuiltFallback, **Function, *Target, *FallbackAction) + : rcc::Expected<void>(std::unexpected(FallbackAction.error())); rcc::MachineInstr *Truncation = (*BuiltFallback)->next(); const rcc::Register *WideFallbackResult = (*BuiltFallback)->operandAt(0)->getIf<rcc::Register>(); const rcc::Register *TruncatedResult = @@ -999,12 +978,11 @@ void testAtomicCompareExchangeLegalization(TestContext &Context) { auto BuiltWithSuccess = WithSuccess->build(); if (!BuiltWithSuccess) return; - auto WithSuccessAction = - rcc::riscv::legalizerInfo().classify(**BuiltWithSuccess, **Function, *Target); - auto WithSuccessLowered = WithSuccessAction - ? rcc::riscv::legalizerInfo().lower(**BuiltWithSuccess, **Function, - *Target, *WithSuccessAction) - : rcc::Expected<void>(std::unexpected(WithSuccessAction.error())); + auto WithSuccessAction = GISel.Legalizer.classify(**BuiltWithSuccess, **Function, *Target); + auto WithSuccessLowered = + WithSuccessAction + ? GISel.Legalizer.lower(**BuiltWithSuccess, **Function, *Target, *WithSuccessAction) + : rcc::Expected<void>(std::unexpected(WithSuccessAction.error())); rcc::MachineInstr *SuccessCompare = (*BuiltWithSuccess)->previous(); rcc::MachineInstr *LoweredAtomic = SuccessCompare == nullptr ? nullptr : SuccessCompare->previous(); @@ -1056,10 +1034,9 @@ void testConstantExtensionPreservesLiveSource(TestContext &Context) { !Copy->build()) return; - auto Action = rcc::riscv::legalizerInfo().classify(**BuiltExtension, **Function, *Target); - auto Lowered = - Action ? rcc::riscv::legalizerInfo().lower(**BuiltExtension, **Function, *Target, *Action) - : rcc::Expected<void>(std::unexpected(Action.error())); + auto Action = GISel.Legalizer.classify(**BuiltExtension, **Function, *Target); + auto Lowered = Action ? GISel.Legalizer.lower(**BuiltExtension, **Function, *Target, *Action) + : rcc::Expected<void>(std::unexpected(Action.error())); Context.expect(Action && *Action == rcc::LegalizationAction::Custom && Lowered && (*BuiltExtension)->opcode() == rcc::opcode(rcc::GenericOpcode::G_CONSTANT) && (*BuiltConstant)->parent() != nullptr && @@ -1104,8 +1081,8 @@ void testIntegerCompareReusesConstantExtension(TestContext &Context) { if (!BuiltExtension) return; - auto Action = rcc::riscv::legalizerInfo().classify(*Compare, *Function, *Target); - auto Lowered = Action ? rcc::riscv::legalizerInfo().lower(*Compare, *Function, *Target, *Action) + auto Action = GISel.Legalizer.classify(*Compare, *Function, *Target); + auto Lowered = Action ? GISel.Legalizer.lower(*Compare, *Function, *Target, *Action) : rcc::Expected<void>(std::unexpected(Action.error())); const rcc::Register *LegalRight = Compare->operandAt(3)->getIf<rcc::Register>(); Context.expect(Action && *Action == rcc::LegalizationAction::Custom && Lowered, @@ -1115,10 +1092,10 @@ void testIntegerCompareReusesConstantExtension(TestContext &Context) { Context.expect(Function->registerInfo().verifyDefUseChains().has_value(), "integer comparison extension reuse must preserve exact def-use chains"); - auto ExtensionAction = rcc::riscv::legalizerInfo().classify(**BuiltExtension, *Function, *Target); - auto Folded = ExtensionAction ? rcc::riscv::legalizerInfo().lower(**BuiltExtension, *Function, - *Target, *ExtensionAction) - : rcc::Expected<void>(std::unexpected(ExtensionAction.error())); + auto ExtensionAction = GISel.Legalizer.classify(**BuiltExtension, *Function, *Target); + auto Folded = ExtensionAction + ? GISel.Legalizer.lower(**BuiltExtension, *Function, *Target, *ExtensionAction) + : rcc::Expected<void>(std::unexpected(ExtensionAction.error())); const rcc::Register *FoldedResult = (*BuiltConstant)->operandAt(0)->getIf<rcc::Register>(); Context.expect(ExtensionAction && *ExtensionAction == rcc::LegalizationAction::Custom && Folded && (*BuiltExtension)->parent() == nullptr && FoldedResult != nullptr && @@ -1178,10 +1155,9 @@ void testNarrowAnyExtBinaryArtifacts(TestContext &Context) { if (!BuiltMultiply || OuterExtension == nullptr) return; - auto Action = rcc::riscv::legalizerInfo().classify(*OuterExtension, **Function, *Target); - auto Lowered = - Action ? rcc::riscv::legalizerInfo().lower(*OuterExtension, **Function, *Target, *Action) - : rcc::Expected<void>(std::unexpected(Action.error())); + auto Action = GISel.Legalizer.classify(*OuterExtension, **Function, *Target); + auto Lowered = Action ? GISel.Legalizer.lower(*OuterExtension, **Function, *Target, *Action) + : rcc::Expected<void>(std::unexpected(Action.error())); const rcc::Register *LegalLeft = OuterExtension->operandAt(1)->getIf<rcc::Register>(); const rcc::Register *LegalRight = OuterExtension->operandAt(2)->getIf<rcc::Register>(); Context.expect( @@ -1200,10 +1176,12 @@ void testMultiplyLibcallWithoutM(TestContext &Context) { auto Target = rcc::riscv::createTargetDescription(); const std::vector<std::string> FeatureNames{"+a"}; auto Features = rcc::riscv::RISCVSubtargetFeatures::fromFeatureList(FeatureNames); - auto Legalizer = Features ? rcc::riscv::createLegalizerInfo(*Features) : nullptr; - auto Multiply64 = - Target ? createBinary(Context, *Target, rcc::GenericOpcode::G_MUL, 64) : InstructionFixture{}; - if (!Target || !Features || !Legalizer || Multiply64.Instruction == nullptr) + if (!Target || !Features) + return; + const rcc::riscv::RISCVSubtarget Subtarget(*Features); + const rcc::LegalizerInfo *Legalizer = Subtarget.getLegalizerInfo(); + auto Multiply64 = createBinary(Context, *Target, rcc::GenericOpcode::G_MUL, 64); + if (Multiply64.Instruction == nullptr) return; auto Action = Legalizer->classify(*Multiply64.Instruction, *Multiply64.Function, *Target); @@ -1314,8 +1292,7 @@ void testAtomicSelection(TestContext &Context) { Nand.Instruction != nullptr, "atomic RMW fixtures must be complete"); if (Add.Instruction != nullptr) { - auto Selection = - rcc::riscv::instructionSelector().select(*Add.Instruction, *Add.Function, *Target); + auto Selection = (*GISel.Selector).select(*Add.Instruction, *Add.Function, *Target); Context.expect(Selection.has_value() && Add.Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::AMOADD_D)), @@ -1324,21 +1301,18 @@ void testAtomicSelection(TestContext &Context) { "selected AMOADD.D must satisfy its descriptor and MMO contract"); } if (Sub.Instruction != nullptr) { - auto Selection = - rcc::riscv::instructionSelector().select(*Sub.Instruction, *Sub.Function, *Target); + auto Selection = (*GISel.Selector).select(*Sub.Instruction, *Sub.Function, *Target); Context.expect(Selection.has_value() && Sub.Function->allInstructions().size() == 2, "G_ATOMICRMW_SUB must negate its operand before AMOADD.D"); Context.expect(Selection && validatesSelectedFunction(*Target, *Sub.Function), "selected atomic subtraction must satisfy target descriptors"); } if (Nand.Instruction != nullptr) { - auto Classification = - rcc::riscv::legalizerInfo().classify(*Nand.Instruction, *Nand.Function, *Target); + auto Classification = GISel.Legalizer.classify(*Nand.Instruction, *Nand.Function, *Target); Context.expect( Classification && *Classification == rcc::LegalizationAction::Unsupported, "an atomic operation without a single-instruction RV64GC mapping must be explicit"); - auto Match = - rcc::riscv::instructionSelector().canSelect(*Nand.Instruction, *Nand.Function, *Target); + auto Match = (*GISel.Selector).canSelect(*Nand.Instruction, *Nand.Function, *Target); Context.expect(!Match && Match.error().code() == rcc::ErrorCode::Unsupported, "unsupported atomic RMW must fail before mutating MachineIR"); Context.expect(!Match && Match.error().message().find("G_ATOMICRMW_NAND") != std::string::npos, @@ -1391,8 +1365,8 @@ void testAtomicSelection(TestContext &Context) { auto AtomicLoad = MakeAtomicAccess(true, 1303); auto AtomicStore = MakeAtomicAccess(false, 1304); if (AtomicLoad.Instruction != nullptr) { - auto Selection = rcc::riscv::instructionSelector().select(*AtomicLoad.Instruction, - *AtomicLoad.Function, *Target); + auto Selection = + (*GISel.Selector).select(*AtomicLoad.Instruction, *AtomicLoad.Function, *Target); Context.expect(Selection && AtomicLoad.Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::LR_D)), @@ -1401,8 +1375,8 @@ void testAtomicSelection(TestContext &Context) { "selected atomic load must satisfy target descriptors"); } if (AtomicStore.Instruction != nullptr) { - auto Selection = rcc::riscv::instructionSelector().select(*AtomicStore.Instruction, - *AtomicStore.Function, *Target); + auto Selection = + (*GISel.Selector).select(*AtomicStore.Instruction, *AtomicStore.Function, *Target); Context.expect(Selection && AtomicStore.Instruction->opcode() == rcc::Opcode::fromValue(static_cast<std::uint32_t>( rcc::riscv::InstructionOpcode::AMOSWAP_D)), @@ -1419,8 +1393,8 @@ void testUnsupportedTypes(TestContext &Context) { return; auto WideInteger = createBinary(Context, *Target, rcc::GenericOpcode::G_ADD, 128); if (WideInteger.Function && WideInteger.Instruction != nullptr) { - auto Selection = rcc::riscv::instructionSelector().canSelect(*WideInteger.Instruction, - *WideInteger.Function, *Target); + auto Selection = + (*GISel.Selector).canSelect(*WideInteger.Instruction, *WideInteger.Function, *Target); Context.expect(!Selection && Selection.error().code() == rcc::ErrorCode::Unsupported, "i128 arithmetic must produce an Unsupported diagnostic"); Context.expect(!Selection && Selection.error().message().find("i128") != std::string::npos, @@ -1449,10 +1423,10 @@ void testUnsupportedTypes(TestContext &Context) { if (!Pending->build()) return; const rcc::MachineInstr &Instruction = **Function->get()->allInstructions().begin(); - auto Action = rcc::riscv::legalizerInfo().classify(Instruction, **Function, *Target); + auto Action = GISel.Legalizer.classify(Instruction, **Function, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Unsupported, "unsupported floating operations must remain explicitly diagnosed"); - auto Selection = rcc::riscv::instructionSelector().canSelect(Instruction, **Function, *Target); + auto Selection = (*GISel.Selector).canSelect(Instruction, **Function, *Target); Context.expect(!Selection && Selection.error().code() == rcc::ErrorCode::Unsupported, "selector pre-matching must reject unsupported floating operations"); Context.expect(!Selection && Selection.error().message().find("G_FEXP") != std::string::npos, @@ -1492,12 +1466,12 @@ void testVACopyLegalization(TestContext &Context) { auto Built = Pending->build(); if (!Built) return; - auto Action = rcc::riscv::legalizerInfo().classify(**Built, **Function, *Target); + auto Action = GISel.Legalizer.classify(**Built, **Function, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Custom, "RV64GC must custom-legalize va_copy"); if (!Action) return; - auto Lowered = rcc::riscv::legalizerInfo().lower(**Built, **Function, *Target, *Action); + auto Lowered = GISel.Legalizer.lower(**Built, **Function, *Target, *Action); Context.expect(Lowered.has_value(), "RV64GC va_copy legalization must succeed"); if (!Lowered) return; @@ -1575,12 +1549,12 @@ void testVAArgLegalization(TestContext &Context) { Context.expect(Target->validateInstruction(**Built, (*Function)->registerInfo()).has_value(), "canonical G_VAARG without MMOs must satisfy the generic descriptor"); - auto Action = rcc::riscv::legalizerInfo().classify(**Built, **Function, *Target); + auto Action = GISel.Legalizer.classify(**Built, **Function, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Custom, "RV64GC must custom-legalize G_VAARG"); if (!Action) return; - auto Lowered = rcc::riscv::legalizerInfo().lower(**Built, **Function, *Target, *Action); + auto Lowered = GISel.Legalizer.lower(**Built, **Function, *Target, *Action); Context.expect(Lowered.has_value(), "RV64GC va_arg legalization must succeed"); if (!Lowered) return; @@ -1666,9 +1640,8 @@ void testFrameIndexLegalization(TestContext &Context) { if (!BuiltUnsupported) return; - auto LegalAction = rcc::riscv::legalizerInfo().classify(**BuiltLegal, **Function, *Target); - auto UnsupportedAction = - rcc::riscv::legalizerInfo().classify(**BuiltUnsupported, **Function, *Target); + auto LegalAction = GISel.Legalizer.classify(**BuiltLegal, **Function, *Target); + auto UnsupportedAction = GISel.Legalizer.classify(**BuiltUnsupported, **Function, *Target); Context.expect(LegalAction && *LegalAction == rcc::LegalizationAction::Legal, "RV64GC must legalize G_FRAME_INDEX for p0"); Context.expect(UnsupportedAction && *UnsupportedAction == rcc::LegalizationAction::Unsupported, @@ -1691,10 +1664,10 @@ void testPointerArithmeticLegalization(TestContext &Context) { {*Pointer}, {*Pointer, *S32}); if (!Legal || !Unsupported) return; - auto LegalAction = rcc::riscv::legalizerInfo().classify(*Legal->firstBlock()->firstInstruction(), - *Legal, *Target); - auto UnsupportedAction = rcc::riscv::legalizerInfo().classify( - *Unsupported->firstBlock()->firstInstruction(), *Unsupported, *Target); + auto LegalAction = + GISel.Legalizer.classify(*Legal->firstBlock()->firstInstruction(), *Legal, *Target); + auto UnsupportedAction = GISel.Legalizer.classify(*Unsupported->firstBlock()->firstInstruction(), + *Unsupported, *Target); Context.expect(LegalAction && *LegalAction == rcc::LegalizationAction::Legal, "RV64GC must legalize G_PTR_ADD for p0 and s64"); Context.expect(UnsupportedAction && *UnsupportedAction == rcc::LegalizationAction::Unsupported, @@ -1745,10 +1718,10 @@ void testMemoryOffsetSelection(TestContext &Context) { Context.expect(Instruction != nullptr, "generic load must remain attached to its block"); if (Instruction == nullptr) return; - auto Action = rcc::riscv::legalizerInfo().classify(*Instruction, **Function, *Target); + auto Action = GISel.Legalizer.classify(*Instruction, **Function, *Target); Context.expect(Action && *Action == rcc::LegalizationAction::Legal, "RV64GC legalizer must accept volatile scalar loads"); - auto Selection = rcc::riscv::instructionSelector().select(*Instruction, **Function, *Target); + auto Selection = (*GISel.Selector).select(*Instruction, **Function, *Target); Context.expect(Selection.has_value(), "RV64GC selector must select a volatile scalar load"); if (!Selection) return; diff --git a/backend/unittests/Target/RISCVFrameLoweringTest.cpp b/backend/unittests/Target/RISCVFrameLoweringTest.cpp index 6a6cd5b..285e962 100644 --- a/backend/unittests/Target/RISCVFrameLoweringTest.cpp +++ b/backend/unittests/Target/RISCVFrameLoweringTest.cpp @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later +#include "GISel/RISCVCallLowering.h" +#include "RISCV.h" #include "rcc/CodeGen/GenericOpcodes.h" #include "rcc/CodeGen/MachineBasicBlock.h" #include "rcc/CodeGen/MachineCFGUpdater.h" @@ -16,8 +18,6 @@ #include "rcc/CodeGen/TargetDescription.h" #include "rcc/CodeGen/TargetFrameLowering.h" #include "rcc/CodeGen/TargetRegisterAllocationInfo.h" -#include "rcc/Target/RISCV/RISCVCallLowering.h" -#include "rcc/Target/RISCV/RISCVCodeGen.h" #include "rcc/Target/RISCV/RISCVInstructions.h" #include "rcc/Target/RISCV/RISCVRegisters.h" #include "rcc/Target/RISCV/RISCVTarget.h" diff --git a/backend/unittests/Target/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp index d0bd952..92fbc55 100644 --- a/backend/unittests/Target/RISCVLateCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVLateCodeGenTest.cpp @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later +#include "RISCV.h" #include "RISCVInstrInfo.h" #include "rcc/CodeGen/GenericOpcodes.h" #include "rcc/CodeGen/MachineBasicBlock.h" @@ -25,7 +26,6 @@ #include "rcc/CodeGen/MachineTailMerge.h" #include "rcc/CodeGen/PrologueEpilogueInsertion.h" #include "rcc/CodeGen/RegisterMask.h" -#include "rcc/Target/RISCV/RISCVCodeGen.h" #include "rcc/Target/RISCV/RISCVInstructions.h" #include "rcc/Target/RISCV/RISCVRegisters.h" #include "rcc/Target/RISCV/RISCVTarget.h" diff --git a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp index 299308c..ad81615 100644 --- a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp +++ b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later +#include "RISCV.h" #include "rcc/CodeGen/LowLevelType.h" #include "rcc/CodeGen/MachineBasicBlock.h" #include "rcc/CodeGen/MachineFrameInfo.h" @@ -16,7 +17,6 @@ #include "rcc/CodeGen/RegAllocPBQP.h" #include "rcc/CodeGen/TargetDescription.h" #include "rcc/CodeGen/TargetRegisterAllocationInfo.h" -#include "rcc/Target/RISCV/RISCVCodeGen.h" #include "rcc/Target/RISCV/RISCVInstructions.h" #include "rcc/Target/RISCV/RISCVRegisters.h" #include "rcc/Target/RISCV/RISCVTarget.h" diff --git a/backend/unittests/Target/RISCVSSAExitTest.cpp b/backend/unittests/Target/RISCVSSAExitTest.cpp index 18cbea9..eafb5a0 100644 --- a/backend/unittests/Target/RISCVSSAExitTest.cpp +++ b/backend/unittests/Target/RISCVSSAExitTest.cpp @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later +#include "RISCV.h" #include "RISCVInstrInfo.h" #include "rcc/CodeGen/GenericOpcodes.h" #include "rcc/CodeGen/MachineBasicBlock.h" @@ -12,7 +13,6 @@ #include "rcc/CodeGen/MachinePass.h" #include "rcc/CodeGen/MachineSSAExit.h" #include "rcc/CodeGen/MachineVerifier.h" -#include "rcc/Target/RISCV/RISCVCodeGen.h" #include "rcc/Target/RISCV/RISCVTarget.h" #include <algorithm> |
