Skip to content

Commit 483abe4

Browse files
committed
[RISCV] GPR Pairs for Inline Asm using Pr
This patch adds support for getting even-odd general purpose register pairs into and out of inline assembly using the `Pr` constraint as proposed in riscv-non-isa/riscv-c-api-doc#92 There are a few different pieces to this patch, each of which need their own explanation. Target-Independent Changes: - This adds two new Machine Value Types (MVTs), which represent pairs for each xlen. Two are needed because MVTs usually have a fixed length. This change unfortunately increases the size of SelectionDAG tables indexed by MVT by a small percentage. - When an inline assembly block returns multiple values, it returns them in a struct, rather than as a single value. This fixes TargetLowering so that `getAsmOperandValueType` is called on the types in that struct, so that targets have the opportunity to propose their own MVT for an inline assembly operand where this wouldn't match conventional arguments/return values. This matches what happens when a single value is returned. RISC-V Changes: - Renames the Register Class used for f64 values on rv32i_zdinx from `GPRPair*` to `GPRF64Pair*`. These register classes are kept broadly unmodified, as their primary value type is used for type inference over selection patterns. This rename affects quite a lot of files. I reordered the definitions in RISCVRegisterInfo.td and added headings to make it easier to browse. - Adds new `GPRPair*` register classes which will be used for `Pr` constraints and for instructions that need an even-odd GPR pair. This new type is used for `amocas.d.*`(rv32) and `amocas.q.*`(rv64) in Zacas, instead of the `GPRF64Pair` class being used before. - Marks the new `GPRPair` class legal as for holding a `MVT::riscv_i<xlen>_pair`. Two new RISCVISD node types are added for creating and destructing a pair - `BuildGPRPair` and `SplitGPRPair`, and are introduced when bitcasting to/from the pair type and the `i<2*xlen>` type. - This adds an override for `getNumRegisters` to ensure that `i<2*xlen>` values, when going to/from inline assembly, only allocate one (pair) register (they would otherwise allocate two). - Ensures that the DAGCombiner doesn't merge the `bitcast` between `i<2*xlen>` types and the pair type into a load/store, as we want to legalise these 2*xlen-wide loads/stores as before - by splitting them into two xlen-wide loads/stores, which will happen with `i<2*xlen>` types. - Ensures that Clang understands that `Pr` is a valid inline assembly constraint.
1 parent 7729c22 commit 483abe4

File tree

14 files changed

+455
-112
lines changed

14 files changed

+455
-112
lines changed

