https://github.com/chenzheng1030 created 
https://github.com/llvm/llvm-project/pull/93267

musttail does not often possible to be generated on PPC targets as when calling 
to a function defined in another module, PPC needs to restore the TOC pointer. 
To restore the TOC pointer, compiler needs to emit a nop after the call to let 
linker generate codes to restore TOC pointer. Tail call cannot generate 
expected call sequence for this case.

To avoid the crash inside the compiler backend, a diagnosis is added in the 
frontend and in the backend, PPC will change the musttail to tail. AIX for now 
does not support tailcall, so on AIX musttail call attribute leads to an error 
instead of warning.

Fixes #63214

>From 17505893b2b48969512e3c2e8433a6446429f65e Mon Sep 17 00:00:00 2001
From: Chen Zheng <czhen...@cn.ibm.com>
Date: Thu, 23 May 2024 22:59:48 -0400
Subject: [PATCH] [PowerPC] Diagnose musttail instead of crash inside backend

musttail does not often possible to generate on PPC targets as when calling
to a function defined in another model, PPC needs to restore the TOC
pointer. To restore the TOC pointer, compiler needs to emit a nop
after the function call to let linker generate codes to restore
TOC pointer. Tail call does not generate expected call sequence for this
case.

To avoid the crash inside the compiler backend, a diagnosis is added
in the frontend and in the backend, PPC will change the musttail to
tail.

Fixes #63214
---
 .../clang/Basic/DiagnosticSemaKinds.td        |  5 +++
 clang/lib/CodeGen/CGCall.cpp                  | 10 +++++-
 clang/test/SemaCXX/attr-musttail-ppc.cpp      | 12 +++++++
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   | 15 +++++++--
 llvm/test/CodeGen/PowerPC/musttail-call.ll    | 32 +++++++++++++++++++
 5 files changed, 70 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/SemaCXX/attr-musttail-ppc.cpp
 create mode 100644 llvm/test/CodeGen/PowerPC/musttail-call.ll

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cc402182687f3..97f0cc4d9e004 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3833,6 +3833,11 @@ def note_cannot_use_trivial_abi_reason : Note<
   "it is polymorphic|"
   "it has a base of a non-trivial class type|it has a virtual base|"
   "it has a __weak field|it has a field of a non-trivial class type}1">;
+def warn_ppc_musttail_maybe_ignored: Warning<
+  "'musttail' attribute may be ignored on ppc targets">,
+  InGroup<IgnoredAttributes>;
+def err_aix_musttail_unsupported: Error<
+  "'musttail' attribute is not supported on AIX">;
 
 // Availability attribute
 def warn_availability_unknown_platform : Warning<
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 97449a5e51e73..0b6eda004a590 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -26,6 +26,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGen/SwiftCallingConv.h"
@@ -5747,8 +5748,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
   if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
     if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
       Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
-    else if (IsMustTail)
+    else if (IsMustTail) {
+      if (getTarget().getTriple().isPPC()) {
+        if (getTarget().getTriple().isOSAIX())
+          CGM.getDiags().Report(Loc, diag::err_aix_musttail_unsupported);
+        else
+          CGM.getDiags().Report(Loc, diag::warn_ppc_musttail_maybe_ignored);
+      }
       Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
+    }
   }
 
   // Add metadata for calls to MSAllocator functions
diff --git a/clang/test/SemaCXX/attr-musttail-ppc.cpp 
b/clang/test/SemaCXX/attr-musttail-ppc.cpp
new file mode 100644
index 0000000000000..72b61adf7560b
--- /dev/null
+++ b/clang/test/SemaCXX/attr-musttail-ppc.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -o /dev/null -emit-llvm 
-verify=aix
+// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -o /dev/null -emit-llvm 
-verify=aix
+// RUN: %clang_cc1 %s -triple powerpc64-unknown-linux-gnu -o /dev/null 
-emit-llvm -verify=linux
+// RUN: %clang_cc1 %s -triple powerpc-unknown-linux-gnu -o /dev/null 
-emit-llvm -verify=linux
+// RUN: %clang_cc1 %s -triple powerpc64le-unknown-linux-gnu -o /dev/null 
-emit-llvm -verify=linux
+
+int Func();
+int Func1() {
+  // linux-warning@+2 {{'musttail' attribute may be ignored on ppc targets}}
+  // aix-error@+1 {{'musttail' attribute is not supported on AIX}}
+  [[clang::musttail]] return Func();
+}
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp 
b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 8450ce9e0e3b3..59e4109e8e075 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -146,6 +146,10 @@ static cl::opt<unsigned> PPCAIXTLSModelOptUseIEForLDLimit(
     cl::desc("Set inclusive limit count of TLS local-dynamic access(es) in a "
              "function to use initial-exec"));
 
