Skip to content

Commit 7f34355

Browse files
authored
[RISCV] Use separate CCValAssign for both parts of f64 with ilp32. (#69129)
Mark any registers as CustomReg and any stack slot as CustomMem. This allows us to more directly emit the register or memory access for the high part. Previously we needed a memory access if the low register was X17 and we assumed the stack offset was 0. If the low part wasn't X17, we assumed the high register was the next register after the low register. This is another part of supporting FP arguments with GISel.
1 parent a559de0 commit 7f34355

File tree

1 file changed

+58
-38
lines changed

1 file changed

+58
-38
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16452,9 +16452,16 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
1645216452
return false;
1645316453
}
1645416454
LocVT = MVT::i32;
16455-
if (!State.AllocateReg(ArgGPRs))
16456-
State.AllocateStack(4, Align(4));
16457-
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
16455+
State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
16456+
Register HiReg = State.AllocateReg(ArgGPRs);
16457+
if (HiReg) {
16458+
State.addLoc(
16459+
CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo));
16460+
} else {
16461+
unsigned StackOffset = State.AllocateStack(4, Align(4));
16462+
State.addLoc(
16463+
CCValAssign::getCustomMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
16464+
}
1645816465
return false;
1645916466
}
1646016467

@@ -16763,7 +16770,9 @@ static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
1676316770
}
1676416771

1676516772
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain,
16766-
const CCValAssign &VA, const SDLoc &DL) {
16773+
const CCValAssign &VA,
16774+
const CCValAssign &HiVA,
16775+
const SDLoc &DL) {
1676716776
assert(VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64 &&
1676816777
"Unexpected VA");
1676916778
MachineFunction &MF = DAG.getMachineFunction();
@@ -16776,16 +16785,17 @@ static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain,
1677616785
RegInfo.addLiveIn(VA.getLocReg(), LoVReg);
1677716786
SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32);
1677816787
SDValue Hi;
16779-
if (VA.getLocReg() == RISCV::X17) {
16788+
if (HiVA.isMemLoc()) {
1678016789
// Second half of f64 is passed on the stack.
16781-
int FI = MFI.CreateFixedObject(4, 0, /*IsImmutable=*/true);
16790+
int FI = MFI.CreateFixedObject(4, HiVA.getLocMemOffset(),
16791+
/*IsImmutable=*/true);
1678216792
SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1678316793
Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN,
1678416794
MachinePointerInfo::getFixedStack(MF, FI));
1678516795
} else {
1678616796
// Second half of f64 is passed in another GPR.
1678716797
Register HiVReg = RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
16788-
RegInfo.addLiveIn(VA.getLocReg() + 1, HiVReg);
16798+
RegInfo.addLiveIn(HiVA.getLocReg(), HiVReg);
1678916799
Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32);
1679016800
}
1679116801
return DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
@@ -17028,15 +17038,16 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
1702817038
CallConv == CallingConv::Fast ? RISCV::CC_RISCV_FastCC
1702917039
: RISCV::CC_RISCV);
1703017040

17031-
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
17041+
for (unsigned i = 0, e = ArgLocs.size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
1703217042
CCValAssign &VA = ArgLocs[i];
1703317043
SDValue ArgValue;
1703417044
// Passing f64 on RV32D with a soft float ABI must be handled as a special
1703517045
// case.
17036-
if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64)
17037-
ArgValue = unpackF64OnRV32DSoftABI(DAG, Chain, VA, DL);
17038-
else if (VA.isRegLoc())
17039-
ArgValue = unpackFromRegLoc(DAG, Chain, VA, DL, Ins[i], *this);
17046+
if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
17047+
assert(VA.needsCustom());
17048+
ArgValue = unpackF64OnRV32DSoftABI(DAG, Chain, VA, ArgLocs[++i], DL);
17049+
} else if (VA.isRegLoc())
17050+
ArgValue = unpackFromRegLoc(DAG, Chain, VA, DL, Ins[InsIdx], *this);
1704017051
else
1704117052
ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL);
1704217053

