Skip to content

Commit 0550970

Browse files
committed
[RISCV] WIP: Pairs
1 parent e986cb6 commit 0550970

14 files changed

+2327
-3339
lines changed

llvm/include/llvm/CodeGen/ValueTypes.td

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -317,20 +317,23 @@ def riscv_nxv16i8x3 : VTVecTup<384, 3, i8, 220>; // RISCV vector tuple(min_num_
317317
def riscv_nxv16i8x4 : VTVecTup<512, 4, i8, 221>; // RISCV vector tuple(min_num_elts=16, nf=4)
318318
def riscv_nxv32i8x2 : VTVecTup<512, 2, i8, 222>; // RISCV vector tuple(min_num_elts=32, nf=2)
319319

320-
def x86mmx : ValueType<64, 223>; // X86 MMX value
321-
def Glue : ValueType<0, 224>; // Pre-RA sched glue
322-
def isVoid : ValueType<0, 225>; // Produces no value
323-
def untyped : ValueType<8, 226> { // Produces an untyped value
320+
def riscv_i32_pair : ValueType<64, 223>; // RISCV pair of RV32 GPRs
321+
def riscv_i64_pair : ValueType<128, 224>; // RISCV pair of RV64 GPRs
322+
323+
def x86mmx : ValueType<64, 225>; // X86 MMX value
324+
def Glue : ValueType<0, 226>; // Pre-RA sched glue
325+
def isVoid : ValueType<0, 227>; // Produces no value
326+
def untyped : ValueType<8, 228> { // Produces an untyped value
324327
let LLVMName = "Untyped";
325328
}
326-
def funcref : ValueType<0, 227>; // WebAssembly's funcref type
327-
def externref : ValueType<0, 228>; // WebAssembly's externref type
328-
def exnref : ValueType<0, 229>; // WebAssembly's exnref type
329-
def x86amx : ValueType<8192, 230>; // X86 AMX value
330-
def i64x8 : ValueType<512, 231>; // 8 Consecutive GPRs (AArch64)
329+
def funcref : ValueType<0, 229>; // WebAssembly's funcref type
330+
def externref : ValueType<0, 230>; // WebAssembly's externref type
331+
def exnref : ValueType<0, 231>; // WebAssembly's exnref type
332+
def x86amx : ValueType<8192, 232>; // X86 AMX value
333+
def i64x8 : ValueType<512, 233>; // 8 Consecutive GPRs (AArch64)
331334
def aarch64svcount
332-
: ValueType<16, 232>; // AArch64 predicate-as-counter
333-
def spirvbuiltin : ValueType<0, 233>; // SPIR-V's builtin type
335+
: ValueType<16, 234>; // AArch64 predicate-as-counter
336+
def spirvbuiltin : ValueType<0, 235>; // SPIR-V's builtin type
334337

335338
let isNormalValueType = false in {
336339
def token : ValueType<0, 504>; // TokenTy

llvm/lib/CodeGen/ValueTypes.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ std::string EVT::getEVTString() const {
177177
if (isFloatingPoint())
178178
return "f" + utostr(getSizeInBits());
179179
llvm_unreachable("Invalid EVT!");
180+
case MVT::riscv_i32_pair:
181+
return "riscv_i32_pair";
182+
case MVT::riscv_i64_pair:
183+
return "riscv_i64_pair";
180184
case MVT::bf16: return "bf16";
181185
case MVT::ppcf128: return "ppcf128";
182186
case MVT::isVoid: return "isVoid";
@@ -214,6 +218,8 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {
214218
assert(isExtended() && "Type is not extended!");
215219
return LLVMTy;
216220
case MVT::isVoid: return Type::getVoidTy(Context);
221+
case MVT::riscv_i32_pair: return IntegerType::get(Context, 64);
222+
case MVT::riscv_i64_pair: return IntegerType::get(Context, 128);
217223
case MVT::x86mmx: return llvm::FixedVectorType::get(llvm::IntegerType::get(Context, 64), 1);
218224
case MVT::aarch64svcount:
219225
return TargetExtType::get(Context, "aarch64.svcount");

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,12 @@ struct RISCVOperand final : public MCParsedAsmOperand {
481481
RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
482482
}
483483

484+
bool isGPRPair() const {
485+
return Kind == KindTy::Register &&
486+
RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
487+
Reg.RegNum);
488+
}
489+
484490
bool isGPRF16() const {
485491
return Kind == KindTy::Register &&
486492
RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(Reg.RegNum);
@@ -491,17 +497,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
491497
RISCVMCRegisterClasses[RISCV::GPRF32RegClassID].contains(Reg.RegNum);
492498
}
493499

494-
bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
495-
bool isGPRAsFPR16() const { return isGPRF16() && Reg.IsGPRAsFPR; }
496-
bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
497-
bool isGPRPairAsFPR() const { return isGPRPair() && Reg.IsGPRAsFPR; }
498-
499-
bool isGPRPair() const {
500+
bool isGPRF64Pair() const {
500501
return Kind == KindTy::Register &&
501-
RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
502+
RISCVMCRegisterClasses[RISCV::GPRF64PairRegClassID].contains(
502503
Reg.RegNum);
503504
}
504505

506+
bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
507+
bool isGPRAsFPR16() const { return isGPRF16() && Reg.IsGPRAsFPR; }
508+
bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
509+
bool isGPRPairAsFPR64() const { return isGPRF64Pair() && Reg.IsGPRAsFPR; }
510+
505511
static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
506512
RISCVMCExpr::VariantKind &VK) {
507513
if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
@@ -2383,7 +2389,7 @@ ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
23832389
const MCRegisterInfo *RI = getContext().getRegisterInfo();
23842390
MCRegister Pair = RI->getMatchingSuperReg(
23852391
Reg, RISCV::sub_gpr_even,
2386-
&RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2392+
&RISCVMCRegisterClasses[RISCV::GPRF64PairRegClassID]);
23872393
Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));
23882394
return ParseStatus::Success;
23892395
}

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,14 +953,27 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
953953
ReplaceNode(Node, Res);
954954
return;
955955
}
956+
case RISCVISD::BuildXLenPair: {
957+
SDValue Ops[] = {
958+
CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32),
959+
Node->getOperand(0),
960+
CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32),
961+
Node->getOperand(1),
962+
CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
963+
964+
SDNode *N = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
965+
Subtarget->getXLenPairVT(), Ops);
966+
ReplaceNode(Node, N);
967+
return;
968+
}
956969
case RISCVISD::BuildPairF64: {
957970
if (!Subtarget->hasStdExtZdinx())
958971
break;
959972

960973
assert(!Subtarget->is64Bit() && "Unexpected subtarget");
961974

962975
SDValue Ops[] = {
963-
CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32),
976+
CurDAG->getTargetConstant(RISCV::GPRF64PairRegClassID, DL, MVT::i32),
964977
Node->getOperand(0),
965978
CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32),
966979
Node->getOperand(1),

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,11 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
114114
}
115115

