https://github.com/chenzheng1030 updated https://github.com/llvm/llvm-project/pull/93267
>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 1/2] [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 +} >From bd6bc67342187695377d3edce137df55f018dbb7 Mon Sep 17 00:00:00 2001 From: Chen Zheng <czhen...@cn.ibm.com> Date: Wed, 29 May 2024 03:21:20 -0400 Subject: [PATCH 2/2] address comments --- .../clang/Basic/DiagnosticSemaKinds.td | 10 +++-- clang/lib/Basic/Targets/PPC.cpp | 3 ++ clang/lib/Basic/Targets/PPC.h | 1 + clang/lib/CodeGen/CGCall.cpp | 9 +--- clang/lib/Sema/SemaStmt.cpp | 14 +++++++ clang/test/SemaCXX/attr-musttail-ppc.cpp | 42 +++++++++++++++---- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 15 ++----- llvm/test/CodeGen/PowerPC/musttail-call.ll | 32 -------------- 8 files changed, 62 insertions(+), 64 deletions(-) delete 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 97f0cc4d9e004..daeee2573e2a3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3833,9 +3833,13 @@ 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_ppc_impossible_musttail: Error< + "'musttail' attribute for this call is impossible because %select{" + "long calls can not be tail called|" + "indirect calls can not be tail called|" + "external calls can not be tail called|" + "calling conv is not suitable for tail call}0" + >; def err_aix_musttail_unsupported: Error< "'musttail' attribute is not supported on AIX">; diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index a1e5f20f7dbe2..9ba0d108e3281 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -93,6 +93,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasQuadwordAtomics = true; } else if (Feature == "+aix-shared-lib-tls-model-opt") { HasAIXShLibTLSModelOpt = true; + } else if (Feature == "+longcall") { + UseLongCalls = true; } // TODO: Finish this list and add an assert that we've handled them // all. @@ -728,6 +730,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const { .Case("isa-v31-instructions", IsISA3_1) .Case("quadword-atomics", HasQuadwordAtomics) .Case("aix-shared-lib-tls-model-opt", HasAIXShLibTLSModelOpt) + .Case("longcall", UseLongCalls) .Default(false); } diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index fc23c30c68523..316174beca8a8 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -82,6 +82,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { bool IsISA3_1 = false; bool HasQuadwordAtomics = false; bool HasAIXShLibTLSModelOpt = false; + bool UseLongCalls = false; protected: std::string ABI; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0b6eda004a590..e96572c59862d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5748,15 +5748,8 @@ 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) { - 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); - } + else if (IsMustTail) Call->setTailCallKind(llvm::CallInst::TCK_MustTail); - } } // Add metadata for calls to MSAllocator functions diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 57465d4a77ac2..0ba7798c87719 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -743,6 +743,20 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { CallerType.Func = CallerDecl->getType()->getAs<FunctionProtoType>(); } + if (Context.getTargetInfo().getTriple().isPPC()) { + if (Context.getTargetInfo().getTriple().isOSAIX()) + return Diag(St->getBeginLoc(), diag::err_aix_musttail_unsupported); + else if (!Context.getTargetInfo().hasFeature("pcrelative-memops")) { + if (Context.getTargetInfo().hasFeature("longcall")) + return Diag(St->getBeginLoc(), diag::err_ppc_impossible_musttail) << 0; + else if (!CE->getDirectCallee()) + return Diag(St->getBeginLoc(), diag::err_ppc_impossible_musttail) << 1; + else if (isa_and_nonnull<FunctionDecl>(CE->getCalleeDecl()) && + !cast<FunctionDecl>(CE->getCalleeDecl())->isDefined()) + return Diag(St->getBeginLoc(), diag::err_ppc_impossible_musttail) << 2; + } + } + const Expr *CalleeExpr = CE->getCallee()->IgnoreParens(); const auto *CalleeBinOp = dyn_cast<BinaryOperator>(CalleeExpr); SourceLocation CalleeLoc = CE->getCalleeDecl() diff --git a/clang/test/SemaCXX/attr-musttail-ppc.cpp b/clang/test/SemaCXX/attr-musttail-ppc.cpp index 72b61adf7560b..3066dc5394efd 100644 --- a/clang/test/SemaCXX/attr-musttail-ppc.cpp +++ b/clang/test/SemaCXX/attr-musttail-ppc.cpp @@ -1,12 +1,36 @@ -// 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 +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -fsyntax-only -verify=aix +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify=aix +// RUN: %clang_cc1 %s -triple powerpc64-unknown-linux-gnu -fsyntax-only -verify=linux +// RUN: %clang_cc1 %s -triple powerpc-unknown-linux-gnu -fsyntax-only -verify=linux +// RUN: %clang_cc1 %s -triple powerpc64le-unknown-linux-gnu -fsyntax-only -verify=linux +// RUN: %clang_cc1 %s -triple powerpc64le-unknown-linux-gnu -target-feature +pcrelative-memops -fsyntax-only -verify=good +// RUN: %clang_cc1 %s -triple powerpc64le-unknown-linux-gnu -target-feature +longcall -fsyntax-only -verify=longcall +// RUN: %clang_cc1 %s -triple powerpc64le-unknown-linux-gnu -target-feature +pcrelative-memops -target-feature +longcall -fsyntax-only -verify=good -int Func(); -int Func1() { - // linux-warning@+2 {{'musttail' attribute may be ignored on ppc targets}} +int good_callee() { + return 0; +} +int good_caller() { + // good-no-diagnostics + // longcall-error@+2 {{'musttail' attribute for this call is impossible because long calls can not be tail called}} + // aix-error@+1 {{'musttail' attribute is not supported on AIX}} + [[clang::musttail]] return good_callee(); +} + +int func(); +int external_call() { + // good-no-diagnostics + // longcall-error@+3 {{'musttail' attribute for this call is impossible because long calls can not be tail called}} + // linux-error@+2 {{'musttail' attribute for this call is impossible because external calls can not be tail called}} + // aix-error@+1 {{'musttail' attribute is not supported on AIX}} + [[clang::musttail]] return func(); +} + +void indirect_call(int r) { + auto Fn = (void (*)(int))1; + // good-no-diagnostics + // longcall-error@+3 {{'musttail' attribute for this call is impossible because long calls can not be tail called}} + // linux-error@+2 {{'musttail' attribute for this call is impossible because indirect calls can not be tail called}} // aix-error@+1 {{'musttail' attribute is not supported on AIX}} - [[clang::musttail]] return Func(); + [[clang::musttail]] return Fn(r); } diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 59e4109e8e075..8450ce9e0e3b3 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -146,10 +146,6 @@ 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, @@ -5949,14 +5945,9 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, } } - 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); - } + if (!isTailCall && CB && CB->isMustTailCall()) + report_fatal_error("failed to perform tail call elimination on a call " + "site marked musttail"); // 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 deleted file mode 100644 index c4c283f5e1f94..0000000000000 --- a/llvm/test/CodeGen/PowerPC/musttail-call.ll +++ /dev/null @@ -1,32 +0,0 @@ -; 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