+static cl::opt<bool> AbortOnImpossibleMusttailCall(
+    "ppc-abort-on-impossible-musttailcall", cl::init(false), cl::Hidden,
+    cl::desc("Abort if any call marked as musttail is impossible."));
+
 STATISTIC(NumTailCalls, "Number of tail calls");
 STATISTIC(NumSiblingCalls, "Number of sibling calls");
 STATISTIC(ShufflesHandledWithVPERM,
@@ -5945,9 +5949,14 @@ 
PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     }
   }
 
-  if (!isTailCall && CB && CB->isMustTailCall())
-    report_fatal_error("failed to perform tail call elimination on a call "
-                       "site marked musttail");
+  if (!isTailCall && CB && CB->isMustTailCall()) {
+    if (AbortOnImpossibleMusttailCall)
+      report_fatal_error("failed to perform tail call elimination on a call "
+                         "site marked musttail");
+    else
+      cast<CallInst>(const_cast<CallBase *>(CB))
+          ->setTailCallKind(llvm::CallInst::TCK_Tail);
+  }
 
   // When long calls (i.e. indirect calls) are always used, calls are always
   // made via function pointer. If we have a function name, first translate it
diff --git a/llvm/test/CodeGen/PowerPC/musttail-call.ll 
b/llvm/test/CodeGen/PowerPC/musttail-call.ll
new file mode 100644
index 0000000000000..c4c283f5e1f94
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/musttail-call.ll
@@ -0,0 +1,32 @@
+; RUN: not --crash llc -mtriple=powerpc64-ibm-aix-xcoff %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=true | \
+; RUN:   FileCheck %s --check-prefix=CRASH
+; RUN: not --crash llc -mtriple=powerpc-ibm-aix-xcoff %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=true | \
+; RUN:   FileCheck %s --check-prefix=CRASH
+; RUN: not --crash llc -mtriple=powerpc64-unknown-linux-gnu %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=true | \
+; RUN:   FileCheck %s --check-prefix=CRASH
+; RUN: not --crash llc -mtriple=powerpc-unknown-linux-gnu %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=true | \
+; RUN:   FileCheck %s --check-prefix=CRASH
+; RUN: not --crash llc -mtriple=powerpc64le-unknown-linux-gnu %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=true | \
+; RUN:   FileCheck %s --check-prefix=CRASH
+; RUN: llc -mtriple=powerpc64-ibm-aix-xcoff %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=false | \
+; RUN:   FileCheck %s --check-prefix=NOCRASH
+; RUN: llc -mtriple=powerpc-ibm-aix-xcoff %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=false | \
+; RUN:   FileCheck %s --check-prefix=NOCRASH
+; RUN: llc -mtriple=powerpc64-unknown-linux-gnu %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=false | \
+; RUN:   FileCheck %s --check-prefix=NOCRASH
+; RUN: llc -mtriple=powerpc-unknown-linux-gnu %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=false | \
+; RUN:   FileCheck %s --check-prefix=NOCRASH
+; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu %s -o - 2>&1 
-ppc-abort-on-impossible-musttailcall=false | \
+; RUN:   FileCheck %s --check-prefix=NOCRASH
+
+; CRASH: LLVM ERROR: failed to perform tail call elimination on a call site 
marked musttail
+; NOCRASH-NOT: LLVM ERROR: failed to perform tail call elimination on a call 
site marked musttail
+; NOCRASH-LABEL: caller
+; NOCRASH:    bl {{callee|.callee}}
+
+
+declare i32 @callee()
+define i32 @caller() {
+  %res = musttail call i32 @callee()
+  ret i32 %res
+}

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

Reply via email to