clang/lib/Basic/Targets/RISCV.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ bool RISCVTargetInfo::validateAsmConstraint(
108108
return true;
109109
}
110110
return false;
111+
case 'P':
112+
// An even-odd register pair - GPR
113+
if (Name[1] == 'r') {
114+
Info.setAllowsRegister();
115+
Name += 1;
116+
return true;
117+
}
118+
return false;
111119
case 'v':
112120
// A vector register.
113121
if (Name[1] == 'r' || Name[1] == 'd' || Name[1] == 'm') {
@@ -122,8 +130,9 @@ bool RISCVTargetInfo::validateAsmConstraint(
122130
std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
123131
std::string R;
124132
switch (*Constraint) {
125-
// c* and v* are two-letter constraints on RISC-V.
133+
// c*, P*, and v* are all two-letter constraints on RISC-V.
126134
case 'c':
135+
case 'P':
127136
case 'v':
128137
R = std::string("^") + std::string(Constraint, 2);
129138
Constraint += 1;

clang/test/CodeGen/RISCV/riscv-inline-asm.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ void test_cf(float f, double d) {
3333
asm volatile("" : "=cf"(cd) : "cf"(d));
3434
}
3535

36+
#if __riscv_xlen == 32
37+
typedef long long double_xlen_t;
38+
#elif __riscv_xlen == 64
39+
typedef __int128_t double_xlen_t;
40+
#endif
41+
double_xlen_t test_Pr_wide_scalar(double_xlen_t p) {
42+
// CHECK-LABEL: define{{.*}} {{i128|i64}} @test_Pr_wide_scalar(
43+
// CHECK: call {{i128|i64}} asm sideeffect "", "=^Pr,^Pr"({{i128|i64}} %{{.*}})
44+
double_xlen_t ret;
45+
asm volatile("" : "=Pr"(ret) : "Pr"(p));
46+
return ret;
47+
}
48+
3649
void test_I(void) {
3750
// CHECK-LABEL: define{{.*}} void @test_I()
3851
// CHECK: call void asm sideeffect "", "I"(i32 2047)

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/SelectionDAG/TargetLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5730,7 +5730,8 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
57305730
assert(!Call.getType()->isVoidTy() && "Bad inline asm!");
57315731
if (auto *STy = dyn_cast<StructType>(Call.getType())) {
57325732
OpInfo.ConstraintVT =
5733-
getSimpleValueType(DL, STy->getElementType(ResNo));
5733+
getAsmOperandValueType(DL, STy->getElementType(ResNo))
5734+
.getSimpleVT();
57345735
} else {
57355736
assert(ResNo == 0 && "Asm only has one result!");
57365737
OpInfo.ConstraintVT =

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)) {
@@ -2399,7 +2405,7 @@ ParseStatus RISCVAsmParser::parseGPRPairAsFPR64(OperandVector &Operands) {
23992405
const MCRegisterInfo *RI = getContext().getRegisterInfo();
24002406
MCRegister Pair = RI->getMatchingSuperReg(
24012407
Reg, RISCV::sub_gpr_even,
2402-
&RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2408+
&RISCVMCRegisterClasses[RISCV::GPRF64PairRegClassID]);
24032409
Operands.push_back(RISCVOperand::createReg(Pair, S, E, /*isGPRAsFPR=*/true));
24042410
return ParseStatus::Success;
24052411
}

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,14 +953,43 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
953953
ReplaceNode(Node, Res);
954954
return;
955955
}
956+
case RISCVISD::BuildGPRPair: {
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+
}
969+
case RISCVISD::SplitGPRPair: {
970+
if (!SDValue(Node, 0).use_empty()) {
971+
SDValue Lo = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL, VT,
972+
Node->getOperand(0));
973+
ReplaceUses(SDValue(Node, 0), Lo);
974+
}
975+
976+
if (!SDValue(Node, 1).use_empty()) {
977+
SDValue Hi = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL, VT,
978+
Node->getOperand(0));
979+
ReplaceUses(SDValue(Node, 1), Hi);
980+
}
981+
982+
CurDAG->RemoveDeadNode(Node);
983+
return;
984+
}
956985
case RISCVISD::BuildPairF64: {
957986
if (!Subtarget->hasStdExtZdinx())
958987
break;
959988

960989
assert(!Subtarget->is64Bit() && "Unexpected subtarget");
961990

962991
SDValue Ops[] = {
963-
CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32),
992+
CurDAG->getTargetConstant(RISCV::GPRF64PairRegClassID, DL, MVT::i32),
964993
Node->getOperand(0),
965994
CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32),
966995
Node->getOperand(1),

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 69 additions & 6 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[] = {
@@ -296,6 +298,11 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
296298
setCondCodeAction(ISD::SETLE, XLenVT, Expand);
297299
}
298300

301+
if (Subtarget.is64Bit())
302+
setOperationAction(ISD::BITCAST, MVT::i128, Custom);
303+
else
304+
setOperationAction(ISD::BITCAST, MVT::i64, Custom);
305+
299306
setOperationAction({ISD::STACKSAVE, ISD::STACKRESTORE}, MVT::Other, Expand);
300307

301308
setOperationAction(ISD::VASTART, MVT::Other, Custom);
@@ -2224,6 +2231,17 @@ bool RISCVTargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT,
22242231
return Index == 0 || Index == ResElts;
22252232
}
22262233

