https://github.com/SLTozer updated 
https://github.com/llvm/llvm-project/pull/136867

>From 90c09c8326077a1ba6797519bbefd014f32b5beb Mon Sep 17 00:00:00 2001
From: Stephen Tozer <stephen.to...@sony.com>
Date: Wed, 23 Apr 2025 14:24:50 +0100
Subject: [PATCH 1/4] [Clang] Emit Fake Uses before musttail calls

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.
---
 clang/lib/CodeGen/CGCall.cpp                | 12 +++-
 clang/test/CodeGenCXX/fake-use-musttail.cpp | 72 +++++++++++++++++++++
 2 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenCXX/fake-use-musttail.cpp

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 8cb27420dd911..c8cddfc06fce7 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6001,8 +6001,18 @@ 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; we
+      // choose to emit the fake use before the call rather than after, to 
avoid
+      // forcing variable values from every call on the "stack" to be preserved
+      // simultaneously.
+      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..7d1420ce5fdb6
--- /dev/null
+++ b/clang/test/CodeGenCXX/fake-use-musttail.cpp
@@ -0,0 +1,72 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 5
+// RUN: %clang_cc1 -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.
+
+struct Class1 {
+  Class1(int);
+};
+
+class Class2 {
+  static const char *foo(int *, const char *, int *, Class1, const int *,
+                         unsigned long);
+  template <class>
+  static char *bar(int *, const char *, int *, Class1, const int *, unsigned 
long);
+};
+
+// CHECK-LABEL: define dso_local noundef ptr 
@_ZN6Class23fooEPiPKcS0_6Class1PKim(
+// CHECK-SAME: ptr noundef [[E:%.*]], ptr noundef [[F:%.*]], ptr noundef 
[[G:%.*]], ptr noundef [[H:%.*]], i64 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] 
align 2 {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TMP0:%.*]] = alloca [[STRUCT_CLASS1:%.*]], align 1
+// CHECK-NEXT:    [[E_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[F_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[G_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[H_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[I_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[AGG_TMP:%.*]] = alloca [[STRUCT_CLASS1]], align 1
+// CHECK-NEXT:    store ptr [[E]], ptr [[E_ADDR]], align 8
+// CHECK-NEXT:    store ptr [[F]], ptr [[F_ADDR]], align 8
+// CHECK-NEXT:    store ptr [[G]], ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    store ptr [[H]], ptr [[H_ADDR]], align 8
+// CHECK-NEXT:    store i64 [[I]], ptr [[I_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[F_ADDR]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    call void @_ZN6Class1C1Ei(ptr noundef nonnull align 1 
dereferenceable(1) [[AGG_TMP]], i32 noundef 0)
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[H_ADDR]], align 8
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr [[I_ADDR]], align 8
+// CHECK-NEXT:    [[FAKE_USE:%.*]] = load i64, ptr [[I_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(i64 [[FAKE_USE]]) 
#[[ATTR3:[0-9]+]]
+// CHECK-NEXT:    [[FAKE_USE1:%.*]] = load ptr, ptr [[H_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE1]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE2:%.*]] = load [[STRUCT_CLASS1]], ptr [[TMP0]], 
align 1
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use([[STRUCT_CLASS1]] 
[[FAKE_USE2]]) #[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE3:%.*]] = load ptr, ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE3]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE4:%.*]] = load ptr, ptr [[F_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE4]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE5:%.*]] = load ptr, ptr [[E_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE5]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[CALL:%.*]] = musttail call noundef ptr 
@_ZN6Class23barIiEEPcPiPKcS2_6Class1PKim(ptr noundef [[TMP1]], ptr noundef 
[[TMP2]], ptr noundef [[TMP3]], ptr noundef [[TMP4]], i64 noundef [[TMP5]])
+// CHECK-NEXT:    ret ptr [[CALL]]
+// CHECK:       [[BB6:.*:]]
+// CHECK-NEXT:    [[FAKE_USE6:%.*]] = load i64, ptr [[I_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(i64 [[FAKE_USE6]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE7:%.*]] = load ptr, ptr [[H_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE7]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE8:%.*]] = load [[STRUCT_CLASS1]], ptr [[TMP0]], 
align 1
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use([[STRUCT_CLASS1]] 
[[FAKE_USE8]]) #[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE9:%.*]] = load ptr, ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE9]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE10:%.*]] = load ptr, ptr [[F_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE10]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE11:%.*]] = load ptr, ptr [[E_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE11]]) 
#[[ATTR3]]
+// CHECK-NEXT:    ret ptr undef
+//
+const char *Class2::foo(int *e, const char *f, int *g, Class1, const int *h,
+                        unsigned long i) {
+  [[clang::musttail]] return bar<int>(e, f, g, int(), h, i);
+}

