aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/include/rcc/CodeGen/MachineCopyPropagation.h6
-rw-r--r--backend/include/rcc/CodeGen/MachineOptimizationPipeline.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineSSAExit.h10
-rw-r--r--backend/include/rcc/CodeGen/TargetCodeGen.h38
-rw-r--r--backend/include/rcc/CodeGen/TargetInstrInfo.h24
-rw-r--r--backend/include/rcc/Target/RISCV/RISCVCodeGen.h3
-rw-r--r--backend/lib/CodeGen/MachineBranchOptimization.cpp5
-rw-r--r--backend/lib/CodeGen/MachineCopyPropagation.cpp6
-rw-r--r--backend/lib/CodeGen/MachineFallthrough.cpp5
-rw-r--r--backend/lib/CodeGen/MachineOptimizationPipeline.cpp18
-rw-r--r--backend/lib/CodeGen/MachineSSAExit.cpp16
-rw-r--r--backend/lib/CodeGen/MachineTailDuplication.cpp3
-rw-r--r--backend/lib/CodeGen/MachineTailMerge.cpp2
-rw-r--r--backend/lib/Target/RISCV/CMakeLists.txt11
-rw-r--r--backend/lib/Target/RISCV/RISCVCodeGen.cpp197
-rw-r--r--backend/lib/Target/RISCV/RISCVInstrInfo.cpp (renamed from backend/lib/Target/RISCV/RISCVBranchInfo.cpp)119
-rw-r--r--backend/lib/Target/RISCV/RISCVInstrInfo.h14
-rw-r--r--backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp4
-rw-r--r--backend/lib/Target/RISCV/RISCVPipeline.cpp9
-rw-r--r--backend/unittests/CodeGen/MachineSSAExitTest.cpp71
-rw-r--r--backend/unittests/Target/CMakeLists.txt8
-rw-r--r--backend/unittests/Target/RISCVLateCodeGenTest.cpp55
-rw-r--r--backend/unittests/Target/RISCVSSAExitTest.cpp85
23 files changed, 366 insertions, 347 deletions
diff --git a/backend/include/rcc/CodeGen/MachineCopyPropagation.h b/backend/include/rcc/CodeGen/MachineCopyPropagation.h
index e8ee788..43baa7e 100644
--- a/backend/include/rcc/CodeGen/MachineCopyPropagation.h
+++ b/backend/include/rcc/CodeGen/MachineCopyPropagation.h
@@ -10,7 +10,7 @@
namespace rcc {
-class TargetSSAInfo;
+class TargetInstrInfo;
enum class MachineCopyPropagationStage : std::uint8_t {
PreRegisterAllocation,
@@ -23,7 +23,7 @@ struct MachineCopyPropagationOptions final {
class MachineCopyPropagationPass final : public MachineFunctionPass {
public:
- MachineCopyPropagationPass(const TargetSSAInfo &Info, MachineCopyPropagationStage Stage,
+ MachineCopyPropagationPass(const TargetInstrInfo &Info, MachineCopyPropagationStage Stage,
MachineCopyPropagationOptions Options = {}) noexcept
: Info(&Info), Stage(Stage), Options(Options) {}
@@ -37,7 +37,7 @@ private:
const TargetDescription &Target,
MachineActionReplay &Actions) const;
- const TargetSSAInfo *Info;
+ const TargetInstrInfo *Info;
MachineCopyPropagationStage Stage;
MachineCopyPropagationOptions Options;
};
diff --git a/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h b/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h
index 2cf1bcd..10bcbc6 100644
--- a/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h
+++ b/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h
@@ -13,16 +13,14 @@ class TargetMachineCombinerInfo;
class TargetMemoryFoldingInfo;
class TargetPseudoExpansionInfo;
class TargetSchedulingModel;
-class TargetSSAInfo;
struct MachineOptimizationPipelineTargetInfo final {
- const TargetSSAInfo &SSA;
+ const TargetInstrInfo &InstrInfo;
const TargetMachineCombinerInfo &Combiner;
const TargetMemoryFoldingInfo &MemoryFolding;
const TargetFrameLowering &FrameLowering;
const TargetPseudoExpansionInfo &PseudoExpansion;
const TargetSchedulingModel &SchedulingModel;
- const TargetInstrInfo &BranchInfo;
};
[[nodiscard]] Expected<void> registerMachineOptimizationAnalyses(MachineAnalysisManager &Analyses);
diff --git a/backend/include/rcc/CodeGen/MachineSSAExit.h b/backend/include/rcc/CodeGen/MachineSSAExit.h
index fdf74f0..4b6966d 100644
--- a/backend/include/rcc/CodeGen/MachineSSAExit.h
+++ b/backend/include/rcc/CodeGen/MachineSSAExit.h
@@ -4,14 +4,14 @@
#define RCC_CODEGEN_MACHINESSAEXIT_H
#include "rcc/CodeGen/MachinePass.h"
-#include "rcc/CodeGen/TargetCodeGen.h"
+#include "rcc/CodeGen/TargetInstrInfo.h"
namespace rcc {
class PHIEliminationPass final : public MachineFunctionPass {
public:
PHIEliminationPass() noexcept = default;
- explicit PHIEliminationPass(const TargetSSAInfo &Info) noexcept : Info(&Info) {}
+ explicit PHIEliminationPass(const TargetInstrInfo &Info) noexcept : Info(&Info) {}
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
@@ -23,13 +23,13 @@ private:
const TargetDescription &Target,
MachineActionReplay &Actions);
- const TargetSSAInfo *Info = nullptr;
+ const TargetInstrInfo *Info = nullptr;
};
class TwoAddressRewritePass final : public MachineFunctionPass {
public:
TwoAddressRewritePass() noexcept = default;
- explicit TwoAddressRewritePass(const TargetSSAInfo &Info) noexcept : Info(&Info) {}
+ explicit TwoAddressRewritePass(const TargetInstrInfo &Info) noexcept : Info(&Info) {}
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
@@ -41,7 +41,7 @@ private:
const TargetDescription &Target,
MachineActionReplay &Actions);
- const TargetSSAInfo *Info = nullptr;
+ const TargetInstrInfo *Info = nullptr;
};
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/TargetCodeGen.h b/backend/include/rcc/CodeGen/TargetCodeGen.h
index 34a6de4..65f65a4 100644
--- a/backend/include/rcc/CodeGen/TargetCodeGen.h
+++ b/backend/include/rcc/CodeGen/TargetCodeGen.h
@@ -3,20 +3,14 @@
#ifndef RCC_CODEGEN_TARGETCODEGEN_H
#define RCC_CODEGEN_TARGETCODEGEN_H
-#include "rcc/CodeGen/MachineIRTypes.h"
-#include "rcc/CodeGen/Register.h"
#include "rcc/Support/Error.h"
-#include <cstddef>
#include <cstdint>
-#include <optional>
namespace rcc {
class MachineFunction;
-class MachineBasicBlock;
class MachineInstr;
-class MachineRegisterInfo;
class TargetDescription;
struct VirtualRegisterInfo;
@@ -96,38 +90,6 @@ public:
}
};
-class TargetSSAInfo {
-public:
- virtual ~TargetSSAInfo() = default;
-
- [[nodiscard]] virtual Expected<bool> isFallthroughEdge(const MachineBasicBlock &From,
- const MachineBasicBlock &To,
- const MachineFunction &Function,
- const TargetDescription &Target) const = 0;
-
- [[nodiscard]] virtual Expected<bool>
- rewriteBranchTarget(MachineBasicBlock &Block, MachineBasicBlock &OldTarget,
- MachineBasicBlock &NewTarget, MachineFunction &Function,
- const TargetDescription &Target) const = 0;
-
- [[nodiscard]] virtual Expected<void>
- insertUnconditionalBranch(MachineBasicBlock &Block, MachineBasicBlock &Target,
- MachineFunction &Function,
- const TargetDescription &TargetDescription) const = 0;
-
- [[nodiscard]] virtual Expected<void> validateCopy(Register Destination,
- SubRegIndex DestinationSubReg, Register Source,
- SubRegIndex SourceSubReg,
- const MachineFunction &Function,
- const TargetDescription &Target) const = 0;
-
- [[nodiscard]] virtual Expected<bool> tryConvertToThreeAddress(MachineInstr &, std::size_t,
- std::size_t, MachineFunction &,
- const TargetDescription &) const {
- return false;
- }
-};
-
} // namespace rcc
#endif // RCC_CODEGEN_TARGETCODEGEN_H
diff --git a/backend/include/rcc/CodeGen/TargetInstrInfo.h b/backend/include/rcc/CodeGen/TargetInstrInfo.h
index d9f0906..34752c5 100644
--- a/backend/include/rcc/CodeGen/TargetInstrInfo.h
+++ b/backend/include/rcc/CodeGen/TargetInstrInfo.h
@@ -3,8 +3,11 @@
#ifndef RCC_CODEGEN_TARGETINSTRINFO_H
#define RCC_CODEGEN_TARGETINSTRINFO_H
+#include "rcc/CodeGen/MachineIRTypes.h"
+#include "rcc/CodeGen/Register.h"
#include "rcc/Support/Error.h"
+#include <cstddef>
#include <cstdint>
#include <optional>
@@ -40,8 +43,25 @@ public:
MachineBasicBlock &NewTarget, MachineFunction &Function,
const TargetDescription &Target) const = 0;
[[nodiscard]] virtual Expected<MachineInstr *>
- insertUnconditionalBranch(MachineBasicBlock &Block, MachineBasicBlock &TargetBlock,
- MachineFunction &Function, const TargetDescription &Target) const = 0;
+ insertBranch(MachineBasicBlock &Block, MachineBasicBlock &TargetBlock, MachineFunction &Function,
+ const TargetDescription &Target) const = 0;
+
+ [[nodiscard]] virtual Expected<bool> isFallthroughEdge(const MachineBasicBlock &From,
+ const MachineBasicBlock &To,
+ const MachineFunction &Function,
+ const TargetDescription &Target) const = 0;
+
+ [[nodiscard]] virtual Expected<void> validateCopy(Register Destination,
+ SubRegIndex DestinationSubReg, Register Source,
+ SubRegIndex SourceSubReg,
+ const MachineFunction &Function,
+ const TargetDescription &Target) const = 0;
+
+ [[nodiscard]] virtual Expected<bool> tryConvertToThreeAddress(MachineInstr &, std::size_t,
+ std::size_t, MachineFunction &,
+ const TargetDescription &) const {
+ return false;
+ }
[[nodiscard]] virtual Expected<std::uint32_t>
instructionSize(const MachineInstr &Instruction, const MachineFunction &Function,
diff --git a/backend/include/rcc/Target/RISCV/RISCVCodeGen.h b/backend/include/rcc/Target/RISCV/RISCVCodeGen.h
index d68157a..6cda815 100644
--- a/backend/include/rcc/Target/RISCV/RISCVCodeGen.h
+++ b/backend/include/rcc/Target/RISCV/RISCVCodeGen.h
@@ -7,7 +7,6 @@
#include "rcc/CodeGen/MachineOptimizationPipeline.h"
#include "rcc/CodeGen/TargetCodeGen.h"
#include "rcc/CodeGen/TargetFrameLowering.h"
-#include "rcc/CodeGen/TargetInstrInfo.h"
#include "rcc/CodeGen/TargetMemoryFolding.h"
#include "rcc/CodeGen/TargetPseudoExpansion.h"
#include "rcc/CodeGen/TargetRegisterAllocationInfo.h"
@@ -23,13 +22,11 @@ namespace rcc::riscv {
createLegalizerInfo(RISCVSubtargetFeatures Features);
[[nodiscard]] const TargetRegisterBankInfo &registerBankInfo() noexcept;
[[nodiscard]] const TargetInstructionSelector &instructionSelector() noexcept;
-[[nodiscard]] const TargetSSAInfo &ssaInfo() noexcept;
[[nodiscard]] const TargetRegisterAllocationInfo &registerAllocationInfo() noexcept;
[[nodiscard]] const TargetFrameLowering &frameLowering() noexcept;
[[nodiscard]] const TargetSchedulingModel &schedulingModel() noexcept;
[[nodiscard]] const TargetMachineCombinerInfo &machineCombinerInfo() noexcept;
[[nodiscard]] const TargetMemoryFoldingInfo &memoryFoldingInfo() noexcept;
-[[nodiscard]] const TargetInstrInfo &branchInfo() noexcept;
[[nodiscard]] const TargetPseudoExpansionInfo &pseudoExpansionInfo() noexcept;
[[nodiscard]] MachineOptimizationPipelineTargetInfo optimizationPipelineInfo() noexcept;
diff --git a/backend/lib/CodeGen/MachineBranchOptimization.cpp b/backend/lib/CodeGen/MachineBranchOptimization.cpp
index 19127ea..df25a4a 100644
--- a/backend/lib/CodeGen/MachineBranchOptimization.cpp
+++ b/backend/lib/CodeGen/MachineBranchOptimization.cpp
@@ -142,7 +142,7 @@ namespace {
if (!RemovedUnconditional)
return std::unexpected(RemovedUnconditional.error());
}
- auto Inserted = Info.insertUnconditionalBranch(*Block, *Selected, Function, Target);
+ auto Inserted = Info.insertBranch(*Block, *Selected, Function, Target);
if (!Inserted)
return std::unexpected(Inserted.error());
@@ -269,8 +269,7 @@ namespace {
} else {
if (Predecessor->next() != Block)
continue;
- auto Inserted =
- Info.insertUnconditionalBranch(*Predecessor, *Successor, Function, Target);
+ auto Inserted = Info.insertBranch(*Predecessor, *Successor, Function, Target);
if (!Inserted)
return std::unexpected(Inserted.error());
}
diff --git a/backend/lib/CodeGen/MachineCopyPropagation.cpp b/backend/lib/CodeGen/MachineCopyPropagation.cpp
index f9211f9..60992a5 100644
--- a/backend/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/backend/lib/CodeGen/MachineCopyPropagation.cpp
@@ -12,8 +12,8 @@
#include "rcc/CodeGen/MachineOperand.h"
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/RegisterMask.h"
-#include "rcc/CodeGen/TargetCodeGen.h"
#include "rcc/CodeGen/TargetDescription.h"
+#include "rcc/CodeGen/TargetInstrInfo.h"
#include "rcc/CodeGen/TargetRegisterInfo.h"
#include <algorithm>
@@ -127,7 +127,7 @@ struct CopyOperands final {
[[nodiscard]] Expected<bool> propagateVirtualCopy(MachineInstr &Copy, const CopyOperands &Operands,
MachineFunction &Function,
const TargetDescription &Target,
- const TargetSSAInfo &Info) {
+ const TargetInstrInfo &Info) {
if (!Operands.Destination.isVirtual() || !Operands.Source.isVirtual())
return false;
if (Function.registerInfo().getUniqueVRegDef(Operands.Destination) !=
@@ -231,7 +231,7 @@ struct CopyOperands final {
[[nodiscard]] Expected<bool> propagatePhysicalCopy(MachineInstr &Copy, const CopyOperands &Operands,
MachineFunction &Function,
const TargetDescription &Target,
- const TargetSSAInfo &Info) {
+ const TargetInstrInfo &Info) {
const std::optional<PhysicalRegister> Destination = Operands.Destination.physicalRegister();
const std::optional<PhysicalRegister> Source = Operands.Source.physicalRegister();
if (!Destination || !Source || Operands.DestinationOperand->subReg().value() != 0 ||
diff --git a/backend/lib/CodeGen/MachineFallthrough.cpp b/backend/lib/CodeGen/MachineFallthrough.cpp
index a853f96..e912f0b 100644
--- a/backend/lib/CodeGen/MachineFallthrough.cpp
+++ b/backend/lib/CodeGen/MachineFallthrough.cpp
@@ -83,8 +83,7 @@ normalizeFallthroughs(MachineFunction &Function, const TargetDescription &Target
Changed = true;
} else if (Analysis->Conditional != nullptr && Analysis->Unconditional == nullptr &&
Analysis->FalseTarget != nullptr) {
- auto Inserted =
- Info.insertUnconditionalBranch(*Block, *Analysis->FalseTarget, Function, Target);
+ auto Inserted = Info.insertBranch(*Block, *Analysis->FalseTarget, Function, Target);
if (!Inserted)
return std::unexpected(Inserted.error());
Changed = true;
@@ -102,7 +101,7 @@ normalizeFallthroughs(MachineFunction &Function, const TargetDescription &Target
return makeUnexpected(ErrorCode::VerificationError,
"fallthrough normalization encountered a null successor");
}
- auto Inserted = Info.insertUnconditionalBranch(*Block, *Successor, Function, Target);
+ auto Inserted = Info.insertBranch(*Block, *Successor, Function, Target);
if (!Inserted)
return std::unexpected(Inserted.error());
Changed = true;
diff --git a/backend/lib/CodeGen/MachineOptimizationPipeline.cpp b/backend/lib/CodeGen/MachineOptimizationPipeline.cpp
index 76dbd44..6d24034 100644
--- a/backend/lib/CodeGen/MachineOptimizationPipeline.cpp
+++ b/backend/lib/CodeGen/MachineOptimizationPipeline.cpp
@@ -69,10 +69,10 @@ addSelectedSSAOptimizationPipeline(MachinePassManager &Pipeline,
Expected<void> addPreRegisterAllocationOptimizationPipeline(
MachinePassManager &Pipeline, const MachineOptimizationPipelineTargetInfo &TargetInfo) {
- auto Added = addPass<MachineBranchOptimizationPass>(Pipeline, TargetInfo.BranchInfo);
+ auto Added = addPass<MachineBranchOptimizationPass>(Pipeline, TargetInfo.InstrInfo);
if (!Added)
return std::unexpected(Added.error());
- Added = addPass<MachineCopyPropagationPass>(Pipeline, TargetInfo.SSA,
+ Added = addPass<MachineCopyPropagationPass>(Pipeline, TargetInfo.InstrInfo,
MachineCopyPropagationStage::PreRegisterAllocation);
if (!Added)
return std::unexpected(Added.error());
@@ -92,7 +92,7 @@ addPostRegisterAllocationPipeline(MachinePassManager &Pipeline,
auto Added = addPass<MachineStackSlotColoringPass>(Pipeline);
if (!Added)
return std::unexpected(Added.error());
- Added = addPass<MachineCopyPropagationPass>(Pipeline, TargetInfo.SSA,
+ Added = addPass<MachineCopyPropagationPass>(Pipeline, TargetInfo.InstrInfo,
MachineCopyPropagationStage::PostRegisterAllocation);
if (!Added)
return std::unexpected(Added.error());
@@ -128,29 +128,29 @@ addPostRegisterAllocationPipeline(MachinePassManager &Pipeline,
Added = addPass<PostRASchedulerPass>(Pipeline, TargetInfo.SchedulingModel);
if (!Added)
return std::unexpected(Added.error());
- Added = addPass<MachineTailDuplicationPass>(Pipeline, TargetInfo.BranchInfo);
+ Added = addPass<MachineTailDuplicationPass>(Pipeline, TargetInfo.InstrInfo);
if (!Added)
return std::unexpected(Added.error());
- Added = addPass<MachineTailMergePass>(Pipeline, TargetInfo.BranchInfo);
+ Added = addPass<MachineTailMergePass>(Pipeline, TargetInfo.InstrInfo);
if (!Added)
return std::unexpected(Added.error());
Added = addPass<MachineBlockPlacementPass>(Pipeline);
if (!Added)
return std::unexpected(Added.error());
- Added = addPass<MachineFallthroughPass>(Pipeline, TargetInfo.BranchInfo);
+ Added = addPass<MachineFallthroughPass>(Pipeline, TargetInfo.InstrInfo);
if (!Added)
return std::unexpected(Added.error());
- Added = addPass<MachineBranchRelaxationPass>(Pipeline, TargetInfo.BranchInfo);
+ Added = addPass<MachineBranchRelaxationPass>(Pipeline, TargetInfo.InstrInfo);
if (!Added)
return std::unexpected(Added.error());
Added = addPass<TargetLatePseudoExpansionPass>(Pipeline, TargetInfo.PseudoExpansion,
- TargetInfo.BranchInfo);
+ TargetInfo.InstrInfo);
if (!Added)
return std::unexpected(Added.error());
Added = addPass<FinalizeEmissionPseudosPass>(Pipeline);
if (!Added)
return std::unexpected(Added.error());
- return addPass<FinalEncodabilityVerifierPass>(Pipeline, TargetInfo.BranchInfo);
+ return addPass<FinalEncodabilityVerifierPass>(Pipeline, TargetInfo.InstrInfo);
}
} // namespace rcc
diff --git a/backend/lib/CodeGen/MachineSSAExit.cpp b/backend/lib/CodeGen/MachineSSAExit.cpp
index 76963ea..ec10b3b 100644
--- a/backend/lib/CodeGen/MachineSSAExit.cpp
+++ b/backend/lib/CodeGen/MachineSSAExit.cpp
@@ -167,7 +167,7 @@ struct PhiPlan final {
[[nodiscard]] Expected<MachineInstr *>
buildCopy(MachineFunction &Function, const TargetDescription &Target,
- const TargetSSAInfo &TargetInfo, MachineBasicBlock &Block, MachineInstr *Before,
+ const TargetInstrInfo &TargetInfo, MachineBasicBlock &Block, MachineInstr *Before,
RegisterValue Destination, RegisterValue Source, const MachineInstr *DebugSource) {
auto Legality = TargetInfo.validateCopy(Destination.Reg, Destination.SubReg, Source.Reg,
Source.SubReg, Function, Target);
@@ -388,7 +388,7 @@ buildImplicitDef(MachineFunction &Function, const TargetDescription &Target,
[[nodiscard]] Expected<MachineBasicBlock *>
placePhiCopiesOnEdge(MachineFunction &Function, const TargetDescription &Target,
- const TargetSSAInfo &TargetInfo, MachineBasicBlock &From,
+ const TargetInstrInfo &TargetInfo, MachineBasicBlock &From,
MachineBasicBlock &To,
std::unordered_map<EdgeKey, MachineBasicBlock *, EdgeKeyHash> &Cache,
MachinePassResult &PassResult) {
@@ -415,7 +415,7 @@ placePhiCopiesOnEdge(MachineFunction &Function, const TargetDescription &Target,
if (!OtherFallthrough)
return std::unexpected(OtherFallthrough.error());
if (*OtherFallthrough) {
- auto Branch = TargetInfo.insertUnconditionalBranch(*LayoutPredecessor, To, Function, Target);
+ auto Branch = TargetInfo.insertBranch(*LayoutPredecessor, To, Function, Target);
if (!Branch)
return std::unexpected(Branch.error());
PassResult.Changed = true;
@@ -445,7 +445,7 @@ placePhiCopiesOnEdge(MachineFunction &Function, const TargetDescription &Target,
auto LiveIns = copyLiveIns(To, *EdgeBlock);
if (!LiveIns)
return std::unexpected(LiveIns.error());
- auto Branch = TargetInfo.insertUnconditionalBranch(*EdgeBlock, To, Function, Target);
+ auto Branch = TargetInfo.insertBranch(*EdgeBlock, To, Function, Target);
if (!Branch)
return std::unexpected(Branch.error());
@@ -526,7 +526,7 @@ placePhiCopiesOnEdge(MachineFunction &Function, const TargetDescription &Target,
[[nodiscard]] Expected<void> expandRegSequence(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target,
- const TargetSSAInfo &TargetInfo) {
+ const TargetInstrInfo &TargetInfo) {
if (Instruction.operandCount() < 3 || (Instruction.operandCount() - 1U) % 2U != 0) {
return makeUnexpected(ErrorCode::VerificationError,
"REG_SEQUENCE requires a destination and source/subregister pairs");
@@ -588,7 +588,7 @@ placePhiCopiesOnEdge(MachineFunction &Function, const TargetDescription &Target,
[[nodiscard]] Expected<void> expandInsertSubreg(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
- const TargetSSAInfo &TargetInfo) {
+ const TargetInstrInfo &TargetInfo) {
if (Instruction.operandCount() != 4) {
return makeUnexpected(ErrorCode::VerificationError,
"INSERT_SUBREG requires destination, base, inserted value, and index");
@@ -792,7 +792,7 @@ Expected<MachinePassResult> PHIEliminationPass::run(MachineFunction &Function,
MachineAnalysisManager &Analyses) {
if (Info == nullptr) {
return makeUnexpected(ErrorCode::InvalidArgument,
- "PHI elimination has no target SSA behavior interface");
+ "PHI elimination has no target instruction information");
}
auto Required = requireProperties(Function, contract());
if (!Required)
@@ -927,7 +927,7 @@ Expected<MachinePassResult> TwoAddressRewritePass::run(MachineFunction &Function
MachineAnalysisManager &Analyses) {
if (Info == nullptr) {
return makeUnexpected(ErrorCode::InvalidArgument,
- "two-address rewrite has no target SSA behavior interface");
+ "two-address rewrite has no target instruction information");
}
auto Required = requireProperties(Function, contract());
if (!Required)
diff --git a/backend/lib/CodeGen/MachineTailDuplication.cpp b/backend/lib/CodeGen/MachineTailDuplication.cpp
index a4b31b2..80c58c9 100644
--- a/backend/lib/CodeGen/MachineTailDuplication.cpp
+++ b/backend/lib/CodeGen/MachineTailDuplication.cpp
@@ -230,8 +230,7 @@ duplicateTailIntoPredecessor(const TailCandidate &Candidate, MachineBasicBlock &
if (!Removed)
return std::unexpected(Removed.error());
}
- auto NewBranch =
- Info.insertUnconditionalBranch(Predecessor, *Candidate.Successor, Function, Target);
+ auto NewBranch = Info.insertBranch(Predecessor, *Candidate.Successor, Function, Target);
if (!NewBranch)
return std::unexpected(NewBranch.error());
MachineCFGUpdater CFG = Function.cfgUpdater();
diff --git a/backend/lib/CodeGen/MachineTailMerge.cpp b/backend/lib/CodeGen/MachineTailMerge.cpp
index c8aad80..07608cc 100644
--- a/backend/lib/CodeGen/MachineTailMerge.cpp
+++ b/backend/lib/CodeGen/MachineTailMerge.cpp
@@ -279,7 +279,7 @@ redirectPredecessor(MachineBasicBlock &Predecessor, MachineBasicBlock &Duplicate
Analysis->FalseTarget == &Duplicate);
if (!IsImplicitEdge)
return false;
- auto Inserted = Info.insertUnconditionalBranch(Predecessor, Canonical, Function, Target);
+ auto Inserted = Info.insertBranch(Predecessor, Canonical, Function, Target);
if (!Inserted)
return std::unexpected(Inserted.error());
}
diff --git a/backend/lib/Target/RISCV/CMakeLists.txt b/backend/lib/Target/RISCV/CMakeLists.txt
index 68bd444..d28cdf3 100644
--- a/backend/lib/Target/RISCV/CMakeLists.txt
+++ b/backend/lib/Target/RISCV/CMakeLists.txt
@@ -47,7 +47,7 @@ set_source_files_properties(
add_library(
RCCBackendRISCV
- RISCVBranchInfo.cpp
+ RISCVInstrInfo.cpp
RISCVCodeGen.cpp
RISCVCallLowering.cpp
RISCVAssemblyPrinter.cpp
@@ -84,7 +84,9 @@ target_include_directories(
"$<BUILD_INTERFACE:${RCC_BACKEND_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${RCC_BACKEND_BINARY_DIR}/generated/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
- PRIVATE "${RCC_BACKEND_BINARY_DIR}/generated/lib/Target/RISCV"
+ PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ "${RCC_BACKEND_BINARY_DIR}/generated/lib/Target/RISCV"
)
target_link_libraries(
RCCBackendRISCV
@@ -116,7 +118,7 @@ install(
)
rcc_backend_register_format_files(
- "${CMAKE_CURRENT_SOURCE_DIR}/RISCVBranchInfo.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVAssemblyPrinter.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVCodeGen.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVCallLowering.cpp"
@@ -140,6 +142,7 @@ rcc_backend_register_format_files(
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVTarget.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVTargetConstant.cpp"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVCodeGen.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfo.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVAssemblyPrinter.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVCallLowering.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVInstPrinter.h"
@@ -156,7 +159,7 @@ rcc_backend_register_format_files(
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVTargetRelocationKinds.h"
)
rcc_backend_register_tidy_files(
- "${CMAKE_CURRENT_SOURCE_DIR}/RISCVBranchInfo.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVAssemblyPrinter.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVCodeGen.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVCallLowering.cpp"
diff --git a/backend/lib/Target/RISCV/RISCVCodeGen.cpp b/backend/lib/Target/RISCV/RISCVCodeGen.cpp
index d03653f..00dba94 100644
--- a/backend/lib/Target/RISCV/RISCVCodeGen.cpp
+++ b/backend/lib/Target/RISCV/RISCVCodeGen.cpp
@@ -6512,198 +6512,6 @@ private:
}
};
-class RISCVSSAInfo final : public TargetSSAInfo {
-public:
- [[nodiscard]] Expected<bool> isFallthroughEdge(const MachineBasicBlock &From,
- const MachineBasicBlock &To,
- const MachineFunction &,
- const TargetDescription &Target) const override {
- if (From.next() != &To ||
- std::ranges::none_of(From.successors(), [&To](const MachineSuccessor &Successor) {
- return Successor.Block == &To;
- })) {
- return false;
- }
-
- bool CanFallThrough = true;
- for (const MachineInstr *Instruction = From.firstInstruction(); Instruction != nullptr;
- Instruction = Instruction->next()) {
- const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode());
- if (Descriptor == nullptr) {
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V fallthrough analysis encountered an unknown opcode");
- }
- if (!Descriptor->Flags.has(InstructionFlag::Terminator))
- continue;
- CanFallThrough = isConditionalBranch(Instruction->opcode());
- }
- return CanFallThrough;
- }
-
- [[nodiscard]] Expected<bool> rewriteBranchTarget(MachineBasicBlock &Block,
- MachineBasicBlock &OldTarget,
- MachineBasicBlock &NewTarget,
- MachineFunction &Function,
- const TargetDescription &Target) const override {
- if (&Block.function() != &Function || &OldTarget.function() != &Function ||
- &NewTarget.function() != &Function) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "RISC-V branch rewrite references another machine function");
- }
-
- bool Changed = false;
- for (MachineInstr *Instruction = Block.firstInstruction(); Instruction != nullptr;
- Instruction = Instruction->next()) {
- const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode());
- if (Descriptor == nullptr) {
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V branch rewrite encountered an unknown opcode");
- }
- if (!Descriptor->Flags.has(InstructionFlag::Branch) ||
- Descriptor->Flags.has(InstructionFlag::IndirectBranch)) {
- continue;
- }
- for (std::size_t Index = 0; Index < Instruction->operandCount(); ++Index) {
- MachineOperand *Operand = Instruction->operandAt(Index);
- const BasicBlockOperand *TargetOperand =
- Operand == nullptr ? nullptr : Operand->getIf<BasicBlockOperand>();
- if (TargetOperand == nullptr || TargetOperand->Block != &OldTarget)
- continue;
- auto Rewritten = Operand->setBasicBlock(NewTarget);
- if (!Rewritten)
- return std::unexpected(Rewritten.error());
- Changed = true;
- }
- }
- return Changed;
- }
-
- [[nodiscard]] Expected<void>
- insertUnconditionalBranch(MachineBasicBlock &Block, MachineBasicBlock &TargetBlock,
- MachineFunction &Function,
- const TargetDescription &Target) const override {
- if (&Block.function() != &Function || &TargetBlock.function() != &Function) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "RISC-V branch insertion references another machine function");
- }
- auto Zero = physicalRegister(PhysicalRegisterID::X0);
- if (!Zero)
- return std::unexpected(Zero.error());
- MachineIRBuilder Builder(Function, Target);
- auto Point = Builder.setInsertPoint(Block);
- if (!Point)
- return std::unexpected(Point.error());
- auto Branch = Builder.buildInstr(targetOpcode(InstructionOpcode::JAL));
- if (!Branch)
- return std::unexpected(Branch.error());
- auto Link = Branch->addDef(Register::fromPhysical(*Zero));
- if (!Link)
- return std::unexpected(Link.error());
- auto Destination = Branch->addBasicBlock(TargetBlock);
- if (!Destination)
- return std::unexpected(Destination.error());
- auto Built = Branch->build();
- if (!Built)
- return std::unexpected(Built.error());
- return {};
- }
-
- [[nodiscard]] Expected<void> validateCopy(Register Destination, SubRegIndex DestinationSubReg,
- Register Source, SubRegIndex SourceSubReg,
- const MachineFunction &Function,
- const TargetDescription &Target) const override {
- if (Destination.isNoRegister() || Source.isNoRegister()) {
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V COPY requires two nonzero registers");
- }
- if (DestinationSubReg.value() != 0 || SourceSubReg.value() != 0) {
- return makeUnexpected(ErrorCode::Unsupported, "RV64GC does not model register subindices");
- }
-
- auto DestinationShape = copyShape(Destination, Function, Target);
- if (!DestinationShape)
- return std::unexpected(DestinationShape.error());
- auto SourceShape = copyShape(Source, Function, Target);
- if (!SourceShape)
- return std::unexpected(SourceShape.error());
- if (DestinationShape->Bank == SourceShape->Bank) {
- if (DestinationShape->Width && SourceShape->Width &&
- DestinationShape->Width != SourceShape->Width) {
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V same-bank COPY has incompatible register widths");
- }
- return {};
- }
-
- const RegisterBankID GPR =
- RegisterBankID::fromValue(static_cast<std::uint32_t>(RegisterBank::GPR));
- const RegisterBankID FPR =
- RegisterBankID::fromValue(static_cast<std::uint32_t>(RegisterBank::FPR));
- const bool IsCrossBankMove = (DestinationShape->Bank == GPR && SourceShape->Bank == FPR) ||
- (DestinationShape->Bank == FPR && SourceShape->Bank == GPR);
- if (!IsCrossBankMove) {
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V COPY crosses unsupported register banks");
- }
- auto SupportedWidth = [](std::optional<std::uint32_t> Width) {
- return !Width || *Width == 32 || *Width == 64;
- };
- if (!SupportedWidth(DestinationShape->Width) || !SupportedWidth(SourceShape->Width)) {
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V GPR/FPR COPY requires 32-bit or 64-bit values");
- }
- return {};
- }
-
-private:
- struct CopyShape final {
- RegisterBankID Bank;
- std::optional<std::uint32_t> Width;
- };
-
- [[nodiscard]] static bool isConditionalBranch(Opcode Value) noexcept {
- return Value == targetOpcode(InstructionOpcode::BEQ) ||
- Value == targetOpcode(InstructionOpcode::BNE) ||
- Value == targetOpcode(InstructionOpcode::BLT) ||
- Value == targetOpcode(InstructionOpcode::BGE) ||
- Value == targetOpcode(InstructionOpcode::BLTU) ||
- Value == targetOpcode(InstructionOpcode::BGEU);
- }
-
- [[nodiscard]] static Expected<CopyShape> copyShape(Register Reg, const MachineFunction &Function,
- const TargetDescription &Target) {
- if (Reg.isVirtual()) {
- auto Info = Function.registerInfo().virtualRegisterInfo(Reg);
- if (!Info)
- return std::unexpected(Info.error());
- const std::optional<RegisterBankID> &Bank = Info->get().Bank;
- const std::optional<RegisterClassID> &RegClass = Info->get().RegClass;
- if (!Bank || !RegClass) {
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V COPY virtual register is not fully constrained");
- }
- const RegisterClassDesc *Class = Target.registers().registerClass(RegClass.value());
- if (Class == nullptr) {
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V COPY references an unknown register class");
- }
- return CopyShape{Bank.value(), Class->SizeInBits};
- }
-
- const std::optional<PhysicalRegister> Physical = Reg.physicalRegister();
- if (!Physical || !Target.registers().isKnownPhysicalRegister(*Physical)) {
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V COPY references an unknown physical register");
- }
- for (const RegisterBankDesc &Bank : Target.registers().registerBanks()) {
- if (Target.registers().bankContainsRegister(Bank.ID, *Physical))
- return CopyShape{Bank.ID, std::nullopt};
- }
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V physical register is not assigned to a register bank");
- }
-};
-
} // namespace
const TargetLegalizerInfo &legalizerInfo() noexcept {
@@ -6725,9 +6533,4 @@ const TargetInstructionSelector &instructionSelector() noexcept {
return Value;
}
-const TargetSSAInfo &ssaInfo() noexcept {
- static const RISCVSSAInfo Value;
- return Value;
-}
-
} // namespace rcc::riscv
diff --git a/backend/lib/Target/RISCV/RISCVBranchInfo.cpp b/backend/lib/Target/RISCV/RISCVInstrInfo.cpp
index 059bbef..6e26e2c 100644
--- a/backend/lib/Target/RISCV/RISCVBranchInfo.cpp
+++ b/backend/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
+#include "RISCVInstrInfo.h"
+
#include "rcc/CodeGen/InstructionDescriptor.h"
#include "rcc/CodeGen/MachineBasicBlock.h"
#include "rcc/CodeGen/MachineFunction.h"
@@ -8,7 +10,6 @@
#include "rcc/CodeGen/MachineOperand.h"
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/TargetDescription.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"
@@ -497,7 +498,7 @@ selectLongBranchScratch(const MachineInstr &Instruction, const MachineBasicBlock
return true;
}
-class RISCVBranchInfo final : public TargetInstrInfo {
+class RISCVInstrInfo final : public TargetInstrInfo {
public:
[[nodiscard]] Expected<MachineBranchAnalysis>
analyzeBranch(MachineBasicBlock &Block, MachineFunction &Function,
@@ -623,9 +624,8 @@ public:
}
[[nodiscard]] Expected<MachineInstr *>
- insertUnconditionalBranch(MachineBasicBlock &Block, MachineBasicBlock &TargetBlock,
- MachineFunction &Function,
- const TargetDescription &Target) const override {
+ insertBranch(MachineBasicBlock &Block, MachineBasicBlock &TargetBlock, MachineFunction &Function,
+ const TargetDescription &Target) const override {
if (&Block.function() != &Function || &TargetBlock.function() != &Function)
return makeUnexpected(ErrorCode::InvalidArgument,
"RISC-V branch insertion references another function");
@@ -635,6 +635,75 @@ public:
return buildJAL(Function, Target, Block, nullptr, *Zero, TargetBlock);
}
+ [[nodiscard]] Expected<bool> isFallthroughEdge(const MachineBasicBlock &From,
+ const MachineBasicBlock &To,
+ const MachineFunction &Function,
+ const TargetDescription &Target) const override {
+ if (&From.function() != &Function || &To.function() != &Function)
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "RISC-V fallthrough query references another machine function");
+ if (From.next() != &To ||
+ std::ranges::none_of(From.successors(), [&To](const MachineSuccessor &Successor) {
+ return Successor.Block == &To;
+ })) {
+ return false;
+ }
+
+ bool CanFallThrough = true;
+ for (const MachineInstr *Instruction = From.firstInstruction(); Instruction != nullptr;
+ Instruction = Instruction->next()) {
+ const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode());
+ if (Descriptor == nullptr)
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V fallthrough analysis encountered an unknown opcode");
+ if (Descriptor->Flags.has(InstructionFlag::Terminator))
+ CanFallThrough = isConditionalBranch(Instruction->opcode());
+ }
+ return CanFallThrough;
+ }
+
+ [[nodiscard]] Expected<void> validateCopy(Register Destination, SubRegIndex DestinationSubReg,
+ Register Source, SubRegIndex SourceSubReg,
+ const MachineFunction &Function,
+ const TargetDescription &Target) const override {
+ if (Destination.isNoRegister() || Source.isNoRegister())
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V COPY requires two nonzero registers");
+ if (DestinationSubReg.value() != 0 || SourceSubReg.value() != 0)
+ return makeUnexpected(ErrorCode::Unsupported, "RV64GC does not model register subindices");
+
+ auto DestinationShape = copyShape(Destination, Function, Target);
+ if (!DestinationShape)
+ return std::unexpected(DestinationShape.error());
+ auto SourceShape = copyShape(Source, Function, Target);
+ if (!SourceShape)
+ return std::unexpected(SourceShape.error());
+ if (DestinationShape->Bank == SourceShape->Bank) {
+ if (DestinationShape->Width && SourceShape->Width &&
+ DestinationShape->Width != SourceShape->Width)
+ return makeUnexpected(ErrorCode::Unsupported,
+ "RISC-V same-bank COPY has incompatible register widths");
+ return {};
+ }
+
+ const RegisterBankID GPR =
+ RegisterBankID::fromValue(static_cast<std::uint32_t>(RegisterBank::GPR));
+ const RegisterBankID FPR =
+ RegisterBankID::fromValue(static_cast<std::uint32_t>(RegisterBank::FPR));
+ const bool IsCrossBankMove = (DestinationShape->Bank == GPR && SourceShape->Bank == FPR) ||
+ (DestinationShape->Bank == FPR && SourceShape->Bank == GPR);
+ if (!IsCrossBankMove)
+ return makeUnexpected(ErrorCode::Unsupported,
+ "RISC-V COPY crosses unsupported register banks");
+ const auto SupportedWidth = [](std::optional<std::uint32_t> Width) {
+ return !Width || *Width == 32 || *Width == 64;
+ };
+ if (!SupportedWidth(DestinationShape->Width) || !SupportedWidth(SourceShape->Width))
+ return makeUnexpected(ErrorCode::Unsupported,
+ "RISC-V GPR/FPR COPY requires 32-bit or 64-bit values");
+ return {};
+ }
+
[[nodiscard]] Expected<std::uint32_t>
instructionSize(const MachineInstr &Instruction, const MachineFunction &,
const TargetDescription &Target) const override {
@@ -726,12 +795,48 @@ public:
return relaxJAL(Instruction, Offset, Function, Target);
return false;
}
+
+private:
+ struct CopyShape final {
+ RegisterBankID Bank;
+ std::optional<std::uint32_t> Width;
+ };
+
+ [[nodiscard]] static Expected<CopyShape> copyShape(Register Reg, const MachineFunction &Function,
+ const TargetDescription &Target) {
+ if (Reg.isVirtual()) {
+ auto Info = Function.registerInfo().virtualRegisterInfo(Reg);
+ if (!Info)
+ return std::unexpected(Info.error());
+ const std::optional<RegisterBankID> &Bank = Info->get().Bank;
+ const std::optional<RegisterClassID> &RegClass = Info->get().RegClass;
+ if (!Bank || !RegClass)
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V COPY virtual register is not fully constrained");
+ const RegisterClassDesc *Class = Target.registers().registerClass(*RegClass);
+ if (Class == nullptr)
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V COPY references an unknown register class");
+ return CopyShape{*Bank, Class->SizeInBits};
+ }
+
+ const std::optional<PhysicalRegister> Physical = Reg.physicalRegister();
+ if (!Physical || !Target.registers().isKnownPhysicalRegister(*Physical))
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V COPY references an unknown physical register");
+ for (const RegisterBankDesc &Bank : Target.registers().registerBanks()) {
+ if (Target.registers().bankContainsRegister(Bank.ID, *Physical))
+ return CopyShape{Bank.ID, std::nullopt};
+ }
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RISC-V physical register is not assigned to a register bank");
+ }
};
} // namespace
-const TargetInstrInfo &branchInfo() noexcept {
- static const RISCVBranchInfo Value;
+const TargetInstrInfo &instrInfo() noexcept {
+ static const RISCVInstrInfo Value;
return Value;
}
diff --git a/backend/lib/Target/RISCV/RISCVInstrInfo.h b/backend/lib/Target/RISCV/RISCVInstrInfo.h
new file mode 100644
index 0000000..62c7723
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVInstrInfo.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_LIB_TARGET_RISCV_RISCVINSTRINFO_H
+#define RCC_LIB_TARGET_RISCV_RISCVINSTRINFO_H
+
+#include "rcc/CodeGen/TargetInstrInfo.h"
+
+namespace rcc::riscv {
+
+[[nodiscard]] const TargetInstrInfo &instrInfo() noexcept;
+
+} // namespace rcc::riscv
+
+#endif // RCC_LIB_TARGET_RISCV_RISCVINSTRINFO_H
diff --git a/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp b/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp
index 2f8c5d1..9301757 100644
--- a/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp
+++ b/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp
@@ -1,18 +1,18 @@
// SPDX-License-Identifier: GPL-3.0-or-later
+#include "RISCVInstrInfo.h"
#include "rcc/Target/RISCV/RISCVCodeGen.h"
namespace rcc::riscv {
MachineOptimizationPipelineTargetInfo optimizationPipelineInfo() noexcept {
return {
- .SSA = ssaInfo(),
+ .InstrInfo = instrInfo(),
.Combiner = machineCombinerInfo(),
.MemoryFolding = memoryFoldingInfo(),
.FrameLowering = frameLowering(),
.PseudoExpansion = pseudoExpansionInfo(),
.SchedulingModel = schedulingModel(),
- .BranchInfo = branchInfo(),
};
}
diff --git a/backend/lib/Target/RISCV/RISCVPipeline.cpp b/backend/lib/Target/RISCV/RISCVPipeline.cpp
index 3665db5..08a4653 100644
--- a/backend/lib/Target/RISCV/RISCVPipeline.cpp
+++ b/backend/lib/Target/RISCV/RISCVPipeline.cpp
@@ -2,6 +2,7 @@
#include "rcc/Target/RISCV/RISCVPipeline.h"
+#include "RISCVInstrInfo.h"
#include "rcc/CodeGen/MachineCombiner.h"
#include "rcc/CodeGen/MachineFunction.h"
#include "rcc/CodeGen/MachineOptimizationPipeline.h"
@@ -45,10 +46,10 @@ template <typename PassT, typename... ArgumentT>
auto Added = addSelectedSSAOptimizationPipeline(Pipeline, optimizationPipelineInfo());
if (!Added)
return std::unexpected(Added.error());
- Added = addPass<PHIEliminationPass>(Pipeline, ssaInfo());
+ Added = addPass<PHIEliminationPass>(Pipeline, instrInfo());
if (!Added)
return std::unexpected(Added.error());
- return addPass<TwoAddressRewritePass>(Pipeline, ssaInfo());
+ return addPass<TwoAddressRewritePass>(Pipeline, instrInfo());
}
[[nodiscard]] Expected<void> addRegisterAllocationPipeline(MachinePassManager &Pipeline) {
@@ -104,13 +105,13 @@ Expected<void> addCanonicalPipeline(MachinePassManager &Pipeline, const MachineF
if (!Added)
return std::unexpected(Added.error());
if (!Function.properties().has(MachineFunctionProperty::NoPHIs)) {
- Added = addPass<PHIEliminationPass>(Pipeline, ssaInfo());
+ Added = addPass<PHIEliminationPass>(Pipeline, instrInfo());
if (!Added)
return std::unexpected(Added.error());
}
}
if (!Function.properties().has(MachineFunctionProperty::TiedOpsRewritten)) {
- auto Added = addPass<TwoAddressRewritePass>(Pipeline, ssaInfo());
+ auto Added = addPass<TwoAddressRewritePass>(Pipeline, instrInfo());
if (!Added)
return std::unexpected(Added.error());
}
diff --git a/backend/unittests/CodeGen/MachineSSAExitTest.cpp b/backend/unittests/CodeGen/MachineSSAExitTest.cpp
index a3940c2..a5cc1c7 100644
--- a/backend/unittests/CodeGen/MachineSSAExitTest.cpp
+++ b/backend/unittests/CodeGen/MachineSSAExitTest.cpp
@@ -15,6 +15,7 @@
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/MachineVerifier.h"
#include "rcc/CodeGen/TargetDescription.h"
+#include "rcc/CodeGen/TargetInstrInfo.h"
#include <algorithm>
#include <array>
@@ -158,9 +159,26 @@ private:
return rcc::test::createTestTargetDescription(std::move(*Instructions));
}
-class TestSSAInfo final : public rcc::TargetSSAInfo {
+class TestInstrInfo final : public rcc::TargetInstrInfo {
public:
- explicit TestSSAInfo(bool RejectCopies = false) : RejectCopies(RejectCopies) {}
+ explicit TestInstrInfo(bool RejectCopies = false) : RejectCopies(RejectCopies) {}
+
+ [[nodiscard]] rcc::Expected<rcc::MachineBranchAnalysis>
+ analyzeBranch(rcc::MachineBasicBlock &, rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
+ return rcc::MachineBranchAnalysis{};
+ }
+
+ [[nodiscard]] rcc::Expected<void>
+ reverseBranchCondition(rcc::MachineInstr &, rcc::MachineBasicBlock &, rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
+ return rcc::makeUnexpected(rcc::ErrorCode::Unsupported, "test target has no branch reversal");
+ }
+
+ [[nodiscard]] rcc::Expected<void> removeBranch(rcc::MachineInstr &, rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
+ return rcc::makeUnexpected(rcc::ErrorCode::Unsupported, "test target has no branch removal");
+ }
[[nodiscard]] rcc::Expected<bool>
isFallthroughEdge(const rcc::MachineBasicBlock &From, const rcc::MachineBasicBlock &To,
@@ -225,10 +243,10 @@ public:
return Changed;
}
- [[nodiscard]] rcc::Expected<void>
- insertUnconditionalBranch(rcc::MachineBasicBlock &Block, rcc::MachineBasicBlock &TargetBlock,
- rcc::MachineFunction &Function,
- const rcc::TargetDescription &Target) const override {
+ [[nodiscard]] rcc::Expected<rcc::MachineInstr *>
+ insertBranch(rcc::MachineBasicBlock &Block, rcc::MachineBasicBlock &TargetBlock,
+ rcc::MachineFunction &Function,
+ const rcc::TargetDescription &Target) const override {
rcc::MachineIRBuilder Builder(Function, Target);
auto Point = Builder.setInsertPoint(Block);
if (!Point)
@@ -242,7 +260,7 @@ public:
auto Built = Pending->build();
if (!Built)
return std::unexpected(Built.error());
- return {};
+ return *Built;
}
[[nodiscard]] rcc::Expected<void>
@@ -289,6 +307,29 @@ public:
return true;
}
+ [[nodiscard]] rcc::Expected<std::uint32_t>
+ instructionSize(const rcc::MachineInstr &, const rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
+ return 4;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::MachineBasicBlock *>
+ branchTarget(rcc::MachineInstr &, rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
+ return static_cast<rcc::MachineBasicBlock *>(nullptr);
+ }
+
+ [[nodiscard]] bool isBranchOffsetInRange(const rcc::MachineInstr &,
+ std::int64_t) const noexcept override {
+ return true;
+ }
+
+ [[nodiscard]] rcc::Expected<bool> relaxBranch(rcc::MachineInstr &, std::int64_t,
+ rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
+ return false;
+ }
+
private:
bool RejectCopies = false;
};
@@ -430,7 +471,7 @@ buildPhi(rcc::MachineFunction &Function, const rcc::TargetDescription &Target,
[[nodiscard]] rcc::Expected<void> runPHIElimination(rcc::MachineFunction &Function,
const rcc::TargetDescription &Target,
- const rcc::TargetSSAInfo &Info) {
+ const rcc::TargetInstrInfo &Info) {
rcc::MachinePassManager Pipeline;
auto Added = Pipeline.addPass(std::make_unique<rcc::PHIEliminationPass>(Info));
if (!Added)
@@ -469,7 +510,7 @@ instructionsWithOpcode(rcc::MachineFunction &Function, rcc::Opcode Opcode) {
}
void testParallelPHIsAndPlacement(TestContext &Context, const rcc::TargetDescription &Target,
- const TestSSAInfo &Info) {
+ const TestInstrInfo &Info) {
auto Fixture = createFunction(Context, "parallel_phis", 1, 3);
if (!Fixture.Function || Fixture.Blocks.size() != 3)
return;
@@ -620,7 +661,7 @@ void testParallelPHIsAndPlacement(TestContext &Context, const rcc::TargetDescrip
}
void testCriticalEdgeAndPhysicalLiveIn(TestContext &Context, const rcc::TargetDescription &Target,
- const TestSSAInfo &Info) {
+ const TestInstrInfo &Info) {
auto Fixture = createFunction(Context, "critical_edge", 2, 4);
if (!Fixture.Function || Fixture.Blocks.size() != 4)
return;
@@ -721,7 +762,7 @@ void testCriticalEdgeAndPhysicalLiveIn(TestContext &Context, const rcc::TargetDe
}
void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescription &Target,
- const TestSSAInfo &Info) {
+ const TestInstrInfo &Info) {
auto BuildFixture = [&](std::uint64_t ID) {
auto Fixture = createFunction(Context, "undef_phi", ID, 2);
if (!Fixture.Function || Fixture.Blocks.size() != 2)
@@ -773,7 +814,7 @@ void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescrip
instructionsWithOpcode(*Atomic.Function, rcc::opcode(rcc::GenericOpcode::PHI)).size();
const std::size_t RegistersBefore = Atomic.Function->registerInfo().virtualRegisters().size();
const std::uint64_t PropertiesBefore = Atomic.Function->properties().rawValue();
- TestSSAInfo RejectingInfo(true);
+ TestInstrInfo RejectingInfo(true);
rcc::MachineAnalysisManager Analyses;
rcc::PHIEliminationPass FailingPass(RejectingInfo);
auto Failed = FailingPass.run(*Atomic.Function, Target, Analyses);
@@ -794,7 +835,7 @@ void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescrip
}
void testTwoAddressAndSubregisterPseudos(TestContext &Context, const rcc::TargetDescription &Target,
- const TestSSAInfo &Info) {
+ const TestInstrInfo &Info) {
auto Fixture = createFunction(Context, "two_address", 5, 1);
if (!Fixture.Function || Fixture.Blocks.empty())
return;
@@ -1015,7 +1056,7 @@ void testTwoAddressAndSubregisterPseudos(TestContext &Context, const rcc::Target
AtomicFixture.Function->registerInfo().virtualRegisters().size();
const std::uint64_t AtomicPropertiesBefore = AtomicFixture.Function->properties().rawValue();
- TestSSAInfo RejectingInfo(true);
+ TestInstrInfo RejectingInfo(true);
rcc::MachineAnalysisManager AtomicAnalyses;
rcc::TwoAddressRewritePass FailingPass(RejectingInfo);
auto Failed = FailingPass.run(*AtomicFixture.Function, Target, AtomicAnalyses);
@@ -1128,7 +1169,7 @@ int main() {
Context.expect(Target.has_value(), "SSA-exit TestTarget must be created");
if (!Target)
return Context.result();
- TestSSAInfo Info;
+ TestInstrInfo Info;
testParallelPHIsAndPlacement(Context, *Target, Info);
testCriticalEdgeAndPhysicalLiveIn(Context, *Target, Info);
testUndefAndFailureAtomicity(Context, *Target, Info);
diff --git a/backend/unittests/Target/CMakeLists.txt b/backend/unittests/Target/CMakeLists.txt
index e68c525..0b4ed74 100644
--- a/backend/unittests/Target/CMakeLists.txt
+++ b/backend/unittests/Target/CMakeLists.txt
@@ -34,6 +34,10 @@ 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)
@@ -61,6 +65,10 @@ 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/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp
index 97590cd..d0bd952 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 "RISCVInstrInfo.h"
#include "rcc/CodeGen/GenericOpcodes.h"
#include "rcc/CodeGen/MachineBasicBlock.h"
#include "rcc/CodeGen/MachineBlockPlacement.h"
@@ -102,7 +103,7 @@ public:
}
};
-class FixedSizeBranchInfo final : public rcc::TargetInstrInfo {
+class FixedSizeInstrInfo final : public rcc::TargetInstrInfo {
public:
[[nodiscard]] rcc::Expected<rcc::MachineBranchAnalysis>
analyzeBranch(rcc::MachineBasicBlock &, rcc::MachineFunction &,
@@ -128,11 +129,23 @@ public:
}
[[nodiscard]] rcc::Expected<rcc::MachineInstr *>
- insertUnconditionalBranch(rcc::MachineBasicBlock &, rcc::MachineBasicBlock &,
- rcc::MachineFunction &, const rcc::TargetDescription &) const override {
+ insertBranch(rcc::MachineBasicBlock &, rcc::MachineBasicBlock &, rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
return rcc::makeUnexpected(rcc::ErrorCode::Unsupported, "test target has no branches");
}
+ [[nodiscard]] rcc::Expected<bool>
+ isFallthroughEdge(const rcc::MachineBasicBlock &, const rcc::MachineBasicBlock &,
+ const rcc::MachineFunction &, const rcc::TargetDescription &) const override {
+ return false;
+ }
+
+ [[nodiscard]] rcc::Expected<void> validateCopy(rcc::Register, rcc::SubRegIndex, rcc::Register,
+ rcc::SubRegIndex, const rcc::MachineFunction &,
+ const rcc::TargetDescription &) const override {
+ return rcc::makeUnexpected(rcc::ErrorCode::Unsupported, "test target has no COPY support");
+ }
+
[[nodiscard]] rcc::Expected<std::uint32_t>
instructionSize(const rcc::MachineInstr &, const rcc::MachineFunction &,
const rcc::TargetDescription &) const override {
@@ -398,7 +411,7 @@ void testFallthroughNormalization(TestContext &Context, const rcc::TargetDescrip
auto Liveness = rcc::rebuildMachineLiveness(*Function, Target);
Context.expect(Liveness.has_value(), "fallthrough fixture liveness must be rebuilt");
rcc::MachineAnalysisManager Analyses;
- rcc::MachineFallthroughPass Pass(rcc::riscv::branchInfo());
+ rcc::MachineFallthroughPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
std::cerr << "fallthrough normalization failure: " << Result.error().message() << '\n';
@@ -433,7 +446,7 @@ void testFallthroughMaterialization(TestContext &Context, const rcc::TargetDescr
Context.expect(rcc::rebuildMachineLiveness(*Function, Target).has_value(),
"materialized fallthrough liveness must be rebuilt");
rcc::MachineAnalysisManager Analyses;
- rcc::MachineFallthroughPass Pass(rcc::riscv::branchInfo());
+ rcc::MachineFallthroughPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
std::cerr << "fallthrough materialization failure: " << Result.error().message() << '\n';
@@ -474,7 +487,7 @@ void testBranchOptimization(TestContext &Context, const rcc::TargetDescription &
}
setSelectedProperties(*Function);
rcc::MachineAnalysisManager Analyses;
- rcc::MachineBranchOptimizationPass Pass(rcc::riscv::branchInfo());
+ rcc::MachineBranchOptimizationPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
std::cerr << "branch optimization failure: " << Result.error().message() << '\n';
@@ -554,7 +567,7 @@ void testTailDuplication(TestContext &Context, const rcc::TargetDescription &Tar
}
setRelaxationProperties(Context, *Function, Target);
rcc::MachineAnalysisManager Analyses;
- rcc::MachineTailDuplicationPass Pass(rcc::riscv::branchInfo());
+ rcc::MachineTailDuplicationPass Pass(rcc::riscv::instrInfo());
Tail->attributes().set(rcc::MachineBasicBlockAttribute::MachineBlockAddressTaken);
auto Protected = Pass.run(*Function, Target, Analyses);
Context.expect(Protected && !Protected->Changed && Tail->isLinked(),
@@ -605,7 +618,7 @@ void testTailMerge(TestContext &Context, const rcc::TargetDescription &Target) {
}
setRelaxationProperties(Context, *Function, Target);
rcc::MachineAnalysisManager Analyses;
- rcc::MachineTailMergePass Pass(rcc::riscv::branchInfo());
+ rcc::MachineTailMergePass Pass(rcc::riscv::instrInfo());
Second->attributes().set(rcc::MachineBasicBlockAttribute::MachineBlockAddressTaken);
auto Protected = Pass.run(*Function, Target, Analyses);
Context.expect(Protected && !Protected->Changed && Second->isLinked(),
@@ -650,7 +663,7 @@ void testCopyPropagation(TestContext &Context, const rcc::TargetDescription &Tar
return;
setSelectedProperties(*Function);
rcc::MachineAnalysisManager Analyses;
- rcc::MachineCopyPropagationPass PreRA(rcc::riscv::ssaInfo(),
+ rcc::MachineCopyPropagationPass PreRA(rcc::riscv::instrInfo(),
rcc::MachineCopyPropagationStage::PreRegisterAllocation);
auto PreResult = PreRA.run(*Function, Target, Analyses);
if (!PreResult)
@@ -690,7 +703,7 @@ void testCopyPropagation(TestContext &Context, const rcc::TargetDescription &Tar
Context.expect(rcc::rebuildMachineLiveness(*PostFunction, Target).has_value(),
"post-RA COPY propagation liveness must be rebuilt");
rcc::MachineAnalysisManager PostAnalyses;
- rcc::MachineCopyPropagationPass PostRA(rcc::riscv::ssaInfo(),
+ rcc::MachineCopyPropagationPass PostRA(rcc::riscv::instrInfo(),
rcc::MachineCopyPropagationStage::PostRegisterAllocation);
auto PostResult = PostRA.run(*PostFunction, Target, PostAnalyses);
if (!PostResult)
@@ -963,7 +976,7 @@ void testCompressedAndConditionalRelaxation(TestContext &Context,
return;
setRelaxationProperties(Context, *Function, Target);
rcc::MachineAnalysisManager Analyses;
- rcc::MachineBranchRelaxationPass Pass(rcc::riscv::branchInfo());
+ rcc::MachineBranchRelaxationPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
std::cerr << "conditional relaxation failure: " << Result.error().message() << '\n';
@@ -998,7 +1011,7 @@ void testCompressedAndConditionalRelaxation(TestContext &Context,
if (!Compressed)
return;
auto Expanded =
- rcc::riscv::branchInfo().relaxBranch(**Compressed, 4096, *CompressedFunction, Target);
+ rcc::riscv::instrInfo().relaxBranch(**Compressed, 4096, *CompressedFunction, Target);
Context.expect(Expanded && *Expanded && CompressedEntry->firstInstruction() != nullptr &&
CompressedEntry->firstInstruction()->opcode() ==
opcode(rcc::riscv::InstructionOpcode::JAL) &&
@@ -1029,13 +1042,13 @@ void testLongJALRelaxation(TestContext &Context, const rcc::TargetDescription &T
"long JAL live-in and annotation fixture must be valid");
if (!X5 || !X6)
return;
- auto TooFar = rcc::riscv::branchInfo().relaxBranch(*JAL, std::numeric_limits<std::int64_t>::max(),
- *Function, Target);
+ auto TooFar = rcc::riscv::instrInfo().relaxBranch(*JAL, std::numeric_limits<std::int64_t>::max(),
+ *Function, Target);
Context.expect(!TooFar && TooFar.error().code() == rcc::ErrorCode::BranchRelaxationFailed &&
JAL->parent() == Entry,
"long JAL relaxation must reject an unencodable PC-relative distance atomically");
auto Relaxed =
- rcc::riscv::branchInfo().relaxBranch(*JAL, std::int64_t{2} * 1024 * 1024, *Function, Target);
+ rcc::riscv::instrInfo().relaxBranch(*JAL, std::int64_t{2} * 1024 * 1024, *Function, Target);
if (!Relaxed)
std::cerr << "long JAL relaxation failure: " << Relaxed.error().message() << '\n';
rcc::MachineInstr *High = Entry->firstInstruction();
@@ -1186,7 +1199,7 @@ void testPostRAPseudoExpansionAndFinalization(TestContext &Context,
rcc::MachinePassManager Pipeline;
Context.expect(Pipeline.addPass(std::make_unique<rcc::FinalizeEmissionPseudosPass>()) &&
Pipeline.addPass(std::make_unique<rcc::FinalEncodabilityVerifierPass>(
- rcc::riscv::branchInfo())),
+ rcc::riscv::instrInfo())),
"finalization passes must register");
auto Finalized = Pipeline.run(*Function, Target, Analyses);
if (!Finalized)
@@ -1310,8 +1323,8 @@ void testTargetLateExpansionRejectsSizeGrowth(TestContext &Context) {
return;
GrowingLatePseudoInfo ExpansionInfo;
- FixedSizeBranchInfo BranchInfo;
- rcc::TargetLatePseudoExpansionPass Pass(ExpansionInfo, BranchInfo);
+ FixedSizeInstrInfo InstrInfo;
+ rcc::TargetLatePseudoExpansionPass Pass(ExpansionInfo, InstrInfo);
rcc::MachineAnalysisManager Analyses;
auto Result = Pass.run(*Function, *Target, Analyses);
Context.expect(!Result && Result.error().code() == rcc::ErrorCode::PseudoExpansionFailed &&
@@ -1358,8 +1371,8 @@ void testTargetLateExpansionRejectsCompensatedGrowth(TestContext &Context) {
return;
GrowingLatePseudoInfo ExpansionInfo;
- FixedSizeBranchInfo BranchInfo;
- rcc::TargetLatePseudoExpansionPass Pass(ExpansionInfo, BranchInfo);
+ FixedSizeInstrInfo InstrInfo;
+ rcc::TargetLatePseudoExpansionPass Pass(ExpansionInfo, InstrInfo);
rcc::MachineAnalysisManager Analyses;
auto Result = Pass.run(*Function, *Target, Analyses);
Context.expect(
@@ -1391,7 +1404,7 @@ void testFinalEncodabilityRejectsInvalidInstruction(TestContext &Context,
}
setRelaxationProperties(Context, *ImmediateFunction, Target);
rcc::MachineAnalysisManager Analyses;
- rcc::FinalEncodabilityVerifierPass Verifier(rcc::riscv::branchInfo());
+ rcc::FinalEncodabilityVerifierPass Verifier(rcc::riscv::instrInfo());
auto ImmediateResult = Verifier.run(*ImmediateFunction, Target, Analyses);
Context.expect(!ImmediateResult &&
ImmediateResult.error().code() == rcc::ErrorCode::FinalEncodabilityFailed,
diff --git a/backend/unittests/Target/RISCVSSAExitTest.cpp b/backend/unittests/Target/RISCVSSAExitTest.cpp
index 8e1f5a2..18cbea9 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 "RISCVInstrInfo.h"
#include "rcc/CodeGen/GenericOpcodes.h"
#include "rcc/CodeGen/MachineBasicBlock.h"
#include "rcc/CodeGen/MachineCFGUpdater.h"
@@ -196,11 +197,11 @@ void testBehaviorAndCopyLegality(TestContext &Context, const rcc::TargetDescript
if (!CFG.addSuccessor(**First, **Second, rcc::BranchProbability::one()))
return;
- auto Fallthrough = rcc::riscv::ssaInfo().isFallthroughEdge(**First, **Second, **Function, Target);
+ auto Fallthrough =
+ rcc::riscv::instrInfo().isFallthroughEdge(**First, **Second, **Function, Target);
Context.expect(Fallthrough && *Fallthrough,
"RV64GC SSA behavior must recognize an empty layout fallthrough edge");
- auto Inserted =
- rcc::riscv::ssaInfo().insertUnconditionalBranch(**First, **Second, **Function, Target);
+ auto Inserted = rcc::riscv::instrInfo().insertBranch(**First, **Second, **Function, Target);
Context.expect(Inserted.has_value(), "RV64GC SSA behavior must insert an unconditional branch");
if (!Inserted)
return;
@@ -212,10 +213,10 @@ void testBehaviorAndCopyLegality(TestContext &Context, const rcc::TargetDescript
blockOperand(*Jump, 1) != nullptr && blockOperand(*Jump, 1)->Block == *Second,
"RV64GC unconditional branches must use JAL with x0 as the link destination");
auto NoFallthrough =
- rcc::riscv::ssaInfo().isFallthroughEdge(**First, **Second, **Function, Target);
+ rcc::riscv::instrInfo().isFallthroughEdge(**First, **Second, **Function, Target);
Context.expect(NoFallthrough && !*NoFallthrough, "JAL must terminate RV64GC layout fallthrough");
auto Rewritten =
- rcc::riscv::ssaInfo().rewriteBranchTarget(**First, **Second, **Third, **Function, Target);
+ rcc::riscv::instrInfo().rewriteBranchTarget(**First, **Second, **Third, **Function, Target);
Context.expect(Rewritten && *Rewritten && blockOperand(*Jump, 1)->Block == *Third,
"RV64GC branch target rewriting must update direct JAL operands");
@@ -237,21 +238,75 @@ void testBehaviorAndCopyLegality(TestContext &Context, const rcc::TargetDescript
return;
Context.expect(
- rcc::riscv::ssaInfo().validateCopy(*GPR, {}, *OtherGPR, {}, **Function, Target).has_value(),
+ rcc::riscv::instrInfo().validateCopy(*GPR, {}, *OtherGPR, {}, **Function, Target).has_value(),
"RV64GC must allow a compatible GPR COPY");
Context.expect(
- rcc::riscv::ssaInfo().validateCopy(*GPR, {}, *FPR64, {}, **Function, Target).has_value(),
+ rcc::riscv::instrInfo().validateCopy(*GPR, {}, *FPR64, {}, **Function, Target).has_value(),
"RV64GC must allow supported 64-bit GPR/FPR bit moves");
- Context.expect(!rcc::riscv::ssaInfo().validateCopy(*FPR64, {}, *FPR32, {}, **Function, Target),
+ Context.expect(!rcc::riscv::instrInfo().validateCopy(*FPR64, {}, *FPR32, {}, **Function, Target),
"RV64GC must reject incompatible same-bank COPY widths");
- Context.expect(!rcc::riscv::ssaInfo().validateCopy(*GPR, rcc::SubRegIndex::fromValue(1),
- *OtherGPR, {}, **Function, Target),
+ Context.expect(!rcc::riscv::instrInfo().validateCopy(*GPR, rcc::SubRegIndex::fromValue(1),
+ *OtherGPR, {}, **Function, Target),
"RV64GC must reject unmodeled subregister COPYs");
Context.expect(
- !rcc::riscv::ssaInfo().validateCopy(*GPR, {}, *Unclassified, {}, **Function, Target),
+ !rcc::riscv::instrInfo().validateCopy(*GPR, {}, *Unclassified, {}, **Function, Target),
"RV64GC must reject COPYs involving an unconstrained virtual register");
}
+void testCompressedConditionalBranchBehavior(TestContext &Context,
+ const rcc::TargetDescription &Target) {
+ auto Function = rcc::MachineFunction::create("riscv_compressed_branch",
+ rcc::MachineFunctionStableID::fromValue(3));
+ if (!Function)
+ return;
+ auto Source = appendBlock(**Function);
+ auto LayoutSuccessor = appendBlock(**Function);
+ auto BranchTarget = appendBlock(**Function);
+ auto ReplacementTarget = appendBlock(**Function);
+ if (!Source || !LayoutSuccessor || !BranchTarget || !ReplacementTarget)
+ return;
+ auto Half = rcc::BranchProbability::fromFraction(1, 2);
+ auto CFG = (*Function)->cfgUpdater();
+ if (!Half || !CFG.addSuccessor(**Source, **BranchTarget, *Half) ||
+ !CFG.addSuccessor(**Source, **LayoutSuccessor, *Half)) {
+ Context.expect(false, "compressed-branch CFG construction must succeed");
+ return;
+ }
+
+ auto X8 = rcc::riscv::physicalRegister(rcc::riscv::PhysicalRegisterID::X8);
+ rcc::MachineIRBuilder Builder(**Function, Target);
+ auto Point = Builder.setInsertPoint(**Source);
+ if (!Point) {
+ Context.expect(false, "compressed conditional branch insertion point must be established");
+ return;
+ }
+ auto Pending = Builder.buildInstr(targetOpcode(rcc::riscv::InstructionOpcode::C_BEQZ));
+ if (!X8 || !Pending || !Pending->addUse(rcc::Register::fromPhysical(*X8)) ||
+ !Pending->addBasicBlock(**BranchTarget)) {
+ Context.expect(false, "compressed conditional branch construction must succeed");
+ return;
+ }
+ auto Branch = Pending->build();
+ if (!Branch) {
+ Context.expect(false, "compressed conditional branch insertion must succeed");
+ return;
+ }
+
+ auto Fallthrough =
+ rcc::riscv::instrInfo().isFallthroughEdge(**Source, **LayoutSuccessor, **Function, Target);
+ auto Analysis = rcc::riscv::instrInfo().analyzeBranch(**Source, **Function, Target);
+ Context.expect(Fallthrough && *Fallthrough && Analysis && Analysis->Conditional == *Branch &&
+ Analysis->TrueTarget == *BranchTarget &&
+ Analysis->FalseTarget == *LayoutSuccessor,
+ "RV64GC instruction information must recognize compressed conditional branches");
+
+ auto Rewritten = rcc::riscv::instrInfo().rewriteBranchTarget(
+ **Source, **BranchTarget, **ReplacementTarget, **Function, Target);
+ Context.expect(Rewritten && *Rewritten && blockOperand(**Branch, 1) != nullptr &&
+ blockOperand(**Branch, 1)->Block == *ReplacementTarget,
+ "RV64GC instruction information must rewrite compressed branch targets");
+}
+
void testRV64GCCriticalEdge(TestContext &Context, const rcc::TargetDescription &Target) {
auto Function = rcc::MachineFunction::create("riscv_ssa_critical_edge",
rcc::MachineFunctionStableID::fromValue(2));
@@ -298,9 +353,10 @@ void testRV64GCCriticalEdge(TestContext &Context, const rcc::TargetDescription &
return;
rcc::MachinePassManager Pipeline;
- Context.expect(Pipeline.addPass(std::make_unique<rcc::PHIEliminationPass>(rcc::riscv::ssaInfo()))
- .has_value(),
- "RV64GC PHI-elimination pass must be registered");
+ Context.expect(
+ Pipeline.addPass(std::make_unique<rcc::PHIEliminationPass>(rcc::riscv::instrInfo()))
+ .has_value(),
+ "RV64GC PHI-elimination pass must be registered");
rcc::MachineAnalysisManager Analyses;
auto Run = Pipeline.run(**Function, Target, Analyses);
Context.expect(Run.has_value(), "RV64GC critical-edge PHI elimination must succeed");
@@ -350,6 +406,7 @@ int main() {
if (!Target)
return Context.result();
testBehaviorAndCopyLegality(Context, *Target);
+ testCompressedConditionalBranchBehavior(Context, *Target);
testRV64GCCriticalEdge(Context, *Target);
return Context.result();
}