116116
MVT XLenVT = Subtarget.getXLenVT();
117+
MVT XLenPairVT = Subtarget.getXLenPairVT();
117118

118119
// Set up the register classes.
119120
addRegisterClass(XLenVT, &RISCV::GPRRegClass);
121+
addRegisterClass(XLenPairVT, &RISCV::GPRPairRegClass);
120122

121123
if (Subtarget.hasStdExtZfhmin())
122124
addRegisterClass(MVT::f16, &RISCV::FPR16RegClass);
@@ -134,7 +136,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
134136
if (Subtarget.is64Bit())
135137
addRegisterClass(MVT::f64, &RISCV::GPRRegClass);
136138
else
137-
addRegisterClass(MVT::f64, &RISCV::GPRPairRegClass);
139+
addRegisterClass(MVT::f64, &RISCV::GPRF64PairRegClass);
138140
}
139141

140142
static const MVT::SimpleValueType BoolVecVTs[] = {
@@ -2216,6 +2218,17 @@ bool RISCVTargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT,
22162218
return Index == 0 || Index == ResElts;
22172219
}
22182220

2221+
EVT RISCVTargetLowering::getAsmOperandValueType(const DataLayout &DL, Type *Ty,
2222+
bool AllowUnknown) const {
2223+
if (Subtarget.isRV32() && Ty->isIntegerTy(64))
2224+
return MVT::riscv_i32_pair;
2225+
2226+
if (Subtarget.isRV64() && Ty->isIntegerTy(128))
2227+
return MVT::riscv_i64_pair;
2228+
2229+
return TargetLowering::getAsmOperandValueType(DL, Ty, AllowUnknown);
2230+
}
2231+
22192232
MVT RISCVTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
22202233
CallingConv::ID CC,
22212234
EVT VT) const {
@@ -20087,11 +20100,13 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
2008720100
NODE_NAME_CASE(SRET_GLUE)
2008820101
NODE_NAME_CASE(MRET_GLUE)
2008920102
NODE_NAME_CASE(CALL)
20103+
NODE_NAME_CASE(TAIL)
2009020104
NODE_NAME_CASE(SELECT_CC)
2009120105
NODE_NAME_CASE(BR_CC)
20106+
NODE_NAME_CASE(BuildXLenPair)
20107+
NODE_NAME_CASE(SplitXLenPair)
2009220108
NODE_NAME_CASE(BuildPairF64)
2009320109
NODE_NAME_CASE(SplitF64)
20094-
NODE_NAME_CASE(TAIL)
2009520110
NODE_NAME_CASE(ADD_LO)
2009620111
NODE_NAME_CASE(HI)
2009720112
NODE_NAME_CASE(LLA)
@@ -20368,6 +20383,8 @@ RISCVTargetLowering::getConstraintType(StringRef Constraint) const {
2036820383
return C_RegisterClass;
2036920384
if (Constraint == "cr" || Constraint == "cf")
2037020385
return C_RegisterClass;
20386+
if (Constraint == "Pr")
20387+
return C_RegisterClass;
2037120388
}
2037220389
return TargetLowering::getConstraintType(Constraint);
2037320390
}
@@ -20389,7 +20406,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2038920406
if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
2039020407
return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
2039120408
if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20392-
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20409+
return std::make_pair(0U, &RISCV::GPRF64PairNoX0RegClass);
2039320410
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
2039420411
case 'f':
2039520412
if (VT == MVT::f16) {
@@ -20406,7 +20423,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2040620423
if (Subtarget.hasStdExtD())
2040720424
return std::make_pair(0U, &RISCV::FPR64RegClass);
2040820425
if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20409-
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20426+
return std::make_pair(0U, &RISCV::GPRF64PairNoX0RegClass);
2041020427
if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
2041120428
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
2041220429
}
@@ -20448,7 +20465,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2044820465
if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
2044920466
return std::make_pair(0U, &RISCV::GPRF32CRegClass);
2045020467
if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20451-
return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20468+
return std::make_pair(0U, &RISCV::GPRF64PairCRegClass);
2045220469
if (!VT.isVector())
2045320470
return std::make_pair(0U, &RISCV::GPRCRegClass);
2045420471
} else if (Constraint == "cf") {
@@ -20466,10 +20483,12 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2046620483
if (Subtarget.hasStdExtD())
2046720484
return std::make_pair(0U, &RISCV::FPR64CRegClass);
2046820485
if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20469-
return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20486+
return std::make_pair(0U, &RISCV::GPRF64PairCRegClass);
2047020487
if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
2047120488
return std::make_pair(0U, &RISCV::GPRCRegClass);
2047220489
}
20490+
} else if (Constraint == "Pr") {
20491+
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
2047320492
}
2047420493