>From 2765fb7d11c1ac294301baba20ef5f44d641be17 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <stephen.to...@sony.com>
Date: Thu, 24 Apr 2025 11:27:03 +0100
Subject: [PATCH 2/4] Simplify test

---
 clang/test/CodeGenCXX/fake-use-musttail.cpp | 65 ++++++++-------------
 1 file changed, 25 insertions(+), 40 deletions(-)

diff --git a/clang/test/CodeGenCXX/fake-use-musttail.cpp 
b/clang/test/CodeGenCXX/fake-use-musttail.cpp
index 7d1420ce5fdb6..c0dacca8eab18 100644
--- a/clang/test/CodeGenCXX/fake-use-musttail.cpp
+++ b/clang/test/CodeGenCXX/fake-use-musttail.cpp
@@ -5,68 +5,53 @@
 /// we emit the fake uses and their corresponding loads immediately prior to 
the
 /// tail call.
 
-struct Class1 {
-  Class1(int);
-};
+template <class>
+char *bar(int *, const char *, int *, const int *, unsigned long);
 
-class Class2 {
-  static const char *foo(int *, const char *, int *, Class1, const int *,
-                         unsigned long);
-  template <class>
-  static char *bar(int *, const char *, int *, Class1, const int *, unsigned 
long);
-};
-
-// CHECK-LABEL: define dso_local noundef ptr 
@_ZN6Class23fooEPiPKcS0_6Class1PKim(
-// CHECK-SAME: ptr noundef [[E:%.*]], ptr noundef [[F:%.*]], ptr noundef 
[[G:%.*]], ptr noundef [[H:%.*]], i64 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] 
align 2 {
+// CHECK-LABEL: define dso_local noundef ptr @_Z3fooPiPKcS_PKim(
+// CHECK-SAME: ptr noundef [[E:%.*]], ptr noundef [[F:%.*]], ptr noundef 
[[G:%.*]], ptr noundef [[H:%.*]], i64 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = alloca [[STRUCT_CLASS1:%.*]], align 1
 // CHECK-NEXT:    [[E_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    [[F_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    [[G_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    [[H_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    [[I_ADDR:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[AGG_TMP:%.*]] = alloca [[STRUCT_CLASS1]], align 1
 // CHECK-NEXT:    store ptr [[E]], ptr [[E_ADDR]], align 8
 // CHECK-NEXT:    store ptr [[F]], ptr [[F_ADDR]], align 8
 // CHECK-NEXT:    store ptr [[G]], ptr [[G_ADDR]], align 8
 // CHECK-NEXT:    store ptr [[H]], ptr [[H_ADDR]], align 8
 // CHECK-NEXT:    store i64 [[I]], ptr [[I_ADDR]], align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[E_ADDR]], align 8
-// CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[F_ADDR]], align 8
-// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[G_ADDR]], align 8
-// CHECK-NEXT:    call void @_ZN6Class1C1Ei(ptr noundef nonnull align 1 
dereferenceable(1) [[AGG_TMP]], i32 noundef 0)
-// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[H_ADDR]], align 8
-// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr [[I_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[E_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[F_ADDR]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[H_ADDR]], align 8
+// CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr [[I_ADDR]], align 8
 // CHECK-NEXT:    [[FAKE_USE:%.*]] = load i64, ptr [[I_ADDR]], align 8
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(i64 [[FAKE_USE]]) 
#[[ATTR3:[0-9]+]]
 // CHECK-NEXT:    [[FAKE_USE1:%.*]] = load ptr, ptr [[H_ADDR]], align 8
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE1]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE2:%.*]] = load [[STRUCT_CLASS1]], ptr [[TMP0]], 
align 1
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use([[STRUCT_CLASS1]] 
[[FAKE_USE2]]) #[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE3:%.*]] = load ptr, ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    [[FAKE_USE2:%.*]] = load ptr, ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE2]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE3:%.*]] = load ptr, ptr [[F_ADDR]], align 8
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE3]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE4:%.*]] = load ptr, ptr [[F_ADDR]], align 8
+// CHECK-NEXT:    [[FAKE_USE4:%.*]] = load ptr, ptr [[E_ADDR]], align 8
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE4]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE5:%.*]] = load ptr, ptr [[E_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE5]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[CALL:%.*]] = musttail call noundef ptr 
@_ZN6Class23barIiEEPcPiPKcS2_6Class1PKim(ptr noundef [[TMP1]], ptr noundef 
[[TMP2]], ptr noundef [[TMP3]], ptr noundef [[TMP4]], i64 noundef [[TMP5]])
+// CHECK-NEXT:    [[CALL:%.*]] = musttail call noundef ptr 
@_Z3barIiEPcPiPKcS1_PKim(ptr noundef [[TMP0]], ptr noundef [[TMP1]], ptr 
noundef [[TMP2]], ptr noundef [[TMP3]], i64 noundef [[TMP4]])
 // CHECK-NEXT:    ret ptr [[CALL]]
