diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 23:57:49 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 23:57:49 +0800 |
| commit | 2872e39af3aa78b7a54b74d104f133aa715d01cb (patch) | |
| tree | 168061fb22943a82efbe53c135d0f920a5e1e839 /backend/unittests | |
| parent | e7586a115e9ff6ee303c2546cb0eab48bde6dfbb (diff) | |
| download | rcc-project-2872e39af3aa78b7a54b74d104f133aa715d01cb.tar.gz rcc-project-2872e39af3aa78b7a54b74d104f133aa715d01cb.tar.xz | |
[CodeGen] Treat reserved registers as always live
Diffstat (limited to 'backend/unittests')
| -rw-r--r-- | backend/unittests/CodeGen/MachineLivenessTest.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/backend/unittests/CodeGen/MachineLivenessTest.cpp b/backend/unittests/CodeGen/MachineLivenessTest.cpp index 3f7621d..84a247f 100644 --- a/backend/unittests/CodeGen/MachineLivenessTest.cpp +++ b/backend/unittests/CodeGen/MachineLivenessTest.cpp @@ -856,6 +856,46 @@ void testRISCVLiveness(TestContext &Context) { "production RV64GC register units must participate in LiveIntervals"); } +void testRISCVReservedRegisterLiveness(TestContext &Context) { + auto Target = rcc::riscv::createTargetDescription(); + auto Fixture = createFunction("riscv-reserved-liveness", 10, 1); + if (!Target || !Fixture) { + Context.expect(false, "RV64GC reserved-register liveness fixture creation must succeed"); + return; + } + auto X0 = rcc::riscv::physicalRegister(rcc::riscv::PhysicalRegisterID::X0); + auto X5 = rcc::riscv::physicalRegister(rcc::riscv::PhysicalRegisterID::X5); + if (!X0 || !X5) { + Context.expect(false, "RV64GC reserved-register fixture registers must resolve"); + return; + } + + rcc::MachineIRBuilder Builder(*Fixture->Function, *Target); + auto Point = Builder.setInsertPoint(*Fixture->Blocks[0]); + auto Pending = Point ? Builder.buildInstr(rcc::Opcode::fromValue( + static_cast<std::uint32_t>(rcc::riscv::InstructionOpcode::ADDI))) + : rcc::Expected<rcc::MachineInstrBuilder>{std::unexpected(Point.error())}; + auto Def = Pending ? Pending->addDef(rcc::Register::fromPhysical(*X5)) + : rcc::Expected<void>{std::unexpected(Pending.error())}; + auto Use = Def ? Pending->addUse(rcc::Register::fromPhysical(*X0)) + : rcc::Expected<void>{std::unexpected(Def.error())}; + auto Immediate = + Use ? Pending->addImmediate(1) : rcc::Expected<void>{std::unexpected(Use.error())}; + auto Instruction = Immediate + ? Pending->build() + : rcc::Expected<rcc::MachineInstr *>{std::unexpected(Immediate.error())}; + if (!Instruction) { + 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); + 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"); +} + } // namespace int main() { @@ -874,5 +914,6 @@ int main() { testFailedRebuildIsAtomic(Context, *Target); testAnalysisRegistrationAndInvalidation(Context, *Target); testRISCVLiveness(Context); + testRISCVReservedRegisterLiveness(Context); return Context.result(); } |
