Skip to content

Commit fbb680b

Browse files
committed
[RISCV][ISel] Inline Asm Support for 'Pr' (GPR Pairs)
1 parent 10fcfdc commit fbb680b

File tree

4 files changed

+128
-88
lines changed

4 files changed

+128
-88
lines changed

llvm/lib/Target/RISCV/RISCVGISel.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,9 @@ def : LdPat<zextloadi16, LHU, i32>;
191191
def : StPat<truncstorei8, SB, GPR, i32>;
192192
def : StPat<truncstorei16, SH, GPR, i32>;
193193

194-
def : Pat<(anyext GPR:$src), (COPY GPR:$src)>;
195-
def : Pat<(sext GPR:$src), (ADDIW GPR:$src, 0)>;
196-
def : Pat<(trunc GPR:$src), (COPY GPR:$src)>;
194+
def : Pat<(i64 (anyext GPR:$src)), (COPY GPR:$src)>;
195+
def : Pat<(i64 (sext GPR:$src)), (ADDIW GPR:$src, 0)>;
196+
def : Pat<(i32 (trunc GPR:$src)), (COPY GPR:$src)>;
197197

198198
def : PatGprGpr<add, ADDW, i32, i32>;
199199
def : PatGprGpr<sub, SUBW, i32, i32>;

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20368,6 +20368,8 @@ RISCVTargetLowering::getConstraintType(StringRef Constraint) const {
2036820368
return C_RegisterClass;
2036920369
if (Constraint == "cr" || Constraint == "cf")
2037020370
return C_RegisterClass;
20371+
if (Constraint == "Pr")
20372+
return C_RegisterClass;
2037120373
}
2037220374
return TargetLowering::getConstraintType(Constraint);
2037320375
}
@@ -20389,7 +20391,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2038920391
if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
2039020392
return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
2039120393
if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20392-
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20394+
return std::make_pair(0U, &RISCV::GPRF64_RV32NoX0RegClass);
2039320395
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
2039420396
case 'f':
2039520397
if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16)
@@ -20436,7 +20438,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2043620438
if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
2043720439
return std::make_pair(0U, &RISCV::GPRF32CRegClass);
2043820440
if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20439-
return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20441+
return std::make_pair(0U, &RISCV::GPRF64_RV32CRegClass);
2044020442
if (!VT.isVector())
2044120443
return std::make_pair(0U, &RISCV::GPRCRegClass);
2044220444
} else if (Constraint == "cf") {
@@ -20446,6 +20448,8 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2044620448
return std::make_pair(0U, &RISCV::FPR32CRegClass);
2044720449
if (Subtarget.hasStdExtD() && VT == MVT::f64)
2044820450
return std::make_pair(0U, &RISCV::FPR64CRegClass);
20451+
} else if (Constraint == "Pr") {
20452+
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
2044920453
}
2045020454

2045120455
// Clang will correctly decode the usage of register name aliases into their

llvm/lib/Target/RISCV/RISCVInstrInfoD.td

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def FPR64INX : RegisterOperand<GPR> {
5252
let DecoderMethod = "DecodeGPRRegisterClass";
5353
}
5454

55-
def FPR64IN32X : RegisterOperand<GPRPair> {
55+
def FPR64IN32X : RegisterOperand<GPRF64_RV32> {
5656
let ParserMatchClass = GPRPairAsFPR;
5757
}
5858

@@ -523,15 +523,15 @@ def PseudoFROUND_D_IN32X : PseudoFROUND<FPR64IN32X, f64>;
523523

524524
/// Loads
525525
let isCall = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 1 in
526-
def PseudoRV32ZdinxLD : Pseudo<(outs GPRPair:$dst), (ins GPR:$rs1, simm12:$imm12), []>;
526+
def PseudoRV32ZdinxLD : Pseudo<(outs GPRF64_RV32:$dst), (ins GPR:$rs1, simm12:$imm12), []>;
527527
def : Pat<(f64 (load (AddrRegImmINX (XLenVT GPR:$rs1), simm12:$imm12))),
528528
(PseudoRV32ZdinxLD GPR:$rs1, simm12:$imm12)>;
529529

530530
/// Stores
531531
let isCall = 0, mayLoad = 0, mayStore = 1, Size = 8, isCodeGenOnly = 1 in
532-
def PseudoRV32ZdinxSD : Pseudo<(outs), (ins GPRPair:$rs2, GPRNoX0:$rs1, simm12:$imm12), []>;
533-
def : Pat<(store (f64 GPRPair:$rs2), (AddrRegImmINX (XLenVT GPR:$rs1), simm12:$imm12)),
534-
(PseudoRV32ZdinxSD GPRPair:$rs2, GPR:$rs1, simm12:$imm12)>;
532+
def PseudoRV32ZdinxSD : Pseudo<(outs), (ins GPRF64_RV32:$rs2, GPRNoX0:$rs1, simm12:$imm12), []>;
533+
def : Pat<(store (f64 GPRF64_RV32:$rs2), (AddrRegImmINX (XLenVT GPR:$rs1), simm12:$imm12)),
534+
(PseudoRV32ZdinxSD GPRF64_RV32:$rs2, GPR:$rs1, simm12:$imm12)>;
535535
} // Predicates = [HasStdExtZdinx, IsRV32]
536536

