From e6cd1347cc2c76babe56842e1b7bd05d68fe9584 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Tue, 11 Aug 2026 23:44:57 +0800 Subject: [RISCV] Model typed floating-point register views --- backend/unittests/Target/RISCVCallLoweringTest.cpp | 11 ++ .../unittests/Target/RISCVFrameLoweringTest.cpp | 6 +- backend/unittests/Target/RISCVLateCodeGenTest.cpp | 3 +- .../Target/RISCVMCEncodingCoverageTest.cpp | 125 ++++++++++++--------- backend/unittests/Target/RISCVMCTest.cpp | 5 +- .../Target/RISCVRegisterAllocationTest.cpp | 8 +- backend/unittests/Target/RISCVTargetTest.cpp | 40 ++++--- 7 files changed, 120 insertions(+), 78 deletions(-) (limited to 'backend/unittests') diff --git a/backend/unittests/Target/RISCVCallLoweringTest.cpp b/backend/unittests/Target/RISCVCallLoweringTest.cpp index c18898f..33723b1 100644 --- a/backend/unittests/Target/RISCVCallLoweringTest.cpp +++ b/backend/unittests/Target/RISCVCallLoweringTest.cpp @@ -226,6 +226,17 @@ void testIntegerAndFloatingAssignments(TestContext &Context) { FloatAssignments[16].StackOffsetBytes == 0, "LP64D floating arguments must fall back from fa0-fa7 to a0-a7 and then stack"); + auto Single = callRequest({abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)}, 1); + Single.Results = {abiValue(floating(rcc::FloatSemantics::IEEESingle), 0)}; + auto SinglePlan = rcc::riscv::callLowering().planCall(Single); + Context.expect(SinglePlan && SinglePlan->argumentAssignments().size() == 1 && + SinglePlan->returnAssignments().size() == 1 && + isLocation(SinglePlan->argumentAssignments()[0], + physical(rcc::riscv::PhysicalRegisterID::F10_F)) && + isLocation(SinglePlan->returnAssignments()[0], + physical(rcc::riscv::PhysicalRegisterID::F10_F)), + "LP64D f32 arguments and returns must use the FPR32 physical-register view"); + auto FloatFragment = abiValue(floating(rcc::FloatSemantics::IEEEDouble), 0); FloatFragment.FragmentCount = 2; FloatFragment.OriginalAlignment = align(16); diff --git a/backend/unittests/Target/RISCVFrameLoweringTest.cpp b/backend/unittests/Target/RISCVFrameLoweringTest.cpp index 0525a6d..6a6cd5b 100644 --- a/backend/unittests/Target/RISCVFrameLoweringTest.cpp +++ b/backend/unittests/Target/RISCVFrameLoweringTest.cpp @@ -592,7 +592,7 @@ void testCalleeSavedRegisters(TestContext &Context, const rcc::TargetDescription !buildAddImmediate(*Fixture->Function, Target, *Fixture->Block, physical(rcc::riscv::PhysicalRegisterID::X9), Zero, 2) || !buildMoveToDouble(*Fixture->Function, Target, *Fixture->Block, - physical(rcc::riscv::PhysicalRegisterID::F8), Zero) || + physical(rcc::riscv::PhysicalRegisterID::F8_D), Zero) || !buildReturn(*Fixture->Function, Target, *Fixture->Block)) { return; } @@ -601,7 +601,7 @@ void testCalleeSavedRegisters(TestContext &Context, const rcc::TargetDescription Context.expect( Lowered && Saved.size() == 3 && Saved[0] == physReg(rcc::riscv::PhysicalRegisterID::X1) && Saved[1] == physReg(rcc::riscv::PhysicalRegisterID::X9) && - Saved[2] == physReg(rcc::riscv::PhysicalRegisterID::F8) && + Saved[2] == physReg(rcc::riscv::PhysicalRegisterID::F8_D) && countOpcode(*Fixture->Function, rcc::riscv::InstructionOpcode::SD) == 2 && countOpcode(*Fixture->Function, rcc::riscv::InstructionOpcode::FSD) == 1 && countOpcode(*Fixture->Function, rcc::riscv::InstructionOpcode::LD) == 2 && @@ -615,7 +615,7 @@ void testCalleeSavedRegisters(TestContext &Context, const rcc::TargetDescription findCalleeSave(*Fixture->Function, physReg(rcc::riscv::PhysicalRegisterID::X1)) != nullptr && findCalleeSave(*Fixture->Function, physReg(rcc::riscv::PhysicalRegisterID::X9)) != nullptr && - findCalleeSave(*Fixture->Function, physReg(rcc::riscv::PhysicalRegisterID::F8)) != + findCalleeSave(*Fixture->Function, physReg(rcc::riscv::PhysicalRegisterID::F8_D)) != nullptr && !hasFrameIndex(*Fixture->Function), "callee-save records, stack objects, and eliminated operands must remain consistent"); diff --git a/backend/unittests/Target/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp index 5069137..e8ac9de 100644 --- a/backend/unittests/Target/RISCVLateCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVLateCodeGenTest.cpp @@ -1122,7 +1122,8 @@ void testPostRAPseudoExpansionAndFinalization(TestContext &Context, return; } auto CrossCopy = Builder.buildInstr(rcc::opcode(rcc::GenericOpcode::COPY)); - if (!CrossCopy || !CrossCopy->addDef(physical(rcc::riscv::PhysicalRegisterID::F10), {}, {}, 16) || + if (!CrossCopy || + !CrossCopy->addDef(physical(rcc::riscv::PhysicalRegisterID::F10_D), {}, {}, 16) || !CrossCopy->addUse(physical(rcc::riscv::PhysicalRegisterID::X10), {}, {}, 16) || !CrossCopy->build()) { Context.expect(false, "post-RA cross-bank copy construction must succeed"); diff --git a/backend/unittests/Target/RISCVMCEncodingCoverageTest.cpp b/backend/unittests/Target/RISCVMCEncodingCoverageTest.cpp index 1e10d24..d66d19d 100644 --- a/backend/unittests/Target/RISCVMCEncodingCoverageTest.cpp +++ b/backend/unittests/Target/RISCVMCEncodingCoverageTest.cpp @@ -27,8 +27,22 @@ namespace { return static_cast(Value) - (std::int64_t{1} << Width); } -void addRegister(rcc::mc::MCInst &Instruction, std::uint32_t Encoding, bool Floating) { - const std::uint32_t ID = Encoding + (Floating ? 33U : 1U); +void addRegister(rcc::mc::MCInst &Instruction, const rcc::InstructionDescriptor &Descriptor, + std::uint32_t Encoding) { + const std::size_t OperandIndex = Instruction.operands().size(); + const rcc::RegisterClassID Class = Descriptor.Operands[OperandIndex].RegClass.value_or( + rcc::RegisterClassID::fromValue(static_cast(rcc::riscv::RegisterClass::GPR))); + const auto IsClass = [Class](rcc::riscv::RegisterClass Candidate) { + return Class.value() == static_cast(Candidate); + }; + std::uint32_t FirstRegister = 1; + if (IsClass(rcc::riscv::RegisterClass::FPR32) || IsClass(rcc::riscv::RegisterClass::FPR32C)) { + FirstRegister = static_cast(rcc::riscv::PhysicalRegisterID::F0_F); + } else if (IsClass(rcc::riscv::RegisterClass::FPR64) || + IsClass(rcc::riscv::RegisterClass::FPR64C)) { + FirstRegister = static_cast(rcc::riscv::PhysicalRegisterID::F0_D); + } + const std::uint32_t ID = Encoding + FirstRegister; Instruction.addOperand(rcc::mc::MCOperand::registerOperand(rcc::mc::MCRegister::fromValue(ID))); } @@ -68,48 +82,48 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, if (Category == rcc::riscv::EncodingCategory::R) { switch (Format) { case RD_RS1_RS2: - addRegister(Result, DestinationEncoding, false); - addRegister(Result, Source1Encoding, false); - addRegister(Result, Source2Encoding, false); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); + addRegister(Result, Descriptor, Source2Encoding); return Result; case FRD_FRS1_FRS2_RM: - addRegister(Result, DestinationEncoding, true); - addRegister(Result, Source1Encoding, true); - addRegister(Result, Source2Encoding, true); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); + addRegister(Result, Descriptor, Source2Encoding); addImmediate(Result, (Encoding >> 12U) & 7U); return Result; case FRD_FRS1_FRS2: - addRegister(Result, DestinationEncoding, true); - addRegister(Result, Source1Encoding, true); - addRegister(Result, Source2Encoding, true); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); + addRegister(Result, Descriptor, Source2Encoding); return Result; case RD_FRS1_FRS2: - addRegister(Result, DestinationEncoding, false); - addRegister(Result, Source1Encoding, true); - addRegister(Result, Source2Encoding, true); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); + addRegister(Result, Descriptor, Source2Encoding); return Result; case FRD_FRS1_RM: - addRegister(Result, DestinationEncoding, true); - addRegister(Result, Source1Encoding, true); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); addImmediate(Result, (Encoding >> 12U) & 7U); return Result; case RD_FRS1_RM: - addRegister(Result, DestinationEncoding, false); - addRegister(Result, Source1Encoding, true); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); addImmediate(Result, (Encoding >> 12U) & 7U); return Result; case FRD_RS1_RM: - addRegister(Result, DestinationEncoding, true); - addRegister(Result, Source1Encoding, false); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); addImmediate(Result, (Encoding >> 12U) & 7U); return Result; case RD_FRS1: - addRegister(Result, DestinationEncoding, false); - addRegister(Result, Source1Encoding, true); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); return Result; case FRD_RS1: - addRegister(Result, DestinationEncoding, true); - addRegister(Result, Source1Encoding, false); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); return Result; default: return fixtureError("unsupported R-type reference fixture format"); @@ -127,8 +141,8 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, const bool FloatingDestination = Format == FRD_OFFSET_RS1; if (Format != RD_RS1_IMM && Format != RD_OFFSET_RS1 && !FloatingDestination) return fixtureError("unsupported I-type reference fixture format"); - addRegister(Result, DestinationEncoding, FloatingDestination); - addRegister(Result, Source1Encoding, false); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); const bool Shift64 = Opcode == SLLI || Opcode == SRLI || Opcode == SRAI; const bool Shift32 = Opcode == SLLIW || Opcode == SRLIW || Opcode == SRAIW; if (Shift64) @@ -143,8 +157,8 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, if (Category == rcc::riscv::EncodingCategory::S) { if (Format != RS2_OFFSET_RS1 && Format != FRS2_OFFSET_RS1) return fixtureError("unsupported S-type reference fixture format"); - addRegister(Result, Source2Encoding, Format == FRS2_OFFSET_RS1); - addRegister(Result, Source1Encoding, false); + addRegister(Result, Descriptor, Source2Encoding); + addRegister(Result, Descriptor, Source1Encoding); const std::uint32_t Immediate = ((Encoding >> 25U) & 0x7fU) << 5U | ((Encoding >> 7U) & 0x1fU); addImmediate(Result, signExtend(Immediate, 12)); return Result; @@ -153,8 +167,8 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, if (Category == rcc::riscv::EncodingCategory::B) { if (Format != RS1_RS2_TARGET) return fixtureError("unsupported B-type reference fixture format"); - addRegister(Result, Source1Encoding, false); - addRegister(Result, Source2Encoding, false); + addRegister(Result, Descriptor, Source1Encoding); + addRegister(Result, Descriptor, Source2Encoding); addImmediate(Result, decodeBranchImmediate(Encoding)); return Result; } @@ -162,7 +176,7 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, if (Category == rcc::riscv::EncodingCategory::U) { if (Format != RD_IMM) return fixtureError("unsupported U-type reference fixture format"); - addRegister(Result, DestinationEncoding, false); + addRegister(Result, Descriptor, DestinationEncoding); addImmediate(Result, signExtend(Encoding >> 12U, 20)); return Result; } @@ -170,7 +184,7 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, if (Category == rcc::riscv::EncodingCategory::J) { if (Format != RD_TARGET) return fixtureError("unsupported J-type reference fixture format"); - addRegister(Result, DestinationEncoding, false); + addRegister(Result, Descriptor, DestinationEncoding); addImmediate(Result, decodeJALImmediate(Encoding)); return Result; } @@ -180,10 +194,10 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, return Result; if (Format != RD_CSR_RS1 && Format != RD_CSR_IMM) return fixtureError("unsupported system reference fixture format"); - addRegister(Result, DestinationEncoding, false); + addRegister(Result, Descriptor, DestinationEncoding); addImmediate(Result, Encoding >> 20U); if (Format == RD_CSR_RS1) - addRegister(Result, Source1Encoding, false); + addRegister(Result, Descriptor, Source1Encoding); else addImmediate(Result, Source1Encoding); return Result; @@ -192,20 +206,20 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, if (Category == rcc::riscv::EncodingCategory::AMO) { if (Format != RD_PAREN_RS1 && Format != RD_RS2_PAREN_RS1) return fixtureError("unsupported atomic reference fixture format"); - addRegister(Result, DestinationEncoding, false); + addRegister(Result, Descriptor, DestinationEncoding); if (Format == RD_RS2_PAREN_RS1) - addRegister(Result, Source2Encoding, false); - addRegister(Result, Source1Encoding, false); + addRegister(Result, Descriptor, Source2Encoding); + addRegister(Result, Descriptor, Source1Encoding); return Result; } if (Category == rcc::riscv::EncodingCategory::R4) { if (Format != FRD_FRS1_FRS2_FRS3_RM) return fixtureError("unsupported R4 reference fixture format"); - addRegister(Result, DestinationEncoding, true); - addRegister(Result, Source1Encoding, true); - addRegister(Result, Source2Encoding, true); - addRegister(Result, (Encoding >> 27U) & 0x1fU, true); + addRegister(Result, Descriptor, DestinationEncoding); + addRegister(Result, Descriptor, Source1Encoding); + addRegister(Result, Descriptor, Source2Encoding); + addRegister(Result, Descriptor, (Encoding >> 27U) & 0x1fU); addImmediate(Result, (Encoding >> 12U) & 7U); return Result; } @@ -229,7 +243,8 @@ createStandardFixture(const rcc::InstructionDescriptor &Descriptor, } [[nodiscard]] rcc::Expected -createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { +createCompressedFixture(const rcc::InstructionDescriptor &Descriptor, + const rcc::riscv::AssemblyInstructionInfo &Assembly) { using enum rcc::riscv::InstructionOpcode; const auto Opcode = static_cast(Assembly.InstructionOpcode.value()); @@ -237,7 +252,7 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { rcc::mc::MCInst Result(rcc::mc::MCOpcode::fromValue(Assembly.InstructionOpcode.value())); if (Opcode == C_ADDI4SPN) { - addRegister(Result, ((Encoding >> 2U) & 7U) + 8U, false); + addRegister(Result, Descriptor, ((Encoding >> 2U) & 7U) + 8U); const std::uint32_t Immediate = ((Encoding >> 11U) & 3U) << 4U | ((Encoding >> 7U) & 0xfU) << 6U | ((Encoding >> 6U) & 1U) << 2U | ((Encoding >> 5U) & 1U) << 3U; @@ -250,8 +265,8 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { const bool DoubleStore = Opcode == C_FSD || Opcode == C_SD; const bool WordStore = Opcode == C_SW; if (DoubleLoad || WordLoad || DoubleStore || WordStore) { - addRegister(Result, ((Encoding >> 2U) & 7U) + 8U, Opcode == C_FLD || Opcode == C_FSD); - addRegister(Result, ((Encoding >> 7U) & 7U) + 8U, false); + addRegister(Result, Descriptor, ((Encoding >> 2U) & 7U) + 8U); + addRegister(Result, Descriptor, ((Encoding >> 7U) & 7U) + 8U); const bool Double = DoubleLoad || DoubleStore; std::uint32_t Immediate = ((Encoding >> 10U) & 7U) << 3U; if (Double) { @@ -266,7 +281,7 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { const bool CI = Opcode == C_ADDI || Opcode == C_ADDIW || Opcode == C_LI || Opcode == C_LUI || Opcode == C_SLLI; if (CI) { - addRegister(Result, (Encoding >> 7U) & 0x1fU, false); + addRegister(Result, Descriptor, (Encoding >> 7U) & 0x1fU); const std::uint32_t Immediate = ((Encoding >> 12U) & 1U) << 5U | ((Encoding >> 2U) & 0x1fU); addImmediate(Result, Opcode == C_SLLI ? Immediate : signExtend(Immediate, 6)); return Result; @@ -282,7 +297,7 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { const bool CompactShift = Opcode == C_SRLI || Opcode == C_SRAI; if (CompactShift || Opcode == C_ANDI) { - addRegister(Result, ((Encoding >> 7U) & 7U) + 8U, false); + addRegister(Result, Descriptor, ((Encoding >> 7U) & 7U) + 8U); const std::uint32_t Immediate = ((Encoding >> 12U) & 1U) << 5U | ((Encoding >> 2U) & 0x1fU); addImmediate(Result, CompactShift ? Immediate : signExtend(Immediate, 6)); return Result; @@ -291,8 +306,8 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { const bool CompactALU = Opcode == C_SUB || Opcode == C_XOR || Opcode == C_OR || Opcode == C_AND || Opcode == C_SUBW || Opcode == C_ADDW; if (CompactALU) { - addRegister(Result, ((Encoding >> 7U) & 7U) + 8U, false); - addRegister(Result, ((Encoding >> 2U) & 7U) + 8U, false); + addRegister(Result, Descriptor, ((Encoding >> 7U) & 7U) + 8U); + addRegister(Result, Descriptor, ((Encoding >> 2U) & 7U) + 8U); return Result; } @@ -302,14 +317,14 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { } if (Opcode == C_BEQZ || Opcode == C_BNEZ) { - addRegister(Result, ((Encoding >> 7U) & 7U) + 8U, false); + addRegister(Result, Descriptor, ((Encoding >> 7U) & 7U) + 8U); addImmediate(Result, decodeRVCBranchImmediate(Encoding)); return Result; } const bool DoubleStackLoad = Opcode == C_FLDSP || Opcode == C_LDSP; if (DoubleStackLoad || Opcode == C_LWSP) { - addRegister(Result, (Encoding >> 7U) & 0x1fU, Opcode == C_FLDSP); + addRegister(Result, Descriptor, (Encoding >> 7U) & 0x1fU); const std::uint32_t Immediate = DoubleStackLoad ? ((Encoding >> 12U) & 1U) << 5U | ((Encoding >> 5U) & 3U) << 3U | ((Encoding >> 2U) & 7U) << 6U @@ -322,9 +337,9 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { const bool CRSingle = Opcode == C_JR || Opcode == C_JALR; const bool CRDouble = Opcode == C_MV || Opcode == C_ADD; if (CRSingle || CRDouble) { - addRegister(Result, (Encoding >> 7U) & 0x1fU, false); + addRegister(Result, Descriptor, (Encoding >> 7U) & 0x1fU); if (CRDouble) - addRegister(Result, (Encoding >> 2U) & 0x1fU, false); + addRegister(Result, Descriptor, (Encoding >> 2U) & 0x1fU); return Result; } @@ -333,7 +348,7 @@ createCompressedFixture(const rcc::riscv::AssemblyInstructionInfo &Assembly) { const bool DoubleStackStore = Opcode == C_FSDSP || Opcode == C_SDSP; if (DoubleStackStore || Opcode == C_SWSP) { - addRegister(Result, (Encoding >> 2U) & 0x1fU, Opcode == C_FSDSP); + addRegister(Result, Descriptor, (Encoding >> 2U) & 0x1fU); const std::uint32_t Immediate = DoubleStackStore ? ((Encoding >> 10U) & 7U) << 3U | ((Encoding >> 7U) & 7U) << 6U : ((Encoding >> 9U) & 0xfU) << 2U | ((Encoding >> 7U) & 3U) << 6U; @@ -350,7 +365,7 @@ createReferenceFixture(const rcc::InstructionDescriptor &Descriptor, const auto Category = static_cast(Descriptor.EncodingCategory.value()); if (Category == rcc::riscv::EncodingCategory::C) - return createCompressedFixture(Assembly); + return createCompressedFixture(Descriptor, Assembly); return createStandardFixture(Descriptor, Assembly); } diff --git a/backend/unittests/Target/RISCVMCTest.cpp b/backend/unittests/Target/RISCVMCTest.cpp index 1d44c73..4836708 100644 --- a/backend/unittests/Target/RISCVMCTest.cpp +++ b/backend/unittests/Target/RISCVMCTest.cpp @@ -102,9 +102,10 @@ symbolExpression(rcc::mc::MCContext &Context, std::string_view Name, std::uint32 {0xf3, 0xda, 0x58, 0x30}, "CSRRWI") && expectEncoding(Emitter, instruction(AMOADD_D, {reg(X22), reg(X23), reg(X24)}), {0x2f, 0x3b, 0x7c, 0x01}, "AMOADD.D") && - expectEncoding(Emitter, instruction(FMADD_D, {reg(F1), reg(F2), reg(F3), reg(F4), imm(2)}), + expectEncoding(Emitter, + instruction(FMADD_D, {reg(F1_D), reg(F2_D), reg(F3_D), reg(F4_D), imm(2)}), {0xc3, 0x20, 0x31, 0x22}, "FMADD.D") && - expectEncoding(Emitter, instruction(FADD_S, {reg(F5), reg(F6), reg(F7), imm(3)}), + expectEncoding(Emitter, instruction(FADD_S, {reg(F5_F), reg(F6_F), reg(F7_F), imm(3)}), {0xd3, 0x32, 0x73, 0x00}, "FADD.S") && expectEncoding(Emitter, instruction(C_ADDI4SPN, {reg(X8), imm(48)}), {0x00, 0x18}, "C.ADDI4SPN") && diff --git a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp index 72cce51..299308c 100644 --- a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp +++ b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp @@ -264,16 +264,16 @@ void testTargetHooks(TestContext &Context, const rcc::TargetDescription &Target) Info.emitSpill(Builder, physical(rcc::riscv::PhysicalRegisterID::X5), registerClass(rcc::riscv::RegisterClass::GPR), *Slot, rcc::LaneMask::all()); auto F32Reload = - Info.emitReload(Builder, physical(rcc::riscv::PhysicalRegisterID::F10), + Info.emitReload(Builder, physical(rcc::riscv::PhysicalRegisterID::F10_F), registerClass(rcc::riscv::RegisterClass::FPR32), *Slot, rcc::LaneMask::all()); auto F32Spill = - Info.emitSpill(Builder, physical(rcc::riscv::PhysicalRegisterID::F10), + Info.emitSpill(Builder, physical(rcc::riscv::PhysicalRegisterID::F10_F), registerClass(rcc::riscv::RegisterClass::FPR32), *Slot, rcc::LaneMask::all()); auto F64Reload = - Info.emitReload(Builder, physical(rcc::riscv::PhysicalRegisterID::F11), + Info.emitReload(Builder, physical(rcc::riscv::PhysicalRegisterID::F11_D), registerClass(rcc::riscv::RegisterClass::FPR64), *Slot, rcc::LaneMask::all()); auto F64Spill = - Info.emitSpill(Builder, physical(rcc::riscv::PhysicalRegisterID::F11), + Info.emitSpill(Builder, physical(rcc::riscv::PhysicalRegisterID::F11_D), registerClass(rcc::riscv::RegisterClass::FPR64), *Slot, rcc::LaneMask::all()); Context.expect(GPRReload && GPRSpill && F32Reload && F32Spill && F64Reload && F64Spill && (*GPRReload)->opcode() == targetOpcode(rcc::riscv::InstructionOpcode::LD) && diff --git a/backend/unittests/Target/RISCVTargetTest.cpp b/backend/unittests/Target/RISCVTargetTest.cpp index 1aa2d72..2d1be09 100644 --- a/backend/unittests/Target/RISCVTargetTest.cpp +++ b/backend/unittests/Target/RISCVTargetTest.cpp @@ -47,10 +47,11 @@ void testRegisterFacts(TestContext &Context) { const rcc::PhysicalRegister X2 = registerID(rcc::riscv::PhysicalRegisterID::X2); const rcc::PhysicalRegister X5 = registerID(rcc::riscv::PhysicalRegisterID::X5); const rcc::PhysicalRegister X8 = registerID(rcc::riscv::PhysicalRegisterID::X8); - const rcc::PhysicalRegister F31 = registerID(rcc::riscv::PhysicalRegisterID::F31); + const rcc::PhysicalRegister F31D = registerID(rcc::riscv::PhysicalRegisterID::F31_D); + const rcc::PhysicalRegister F31F = registerID(rcc::riscv::PhysicalRegisterID::F31_F); Context.expect( - Registers->physicalRegisters().size() == 64 && Registers->registerUnits().size() == 64 && + Registers->physicalRegisters().size() == 96 && Registers->registerUnits().size() == 64 && Registers->registerClasses().size() == 8 && Registers->registerBanks().size() == 2, "RV64GC must expose the complete scalar, compressed, and restricted register classes"); Context.expect(Registers->physicalRegister("x0") != nullptr && @@ -65,9 +66,17 @@ void testRegisterFacts(TestContext &Context) { Registers->isReservedRegister(X0) && Registers->isReservedRegister(X2) && !Registers->isReservedRegister(X5), "zero, stack, global, and thread register constraints must be recorded statically"); - Context.expect(Registers->physicalRegister(F31) != nullptr && - Registers->physicalRegister(F31)->Encoding == 31, - "floating register physical IDs must remain distinct from their ISA encodings"); + Context.expect(Registers->physicalRegister(F31D) != nullptr && + Registers->physicalRegister(F31D)->Encoding == 31 && + Registers->physicalRegister("f31_d") != nullptr && + Registers->physicalRegister("f31_d")->Reg == F31D && + Registers->physicalRegister("f31_f") != nullptr && + Registers->physicalRegister("f31_f")->Reg == F31F && + Registers->physicalRegisterMIRName(F31D) == "f31_d" && + Registers->physicalRegisterMIRName(F31F) == "f31_f" && + Registers->regsOverlap(F31D, F31F) && + Registers->subRegister(F31D, rcc::SubRegIndex::fromValue(1)) == F31F, + "FPR32 and FPR64 MIR views must retain encoding, overlap, and subregister facts"); const auto *GPR = Registers->registerClass("gpr"); Context.expect( @@ -83,16 +92,20 @@ void testRegisterFacts(TestContext &Context) { void testABIAndDebugFacts(TestContext &Context) { const rcc::PhysicalRegister X1 = registerID(rcc::riscv::PhysicalRegisterID::X1); const rcc::PhysicalRegister X10 = registerID(rcc::riscv::PhysicalRegisterID::X10); - const rcc::PhysicalRegister F8 = registerID(rcc::riscv::PhysicalRegisterID::F8); - const rcc::PhysicalRegister F10 = registerID(rcc::riscv::PhysicalRegisterID::F10); - const rcc::PhysicalRegister F31 = registerID(rcc::riscv::PhysicalRegisterID::F31); + const rcc::PhysicalRegister F8D = registerID(rcc::riscv::PhysicalRegisterID::F8_D); + const rcc::PhysicalRegister F8F = registerID(rcc::riscv::PhysicalRegisterID::F8_F); + const rcc::PhysicalRegister F10D = registerID(rcc::riscv::PhysicalRegisterID::F10_D); + const rcc::PhysicalRegister F10F = registerID(rcc::riscv::PhysicalRegisterID::F10_F); + const rcc::PhysicalRegister F31D = registerID(rcc::riscv::PhysicalRegisterID::F31_D); + const rcc::PhysicalRegister F31F = registerID(rcc::riscv::PhysicalRegisterID::F31_F); const auto LP64Mask = rcc::riscv::createCallPreservedMask(rcc::riscv::CallingConvention::LP64); const auto LP64DMask = rcc::riscv::createCallPreservedMask(rcc::riscv::CallingConvention::LP64D); Context.expect( - LP64DMask != nullptr && LP64DMask->preserves(X1) && LP64DMask->preserves(F8) && - LP64DMask->clobbers(X10) && LP64DMask->clobbers(F10) && LP64Mask != nullptr && - LP64Mask->preserves(X1) && LP64Mask->clobbers(F8) && LP64Mask->clobbers(X10), + LP64DMask != nullptr && LP64DMask->preserves(X1) && LP64DMask->preserves(F8D) && + LP64DMask->preserves(F8F) && LP64DMask->clobbers(X10) && LP64DMask->clobbers(F10D) && + LP64DMask->clobbers(F10F) && LP64Mask != nullptr && LP64Mask->preserves(X1) && + LP64Mask->clobbers(F8D) && LP64Mask->clobbers(F8F) && LP64Mask->clobbers(X10), "LP64 and LP64D masks must distinguish integer and floating callee-saved registers"); auto MIRText = rcc::riscv::createMIRTextInfo(); @@ -111,8 +124,9 @@ void testABIAndDebugFacts(TestContext &Context) { "RV64GC MIR target flags must expose the canonical direct-call spelling"); Context.expect(MIRText->dwarfRegister(X1) == 1, "the return-address register must retain its DWARF register number"); - Context.expect(MIRText->physicalRegister(63) == F31, - "the final floating register DWARF number must map to f31"); + Context.expect(MIRText->dwarfRegister(F31D) == 63 && MIRText->dwarfRegister(F31F) == 63 && + MIRText->physicalRegister(63) == F31D, + "typed floating views must share one canonical DWARF register mapping"); const auto Conventions = rcc::riscv::callingConventions(); const auto *LP64 = rcc::riscv::callingConvention(rcc::riscv::CallingConvention::LP64); -- cgit v1.2.3