2047520494
// Clang will correctly decode the usage of register name aliases into their
@@ -20630,7 +20649,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2063020649
// Subtarget into account.
2063120650
if (Res.second == &RISCV::GPRF16RegClass ||
2063220651
Res.second == &RISCV::GPRF32RegClass ||
20633-
Res.second == &RISCV::GPRPairRegClass)
20652+
Res.second == &RISCV::GPRF64PairRegClass)
2063420653
return std::make_pair(Res.first, &RISCV::GPRRegClass);
2063520654

2063620655
return Res;
@@ -21269,6 +21288,24 @@ bool RISCVTargetLowering::splitValueIntoRegisterParts(
2126921288
return true;
2127021289
}
2127121290

21291+
if (NumParts == 1 && ValueVT == MVT::i128 && PartVT == MVT::riscv_i64_pair) {
21292+
// Used on inputs *to* inline assembly.
21293+
SDValue Lo, Hi;
21294+
std::tie(Lo, Hi) = DAG.SplitScalar(Val, DL, MVT::i64, MVT::i64);
21295+
Parts[0] = DAG.getNode(RISCVISD::BuildXLenPair, DL, PartVT, Lo, Hi);
21296+
return true;
21297+
}
21298+
21299+
if (NumParts == 1 && ValueVT == MVT::i64 && PartVT == MVT::riscv_i32_pair) {
21300+
// Used on inputs *to* inline assembly.
21301+
SDValue Lo, Hi;
21302+
std::tie(Lo, Hi) = DAG.SplitScalar(Val, DL, MVT::i32, MVT::i32);
21303+
Parts[0] = DAG.getNode(RISCVISD::BuildXLenPair, DL, PartVT, Lo, Hi);
21304+
return true;
21305+
}
21306+
21307+
// || (ValueVT == MVT::i64 && PartVT == MVT::riscv_i32_pair)
21308+
2127221309
if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
2127321310
LLVMContext &Context = *DAG.getContext();
2127421311
EVT ValueEltVT = ValueVT.getVectorElementType();
@@ -21338,6 +21375,16 @@ SDValue RISCVTargetLowering::joinRegisterPartsIntoValue(
2133821375
return Val;
2133921376
}
2134021377