537537
let Predicates = [HasStdExtD] in {

llvm/lib/Target/RISCV/RISCVRegisterInfo.td

Lines changed: 114 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ def sub_gpr_odd : SubRegIndex<32, 32> {
7474
}
7575
} // Namespace = "RISCV"
7676

77-
// Integer registers
77+
//===----------------------------------------------------------------------===//
78+
// General Purpose Registers (aka Integer Registers)
79+
//===----------------------------------------------------------------------===//
80+
7881
// CostPerUse is set higher for registers that may not be compressible as they
7982
// are not part of GPRC, the most restrictive register class used by the
8083
// compressed instruction set. This will influence the greedy register
@@ -205,14 +208,21 @@ let RegAltNameIndices = [ABIRegAltName] in {
205208

206209
def XLenVT : ValueTypeByHwMode<[RV32, RV64],
207210
[i32, i64]>;
211+
def XLenPairVT : ValueTypeByHwMode<[RV32, RV64],
212+
[i64, i128]>;
213+
208214
// Allow f64 in GPR for ZDINX on RV64.
209215
def XLenFVT : ValueTypeByHwMode<[RV64],
210216
[f64]>;
211217
def XLenPairFVT : ValueTypeByHwMode<[RV32],
212218
[f64]>;
219+
213220
def XLenRI : RegInfoByHwMode<
214221
[RV32, RV64],
215222
[RegInfo<32,32,32>, RegInfo<64,64,64>]>;
223+
def XLenPairRI : RegInfoByHwMode<
224+
[RV32, RV64],
225+
[RegInfo<64, 64, 32>, RegInfo<128, 128, 64>]>;
216226

217227
class RISCVRegisterClass<list<ValueType> regTypes, int align, dag regList>
218228
: RegisterClass<"RISCV", regTypes, align, regList> {
@@ -279,7 +289,59 @@ def SR07 : GPRRegisterClass<(add (sequence "X%u", 8, 9),
279289

280290
def GPRX1X5 : GPRRegisterClass<(add X1, X5)>;
281291

282-
// Floating point registers
292+
//===----------------------------------------------------------------------===//
293+
// Even-Odd GPR Pairs
294+
//===----------------------------------------------------------------------===//
295+
296+
// Dummy zero register for use in the register pair containing X0 (as X1 is
297+
// not read to or written when the X0 register pair is used).
298+
def DUMMY_REG_PAIR_WITH_X0 : RISCVReg<0, "0">;
299+
300+
// Must add DUMMY_REG_PAIR_WITH_X0 to a separate register class to prevent the
301+
// register's existence from changing codegen (due to the regPressureSetLimit
302+
// for the GPR register class being altered).
303+
def GPRAll : GPRRegisterClass<(add GPR, DUMMY_REG_PAIR_WITH_X0)>;
304+
305+
let RegAltNameIndices = [ABIRegAltName] in {
306+
def X0_Pair : RISCVRegWithSubRegs<0, X0.AsmName,
307+
[X0, DUMMY_REG_PAIR_WITH_X0],
308+
X0.AltNames> {
309+
let SubRegIndices = [sub_gpr_even, sub_gpr_odd];
310+
let CoveredBySubRegs = 1;
311+
}
312+
foreach I = 1-15 in {
313+
defvar Index = !shl(I, 1);
314+
defvar IndexP1 = !add(Index, 1);
315+
defvar Reg = !cast<Register>("X"#Index);
316+
defvar RegP1 = !cast<Register>("X"#IndexP1);
317+
def "X" # Index #"_X" # IndexP1 : RISCVRegWithSubRegs<Index,
318+
Reg.AsmName,
319+
[Reg, RegP1],
320+
Reg.AltNames> {
321+
let SubRegIndices = [sub_gpr_even, sub_gpr_odd];
322+
let CoveredBySubRegs = 1;
323+
}
324+
}
325+
}
326+
327+
let RegInfos = XLenPairRI,
328+
DecoderMethod = "DecodeGPRPairRegisterClass" in {
329+
def GPRPair : RISCVRegisterClass<[XLenPairVT], 64, (add
330+
X10_X11, X12_X13, X14_X15, X16_X17,
331+
X6_X7,
332+
X28_X29, X30_X31,
333+
X8_X9,
334+
X18_X19, X20_X21, X22_X23, X24_X25, X26_X27,
335+
X0_Pair, X2_X3, X4_X5
336+
)>;
337+
338+
def GPRPairNoX0 : RISCVRegisterClass<[XLenPairVT], 64, (sub GPRPair, X0_Pair)>;
339+
} // let RegInfos = XLenPairRI, DecoderMethod = "DecodeGPRPairRegisterClass"
340+
341+
//===----------------------------------------------------------------------===//
342+
// Floating Point Registers
343+
//===----------------------------------------------------------------------===//
344+
283345
let RegAltNameIndices = [ABIRegAltName] in {
284346
def F0_H : RISCVReg16<0, "f0", ["ft0"]>, DwarfRegNum<[32]>;
285347
def F1_H : RISCVReg16<1, "f1", ["ft1"]>, DwarfRegNum<[33]>;
@@ -373,8 +435,50 @@ def FPR64C : RISCVRegisterClass<[f64], 64, (add
373435
(sequence "F%u_D", 8, 9)
374436
)>;
375437

438+
//===----------------------------------------------------------------------===//
439+
// GPR Classes for "H/F/D in X"
440+
//===----------------------------------------------------------------------===//
441+
442+
// 16-bit GPR sub-register class used by Zhinx instructions.
443+
def GPRF16 : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 17),
444+
(sequence "X%u_H", 5, 7),
445+
(sequence "X%u_H", 28, 31),
446+
(sequence "X%u_H", 8, 9),
447+
(sequence "X%u_H", 18, 27),
448+
(sequence "X%u_H", 0, 4))>;
449+
def GPRF16C : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 15),
450+
(sequence "X%u_H", 8, 9))>;
451+
452+
def GPRF32 : RISCVRegisterClass<[f32], 32, (add (sequence "X%u_W", 10, 17),
453+
(sequence "X%u_W", 5, 7),
454+
(sequence "X%u_W", 28, 31),
455+
(sequence "X%u_W", 8, 9),
456+
(sequence "X%u_W", 18, 27),
457+
(sequence "X%u_W", 0, 4))>;
458+
def GPRF32C : RISCVRegisterClass<[f32], 32, (add (sequence "X%u_W", 10, 15),
459+
(sequence "X%u_W", 8, 9))>;
460+
def GPRF32NoX0 : RISCVRegisterClass<[f32], 32, (sub GPRF32, X0_W)>;
461+
462+
let DecoderMethod = "DecodeGPRPairRegisterClass" in
463+
def GPRF64_RV32 : RISCVRegisterClass<[XLenPairFVT], 64, (add
464+
X10_X11, X12_X13, X14_X15, X16_X17,
465+
X6_X7,
466+
X28_X29, X30_X31,
467+
X8_X9,
468+
X18_X19, X20_X21, X22_X23, X24_X25, X26_X27,
469+
X0_Pair, X2_X3, X4_X5
470+
)>;
471+
472+
def GPRF64_RV32C : RISCVRegisterClass<[XLenPairFVT], 64, (add
473+
X10_X11, X12_X13, X14_X15, X8_X9
474+
)>;
475+
476+
def GPRF64_RV32NoX0 : RISCVRegisterClass<[XLenPairFVT], 64, (sub GPRF64_RV32, X0_Pair)>;
477+
478+
//===----------------------------------------------------------------------===//
376479
// Vector type mapping to LLVM types.
377-
//
480+
//===----------------------------------------------------------------------===//
481+
378482
// The V vector extension requires that VLEN >= 128 and <= 65536.
379483
// Additionally, the only supported ELEN values are 32 and 64,
380484
// thus `vscale` can be defined as VLEN/64,
@@ -534,7 +638,10 @@ class VRegList<list<dag> LIn, int start, int nf, int lmul, bit isV0> {
534638
!foreach(i, IndexSet<start, nf, lmul, isV0>.R, "v" # i));
535639
}
536640

641+
//===----------------------------------------------------------------------===//
537642
// Vector registers
643+
//===----------------------------------------------------------------------===//
644+
538645
foreach Index = !range(0, 32, 1) in {
539646
def V#Index : RISCVReg<Index, "v"#Index>, DwarfRegNum<[!add(Index, 96)]>;
540647
}
@@ -652,80 +759,6 @@ def VRM8NoV0 : VReg<VM8VTs, (sub VRM8, V0M8), 8>;
652759

653760
def VMV0 : VReg<VMaskVTs, (add V0), 1>;
654761

655-
// 16-bit GPR sub-register class used by Zhinx instructions.
656-
def GPRF16 : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 17),
657-
(sequence "X%u_H", 5, 7),
658-
(sequence "X%u_H", 28, 31),
659-
(sequence "X%u_H", 8, 9),
660-
(sequence "X%u_H", 18, 27),
661-
(sequence "X%u_H", 0, 4))>;
662-
def GPRF16C : RISCVRegisterClass<[f16], 16, (add (sequence "X%u_H", 10, 15),
663-
(sequence "X%u_H", 8, 9))>;
664-
def GPRF16NoX0 : RISCVRegisterClass<[f16], 16, (sub GPRF16, X0_H)>;
665-
666-
def GPRF32 : RISCVRegisterClass<[f32], 32, (add (sequence "X%u_W", 10, 17),
667-
(sequence "X%u_W", 5, 7),
668-
(sequence "X%u_W", 28, 31),
669-
(sequence "X%u_W", 8, 9),
670-
(sequence "X%u_W", 18, 27),
671-
(sequence "X%u_W", 0, 4))>;
672-
def GPRF32C : RISCVRegisterClass<[f32], 32, (add (sequence "X%u_W", 10, 15),
673-
(sequence "X%u_W", 8, 9))>;
674-
def GPRF32NoX0 : RISCVRegisterClass<[f32], 32, (sub GPRF32, X0_W)>;
675-
676-
def XLenPairRI : RegInfoByHwMode<
677-
[RV32, RV64],
678-
[RegInfo<64, 64, 32>, RegInfo<128, 128, 64>]>;
679-
680-
// Dummy zero register for use in the register pair containing X0 (as X1 is
681-
// not read to or written when the X0 register pair is used).
682-
def DUMMY_REG_PAIR_WITH_X0 : RISCVReg<0, "0">;
683-
684-
// Must add DUMMY_REG_PAIR_WITH_X0 to a separate register class to prevent the
685-
// register's existence from changing codegen (due to the regPressureSetLimit
686-
// for the GPR register class being altered).
687-
def GPRAll : GPRRegisterClass<(add GPR, DUMMY_REG_PAIR_WITH_X0)>;
688-
689-
let RegAltNameIndices = [ABIRegAltName] in {
690-
def X0_Pair : RISCVRegWithSubRegs<0, X0.AsmName,
691-
[X0, DUMMY_REG_PAIR_WITH_X0],
692-
X0.AltNames> {
693-
let SubRegIndices = [sub_gpr_even, sub_gpr_odd];
694-
let CoveredBySubRegs = 1;
695-
}
696-
foreach I = 1-15 in {
697-
defvar Index = !shl(I, 1);
698-
defvar IndexP1 = !add(Index, 1);
699-
defvar Reg = !cast<Register>("X"#Index);
700-
defvar RegP1 = !cast<Register>("X"#IndexP1);
701-
def "X" # Index #"_X" # IndexP1 : RISCVRegWithSubRegs<Index,
702-
Reg.AsmName,
703-
[Reg, RegP1],
704-
Reg.AltNames> {
705-
let SubRegIndices = [sub_gpr_even, sub_gpr_odd];
706-
let CoveredBySubRegs = 1;
707-
}
708-
}
709-
}
710-
711-
let RegInfos = XLenPairRI,
712-
DecoderMethod = "DecodeGPRPairRegisterClass" in {
713-
def GPRPair : RISCVRegisterClass<[XLenPairFVT], 64, (add
714-
X10_X11, X12_X13, X14_X15, X16_X17,
715-
X6_X7,
716-
X28_X29, X30_X31,
717-
X8_X9,
718-
X18_X19, X20_X21, X22_X23, X24_X25, X26_X27,
719-
X0_Pair, X2_X3, X4_X5
720-
)>;
721-
722-
def GPRPairC : RISCVRegisterClass<[XLenPairFVT], 64, (add
723-
X10_X11, X12_X13, X14_X15, X8_X9
724-
)>;
725-
726-
def GPRPairNoX0 : RISCVRegisterClass<[XLenPairFVT], 64, (sub GPRPair, X0_Pair)>;
727-
} // let RegInfos = XLenPairRI, DecoderMethod = "DecodeGPRPairRegisterClass"
728-
729762
// The register class is added for inline assembly for vector mask types.
730763
def VM : VReg<VMaskVTs, (add VR), 1>;
731764

@@ -770,7 +803,10 @@ foreach m = LMULList in {
770803
}
771804
}
772805

773-
// Special registers
806+
//===----------------------------------------------------------------------===//
807+
// Special Registers
808+
//===----------------------------------------------------------------------===//
809+
774810
def FFLAGS : RISCVReg<0, "fflags">;
775811
def FRM : RISCVReg<0, "frm">;
776812

0 commit comments

Comments
 (0)