2234+
EVT RISCVTargetLowering::getAsmOperandValueType(const DataLayout &DL, Type *Ty,
2235+
bool AllowUnknown) const {
2236+
if (!Subtarget.is64Bit() && Ty->isIntegerTy(64))
2237+
return MVT::riscv_i32_pair;
2238+
2239+
if (Subtarget.is64Bit() && Ty->isIntegerTy(128))
2240+
return MVT::riscv_i64_pair;
2241+
2242+
return TargetLowering::getAsmOperandValueType(DL, Ty, AllowUnknown);
2243+
}
2244+
22272245
MVT RISCVTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
22282246
CallingConv::ID CC,
22292247
EVT VT) const {
@@ -2238,6 +2256,17 @@ MVT RISCVTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
22382256
return PartVT;
22392257
}
22402258

2259+
unsigned
2260+
RISCVTargetLowering::getNumRegisters(LLVMContext &Context, EVT VT,
2261+
std::optional<MVT> RegisterVT) const {
2262+
// Pair inline assembly operand
2263+
if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2264+
*RegisterVT == Subtarget.getXLenPairVT())
2265+
return 1;
2266+
2267+
return TargetLowering::getNumRegisters(Context, VT, RegisterVT);
2268+
}
2269+
22412270
unsigned RISCVTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context,
22422271
CallingConv::ID CC,
22432272
EVT VT) const {
@@ -2776,6 +2805,19 @@ RISCVTargetLowering::computeVLMAXBounds(MVT VecVT,
27762805
return std::make_pair(MinVLMAX, MaxVLMAX);
27772806
}
27782807

2808+
bool RISCVTargetLowering::isLoadBitCastBeneficial(
2809+
EVT LoadVT, EVT BitcastVT, const SelectionDAG &DAG,
2810+
const MachineMemOperand &MMO) const {
2811+
// We want to leave `bitcasts` to/from MVT::riscv_i<xlen>_pair separate from
2812+
// loads/stores so they can be turned into BuildGPRPair/::SplitGPRPair nodes.
2813+
if (LoadVT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) &&
2814+
BitcastVT == Subtarget.getXLenPairVT())
2815+
return false;
2816+
2817+
return TargetLoweringBase::isLoadBitCastBeneficial(LoadVT, BitcastVT, DAG,
2818+
MMO);
2819+
}
2820+
27792821
// The state of RVV BUILD_VECTOR and VECTOR_SHUFFLE lowering is that very few
27802822
// of either is (currently) supported. This can get us into an infinite loop
27812823
// where we try to lower a BUILD_VECTOR as a VECTOR_SHUFFLE as a BUILD_VECTOR
@@ -6413,6 +6455,13 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
64136455
std::tie(Lo, Hi) = DAG.SplitScalar(Op0, DL, MVT::i32, MVT::i32);
64146456
return DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
64156457
}
6458+
if (VT == Subtarget.getXLenPairVT() && Op0VT.isScalarInteger() &&
6459+
Op0VT.getSizeInBits() == 2 * Subtarget.getXLen()) {
6460+
SDValue Lo, Hi;
6461+
std::tie(Lo, Hi) = DAG.SplitScalar(Op0, DL, XLenVT, XLenVT);
6462+
return DAG.getNode(RISCVISD::BuildGPRPair, DL, Subtarget.getXLenPairVT(),
6463+
Lo, Hi);
6464+
}
64166465