@@ -17048,19 +17059,20 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
1704817059
// stores are relative to that.
1704917060
InVals.push_back(DAG.getLoad(VA.getValVT(), DL, Chain, ArgValue,
1705017061
MachinePointerInfo()));
17051-
unsigned ArgIndex = Ins[i].OrigArgIndex;
17052-
unsigned ArgPartOffset = Ins[i].PartOffset;
17062+
unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
17063+
unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
1705317064
assert(VA.getValVT().isVector() || ArgPartOffset == 0);
17054-
while (i + 1 != e && Ins[i + 1].OrigArgIndex == ArgIndex) {
17065+
while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
1705517066
CCValAssign &PartVA = ArgLocs[i + 1];
17056-
unsigned PartOffset = Ins[i + 1].PartOffset - ArgPartOffset;
17067+
unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
1705717068
SDValue Offset = DAG.getIntPtrConstant(PartOffset, DL);
1705817069
if (PartVA.getValVT().isScalableVector())
1705917070
Offset = DAG.getNode(ISD::VSCALE, DL, XLenVT, Offset);
1706017071
SDValue Address = DAG.getNode(ISD::ADD, DL, PtrVT, ArgValue, Offset);
1706117072
InVals.push_back(DAG.getLoad(PartVA.getValVT(), DL, Chain, Address,
1706217073
MachinePointerInfo()));
1706317074
++i;
17075+
++InsIdx;
1706417076
}
1706517077
continue;
1706617078
}
@@ -17276,14 +17288,16 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
1727617288
SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
1727717289
SmallVector<SDValue, 8> MemOpChains;
1727817290
SDValue StackPtr;
17279-
for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) {
17291+
for (unsigned i = 0, j = 0, e = ArgLocs.size(), OutIdx = 0; i != e;
17292+
++i, ++OutIdx) {
1728017293
CCValAssign &VA = ArgLocs[i];
17281-
SDValue ArgValue = OutVals[i];
17282-
ISD::ArgFlagsTy Flags = Outs[i].Flags;
17294+
SDValue ArgValue = OutVals[OutIdx];
17295+
ISD::ArgFlagsTy Flags = Outs[OutIdx].Flags;
1728317296

1728417297
// Handle passing f64 on RV32D with a soft float ABI as a special case.
1728517298
if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
1728617299
assert(VA.isRegLoc() && "Expected register VA assignment");
17300+
assert(VA.needsCustom());
1728717301
SDValue SplitF64 = DAG.getNode(
1728817302
RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32), ArgValue);
1728917303
SDValue Lo = SplitF64.getValue(0);
@@ -17292,18 +17306,22 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
1729217306
Register RegLo = VA.getLocReg();
1729317307
RegsToPass.push_back(std::make_pair(RegLo, Lo));
1729417308

17295-
if (RegLo == RISCV::X17) {
17309+
// Get the CCValAssign for the Hi part.
17310+
CCValAssign &HiVA = ArgLocs[++i];
17311+
17312+
if (HiVA.isMemLoc()) {
1729617313
// Second half of f64 is passed on the stack.
17297-
// Work out the address of the stack slot.
1729817314
if (!StackPtr.getNode())
1729917315
StackPtr = DAG.getCopyFromReg(Chain, DL, RISCV::X2, PtrVT);
17316+
SDValue Address =
17317+
DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,
17318+
DAG.getIntPtrConstant(HiVA.getLocMemOffset(), DL));
1730017319
// Emit the store.
1730117320
MemOpChains.push_back(
17302-
DAG.getStore(Chain, DL, Hi, StackPtr, MachinePointerInfo()));
17321+
DAG.getStore(Chain, DL, Hi, Address, MachinePointerInfo()));
1730317322
} else {
1730417323
// Second half of f64 is passed in another GPR.
17305-
assert(RegLo < RISCV::X31 && "Invalid register pair");
17306-
Register RegHigh = RegLo + 1;
17324+
Register RegHigh = HiVA.getLocReg();
1730717325
RegsToPass.push_back(std::make_pair(RegHigh, Hi));
1730817326
}
1730917327
continue;
@@ -17314,24 +17332,24 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
1731417332
if (VA.getLocInfo() == CCValAssign::Indirect) {
1731517333
// Store the argument in a stack slot and pass its address.
1731617334
Align StackAlign =
17317-
std::max(getPrefTypeAlign(Outs[i].ArgVT, DAG),
17335+
std::max(getPrefTypeAlign(Outs[OutIdx].ArgVT, DAG),
1731817336
getPrefTypeAlign(ArgValue.getValueType(), DAG));
1731917337
TypeSize StoredSize = ArgValue.getValueType().getStoreSize();
1732017338
// If the original argument was split (e.g. i128), we need
1732117339
// to store the required parts of it here (and pass just one address).
1732217340
// Vectors may be partly split to registers and partly to the stack, in
1732317341
// which case the base address is partly offset and subsequent stores are
1732417342
// relative to that.
17325-
unsigned ArgIndex = Outs[i].OrigArgIndex;
17326-
unsigned ArgPartOffset = Outs[i].PartOffset;
17343+
unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
17344+
unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
1732717345
assert(VA.getValVT().isVector() || ArgPartOffset == 0);
1732817346
// Calculate the total size to store. We don't have access to what we're
1732917347
// actually storing other than performing the loop and collecting the
1733017348
// info.
1733117349
SmallVector<std::pair<SDValue, SDValue>> Parts;
17332-
while (i + 1 != e && Outs[i + 1].OrigArgIndex == ArgIndex) {
17333-
SDValue PartValue = OutVals[i + 1];
17334-
unsigned PartOffset = Outs[i + 1].PartOffset - ArgPartOffset;
17350+
while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
17351+
SDValue PartValue = OutVals[OutIdx + 1];
17352+
unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
1733517353
SDValue Offset = DAG.getIntPtrConstant(PartOffset, DL);
1733617354
EVT PartVT = PartValue.getValueType();
1733717355
if (PartVT.isScalableVector())
@@ -17340,6 +17358,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
1734017358
StackAlign = std::max(StackAlign, getPrefTypeAlign(PartVT, DAG));
1734117359
Parts.push_back(std::make_pair(PartValue, Offset));
1734217360
++i;
17361+
++OutIdx;
1734317362
}
1734417363
SDValue SpillSlot = DAG.CreateStackTemporary(StoredSize, StackAlign);
1734517364
int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
@@ -17481,7 +17500,8 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
1748117500
analyzeInputArgs(MF, RetCCInfo, Ins, /*IsRet=*/true, RISCV::CC_RISCV);
1748217501

1748317502
// Copy all of the result registers out of their specified physreg.
17484-
for (auto &VA : RVLocs) {
17503+
for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
17504+
auto &VA = RVLocs[i];
1748517505
// Copy the value out
1748617506
SDValue RetValue =
1748717507
DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);
@@ -17490,9 +17510,9 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
1749017510
Glue = RetValue.getValue(2);
1749117511

1749217512
if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
17493-
assert(VA.getLocReg() == ArgGPRs[0] && "Unexpected reg assignment");
17494-
SDValue RetValue2 =
17495-
DAG.getCopyFromReg(Chain, DL, ArgGPRs[1], MVT::i32, Glue);
17513+
assert(VA.needsCustom());
17514+
SDValue RetValue2 = DAG.getCopyFromReg(Chain, DL, RVLocs[++i].getLocReg(),
17515+
MVT::i32, Glue);
1749617516
Chain = RetValue2.getValue(1);
1749717517
Glue = RetValue2.getValue(2);
1749817518
RetValue = DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, RetValue,
@@ -17555,21 +17575,21 @@ RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
1755517575
SmallVector<SDValue, 4> RetOps(1, Chain);
1755617576

1755717577
// Copy the result values into the output registers.
17558-
for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
17559-
SDValue Val = OutVals[i];
17578+
for (unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
17579+
SDValue Val = OutVals[OutIdx];
1756017580
CCValAssign &VA = RVLocs[i];
1756117581
assert(VA.isRegLoc() && "Can only return in registers!");
1756217582

1756317583
if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
1756417584
// Handle returning f64 on RV32D with a soft float ABI.
1756517585
assert(VA.isRegLoc() && "Expected return via registers");
17586+
assert(VA.needsCustom());
1756617587
SDValue SplitF64 = DAG.getNode(RISCVISD::SplitF64, DL,
1756717588
DAG.getVTList(MVT::i32, MVT::i32), Val);
1756817589
SDValue Lo = SplitF64.getValue(0);
1756917590
SDValue Hi = SplitF64.getValue(1);
1757017591
Register RegLo = VA.getLocReg();
17571-
assert(RegLo < RISCV::X31 && "Invalid register pair");
17572-
Register RegHi = RegLo + 1;
17592+
Register RegHi = RVLocs[++i].getLocReg();
1757317593

1757417594
if (STI.isRegisterReservedByUser(RegLo) ||
1757517595
STI.isRegisterReservedByUser(RegHi))

0 commit comments

Comments
 (0)