aboutsummaryrefslogtreecommitdiff
path: root/backend/unittests/CodeGen/GlobalISel
diff options
context:
space:
mode:
Diffstat (limited to 'backend/unittests/CodeGen/GlobalISel')
-rw-r--r--backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp11
-rw-r--r--backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp116
2 files changed, 48 insertions, 79 deletions
diff --git a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
index 6d9fa3c..9f3f0b5 100644
--- a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
+++ b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
@@ -121,9 +121,11 @@ void testPipeline(TestContext &Context) {
rcc::MachineFunctionProperty::TracksLiveness};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
rcc::MachineFunctionPassManager Pipeline;
- Context.expect(
- Pipeline.addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo())).has_value(),
- "legalizer must be accepted by the pass manager");
+ Context.expect(Pipeline
+ .addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo(),
+ rcc::OptimizationLevel::O2))
+ .has_value(),
+ "legalizer must be accepted by the pass manager");
Context.expect(Pipeline.addPass(std::make_unique<rcc::RegBankSelect>(Subtarget.getRegBankInfo()))
.has_value(),
"register-bank selector must be accepted by the pass manager");
@@ -327,7 +329,8 @@ void testExtendedRV64GCPipeline(TestContext &Context) {
rcc::MachineFunctionProperty::TracksLiveness};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
rcc::MachineFunctionPassManager Pipeline;
- if (!Pipeline.addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo())) ||
+ if (!Pipeline.addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo(),
+ rcc::OptimizationLevel::O2)) ||
!Pipeline.addPass(std::make_unique<rcc::RegBankSelect>(Subtarget.getRegBankInfo())) ||
!Pipeline.addPass(
std::make_unique<rcc::InstructionSelect>(Subtarget.getInstructionSelector()))) {
diff --git a/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp b/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
index b191a3f..eaf3741 100644
--- a/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
+++ b/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
@@ -3,6 +3,9 @@
#include "rcc/CodeGen/GlobalISel/Legalizer.h"
#include "GISelMITest.h"
+#include "rcc/CodeGen/GlobalISel/GISelChangeObserver.h"
+#include "rcc/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "rcc/Target/RISCV/RISCVRegisters.h"
#include "rcc/Target/RISCV/RISCVSubtarget.h"
#include "rcc/Target/RISCV/RISCVTarget.h"
@@ -14,53 +17,38 @@ namespace {
using rcc::test::buildAdd;
using rcc::test::createFixture;
-using rcc::test::createFloatRegister;
using rcc::test::createRegister;
using rcc::test::TestContext;
-class TogglingLegalizer final : public rcc::LegalizerInfo {
-public:
- [[nodiscard]] rcc::Expected<rcc::LegalizationAction>
- classify(const rcc::MachineInstr &, const rcc::MachineFunction &,
- const rcc::TargetDescription &) const override {
- return rcc::LegalizationAction::Lower;
- }
-
- [[nodiscard]] rcc::Expected<void> lower(rcc::MachineInstr &Instruction, rcc::MachineFunction &,
- const rcc::TargetDescription &,
- rcc::LegalizationAction) const override {
- const auto Generic = static_cast<rcc::GenericOpcode>(Instruction.opcode().value());
- return Instruction.setOpcode(rcc::opcode(Generic == rcc::GenericOpcode::G_ADD
- ? rcc::GenericOpcode::G_SUB
- : rcc::GenericOpcode::G_ADD));
- }
-};
-
class BackwardInvalidatingLegalizer final : public rcc::LegalizerInfo {
public:
- [[nodiscard]] rcc::Expected<rcc::LegalizationAction>
- classify(const rcc::MachineInstr &Instruction, const rcc::MachineFunction &,
- const rcc::TargetDescription &) const override {
- return Instruction.opcode() == rcc::opcode(rcc::GenericOpcode::G_SUB)
- ? rcc::LegalizationAction::Custom
- : rcc::LegalizationAction::Legal;
+ BackwardInvalidatingLegalizer() {
+ getActionDefinitionsBuilder(rcc::opcode(rcc::GenericOpcode::G_ADD)).alwaysLegal();
+ getActionDefinitionsBuilder(rcc::opcode(rcc::GenericOpcode::G_SUB)).custom();
}
- [[nodiscard]] rcc::Expected<void> lower(rcc::MachineInstr &Instruction,
- rcc::MachineFunction &Function,
- const rcc::TargetDescription &,
- rcc::LegalizationAction) const override {
+ [[nodiscard]] rcc::Expected<void>
+ legalizeCustom(rcc::LegalizerHelper &Helper, rcc::MachineInstr &Instruction,
+ const rcc::LegalizationDecision &) const override {
+ rcc::MachineFunction &Function = Helper.MIRBuilder.function();
for (rcc::MachineInstr *Candidate : Function.allInstructions()) {
if (Candidate != &Instruction &&
Candidate->opcode() == rcc::opcode(rcc::GenericOpcode::G_ADD)) {
+ Helper.Observer.changingInstr(*Candidate);
auto Invalidated = Candidate->setOpcode(rcc::opcode(rcc::GenericOpcode::G_SUB));
if (!Invalidated)
return std::unexpected(Invalidated.error());
+ Helper.Observer.changedInstr(*Candidate);
break;
}
}
- return Instruction.setOpcode(
+ Helper.Observer.changingInstr(Instruction);
+ auto Changed = Instruction.setOpcode(
rcc::Opcode::fromValue(static_cast<std::uint32_t>(rcc::riscv::InstructionOpcode::ADD)));
+ if (!Changed)
+ return std::unexpected(Changed.error());
+ Helper.Observer.changedInstr(Instruction);
+ return {};
}
};
@@ -72,7 +60,7 @@ void testNullAndMissingContracts(TestContext &Context) {
if (!Target || !Fixture.Function)
return;
- rcc::Legalizer NullPass(nullptr);
+ rcc::Legalizer NullPass(nullptr, rcc::OptimizationLevel::O2);
rcc::MachineFunctionAnalysisManager Analyses;
auto NullResult = NullPass.run(*Fixture.Function, *Target, Analyses);
Context.expect(!NullResult && NullResult.error().code() == rcc::ErrorCode::InvalidArgument,
@@ -81,7 +69,7 @@ void testNullAndMissingContracts(TestContext &Context) {
"a rejected pass must not publish function properties");
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
- rcc::Legalizer ValidPass(Subtarget.getLegalizerInfo());
+ rcc::Legalizer ValidPass(Subtarget.getLegalizerInfo(), rcc::OptimizationLevel::O2);
auto MissingResult = ValidPass.run(*Fixture.Function, *Target, Analyses);
Context.expect(!MissingResult &&
MissingResult.error().code() == rcc::ErrorCode::VerificationError,
@@ -97,14 +85,13 @@ void testUnsupportedRollback(TestContext &Context) {
"unsupported pipeline fixture must be complete");
if (!Unsupported.Function || Unsupported.Entry == nullptr)
return;
- const rcc::Register UnsupportedReg = createFloatRegister(Context, *Unsupported.Function);
- const rcc::Register UnsupportedSource = createFloatRegister(Context, *Unsupported.Function);
+ const rcc::Register UnsupportedReg = createRegister(Context, *Unsupported.Function, 64);
rcc::MachineIRBuilder UnsupportedBuilder(*Unsupported.Function, *Target);
Context.expect(UnsupportedBuilder.setInsertPoint(*Unsupported.Entry).has_value(),
"unsupported pipeline insertion point must be valid");
- if (UnsupportedReg.isNoRegister() || UnsupportedSource.isNoRegister())
+ if (UnsupportedReg.isNoRegister())
return;
- auto Pending = UnsupportedBuilder.buildInstr(rcc::opcode(rcc::GenericOpcode::G_FEXP));
+ auto Pending = UnsupportedBuilder.buildInstr(rcc::opcode(rcc::GenericOpcode::G_GET_FPENV));
Context.expect(Pending.has_value(), "unsupported generic instruction must be constructible");
if (!Pending)
return;
@@ -112,21 +99,22 @@ void testUnsupportedRollback(TestContext &Context) {
Context.expect(Built.has_value(), "unsupported generic definition must be accepted");
if (!Built)
return;
- Context.expect(Pending->addUse(UnsupportedSource).has_value() && Pending->build().has_value(),
- "unsupported floating operation must be constructible");
+ Context.expect(Pending->build().has_value(),
+ "unsupported floating-point environment operation must be constructible");
Unsupported.Function->properties() = {rcc::MachineFunctionProperty::IsSSA,
rcc::MachineFunctionProperty::TracksLiveness};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
rcc::MachineFunctionPassManager OnlyLegalizer;
- Context.expect(
- OnlyLegalizer.addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo()))
- .has_value(),
- "standalone legalizer must be accepted");
+ Context.expect(OnlyLegalizer
+ .addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo(),
+ rcc::OptimizationLevel::O2))
+ .has_value(),
+ "standalone legalizer must be accepted");
rcc::MachineFunctionAnalysisManager UnsupportedAnalyses;
auto Failure = OnlyLegalizer.run(*Unsupported.Function, *Target, UnsupportedAnalyses);
Context.expect(!Failure && Failure.error().code() == rcc::ErrorCode::Unsupported,
"unsupported generic instructions must produce a target diagnostic");
- Context.expect(!Failure && Failure.error().message().find("G_FEXP") != std::string::npos,
+ Context.expect(!Failure && Failure.error().message().find("G_GET_FPENV") != std::string::npos,
"unsupported legalization diagnostics must name the rejected opcode");
Context.expect(
Unsupported.Function->properties().has(rcc::MachineFunctionProperty::IsSSA) &&
@@ -134,36 +122,6 @@ void testUnsupportedRollback(TestContext &Context) {
"failed legalizer execution must not publish Legalized");
}
-void testLegalizerCycleDiagnostic(TestContext &Context) {
- auto Target = rcc::riscv::createTargetDescription();
- auto Fixture = createFixture(Context, "pipeline_legalizer_cycle", 6);
- Context.expect(Target.has_value() && Fixture.Function != nullptr && Fixture.Entry != nullptr,
- "legalizer cycle fixture must be complete");
- if (!Target || !Fixture.Function || Fixture.Entry == nullptr)
- return;
- const rcc::Register Left = createRegister(Context, *Fixture.Function, 64);
- const rcc::Register Right = createRegister(Context, *Fixture.Function, 64);
- const rcc::Register Result = createRegister(Context, *Fixture.Function, 64);
- rcc::MachineIRBuilder Builder(*Fixture.Function, *Target);
- if (Left.isNoRegister() || Right.isNoRegister() || Result.isNoRegister() ||
- !Builder.setInsertPoint(*Fixture.Entry) || !buildAdd(Context, Builder, Result, Left, Right))
- return;
- Fixture.Function->properties() = {rcc::MachineFunctionProperty::IsSSA,
- rcc::MachineFunctionProperty::TracksLiveness};
- TogglingLegalizer Legalizer;
- rcc::Legalizer StablePass(Legalizer);
- rcc::MachineFunctionAnalysisManager Analyses;
- auto ResultRun = StablePass.run(*Fixture.Function, *Target, Analyses);
- Context.expect(!ResultRun && ResultRun.error().code() == rcc::ErrorCode::InternalError,
- "repeated legalization states must report InternalError");
- Context.expect(Fixture.Entry->firstInstruction() != nullptr &&
- Fixture.Entry->firstInstruction()->opcode() ==
- rcc::opcode(rcc::GenericOpcode::G_ADD),
- "failed legalization preflight must preserve the original instruction");
- Context.expect(!Fixture.Function->properties().has(rcc::MachineFunctionProperty::Legalized),
- "a failed legalization cycle must not publish Legalized");
-}
-
void testLegalizerRevisitsInvalidatedInstructions(TestContext &Context) {
auto Target = rcc::riscv::createTargetDescription();
auto Fixture = createFixture(Context, "pipeline_legalizer_revisit", 7);
@@ -183,11 +141,20 @@ void testLegalizerRevisitsInvalidatedInstructions(TestContext &Context) {
rcc::MachineInstr *Second = First == nullptr ? nullptr : First->next();
if (Second == nullptr || !Second->setOpcode(rcc::opcode(rcc::GenericOpcode::G_SUB)))
return;
+ auto X10 = rcc::riscv::physicalRegister(rcc::riscv::PhysicalRegisterID::X10);
+ auto X11 = rcc::riscv::physicalRegister(rcc::riscv::PhysicalRegisterID::X11);
+ auto FirstCopy = Builder.buildInstr(rcc::opcode(rcc::GenericOpcode::COPY));
+ auto SecondCopy = Builder.buildInstr(rcc::opcode(rcc::GenericOpcode::COPY));
+ if (!X10 || !X11 || !FirstCopy || !FirstCopy->addDef(rcc::Register::fromPhysical(*X10)) ||
+ !FirstCopy->addUse(FirstResult) || !FirstCopy->build() || !SecondCopy ||
+ !SecondCopy->addDef(rcc::Register::fromPhysical(*X11)) || !SecondCopy->addUse(SecondResult) ||
+ !SecondCopy->build())
+ return;
Fixture.Function->properties() = {rcc::MachineFunctionProperty::IsSSA,
rcc::MachineFunctionProperty::TracksLiveness};
BackwardInvalidatingLegalizer Legalizer;
- rcc::Legalizer Pass(Legalizer);
+ rcc::Legalizer Pass(Legalizer, rcc::OptimizationLevel::O2);
rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pass.run(*Fixture.Function, *Target, Analyses);
const rcc::Opcode LegalOpcode =
@@ -202,7 +169,6 @@ int main() {
TestContext Context;
testNullAndMissingContracts(Context);
testUnsupportedRollback(Context);
- testLegalizerCycleDiagnostic(Context);
testLegalizerRevisitsInvalidatedInstructions(Context);
return Context.result();
}