aboutsummaryrefslogtreecommitdiff
path: root/backend/unittests/CodeGen/MachineLivenessTest.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-12 01:22:08 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-12 01:22:08 +0800
commit0e43f63ac7fa5e28497760a0dfec2fe20557bce0 (patch)
treeb3279773b3f84dda8853be185a5af18f6938bddd /backend/unittests/CodeGen/MachineLivenessTest.cpp
parent785805863cbee537ba1e963ff177265171801aeb (diff)
downloadrcc-project-0e43f63ac7fa5e28497760a0dfec2fe20557bce0.tar.gz
rcc-project-0e43f63ac7fa5e28497760a0dfec2fe20557bce0.tar.xz
[CodeGen] Track reserved register defs precisely
Diffstat (limited to 'backend/unittests/CodeGen/MachineLivenessTest.cpp')
-rw-r--r--backend/unittests/CodeGen/MachineLivenessTest.cpp28
1 files changed, 25 insertions, 3 deletions
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