Skip to content

Commit 3c5b42a

Browse files
authored
[RISCV] Allocate the varargs GPR save area as a single object. (llvm#74354)
Previously we allocated one object for each GPR. We also allocated the same offset twice, once to save for VASTART and then again for the first register in the save loop. This patch uses a single object for all the registers and shares this with VASTART. This is more consistent with other targets like AArch64 and ARM. I've removed the setValue(nullptr) from the memory operand now. Having a single object makes me a lot more comfortable about alias analysis being able to see what is going on. This led to the scheduling changes in push-pop-popret.ll and vararg.ll.
1 parent 02f4b36 commit 3c5b42a

File tree

4 files changed

+221
-190
lines changed

4 files changed

+221
-190
lines changed

llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -432,60 +432,63 @@ void RISCVCallLowering::saveVarArgRegisters(
432432
const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
433433
unsigned XLenInBytes = Subtarget.getXLen() / 8;
434434
ArrayRef<MCPhysReg> ArgRegs = RISCV::getArgGPRs();
435+
MachineRegisterInfo &MRI = MF.getRegInfo();
435436
unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
437+
MachineFrameInfo &MFI = MF.getFrameInfo();
438+
RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
436439

437-
// Offset of the first variable argument from stack pointer, and size of
438-
// the vararg save area. For now, the varargs save area is either zero or
439-
// large enough to hold a0-a7.
440-
int VaArgOffset;
440+
// Size of the vararg save area. For now, the varargs save area is either
441+
// zero or large enough to hold a0-a7.
441442
int VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
443+
int FI;
442444

443445
// If all registers are allocated, then all varargs must be passed on the
444446
// stack and we don't need to save any argregs.
445447
if (VarArgsSaveSize == 0) {
446-
VaArgOffset = Assigner.StackSize;
448+
int VaArgOffset = Assigner.StackSize;
449+
FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
447450
} else {
448-
VaArgOffset = -VarArgsSaveSize;
451+
int VaArgOffset = -VarArgsSaveSize;
452+
FI = MFI.CreateFixedObject(VarArgsSaveSize, VaArgOffset, true);
453+
454+
// If saving an odd number of registers then create an extra stack slot to
455+
// ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
456+
// offsets to even-numbered registered remain 2*XLEN-aligned.
457+
if (Idx % 2) {
458+
MFI.CreateFixedObject(XLenInBytes,
459+
VaArgOffset - static_cast<int>(XLenInBytes), true);
460+
VarArgsSaveSize += XLenInBytes;
461+
}
462+
463+
const LLT p0 = LLT::pointer(MF.getDataLayout().getAllocaAddrSpace(),
464+
Subtarget.getXLen());
465+
const LLT sXLen = LLT::scalar(Subtarget.getXLen());
466+
467+
auto FIN = MIRBuilder.buildFrameIndex(p0, FI);
468+
auto Offset = MIRBuilder.buildConstant(
469+
MRI.createGenericVirtualRegister(sXLen), XLenInBytes);
470+
471+
// Copy the integer registers that may have been used for passing varargs
472+
// to the vararg save area.
473+
const MVT XLenVT = Subtarget.getXLenVT();
474+
for (unsigned I = Idx; I < ArgRegs.size(); ++I) {
475+
const Register VReg = MRI.createGenericVirtualRegister(sXLen);
476+
Handler.assignValueToReg(
477+
VReg, ArgRegs[I],
478+
CCValAssign::getReg(I + MF.getFunction().getNumOperands(), XLenVT,
479+
ArgRegs[I], XLenVT, CCValAssign::Full));
480+
auto MPO =
481+
MachinePointerInfo::getFixedStack(MF, FI, (I - Idx) * XLenInBytes);
482+
MIRBuilder.buildStore(VReg, FIN, MPO, inferAlignFromPtrInfo(MF, MPO));
483+
FIN = MIRBuilder.buildPtrAdd(MRI.createGenericVirtualRegister(p0),
484+
FIN.getReg(0), Offset);
485+
}
449486
}
450487

451488
// Record the frame index of the first variable argument which is a value
452489
// necessary to G_VASTART.
453-
MachineFrameInfo &MFI = MF.getFrameInfo();
454-
int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
455-
RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
456490
RVFI->setVarArgsFrameIndex(FI);
457-
458-
// If saving an odd number of registers then create an extra stack slot to
459-
// ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
460-
// offsets to even-numbered registered remain 2*XLEN-aligned.
461-
if (Idx % 2) {
462-
MFI.CreateFixedObject(XLenInBytes, VaArgOffset - (int)XLenInBytes, true);
463-
VarArgsSaveSize += XLenInBytes;
464-
}
465491
RVFI->setVarArgsSaveSize(VarArgsSaveSize);
466-
467-
// Copy the integer registers that may have been used for passing varargs
468-
// to the vararg save area.
469-
const LLT p0 = LLT::pointer(MF.getDataLayout().getAllocaAddrSpace(),
470-
Subtarget.getXLen());
471-
const LLT sXLen = LLT::scalar(Subtarget.getXLen());
472-
const MVT XLenVT = Subtarget.getXLenVT();
473-
MachineRegisterInfo &MRI = MF.getRegInfo();
474-
for (unsigned I = Idx; I < ArgRegs.size(); ++I, VaArgOffset += XLenInBytes) {
475-
const Register VReg = MRI.createGenericVirtualRegister(sXLen);
476-
Handler.assignValueToReg(
477-
VReg, ArgRegs[I],
478-
CCValAssign::getReg(I + MF.getFunction().getNumOperands(), XLenVT,
479-
ArgRegs[I], XLenVT, CCValAssign::Full));
480-
FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
481-
auto FIN = MIRBuilder.buildFrameIndex(p0, FI);
482-
auto MPO = MachinePointerInfo::getFixedStack(MF, FI);
483-
auto Store =
484-
MIRBuilder.buildStore(VReg, FIN, MPO, inferAlignFromPtrInfo(MF, MPO));
485-
// This was taken from SelectionDAG, but we are not sure why it exists.
486-
// It is being investigated in github.com/llvm/llvm-project/issues/73735.
487-
Store->memoperands()[0]->setValue((Value *)nullptr);
488-
}
489492
}
490493

491494
bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17698,49 +17698,49 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
1769817698
MachineRegisterInfo &RegInfo = MF.getRegInfo();
1769917699
RISCVMachineFunctionInfo *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
1770017700

17701-
// Offset of the first variable argument from stack pointer, and size of
17702-
// the vararg save area. For now, the varargs save area is either zero or
17703-
// large enough to hold a0-a7.
17704-
int VaArgOffset;
17701+
// Size of the vararg save area. For now, the varargs save area is either
17702+
// zero or large enough to hold a0-a7.
1770517703
int VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
17704+
int FI;
1770617705

1770717706
// If all registers are allocated, then all varargs must be passed on the
1770817707
// stack and we don't need to save any argregs.
1770917708
if (VarArgsSaveSize == 0) {
17710-
VaArgOffset = CCInfo.getStackSize();
17709+
int VaArgOffset = CCInfo.getStackSize();
17710+
FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
1771117711
} else {
17712-
VaArgOffset = -VarArgsSaveSize;
17712+
int VaArgOffset = -VarArgsSaveSize;
17713+
FI = MFI.CreateFixedObject(VarArgsSaveSize, VaArgOffset, true);
17714+
17715+
// If saving an odd number of registers then create an extra stack slot to
17716+
// ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
17717+
// offsets to even-numbered registered remain 2*XLEN-aligned.
17718+
if (Idx % 2) {
17719+
MFI.CreateFixedObject(
17720+
XLenInBytes, VaArgOffset - static_cast<int>(XLenInBytes), true);
17721+
VarArgsSaveSize += XLenInBytes;
17722+
}
17723+
17724+
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
17725+
17726+
// Copy the integer registers that may have been used for passing varargs
17727+
// to the vararg save area.
17728+
for (unsigned I = Idx; I < ArgRegs.size(); ++I) {
17729+
const Register Reg = RegInfo.createVirtualRegister(RC);
17730+
RegInfo.addLiveIn(ArgRegs[I], Reg);
17731+
SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT);
17732+
SDValue Store = DAG.getStore(
17733+
Chain, DL, ArgValue, FIN,
17734+
MachinePointerInfo::getFixedStack(MF, FI, (I - Idx) * XLenInBytes));
17735+
OutChains.push_back(Store);
17736+
FIN =
17737+
DAG.getMemBasePlusOffset(FIN, TypeSize::getFixed(XLenInBytes), DL);
17738+
}
1771317739
}
1771417740

