diff options
Diffstat (limited to 'lib/Target/ARM/ARMCallLowering.cpp')
| -rw-r--r-- | lib/Target/ARM/ARMCallLowering.cpp | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp index 47f998b696f5..8e80c32bcf89 100644 --- a/lib/Target/ARM/ARMCallLowering.cpp +++ b/lib/Target/ARM/ARMCallLowering.cpp @@ -237,7 +237,7 @@ void ARMCallLowering::splitToValueTypes( /// Lower the return value for the already existing \p Ret. This assumes that /// \p MIRBuilder's insertion point is correct. bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, - const Value *Val, unsigned VReg, + const Value *Val, ArrayRef<unsigned> VRegs, MachineInstrBuilder &Ret) const { if (!Val) // Nothing to do here. @@ -251,16 +251,24 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, if (!isSupportedType(DL, TLI, Val->getType())) return false; - SmallVector<ArgInfo, 4> SplitVTs; - SmallVector<unsigned, 4> Regs; - ArgInfo RetInfo(VReg, Val->getType()); - setArgFlags(RetInfo, AttributeList::ReturnIndex, DL, F); - splitToValueTypes(RetInfo, SplitVTs, MF, [&](unsigned Reg, uint64_t Offset) { - Regs.push_back(Reg); - }); + SmallVector<EVT, 4> SplitEVTs; + ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs); + assert(VRegs.size() == SplitEVTs.size() && + "For each split Type there should be exactly one VReg."); - if (Regs.size() > 1) - MIRBuilder.buildUnmerge(Regs, VReg); + SmallVector<ArgInfo, 4> SplitVTs; + LLVMContext &Ctx = Val->getType()->getContext(); + for (unsigned i = 0; i < SplitEVTs.size(); ++i) { + ArgInfo CurArgInfo(VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx)); + setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); + + SmallVector<unsigned, 4> Regs; + splitToValueTypes( + CurArgInfo, SplitVTs, MF, + [&](unsigned Reg, uint64_t Offset) { Regs.push_back(Reg); }); + if (Regs.size() > 1) + MIRBuilder.buildUnmerge(Regs, VRegs[i]); + } CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); @@ -270,14 +278,15 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, } bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, - const Value *Val, unsigned VReg) const { - assert(!Val == !VReg && "Return value without a vreg"); + const Value *Val, + ArrayRef<unsigned> VRegs) const { + assert(!Val == VRegs.empty() && "Return value without a vreg"); auto const &ST = MIRBuilder.getMF().getSubtarget<ARMSubtarget>(); unsigned Opcode = ST.getReturnOpcode(); auto Ret = MIRBuilder.buildInstrNoInsert(Opcode).add(predOps(ARMCC::AL)); - if (!lowerReturnVal(MIRBuilder, Val, VReg, Ret)) + if (!lowerReturnVal(MIRBuilder, Val, VRegs, Ret)) return false; MIRBuilder.insertInstr(Ret); @@ -420,7 +429,7 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, auto &TLI = *getTLI<ARMTargetLowering>(); auto Subtarget = TLI.getSubtarget(); - if (Subtarget->isThumb()) + if (Subtarget->isThumb1Only()) return false; // Quick exit if there aren't any args @@ -491,6 +500,22 @@ struct CallReturnHandler : public IncomingValueHandler { MachineInstrBuilder MIB; }; +// FIXME: This should move to the ARMSubtarget when it supports all the opcodes. +unsigned getCallOpcode(const ARMSubtarget &STI, bool isDirect) { + if (isDirect) + return STI.isThumb() ? ARM::tBL : ARM::BL; + + if (STI.isThumb()) + return ARM::tBLXr; + + if (STI.hasV5TOps()) + return ARM::BLX; + + if (STI.hasV4TOps()) + return ARM::BX_CALL; + + return ARM::BMOVPCRX_CALL; +} } // end anonymous namespace bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, @@ -508,27 +533,34 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, if (STI.genLongCalls()) return false; + if (STI.isThumb1Only()) + return false; + auto CallSeqStart = MIRBuilder.buildInstr(ARM::ADJCALLSTACKDOWN); // Create the call instruction so we can add the implicit uses of arg // registers, but don't insert it yet. bool isDirect = !Callee.isReg(); - auto CallOpcode = - isDirect ? ARM::BL - : STI.hasV5TOps() - ? ARM::BLX - : STI.hasV4TOps() ? ARM::BX_CALL : ARM::BMOVPCRX_CALL; - auto MIB = MIRBuilder.buildInstrNoInsert(CallOpcode) - .add(Callee) - .addRegMask(TRI->getCallPreservedMask(MF, CallConv)); - if (Callee.isReg()) { + auto CallOpcode = getCallOpcode(STI, isDirect); + auto MIB = MIRBuilder.buildInstrNoInsert(CallOpcode); + + bool isThumb = STI.isThumb(); + if (isThumb) + MIB.add(predOps(ARMCC::AL)); + + MIB.add(Callee); + if (!isDirect) { auto CalleeReg = Callee.getReg(); - if (CalleeReg && !TRI->isPhysicalRegister(CalleeReg)) - MIB->getOperand(0).setReg(constrainOperandRegClass( + if (CalleeReg && !TRI->isPhysicalRegister(CalleeReg)) { + unsigned CalleeIdx = isThumb ? 2 : 0; + MIB->getOperand(CalleeIdx).setReg(constrainOperandRegClass( MF, *TRI, MRI, *STI.getInstrInfo(), *STI.getRegBankInfo(), - *MIB.getInstr(), MIB->getDesc(), Callee, 0)); + *MIB.getInstr(), MIB->getDesc(), Callee, CalleeIdx)); + } } + MIB.addRegMask(TRI->getCallPreservedMask(MF, CallConv)); + SmallVector<ArgInfo, 8> ArgInfos; for (auto Arg : OrigArgs) { if (!isSupportedType(DL, TLI, Arg.Ty)) |
