aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/lib/Target/Description/TargetDescriptionGenerator.cpp12
-rw-r--r--backend/lib/Target/RISCV/RISCV.rccdesc118
-rw-r--r--backend/lib/Target/RISCV/RISCVCallLowering.cpp47
-rw-r--r--backend/lib/Target/RISCV/RISCVFrameLowering.cpp20
-rw-r--r--backend/lib/Target/RISCV/RISCVInstPrinter.cpp5
-rw-r--r--backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp21
-rw-r--r--backend/lib/Target/RISCV/RISCVTarget.cpp37
-rw-r--r--backend/unittests/Target/RISCVCallLoweringTest.cpp11
-rw-r--r--backend/unittests/Target/RISCVFrameLoweringTest.cpp6
-rw-r--r--backend/unittests/Target/RISCVLateCodeGenTest.cpp3
-rw-r--r--backend/unittests/Target/RISCVMCEncodingCoverageTest.cpp125
-rw-r--r--backend/unittests/Target/RISCVMCTest.cpp5
-rw-r--r--backend/unittests/Target/RISCVRegisterAllocationTest.cpp8
-rw-r--r--backend/unittests/Target/RISCVTargetTest.cpp40
14 files changed, 303 insertions, 155 deletions
diff --git a/backend/lib/Target/Description/TargetDescriptionGenerator.cpp b/backend/lib/Target/Description/TargetDescriptionGenerator.cpp
index dd3545b..bd0e794 100644
--- a/backend/lib/Target/Description/TargetDescriptionGenerator.cpp
+++ b/backend/lib/Target/Description/TargetDescriptionGenerator.cpp
@@ -1840,14 +1840,12 @@ private:
std::unordered_set<std::uint32_t> IDs;
std::unordered_set<std::string> Symbols;
std::unordered_set<std::string> Names;
- std::unordered_set<std::uint32_t> DwarfRegisters;
for (const SourceRegister &Register : Input.Registers) {
if (Register.ID == 0 || !isIdentifier(Register.Symbol) || Register.Name.empty() ||
!IDs.insert(Register.ID).second || !Symbols.insert(Register.Symbol).second ||
- !Names.insert(lowerASCII(Register.Name)).second ||
- !DwarfRegisters.insert(Register.DwarfRegister).second || Register.Units.empty()) {
- fail(Register.Range, "registers require nonzero unique IDs, symbols, canonical names, "
- "DWARF numbers, and units");
+ !Names.insert(lowerASCII(Register.Name)).second || Register.Units.empty()) {
+ fail(Register.Range,
+ "registers require nonzero unique IDs, symbols, canonical names, and units");
return false;
}
RegisterBySymbol.emplace(Register.Symbol, Register.ID);
@@ -2900,9 +2898,11 @@ void emitImmediatePredicate(std::ostream &Output, const NormalizedImmediatePredi
Output << "})},\n";
}
Output << " };\n Description.CFIRegisters = {\n";
+ std::unordered_set<std::uint32_t> CanonicalDwarfRegisters;
for (const NormalizedRegister &Register : Model.Registers) {
+ const bool IsCanonical = CanonicalDwarfRegisters.insert(Register.DwarfRegister).second;
Output << " {physical(PhysicalRegisterID::" << Register.Symbol << "), "
- << Register.DwarfRegister << ", true},\n";
+ << Register.DwarfRegister << ", " << (IsCanonical ? "true" : "false") << "},\n";
}
Output << " };\n}\n\n";
diff --git a/backend/lib/Target/RISCV/RISCV.rccdesc b/backend/lib/Target/RISCV/RISCV.rccdesc
index 93c94b4..5000d8b 100644
--- a/backend/lib/Target/RISCV/RISCV.rccdesc
+++ b/backend/lib/Target/RISCV/RISCV.rccdesc
@@ -109,38 +109,70 @@ registers:
- { id: 30, symbol: X29, name: x29, encoding: 29, dwarf_register: 29, units: [{ unit: U_X29, lanes: 1 }], aliases: [t4] }
- { id: 31, symbol: X30, name: x30, encoding: 30, dwarf_register: 30, units: [{ unit: U_X30, lanes: 1 }], aliases: [t5] }
- { id: 32, symbol: X31, name: x31, encoding: 31, dwarf_register: 31, units: [{ unit: U_X31, lanes: 1 }], aliases: [t6] }
- - { id: 33, symbol: F0, name: f0, encoding: 0, dwarf_register: 32, units: [{ unit: U_F0, lanes: 1 }], aliases: [ft0] }
- - { id: 34, symbol: F1, name: f1, encoding: 1, dwarf_register: 33, units: [{ unit: U_F1, lanes: 1 }], aliases: [ft1] }
- - { id: 35, symbol: F2, name: f2, encoding: 2, dwarf_register: 34, units: [{ unit: U_F2, lanes: 1 }], aliases: [ft2] }
- - { id: 36, symbol: F3, name: f3, encoding: 3, dwarf_register: 35, units: [{ unit: U_F3, lanes: 1 }], aliases: [ft3] }
- - { id: 37, symbol: F4, name: f4, encoding: 4, dwarf_register: 36, units: [{ unit: U_F4, lanes: 1 }], aliases: [ft4] }
- - { id: 38, symbol: F5, name: f5, encoding: 5, dwarf_register: 37, units: [{ unit: U_F5, lanes: 1 }], aliases: [ft5] }
- - { id: 39, symbol: F6, name: f6, encoding: 6, dwarf_register: 38, units: [{ unit: U_F6, lanes: 1 }], aliases: [ft6] }
- - { id: 40, symbol: F7, name: f7, encoding: 7, dwarf_register: 39, units: [{ unit: U_F7, lanes: 1 }], aliases: [ft7] }
- - { id: 41, symbol: F8, name: f8, encoding: 8, dwarf_register: 40, units: [{ unit: U_F8, lanes: 1 }], aliases: [fs0] }
- - { id: 42, symbol: F9, name: f9, encoding: 9, dwarf_register: 41, units: [{ unit: U_F9, lanes: 1 }], aliases: [fs1] }
- - { id: 43, symbol: F10, name: f10, encoding: 10, dwarf_register: 42, units: [{ unit: U_F10, lanes: 1 }], aliases: [fa0] }
- - { id: 44, symbol: F11, name: f11, encoding: 11, dwarf_register: 43, units: [{ unit: U_F11, lanes: 1 }], aliases: [fa1] }
- - { id: 45, symbol: F12, name: f12, encoding: 12, dwarf_register: 44, units: [{ unit: U_F12, lanes: 1 }], aliases: [fa2] }
- - { id: 46, symbol: F13, name: f13, encoding: 13, dwarf_register: 45, units: [{ unit: U_F13, lanes: 1 }], aliases: [fa3] }
- - { id: 47, symbol: F14, name: f14, encoding: 14, dwarf_register: 46, units: [{ unit: U_F14, lanes: 1 }], aliases: [fa4] }
- - { id: 48, symbol: F15, name: f15, encoding: 15, dwarf_register: 47, units: [{ unit: U_F15, lanes: 1 }], aliases: [fa5] }
- - { id: 49, symbol: F16, name: f16, encoding: 16, dwarf_register: 48, units: [{ unit: U_F16, lanes: 1 }], aliases: [fa6] }
- - { id: 50, symbol: F17, name: f17, encoding: 17, dwarf_register: 49, units: [{ unit: U_F17, lanes: 1 }], aliases: [fa7] }
- - { id: 51, symbol: F18, name: f18, encoding: 18, dwarf_register: 50, units: [{ unit: U_F18, lanes: 1 }], aliases: [fs2] }
- - { id: 52, symbol: F19, name: f19, encoding: 19, dwarf_register: 51, units: [{ unit: U_F19, lanes: 1 }], aliases: [fs3] }
- - { id: 53, symbol: F20, name: f20, encoding: 20, dwarf_register: 52, units: [{ unit: U_F20, lanes: 1 }], aliases: [fs4] }
- - { id: 54, symbol: F21, name: f21, encoding: 21, dwarf_register: 53, units: [{ unit: U_F21, lanes: 1 }], aliases: [fs5] }
- - { id: 55, symbol: F22, name: f22, encoding: 22, dwarf_register: 54, units: [{ unit: U_F22, lanes: 1 }], aliases: [fs6] }
- - { id: 56, symbol: F23, name: f23, encoding: 23, dwarf_register: 55, units: [{ unit: U_F23, lanes: 1 }], aliases: [fs7] }
- - { id: 57, symbol: F24, name: f24, encoding: 24, dwarf_register: 56, units: [{ unit: U_F24, lanes: 1 }], aliases: [fs8] }
- - { id: 58, symbol: F25, name: f25, encoding: 25, dwarf_register: 57, units: [{ unit: U_F25, lanes: 1 }], aliases: [fs9] }
- - { id: 59, symbol: F26, name: f26, encoding: 26, dwarf_register: 58, units: [{ unit: U_F26, lanes: 1 }], aliases: [fs10] }
- - { id: 60, symbol: F27, name: f27, encoding: 27, dwarf_register: 59, units: [{ unit: U_F27, lanes: 1 }], aliases: [fs11] }
- - { id: 61, symbol: F28, name: f28, encoding: 28, dwarf_register: 60, units: [{ unit: U_F28, lanes: 1 }], aliases: [ft8] }
- - { id: 62, symbol: F29, name: f29, encoding: 29, dwarf_register: 61, units: [{ unit: U_F29, lanes: 1 }], aliases: [ft9] }
- - { id: 63, symbol: F30, name: f30, encoding: 30, dwarf_register: 62, units: [{ unit: U_F30, lanes: 1 }], aliases: [ft10] }
- - { id: 64, symbol: F31, name: f31, encoding: 31, dwarf_register: 63, units: [{ unit: U_F31, lanes: 1 }], aliases: [ft11] }
+ - { id: 33, symbol: F0_D, name: f0_d, encoding: 0, dwarf_register: 32, units: [{ unit: U_F0, lanes: 1 }], aliases: [ft0] }
+ - { id: 34, symbol: F1_D, name: f1_d, encoding: 1, dwarf_register: 33, units: [{ unit: U_F1, lanes: 1 }], aliases: [ft1] }
+ - { id: 35, symbol: F2_D, name: f2_d, encoding: 2, dwarf_register: 34, units: [{ unit: U_F2, lanes: 1 }], aliases: [ft2] }
+ - { id: 36, symbol: F3_D, name: f3_d, encoding: 3, dwarf_register: 35, units: [{ unit: U_F3, lanes: 1 }], aliases: [ft3] }
+ - { id: 37, symbol: F4_D, name: f4_d, encoding: 4, dwarf_register: 36, units: [{ unit: U_F4, lanes: 1 }], aliases: [ft4] }
+ - { id: 38, symbol: F5_D, name: f5_d, encoding: 5, dwarf_register: 37, units: [{ unit: U_F5, lanes: 1 }], aliases: [ft5] }
+ - { id: 39, symbol: F6_D, name: f6_d, encoding: 6, dwarf_register: 38, units: [{ unit: U_F6, lanes: 1 }], aliases: [ft6] }
+ - { id: 40, symbol: F7_D, name: f7_d, encoding: 7, dwarf_register: 39, units: [{ unit: U_F7, lanes: 1 }], aliases: [ft7] }
+ - { id: 41, symbol: F8_D, name: f8_d, encoding: 8, dwarf_register: 40, units: [{ unit: U_F8, lanes: 1 }], aliases: [fs0] }
+ - { id: 42, symbol: F9_D, name: f9_d, encoding: 9, dwarf_register: 41, units: [{ unit: U_F9, lanes: 1 }], aliases: [fs1] }
+ - { id: 43, symbol: F10_D, name: f10_d, encoding: 10, dwarf_register: 42, units: [{ unit: U_F10, lanes: 1 }], aliases: [fa0] }
+ - { id: 44, symbol: F11_D, name: f11_d, encoding: 11, dwarf_register: 43, units: [{ unit: U_F11, lanes: 1 }], aliases: [fa1] }
+ - { id: 45, symbol: F12_D, name: f12_d, encoding: 12, dwarf_register: 44, units: [{ unit: U_F12, lanes: 1 }], aliases: [fa2] }
+ - { id: 46, symbol: F13_D, name: f13_d, encoding: 13, dwarf_register: 45, units: [{ unit: U_F13, lanes: 1 }], aliases: [fa3] }
+ - { id: 47, symbol: F14_D, name: f14_d, encoding: 14, dwarf_register: 46, units: [{ unit: U_F14, lanes: 1 }], aliases: [fa4] }
+ - { id: 48, symbol: F15_D, name: f15_d, encoding: 15, dwarf_register: 47, units: [{ unit: U_F15, lanes: 1 }], aliases: [fa5] }
+ - { id: 49, symbol: F16_D, name: f16_d, encoding: 16, dwarf_register: 48, units: [{ unit: U_F16, lanes: 1 }], aliases: [fa6] }
+ - { id: 50, symbol: F17_D, name: f17_d, encoding: 17, dwarf_register: 49, units: [{ unit: U_F17, lanes: 1 }], aliases: [fa7] }
+ - { id: 51, symbol: F18_D, name: f18_d, encoding: 18, dwarf_register: 50, units: [{ unit: U_F18, lanes: 1 }], aliases: [fs2] }
+ - { id: 52, symbol: F19_D, name: f19_d, encoding: 19, dwarf_register: 51, units: [{ unit: U_F19, lanes: 1 }], aliases: [fs3] }
+ - { id: 53, symbol: F20_D, name: f20_d, encoding: 20, dwarf_register: 52, units: [{ unit: U_F20, lanes: 1 }], aliases: [fs4] }
+ - { id: 54, symbol: F21_D, name: f21_d, encoding: 21, dwarf_register: 53, units: [{ unit: U_F21, lanes: 1 }], aliases: [fs5] }
+ - { id: 55, symbol: F22_D, name: f22_d, encoding: 22, dwarf_register: 54, units: [{ unit: U_F22, lanes: 1 }], aliases: [fs6] }
+ - { id: 56, symbol: F23_D, name: f23_d, encoding: 23, dwarf_register: 55, units: [{ unit: U_F23, lanes: 1 }], aliases: [fs7] }
+ - { id: 57, symbol: F24_D, name: f24_d, encoding: 24, dwarf_register: 56, units: [{ unit: U_F24, lanes: 1 }], aliases: [fs8] }
+ - { id: 58, symbol: F25_D, name: f25_d, encoding: 25, dwarf_register: 57, units: [{ unit: U_F25, lanes: 1 }], aliases: [fs9] }
+ - { id: 59, symbol: F26_D, name: f26_d, encoding: 26, dwarf_register: 58, units: [{ unit: U_F26, lanes: 1 }], aliases: [fs10] }
+ - { id: 60, symbol: F27_D, name: f27_d, encoding: 27, dwarf_register: 59, units: [{ unit: U_F27, lanes: 1 }], aliases: [fs11] }
+ - { id: 61, symbol: F28_D, name: f28_d, encoding: 28, dwarf_register: 60, units: [{ unit: U_F28, lanes: 1 }], aliases: [ft8] }
+ - { id: 62, symbol: F29_D, name: f29_d, encoding: 29, dwarf_register: 61, units: [{ unit: U_F29, lanes: 1 }], aliases: [ft9] }
+ - { id: 63, symbol: F30_D, name: f30_d, encoding: 30, dwarf_register: 62, units: [{ unit: U_F30, lanes: 1 }], aliases: [ft10] }
+ - { id: 64, symbol: F31_D, name: f31_d, encoding: 31, dwarf_register: 63, units: [{ unit: U_F31, lanes: 1 }], aliases: [ft11] }
+ - { id: 65, symbol: F0_F, name: f0_f, encoding: 0, dwarf_register: 32, units: [{ unit: U_F0, lanes: 1 }] }
+ - { id: 66, symbol: F1_F, name: f1_f, encoding: 1, dwarf_register: 33, units: [{ unit: U_F1, lanes: 1 }] }
+ - { id: 67, symbol: F2_F, name: f2_f, encoding: 2, dwarf_register: 34, units: [{ unit: U_F2, lanes: 1 }] }
+ - { id: 68, symbol: F3_F, name: f3_f, encoding: 3, dwarf_register: 35, units: [{ unit: U_F3, lanes: 1 }] }
+ - { id: 69, symbol: F4_F, name: f4_f, encoding: 4, dwarf_register: 36, units: [{ unit: U_F4, lanes: 1 }] }
+ - { id: 70, symbol: F5_F, name: f5_f, encoding: 5, dwarf_register: 37, units: [{ unit: U_F5, lanes: 1 }] }
+ - { id: 71, symbol: F6_F, name: f6_f, encoding: 6, dwarf_register: 38, units: [{ unit: U_F6, lanes: 1 }] }
+ - { id: 72, symbol: F7_F, name: f7_f, encoding: 7, dwarf_register: 39, units: [{ unit: U_F7, lanes: 1 }] }
+ - { id: 73, symbol: F8_F, name: f8_f, encoding: 8, dwarf_register: 40, units: [{ unit: U_F8, lanes: 1 }] }
+ - { id: 74, symbol: F9_F, name: f9_f, encoding: 9, dwarf_register: 41, units: [{ unit: U_F9, lanes: 1 }] }
+ - { id: 75, symbol: F10_F, name: f10_f, encoding: 10, dwarf_register: 42, units: [{ unit: U_F10, lanes: 1 }] }
+ - { id: 76, symbol: F11_F, name: f11_f, encoding: 11, dwarf_register: 43, units: [{ unit: U_F11, lanes: 1 }] }
+ - { id: 77, symbol: F12_F, name: f12_f, encoding: 12, dwarf_register: 44, units: [{ unit: U_F12, lanes: 1 }] }
+ - { id: 78, symbol: F13_F, name: f13_f, encoding: 13, dwarf_register: 45, units: [{ unit: U_F13, lanes: 1 }] }
+ - { id: 79, symbol: F14_F, name: f14_f, encoding: 14, dwarf_register: 46, units: [{ unit: U_F14, lanes: 1 }] }
+ - { id: 80, symbol: F15_F, name: f15_f, encoding: 15, dwarf_register: 47, units: [{ unit: U_F15, lanes: 1 }] }
+ - { id: 81, symbol: F16_F, name: f16_f, encoding: 16, dwarf_register: 48, units: [{ unit: U_F16, lanes: 1 }] }
+ - { id: 82, symbol: F17_F, name: f17_f, encoding: 17, dwarf_register: 49, units: [{ unit: U_F17, lanes: 1 }] }
+ - { id: 83, symbol: F18_F, name: f18_f, encoding: 18, dwarf_register: 50, units: [{ unit: U_F18, lanes: 1 }] }
+ - { id: 84, symbol: F19_F, name: f19_f, encoding: 19, dwarf_register: 51, units: [{ unit: U_F19, lanes: 1 }] }
+ - { id: 85, symbol: F20_F, name: f20_f, encoding: 20, dwarf_register: 52, units: [{ unit: U_F20, lanes: 1 }] }
+ - { id: 86, symbol: F21_F, name: f21_f, encoding: 21, dwarf_register: 53, units: [{ unit: U_F21, lanes: 1 }] }
+ - { id: 87, symbol: F22_F, name: f22_f, encoding: 22, dwarf_register: 54, units: [{ unit: U_F22, lanes: 1 }] }
+ - { id: 88, symbol: F23_F, name: f23_f, encoding: 23, dwarf_register: 55, units: [{ unit: U_F23, lanes: 1 }] }
+ - { id: 89, symbol: F24_F, name: f24_f, encoding: 24, dwarf_register: 56, units: [{ unit: U_F24, lanes: 1 }] }
+ - { id: 90, symbol: F25_F, name: f25_f, encoding: 25, dwarf_register: 57, units: [{ unit: U_F25, lanes: 1 }] }
+ - { id: 91, symbol: F26_F, name: f26_f, encoding: 26, dwarf_register: 58, units: [{ unit: U_F26, lanes: 1 }] }
+ - { id: 92, symbol: F27_F, name: f27_f, encoding: 27, dwarf_register: 59, units: [{ unit: U_F27, lanes: 1 }] }
+ - { id: 93, symbol: F28_F, name: f28_f, encoding: 28, dwarf_register: 60, units: [{ unit: U_F28, lanes: 1 }] }
+ - { id: 94, symbol: F29_F, name: f29_f, encoding: 29, dwarf_register: 61, units: [{ unit: U_F29, lanes: 1 }] }
+ - { id: 95, symbol: F30_F, name: f30_f, encoding: 30, dwarf_register: 62, units: [{ unit: U_F30, lanes: 1 }] }
+ - { id: 96, symbol: F31_F, name: f31_f, encoding: 31, dwarf_register: 63, units: [{ unit: U_F31, lanes: 1 }] }
register_banks:
- { id: 1, symbol: GPR, name: GPRB, maximum_size_bits: 64 }
@@ -178,8 +210,8 @@ register_classes:
spill_size_bits: 64
spill_alignment_bits: 64
lanes: 1
- registers: [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]
- allocation_order: [F10, F11, F12, F13, F14, F15, F16, F17, F0, F1, F2, F3, F4, F5, F6, F7, F28, F29, F30, F31, F8, F9, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27]
+ registers: [F0_D, F1_D, F2_D, F3_D, F4_D, F5_D, F6_D, F7_D, F8_D, F9_D, F10_D, F11_D, F12_D, F13_D, F14_D, F15_D, F16_D, F17_D, F18_D, F19_D, F20_D, F21_D, F22_D, F23_D, F24_D, F25_D, F26_D, F27_D, F28_D, F29_D, F30_D, F31_D]
+ allocation_order: [F10_D, F11_D, F12_D, F13_D, F14_D, F15_D, F16_D, F17_D, F0_D, F1_D, F2_D, F3_D, F4_D, F5_D, F6_D, F7_D, F28_D, F29_D, F30_D, F31_D, F8_D, F9_D, F18_D, F19_D, F20_D, F21_D, F22_D, F23_D, F24_D, F25_D, F26_D, F27_D]
-
id: 4
symbol: FPR64C
@@ -189,8 +221,8 @@ register_classes:
spill_size_bits: 64
spill_alignment_bits: 64
lanes: 1
- registers: [F8, F9, F10, F11, F12, F13, F14, F15]
- allocation_order: [F10, F11, F12, F13, F14, F15, F8, F9]
+ registers: [F8_D, F9_D, F10_D, F11_D, F12_D, F13_D, F14_D, F15_D]
+ allocation_order: [F10_D, F11_D, F12_D, F13_D, F14_D, F15_D, F8_D, F9_D]
-
id: 5
symbol: FPR32
@@ -200,8 +232,8 @@ register_classes:
spill_size_bits: 32
spill_alignment_bits: 32
lanes: 1
- registers: [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]
- allocation_order: [F10, F11, F12, F13, F14, F15, F16, F17, F0, F1, F2, F3, F4, F5, F6, F7, F28, F29, F30, F31, F8, F9, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27]
+ registers: [F0_F, F1_F, F2_F, F3_F, F4_F, F5_F, F6_F, F7_F, F8_F, F9_F, F10_F, F11_F, F12_F, F13_F, F14_F, F15_F, F16_F, F17_F, F18_F, F19_F, F20_F, F21_F, F22_F, F23_F, F24_F, F25_F, F26_F, F27_F, F28_F, F29_F, F30_F, F31_F]
+ allocation_order: [F10_F, F11_F, F12_F, F13_F, F14_F, F15_F, F16_F, F17_F, F0_F, F1_F, F2_F, F3_F, F4_F, F5_F, F6_F, F7_F, F28_F, F29_F, F30_F, F31_F, F8_F, F9_F, F18_F, F19_F, F20_F, F21_F, F22_F, F23_F, F24_F, F25_F, F26_F, F27_F]
-
id: 6
symbol: FPR32C
@@ -211,8 +243,8 @@ register_classes:
spill_size_bits: 32
spill_alignment_bits: 32
lanes: 1
- registers: [F8, F9, F10, F11, F12, F13, F14, F15]
- allocation_order: [F10, F11, F12, F13, F14, F15, F8, F9]
+ registers: [F8_F, F9_F, F10_F, F11_F, F12_F, F13_F, F14_F, F15_F]
+ allocation_order: [F10_F, F11_F, F12_F, F13_F, F14_F, F15_F, F8_F, F9_F]
-
id: 7
symbol: GPR_NX0
@@ -242,7 +274,7 @@ register_masks:
preserved: [X1, X8, X9, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27]
-
name: CSR_ILP32D_LP64D
- preserved: [X1, X8, X9, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, F8, F9, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27]
+ preserved: [X1, X8, X9, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, F8_D, F9_D, F18_D, F19_D, F20_D, F21_D, F22_D, F23_D, F24_D, F25_D, F26_D, F27_D, F8_F, F9_F, F18_F, F19_F, F20_F, F21_F, F22_F, F23_F, F24_F, F25_F, F26_F, F27_F]
mir_operand_flags:
direct_mask: 31
@@ -278,9 +310,9 @@ calling_conventions:
integer_register_class: GPR
floating_register_class: FPR64
integer_argument_registers: [X10, X11, X12, X13, X14, X15, X16, X17]
- floating_argument_registers: [F10, F11, F12, F13, F14, F15, F16, F17]
+ floating_argument_registers: [F10_D, F11_D, F12_D, F13_D, F14_D, F15_D, F16_D, F17_D]
integer_return_registers: [X10, X11]
- floating_return_registers: [F10, F11]
+ floating_return_registers: [F10_D, F11_D]
preserved_mask: CSR_ILP32D_LP64D
stack_alignment_bytes: 16
stack_argument_alignment_bytes: 16
diff --git a/backend/lib/Target/RISCV/RISCVCallLowering.cpp b/backend/lib/Target/RISCV/RISCVCallLowering.cpp
index 60bf6f2..5da3fc8 100644
--- a/backend/lib/Target/RISCV/RISCVCallLowering.cpp
+++ b/backend/lib/Target/RISCV/RISCVCallLowering.cpp
@@ -70,6 +70,26 @@ constexpr std::uint32_t AllowedDirectCallFlags =
(*Semantics == FloatSemantics::IEEESingle || *Semantics == FloatSemantics::IEEEDouble);
}
+[[nodiscard]] Expected<PhysicalRegister> floatingRegisterView(PhysicalRegister DoubleView,
+ LLT Type) {
+ if (!isSupportedFloat(Type)) {
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "RISC-V floating-register view requires f32 or f64");
+ }
+ if (Type.scalarBitWidth() == 64)
+ return DoubleView;
+
+ constexpr std::uint32_t FirstDouble = static_cast<std::uint32_t>(PhysicalRegisterID::F0_D);
+ constexpr std::uint32_t LastDouble = static_cast<std::uint32_t>(PhysicalRegisterID::F31_D);
+ constexpr std::uint32_t FirstSingle = static_cast<std::uint32_t>(PhysicalRegisterID::F0_F);
+ const std::uint32_t Number = DoubleView.number();
+ if (Number < FirstDouble || Number > LastDouble) {
+ return makeUnexpected(ErrorCode::InternalError,
+ "RISC-V ABI floating register is not an FPR64 view");
+ }
+ return PhysicalRegister::create(FirstSingle + Number - FirstDouble);
+}
+
[[nodiscard]] bool requiresIntegerTransport(const ABIValue &Value) noexcept {
return !isSupportedFloat(Value.Type) || Value.Flags.has(ABIValueFlag::ByVal) ||
Value.Flags.has(ABIValueFlag::StructReturn) || Value.Flags.has(ABIValueFlag::Indirect);
@@ -301,14 +321,19 @@ assignArguments(std::span<const ABIValue> Values, std::size_t FixedArgumentCount
if (CanUsePreferredAggregate) {
for (std::size_t Fragment = 0; Fragment < GroupSize; ++Fragment) {
const ABIValue &Value = Values[Index + Fragment];
- Expected<CCAssignment> Assignment =
- requiresIntegerTransport(Value)
- ? registerAssignment(Value, Index + Fragment,
- Convention.IntegerArgumentRegisters[State.GPR++], *I64, false,
- false)
- : registerAssignment(Value, Index + Fragment,
- Convention.FloatingArgumentRegisters[State.FPR++], Value.Type,
- false, false);
+ Expected<CCAssignment> Assignment = makeUnexpected(
+ ErrorCode::InternalError, "RISC-V ABI argument assignment was not initialized");
+ if (requiresIntegerTransport(Value)) {
+ Assignment = registerAssignment(Value, Index + Fragment,
+ Convention.IntegerArgumentRegisters[State.GPR++], *I64,
+ false, false);
+ } else {
+ auto View =
+ floatingRegisterView(Convention.FloatingArgumentRegisters[State.FPR++], Value.Type);
+ if (!View)
+ return std::unexpected(View.error());
+ Assignment = registerAssignment(Value, Index + Fragment, *View, Value.Type, false, false);
+ }
if (!Assignment)
return std::unexpected(Assignment.error());
Result.Assignments.push_back(*Assignment);
@@ -413,8 +438,10 @@ assignReturns(std::span<const ABIValue> Values, bool RequireRegisters,
Expected<CCAssignment> Assignment = makeUnexpected(
ErrorCode::Unsupported, "RISC-V calling convention has no return register available");
if (UseFloatingRegister) {
- Assignment = registerAssignment(Value, Index, Convention.FloatingReturnRegisters[FPR++],
- Value.Type, false, false);
+ auto View = floatingRegisterView(Convention.FloatingReturnRegisters[FPR++], Value.Type);
+ if (!View)
+ return std::unexpected(View.error());
+ Assignment = registerAssignment(Value, Index, *View, Value.Type, false, false);
} else if (GPR < Convention.IntegerReturnRegisters.size()) {
Assignment = registerAssignment(Value, Index, Convention.IntegerReturnRegisters[GPR++], *I64,
false, isSupportedFloat(Value.Type));
diff --git a/backend/lib/Target/RISCV/RISCVFrameLowering.cpp b/backend/lib/Target/RISCV/RISCVFrameLowering.cpp
index 4ba5540..513788f 100644
--- a/backend/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/backend/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -320,15 +320,15 @@ struct CallFrameRequirement final {
[[nodiscard]] std::array<PhysicalRegisterID, 25> saveOrder() noexcept {
return {
- PhysicalRegisterID::X1, PhysicalRegisterID::X8, PhysicalRegisterID::X9,
- PhysicalRegisterID::X18, PhysicalRegisterID::X19, PhysicalRegisterID::X20,
- PhysicalRegisterID::X21, PhysicalRegisterID::X22, PhysicalRegisterID::X23,
- PhysicalRegisterID::X24, PhysicalRegisterID::X25, PhysicalRegisterID::X26,
- PhysicalRegisterID::X27, PhysicalRegisterID::F8, PhysicalRegisterID::F9,
- PhysicalRegisterID::F18, PhysicalRegisterID::F19, PhysicalRegisterID::F20,
- PhysicalRegisterID::F21, PhysicalRegisterID::F22, PhysicalRegisterID::F23,
- PhysicalRegisterID::F24, PhysicalRegisterID::F25, PhysicalRegisterID::F26,
- PhysicalRegisterID::F27,
+ PhysicalRegisterID::X1, PhysicalRegisterID::X8, PhysicalRegisterID::X9,
+ PhysicalRegisterID::X18, PhysicalRegisterID::X19, PhysicalRegisterID::X20,
+ PhysicalRegisterID::X21, PhysicalRegisterID::X22, PhysicalRegisterID::X23,
+ PhysicalRegisterID::X24, PhysicalRegisterID::X25, PhysicalRegisterID::X26,
+ PhysicalRegisterID::X27, PhysicalRegisterID::F8_D, PhysicalRegisterID::F9_D,
+ PhysicalRegisterID::F18_D, PhysicalRegisterID::F19_D, PhysicalRegisterID::F20_D,
+ PhysicalRegisterID::F21_D, PhysicalRegisterID::F22_D, PhysicalRegisterID::F23_D,
+ PhysicalRegisterID::F24_D, PhysicalRegisterID::F25_D, PhysicalRegisterID::F26_D,
+ PhysicalRegisterID::F27_D,
};
}
@@ -993,7 +993,7 @@ emitSavedRegisterCFI(MachineIRBuilder &Builder, const TargetDescription &Target,
[[nodiscard]] Expected<MachineInstr *>
emitCalleeSave(MachineIRBuilder &Builder, PhysicalRegister Reg, FrameIndex Index, bool Restore) {
- const bool IsFPR = Reg.number() >= static_cast<std::uint32_t>(PhysicalRegisterID::F0);
+ const bool IsFPR = Reg.number() >= static_cast<std::uint32_t>(PhysicalRegisterID::F0_D);
const InstructionOpcode OpcodeValue =
Restore ? (IsFPR ? InstructionOpcode::FLD : InstructionOpcode::LD)
: (IsFPR ? InstructionOpcode::FSD : InstructionOpcode::SD);
diff --git a/backend/lib/Target/RISCV/RISCVInstPrinter.cpp b/backend/lib/Target/RISCV/RISCVInstPrinter.cpp
index ba3e509..4699835 100644
--- a/backend/lib/Target/RISCV/RISCVInstPrinter.cpp
+++ b/backend/lib/Target/RISCV/RISCVInstPrinter.cpp
@@ -90,7 +90,10 @@ constexpr std::array LinearFormats{
return makeUnexpected(ErrorCode::AssemblyLoweringFailed,
"RISC-V MC instruction references an unknown register");
}
- return std::string(*Name);
+ std::string AssemblyName(*Name);
+ if (AssemblyName.ends_with("_f") || AssemblyName.ends_with("_d"))
+ AssemblyName.resize(AssemblyName.size() - 2);
+ return AssemblyName;
}
if (const std::int64_t *Immediate = Operand.immediateValue(); Immediate != nullptr)
return std::to_string(*Immediate);
diff --git a/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp b/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp
index aee09a9..055b67b 100644
--- a/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp
+++ b/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp
@@ -81,10 +81,14 @@ createStackMemoryOperand(MachineIRBuilder &Builder, FrameIndex StackSlot, Memory
PhysicalRegisterID::X25, PhysicalRegisterID::X26, PhysicalRegisterID::X27,
};
const std::array FPRs{
- PhysicalRegisterID::F8, PhysicalRegisterID::F9, PhysicalRegisterID::F18,
- PhysicalRegisterID::F19, PhysicalRegisterID::F20, PhysicalRegisterID::F21,
- PhysicalRegisterID::F22, PhysicalRegisterID::F23, PhysicalRegisterID::F24,
- PhysicalRegisterID::F25, PhysicalRegisterID::F26, PhysicalRegisterID::F27,
+ PhysicalRegisterID::F8_D, PhysicalRegisterID::F9_D, PhysicalRegisterID::F18_D,
+ PhysicalRegisterID::F19_D, PhysicalRegisterID::F20_D, PhysicalRegisterID::F21_D,
+ PhysicalRegisterID::F22_D, PhysicalRegisterID::F23_D, PhysicalRegisterID::F24_D,
+ PhysicalRegisterID::F25_D, PhysicalRegisterID::F26_D, PhysicalRegisterID::F27_D,
+ PhysicalRegisterID::F8_F, PhysicalRegisterID::F9_F, PhysicalRegisterID::F18_F,
+ PhysicalRegisterID::F19_F, PhysicalRegisterID::F20_F, PhysicalRegisterID::F21_F,
+ PhysicalRegisterID::F22_F, PhysicalRegisterID::F23_F, PhysicalRegisterID::F24_F,
+ PhysicalRegisterID::F25_F, PhysicalRegisterID::F26_F, PhysicalRegisterID::F27_F,
};
const auto Matches = [Number](PhysicalRegisterID ID) {
return Number == static_cast<std::uint32_t>(ID);
@@ -96,9 +100,12 @@ createStackMemoryOperand(MachineIRBuilder &Builder, FrameIndex StackSlot, Memory
const std::uint32_t Number = Reg.number();
const std::uint32_t X8 = static_cast<std::uint32_t>(PhysicalRegisterID::X8);
const std::uint32_t X15 = static_cast<std::uint32_t>(PhysicalRegisterID::X15);
- const std::uint32_t F8 = static_cast<std::uint32_t>(PhysicalRegisterID::F8);
- const std::uint32_t F15 = static_cast<std::uint32_t>(PhysicalRegisterID::F15);
- return (Number >= X8 && Number <= X15) || (Number >= F8 && Number <= F15);
+ const std::uint32_t F8D = static_cast<std::uint32_t>(PhysicalRegisterID::F8_D);
+ const std::uint32_t F15D = static_cast<std::uint32_t>(PhysicalRegisterID::F15_D);
+ const std::uint32_t F8F = static_cast<std::uint32_t>(PhysicalRegisterID::F8_F);
+ const std::uint32_t F15F = static_cast<std::uint32_t>(PhysicalRegisterID::F15_F);
+ return (Number >= X8 && Number <= X15) || (Number >= F8D && Number <= F15D) ||
+ (Number >= F8F && Number <= F15F);
}
class RISCVRegisterAllocationInfo final : public TargetRegisterAllocationInfo {
diff --git a/backend/lib/Target/RISCV/RISCVTarget.cpp b/backend/lib/Target/RISCV/RISCVTarget.cpp
index 299b5ab..090d0bc 100644
--- a/backend/lib/Target/RISCV/RISCVTarget.cpp
+++ b/backend/lib/Target/RISCV/RISCVTarget.cpp
@@ -63,6 +63,41 @@ physicalRegisters(std::initializer_list<PhysicalRegisterID> IDs) {
};
}
+[[nodiscard]] Expected<void> appendRISCVSubRegisterInfo(TargetRegisterInfoDesc &Description) {
+ constexpr SubRegIndex FPR32SubReg = SubRegIndex::fromValue(1);
+ constexpr std::uint32_t FirstDouble = static_cast<std::uint32_t>(PhysicalRegisterID::F0_D);
+ constexpr std::uint32_t LastDouble = static_cast<std::uint32_t>(PhysicalRegisterID::F31_D);
+ constexpr std::uint32_t FirstSingle = static_cast<std::uint32_t>(PhysicalRegisterID::F0_F);
+ constexpr std::uint32_t LastSingle = static_cast<std::uint32_t>(PhysicalRegisterID::F31_F);
+ static_assert(LastDouble - FirstDouble == 31);
+ static_assert(LastSingle - FirstSingle == 31);
+
+ Description.SubRegIndices.push_back({FPR32SubReg, "sub_32", LaneMask::fromRaw(1), 32, 0});
+ for (std::uint32_t Index = 0; Index != 32; ++Index) {
+ auto Double = PhysicalRegister::create(FirstDouble + Index);
+ auto Single = PhysicalRegister::create(FirstSingle + Index);
+ if (!Double || !Single)
+ return makeUnexpected(ErrorCode::InternalError, "RISC-V FPR view ID is invalid");
+ Description.PhysicalSubRegisters.push_back({*Double, FPR32SubReg, *Single});
+ }
+
+ const auto AddClassMapping = [&](RegisterClass Super, RegisterClass Sub) -> Expected<void> {
+ const RegisterClassID SuperID = RegisterClassID::fromValue(static_cast<std::uint32_t>(Super));
+ const RegisterClassID SubID = RegisterClassID::fromValue(static_cast<std::uint32_t>(Sub));
+ const auto Position =
+ std::ranges::find(Description.RegisterClasses, SuperID, &RegisterClassDesc::ID);
+ if (Position == Description.RegisterClasses.end()) {
+ return makeUnexpected(ErrorCode::InternalError, "RISC-V FPR super-register class is missing");
+ }
+ Position->SupportedSubRegs.push_back(FPR32SubReg);
+ Description.SubRegClassMappings.push_back({SuperID, FPR32SubReg, SubID});
+ return {};
+ };
+ if (auto Result = AddClassMapping(RegisterClass::FPR64, RegisterClass::FPR32); !Result)
+ return Result;
+ return AddClassMapping(RegisterClass::FPR64C, RegisterClass::FPR32C);
+}
+
[[nodiscard]] std::shared_ptr<const RegisterMask>
makePreservedMask(std::initializer_list<PhysicalRegisterID> Preserved) {
std::vector<std::uint64_t> Words;
@@ -87,6 +122,8 @@ Expected<PhysicalRegister> physicalRegister(PhysicalRegisterID ID) {
Expected<TargetRegisterInfo> createRegisterInfo() {
TargetRegisterInfoDesc Description;
appendGeneratedRegisterInfo(Description);
+ if (auto Result = appendRISCVSubRegisterInfo(Description); !Result)
+ return std::unexpected(Result.error());
return TargetRegisterInfo::create(std::move(Description));
}
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<std::int64_t>(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<std::uint32_t>(rcc::riscv::RegisterClass::GPR)));
+ const auto IsClass = [Class](rcc::riscv::RegisterClass Candidate) {
+ return Class.value() == static_cast<std::uint32_t>(Candidate);
+ };
+ std::uint32_t FirstRegister = 1;
+ if (IsClass(rcc::riscv::RegisterClass::FPR32) || IsClass(rcc::riscv::RegisterClass::FPR32C)) {
+ FirstRegister = static_cast<std::uint32_t>(rcc::riscv::PhysicalRegisterID::F0_F);
+ } else if (IsClass(rcc::riscv::RegisterClass::FPR64) ||
+ IsClass(rcc::riscv::RegisterClass::FPR64C)) {
+ FirstRegister = static_cast<std::uint32_t>(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<rcc::mc::MCInst>
-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<rcc::riscv::InstructionOpcode>(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<rcc::riscv::EncodingCategory>(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);