-// CHECK:       [[BB6:.*:]]
-// CHECK-NEXT:    [[FAKE_USE6:%.*]] = load i64, ptr [[I_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(i64 [[FAKE_USE6]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE7:%.*]] = load ptr, ptr [[H_ADDR]], align 8
+// CHECK:       [[BB5:.*:]]
+// CHECK-NEXT:    [[FAKE_USE5:%.*]] = load i64, ptr [[I_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(i64 [[FAKE_USE5]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE6:%.*]] = load ptr, ptr [[H_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE6]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE7:%.*]] = load ptr, ptr [[G_ADDR]], align 8
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE7]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE8:%.*]] = load [[STRUCT_CLASS1]], ptr [[TMP0]], 
align 1
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use([[STRUCT_CLASS1]] 
[[FAKE_USE8]]) #[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE9:%.*]] = load ptr, ptr [[G_ADDR]], align 8
+// CHECK-NEXT:    [[FAKE_USE8:%.*]] = load ptr, ptr [[F_ADDR]], align 8
+// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE8]]) 
#[[ATTR3]]
+// CHECK-NEXT:    [[FAKE_USE9:%.*]] = load ptr, ptr [[E_ADDR]], align 8
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE9]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE10:%.*]] = load ptr, ptr [[F_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE10]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE11:%.*]] = load ptr, ptr [[E_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE11]]) 
#[[ATTR3]]
 // CHECK-NEXT:    ret ptr undef
 //
-const char *Class2::foo(int *e, const char *f, int *g, Class1, const int *h,
+const char *foo(int *e, const char *f, int *g, const int *h,
                         unsigned long i) {
-  [[clang::musttail]] return bar<int>(e, f, g, int(), h, i);
+  [[clang::musttail]] return bar<int>(e, f, g, h, i);
 }

>From d0e4e68a2f4f16a721fa0b265f023e030b441bd5 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <stephen.to...@sony.com>
Date: Thu, 24 Apr 2025 12:55:09 +0100
Subject: [PATCH 3/4] Use extern C to prevent name mangling

---
 clang/test/CodeGenCXX/fake-use-musttail.cpp | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/clang/test/CodeGenCXX/fake-use-musttail.cpp 
b/clang/test/CodeGenCXX/fake-use-musttail.cpp
index c0dacca8eab18..d0ac8ca5bea90 100644
--- a/clang/test/CodeGenCXX/fake-use-musttail.cpp
+++ b/clang/test/CodeGenCXX/fake-use-musttail.cpp
@@ -5,10 +5,9 @@
 /// we emit the fake uses and their corresponding loads immediately prior to 
the
 /// tail call.
 
-template <class>
-char *bar(int *, const char *, int *, const int *, unsigned long);
+extern "C" char *bar(int *, const char *, int *, const int *, unsigned long);
 
-// CHECK-LABEL: define dso_local noundef ptr @_Z3fooPiPKcS_PKim(
+// CHECK-LABEL: define dso_local ptr @foo(
 // CHECK-SAME: ptr noundef [[E:%.*]], ptr noundef [[F:%.*]], ptr noundef 
[[G:%.*]], ptr noundef [[H:%.*]], i64 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[E_ADDR:%.*]] = alloca ptr, align 8
@@ -36,7 +35,7 @@ char *bar(int *, const char *, int *, const int *, unsigned 
long);
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE3]]) 
#[[ATTR3]]
 // CHECK-NEXT:    [[FAKE_USE4:%.*]] = load ptr, ptr [[E_ADDR]], align 8
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE4]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[CALL:%.*]] = musttail call noundef ptr 
@_Z3barIiEPcPiPKcS1_PKim(ptr noundef [[TMP0]], ptr noundef [[TMP1]], ptr 
noundef [[TMP2]], ptr noundef [[TMP3]], i64 noundef [[TMP4]])
+// CHECK-NEXT:    [[CALL:%.*]] = musttail call ptr @bar(ptr noundef [[TMP0]], 
ptr noundef [[TMP1]], ptr noundef [[TMP2]], ptr noundef [[TMP3]], i64 noundef 
[[TMP4]])
 // CHECK-NEXT:    ret ptr [[CALL]]
 // CHECK:       [[BB5:.*:]]
 // CHECK-NEXT:    [[FAKE_USE5:%.*]] = load i64, ptr [[I_ADDR]], align 8
@@ -51,7 +50,7 @@ char *bar(int *, const char *, int *, const int *, unsigned 
long);
 // CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE9]]) 
