diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-24 18:27:25 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-24 18:27:25 +0800 |
| commit | f430936038432e90b2d70e08ac51620931651450 (patch) | |
| tree | 741d8f94e2315180a6b0dd3fdbe8b25ab298548a | |
| parent | 1b4601c1ac91a06091610e969e70bcd1cb014cc5 (diff) | |
| download | rcc-project-f430936038432e90b2d70e08ac51620931651450.tar.gz rcc-project-f430936038432e90b2d70e08ac51620931651450.tar.xz | |
[RISCV] Match LLVM compressed stack frame lowering
| -rw-r--r-- | backend/include/rcc/Target/RISCV/RISCVSubtarget.h | 3 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCV.h | 3 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVFrameLowering.cpp | 171 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp | 2 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVSubtarget.cpp | 5 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVFrameLoweringTest.cpp | 11 | ||||
| -rw-r--r-- | backend/unittests/Target/RISCVLateCodeGenTest.cpp | 11 |
7 files changed, 102 insertions, 104 deletions
diff --git a/backend/include/rcc/Target/RISCV/RISCVSubtarget.h b/backend/include/rcc/Target/RISCV/RISCVSubtarget.h index 52b99af..208f758 100644 --- a/backend/include/rcc/Target/RISCV/RISCVSubtarget.h +++ b/backend/include/rcc/Target/RISCV/RISCVSubtarget.h @@ -17,6 +17,7 @@ namespace rcc { class InstructionSelector; class LegalizerInfo; class TargetCallLowering; +class TargetFrameLowering; class TargetSchedulingHooks; class TargetSchedulingModel; @@ -131,6 +132,7 @@ public: [[nodiscard]] InstructionSelector *getInstructionSelector() const; [[nodiscard]] const LegalizerInfo *getLegalizerInfo() const; [[nodiscard]] const RISCVRegisterBankInfo *getRegBankInfo() const; + [[nodiscard]] const TargetFrameLowering &frameLowering() const noexcept; [[nodiscard]] const TargetSchedulingModel &schedulingModel() const noexcept; private: @@ -138,6 +140,7 @@ private: RelocationModel Relocation; CodeModel Code; RISCVABI ABI; + std::unique_ptr<TargetFrameLowering> FrameLoweringInfo; mutable std::unique_ptr<TargetCallLowering> CallLoweringInfo; mutable std::unique_ptr<InstructionSelector> InstSelector; mutable std::unique_ptr<LegalizerInfo> Legalizer; diff --git a/backend/lib/Target/RISCV/RISCV.h b/backend/lib/Target/RISCV/RISCV.h index 0a4038b..fea5010 100644 --- a/backend/lib/Target/RISCV/RISCV.h +++ b/backend/lib/Target/RISCV/RISCV.h @@ -26,7 +26,8 @@ class RISCVSubtarget; createRISCVInstructionSelector(const RISCVSubtarget &Subtarget, const RISCVRegisterBankInfo &RegisterBanks); [[nodiscard]] const TargetRegisterAllocationInfo ®isterAllocationInfo() noexcept; -[[nodiscard]] const TargetFrameLowering &frameLowering(RISCVABI ABI = RISCVABI::LP64D) noexcept; +[[nodiscard]] std::unique_ptr<TargetFrameLowering> +createFrameLowering(const RISCVSubtarget &Subtarget); [[nodiscard]] std::unique_ptr<TargetSchedulingHooks> createSchedulingHooks(const RISCVSubtargetFeatures &Features); [[nodiscard]] Expected<TargetSchedulingModel> diff --git a/backend/lib/Target/RISCV/RISCVFrameLowering.cpp b/backend/lib/Target/RISCV/RISCVFrameLowering.cpp index ec1c775..55447c9 100644 --- a/backend/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/backend/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -27,6 +27,7 @@ #include <iostream> #include <iterator> #include <limits> +#include <memory> #include <optional> #include <ranges> #include <span> @@ -523,7 +524,9 @@ createResolvedStackMemory(MachineFunction &Function, MemoryAccessFlag Access, st return std::unexpected(Low.error()); if (auto Result = Low->addDef(Register::fromPhysical(Destination)); !Result) return std::unexpected(Result.error()); - if (auto Result = Low->addUse(Register::fromPhysical(Destination)); !Result) + RegisterOperandFlags Killed; + Killed.set(RegisterOperandFlag::Kill); + if (auto Result = Low->addUse(Register::fromPhysical(Destination), Killed); !Result) return std::unexpected(Result.error()); if (auto Result = Low->addImmediate(Lower); !Result) return std::unexpected(Result.error()); @@ -568,7 +571,9 @@ createResolvedStackMemory(MachineFunction &Function, MemoryAccessFlag Access, st return std::unexpected(Shift.error()); if (auto Result = Shift->addDef(Register::fromPhysical(Destination)); !Result) return std::unexpected(Result.error()); - if (auto Result = Shift->addUse(Register::fromPhysical(Destination)); !Result) + RegisterOperandFlags Killed; + Killed.set(RegisterOperandFlag::Kill); + if (auto Result = Shift->addUse(Register::fromPhysical(Destination), Killed); !Result) return std::unexpected(Result.error()); if (auto Result = Shift->addImmediate(12); !Result) return std::unexpected(Result.error()); @@ -582,7 +587,7 @@ createResolvedStackMemory(MachineFunction &Function, MemoryAccessFlag Access, st return std::unexpected(Add.error()); if (auto Result = Add->addDef(Register::fromPhysical(Destination)); !Result) return std::unexpected(Result.error()); - if (auto Result = Add->addUse(Register::fromPhysical(Destination)); !Result) + if (auto Result = Add->addUse(Register::fromPhysical(Destination), Killed); !Result) return std::unexpected(Result.error()); if (auto Result = Add->addImmediate(Digits[Reverse - 1U]); !Result) return std::unexpected(Result.error()); @@ -816,9 +821,6 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati std::vector<const StackObject *> Specials; std::vector<const StackObject *> Locals; std::vector<const StackObject *> Emergencies; - std::vector<const StackObject *> PreallocatedLocals; - std::uint64_t LocalBlobSize = Frame.state().LocalFrameSize; - std::uint64_t LocalBlobAlignment = 1; std::uint64_t MaximumAlignment = requiredStackAlignment(Function); for (const StackObject &Object : Frame.objects()) { if (Object.isTombstone() || Object.description()->IsDead) @@ -831,27 +833,21 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati MaximumAlignment = std::max(MaximumAlignment, Description.Align.bytes()); if (Object.isVariableSized()) continue; - if (Description.LocalOffset) { + if (Description.LocalOffset && isOutgoingCallObject(Description)) { if (*Description.LocalOffset < 0 || static_cast<std::uint64_t>(*Description.LocalOffset) % Description.Align.bytes() != 0) { return makeUnexpected(ErrorCode::FrameLayoutFailed, - "RISC-V local stack object has an invalid offset"); + "RISC-V outgoing stack object has an invalid offset"); } const std::uint64_t Offset = static_cast<std::uint64_t>(*Description.LocalOffset); if (Description.Size.value_or(0) > std::numeric_limits<std::uint64_t>::max() - Offset) { return makeUnexpected(ErrorCode::FrameLayoutFailed, - "RISC-V local stack object range overflows"); + "RISC-V outgoing stack object range overflows"); } const std::uint64_t End = Offset + Description.Size.value_or(0); - if (isOutgoingCallObject(Description)) { - if (!Frame.maxCallFrameSize() || End > *Frame.maxCallFrameSize()) { - return makeUnexpected(ErrorCode::FrameLayoutFailed, - "RISC-V outgoing stack object exceeds the call frame"); - } - } else { - LocalBlobSize = std::max(LocalBlobSize, End); - LocalBlobAlignment = std::max(LocalBlobAlignment, Description.Align.bytes()); - PreallocatedLocals.push_back(&Object); + if (!Frame.maxCallFrameSize() || End > *Frame.maxCallFrameSize()) { + return makeUnexpected(ErrorCode::FrameLayoutFailed, + "RISC-V outgoing stack object exceeds the call frame"); } continue; } @@ -877,9 +873,6 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati std::ranges::sort(Locals, Order); std::ranges::sort(Specials, Order); std::ranges::sort(Emergencies, Order); - std::ranges::sort(PreallocatedLocals, [](const StackObject *Left, const StackObject *Right) { - return Left->index().value() < Right->index().value(); - }); const auto Place = [&](std::span<const StackObject *const> Objects) -> Expected<void> { for (const StackObject *Object : Objects) { @@ -903,38 +896,6 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati return {}; }; - const auto PlacePreallocated = [&]() -> Expected<void> { - if (LocalBlobSize == 0) - return {}; - auto Aligned = alignTo(Cursor, LocalBlobAlignment); - if (!Aligned) - return std::unexpected(Aligned.error()); - const std::uint64_t BlobStart = *Aligned; - for (const StackObject *Object : PreallocatedLocals) { - const std::uint64_t LocalOffset = - static_cast<std::uint64_t>(*Object->description()->LocalOffset); - const std::uint64_t Size = Object->description()->Size.value_or(0); - if (BlobStart > std::numeric_limits<std::uint64_t>::max() - LocalOffset || - BlobStart + LocalOffset > std::numeric_limits<std::uint64_t>::max() - Size) { - return makeUnexpected(ErrorCode::FrameLayoutFailed, - "RISC-V local frame offset overflows uint64"); - } - const std::uint64_t End = BlobStart + LocalOffset + Size; - if (End > static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max())) { - return makeUnexpected(ErrorCode::FrameLayoutFailed, - "RISC-V local frame offset exceeds int64"); - } - auto Set = Frame.setObjectOffset(Object->index(), -static_cast<std::int64_t>(End)); - if (!Set) - return std::unexpected(Set.error()); - } - if (LocalBlobSize > std::numeric_limits<std::uint64_t>::max() - BlobStart) - return makeUnexpected(ErrorCode::FrameLayoutFailed, - "RISC-V local frame size overflows uint64"); - Cursor = BlobStart + LocalBlobSize; - return {}; - }; - auto PlacedSpecials = Place(Specials); if (!PlacedSpecials) return std::unexpected(PlacedSpecials.error()); @@ -948,9 +909,6 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati auto PlacedLocals = Place(Locals); if (!PlacedLocals) return std::unexpected(PlacedLocals.error()); - auto PlacedPreallocated = PlacePreallocated(); - if (!PlacedPreallocated) - return std::unexpected(PlacedPreallocated.error()); if (!PlaceEmergenciesBeforeLocals) { auto PlacedEmergencies = Place(Emergencies); if (!PlacedEmergencies) @@ -967,15 +925,6 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati return std::unexpected(Set.error()); } } - if (LocalBlobSize > std::numeric_limits<std::uint32_t>::max()) { - return makeUnexpected(ErrorCode::FrameLayoutFailed, - "RISC-V local frame blob exceeds MIR limits"); - } - MachineFrameState State = Frame.state(); - State.LocalFrameSize = static_cast<std::uint32_t>(LocalBlobSize); - auto UpdatedState = Frame.setState(std::move(State)); - if (!UpdatedState) - return std::unexpected(UpdatedState.error()); if (CallFrame > std::numeric_limits<std::uint64_t>::max() - Cursor) return makeUnexpected(ErrorCode::FrameLayoutFailed, "RISC-V call frame size overflows uint64"); Cursor += CallFrame; @@ -1015,19 +964,34 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati return *FinalSize; } -[[nodiscard]] std::uint64_t firstSPAdjustAmount(const MachineFunction &Function) noexcept { +[[nodiscard]] std::uint64_t firstSPAdjustAmount(const MachineFunction &Function, + const RISCVSubtargetFeatures &Features) noexcept { const std::uint64_t StackSize = Function.frameInfo().state().StackSize; if (StackSize <= static_cast<std::uint64_t>(MaxSigned12) || Function.records().calleeSavedRegisters().empty()) { return 0; } + if (Features.has(RISCVExtension::C)) { + const auto CanCompress = [StackSize](std::uint64_t CompressLength) { + return StackSize <= 2047U + CompressLength || + (StackSize > 4096U - StackAlignmentBytes && StackSize <= 4094U + CompressLength) || + StackSize > 6144U - StackAlignmentBytes; + }; + constexpr std::uint64_t AddImmediate16SPCompressLength = 496; + if (CanCompress(AddImmediate16SPCompressLength)) + return AddImmediate16SPCompressLength; + constexpr std::uint64_t RV64StackCompressLength = 512; + if (CanCompress(RV64StackCompressLength)) + return RV64StackCompressLength; + } return 2048U - StackAlignmentBytes; } [[nodiscard]] Expected<std::int64_t> objectReferenceOffset(const MachineFunction &Function, const MachineInstr &Instruction, const StackObjectDesc &Object, - std::int64_t OperandOffset) { + std::int64_t OperandOffset, + const RISCVSubtargetFeatures &Features) { if (!Object.Offset) return makeUnexpected(ErrorCode::VerificationError, "RISC-V FrameIndex references an object without a final offset"); @@ -1036,7 +1000,7 @@ emitAddImmediateAdjustment(MachineIRBuilder &Builder, PhysicalRegister Destinati if (Object.LocalOffset && isOutgoingCallObject(Object)) BaseOffset = *Object.LocalOffset; else if (Object.Kind == StackObjectKind::CalleeSaved) { - const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function); + const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function, Features); const std::uint64_t Adjustment = FirstAdjustment == 0 ? Function.frameInfo().state().StackSize : FirstAdjustment; if (Adjustment > static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max())) { @@ -1257,12 +1221,12 @@ calleeSaveOperations(MachineBasicBlock &Block, const MachineFunction &Function, class RISCVFrameLowering final : public TargetFrameLowering { public: - explicit RISCVFrameLowering(RISCVABI ABI) noexcept : ABI(ABI) {} + explicit RISCVFrameLowering(const RISCVSubtarget &Subtarget) noexcept : Subtarget(Subtarget) {} [[nodiscard]] bool isCalleeSavedRegister(PhysicalRegister Reg, const MachineFunction &, const TargetDescription &Target) const noexcept override { - return std::ranges::any_of(saveOrder(ABI), [&](PhysicalRegisterID ID) { + return std::ranges::any_of(saveOrder(Subtarget.targetABI()), [&](PhysicalRegisterID ID) { const auto Candidate = physicalRegister(ID); return Candidate && Target.registers().regsOverlap(Reg, *Candidate); }); @@ -1321,10 +1285,11 @@ public: if (!FrameRegisters) return std::unexpected(FrameRegisters.error()); - auto SavedRegisters = modifiedCalleeSavedRegisters(Function, Target, ABI); + auto SavedRegisters = modifiedCalleeSavedRegisters(Function, Target, Subtarget.targetABI()); if (!SavedRegisters) return std::unexpected(SavedRegisters.error()); - auto ExistingSlots = validateCalleeSaveObjects(Function, *SavedRegisters, ABI); + auto ExistingSlots = + validateCalleeSaveObjects(Function, *SavedRegisters, Subtarget.targetABI()); if (!ExistingSlots) return std::unexpected(ExistingSlots.error()); auto Align8 = Alignment::create(8); @@ -1342,7 +1307,8 @@ public: if (!Created) return std::unexpected(Created.error()); } - auto CompleteSlots = validateCalleeSaveObjects(Function, *SavedRegisters, ABI); + auto CompleteSlots = + validateCalleeSaveObjects(Function, *SavedRegisters, Subtarget.targetABI()); if (!CompleteSlots) return std::unexpected(CompleteSlots.error()); @@ -1386,8 +1352,8 @@ public: if (Object == nullptr || Object->description()->IsDead) return makeUnexpected(ErrorCode::VerificationError, "RISC-V frame instruction references an invalid object"); - auto Offset = - objectReferenceOffset(Function, *Instruction, *Object->description(), Extra); + auto Offset = objectReferenceOffset(Function, *Instruction, *Object->description(), Extra, + Subtarget.features()); if (!Offset) return std::unexpected(Offset.error()); NeedsEmergency |= !fitsSigned12(*Offset); @@ -1652,7 +1618,7 @@ public: } PhysicalRegister Temporary = *DefaultTemporary; std::optional<ScavengedRegister> Scratch; - const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function); + const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function, Subtarget.features()); const std::uint64_t InitialAllocation = FirstAdjustment == 0 ? StackSize : FirstAdjustment; const std::uint64_t SecondAdjustment = StackSize - InitialAllocation; const std::int64_t InitialAmount = -static_cast<std::int64_t>(InitialAllocation); @@ -1700,7 +1666,8 @@ public: MachineInstrFlag::FrameSetup); if (!Constant) return std::unexpected(Constant.error()); - auto Adjust = emitRegisterSub(Builder, *SP, *SP, Temporary, MachineInstrFlag::FrameSetup); + auto Adjust = + emitRegisterSub(Builder, *SP, *SP, Temporary, MachineInstrFlag::FrameSetup, true); if (!Adjust) return std::unexpected(Adjust.error()); } @@ -1778,7 +1745,7 @@ public: if (!Constant) return std::unexpected(Constant.error()); auto Adjust = - emitRegisterSub(AfterSaves, *SP, *SP, Temporary, MachineInstrFlag::FrameSetup); + emitRegisterSub(AfterSaves, *SP, *SP, Temporary, MachineInstrFlag::FrameSetup, true); if (!Adjust) return std::unexpected(Adjust.error()); } @@ -1844,7 +1811,8 @@ public: if (!Set) return std::unexpected(Set.error()); if (!canEmitAddImmediateAdjustment(FramePointerAdjustment, StackAlignmentBytes)) { - Set = emitRegisterAdd(AfterSaves, *FP, *SP, Temporary, MachineInstrFlag::FrameSetup); + Set = + emitRegisterAdd(AfterSaves, *FP, *SP, Temporary, MachineInstrFlag::FrameSetup, true); if (!Set) return std::unexpected(Set.error()); } @@ -1866,10 +1834,16 @@ public: if (!Constant) return std::unexpected(Constant.error()); auto Adjust = - emitRegisterSub(AfterSaves, *SP, *SP, Temporary, MachineInstrFlag::FrameSetup); + emitRegisterSub(AfterSaves, *SP, *SP, Temporary, MachineInstrFlag::FrameSetup, true); if (!Adjust) return std::unexpected(Adjust.error()); } + if (!requiresFramePointer(Function)) { + auto CFA = emitDefCFAOffset(AfterSaves, static_cast<std::int64_t>(StackSize), + MachineInstrFlag::FrameSetup); + if (!CFA) + return std::unexpected(CFA.error()); + } } } if (Saves.empty() && requiresFramePointer(Function)) { @@ -1883,7 +1857,7 @@ public: if (!Set) return std::unexpected(Set.error()); if (!canEmitAddImmediateAdjustment(FramePointerAdjustment, StackAlignmentBytes)) { - Set = emitRegisterAdd(Builder, *FP, *SP, Temporary, MachineInstrFlag::FrameSetup); + Set = emitRegisterAdd(Builder, *FP, *SP, Temporary, MachineInstrFlag::FrameSetup, true); if (!Set) return std::unexpected(Set.error()); } @@ -1952,7 +1926,7 @@ public: } if (Realign) { - const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function); + const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function, Subtarget.features()); if (FirstAdjustment > static_cast<std::uint64_t>(MaxSigned12)) { return makeUnexpected(ErrorCode::FrameLayoutFailed, "RISC-V first epilogue adjustment exceeds signed 12 bits"); @@ -1981,8 +1955,8 @@ public: if (!Adjust) return std::unexpected(Adjust.error()); } - } else if (HasFP) { - const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function); + } else if (HasFP || firstSPAdjustAmount(Function, Subtarget.features()) != 0) { + const std::uint64_t FirstAdjustment = firstSPAdjustAmount(Function, Subtarget.features()); const std::uint64_t RestoreAreaSize = FirstAdjustment == 0 ? StackSize : FirstAdjustment; const std::uint64_t SecondAdjustment = StackSize - RestoreAreaSize; MachineInstr *FirstRestore = Restores.empty() ? &Terminator : Restores.front().Instruction; @@ -2003,14 +1977,21 @@ public: if (!Point) return std::unexpected(Point.error()); if (SecondAdjustment == 0) { + if (!HasFP) { + return makeUnexpected(ErrorCode::InternalError, + "RISC-V split epilogue has no second adjustment"); + } auto RestoreSP = emitAddImmediateAdjustment( Teardown, *SP, *FP, -static_cast<std::int64_t>(RestoreAreaSize), StackAlignmentBytes, MachineInstrFlag::FrameDestroy); if (!RestoreSP) return std::unexpected(RestoreSP.error()); } - auto CFA = emitDefCFI(Teardown, Target, *SP, static_cast<std::int64_t>(RestoreAreaSize), - MachineInstrFlag::FrameDestroy); + auto CFA = HasFP + ? emitDefCFI(Teardown, Target, *SP, static_cast<std::int64_t>(RestoreAreaSize), + MachineInstrFlag::FrameDestroy) + : emitDefCFAOffset(Teardown, static_cast<std::int64_t>(RestoreAreaSize), + MachineInstrFlag::FrameDestroy); if (!CFA) return std::unexpected(CFA.error()); if (RestoreAreaSize != 0) { @@ -2058,7 +2039,7 @@ public: if (!Constant) return std::unexpected(Constant.error()); auto Adjust = - emitRegisterAdd(Teardown, *SP, *SP, Scratch->Reg, MachineInstrFlag::FrameDestroy); + emitRegisterAdd(Teardown, *SP, *SP, Scratch->Reg, MachineInstrFlag::FrameDestroy, true); if (!Adjust) return std::unexpected(Adjust.error()); } @@ -2079,8 +2060,8 @@ public: if (Object->isVariableSized()) return makeUnexpected(ErrorCode::Unsupported, "RISC-V variable-sized object cannot be addressed by FrameIndex"); - auto Offset = - objectReferenceOffset(Function, Instruction, *Object->description(), OperandOffset); + auto Offset = objectReferenceOffset(Function, Instruction, *Object->description(), + OperandOffset, Subtarget.features()); if (!Offset) return std::unexpected(Offset.error()); const StackObjectDesc &Description = *Object->description(); @@ -2179,8 +2160,8 @@ public: auto Constant = emitConstant(Builder, Scratch->Reg, *Zero, AddressOffset, std::nullopt); if (!Constant) return std::unexpected(Constant.error()); - auto Address = - emitRegisterAdd(Builder, Scratch->Reg, Reference->BaseRegister, Scratch->Reg, std::nullopt); + auto Address = emitRegisterAdd(Builder, Scratch->Reg, Reference->BaseRegister, Scratch->Reg, + std::nullopt, true); if (!Address) return std::unexpected(Address.error()); auto Base = replaceWithRegister(Instruction, OperandIndex, Scratch->Reg); @@ -2272,15 +2253,13 @@ private: return emitScratchAccess(Builder, Scratch, Reference, Restore); } - RISCVABI ABI; + const RISCVSubtarget &Subtarget; }; } // namespace -const TargetFrameLowering &frameLowering(RISCVABI ABI) noexcept { - static const RISCVFrameLowering LP64Info(RISCVABI::LP64); - static const RISCVFrameLowering LP64DInfo(RISCVABI::LP64D); - return ABI == RISCVABI::LP64D ? LP64DInfo : LP64Info; +std::unique_ptr<TargetFrameLowering> createFrameLowering(const RISCVSubtarget &Subtarget) { + return std::make_unique<RISCVFrameLowering>(Subtarget); } } // namespace rcc::riscv diff --git a/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp b/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp index 45c557a..e81ee54 100644 --- a/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp +++ b/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp @@ -12,7 +12,7 @@ MachineOptimizationPipelineTargetInfo optimizationPipelineInfo(const RISCVSubtar .InstrInfo = instrInfo(), .Combiner = machineCombinerInfo(), .MemoryFolding = memoryFoldingInfo(), - .FrameLowering = frameLowering(Subtarget.targetABI()), + .FrameLowering = Subtarget.frameLowering(), .PseudoExpansion = pseudoExpansionInfo(), .SchedulingModel = Subtarget.schedulingModel(), .SchedulerOptions = {.EmitDebugOutput = EmitSchedulerDebugOutput}, diff --git a/backend/lib/Target/RISCV/RISCVSubtarget.cpp b/backend/lib/Target/RISCV/RISCVSubtarget.cpp index 499219b..314aeb7 100644 --- a/backend/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/backend/lib/Target/RISCV/RISCVSubtarget.cpp @@ -197,6 +197,7 @@ RISCVSubtarget::RISCVSubtarget(RISCVSubtargetFeatures Features, RelocationModel CodeModel Code, RISCVABI ABI) : Features(Features), Relocation(Relocation), Code(Code), ABI(ABI), SchedulingHooks(createSchedulingHooks(Features)) { + FrameLoweringInfo = createFrameLowering(*this); auto Model = createSchedulingModel(*SchedulingHooks); if (!Model) std::abort(); @@ -229,6 +230,10 @@ const RISCVRegisterBankInfo *RISCVSubtarget::getRegBankInfo() const { return RegBankInfo.get(); } +const TargetFrameLowering &RISCVSubtarget::frameLowering() const noexcept { + return *FrameLoweringInfo; +} + const TargetSchedulingModel &RISCVSubtarget::schedulingModel() const noexcept { return *SchedulingModel; } diff --git a/backend/unittests/Target/RISCVFrameLoweringTest.cpp b/backend/unittests/Target/RISCVFrameLoweringTest.cpp index ec4bfa3..9b8e25c 100644 --- a/backend/unittests/Target/RISCVFrameLoweringTest.cpp +++ b/backend/unittests/Target/RISCVFrameLoweringTest.cpp @@ -57,6 +57,11 @@ struct FunctionFixture final { rcc::MachineBasicBlock *Block = nullptr; }; +[[nodiscard]] const rcc::riscv::RISCVSubtarget &subtarget() { + static const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc()); + return Subtarget; +} + class ObservingFrameLowering final : public rcc::TargetFrameLowering { public: explicit ObservingFrameLowering(const rcc::TargetFrameLowering &Delegate, @@ -227,7 +232,7 @@ runFrameLoweringWith(rcc::MachineFunction &Function, const rcc::TargetDescriptio [[nodiscard]] rcc::Expected<void> runFrameLowering(rcc::MachineFunction &Function, const rcc::TargetDescription &Target) { - return runFrameLoweringWith(Function, Target, rcc::riscv::frameLowering()); + return runFrameLoweringWith(Function, Target, subtarget().frameLowering()); } [[nodiscard]] rcc::Expected<rcc::FrameIndex> @@ -1173,7 +1178,7 @@ void testPEIOrderingAndPostconditions(TestContext &Context, const rcc::TargetDes !buildReturn(*Ordered->Function, Target, *Ordered->Block)) { return; } - ObservingFrameLowering Observer(rcc::riscv::frameLowering()); + ObservingFrameLowering Observer(subtarget().frameLowering()); auto OrderedResult = runFrameLoweringWith(*Ordered->Function, Target, Observer); Context.expect( OrderedResult && Observer.PrepareSawUnfrozen && Observer.InsertSawUnfrozen && @@ -1197,7 +1202,7 @@ void testPEIOrderingAndPostconditions(TestContext &Context, const rcc::TargetDes return; } const std::size_t OriginalInstructionCount = InvalidPostcondition->Block->instructionCount(); - ObservingFrameLowering Broken(rcc::riscv::frameLowering(), true); + ObservingFrameLowering Broken(subtarget().frameLowering(), true); auto Rejected = runFrameLoweringWith(*InvalidPostcondition->Function, Target, Broken); Context.expect( !Rejected && !InvalidPostcondition->Function->frameInfo().isFrozen() && diff --git a/backend/unittests/Target/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp index 8160370..d78d4c4 100644 --- a/backend/unittests/Target/RISCVLateCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVLateCodeGenTest.cpp @@ -66,6 +66,11 @@ constexpr rcc::Opcode GrowingLatePseudoOpcode = rcc::Opcode::fromValue(10'000); constexpr rcc::Opcode LateExpansionRealOpcode = rcc::Opcode::fromValue(10'001); constexpr rcc::Opcode ShrinkingLatePseudoOpcode = rcc::Opcode::fromValue(10'002); +[[nodiscard]] const rcc::riscv::RISCVSubtarget &subtarget() { + static const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc()); + return Subtarget; +} + class GrowingLatePseudoInfo final : public rcc::TargetPseudoExpansionInfo { public: [[nodiscard]] rcc::Expected<bool> @@ -741,7 +746,7 @@ void testShrinkWrappedFrameRegion(TestContext &Context, const rcc::TargetDescrip Context.expect(rcc::rebuildMachineLiveness(*Function, Target).has_value(), "shrink-wrapping fixture liveness must be rebuilt"); rcc::MachineFunctionAnalysisManager Analyses; - rcc::MachineShrinkWrappingPass Shrink{rcc::riscv::frameLowering()}; + rcc::MachineShrinkWrappingPass Shrink{subtarget().frameLowering()}; auto Shrunk = Shrink.run(*Function, Target, Analyses); Context.expect(Shrunk && Shrunk->Changed && Function->frameInfo().state().SavePoints.size() == 1 && @@ -755,7 +760,7 @@ void testShrinkWrappedFrameRegion(TestContext &Context, const rcc::TargetDescrip rcc::MachineFunctionPassManager FramePipeline; Context.expect(FramePipeline .addPass(std::make_unique<rcc::PrologueEpilogueInsertionPass>( - rcc::riscv::frameLowering())) + subtarget().frameLowering())) .has_value(), "shrink-wrapped PEI pass must register"); auto Lowered = FramePipeline.run(*Function, Target, Analyses); @@ -1058,7 +1063,7 @@ void testPostRAPseudoExpansionAndFinalization(TestContext &Context, void testCanonicalOptimizationPipelines(TestContext &Context, const rcc::TargetDescription &Target) { const rcc::MachineOptimizationPipelineTargetInfo TargetInfo = - rcc::riscv::optimizationPipelineInfo(); + rcc::riscv::optimizationPipelineInfo(subtarget()); rcc::MachineFunctionPassManager SelectedPipeline; rcc::MachineFunctionPassManager PreRAPipeline; Context.expect(rcc::addSelectedSSAOptimizationPipeline(SelectedPipeline, TargetInfo) && |
