[clang] [Clang] Remove unnecessary return block after musttail call (PR #191198)
Paweł Bylica via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 14 05:49:55 PDT 2026
https://github.com/chfast updated https://github.com/llvm/llvm-project/pull/191198
>From 715f659c070eca1b013825e648954da99498fda4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Bylica?= <pawel at hepcolgum.band>
Date: Thu, 9 Apr 2026 08:49:37 +0200
Subject: [PATCH] [Clang] Remove unnecessary return block after musttail call
After a musttail call, the function epilog emitted a redundant return
in a dead block. This happened because EnsureInsertPoint() created a
new block after the musttail's ClearInsertionPoint(), and
EmitFunctionEpilog then added a return to it.
Remove EnsureInsertPoint() after the musttail return so the insert
point stays cleared. Guard EmitFunctionEpilog and the return value
store in EmitReturnStmt with HaveInsertPoint() checks.
This is a reworked version of #134282, addressing review feedback.
Fixes #104770.
Co-authored-by: Kiran <kiran-isaac at users.noreply.github.com>
---
clang/lib/CodeGen/CGCall.cpp | 5 +++-
clang/lib/CodeGen/CGExprComplex.cpp | 4 ++-
clang/lib/CodeGen/CGStmt.cpp | 3 ++
clang/test/CodeGenCXX/attr-musttail.cpp | 4 +--
clang/test/CodeGenCXX/fake-use-musttail.cpp | 6 +---
clang/test/CodeGenCXX/musttail-epilog.cpp | 32 +++++++++++++++++++++
6 files changed, 45 insertions(+), 9 deletions(-)
create mode 100644 clang/test/CodeGenCXX/musttail-epilog.cpp
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index c0e2456891e9d..db6ce0ace8c86 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4104,6 +4104,10 @@ llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src,
void CodeGenFunction::EmitFunctionEpilog(
const CGFunctionInfo &FI, bool EmitRetDbgLoc, SourceLocation EndLoc,
uint64_t RetKeyInstructionsSourceAtom) {
+ // Nothing to do if the function body already emitted a return.
+ if (!HaveInsertPoint())
+ return;
+
if (FI.isNoReturn()) {
// Noreturn functions don't return.
EmitUnreachable(EndLoc);
@@ -6271,7 +6275,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
else
Builder.CreateRet(CI);
Builder.ClearInsertionPoint();
- EnsureInsertPoint();
return GetUndefRValue(RetTy);
}
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 757663eb50f58..e70c75752d561 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -1491,7 +1491,9 @@ void CodeGenFunction::EmitComplexExprIntoLValue(const Expr *E, LValue dest,
"Invalid complex expression to emit");
ComplexExprEmitter Emitter(*this);
ComplexPairTy Val = Emitter.Visit(const_cast<Expr *>(E));
- Emitter.EmitStoreOfComplex(Val, dest, isInit);
+ // The call may have already emitted a return (e.g. musttail).
+ if (HaveInsertPoint())
+ Emitter.EmitStoreOfComplex(Val, dest, isInit);
}
/// EmitStoreOfComplex - Store a complex number into the specified l-value.
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index a75d3dc64c6b4..a55d53cf0c0a5 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1644,6 +1644,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
switch (getEvaluationKind(RV->getType())) {
case TEK_Scalar: {
llvm::Value *Ret = EmitScalarExpr(RV);
+ // The call may have already emitted a return (e.g. musttail).
+ if (!HaveInsertPoint())
+ break;
if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) {
EmitStoreOfScalar(Ret, MakeAddrLValue(ReturnValue, RV->getType()),
/*isInit*/ true);
diff --git a/clang/test/CodeGenCXX/attr-musttail.cpp b/clang/test/CodeGenCXX/attr-musttail.cpp
index c0081ec232e4a..1d908e2c785f1 100644
--- a/clang/test/CodeGenCXX/attr-musttail.cpp
+++ b/clang/test/CodeGenCXX/attr-musttail.cpp
@@ -7,11 +7,11 @@ int Baz(int);
int Func1(int x) {
if (x) {
- // CHECK: %call = musttail call noundef i32 @_Z3Bari(i32 noundef %1)
+ // CHECK: %call = musttail call noundef i32 @_Z3Bari(i32 noundef %{{.*}})
// CHECK-NEXT: ret i32 %call
[[clang::musttail]] return Bar(x);
} else {
- [[clang::musttail]] return Baz(x); // CHECK: %call1 = musttail call noundef i32 @_Z3Bazi(i32 noundef %3)
+ [[clang::musttail]] return Baz(x); // CHECK: %call1 = musttail call noundef i32 @_Z3Bazi(i32 noundef %{{.*}})
}
}
diff --git a/clang/test/CodeGenCXX/fake-use-musttail.cpp b/clang/test/CodeGenCXX/fake-use-musttail.cpp
index 9d341ab52f1c8..ac7f8a1f17c61 100644
--- a/clang/test/CodeGenCXX/fake-use-musttail.cpp
+++ b/clang/test/CodeGenCXX/fake-use-musttail.cpp
@@ -16,11 +16,7 @@ extern "C" char *bar(int *);
// CHECK-NEXT: notail call void (...) @llvm.fake.use(ptr [[FAKE_USE]])
// CHECK-NEXT: [[CALL:%.*]] = musttail call ptr @bar(ptr noundef [[TMP0]])
// CHECK-NEXT: ret ptr [[CALL]]
-
-// CHECK: [[BB1:.*:]]
-// CHECK-NEXT: [[FAKE_USE1:%.*]] = load ptr, ptr [[E_ADDR]]
-// CHECK-NEXT: notail call void (...) @llvm.fake.use(ptr [[FAKE_USE1]])
-// CHECK-NEXT: ret ptr undef
+// CHECK-NOT: ret ptr
//
extern "C" const char *foo(int *e) {
[[clang::musttail]] return bar(e);
diff --git a/clang/test/CodeGenCXX/musttail-epilog.cpp b/clang/test/CodeGenCXX/musttail-epilog.cpp
new file mode 100644
index 0000000000000..566dff65e8748
--- /dev/null
+++ b/clang/test/CodeGenCXX/musttail-epilog.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
+
+// After a musttail call, the function epilog should not emit a redundant
+// return statement in a dead block.
+
+int F1(short);
+void V1(int);
+double _Complex C1(short);
+
+// CHECK-LABEL: define {{.*}} @_Z5test1s(
+// CHECK: musttail call
+// CHECK-NEXT: ret i32
+// CHECK-NOT: ret i32
+int test1(short P0) {
+ [[clang::musttail]] return F1(P0);
+}
+
+// CHECK-LABEL: define {{.*}} @_Z5test2i(
+// CHECK: musttail call
+// CHECK-NEXT: ret void
+// CHECK-NOT: ret void
+void test2(int x) {
+ [[clang::musttail]] return V1(x);
+}
+
+// CHECK-LABEL: define {{.*}} @_Z5test3s(
+// CHECK: musttail call
+// CHECK-NEXT: ret { double, double }
+// CHECK-NOT: ret { double, double }
+double _Complex test3(short P0) {
+ [[clang::musttail]] return C1(P0);
+}
More information about the cfe-commits
mailing list