File tree Expand file tree Collapse file tree 4 files changed +141
-1
lines changed Expand file tree Collapse file tree 4 files changed +141
-1
lines changed Original file line number Diff line number Diff line change @@ -1864,6 +1864,19 @@ static bool InstrBreaksNonConvergent(Instruction &I,
18641864 !SCCNodes.contains (CB->getCalledFunction ());
18651865}
18661866
1867+ static bool FunctionRequiresConvergence (const Function &F) {
1868+ for (auto &Use : F.uses ()) {
1869+ CallBase *CB = dyn_cast<CallBase>(Use.getUser ());
1870+ if (!CB)
1871+ return true ;
1872+
1873+ if (CB->getConvergenceControlToken ())
1874+ return true ;
1875+ }
1876+
1877+ return false ;
1878+ }
1879+
18671880// / Helper for NoUnwind inference predicate InstrBreaksAttribute.
18681881static bool InstrBreaksNonThrowing (Instruction &I, const SCCNodeSet &SCCNodes) {
18691882 if (!I.mayThrow (/* IncludePhaseOneUnwind */ true ))
@@ -1967,7 +1980,9 @@ static void inferConvergent(const SCCNodeSet &SCCNodes,
19671980 AI.registerAttrInference (AttributeInferer::InferenceDescriptor{
19681981 Attribute::Convergent,
19691982 // Skip non-convergent functions.
1970- [](const Function &F) { return !F.isConvergent (); },
1983+ [](const Function &F) {
1984+ return !F.isConvergent () || FunctionRequiresConvergence (F);
1985+ },
19711986 // Instructions that break non-convergent assumption.
19721987 [SCCNodes](Instruction &I) {
19731988 return InstrBreaksNonConvergent (I, SCCNodes);
Original file line number Diff line number Diff line change 1+ ; RUN: opt %s -passes=adce -S | FileCheck %s
2+
3+ ; CHECK: Function Attrs: convergent
4+ ; CHECK-NEXT: define i32 @foo(i32 %a) #0 {
5+ define i32 @foo (i32 %a ) #0 {
6+ entry:
7+ ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry()
8+ %0 = call token @llvm.experimental.convergence.entry ()
9+ ret i32 %a
10+ }
11+
12+ ; CHECK: Function Attrs: convergent
13+ ; CHECK-NEXT: define void @bar() #0 {
14+ define void @bar () #0 {
15+ entry:
16+ ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry()
17+ %0 = call token @llvm.experimental.convergence.anchor ()
18+ ret void
19+ }
20+
21+ ; CHECK: Function Attrs: convergent
22+ ; CHECK-NEXT: define void @baz() #0 {
23+ define void @baz () #0 {
24+ entry:
25+ ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry()
26+ %0 = call token @llvm.experimental.convergence.entry ()
27+ br label %header
28+
29+ header:
30+ ; CHECK-NOT: %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
31+ %1 = call token @llvm.experimental.convergence.loop () [ "convergencectrl" (token %0 ) ]
32+ br i1 true , label %body , label %exit
33+
34+ body:
35+ br label %header
36+
37+ exit:
38+ ret void
39+ }
40+
41+ declare token @llvm.experimental.convergence.entry () #1
42+ declare token @llvm.experimental.convergence.anchor () #1
43+ declare token @llvm.experimental.convergence.loop () #1
44+
45+ attributes #0 = { convergent }
46+ attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
Original file line number Diff line number Diff line change 1+ ; RUN: opt %s -passes=bdce -S | FileCheck %s
2+
3+ ; CHECK: Function Attrs: convergent
4+ ; CHECK-NEXT: define i32 @foo(i32 %a) #0 {
5+ define i32 @foo (i32 %a ) #0 {
6+ entry:
7+ ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry()
8+ %0 = call token @llvm.experimental.convergence.entry ()
9+ ret i32 %a
10+ }
11+
12+ ; CHECK: Function Attrs: convergent
13+ ; CHECK-NEXT: define void @bar() #0 {
14+ define void @bar () #0 {
15+ entry:
16+ ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry()
17+ %0 = call token @llvm.experimental.convergence.anchor ()
18+ ret void
19+ }
20+
21+ ; CHECK: Function Attrs: convergent
22+ ; CHECK-NEXT: define void @baz() #0 {
23+ define void @baz () #0 {
24+ entry:
25+ ; CHECK-NOT: %0 = call token @llvm.experimental.convergence.entry()
26+ %0 = call token @llvm.experimental.convergence.entry ()
27+ br label %header
28+
29+ header:
30+ ; CHECK-NOT: %1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
31+ %1 = call token @llvm.experimental.convergence.loop () [ "convergencectrl" (token %0 ) ]
32+ br i1 true , label %body , label %exit
33+
34+ body:
35+ br label %header
36+
37+ exit:
38+ ret void
39+ }
40+
41+ declare token @llvm.experimental.convergence.entry () #1
42+ declare token @llvm.experimental.convergence.anchor () #1
43+ declare token @llvm.experimental.convergence.loop () #1
44+
45+ attributes #0 = { convergent }
46+ attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
47+
Original file line number Diff line number Diff line change @@ -129,3 +129,35 @@ define i32 @noopt_friend() convergent {
129129 %a = call i32 @noopt ()
130130 ret i32 0
131131}
132+
133+ ; A function which should normally be stripped of its convergent attribute,
134+ ; but because it's used in a controlled convergence call, the attribute
135+ ; remains.
136+ ; This could be improved by propagating the non-convergence outside of the
137+ ; function, but for the time being, we stop when we encounter this scenario.
138+ define i32 @leaf_noconvergent_used () convergent {
139+ ; CHECK: Function Attrs: convergent mustprogress nofree norecurse nosync nounwind willreturn memory(none)
140+ ; CHECK-LABEL: define {{[^@]+}}@leaf_noconvergent_used
141+ ; CHECK-SAME: () #[[ATTR7:[0-9]+]] {
142+ ; CHECK-NEXT: ret i32 0
143+ ;
144+ ret i32 0
145+ }
146+
147+ define i32 @nonleaf_convergent () convergent {
148+ ; CHECK: Function Attrs: convergent mustprogress nofree norecurse nosync nounwind willreturn memory(none)
149+ ; CHECK-LABEL: define {{[^@]+}}@nonleaf_convergent
150+ ; CHECK-SAME: () #[[ATTR7]] {
151+ ; CHECK-NEXT: [[TMP1:%.*]] = call token @llvm.experimental.convergence.entry()
152+ ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @leaf_noconvergent_used() [ "convergencectrl"(token [[TMP1]]) ]
153+ ; CHECK-NEXT: ret i32 0
154+ ;
155+ %1 = call token @llvm.experimental.convergence.entry ()
156+ %2 = call i32 @leaf_noconvergent_used () [ "convergencectrl" (token %1 ) ]
157+ ret i32 0
158+ }
159+
160+
161+ declare token @llvm.experimental.convergence.entry () #1
162+
163+ attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
You can’t perform that action at this time.
0 commit comments