diff options
Diffstat (limited to 'llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp index b9faad453aba..43928d7c2a09 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp @@ -60,7 +60,7 @@ struct AMDGPUOutgoingValueHandler : public CallLowering::OutgoingValueHandler { } void assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign &VA) override { + CCValAssign VA) override { Register ExtReg = extendRegisterMin32(*this, ValVReg, VA); // If this is a scalar return, insert a readfirstlane just in case the value @@ -103,7 +103,7 @@ struct AMDGPUIncomingArgHandler : public CallLowering::IncomingValueHandler { } void assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign &VA) override { + CCValAssign VA) override { markPhysRegUsed(PhysReg); if (VA.getLocVT().getSizeInBits() < 32) { @@ -203,7 +203,7 @@ struct AMDGPUOutgoingArgHandler : public AMDGPUOutgoingValueHandler { } void assignValueToReg(Register ValVReg, Register PhysReg, - CCValAssign &VA) override { + CCValAssign VA) override { MIB.addUse(PhysReg, RegState::Implicit); Register ExtReg = extendRegisterMin32(*this, ValVReg, VA); MIRBuilder.buildCopy(PhysReg, ExtReg); @@ -236,7 +236,7 @@ AMDGPUCallLowering::AMDGPUCallLowering(const AMDGPUTargetLowering &TLI) : CallLowering(&TLI) { } -// FIXME: Compatability shim +// FIXME: Compatibility shim static ISD::NodeType extOpcodeToISDExtOpcode(unsigned MIOpc) { switch (MIOpc) { case TargetOpcode::G_SEXT: @@ -355,14 +355,23 @@ bool AMDGPUCallLowering::lowerReturn(MachineIRBuilder &B, const Value *Val, auto const &ST = MF.getSubtarget<GCNSubtarget>(); - unsigned ReturnOpc = - IsShader ? AMDGPU::SI_RETURN_TO_EPILOG : AMDGPU::S_SETPC_B64_return; + unsigned ReturnOpc = 0; + if (IsShader) + ReturnOpc = AMDGPU::SI_RETURN_TO_EPILOG; + else if (CC == CallingConv::AMDGPU_Gfx) + ReturnOpc = AMDGPU::S_SETPC_B64_return_gfx; + else + ReturnOpc = AMDGPU::S_SETPC_B64_return; auto Ret = B.buildInstrNoInsert(ReturnOpc); Register ReturnAddrVReg; if (ReturnOpc == AMDGPU::S_SETPC_B64_return) { ReturnAddrVReg = MRI.createVirtualRegister(&AMDGPU::CCR_SGPR_64RegClass); Ret.addUse(ReturnAddrVReg); + } else if (ReturnOpc == AMDGPU::S_SETPC_B64_return_gfx) { + ReturnAddrVReg = + MRI.createVirtualRegister(&AMDGPU::Gfx_CCR_SGPR_64RegClass); + Ret.addUse(ReturnAddrVReg); } if (!FLI.CanLowerReturn) @@ -370,7 +379,8 @@ bool AMDGPUCallLowering::lowerReturn(MachineIRBuilder &B, const Value *Val, else if (!lowerReturnVal(B, Val, VRegs, Ret)) return false; - if (ReturnOpc == AMDGPU::S_SETPC_B64_return) { + if (ReturnOpc == AMDGPU::S_SETPC_B64_return || + ReturnOpc == AMDGPU::S_SETPC_B64_return_gfx) { const SIRegisterInfo *TRI = ST.getRegisterInfo(); Register LiveInReturn = MF.addLiveIn(TRI->getReturnAddressReg(MF), &AMDGPU::SGPR_64RegClass); @@ -753,6 +763,11 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const { MachineFunction &MF = MIRBuilder.getMF(); + // If there's no call site, this doesn't correspond to a call from the IR and + // doesn't need implicit inputs. + if (!Info.CB) + return true; + const AMDGPUFunctionArgInfo *CalleeArgInfo = &AMDGPUArgumentUsageInfo::FixedABIFunctionInfo; @@ -773,17 +788,32 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, AMDGPUFunctionArgInfo::WORKGROUP_ID_Z }; + static constexpr StringLiteral ImplicitAttrNames[] = { + "amdgpu-no-dispatch-ptr", + "amdgpu-no-queue-ptr", + "amdgpu-no-implicitarg-ptr", + "amdgpu-no-dispatch-id", + "amdgpu-no-workgroup-id-x", + "amdgpu-no-workgroup-id-y", + "amdgpu-no-workgroup-id-z" + }; + MachineRegisterInfo &MRI = MF.getRegInfo(); const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); const AMDGPULegalizerInfo *LI = static_cast<const AMDGPULegalizerInfo*>(ST.getLegalizerInfo()); + unsigned I = 0; for (auto InputID : InputRegs) { const ArgDescriptor *OutgoingArg; const TargetRegisterClass *ArgRC; LLT ArgTy; + // If the callee does not use the attribute value, skip copying the value. + if (Info.CB->hasFnAttr(ImplicitAttrNames[I++])) + continue; + std::tie(OutgoingArg, ArgRC, ArgTy) = CalleeArgInfo->getPreloadedValue(InputID); if (!OutgoingArg) @@ -843,16 +873,22 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, const ArgDescriptor *IncomingArgZ = std::get<0>(WorkitemIDZ); const LLT S32 = LLT::scalar(32); + const bool NeedWorkItemIDX = !Info.CB->hasFnAttr("amdgpu-no-workitem-id-x"); + const bool NeedWorkItemIDY = !Info.CB->hasFnAttr("amdgpu-no-workitem-id-y"); + const bool NeedWorkItemIDZ = !Info.CB->hasFnAttr("amdgpu-no-workitem-id-z"); + // If incoming ids are not packed we need to pack them. // FIXME: Should consider known workgroup size to eliminate known 0 cases. Register InputReg; - if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo->WorkItemIDX) { + if (IncomingArgX && !IncomingArgX->isMasked() && CalleeArgInfo->WorkItemIDX && + NeedWorkItemIDX) { InputReg = MRI.createGenericVirtualRegister(S32); LI->loadInputValue(InputReg, MIRBuilder, IncomingArgX, std::get<1>(WorkitemIDX), std::get<2>(WorkitemIDX)); } - if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo->WorkItemIDY) { + if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo->WorkItemIDY && + NeedWorkItemIDY) { Register Y = MRI.createGenericVirtualRegister(S32); LI->loadInputValue(Y, MIRBuilder, IncomingArgY, std::get<1>(WorkitemIDY), std::get<2>(WorkitemIDY)); @@ -861,7 +897,8 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, InputReg = InputReg ? MIRBuilder.buildOr(S32, InputReg, Y).getReg(0) : Y; } - if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo->WorkItemIDZ) { + if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo->WorkItemIDZ && + NeedWorkItemIDZ) { Register Z = MRI.createGenericVirtualRegister(S32); LI->loadInputValue(Z, MIRBuilder, IncomingArgZ, std::get<1>(WorkitemIDZ), std::get<2>(WorkitemIDZ)); @@ -870,7 +907,7 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, InputReg = InputReg ? MIRBuilder.buildOr(S32, InputReg, Z).getReg(0) : Z; } - if (!InputReg) { + if (!InputReg && (NeedWorkItemIDX || NeedWorkItemIDY || NeedWorkItemIDZ)) { InputReg = MRI.createGenericVirtualRegister(S32); // Workitem ids are already packed, any of present incoming arguments will @@ -883,7 +920,9 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, } if (OutgoingArg->isRegister()) { - ArgRegs.emplace_back(OutgoingArg->getRegister(), InputReg); + if (InputReg) + ArgRegs.emplace_back(OutgoingArg->getRegister(), InputReg); + if (!CCInfo.AllocateReg(OutgoingArg->getRegister())) report_fatal_error("failed to allocate implicit input argument"); } else { @@ -903,7 +942,9 @@ getAssignFnsForCC(CallingConv::ID CC, const SITargetLowering &TLI) { static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect, bool IsTailCall) { - return IsTailCall ? AMDGPU::SI_TCRETURN : AMDGPU::SI_CALL; + assert(!(IsIndirect && IsTailCall) && "Indirect calls can't be tail calls, " + "because the address can be divergent"); + return IsTailCall ? AMDGPU::SI_TCRETURN : AMDGPU::G_SI_CALL; } // Add operands to call instruction to track the callee. @@ -1033,6 +1074,11 @@ bool AMDGPUCallLowering::isEligibleForTailCallOptimization( if (!Info.IsTailCall) return false; + // Indirect calls can't be tail calls, because the address can be divergent. + // TODO Check divergence info if the call really is divergent. + if (Info.Callee.isReg()) + return false; + MachineFunction &MF = B.getMF(); const Function &CallerF = MF.getFunction(); CallingConv::ID CalleeCC = Info.CallConv; |
