aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
diff options
context:
space:
mode:
authorDiana Picus <Diana-Magda.Picus@amd.com>2025-09-04 10:34:43 +0200
committerGitHub <noreply@github.com>2025-09-04 10:34:43 +0200
commit018dc1b3977bb249d55a6808bb45802a10f818fa (patch)
tree0151a68c8f3628dc2ae093d3cfa1537958bce48a /llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
parentd1408667de830da8817c24cb9788da6caae551c7 (diff)
downloadllvm-018dc1b3977bb249d55a6808bb45802a10f818fa.zip
llvm-018dc1b3977bb249d55a6808bb45802a10f818fa.tar.gz
llvm-018dc1b3977bb249d55a6808bb45802a10f818fa.tar.bz2
[AMDGPU] Tail call support for whole wave functions (#145860)
Support tail calls to whole wave functions (trivial) and from whole wave functions (slightly more involved because we need a new pseudo for the tail call return, that patches up the EXEC mask). Move the expansion of whole wave function return pseudos (regular and tail call returns) to prolog epilog insertion, since that's where we patch up the EXEC mask.
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp54
1 files changed, 33 insertions, 21 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 76c7e9d..430e474 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7974,12 +7974,19 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
}
case Intrinsic::amdgcn_call_whole_wave: {
TargetLowering::ArgListTy Args;
+ bool isTailCall = I.isTailCall();
// The first argument is the callee. Skip it when assembling the call args.
for (unsigned Idx = 1; Idx < I.arg_size(); ++Idx) {
TargetLowering::ArgListEntry Arg(getValue(I.getArgOperand(Idx)),
I.getArgOperand(Idx)->getType());
Arg.setAttributes(&I, Idx);
+
+ // If we have an explicit sret argument that is an Instruction, (i.e., it
+ // might point to function-local memory), we can't meaningfully tail-call.
+ if (Arg.IsSRet && isa<Instruction>(I.getArgOperand(Idx)))
+ isTailCall = false;
+
Args.push_back(Arg);
}
@@ -7994,7 +8001,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
.setChain(getRoot())
.setCallee(CallingConv::AMDGPU_Gfx_WholeWave, I.getType(),
getValue(I.getArgOperand(0)), std::move(Args))
- .setTailCall(false)
+ .setTailCall(isTailCall && canTailCall(I))
.setIsPreallocated(
I.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0)
.setConvergent(I.isConvergent())
@@ -8929,6 +8936,29 @@ SelectionDAGBuilder::lowerInvokable(TargetLowering::CallLoweringInfo &CLI,
return Result;
}
+bool SelectionDAGBuilder::canTailCall(const CallBase &CB) const {
+ bool isMustTailCall = CB.isMustTailCall();
+
+ // Avoid emitting tail calls in functions with the disable-tail-calls
+ // attribute.
+ const Function *Caller = CB.getParent()->getParent();
+ if (Caller->getFnAttribute("disable-tail-calls").getValueAsString() ==
+ "true" &&
+ !isMustTailCall)
+ return false;
+
+ // We can't tail call inside a function with a swifterror argument. Lowering
+ // does not support this yet. It would have to move into the swifterror
+ // register before the call.
+ if (DAG.getTargetLoweringInfo().supportSwiftError() &&
+ Caller->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
+ return false;
+
+ // Check if target-independent constraints permit a tail call here.
+ // Target-dependent constraints are checked within TLI->LowerCallTo.
+ return isInTailCallPosition(CB, DAG.getTarget());
+}
+
void SelectionDAGBuilder::LowerCallTo(const CallBase &CB, SDValue Callee,
bool isTailCall, bool isMustTailCall,
const BasicBlock *EHPadBB,
@@ -8943,21 +8973,8 @@ void SelectionDAGBuilder::LowerCallTo(const CallBase &CB, SDValue Callee,
const Value *SwiftErrorVal = nullptr;
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
- if (isTailCall) {
- // Avoid emitting tail calls in functions with the disable-tail-calls
- // attribute.
- auto *Caller = CB.getParent()->getParent();
- if (Caller->getFnAttribute("disable-tail-calls").getValueAsString() ==
- "true" && !isMustTailCall)
- isTailCall = false;
-
- // We can't tail call inside a function with a swifterror argument. Lowering
- // does not support this yet. It would have to move into the swifterror
- // register before the call.
- if (TLI.supportSwiftError() &&
- Caller->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
- isTailCall = false;
- }
+ if (isTailCall)
+ isTailCall = canTailCall(CB);
for (auto I = CB.arg_begin(), E = CB.arg_end(); I != E; ++I) {
const Value *V = *I;
@@ -8997,11 +9014,6 @@ void SelectionDAGBuilder::LowerCallTo(const CallBase &CB, SDValue Callee,
Args.push_back(Entry);
}
- // Check if target-independent constraints permit a tail call here.
- // Target-dependent constraints are checked within TLI->LowerCallTo.
- if (isTailCall && !isInTailCallPosition(CB, DAG.getTarget()))
- isTailCall = false;
-
// Disable tail calls if there is an swifterror argument. Targets have not
// been updated to support tail calls.
if (TLI.supportSwiftError() && SwiftErrorVal)