1771517741
// Record the frame index of the first variable argument
1771617742
// which is a value necessary to VASTART.
17717-
int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
1771817743
RVFI->setVarArgsFrameIndex(FI);
17719-
17720-
// If saving an odd number of registers then create an extra stack slot to
17721-
// ensure that the frame pointer is 2*XLEN-aligned, which in turn ensures
17722-
// offsets to even-numbered registered remain 2*XLEN-aligned.
17723-
if (Idx % 2) {
17724-
MFI.CreateFixedObject(XLenInBytes, VaArgOffset - (int)XLenInBytes, true);
17725-
VarArgsSaveSize += XLenInBytes;
17726-
}
17727-
17728-
// Copy the integer registers that may have been used for passing varargs
17729-
// to the vararg save area.
17730-
for (unsigned I = Idx; I < ArgRegs.size();
17731-
++I, VaArgOffset += XLenInBytes) {
17732-
const Register Reg = RegInfo.createVirtualRegister(RC);
17733-
RegInfo.addLiveIn(ArgRegs[I], Reg);
17734-
SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT);
17735-
FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
17736-
SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
17737-
SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
17738-
MachinePointerInfo::getFixedStack(MF, FI));
17739-
cast<StoreSDNode>(Store.getNode())
17740-
->getMemOperand()
17741-
->setValue((Value *)nullptr);
17742-
OutChains.push_back(Store);
17743-
}
1774417744
RVFI->setVarArgsSaveSize(VarArgsSaveSize);
1774517745
}
1774617746

0 commit comments

Comments
 (0)