[clang] [clang] Allow 'convergent' to be a statement attribute (PR #100637)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 25 15:54:40 PDT 2024
https://github.com/darkbuck updated https://github.com/llvm/llvm-project/pull/100637
>From d9de73264bf4d555e7e09a2c2687eae72c1fa19e Mon Sep 17 00:00:00 2001
From: Michael Liao <michael.hliao at gmail.com>
Date: Thu, 25 Jul 2024 15:19:15 -0400
Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
=?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.4
---
clang/include/clang/Basic/Attr.td | 3 ++-
clang/lib/CodeGen/CGCall.cpp | 5 +++++
clang/lib/CodeGen/CGStmt.cpp | 33 ++++++++++++++++++++---------
clang/lib/CodeGen/CodeGenFunction.h | 3 +++
clang/lib/Sema/SemaStmtAttr.cpp | 16 ++++++++++++++
clang/test/SemaOpenCL/convergent.cl | 4 ++--
6 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 4825979a974d2..c3bcaa5d5f235 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2042,7 +2042,8 @@ def NoDuplicate : InheritableAttr {
def Convergent : InheritableAttr {
let Spellings = [Clang<"convergent">];
- let Subjects = SubjectList<[Function]>;
+ let Subjects = SubjectList<[Function, Stmt], WarnDiag,
+ "functions and statements">;
let Documentation = [ConvergentDocs];
let SimpleHandler = 1;
}
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 2f3dd5d01fa6c..d73feb4382acd 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5636,6 +5636,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Attrs =
Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline);
+ // Add call-site convergent attribute if exists.
+ if (InConvergentAttributedStmt)
+ Attrs =
+ Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::Convergent);
+
// Apply some call-site-specific attributes.
// TODO: work this into building the attribute set.
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index aa97f685ac7a9..99559dfe075fb 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -723,6 +723,7 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
bool nomerge = false;
bool noinline = false;
bool alwaysinline = false;
+ bool convergent = false;
const CallExpr *musttail = nullptr;
for (const auto *A : S.getAttrs()) {
@@ -738,6 +739,9 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
case attr::AlwaysInline:
alwaysinline = true;
break;
+ case attr::Convergent:
+ convergent = true;
+ break;
case attr::MustTail: {
const Stmt *Sub = S.getSubStmt();
const ReturnStmt *R = cast<ReturnStmt>(Sub);
@@ -756,6 +760,7 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge);
SaveAndRestore save_noinline(InNoInlineAttributedStmt, noinline);
SaveAndRestore save_alwaysinline(InAlwaysInlineAttributedStmt, alwaysinline);
+ SaveAndRestore save_convergent(InConvergentAttributedStmt, convergent);
SaveAndRestore save_musttail(MustTailCall, musttail);
EmitStmt(S.getSubStmt(), S.getAttrs());
}
@@ -2465,7 +2470,8 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str,
static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect,
bool HasUnwindClobber, bool ReadOnly,
- bool ReadNone, bool NoMerge, const AsmStmt &S,
+ bool ReadNone, bool NoMerge, bool Convergent,
+ const AsmStmt &S,
const std::vector<llvm::Type *> &ResultRegTypes,
const std::vector<llvm::Type *> &ArgElemTypes,
CodeGenFunction &CGF,
@@ -2475,6 +2481,10 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect,
if (NoMerge)
Result.addFnAttr(llvm::Attribute::NoMerge);
+
+ if (Convergent)
+ Result.addFnAttr(llvm::Attribute::Convergent);
+
// Attach readnone and readonly attributes.
if (!HasSideEffect) {
if (ReadNone)
@@ -3037,9 +3047,10 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
if (IsGCCAsmGoto) {
CBR = Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
EmitBlock(Fallthrough);
- UpdateAsmCallInst(*CBR, HasSideEffect, false, ReadOnly, ReadNone,
- InNoMergeAttributedStmt, S, ResultRegTypes, ArgElemTypes,
- *this, RegResults);
+ UpdateAsmCallInst(*CBR, HasSideEffect, /*HasUnwindClobber=*/false, ReadOnly,
+ ReadNone, InNoMergeAttributedStmt,
+ InConvergentAttributedStmt, S, ResultRegTypes,
+ ArgElemTypes, *this, RegResults);
// Because we are emitting code top to bottom, we don't have enough
// information at this point to know precisely whether we have a critical
// edge. If we have outputs, split all indirect destinations.
@@ -3067,15 +3078,17 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
}
} else if (HasUnwindClobber) {
llvm::CallBase *Result = EmitCallOrInvoke(IA, Args, "");
- UpdateAsmCallInst(*Result, HasSideEffect, true, ReadOnly, ReadNone,
- InNoMergeAttributedStmt, S, ResultRegTypes, ArgElemTypes,
- *this, RegResults);
+ UpdateAsmCallInst(*Result, HasSideEffect, /*HasUnwindClobber=*/true,
+ ReadOnly, ReadNone, InNoMergeAttributedStmt,
+ InConvergentAttributedStmt, S, ResultRegTypes,
+ ArgElemTypes, *this, RegResults);
} else {
llvm::CallInst *Result =
Builder.CreateCall(IA, Args, getBundlesForFunclet(IA));
- UpdateAsmCallInst(*Result, HasSideEffect, false, ReadOnly, ReadNone,
- InNoMergeAttributedStmt, S, ResultRegTypes, ArgElemTypes,
- *this, RegResults);
+ UpdateAsmCallInst(*Result, HasSideEffect, /*HasUnwindClobber=*/false,
+ ReadOnly, ReadNone, InNoMergeAttributedStmt,
+ InConvergentAttributedStmt, S, ResultRegTypes,
+ ArgElemTypes, *this, RegResults);
}
EmitAsmStores(*this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 67e3019565cd0..329120b70fd49 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -612,6 +612,9 @@ class CodeGenFunction : public CodeGenTypeCache {
/// True if the current statement has always_inline attribute.
bool InAlwaysInlineAttributedStmt = false;
+ /// True if the current statement has convergent attribute.
+ bool InConvergentAttributedStmt = false;
+
// The CallExpr within the current statement that the musttail attribute
// applies to. nullptr if there is no 'musttail' on the current statement.
const CallExpr *MustTailCall = nullptr;
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 7f452d177c16f..ff743d9f9df20 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -230,6 +230,20 @@ static Attr *handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A,
return ::new (S.Context) NoMergeAttr(S.Context, A);
}
+static Attr *handleConvergentAttr(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+ NoMergeAttr NMA(S.Context, A);
+ CallExprFinder CEF(S, St);
+
+ if (!CEF.foundCallExpr() && !CEF.foundAsmStmt()) {
+ S.Diag(St->getBeginLoc(), diag::warn_attribute_ignored_no_calls_in_stmt)
+ << A;
+ return nullptr;
+ }
+
+ return ::new (S.Context) ConvergentAttr(S.Context, A);
+}
+
template <typename OtherAttr, int DiagIdx>
static bool CheckStmtInlineAttr(Sema &SemaRef, const Stmt *OrigSt,
const Stmt *CurSt,
@@ -672,6 +686,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
return handleCodeAlignAttr(S, St, A);
case ParsedAttr::AT_MSConstexpr:
return handleMSConstexprAttr(S, St, A, Range);
+ case ParsedAttr::AT_Convergent:
+ return handleConvergentAttr(S, St, A, Range);
default:
// N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
// declaration attribute is not written on a statement, but this code is
diff --git a/clang/test/SemaOpenCL/convergent.cl b/clang/test/SemaOpenCL/convergent.cl
index 1b7fda41fc0c8..a00e65cea0176 100644
--- a/clang/test/SemaOpenCL/convergent.cl
+++ b/clang/test/SemaOpenCL/convergent.cl
@@ -4,9 +4,9 @@ void f1(void) __attribute__((convergent));
void f2(void) __attribute__((convergent(1))); // expected-error {{'convergent' attribute takes no arguments}}
-void f3(int a __attribute__((convergent))); // expected-warning {{'convergent' attribute only applies to functions}}
+void f3(int a __attribute__((convergent))); // expected-warning {{'convergent' attribute only applies to functions and statements}}
void f4(void) {
- int var1 __attribute__((convergent)); // expected-warning {{'convergent' attribute only applies to functions}}
+ int var1 __attribute__((convergent)); // expected-warning {{'convergent' attribute only applies to functions and statements}}
}
>From 72631243e58ce58daa2535675aa5a8893267e7a0 Mon Sep 17 00:00:00 2001
From: Michael Liao <michael.hliao at gmail.com>
Date: Thu, 25 Jul 2024 15:34:11 -0400
Subject: [PATCH 2/3] Fix clang-formatting
Created using spr 1.3.4
---
clang/lib/CodeGen/CGCall.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d73feb4382acd..d11fe5795c52a 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5638,8 +5638,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// Add call-site convergent attribute if exists.
if (InConvergentAttributedStmt)
- Attrs =
- Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::Convergent);
+ Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::Convergent);
// Apply some call-site-specific attributes.
// TODO: work this into building the attribute set.
>From ef8ebb9e00f6f281a07decd79021dbe48bf1e29f Mon Sep 17 00:00:00 2001
From: Michael Liao <michael.hliao at gmail.com>
Date: Thu, 25 Jul 2024 18:54:31 -0400
Subject: [PATCH 3/3] cleanup
Created using spr 1.3.4
---
clang/test/CodeGen/convergent.cpp | 4 ----
1 file changed, 4 deletions(-)
diff --git a/clang/test/CodeGen/convergent.cpp b/clang/test/CodeGen/convergent.cpp
index ae782710f04fb..1d9c07d26bf71 100644
--- a/clang/test/CodeGen/convergent.cpp
+++ b/clang/test/CodeGen/convergent.cpp
@@ -16,14 +16,12 @@ class B : public A {
bool bar();
[[clang::convergent]] void f(bool, bool);
-//[[clang::convergent]] void (*fptr)(void);
void foo(int i, A *ap, B *bp) {
[[clang::convergent]] bar();
[[clang::convergent]] (i = 4, bar());
[[clang::convergent]] (void)(bar());
f(bar(), bar());
- //fptr();
[[clang::convergent]] [] { bar(); bar(); }(); // convergent only applies to the anonymous function call
[[clang::convergent]] for (bar(); bar(); bar()) {}
[[clang::convergent]] { asm("nop"); }
@@ -68,8 +66,6 @@ void something_else_again() {
// CHECK: call noundef zeroext i1 @_Z3barv(){{$}}
// CHECK: call noundef zeroext i1 @_Z3barv(){{$}}
// CHECK: call void @_Z1fbb({{.*}}) #[[ATTR0]]
-// XXX: %[[FPTR:.*]] = load ptr, ptr @fptr
-// XXX-NEXT: call void %[[FPTR]]() #[[ATTR0]]
// CHECK: call void @"_ZZ3fooiP1AP1BENK3$_0clEv"{{.*}} #[[ATTR0]]
// CHECK: call noundef zeroext i1 @_Z3barv() #[[ATTR0]]
// CHECK-LABEL: for.cond:
More information about the cfe-commits
mailing list