886 lines · plain
1//===-- RISCVRegisterInfo.td - RISC-V Register defs --------*- tablegen -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9//===----------------------------------------------------------------------===//10// Declarations that describe the RISC-V register files11//===----------------------------------------------------------------------===//12 13let Namespace = "RISCV" in {14class RISCVReg<bits<5> Enc, string n, list<string> alt = []> : Register<n> {15 let HWEncoding{4-0} = Enc;16 let AltNames = alt;17}18 19class RISCVRegWithSubRegs<bits<5> Enc, string n, list<Register> subregs,20 list<string> alt = []>21 : RegisterWithSubRegs<n, subregs> {22 let HWEncoding{4-0} = Enc;23 let AltNames = alt;24}25 26class RISCVReg16<bits<5> Enc, string n, list<string> alt = []> : Register<n> {27 let HWEncoding{4-0} = Enc;28 let AltNames = alt;29}30 31def sub_16 : SubRegIndex<16>;32class RISCVReg32<RISCVReg16 subreg>33 : RISCVRegWithSubRegs<subreg.HWEncoding{4-0}, subreg.AsmName, [subreg],34 subreg.AltNames> {35 let SubRegIndices = [sub_16];36}37 38// Because RISCVReg64 register have AsmName and AltNames that alias with their39// 16/32-bit sub-register, RISCVAsmParser will need to coerce a register number40// from a RISCVReg16/RISCVReg32 to the equivalent RISCVReg64 when appropriate.41def sub_32 : SubRegIndex<32>;42class RISCVReg64<RISCVReg32 subreg>43 : RISCVRegWithSubRegs<subreg.HWEncoding{4-0}, subreg.AsmName, [subreg],44 subreg.AltNames> {45 let SubRegIndices = [sub_32];46}47 48def sub_64 : SubRegIndex<64>;49class RISCVReg128<RISCVReg64 subreg>50 : RISCVRegWithSubRegs<subreg.HWEncoding{4-0}, subreg.AsmName, [subreg],51 subreg.AltNames> {52 let SubRegIndices = [sub_64];53}54 55let FallbackRegAltNameIndex = NoRegAltName in56def ABIRegAltName : RegAltNameIndex;57 58def sub_vrm4_0 : SubRegIndex<256>;59def sub_vrm4_1 : SubRegIndex<256, 256>;60def sub_vrm2_0 : SubRegIndex<128>;61def sub_vrm2_1 : SubRegIndex<128, 128>;62def sub_vrm2_2 : ComposedSubRegIndex<sub_vrm4_1, sub_vrm2_0>;63def sub_vrm2_3 : ComposedSubRegIndex<sub_vrm4_1, sub_vrm2_1>;64def sub_vrm1_0 : SubRegIndex<64>;65def sub_vrm1_1 : SubRegIndex<64, 64>;66def sub_vrm1_2 : ComposedSubRegIndex<sub_vrm2_1, sub_vrm1_0>;67def sub_vrm1_3 : ComposedSubRegIndex<sub_vrm2_1, sub_vrm1_1>;68def sub_vrm1_4 : ComposedSubRegIndex<sub_vrm2_2, sub_vrm1_0>;69def sub_vrm1_5 : ComposedSubRegIndex<sub_vrm2_2, sub_vrm1_1>;70def sub_vrm1_6 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_0>;71def sub_vrm1_7 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_1>;72 73// GPR sizes change with HwMode.74def sub_gpr_even : SubRegIndex<32> {75 let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64],76 [SubRegRange<32>, SubRegRange<64>]>;77}78def sub_gpr_odd : SubRegIndex<32, 32> {79 let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64],80 [SubRegRange<32, 32>, SubRegRange<64, 64>]>;81}82} // Namespace = "RISCV"83 84//===----------------------------------------------------------------------===//85// General Purpose Registers (aka Integer Registers)86//===----------------------------------------------------------------------===//87 88// CostPerUse is set higher for registers that may not be compressible as they89// are not part of GPRC, the most restrictive register class used by the90// compressed instruction set. This will influence the greedy register91// allocator to reduce the use of registers that can't be encoded in 16 bit92// instructions.93 94let RegAltNameIndices = [ABIRegAltName] in {95 // 16-bit sub-registers for use by Zhinx. Having a 16-bit sub-register reduces96 // the spill size for these operations.97 let isConstant = true in98 def X0_H : RISCVReg<0, "x0", ["zero"]>;99 let CostPerUse = [0, 1] in {100 def X1_H : RISCVReg<1, "x1", ["ra"]>;101 def X2_H : RISCVReg<2, "x2", ["sp"]>;102 def X3_H : RISCVReg<3, "x3", ["gp"]>;103 def X4_H : RISCVReg<4, "x4", ["tp"]>;104 def X5_H : RISCVReg<5, "x5", ["t0"]>;105 def X6_H : RISCVReg<6, "x6", ["t1"]>;106 def X7_H : RISCVReg<7, "x7", ["t2"]>;107 }108 def X8_H : RISCVReg<8, "x8", ["s0", "fp"]>;109 def X9_H : RISCVReg<9, "x9", ["s1"]>;110 def X10_H : RISCVReg<10,"x10", ["a0"]>;111 def X11_H : RISCVReg<11,"x11", ["a1"]>;112 def X12_H : RISCVReg<12,"x12", ["a2"]>;113 def X13_H : RISCVReg<13,"x13", ["a3"]>;114 def X14_H : RISCVReg<14,"x14", ["a4"]>;115 def X15_H : RISCVReg<15,"x15", ["a5"]>;116 let CostPerUse = [0, 1] in {117 def X16_H : RISCVReg<16,"x16", ["a6"]>;118 def X17_H : RISCVReg<17,"x17", ["a7"]>;119 def X18_H : RISCVReg<18,"x18", ["s2"]>;120 def X19_H : RISCVReg<19,"x19", ["s3"]>;121 def X20_H : RISCVReg<20,"x20", ["s4"]>;122 def X21_H : RISCVReg<21,"x21", ["s5"]>;123 def X22_H : RISCVReg<22,"x22", ["s6"]>;124 def X23_H : RISCVReg<23,"x23", ["s7"]>;125 def X24_H : RISCVReg<24,"x24", ["s8"]>;126 def X25_H : RISCVReg<25,"x25", ["s9"]>;127 def X26_H : RISCVReg<26,"x26", ["s10"]>;128 def X27_H : RISCVReg<27,"x27", ["s11"]>;129 def X28_H : RISCVReg<28,"x28", ["t3"]>;130 def X29_H : RISCVReg<29,"x29", ["t4"]>;131 def X30_H : RISCVReg<30,"x30", ["t5"]>;132 def X31_H : RISCVReg<31,"x31", ["t6"]>;133 }134 135 let SubRegIndices = [sub_16] in {136 let isConstant = true in137 def X0_W : RISCVRegWithSubRegs<0, "x0", [X0_H], ["zero"]>;138 let CostPerUse = [0, 1] in {139 def X1_W : RISCVRegWithSubRegs<1, "x1", [X1_H], ["ra"]>;140 def X2_W : RISCVRegWithSubRegs<2, "x2", [X2_H], ["sp"]>;141 def X3_W : RISCVRegWithSubRegs<3, "x3", [X3_H], ["gp"]>;142 def X4_W : RISCVRegWithSubRegs<4, "x4", [X4_H], ["tp"]>;143 def X5_W : RISCVRegWithSubRegs<5, "x5", [X5_H], ["t0"]>;144 def X6_W : RISCVRegWithSubRegs<6, "x6", [X6_H], ["t1"]>;145 def X7_W : RISCVRegWithSubRegs<7, "x7", [X7_H], ["t2"]>;146 }147 def X8_W : RISCVRegWithSubRegs<8, "x8", [X8_H], ["s0", "fp"]>;148 def X9_W : RISCVRegWithSubRegs<9, "x9", [X9_H], ["s1"]>;149 def X10_W : RISCVRegWithSubRegs<10,"x10", [X10_H], ["a0"]>;150 def X11_W : RISCVRegWithSubRegs<11,"x11", [X11_H], ["a1"]>;151 def X12_W : RISCVRegWithSubRegs<12,"x12", [X12_H], ["a2"]>;152 def X13_W : RISCVRegWithSubRegs<13,"x13", [X13_H], ["a3"]>;153 def X14_W : RISCVRegWithSubRegs<14,"x14", [X14_H], ["a4"]>;154 def X15_W : RISCVRegWithSubRegs<15,"x15", [X15_H], ["a5"]>;155 let CostPerUse = [0, 1] in {156 def X16_W : RISCVRegWithSubRegs<16,"x16", [X16_H], ["a6"]>;157 def X17_W : RISCVRegWithSubRegs<17,"x17", [X17_H], ["a7"]>;158 def X18_W : RISCVRegWithSubRegs<18,"x18", [X18_H], ["s2"]>;159 def X19_W : RISCVRegWithSubRegs<19,"x19", [X19_H], ["s3"]>;160 def X20_W : RISCVRegWithSubRegs<20,"x20", [X20_H], ["s4"]>;161 def X21_W : RISCVRegWithSubRegs<21,"x21", [X21_H], ["s5"]>;162 def X22_W : RISCVRegWithSubRegs<22,"x22", [X22_H], ["s6"]>;163 def X23_W : RISCVRegWithSubRegs<23,"x23", [X23_H], ["s7"]>;164 def X24_W : RISCVRegWithSubRegs<24,"x24", [X24_H], ["s8"]>;165 def X25_W : RISCVRegWithSubRegs<25,"x25", [X25_H], ["s9"]>;166 def X26_W : RISCVRegWithSubRegs<26,"x26", [X26_H], ["s10"]>;167 def X27_W : RISCVRegWithSubRegs<27,"x27", [X27_H], ["s11"]>;168 def X28_W : RISCVRegWithSubRegs<28,"x28", [X28_H], ["t3"]>;169 def X29_W : RISCVRegWithSubRegs<29,"x29", [X29_H], ["t4"]>;170 def X30_W : RISCVRegWithSubRegs<30,"x30", [X30_H], ["t5"]>;171 def X31_W : RISCVRegWithSubRegs<31,"x31", [X31_H], ["t6"]>;172 }173 }174 175 let SubRegIndices = [sub_32] in {176 let isConstant = true in177 def X0 : RISCVRegWithSubRegs<0, "x0", [X0_W], ["zero"]>, DwarfRegNum<[0]>;178 let CostPerUse = [0, 1] in {179 def X1 : RISCVRegWithSubRegs<1, "x1", [X1_W], ["ra"]>, DwarfRegNum<[1]>;180 def X2 : RISCVRegWithSubRegs<2, "x2", [X2_W], ["sp"]>, DwarfRegNum<[2]>;181 def X3 : RISCVRegWithSubRegs<3, "x3", [X3_W], ["gp"]>, DwarfRegNum<[3]>;182 def X4 : RISCVRegWithSubRegs<4, "x4", [X4_W], ["tp"]>, DwarfRegNum<[4]>;183 def X5 : RISCVRegWithSubRegs<5, "x5", [X5_W], ["t0"]>, DwarfRegNum<[5]>;184 def X6 : RISCVRegWithSubRegs<6, "x6", [X6_W], ["t1"]>, DwarfRegNum<[6]>;185 def X7 : RISCVRegWithSubRegs<7, "x7", [X7_W], ["t2"]>, DwarfRegNum<[7]>;186 }187 def X8 : RISCVRegWithSubRegs<8, "x8", [X8_W], ["s0", "fp"]>, DwarfRegNum<[8]>;188 def X9 : RISCVRegWithSubRegs<9, "x9", [X9_W], ["s1"]>, DwarfRegNum<[9]>;189 def X10 : RISCVRegWithSubRegs<10,"x10", [X10_W], ["a0"]>, DwarfRegNum<[10]>;190 def X11 : RISCVRegWithSubRegs<11,"x11", [X11_W], ["a1"]>, DwarfRegNum<[11]>;191 def X12 : RISCVRegWithSubRegs<12,"x12", [X12_W], ["a2"]>, DwarfRegNum<[12]>;192 def X13 : RISCVRegWithSubRegs<13,"x13", [X13_W], ["a3"]>, DwarfRegNum<[13]>;193 def X14 : RISCVRegWithSubRegs<14,"x14", [X14_W], ["a4"]>, DwarfRegNum<[14]>;194 def X15 : RISCVRegWithSubRegs<15,"x15", [X15_W], ["a5"]>, DwarfRegNum<[15]>;195 let CostPerUse = [0, 1] in {196 def X16 : RISCVRegWithSubRegs<16,"x16", [X16_W], ["a6"]>, DwarfRegNum<[16]>;197 def X17 : RISCVRegWithSubRegs<17,"x17", [X17_W], ["a7"]>, DwarfRegNum<[17]>;198 def X18 : RISCVRegWithSubRegs<18,"x18", [X18_W], ["s2"]>, DwarfRegNum<[18]>;199 def X19 : RISCVRegWithSubRegs<19,"x19", [X19_W], ["s3"]>, DwarfRegNum<[19]>;200 def X20 : RISCVRegWithSubRegs<20,"x20", [X20_W], ["s4"]>, DwarfRegNum<[20]>;201 def X21 : RISCVRegWithSubRegs<21,"x21", [X21_W], ["s5"]>, DwarfRegNum<[21]>;202 def X22 : RISCVRegWithSubRegs<22,"x22", [X22_W], ["s6"]>, DwarfRegNum<[22]>;203 def X23 : RISCVRegWithSubRegs<23,"x23", [X23_W], ["s7"]>, DwarfRegNum<[23]>;204 def X24 : RISCVRegWithSubRegs<24,"x24", [X24_W], ["s8"]>, DwarfRegNum<[24]>;205 def X25 : RISCVRegWithSubRegs<25,"x25", [X25_W], ["s9"]>, DwarfRegNum<[25]>;206 def X26 : RISCVRegWithSubRegs<26,"x26", [X26_W], ["s10"]>, DwarfRegNum<[26]>;207 def X27 : RISCVRegWithSubRegs<27,"x27", [X27_W], ["s11"]>, DwarfRegNum<[27]>;208 def X28 : RISCVRegWithSubRegs<28,"x28", [X28_W], ["t3"]>, DwarfRegNum<[28]>;209 def X29 : RISCVRegWithSubRegs<29,"x29", [X29_W], ["t4"]>, DwarfRegNum<[29]>;210 def X30 : RISCVRegWithSubRegs<30,"x30", [X30_W], ["t5"]>, DwarfRegNum<[30]>;211 def X31 : RISCVRegWithSubRegs<31,"x31", [X31_W], ["t6"]>, DwarfRegNum<[31]>;212 }213 }214}215 216def XLenVT : ValueTypeByHwMode<[RV32, RV64],217 [i32, i64]>;218defvar XLenPairVT = untyped;219 220// Allow f64 in GPR for ZDINX on RV64.221def XLenFVT : ValueTypeByHwMode<[RV64],222 [f64]>;223def XLenPairFVT : ValueTypeByHwMode<[RV32],224 [f64]>;225 226// P extension227def XLenVecI8VT : ValueTypeByHwMode<[RV32, RV64],228 [v4i8, v8i8]>;229def XLenVecI16VT : ValueTypeByHwMode<[RV32, RV64],230 [v2i16, v4i16]>;231def XLenVecI32VT : ValueTypeByHwMode<[RV64],232 [v2i32]>;233def XLenRI : RegInfoByHwMode<234 [RV32, RV64],235 [RegInfo<32,32,32>, RegInfo<64,64,64>]>;236 237class RISCVRegisterClass<list<ValueType> regTypes, int align, dag regList>238 : RegisterClass<"RISCV", regTypes, align, regList> {239 bit IsVRegClass = 0;240 int VLMul = 1;241 int NF = 1;242 243 let TSFlags{0} = IsVRegClass;244 let TSFlags{2-1} = !logtwo(VLMul);245 let TSFlags{5-3} = !sub(NF, 1);246}247 248class GPRRegisterClass<dag regList>249 : RISCVRegisterClass<[XLenVT, XLenFVT,250 // P extension packed vector types:251 XLenVecI8VT, XLenVecI16VT, XLenVecI32VT], 32, regList> {252 let RegInfos = XLenRI;253}254 255// The order of registers represents the preferred allocation sequence.256// Registers are listed in the order caller-save, callee-save, specials.257def GPR : GPRRegisterClass<(add (sequence "X%u", 10, 17),258 (sequence "X%u", 5, 7),259 (sequence "X%u", 28, 31),260 (sequence "X%u", 8, 9),261 (sequence "X%u", 18, 27),262 (sequence "X%u", 0, 4))>;263 264def GPRX0 : GPRRegisterClass<(add X0)>;265 266def GPRX1 : GPRRegisterClass<(add X1)> {267 let DiagnosticType = "InvalidRegClassGPRX1";268 let DiagnosticString = "register must be ra (x1)";269}270 271def GPRX5 : GPRRegisterClass<(add X5)> {272 let DiagnosticType = "InvalidRegClassGPRX5";273 let DiagnosticString = "register must be t0 (x5)";274}275 276def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)> {277 let DiagnosticType = "InvalidRegClassGPRNoX0";278 let DiagnosticString = "register must be a GPR excluding zero (x0)";279}280 281def GPRNoX2 : GPRRegisterClass<(sub GPR, X2)> {282 let DiagnosticType = "InvalidRegClassGPRNoX2";283 let DiagnosticString = "register must be a GPR excluding sp (x2)";284}285 286def GPRNoX0X2 : GPRRegisterClass<(sub GPR, X0, X2)> {287 let DiagnosticType = "InvalidRegClassGPRNoX0X2";288 let DiagnosticString = "register must be a GPR excluding zero (x0) and sp (x2)";289}290 291def GPRX7 : GPRRegisterClass<(add X7)>;292 293// Don't use X1 or X5 for JALR since that is a hint to pop the return address294// stack on some microarchitectures. Also remove the reserved registers X0, X2,295// X3, and X4 as it reduces the number of register classes that get synthesized296// by tablegen.297def GPRJALR : GPRRegisterClass<(sub GPR, (sequence "X%u", 0, 5))>;298 299def GPRJALRNonX7 : GPRRegisterClass<(sub GPRJALR, X7)>;300 301def GPRC : GPRRegisterClass<(add (sequence "X%u", 10, 15),302 (sequence "X%u", 8, 9))>;303 304// For indirect tail calls, we can't use callee-saved registers, as they are305// restored to the saved value before the tail call, which would clobber a call306// address. We shouldn't use x5 since that is a hint for to pop the return307// address stack on some microarchitectures.308def GPRTC : GPRRegisterClass<(add (sequence "X%u", 6, 7),309 (sequence "X%u", 10, 17),310 (sequence "X%u", 28, 31))>;311def GPRTCNonX7 : GPRRegisterClass<(sub GPRTC, X7)>;312 313def SP : GPRRegisterClass<(add X2)> {314 let DiagnosticType = "InvalidRegClassSP";315 let DiagnosticString = "register must be sp (x2)";316}317 318// Saved Registers from s0 to s7, for C.MVA01S07 instruction in Zcmp extension319def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9),320 (sequence "X%u", 18, 23))>;321 322def GPRX1X5 : GPRRegisterClass<(add X1, X5)> {323 let DiagnosticType = "InvalidRegClassGPRX1X5";324 let DiagnosticString = "register must be ra or t0 (x1 or x5)";325}326 327def GPRNoX31 : GPRRegisterClass<(sub GPR, X31)> {328 let DiagnosticType = "InvalidRegClassGPRX31";329 let DiagnosticString = "register must be a GPR excluding t6 (x31)";330}331 332//===----------------------------------------------------------------------===//333// Even-Odd GPR Pairs334//===----------------------------------------------------------------------===//335 336def XLenPairRI : RegInfoByHwMode<337 [RV32, RV64],338 [RegInfo<64, 64, 32>, RegInfo<128, 128, 64>]>;339 340// Dummy zero register for use in the register pair containing X0 (as X1 is341// not read to or written when the X0 register pair is used).342def DUMMY_REG_PAIR_WITH_X0 : RISCVReg<0, "0">;343 344// Must add DUMMY_REG_PAIR_WITH_X0 to a separate register class to prevent the345// register's existence from changing codegen (due to the regPressureSetLimit346// for the GPR register class being altered).347def GPRAll : GPRRegisterClass<(add GPR, DUMMY_REG_PAIR_WITH_X0)>;348 349let RegAltNameIndices = [ABIRegAltName] in {350 def X0_Pair : RISCVRegWithSubRegs<0, X0.AsmName,351 [X0, DUMMY_REG_PAIR_WITH_X0],352 X0.AltNames> {353 let SubRegIndices = [sub_gpr_even, sub_gpr_odd];354 let CoveredBySubRegs = 1;355 }356 foreach I = 1-15 in {357 defvar Index = !shl(I, 1);358 defvar IndexP1 = !add(Index, 1);359 defvar Reg = !cast<Register>("X"#Index);360 defvar RegP1 = !cast<Register>("X"#IndexP1);361 def "X" # Index #"_X" # IndexP1 : RISCVRegWithSubRegs<Index,362 Reg.AsmName,363 [Reg, RegP1],364 Reg.AltNames> {365 let SubRegIndices = [sub_gpr_even, sub_gpr_odd];366 let CoveredBySubRegs = 1;367 }368 }369}370 371let RegInfos = XLenPairRI, CopyCost = 2 in {372def GPRPair : RISCVRegisterClass<[XLenPairVT, XLenPairFVT], 64, (add373 X10_X11, X12_X13, X14_X15, X16_X17,374 X6_X7,375 X28_X29, X30_X31,376 X8_X9,377 X18_X19, X20_X21, X22_X23, X24_X25, X26_X27,378 X0_Pair, X2_X3, X4_X5379)>;380 381def GPRPairNoX0 : RISCVRegisterClass<[XLenPairVT, XLenPairFVT], 64, (sub GPRPair, X0_Pair)>;382 383def GPRPairC : RISCVRegisterClass<[XLenPairVT, XLenPairFVT], 64, (add384 X10_X11, X12_X13, X14_X15, X8_X9385)>;386} // let RegInfos = XLenPairRI, CopyCost = 2387 388//===----------------------------------------------------------------------===//389// Floating Point registers390//===----------------------------------------------------------------------===//391 392let RegAltNameIndices = [ABIRegAltName] in {393 def F0_H : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>;394 def F1_H : RISCVReg16<1, "f1", ["ft1"]>, DwarfRegNum<[33]>;395 def F2_H : RISCVReg16<2, "f2", ["ft2"]>, DwarfRegNum<[34]>;396 def F3_H : RISCVReg16<3, "f3", ["ft3"]>, DwarfRegNum<[35]>;397 def F4_H : RISCVReg16<4, "f4", ["ft4"]>, DwarfRegNum<[36]>;398 def F5_H : RISCVReg16<5, "f5", ["ft5"]>, DwarfRegNum<[37]>;399 def F6_H : RISCVReg16<6, "f6", ["ft6"]>, DwarfRegNum<[38]>;400 def F7_H : RISCVReg16<7, "f7", ["ft7"]>, DwarfRegNum<[39]>;401 def F8_H : RISCVReg16<8, "f8", ["fs0"]>, DwarfRegNum<[40]>;402 def F9_H : RISCVReg16<9, "f9", ["fs1"]>, DwarfRegNum<[41]>;403 def F10_H : RISCVReg16<10,"f10", ["fa0"]>, DwarfRegNum<[42]>;404 def F11_H : RISCVReg16<11,"f11", ["fa1"]>, DwarfRegNum<[43]>;405 def F12_H : RISCVReg16<12,"f12", ["fa2"]>, DwarfRegNum<[44]>;406 def F13_H : RISCVReg16<13,"f13", ["fa3"]>, DwarfRegNum<[45]>;407 def F14_H : RISCVReg16<14,"f14", ["fa4"]>, DwarfRegNum<[46]>;408 def F15_H : RISCVReg16<15,"f15", ["fa5"]>, DwarfRegNum<[47]>;409 def F16_H : RISCVReg16<16,"f16", ["fa6"]>, DwarfRegNum<[48]>;410 def F17_H : RISCVReg16<17,"f17", ["fa7"]>, DwarfRegNum<[49]>;411 def F18_H : RISCVReg16<18,"f18", ["fs2"]>, DwarfRegNum<[50]>;412 def F19_H : RISCVReg16<19,"f19", ["fs3"]>, DwarfRegNum<[51]>;413 def F20_H : RISCVReg16<20,"f20", ["fs4"]>, DwarfRegNum<[52]>;414 def F21_H : RISCVReg16<21,"f21", ["fs5"]>, DwarfRegNum<[53]>;415 def F22_H : RISCVReg16<22,"f22", ["fs6"]>, DwarfRegNum<[54]>;416 def F23_H : RISCVReg16<23,"f23", ["fs7"]>, DwarfRegNum<[55]>;417 def F24_H : RISCVReg16<24,"f24", ["fs8"]>, DwarfRegNum<[56]>;418 def F25_H : RISCVReg16<25,"f25", ["fs9"]>, DwarfRegNum<[57]>;419 def F26_H : RISCVReg16<26,"f26", ["fs10"]>, DwarfRegNum<[58]>;420 def F27_H : RISCVReg16<27,"f27", ["fs11"]>, DwarfRegNum<[59]>;421 def F28_H : RISCVReg16<28,"f28", ["ft8"]>, DwarfRegNum<[60]>;422 def F29_H : RISCVReg16<29,"f29", ["ft9"]>, DwarfRegNum<[61]>;423 def F30_H : RISCVReg16<30,"f30", ["ft10"]>, DwarfRegNum<[62]>;424 def F31_H : RISCVReg16<31,"f31", ["ft11"]>, DwarfRegNum<[63]>;425 426 foreach Index = 0-31 in {427 def F#Index#_F : RISCVReg32<!cast<RISCVReg16>("F"#Index#"_H")>,428 DwarfRegAlias<!cast<Register>("F"#Index#"_H")>;429 }430 431 foreach Index = 0-31 in {432 def F#Index#_D : RISCVReg64<!cast<RISCVReg32>("F"#Index#"_F")>,433 DwarfRegAlias<!cast<Register>("F"#Index#"_H")>;434 }435 436 foreach Index = 0-31 in {437 def F#Index#_Q : RISCVReg128<!cast<RISCVReg64>("F"#Index#"_D")>,438 DwarfRegAlias<!cast<Register>("F"#Index#"_H")>;439 }440}441 442// The order of registers represents the preferred allocation sequence,443// meaning caller-save regs are listed before callee-save.444// We start by allocating argument registers in reverse order since they are445// compressible.446def FPR16 : RISCVRegisterClass<[f16, bf16], 16, (add447 (sequence "F%u_H", 15, 10), // fa5-fa0448 (sequence "F%u_H", 0, 7), // ft0-f7449 (sequence "F%u_H", 16, 17), // fa6-fa7450 (sequence "F%u_H", 28, 31), // ft8-ft11451 (sequence "F%u_H", 8, 9), // fs0-fs1452 (sequence "F%u_H", 18, 27) // fs2-fs11453)>;454 455def FPR16C : RISCVRegisterClass<[f16, bf16], 16, (add456 (sequence "F%u_H", 15, 10),457 (sequence "F%u_H", 8, 9)458)>;459 460def FPR32 : RISCVRegisterClass<[f32], 32, (add461 (sequence "F%u_F", 15, 10),462 (sequence "F%u_F", 0, 7),463 (sequence "F%u_F", 16, 17),464 (sequence "F%u_F", 28, 31),465 (sequence "F%u_F", 8, 9),466 (sequence "F%u_F", 18, 27)467)>;468 469def FPR32C : RISCVRegisterClass<[f32], 32, (add470 (sequence "F%u_F", 15, 10),471 (sequence "F%u_F", 8, 9)472)>;473 474// The order of registers represents the preferred allocation sequence,475// meaning caller-save regs are listed before callee-save.476def FPR64 : RISCVRegisterClass<[f64], 64, (add477 (sequence "F%u_D", 15, 10),478 (sequence "F%u_D", 0, 7),479 (sequence "F%u_D", 16, 17),480 (sequence "F%u_D", 28, 31),481 (sequence "F%u_D", 8, 9),482 (sequence "F%u_D", 18, 27)483)>;484 485def FPR64C : RISCVRegisterClass<[f64], 64, (add486 (sequence "F%u_D", 15, 10),487 (sequence "F%u_D", 8, 9)488)>;489 490def FPR128 : RISCVRegisterClass<[f128], 128, (add491 (sequence "F%u_Q", 15, 10),492 (sequence "F%u_Q", 0, 7),493 (sequence "F%u_Q", 16, 17),494 (sequence "F%u_Q", 28, 31),495 (sequence "F%u_Q", 8, 9),496 (sequence "F%u_Q", 18, 27)497)>;498 499//===----------------------------------------------------------------------===//500// GPR Classes for "H/F/D in X"501//===----------------------------------------------------------------------===//502 503// 16-bit GPR sub-register class used by Zhinx instructions.504def GPRF16 : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 17),505 (sequence "X%u_H", 5, 7),506 (sequence "X%u_H", 28, 31),507 (sequence "X%u_H", 8, 9),508 (sequence "X%u_H", 18, 27),509 (sequence "X%u_H", 0, 4))>;510def GPRF16C : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 15),511 (sequence "X%u_H", 8, 9))>;512def GPRF16NoX0 : RISCVRegisterClass<[f16], 16, (sub GPRF16, X0_H)>;513 514def GPRF32 : RISCVRegisterClass<[f32], 32, (add (sequence "X%u_W", 10, 17),515 (sequence "X%u_W", 5, 7),516 (sequence "X%u_W", 28, 31),517 (sequence "X%u_W", 8, 9),518 (sequence "X%u_W", 18, 27),519 (sequence "X%u_W", 0, 4))>;520def GPRF32C : RISCVRegisterClass<[f32], 32, (add (sequence "X%u_W", 10, 15),521 (sequence "X%u_W", 8, 9))>;522def GPRF32NoX0 : RISCVRegisterClass<[f32], 32, (sub GPRF32, X0_W)>;523 524//===----------------------------------------------------------------------===//525// Vector type mapping to LLVM types.526//===----------------------------------------------------------------------===//527 528// The V vector extension requires that VLEN >= 128 and <= 65536.529// Additionally, the only supported ELEN values are 32 and 64,530// thus `vscale` can be defined as VLEN/64,531// allowing the same types with either ELEN value.532//533// MF8 MF4 MF2 M1 M2 M4 M8534// i64* N/A N/A N/A nxv1i64 nxv2i64 nxv4i64 nxv8i64535// i32 N/A N/A nxv1i32 nxv2i32 nxv4i32 nxv8i32 nxv16i32536// i16 N/A nxv1i16 nxv2i16 nxv4i16 nxv8i16 nxv16i16 nxv32i16537// i8 nxv1i8 nxv2i8 nxv4i8 nxv8i8 nxv16i8 nxv32i8 nxv64i8538// double* N/A N/A N/A nxv1f64 nxv2f64 nxv4f64 nxv8f64539// float N/A N/A nxv1f32 nxv2f32 nxv4f32 nxv8f32 nxv16f32540// half N/A nxv1f16 nxv2f16 nxv4f16 nxv8f16 nxv16f16 nxv32f16541// * ELEN=64542 543defvar vint8mf8_t = nxv1i8;544defvar vint8mf4_t = nxv2i8;545defvar vint8mf2_t = nxv4i8;546defvar vint8m1_t = nxv8i8;547defvar vint8m2_t = nxv16i8;548defvar vint8m4_t = nxv32i8;549defvar vint8m8_t = nxv64i8;550 551defvar vint16mf4_t = nxv1i16;552defvar vint16mf2_t = nxv2i16;553defvar vint16m1_t = nxv4i16;554defvar vint16m2_t = nxv8i16;555defvar vint16m4_t = nxv16i16;556defvar vint16m8_t = nxv32i16;557 558defvar vint32mf2_t = nxv1i32;559defvar vint32m1_t = nxv2i32;560defvar vint32m2_t = nxv4i32;561defvar vint32m4_t = nxv8i32;562defvar vint32m8_t = nxv16i32;563 564defvar vint64m1_t = nxv1i64;565defvar vint64m2_t = nxv2i64;566defvar vint64m4_t = nxv4i64;567defvar vint64m8_t = nxv8i64;568 569defvar vfloat16mf4_t = nxv1f16;570defvar vfloat16mf2_t = nxv2f16;571defvar vfloat16m1_t = nxv4f16;572defvar vfloat16m2_t = nxv8f16;573defvar vfloat16m4_t = nxv16f16;574defvar vfloat16m8_t = nxv32f16;575 576defvar vbfloat16mf4_t = nxv1bf16;577defvar vbfloat16mf2_t = nxv2bf16;578defvar vbfloat16m1_t = nxv4bf16;579defvar vbfloat16m2_t = nxv8bf16;580defvar vbfloat16m4_t = nxv16bf16;581defvar vbfloat16m8_t = nxv32bf16;582 583defvar vfloat32mf2_t = nxv1f32;584defvar vfloat32m1_t = nxv2f32;585defvar vfloat32m2_t = nxv4f32;586defvar vfloat32m4_t = nxv8f32;587defvar vfloat32m8_t = nxv16f32;588 589defvar vfloat64m1_t = nxv1f64;590defvar vfloat64m2_t = nxv2f64;591defvar vfloat64m4_t = nxv4f64;592defvar vfloat64m8_t = nxv8f64;593 594defvar vbool1_t = nxv64i1;595defvar vbool2_t = nxv32i1;596defvar vbool4_t = nxv16i1;597defvar vbool8_t = nxv8i1;598defvar vbool16_t = nxv4i1;599defvar vbool32_t = nxv2i1;600defvar vbool64_t = nxv1i1;601 602// There is no need to define register classes for fractional LMUL.603defvar LMULList = [1, 2, 4, 8];604 605//===----------------------------------------------------------------------===//606// Utility classes for segment load/store.607//===----------------------------------------------------------------------===//608// The set of legal NF for LMUL = lmul.609// LMUL <= 1, NF = 2, 3, 4, 5, 6, 7, 8610// LMUL == 2, NF = 2, 3, 4611// LMUL == 4, NF = 2612// LMUL == 8, no legal NF613class NFList<int lmul> {614 list<int> L = !cond(!eq(lmul, 8): [],615 !eq(lmul, 4): [2],616 !eq(lmul, 2): [2, 3, 4],617 true: [2, 3, 4, 5, 6, 7, 8]);618}619 620// Generate [start, end) SubRegIndex list.621class SubRegSet<int nf, int lmul> {622 list<SubRegIndex> L = !foldl([]<SubRegIndex>,623 !range(0, 8),624 AccList, i,625 !listconcat(AccList,626 !if(!lt(i, nf),627 [!cast<SubRegIndex>("sub_vrm" # lmul # "_" # i)],628 [])));629}630 631// Collect the valid indexes into 'R' under NF and LMUL values from TUPLE_INDEX.632// When NF = 2, the valid TUPLE_INDEX is 0 and 1.633// For example, when LMUL = 4, the potential valid indexes is634// [8, 12, 16, 20, 24, 28, 4]. However, not all these indexes are valid under635// NF = 2. For example, 28 is not valid under LMUL = 4, NF = 2 and TUPLE_INDEX = 0.636// The filter is637// (tuple_index + i) x lmul <= (tuple_index x lmul) + 32 - (nf x lmul)638//639// Use START = 0, LMUL = 4 and NF = 2 as the example,640// i x 4 <= 24641// The class will return [8, 12, 16, 20, 24, 4].642// Use START = 1, LMUL = 4 and NF = 2 as the example,643// (1 + i) x 4 <= 28644// The class will return [12, 16, 20, 24, 28, 8].645//646class IndexSet<int tuple_index, int nf, int lmul, bit isV0 = false> {647 list<int> R =648 !foldl([]<int>,649 !if(isV0, [0],650 !cond(651 !eq(lmul, 1): !listconcat(!range(8, 32), !range(1, 8)),652 !eq(lmul, 2): !listconcat(!range(4, 16), !range(1, 4)),653 !eq(lmul, 4): !listconcat(!range(2, 8), !range(1, 2)))),654 L, i,655 !listconcat(L,656 !if(!le(!mul(!add(i, tuple_index), lmul),657 !sub(!add(32, !mul(tuple_index, lmul)), !mul(nf, lmul))),658 [!mul(!add(i, tuple_index), lmul)], [])));659}660 661// This class returns a list of vector register collections.662// For example, for NF = 2 and LMUL = 4,663// L would be:664// ([ V8M4, V12M4, V16M4, V20M4, V24M4, V4M4],665// [V12M4, V16M4, V20M4, V24M4, V28M4, V8M4])666// Names are the starting register of each register list,667// in this example:668// ["v8", "v12", "v16", "v20", "v24", "v4"]669class VRegList<list<dag> LIn, int start, int nf, int lmul, bit isV0> {670 list<dag> L =671 !if(!ge(start, nf),672 LIn,673 !listconcat(674 [!dag(add,675 !foreach(i, IndexSet<start, nf, lmul, isV0>.R,676 !cast<Register>("V" # i # !cond(!eq(lmul, 2): "M2",677 !eq(lmul, 4): "M4",678 true: ""))),679 !listsplat("",680 !size(IndexSet<start, nf, lmul, isV0>.R)))],681 VRegList<LIn, !add(start, 1), nf, lmul, isV0>.L));682 list<string> Names =683 !if(!ge(start, nf), [],684 !foreach(i, IndexSet<start, nf, lmul, isV0>.R, "v" # i));685}686 687//===----------------------------------------------------------------------===//688// Vector registers689//===----------------------------------------------------------------------===//690 691foreach Index = !range(0, 32, 1) in {692 def V#Index : RISCVReg<Index, "v"#Index>, DwarfRegNum<[!add(Index, 96)]>;693}694 695foreach Index = !range(0, 32, 2) in {696 def V#Index#M2 : RISCVRegWithSubRegs<Index, "v"#Index,697 [!cast<Register>("V"#Index),698 !cast<Register>("V"#!add(Index, 1))]>,699 DwarfRegAlias<!cast<Register>("V"#Index)> {700 let SubRegIndices = [sub_vrm1_0, sub_vrm1_1];701 }702}703 704foreach Index = !range(0, 32, 4) in {705 def V#Index#M4 : RISCVRegWithSubRegs<Index, "v"#Index,706 [!cast<Register>("V"#Index#"M2"),707 !cast<Register>("V"#!add(Index, 2)#"M2")]>,708 DwarfRegAlias<!cast<Register>("V"#Index)> {709 let SubRegIndices = [sub_vrm2_0, sub_vrm2_1];710 }711}712 713foreach Index = !range(0, 32, 8) in {714 def V#Index#M8 : RISCVRegWithSubRegs<Index, "v"#Index,715 [!cast<Register>("V"#Index#"M4"),716 !cast<Register>("V"#!add(Index, 4)#"M4")]>,717 DwarfRegAlias<!cast<Register>("V"#Index)> {718 let SubRegIndices = [sub_vrm4_0, sub_vrm4_1];719 }720}721 722def VTYPE : RISCVReg<0, "vtype">;723def VL : RISCVReg<0, "vl">;724def VXSAT : RISCVReg<0, "vxsat">;725def VXRM : RISCVReg<0, "vxrm">;726let isConstant = true in727def VLENB : RISCVReg<0, "vlenb">,728 DwarfRegNum<[!add(4096, SysRegVLENB.Encoding)]>;729 730def VCSR : RISCVRegisterClass<[XLenVT], 32,731 (add VTYPE, VL, VLENB)> {732 let RegInfos = XLenRI;733 let isAllocatable = 0;734}735 736 737foreach m = [1, 2, 4] in {738 foreach n = NFList<m>.L in {739 defvar RegListWOV0 = VRegList<[], 0, n, m, false>;740 defvar RegListWV0 = VRegList<[], 0, n, m, true>;741 def "VN" # n # "M" # m # "NoV0": RegisterTuples<742 SubRegSet<n, m>.L,743 RegListWOV0.L,744 RegListWOV0.Names>;745 def "VN" # n # "M" # m # "V0" : RegisterTuples<746 SubRegSet<n, m>.L,747 RegListWV0.L,748 RegListWV0.Names>;749 }750}751 752class VReg<list<ValueType> regTypes, dag regList, int Vlmul, int nf = 1>753 : RISCVRegisterClass<regTypes,754 64, // The maximum supported ELEN is 64.755 regList> {756 let IsVRegClass = 1;757 let VLMul = Vlmul;758 let NF = nf;759 760 let Size = !mul(VLMul, NF, 64);761 let CopyCost = !mul(VLMul, NF);762 // Prefer to allocate high LMUL registers first.763 let AllocationPriority = !if(!gt(Vlmul, 1), Vlmul, 0);764}765 766defvar VMaskVTs = [vbool1_t, vbool2_t, vbool4_t, vbool8_t, vbool16_t,767 vbool32_t, vbool64_t];768 769defvar VM1VTs = [vint8m1_t, vint16m1_t, vint32m1_t, vint64m1_t,770 vbfloat16m1_t, vfloat16m1_t, vfloat32m1_t,771 vfloat64m1_t, vint8mf2_t, vint8mf4_t, vint8mf8_t,772 vint16mf2_t, vint16mf4_t, vint32mf2_t,773 vfloat16mf4_t, vfloat16mf2_t, vbfloat16mf4_t,774 vbfloat16mf2_t, vfloat32mf2_t];775 776defvar VM2VTs = [vint8m2_t, vint16m2_t, vint32m2_t, vint64m2_t,777 vfloat16m2_t, vbfloat16m2_t,778 vfloat32m2_t, vfloat64m2_t];779 780defvar VM4VTs = [vint8m4_t, vint16m4_t, vint32m4_t, vint64m4_t,781 vfloat16m4_t, vbfloat16m4_t,782 vfloat32m4_t, vfloat64m4_t];783 784defvar VM8VTs = [vint8m8_t, vint16m8_t, vint32m8_t, vint64m8_t,785 vfloat16m8_t, vbfloat16m8_t,786 vfloat32m8_t, vfloat64m8_t];787 788// We reverse the order of last 8 registers so that we don't needlessly prevent789// allocation of higher lmul register groups while still putting v0 last in the790// allocation order.791 792def VR : VReg<!listconcat(VM1VTs, VMaskVTs),793 (add (sequence "V%u", 8, 31),794 (sequence "V%u", 7, 0)), 1>;795 796def VRNoV0 : VReg<!listconcat(VM1VTs, VMaskVTs), (sub VR, V0), 1>;797 798def VRM2 : VReg<VM2VTs, (add (sequence "V%uM2", 8, 31, 2),799 (sequence "V%uM2", 6, 0, 2)), 2>;800 801def VRM2NoV0 : VReg<VM2VTs, (sub VRM2, V0M2), 2>;802 803def VRM4 : VReg<VM4VTs, (add V8M4, V12M4, V16M4, V20M4,804 V24M4, V28M4, V4M4, V0M4), 4>;805 806def VRM4NoV0 : VReg<VM4VTs, (sub VRM4, V0M4), 4>;807 808def VRM8 : VReg<VM8VTs, (add V8M8, V16M8, V24M8, V0M8), 8>;809 810def VRM8NoV0 : VReg<VM8VTs, (sub VRM8, V0M8), 8>;811 812def VMV0 : VReg<VMaskVTs, (add V0), 1>;813 814// The register class is added for inline assembly for vector mask types.815def VM : VReg<VMaskVTs, (add VR), 1>;816 817defvar VTupM1N2VTs = [riscv_nxv8i8x2, riscv_nxv4i8x2, riscv_nxv2i8x2, riscv_nxv1i8x2];818defvar VTupM1N3VTs = [riscv_nxv8i8x3, riscv_nxv4i8x3, riscv_nxv2i8x3, riscv_nxv1i8x3];819defvar VTupM1N4VTs = [riscv_nxv8i8x4, riscv_nxv4i8x4, riscv_nxv2i8x4, riscv_nxv1i8x4];820defvar VTupM1N5VTs = [riscv_nxv8i8x5, riscv_nxv4i8x5, riscv_nxv2i8x5, riscv_nxv1i8x5];821defvar VTupM1N6VTs = [riscv_nxv8i8x6, riscv_nxv4i8x6, riscv_nxv2i8x6, riscv_nxv1i8x6];822defvar VTupM1N7VTs = [riscv_nxv8i8x7, riscv_nxv4i8x7, riscv_nxv2i8x7, riscv_nxv1i8x7];823defvar VTupM1N8VTs = [riscv_nxv8i8x8, riscv_nxv4i8x8, riscv_nxv2i8x8, riscv_nxv1i8x8];824defvar VTupM2N2VTs = [riscv_nxv16i8x2];825defvar VTupM2N3VTs = [riscv_nxv16i8x3];826defvar VTupM2N4VTs = [riscv_nxv16i8x4];827defvar VTupM4N2VTs = [riscv_nxv32i8x2];828class VTupRegList<int LMUL, int NF> {829 list<ValueType> L = !cond(!and(!eq(LMUL, 1), !eq(NF, 2)): VTupM1N2VTs,830 !and(!eq(LMUL, 1), !eq(NF, 3)): VTupM1N3VTs,831 !and(!eq(LMUL, 1), !eq(NF, 4)): VTupM1N4VTs,832 !and(!eq(LMUL, 1), !eq(NF, 5)): VTupM1N5VTs,833 !and(!eq(LMUL, 1), !eq(NF, 6)): VTupM1N6VTs,834 !and(!eq(LMUL, 1), !eq(NF, 7)): VTupM1N7VTs,835 !and(!eq(LMUL, 1), !eq(NF, 8)): VTupM1N8VTs,836 !and(!eq(LMUL, 2), !eq(NF, 2)): VTupM2N2VTs,837 !and(!eq(LMUL, 2), !eq(NF, 3)): VTupM2N3VTs,838 !and(!eq(LMUL, 2), !eq(NF, 4)): VTupM2N4VTs,839 !and(!eq(LMUL, 4), !eq(NF, 2)): VTupM4N2VTs);840}841 842foreach m = LMULList in {843 foreach nf = NFList<m>.L in {844 def "VRN" # nf # "M" # m # "NoV0"845 : VReg<VTupRegList<m, nf>.L,846 (add !cast<RegisterTuples>("VN" # nf # "M" # m # "NoV0")),847 m, nf>;848 def "VRN" # nf # "M" # m849 : VReg<VTupRegList<m, nf>.L,850 (add !cast<RegisterTuples>("VN" # nf # "M" # m # "NoV0"),851 !cast<RegisterTuples>("VN" # nf # "M" # m # "V0")),852 m, nf>;853 }854}855 856//===----------------------------------------------------------------------===//857// Special registers858//===----------------------------------------------------------------------===//859 860def FFLAGS : RISCVReg<0, "fflags">;861def FRM : RISCVReg<0, "frm">;862def FCSR : RISCVReg<0, "fcsr">;863 864// Shadow Stack register865def SSP : RISCVReg<0, "ssp">;866 867// Dummy SiFive VCIX state register868def SF_VCIX_STATE : RISCVReg<0, "sf.vcix_state">;869def : RISCVRegisterClass<[XLenVT], 32, (add SF_VCIX_STATE)> {870 let RegInfos = XLenRI;871 let isAllocatable = 0;872}873 874//===----------------------------------------------------------------------===//875// XSfmmbase tiles876//===----------------------------------------------------------------------===//877foreach Index = 0-15 in878 def T#Index : RISCVReg<Index, "mt"#Index, []>,879 DwarfRegNum<[!add(Index, 3072)]>;880 881let RegInfos = XLenRI in {882 def TR : RISCVRegisterClass<[untyped], 32, (add (sequence "T%u", 0, 15))>;883 def TRM2 : RISCVRegisterClass<[untyped], 32, (add (decimate TR, 2))>;884 def TRM4 : RISCVRegisterClass<[untyped], 32, (add (decimate TR, 4))>;885}886