summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Mips/MipsISelLowering.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Target/Mips/MipsISelLowering.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/Target/Mips/MipsISelLowering.cpp')
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.cpp81
1 files changed, 49 insertions, 32 deletions
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 8b599bca3915..9399c949a3f2 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -122,9 +122,7 @@ unsigned MipsTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context,
CallingConv::ID CC,
EVT VT) const {
if (VT.isVector())
- return std::max(((unsigned)VT.getSizeInBits() /
- (Subtarget.isABI_O32() ? 32 : 64)),
- 1U);
+ return divideCeil(VT.getSizeInBits(), Subtarget.isABI_O32() ? 32 : 64);
return MipsTargetLowering::getNumRegisters(Context, VT);
}
@@ -134,10 +132,10 @@ unsigned MipsTargetLowering::getVectorTypeBreakdownForCallingConv(
// Break down vector types to either 2 i64s or 4 i32s.
RegisterVT = getRegisterTypeForCallingConv(Context, CC, VT);
IntermediateVT = RegisterVT;
- NumIntermediates = VT.getFixedSizeInBits() < RegisterVT.getFixedSizeInBits()
- ? VT.getVectorNumElements()
- : VT.getSizeInBits() / RegisterVT.getSizeInBits();
-
+ NumIntermediates =
+ VT.getFixedSizeInBits() < RegisterVT.getFixedSizeInBits()
+ ? VT.getVectorNumElements()
+ : divideCeil(VT.getSizeInBits(), RegisterVT.getSizeInBits());
return NumIntermediates;
}
@@ -2928,13 +2926,23 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
Reg = State.AllocateReg(IntRegs);
LocVT = MVT::i32;
} else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) {
+ LocVT = MVT::i32;
+
// Allocate int register and shadow next int register. If first
// available register is Mips::A1 or Mips::A3, shadow it too.
Reg = State.AllocateReg(IntRegs);
if (Reg == Mips::A1 || Reg == Mips::A3)
Reg = State.AllocateReg(IntRegs);
- State.AllocateReg(IntRegs);
- LocVT = MVT::i32;
+
+ if (Reg) {
+ State.addLoc(
+ CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+ MCRegister HiReg = State.AllocateReg(IntRegs);
+ assert(HiReg);
+ State.addLoc(
+ CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo));
+ return false;
+ }
} else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) {
// we are guaranteed to find an available float register
if (ValVT == MVT::f32) {
@@ -2994,12 +3002,6 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
// Call Calling Convention Implementation
//===----------------------------------------------------------------------===//
-// Return next O32 integer argument register.
-static unsigned getNextIntArgReg(unsigned Reg) {
- assert((Reg == Mips::A0) || (Reg == Mips::A2));
- return (Reg == Mips::A0) ? Mips::A1 : Mips::A3;
-}
-
SDValue MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset,
SDValue Chain, SDValue Arg,
const SDLoc &DL, bool IsTailCall,
@@ -3251,11 +3253,11 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
CCInfo.rewindByValRegsInfo();
// Walk the register/memloc assignments, inserting copies/loads.
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- SDValue Arg = OutVals[i];
+ for (unsigned i = 0, e = ArgLocs.size(), OutIdx = 0; i != e; ++i, ++OutIdx) {
+ SDValue Arg = OutVals[OutIdx];
CCValAssign &VA = ArgLocs[i];
MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT();
- ISD::ArgFlagsTy Flags = Outs[i].Flags;
+ ISD::ArgFlagsTy Flags = Outs[OutIdx].Flags;
bool UseUpperBits = false;
// ByVal Arg.
@@ -3293,8 +3295,11 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
Arg, DAG.getConstant(1, DL, MVT::i32));
if (!Subtarget.isLittle())
std::swap(Lo, Hi);
+
+ assert(VA.needsCustom());
+
Register LocRegLo = VA.getLocReg();
- unsigned LocRegHigh = getNextIntArgReg(LocRegLo);
+ Register LocRegHigh = ArgLocs[++i].getLocReg();
RegsToPass.push_back(std::make_pair(LocRegLo, Lo));
RegsToPass.push_back(std::make_pair(LocRegHigh, Hi));
continue;
@@ -3325,7 +3330,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
}
if (UseUpperBits) {
- unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits();
+ unsigned ValSizeInBits = Outs[OutIdx].ArgVT.getSizeInBits();
unsigned LocSizeInBits = VA.getLocVT().getSizeInBits();
Arg = DAG.getNode(
ISD::SHL, DL, VA.getLocVT(), Arg,
@@ -3636,18 +3641,18 @@ SDValue MipsTargetLowering::LowerFormalArguments(
unsigned CurArgIdx = 0;
CCInfo.rewindByValRegsInfo();
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ for (unsigned i = 0, e = ArgLocs.size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
CCValAssign &VA = ArgLocs[i];
- if (Ins[i].isOrigArg()) {
- std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx);
- CurArgIdx = Ins[i].getOrigArgIndex();
+ if (Ins[InsIdx].isOrigArg()) {
+ std::advance(FuncArg, Ins[InsIdx].getOrigArgIndex() - CurArgIdx);
+ CurArgIdx = Ins[InsIdx].getOrigArgIndex();
}
EVT ValVT = VA.getValVT();
- ISD::ArgFlagsTy Flags = Ins[i].Flags;
+ ISD::ArgFlagsTy Flags = Ins[InsIdx].Flags;
bool IsRegLoc = VA.isRegLoc();
if (Flags.isByVal()) {
- assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit");
+ assert(Ins[InsIdx].isOrigArg() && "Byval arguments cannot be implicit");
unsigned FirstByValReg, LastByValReg;
unsigned ByValIdx = CCInfo.getInRegsParamsProcessed();
CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg);
@@ -3672,7 +3677,8 @@ SDValue MipsTargetLowering::LowerFormalArguments(
unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC);
SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT);
- ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG);
+ ArgValue =
+ UnpackFromArgumentSlot(ArgValue, VA, Ins[InsIdx].ArgVT, DL, DAG);
// Handle floating point arguments passed in integer registers and
// long double arguments passed in floating point registers.
@@ -3682,8 +3688,10 @@ SDValue MipsTargetLowering::LowerFormalArguments(
ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue);
else if (ABI.IsO32() && RegVT == MVT::i32 &&
ValVT == MVT::f64) {
- unsigned Reg2 = addLiveIn(DAG.getMachineFunction(),
- getNextIntArgReg(ArgReg), RC);
+ assert(VA.needsCustom() && "Expected custom argument for f64 split");
+ CCValAssign &NextVA = ArgLocs[++i];
+ unsigned Reg2 =
+ addLiveIn(DAG.getMachineFunction(), NextVA.getLocReg(), RC);
SDValue ArgValue2 = DAG.getCopyFromReg(Chain, DL, Reg2, RegVT);
if (!Subtarget.isLittle())
std::swap(ArgValue, ArgValue2);
@@ -3695,6 +3703,8 @@ SDValue MipsTargetLowering::LowerFormalArguments(
} else { // VA.isRegLoc()
MVT LocVT = VA.getLocVT();
+ assert(!VA.needsCustom() && "unexpected custom memory argument");
+
if (ABI.IsO32()) {
// We ought to be able to use LocVT directly but O32 sets it to i32
// when allocating floating point values to integer registers.
@@ -3718,17 +3728,24 @@ SDValue MipsTargetLowering::LowerFormalArguments(
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));
OutChains.push_back(ArgValue.getValue(1));
- ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG);
+ ArgValue =
+ UnpackFromArgumentSlot(ArgValue, VA, Ins[InsIdx].ArgVT, DL, DAG);
InVals.push_back(ArgValue);
}
}
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ for (unsigned i = 0, e = ArgLocs.size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
+
+ if (ArgLocs[i].needsCustom()) {
+ ++i;
+ continue;
+ }
+
// The mips ABIs for returning structs by value requires that we copy
// the sret argument into $v0 for the return. Save the argument into
// a virtual register so that we can access it from the return points.
- if (Ins[i].Flags.isSRet()) {
+ if (Ins[InsIdx].Flags.isSRet()) {
unsigned Reg = MipsFI->getSRetReturnReg();
if (!Reg) {
Reg = MF.getRegInfo().createVirtualRegister(