64176466
// Consider other scalar<->scalar casts as legal if the types are legal.
64186467
// Otherwise expand them.
@@ -12886,6 +12935,14 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
1288612935
SDValue RetReg = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64,
1288712936
NewReg.getValue(0), NewReg.getValue(1));
1288812937
Results.push_back(RetReg);
12938+
} else if (VT.isInteger() &&
12939+
VT.getSizeInBits() == 2 * Subtarget.getXLen() &&
12940+
Op0VT == Subtarget.getXLenPairVT()) {
12941+
SDValue NewReg = DAG.getNode(RISCVISD::SplitGPRPair, DL,
12942+
DAG.getVTList(XLenVT, XLenVT), Op0);
12943+
SDValue RetReg = DAG.getNode(ISD::BUILD_PAIR, DL, VT, NewReg.getValue(0),
12944+
NewReg.getValue(1));
12945+
Results.push_back(RetReg);
1288912946
} else if (!VT.isVector() && Op0VT.isFixedLengthVector() &&
1289012947
isTypeLegal(Op0VT)) {
1289112948
// Custom-legalize bitcasts from fixed-length vector types to illegal
@@ -20130,6 +20187,8 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
2013020187
NODE_NAME_CASE(TAIL)
2013120188
NODE_NAME_CASE(SELECT_CC)
2013220189
NODE_NAME_CASE(BR_CC)
20190+
NODE_NAME_CASE(BuildGPRPair)
20191+
NODE_NAME_CASE(SplitGPRPair)
2013320192
NODE_NAME_CASE(BuildPairF64)
2013420193
NODE_NAME_CASE(SplitF64)
2013520194
NODE_NAME_CASE(ADD_LO)
@@ -20408,6 +20467,8 @@ RISCVTargetLowering::getConstraintType(StringRef Constraint) const {
2040820467
return C_RegisterClass;
2040920468
if (Constraint == "cr" || Constraint == "cf")
2041020469
return C_RegisterClass;
20470+
if (Constraint == "Pr")
20471+
return C_RegisterClass;
2041120472
}
2041220473
return TargetLowering::getConstraintType(Constraint);
2041320474
}
@@ -20429,7 +20490,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2042920490
if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
2043020491
return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
2043120492
if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20432-
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20493+
return std::make_pair(0U, &RISCV::GPRF64PairNoX0RegClass);
2043320494
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
2043420495
case 'f':
2043520496
if (VT == MVT::f16) {
@@ -20446,7 +20507,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2044620507
if (Subtarget.hasStdExtD())
2044720508
return std::make_pair(0U, &RISCV::FPR64RegClass);
2044820509
if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20449-
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20510+
return std::make_pair(0U, &RISCV::GPRF64PairNoX0RegClass);
2045020511
if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
2045120512
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
2045220513
}
@@ -20488,7 +20549,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2048820549
if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
2048920550
return std::make_pair(0U, &RISCV::GPRF32CRegClass);
2049020551
if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20491-
return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20552+
return std::make_pair(0U, &RISCV::GPRF64PairCRegClass);
2049220553
if (!VT.isVector())
2049320554
return std::make_pair(0U, &RISCV::GPRCRegClass);
2049420555
} else if (Constraint == "cf") {
@@ -20506,10 +20567,12 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2050620567
if (Subtarget.hasStdExtD())
2050720568
return std::make_pair(0U, &RISCV::FPR64CRegClass);
2050820569
if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
20509-
return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20570+
return std::make_pair(0U, &RISCV::GPRF64PairCRegClass);
2051020571
if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
2051120572
return std::make_pair(0U, &RISCV::GPRCRegClass);
2051220573
}
20574+
} else if (Constraint == "Pr") {
20575+
return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
2051320576
}
2051420577

2051520578
// Clang will correctly decode the usage of register name aliases into their
@@ -20670,7 +20733,7 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2067020733
// Subtarget into account.
2067120734
if (Res.second == &RISCV::GPRF16RegClass ||
2067220735
Res.second == &RISCV::GPRF32RegClass ||
20673-
Res.second == &RISCV::GPRPairRegClass)
20736+
Res.second == &RISCV::GPRF64PairRegClass)
2067420737
return std::make_pair(Res.first, &RISCV::GPRRegClass);
2067520738

2067620739
return Res;

0 commit comments

Comments
 (0)