Author: Stephen Tozer
Date: 2025-04-25T11:47:38+01:00
New Revision: 2d00c73003a6c5e9fd468afcf271b505d4f80f27

URL: 
https://github.com/llvm/llvm-project/commit/2d00c73003a6c5e9fd468afcf271b505d4f80f27
DIFF: 
https://github.com/llvm/llvm-project/commit/2d00c73003a6c5e9fd468afcf271b505d4f80f27.diff

LOG: [Clang][CodeGen] Emit fake uses before musttail calls (#136867)

Fixes the issue reported following the merge of #118026.

When a valid `musttail` call is made, the function it is made from must
return immediately after the call; if there are any cleanups left in the
function, then an error is triggered. This is not necessary for fake
uses however - it is perfectly valid to simply emit the fake use
"cleanup" code before the tail call, and indeed LLVM will automatically
move any fake uses following a tail call to come before the tail call.

Therefore, this patch specifically choose to handle fake use cleanups
when a musttail call is present by simply emitting them immediately
before the call.

Added: 
    clang/test/CodeGenCXX/fake-use-musttail.cpp

Modified: 
    clang/lib/CodeGen/CGCall.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 836f34e5b347d..c7fbbbc6fd40d 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6001,8 +6001,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
     for (auto it = EHStack.find(CurrentCleanupScopeDepth); it != EHStack.end();
          ++it) {
       EHCleanupScope *Cleanup = dyn_cast<EHCleanupScope>(&*it);
-      if (!(Cleanup && Cleanup->getCleanup()->isRedundantBeforeReturn()))
+      // Fake uses can be safely emitted immediately prior to the tail call, so
+      // we choose to emit them just before the call here.
+      if (Cleanup && Cleanup->isFakeUse()) {
+        CGBuilderTy::InsertPointGuard IPG(Builder);
+        Builder.SetInsertPoint(CI);
+        Cleanup->getCleanup()->Emit(*this, EHScopeStack::Cleanup::Flags());
+      } else if (!(Cleanup &&
+                   Cleanup->getCleanup()->isRedundantBeforeReturn())) {
         CGM.ErrorUnsupported(MustTailCall, "tail call skipping over cleanups");
+      }
     }
     if (CI->getType()->isVoidTy())
       Builder.CreateRetVoid();

diff  --git a/clang/test/CodeGenCXX/fake-use-musttail.cpp 
b/clang/test/CodeGenCXX/fake-use-musttail.cpp
new file mode 100644
index 0000000000000..9d341ab52f1c8
--- /dev/null
+++ b/clang/test/CodeGenCXX/fake-use-musttail.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm 
-fextend-variable-liveness -o - %s | FileCheck %s
+
+/// Tests that when we have fake uses in a function ending in a musttail call,
+/// we emit the fake uses and their corresponding loads immediately prior to 
the
+/// tail call.
+
+extern "C" char *bar(int *);
+
+// CHECK-LABEL: define dso_local ptr @foo(
+// CHECK-SAME:    ptr noundef [[E:%.*]])
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[E_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    store ptr [[E]], ptr [[E_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[E_ADDR]], align 8
+// CHECK-NEXT:    [[FAKE_USE:%.*]] = load ptr, ptr [[E_ADDR]]
+// 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
+//
+extern "C" const char *foo(int *e) {
+  [[clang::musttail]] return bar(e);
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to