diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-12 01:22:08 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-12 01:22:08 +0800 |
| commit | 0e43f63ac7fa5e28497760a0dfec2fe20557bce0 (patch) | |
| tree | b3279773b3f84dda8853be185a5af18f6938bddd /backend | |
| parent | 785805863cbee537ba1e963ff177265171801aeb (diff) | |
| download | rcc-project-0e43f63ac7fa5e28497760a0dfec2fe20557bce0.tar.gz rcc-project-0e43f63ac7fa5e28497760a0dfec2fe20557bce0.tar.xz | |
[CodeGen] Track reserved register defs precisely
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/lib/CodeGen/MachineLiveness.cpp | 15 | ||||
| -rw-r--r-- | backend/lib/CodeGen/PostRAScheduler.cpp | 2 | ||||
| -rw-r--r-- | backend/unittests/CodeGen/MachineLivenessTest.cpp | 28 |
3 files changed, 33 insertions, 12 deletions
diff --git a/backend/lib/CodeGen/MachineLiveness.cpp b/backend/lib/CodeGen/MachineLiveness.cpp index 528a675..7984e7d 100644 --- a/backend/lib/CodeGen/MachineLiveness.cpp +++ b/backend/lib/CodeGen/MachineLiveness.cpp @@ -846,11 +846,10 @@ struct LivenessRebuildPlan final { std::vector<OperandFlagPlan> Operands; }; -[[nodiscard]] Expected<bool> liveSetIntersects(const MachineOperand &Operand, - const RegisterLaneSet &Virtual, - const RegisterUnitLaneSet &Physical, - const MachineFunction &Function, - const TargetDescription &Target) { +[[nodiscard]] Expected<bool> +liveSetIntersects(const MachineOperand &Operand, const RegisterLaneSet &Virtual, + const RegisterUnitLaneSet &Physical, const MachineFunction &Function, + const TargetDescription &Target, bool TreatReservedAsLive) { const Register *Reg = Operand.getIf<Register>(); if (Reg == nullptr || Reg->isNoRegister()) return false; @@ -860,7 +859,7 @@ struct LivenessRebuildPlan final { return std::unexpected(Lanes.error()); return Virtual.intersects(*Reg, *Lanes); } - if (isReservedPhysicalRegister(*Reg, Function, Target)) + if (TreatReservedAsLive && isReservedPhysicalRegister(*Reg, Function, Target)) return true; auto Units = physicalOperandUnits(Operand, Target); if (!Units) @@ -947,7 +946,7 @@ buildLivenessRebuildPlan(const MachineFunction &Function, const TargetDescriptio const MachineOperand *Operand = Instruction->operandAt(Index); if (Operand == nullptr || !Operand->isRegister() || !Operand->isDef()) continue; - auto IsLive = liveSetIntersects(*Operand, Virtual, Physical, Function, Target); + auto IsLive = liveSetIntersects(*Operand, Virtual, Physical, Function, Target, false); if (!IsLive) return std::unexpected(IsLive.error()); RegisterOperandFlags Flags = Operand->registerFlags(); @@ -1003,7 +1002,7 @@ buildLivenessRebuildPlan(const MachineFunction &Function, const TargetDescriptio !Operand->registerValue()->isNoRegister(); bool IsKill = false; if (IsSemanticUse) { - auto IsLive = liveSetIntersects(*Operand, Virtual, Physical, Function, Target); + auto IsLive = liveSetIntersects(*Operand, Virtual, Physical, Function, Target, true); if (!IsLive) return std::unexpected(IsLive.error()); IsKill = !*IsLive; diff --git a/backend/lib/CodeGen/PostRAScheduler.cpp b/backend/lib/CodeGen/PostRAScheduler.cpp index 204f05e..6a91239 100644 --- a/backend/lib/CodeGen/PostRAScheduler.cpp +++ b/backend/lib/CodeGen/PostRAScheduler.cpp @@ -182,7 +182,7 @@ buildBlockLivenessRepairPlan(MachineBasicBlock &Block, const TargetDescription & auto Units = physicalOperandUnits(*Operand, Target); if (!Units) return std::unexpected(Units.error()); - if (!isReservedPhysicalRegister(*Reg, Block.function(), Target) && !intersects(Live, *Units)) + if (!intersects(Live, *Units)) Update.Flags.set(RegisterOperandFlag::Dead); } diff --git a/backend/unittests/CodeGen/MachineLivenessTest.cpp b/backend/unittests/CodeGen/MachineLivenessTest.cpp index 84a247f..cca7629 100644 --- a/backend/unittests/CodeGen/MachineLivenessTest.cpp +++ b/backend/unittests/CodeGen/MachineLivenessTest.cpp @@ -884,16 +884,38 @@ void testRISCVReservedRegisterLiveness(TestContext &Context) { auto Instruction = Immediate ? Pending->build() : rcc::Expected<rcc::MachineInstr *>{std::unexpected(Immediate.error())}; - if (!Instruction) { + auto DeadDef = + Instruction ? Builder.buildInstr(rcc::Opcode::fromValue( + static_cast<std::uint32_t>(rcc::riscv::InstructionOpcode::ADDI))) + : rcc::Expected<rcc::MachineInstrBuilder>{std::unexpected(Instruction.error())}; + auto DeadDefDestination = DeadDef ? DeadDef->addDef(rcc::Register::fromPhysical(*X0)) + : rcc::Expected<void>{std::unexpected(DeadDef.error())}; + auto DeadDefSource = DeadDefDestination + ? DeadDef->addUse(rcc::Register::fromPhysical(*X0)) + : rcc::Expected<void>{std::unexpected(DeadDefDestination.error())}; + auto DeadDefImmediate = DeadDefSource + ? DeadDef->addImmediate(0) + : rcc::Expected<void>{std::unexpected(DeadDefSource.error())}; + auto DeadDefInstruction = + DeadDefImmediate + ? DeadDef->build() + : rcc::Expected<rcc::MachineInstr *>{std::unexpected(DeadDefImmediate.error())}; + if (!Instruction || !DeadDefInstruction) { Context.expect(false, "RV64GC reserved-register liveness instruction must be built"); return; } auto Rebuilt = rcc::rebuildMachineLiveness(*Fixture->Function, *Target); const rcc::MachineOperand *ZeroUse = (*Instruction)->operandAt(1); + const rcc::MachineOperand *ZeroDef = (*DeadDefInstruction)->operandAt(0); + const rcc::MachineOperand *DeadDefZeroUse = (*DeadDefInstruction)->operandAt(1); Context.expect(Rebuilt && Fixture->Blocks[0]->liveIns().empty() && ZeroUse != nullptr && - !ZeroUse->registerFlags().has(rcc::RegisterOperandFlag::Kill), - "reserved registers must remain available without live-ins or kill flags"); + !ZeroUse->registerFlags().has(rcc::RegisterOperandFlag::Kill) && + ZeroDef != nullptr && + ZeroDef->registerFlags().has(rcc::RegisterOperandFlag::Dead) && + DeadDefZeroUse != nullptr && + !DeadDefZeroUse->registerFlags().has(rcc::RegisterOperandFlag::Kill), + "reserved uses must remain available while dead defs retain precise liveness"); } } // namespace |