21378+
// if (/*ValueVT == MVT::riscv_i64_pair &&*/ PartVT == MVT::riscv_i64_pair) {
21379+
// // Used on outputs *from* inline assembly.
21380+
// SDValue Val = Parts[0];
21381+
// SDValue Pair = DAG.getNode(RISCVISD::SplitXLenPair, DL, {MVT::i64,
21382+
// MVT::i64}, Val); return DAG.getNode(ISD::BUILD_PAIR, DL, ValueVT,
21383+
// Pair.getValue(0), Pair.getValue(1));
21384+
// }
21385+
21386+
// (PartVT == MVT::i64 && ValueVT == MVT::riscv_i32_pair)
21387+
2134121388
if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
2134221389
LLVMContext &Context = *DAG.getContext();
2134321390
SDValue Val = Parts[0];

llvm/lib/Target/RISCV/RISCVISelLowering.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ enum NodeType : unsigned {
3434
SRET_GLUE,
3535
MRET_GLUE,
3636
CALL,
37+
TAIL,
38+
3739
/// Select with condition operator - This selects between a true value and
3840
/// a false value (ops #3 and #4) based on the boolean result of comparing
3941
/// the lhs and rhs (ops #0 and #1) of a conditional expression with the
@@ -42,9 +44,16 @@ enum NodeType : unsigned {
4244
/// integer or floating point.
4345
SELECT_CC,
4446
BR_CC,
47+
48+
/// Turn a pair of `i<xlen>`s into a `riscv_i<xlen>_pair`.
49+
BuildXLenPair,
50+
/// Turn a `riscv_i<xlen>_pair` into a pair of `i<xlen>`s.
51+
SplitXLenPair,
52+
53+
/// Turn a pair of `i32`s into an `f64`. Needed for rv32d/ilp32
4554
BuildPairF64,
55+
/// Turn a `f64` into a pair of `i32`s. Needed for rv32d/ilp32
4656
SplitF64,
47-
TAIL,
4857

4958
// Add the Lo 12 bits from an address. Selected to ADDI.
5059
ADD_LO,
@@ -534,6 +543,9 @@ class RISCVTargetLowering : public TargetLowering {
534543

535544
bool softPromoteHalfType() const override { return true; }
536545

546+
EVT getAsmOperandValueType(const DataLayout &DL, Type *Ty,
547+
bool AllowUnknown = false) const override;
548+
537549
/// Return the register type for a given MVT, ensuring vectors are treated
538550
/// as a series of gpr sized integers.
539551
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,

llvm/lib/Target/RISCV/RISCVInstrInfoD.td

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def AddrRegImmINX : ComplexPattern<iPTR, 2, "SelectAddrRegImmRV32Zdinx">;
3636
def GPRPairAsFPR : AsmOperandClass {
3737
let Name = "GPRPairAsFPR";
3838
let ParserMethod = "parseGPRPairAsFPR64";
39-
let PredicateMethod = "isGPRPairAsFPR";
39+
let PredicateMethod = "isGPRPairAsFPR64";
4040
let RenderMethod = "addRegOperands";
4141
}
4242

@@ -52,7 +52,7 @@ def FPR64INX : RegisterOperand<GPR> {
5252
let DecoderMethod = "DecodeGPRRegisterClass";
5353
}
5454

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

@@ -491,7 +491,7 @@ def : StPat<store, FSD, FPR64, f64>;
491491
/// Pseudo-instructions needed for the soft-float ABI with RV32D
492492

493493
// Moves two GPRs to an FPR.
494-
let usesCustomInserter = 1 in
494+
let usesCustomInserter = 1, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
495495
def BuildPairF64Pseudo
496496
: Pseudo<(outs FPR64:$dst), (ins GPR:$src1, GPR:$src2),
497497
[(set FPR64:$dst, (RISCVBuildPairF64 GPR:$src1, GPR:$src2))]>;
@@ -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 GPRF64Pair:$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 GPRF64Pair:$rs2, GPRNoX0:$rs1, simm12:$imm12), []>;
533+
def : Pat<(store (f64 GPRF64Pair:$rs2), (AddrRegImmINX (XLenVT GPR:$rs1), simm12:$imm12)),
534+
(PseudoRV32ZdinxSD GPRF64Pair:$rs2, GPR:$rs1, simm12:$imm12)>;
535535
} // Predicates = [HasStdExtZdinx, IsRV32]
536536

537537
let Predicates = [HasStdExtD] in {

0 commit comments

Comments
 (0)