Skip to content

Commit 486720a

Browse files
committed
fix attributor
1 parent 05f601d commit 486720a

File tree

5 files changed

+211
-39
lines changed

5 files changed

+211
-39
lines changed

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,6 +2902,22 @@ struct AANonConvergentImpl : public AANonConvergent {
29022902
}
29032903
};
29042904

2905+
static bool FunctionCalledWithConvergenceToken(const Function *F) {
2906+
for (auto &Use : F->uses()) {
2907+
CallBase *CB = dyn_cast<CallBase>(Use.getUser());
2908+
if (!CB)
2909+
continue;
2910+
2911+
// We are not called, just used as an argument.
2912+
if (CB->getCalledFunction() != F)
2913+
continue;
2914+
2915+
if (CB->getConvergenceControlToken())
2916+
return true;
2917+
}
2918+
return false;
2919+
}
2920+
29052921
struct AANonConvergentFunction final : AANonConvergentImpl {
29062922
AANonConvergentFunction(const IRPosition &IRP, Attributor &A)
29072923
: AANonConvergentImpl(IRP, A) {}
@@ -2929,6 +2945,11 @@ struct AANonConvergentFunction final : AANonConvergentImpl {
29292945
UsedAssumedInformation)) {
29302946
return indicatePessimisticFixpoint();
29312947
}
2948+
2949+
const Function *F = this->getIRPosition().getAssociatedFunction();
2950+
if (FunctionCalledWithConvergenceToken(F))
2951+
return indicatePessimisticFixpoint();
2952+
29322953
return ChangeStatus::UNCHANGED;
29332954
}
29342955

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,12 +1864,16 @@ 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()) {
1867+
static bool FunctionRequiresConvergence(const Function *F) {
1868+
for (auto &Use : F->uses()) {
18691869
CallBase *CB = dyn_cast<CallBase>(Use.getUser());
18701870
if (!CB)
18711871
return true;
18721872

1873+
// We are not called, just used as an argument.
1874+
if (CB->getCalledFunction() != F)
1875+
continue;
1876+
18731877
if (CB->getConvergenceControlToken())
18741878
return true;
18751879
}
@@ -1981,7 +1985,7 @@ static void inferConvergent(const SCCNodeSet &SCCNodes,
19811985
Attribute::Convergent,
19821986
// Skip non-convergent functions.
19831987
[](const Function &F) {
1984-
return !F.isConvergent() || FunctionRequiresConvergence(F);
1988+
return !F.isConvergent() || FunctionRequiresConvergence(&F);
19851989
},
19861990
// Instructions that break non-convergent assumption.
19871991
[SCCNodes](Instruction &I) {

llvm/test/Transforms/ADCE/convergence.ll

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,37 @@ exit:
5353
ret void
5454
}
5555

56+
define void @indirect_inner() #0 {
57+
; CHECK-LABEL: define void @indirect_inner(
58+
; CHECK-SAME: ) #[[ATTR0]] {
59+
; CHECK-NEXT: [[ENTRY:.*:]]
60+
; CHECK-NEXT: ret void
61+
;
62+
entry:
63+
%tk0 = call token @llvm.experimental.convergence.entry()
64+
ret void
65+
}
66+
67+
define void @indirect() #0 {
68+
; CHECK-LABEL: define void @indirect(
69+
; CHECK-SAME: ) #[[ATTR0]] {
70+
; CHECK-NEXT: [[ENTRY:.*:]]
71+
; CHECK-NEXT: [[TK0:%.*]] = call token @llvm.experimental.convergence.entry()
72+
; CHECK-NEXT: [[VAR:%.*]] = alloca ptr, align 8
73+
; CHECK-NEXT: store ptr @indirect_inner, ptr [[VAR]], align 8
74+
; CHECK-NEXT: [[PTR:%.*]] = load ptr, ptr [[VAR]], align 8
75+
; CHECK-NEXT: call void [[PTR]]() #[[ATTR0]] [ "convergencectrl"(token [[TK0]]) ]
76+
; CHECK-NEXT: ret void
77+
;
78+
entry:
79+
%tk0 = call token @llvm.experimental.convergence.entry()
80+
%var = alloca ptr, align 8
81+
store ptr @indirect_inner, ptr %var, align 8
82+
%ptr = load ptr, ptr %var, align 8
83+
call void %ptr() convergent [ "convergencectrl"(token %tk0) ]
84+
ret void
85+
}
86+
5687
declare token @llvm.experimental.convergence.entry() #1
5788
declare token @llvm.experimental.convergence.anchor() #1
5889
declare token @llvm.experimental.convergence.loop() #1
Lines changed: 150 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2-
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3-
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 5
2+
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3+
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S %s | FileCheck %s --check-prefixes=CHECK,CGSCC
44

55
define i32 @defined() convergent {
66
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
7-
; CHECK-LABEL: define {{[^@]+}}@defined
8-
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
7+
; CHECK-LABEL: define noundef i32 @defined(
8+
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
99
; CHECK-NEXT: ret i32 1
1010
;
1111
ret i32 1
1212
}
1313

1414
define i32 @calls_defined() convergent {
1515
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
16-
; TUNIT-LABEL: define {{[^@]+}}@calls_defined
17-
; TUNIT-SAME: () #[[ATTR0]] {
16+
; TUNIT-LABEL: define noundef i32 @calls_defined(
17+
; TUNIT-SAME: ) #[[ATTR0]] {
1818
; TUNIT-NEXT: ret i32 1
1919
;
2020
; CGSCC: Function Attrs: convergent mustprogress nofree nosync nounwind willreturn memory(none)
21-
; CGSCC-LABEL: define {{[^@]+}}@calls_defined
22-
; CGSCC-SAME: () #[[ATTR1:[0-9]+]] {
23-
; CGSCC-NEXT: [[A:%.*]] = call noundef i32 @defined() #[[ATTR6:[0-9]+]]
21+
; CGSCC-LABEL: define noundef i32 @calls_defined(
22+
; CGSCC-SAME: ) #[[ATTR1:[0-9]+]] {
23+
; CGSCC-NEXT: [[A:%.*]] = call noundef i32 @defined() #[[ATTR7:[0-9]+]]
2424
; CGSCC-NEXT: ret i32 [[A]]
2525
;
2626
%a = call i32 @defined()
@@ -30,7 +30,7 @@ define i32 @calls_defined() convergent {
3030
declare void @declared_non_convergent()
3131

3232
define void @calls_declared_non_convergent() convergent {
33-
; CHECK-LABEL: define {{[^@]+}}@calls_declared_non_convergent() {
33+
; CHECK-LABEL: define void @calls_declared_non_convergent() {
3434
; CHECK-NEXT: call void @declared_non_convergent()
3535
; CHECK-NEXT: ret void
3636
;
@@ -43,24 +43,135 @@ declare i32 @declared_convergent() convergent
4343

4444
define i32 @calls_declared_convergent() convergent {
4545
; TUNIT: Function Attrs: convergent
46-
; TUNIT-LABEL: define {{[^@]+}}@calls_declared_convergent
47-
; TUNIT-SAME: () #[[ATTR1:[0-9]+]] {
46+
; TUNIT-LABEL: define i32 @calls_declared_convergent(
47+
; TUNIT-SAME: ) #[[ATTR1:[0-9]+]] {
4848
; TUNIT-NEXT: [[A:%.*]] = call i32 @declared_convergent()
4949
; TUNIT-NEXT: ret i32 [[A]]
5050
;
5151
; CGSCC: Function Attrs: convergent
52-
; CGSCC-LABEL: define {{[^@]+}}@calls_declared_convergent
53-
; CGSCC-SAME: () #[[ATTR2:[0-9]+]] {
52+
; CGSCC-LABEL: define i32 @calls_declared_convergent(
53+
; CGSCC-SAME: ) #[[ATTR2:[0-9]+]] {
5454
; CGSCC-NEXT: [[A:%.*]] = call i32 @declared_convergent()
5555
; CGSCC-NEXT: ret i32 [[A]]
5656
;
5757
%a = call i32 @declared_convergent()
5858
ret i32 %a
5959
}
6060

61+
; Function declared convergent. Body not provided to prevent inlining
62+
; of the functions below.
63+
declare i32 @direct_call_convergent_attribute_with_token_declared(i32 %a)
64+
65+
; This function could be declared non-convergent as it only calls
66+
; non-convergent functions, but it is being called with a convergence token,
67+
; hence it is not allowed to drop the convergence attribute.
68+
define i32 @direct_call_convergent_attribute_with_token_inner(i32 %a) convergent {
69+
; TUNIT: Function Attrs: convergent
70+
; TUNIT-LABEL: define i32 @direct_call_convergent_attribute_with_token_inner(
71+
; TUNIT-SAME: i32 [[A:%.*]]) #[[ATTR1]] {
72+
; TUNIT-NEXT: [[RS:%.*]] = call i32 @direct_call_convergent_attribute_with_token_declared(i32 [[A]])
73+
; TUNIT-NEXT: ret i32 [[RS]]
74+
;
75+
; CGSCC: Function Attrs: convergent
76+
; CGSCC-LABEL: define i32 @direct_call_convergent_attribute_with_token_inner(
77+
; CGSCC-SAME: i32 [[A:%.*]]) #[[ATTR2]] {
78+
; CGSCC-NEXT: [[RS:%.*]] = call i32 @direct_call_convergent_attribute_with_token_declared(i32 [[A]])
79+
; CGSCC-NEXT: ret i32 [[RS]]
80+
;
81+
%rs = call i32 @direct_call_convergent_attribute_with_token_declared(i32 %a)
82+
ret i32 %rs
83+
}
84+
85+
define i32 @direct_call_convergent_attribute_with_token(i32 %a) convergent {
86+
; TUNIT: Function Attrs: convergent
87+
; TUNIT-LABEL: define i32 @direct_call_convergent_attribute_with_token(
88+
; TUNIT-SAME: i32 [[A:%.*]]) #[[ATTR1]] {
89+
; TUNIT-NEXT: [[TK:%.*]] = call token @llvm.experimental.convergence.entry() #[[ATTR6:[0-9]+]]
90+
; TUNIT-NEXT: [[RS:%.*]] = call i32 @direct_call_convergent_attribute_with_token_inner(i32 [[A]]) [ "convergencectrl"(token [[TK]]) ]
91+
; TUNIT-NEXT: ret i32 [[RS]]
92+
;
93+
; CGSCC: Function Attrs: convergent
94+
; CGSCC-LABEL: define i32 @direct_call_convergent_attribute_with_token(
95+
; CGSCC-SAME: i32 [[A:%.*]]) #[[ATTR2]] {
96+
; CGSCC-NEXT: [[TK:%.*]] = call token @llvm.experimental.convergence.entry() #[[ATTR8:[0-9]+]]
97+
; CGSCC-NEXT: [[RS:%.*]] = call i32 @direct_call_convergent_attribute_with_token_inner(i32 [[A]]) [ "convergencectrl"(token [[TK]]) ]
98+
; CGSCC-NEXT: ret i32 [[RS]]
99+
;
100+
%tk = call token @llvm.experimental.convergence.entry()
101+
%rs = call i32 @direct_call_convergent_attribute_with_token_inner(i32 %a) [ "convergencectrl"(token %tk) ]
102+
ret i32 %rs
103+
}
104+
105+
; Function declared non-convergent.
106+
declare i32 @indirect_call_declared(i32 %a)
107+
108+
; Function declared convergent, but which is not required to be
109+
; marked convergent: the only used is through a call which is marked
110+
; as convergent, hence the function attribute can be dropped.
111+
define i32 @indirect_call_inner(i32 %a) convergent {
112+
; CHECK-LABEL: define i32 @indirect_call_inner(
113+
; CHECK-SAME: i32 [[A:%.*]]) {
114+
; CHECK-NEXT: [[RS:%.*]] = call i32 @indirect_call_declared(i32 [[A]])
115+
; CHECK-NEXT: ret i32 [[RS]]
116+
;
117+
%rs = call i32 @indirect_call_declared(i32 %a)
118+
ret i32 %rs
119+
}
120+
121+
; Convergent function, calling a function and marking the call as convergent.
122+
define i32 @indirect_call(i32 %a) convergent {
123+
; TUNIT: Function Attrs: convergent
124+
; TUNIT-LABEL: define i32 @indirect_call(
125+
; TUNIT-SAME: i32 [[A:%.*]]) #[[ATTR1]] {
126+
; TUNIT-NEXT: [[TK:%.*]] = call token @llvm.experimental.convergence.entry() #[[ATTR7:[0-9]+]]
127+
; TUNIT-NEXT: [[RS:%.*]] = call i32 @indirect_call_inner(i32 [[A]]) #[[ATTR1]] [ "convergencectrl"(token [[TK]]) ]
128+
; TUNIT-NEXT: ret i32 [[RS]]
129+
;
130+
; CGSCC: Function Attrs: convergent
131+
; CGSCC-LABEL: define i32 @indirect_call(
132+
; CGSCC-SAME: i32 [[A:%.*]]) #[[ATTR2]] {
133+
; CGSCC-NEXT: [[TK:%.*]] = call token @llvm.experimental.convergence.entry() #[[ATTR7]]
134+
; CGSCC-NEXT: [[RS:%.*]] = call i32 @indirect_call_inner(i32 [[A]]) #[[ATTR2]] [ "convergencectrl"(token [[TK]]) ]
135+
; CGSCC-NEXT: ret i32 [[RS]]
136+
;
137+
%tk = call token @llvm.experimental.convergence.entry()
138+
%fptr = alloca ptr
139+
store ptr @indirect_call_inner, ptr %fptr
140+
%ic = load ptr, ptr %fptr
141+
%rs = call i32 %ic(i32 %a) convergent [ "convergencectrl"(token %tk) ]
142+
ret i32 %rs
143+
}
144+
145+
; A non-convergent declaration.
146+
declare i32 @leaf_convergent_indirect_declared(i32 %a)
147+
148+
; A function calling indirectly a non-convergent function.
149+
define i32 @leaf_convergent_indirect(i32 %a) convergent {
150+
; TUNIT: Function Attrs: convergent
151+
; TUNIT-LABEL: define i32 @leaf_convergent_indirect(
152+
; TUNIT-SAME: i32 [[A:%.*]]) #[[ATTR1]] {
153+
; TUNIT-NEXT: [[TK:%.*]] = call token @llvm.experimental.convergence.entry() #[[ATTR7]]
154+
; TUNIT-NEXT: [[RS:%.*]] = call i32 @leaf_convergent_indirect_declared(i32 [[A]]) #[[ATTR1]] [ "convergencectrl"(token [[TK]]) ]
155+
; TUNIT-NEXT: ret i32 [[RS]]
156+
;
157+
; CGSCC: Function Attrs: convergent
158+
; CGSCC-LABEL: define i32 @leaf_convergent_indirect(
159+
; CGSCC-SAME: i32 [[A:%.*]]) #[[ATTR2]] {
160+
; CGSCC-NEXT: [[TK:%.*]] = call token @llvm.experimental.convergence.entry() #[[ATTR7]]
161+
; CGSCC-NEXT: [[RS:%.*]] = call i32 @leaf_convergent_indirect_declared(i32 [[A]]) #[[ATTR2]] [ "convergencectrl"(token [[TK]]) ]
162+
; CGSCC-NEXT: ret i32 [[RS]]
163+
;
164+
%tk = call token @llvm.experimental.convergence.entry()
165+
%fptr = alloca ptr
166+
store ptr @leaf_convergent_indirect_declared, ptr %fptr
167+
%ic = load ptr, ptr %fptr
168+
%rs = call i32 %ic(i32 %a) convergent [ "convergencectrl"(token %tk) ]
169+
ret i32 %rs
170+
}
171+
61172
define i32 @defined_with_asm(i32 %a, i32 %b) {
62-
; CHECK-LABEL: define {{[^@]+}}@defined_with_asm
63-
; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
173+
; CHECK-LABEL: define i32 @defined_with_asm(
174+
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
64175
; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[A]], [[B]]
65176
; CHECK-NEXT: [[ASM_RESULT:%.*]] = call i32 asm sideeffect "addl $1, $0", "=r,r"(i32 [[RESULT]])
66177
; CHECK-NEXT: ret i32 [[ASM_RESULT]]
@@ -72,14 +183,14 @@ define i32 @defined_with_asm(i32 %a, i32 %b) {
72183

73184
define i32 @calls_defined_with_asm(i32 %a, i32 %b) convergent {
74185
; TUNIT: Function Attrs: convergent
75-
; TUNIT-LABEL: define {{[^@]+}}@calls_defined_with_asm
76-
; TUNIT-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR1]] {
186+
; TUNIT-LABEL: define i32 @calls_defined_with_asm(
187+
; TUNIT-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR1]] {
77188
; TUNIT-NEXT: [[C:%.*]] = call i32 @defined_with_asm(i32 [[A]], i32 [[B]])
78189
; TUNIT-NEXT: ret i32 [[C]]
79190
;
80191
; CGSCC: Function Attrs: convergent
81-
; CGSCC-LABEL: define {{[^@]+}}@calls_defined_with_asm
82-
; CGSCC-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR2]] {
192+
; CGSCC-LABEL: define i32 @calls_defined_with_asm(
193+
; CGSCC-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR2]] {
83194
; CGSCC-NEXT: [[C:%.*]] = call i32 @defined_with_asm(i32 [[A]], i32 [[B]])
84195
; CGSCC-NEXT: ret i32 [[C]]
85196
;
@@ -91,15 +202,15 @@ declare void @llvm.convergent.copy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1
91202

92203
define void @calls_convergent_intrinsic(ptr %dest, ptr %src, i64 %size) convergent {
93204
; TUNIT: Function Attrs: convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
94-
; TUNIT-LABEL: define {{[^@]+}}@calls_convergent_intrinsic
95-
; TUNIT-SAME: (ptr nofree [[DEST:%.*]], ptr nofree [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR3:[0-9]+]] {
96-
; TUNIT-NEXT: call void @llvm.convergent.copy.p0.p0.i64(ptr nofree [[DEST]], ptr nofree [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR5:[0-9]+]]
205+
; TUNIT-LABEL: define void @calls_convergent_intrinsic(
206+
; TUNIT-SAME: ptr nofree [[DEST:%.*]], ptr nofree [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR3:[0-9]+]] {
207+
; TUNIT-NEXT: call void @llvm.convergent.copy.p0.p0.i64(ptr nofree [[DEST]], ptr nofree [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR6]]
97208
; TUNIT-NEXT: ret void
98209
;
99210
; CGSCC: Function Attrs: convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
100-
; CGSCC-LABEL: define {{[^@]+}}@calls_convergent_intrinsic
101-
; CGSCC-SAME: (ptr nofree [[DEST:%.*]], ptr nofree [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR4:[0-9]+]] {
102-
; CGSCC-NEXT: call void @llvm.convergent.copy.p0.p0.i64(ptr nofree [[DEST]], ptr nofree [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR7:[0-9]+]]
211+
; CGSCC-LABEL: define void @calls_convergent_intrinsic(
212+
; CGSCC-SAME: ptr nofree [[DEST:%.*]], ptr nofree [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR4:[0-9]+]] {
213+
; CGSCC-NEXT: call void @llvm.convergent.copy.p0.p0.i64(ptr nofree [[DEST]], ptr nofree [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR8]]
103214
; CGSCC-NEXT: ret void
104215
;
105216
call void @llvm.convergent.copy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1 false)
@@ -110,15 +221,15 @@ declare void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1 %isVolati
110221

111222
define void @calls_intrinsic(ptr %dest, ptr %src, i64 %size) convergent {
112223
; TUNIT: Function Attrs: convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
113-
; TUNIT-LABEL: define {{[^@]+}}@calls_intrinsic
114-
; TUNIT-SAME: (ptr nofree writeonly captures(none) [[DEST:%.*]], ptr nofree readonly captures(none) [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR2:[0-9]+]] {
115-
; TUNIT-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr nofree writeonly captures(none) [[DEST]], ptr nofree readonly captures(none) [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR5]]
224+
; TUNIT-LABEL: define void @calls_intrinsic(
225+
; TUNIT-SAME: ptr nofree writeonly captures(none) [[DEST:%.*]], ptr nofree readonly captures(none) [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR2:[0-9]+]] {
226+
; TUNIT-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr nofree writeonly captures(none) [[DEST]], ptr nofree readonly captures(none) [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR6]]
116227
; TUNIT-NEXT: ret void
117228
;
118229
; CGSCC: Function Attrs: convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
119-
; CGSCC-LABEL: define {{[^@]+}}@calls_intrinsic
120-
; CGSCC-SAME: (ptr nofree writeonly captures(none) [[DEST:%.*]], ptr nofree readonly captures(none) [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR3:[0-9]+]] {
121-
; CGSCC-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr nofree writeonly captures(none) [[DEST]], ptr nofree readonly captures(none) [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR7]]
230+
; CGSCC-LABEL: define void @calls_intrinsic(
231+
; CGSCC-SAME: ptr nofree writeonly captures(none) [[DEST:%.*]], ptr nofree readonly captures(none) [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR3:[0-9]+]] {
232+
; CGSCC-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr nofree writeonly captures(none) [[DEST]], ptr nofree readonly captures(none) [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR8]]
122233
; CGSCC-NEXT: ret void
123234
;
124235
call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1 false)
@@ -133,14 +244,17 @@ attributes #0 = { convergent mustprogress nofree norecurse nosync nounwind willr
133244
; TUNIT: attributes #[[ATTR2]] = { convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
134245
; TUNIT: attributes #[[ATTR3]] = { convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) }
135246
; TUNIT: attributes #[[ATTR4:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
136-
; TUNIT: attributes #[[ATTR5]] = { nofree willreturn }
247+
; TUNIT: attributes #[[ATTR5:[0-9]+]] = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
248+
; TUNIT: attributes #[[ATTR6]] = { nofree willreturn }
249+
; TUNIT: attributes #[[ATTR7]] = { nofree nosync willreturn }
137250
;.
138251
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
139252
; CGSCC: attributes #[[ATTR1]] = { convergent mustprogress nofree nosync nounwind willreturn memory(none) }
140253
; CGSCC: attributes #[[ATTR2]] = { convergent }
141254
; CGSCC: attributes #[[ATTR3]] = { convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
142255
; CGSCC: attributes #[[ATTR4]] = { convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) }
143256
; CGSCC: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
144-
; CGSCC: attributes #[[ATTR6]] = { nofree nosync willreturn }
145-
; CGSCC: attributes #[[ATTR7]] = { nofree willreturn }
257+
; CGSCC: attributes #[[ATTR6:[0-9]+]] = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
258+
; CGSCC: attributes #[[ATTR7]] = { nofree nosync willreturn }
259+
; CGSCC: attributes #[[ATTR8]] = { nofree willreturn }
146260
;.

llvm/test/Transforms/FunctionAttrs/convergent.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
22
; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
3+
; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
4+
; RUN: opt -passes=function-attrs --aa-pipeline=basic-aa -S %s | FileCheck %s
35

46
define i32 @nonleaf() convergent {
57
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)

0 commit comments

Comments
 (0)