aboutsummaryrefslogtreecommitdiff
path: root/backend/unittests/Target
diff options
context:
space:
mode:
Diffstat (limited to 'backend/unittests/Target')
-rw-r--r--backend/unittests/Target/CMakeLists.txt10
-rw-r--r--backend/unittests/Target/RISCVCallLoweringTest.cpp73
-rw-r--r--backend/unittests/Target/RISCVCodeGenTest.cpp279
-rw-r--r--backend/unittests/Target/RISCVFrameLoweringTest.cpp4
-rw-r--r--backend/unittests/Target/RISCVLateCodeGenTest.cpp2
-rw-r--r--backend/unittests/Target/RISCVRegisterAllocationTest.cpp2
-rw-r--r--backend/unittests/Target/RISCVSSAExitTest.cpp2
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>