#[[ATTR3]]
 // CHECK-NEXT:    ret ptr undef
 //
-const char *foo(int *e, const char *f, int *g, const int *h,
+extern "C" const char *foo(int *e, const char *f, int *g, const int *h,
                         unsigned long i) {
-  [[clang::musttail]] return bar<int>(e, f, g, h, i);
+  [[clang::musttail]] return bar(e, f, g, h, i);
 }

>From c8c371f048a59d1f4eeda69cd628456b0db294e6 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <stephen.to...@sony.com>
Date: Fri, 25 Apr 2025 09:51:53 +0100
Subject: [PATCH 4/4] Reduce comment, further simplify test

---
 clang/lib/CodeGen/CGCall.cpp                |  6 +--
 clang/test/CodeGenCXX/fake-use-musttail.cpp | 51 +++++----------------
 2 files changed, 13 insertions(+), 44 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index c8cddfc06fce7..4dbc5c2f00971 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6001,10 +6001,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
     for (auto it = EHStack.find(CurrentCleanupScopeDepth); it != EHStack.end();
          ++it) {
       EHCleanupScope *Cleanup = dyn_cast<EHCleanupScope>(&*it);
-      // Fake uses can be safely emitted immediately prior to the tail call; we
-      // choose to emit the fake use before the call rather than after, to 
avoid
-      // forcing variable values from every call on the "stack" to be preserved
-      // simultaneously.
+      // 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);
diff --git a/clang/test/CodeGenCXX/fake-use-musttail.cpp 
b/clang/test/CodeGenCXX/fake-use-musttail.cpp
index d0ac8ca5bea90..f73e45d8a92a4 100644
--- a/clang/test/CodeGenCXX/fake-use-musttail.cpp
+++ b/clang/test/CodeGenCXX/fake-use-musttail.cpp
@@ -1,56 +1,27 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 5
 // RUN: %clang_cc1 -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 *, const char *, int *, const int *, unsigned long);
+extern "C" char *bar(int *);
 
 // CHECK-LABEL: define dso_local ptr @foo(
-// CHECK-SAME: ptr noundef [[E:%.*]], ptr noundef [[F:%.*]], ptr noundef 
[[G:%.*]], ptr noundef [[H:%.*]], i64 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-SAME:    ptr noundef [[E:%.*]])
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[E_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[F_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[G_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[H_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[I_ADDR:%.*]] = alloca i64, align 8
 // CHECK-NEXT:    store ptr [[E]], ptr [[E_ADDR]], align 8
-// CHECK-NEXT:    store ptr [[F]], ptr [[F_ADDR]], align 8
-// CHECK-NEXT:    store ptr [[G]], ptr [[G_ADDR]], align 8
-// CHECK-NEXT:    store ptr [[H]], ptr [[H_ADDR]], align 8
-// CHECK-NEXT:    store i64 [[I]], ptr [[I_ADDR]], align 8
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[E_ADDR]], align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[F_ADDR]], align 8
-// CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[G_ADDR]], align 8
-// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[H_ADDR]], align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr [[I_ADDR]], align 8
-// CHECK-NEXT:    [[FAKE_USE:%.*]] = load i64, ptr [[I_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(i64 [[FAKE_USE]]) 
#[[ATTR3:[0-9]+]]
-// CHECK-NEXT:    [[FAKE_USE1:%.*]] = load ptr, ptr [[H_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE1]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE2:%.*]] = load ptr, ptr [[G_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE2]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE3:%.*]] = load ptr, ptr [[F_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE3]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE4:%.*]] = load ptr, ptr [[E_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE4]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[CALL:%.*]] = musttail call ptr @bar(ptr noundef [[TMP0]], 
ptr noundef [[TMP1]], ptr noundef [[TMP2]], ptr noundef [[TMP3]], i64 noundef 
[[TMP4]])
+// 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:       [[BB5:.*:]]
-// CHECK-NEXT:    [[FAKE_USE5:%.*]] = load i64, ptr [[I_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(i64 [[FAKE_USE5]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE6:%.*]] = load ptr, ptr [[H_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE6]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE7:%.*]] = load ptr, ptr [[G_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE7]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE8:%.*]] = load ptr, ptr [[F_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE8]]) 
#[[ATTR3]]
-// CHECK-NEXT:    [[FAKE_USE9:%.*]] = load ptr, ptr [[E_ADDR]], align 8
-// CHECK-NEXT:    notail call void (...) @llvm.fake.use(ptr [[FAKE_USE9]]) 
#[[ATTR3]]
+
+// 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, const char *f, int *g, const int *h,
-                        unsigned long i) {
-  [[clang::musttail]] return bar(e, f, g, h, i);
+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