Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / Attributor / nosync.ll
blob5059666943809dd1121b27addc25dd25997b5937
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
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6 ; Test cases designed for the nosync function attribute.
7 ; FIXME's are used to indicate problems and missing attributes.
9 ; struct RT {
10 ;   char A;
11 ;   int B[10][20];
12 ;   char C;
13 ; };
14 ; struct ST {
15 ;   int X;
16 ;   double Y;
17 ;   struct RT Z;
18 ; };
20 ; int *foo(struct ST *s) {
21 ;   return &s[1].Z.B[5][13];
22 ; }
24 ; TEST 1
25 ; non-convergent and readnone implies nosync
26 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
27 %struct.ST = type { i32, double, %struct.RT }
30 ; CHECK: @[[A:[a-zA-Z0-9_$"\\.-]+]] = common global i32 0, align 4
32 define ptr @foo(ptr %s) nounwind optsize ssp memory(none) uwtable {
33 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind optsize ssp willreturn memory(none) uwtable
34 ; CHECK-LABEL: define {{[^@]+}}@foo
35 ; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[S:%.*]]) #[[ATTR0:[0-9]+]] {
36 ; CHECK-NEXT:  entry:
37 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], ptr [[S]], i64 1, i32 2, i32 1, i64 5, i64 13
38 ; CHECK-NEXT:    ret ptr [[ARRAYIDX]]
40 entry:
41   %arrayidx = getelementptr inbounds %struct.ST, ptr %s, i64 1, i32 2, i32 1, i64 5, i64 13
42   ret ptr %arrayidx
45 ; TEST 2
46 ; atomic load with monotonic ordering
47 ; int load_monotonic(_Atomic int *num) {
48 ;   int n = atomic_load_explicit(num, memory_order_relaxed);
49 ;   return n;
50 ; }
52 define i32 @load_monotonic(ptr nocapture readonly %arg) norecurse nounwind uwtable {
53 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
54 ; CHECK-LABEL: define {{[^@]+}}@load_monotonic
55 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR1:[0-9]+]] {
56 ; CHECK-NEXT:    [[I:%.*]] = load atomic i32, ptr [[ARG]] monotonic, align 4
57 ; CHECK-NEXT:    ret i32 [[I]]
59   %i = load atomic i32, ptr %arg monotonic, align 4
60   ret i32 %i
64 ; TEST 3
65 ; atomic store with monotonic ordering.
66 ; void store_monotonic(_Atomic int *num) {
67 ;   atomic_load_explicit(num, memory_order_relaxed);
68 ; }
70 define void @store_monotonic(ptr nocapture %arg) norecurse nounwind uwtable {
71 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable
72 ; CHECK-LABEL: define {{[^@]+}}@store_monotonic
73 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR1]] {
74 ; CHECK-NEXT:    store atomic i32 10, ptr [[ARG]] monotonic, align 4
75 ; CHECK-NEXT:    ret void
77   store atomic i32 10, ptr %arg monotonic, align 4
78   ret void
81 ; TEST 4 - negative, should not deduce nosync
82 ; atomic load with acquire ordering.
83 ; int load_acquire(_Atomic int *num) {
84 ;   int n = atomic_load_explicit(num, memory_order_acquire);
85 ;   return n;
86 ; }
88 define i32 @load_acquire(ptr nocapture readonly %arg) norecurse nounwind uwtable {
89 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
90 ; CHECK-LABEL: define {{[^@]+}}@load_acquire
91 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR2:[0-9]+]] {
92 ; CHECK-NEXT:    [[I:%.*]] = load atomic i32, ptr [[ARG]] acquire, align 4
93 ; CHECK-NEXT:    ret i32 [[I]]
95   %i = load atomic i32, ptr %arg acquire, align 4
96   ret i32 %i
99 ; TEST 5 - negative, should not deduce nosync
100 ; atomic load with release ordering
101 ; void load_release(_Atomic int *num) {
102 ;   atomic_store_explicit(num, 10, memory_order_release);
103 ; }
105 define void @load_release(ptr nocapture %arg) norecurse nounwind uwtable {
106 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
107 ; CHECK-LABEL: define {{[^@]+}}@load_release
108 ; CHECK-SAME: (ptr nocapture nofree noundef writeonly align 4 [[ARG:%.*]]) #[[ATTR2]] {
109 ; CHECK-NEXT:    store atomic volatile i32 10, ptr [[ARG]] release, align 4
110 ; CHECK-NEXT:    ret void
112   store atomic volatile i32 10, ptr %arg release, align 4
113   ret void
116 ; TEST 6 - negative volatile, relaxed atomic
118 define void @load_volatile_release(ptr nocapture %arg) norecurse nounwind uwtable {
119 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
120 ; CHECK-LABEL: define {{[^@]+}}@load_volatile_release
121 ; CHECK-SAME: (ptr nocapture nofree noundef writeonly align 4 [[ARG:%.*]]) #[[ATTR2]] {
122 ; CHECK-NEXT:    store atomic volatile i32 10, ptr [[ARG]] release, align 4
123 ; CHECK-NEXT:    ret void
125   store atomic volatile i32 10, ptr %arg release, align 4
126   ret void
129 ; TEST 7 - negative, should not deduce nosync
130 ; volatile store.
131 ; void volatile_store(volatile int *num) {
132 ;   *num = 14;
133 ; }
135 define void @volatile_store(ptr %arg) norecurse nounwind uwtable {
136 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
137 ; CHECK-LABEL: define {{[^@]+}}@volatile_store
138 ; CHECK-SAME: (ptr nofree noundef align 4 [[ARG:%.*]]) #[[ATTR2]] {
139 ; CHECK-NEXT:    store volatile i32 14, ptr [[ARG]], align 4
140 ; CHECK-NEXT:    ret void
142   store volatile i32 14, ptr %arg, align 4
143   ret void
146 ; TEST 8 - negative, should not deduce nosync
147 ; volatile load.
148 ; int volatile_load(volatile int *num) {
149 ;   int n = *num;
150 ;   return n;
151 ; }
153 define i32 @volatile_load(ptr %arg) norecurse nounwind uwtable {
154 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
155 ; CHECK-LABEL: define {{[^@]+}}@volatile_load
156 ; CHECK-SAME: (ptr nofree noundef align 4 [[ARG:%.*]]) #[[ATTR2]] {
157 ; CHECK-NEXT:    [[I:%.*]] = load volatile i32, ptr [[ARG]], align 4
158 ; CHECK-NEXT:    ret i32 [[I]]
160   %i = load volatile i32, ptr %arg, align 4
161   ret i32 %i
164 ; TEST 9
166 ; CHECK: Function Attrs: noinline nosync nounwind uwtable
167 ; CHECK-NEXT: declare void @nosync_function()
168 declare void @nosync_function() noinline nounwind uwtable nosync
170 define void @call_nosync_function() noinline nounwind uwtable {
171 ; CHECK: Function Attrs: noinline nosync nounwind uwtable
172 ; CHECK-LABEL: define {{[^@]+}}@call_nosync_function
173 ; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
174 ; CHECK-NEXT:    tail call void @nosync_function() #[[ATTR4:[0-9]+]]
175 ; CHECK-NEXT:    ret void
177   tail call void @nosync_function() noinline nounwind uwtable
178   ret void
181 ; TEST 10 - negative, should not deduce nosync
183 ; CHECK: Function Attrs: noinline nounwind uwtable
184 ; CHECK-NEXT: declare void @might_sync()
185 declare void @might_sync() noinline nounwind uwtable
187 define void @call_might_sync() noinline nounwind uwtable {
188 ; CHECK: Function Attrs: noinline nounwind uwtable
189 ; CHECK-LABEL: define {{[^@]+}}@call_might_sync
190 ; CHECK-SAME: () #[[ATTR4]] {
191 ; CHECK-NEXT:    tail call void @might_sync() #[[ATTR4]]
192 ; CHECK-NEXT:    ret void
194   tail call void @might_sync() noinline nounwind uwtable
195   ret void
198 ; TEST 11 - positive, should deduce nosync
199 ; volatile operation in same scc but dead. Call volatile_load defined in TEST 8.
201 define i32 @scc1(ptr %arg) noinline nounwind uwtable {
202 ; CHECK: Function Attrs: nofree noinline nounwind memory(argmem: readwrite) uwtable
203 ; CHECK-LABEL: define {{[^@]+}}@scc1
204 ; CHECK-SAME: (ptr nofree [[ARG:%.*]]) #[[ATTR5:[0-9]+]] {
205 ; CHECK-NEXT:    tail call void @scc2(ptr nofree [[ARG]]) #[[ATTR20:[0-9]+]]
206 ; CHECK-NEXT:    [[VAL:%.*]] = tail call i32 @volatile_load(ptr nofree noundef align 4 [[ARG]]) #[[ATTR20]]
207 ; CHECK-NEXT:    ret i32 [[VAL]]
209   tail call void @scc2(ptr %arg)
210   %val = tail call i32 @volatile_load(ptr %arg)
211   ret i32 %val
214 define void @scc2(ptr %arg) noinline nounwind uwtable {
215 ; CHECK: Function Attrs: nofree noinline nounwind memory(argmem: readwrite) uwtable
216 ; CHECK-LABEL: define {{[^@]+}}@scc2
217 ; CHECK-SAME: (ptr nofree [[ARG:%.*]]) #[[ATTR5]] {
218 ; CHECK-NEXT:    [[I:%.*]] = tail call i32 @scc1(ptr nofree [[ARG]]) #[[ATTR20]]
219 ; CHECK-NEXT:    ret void
221   %i = tail call i32 @scc1(ptr %arg)
222   ret void
225 ; TEST 12 - fences, negative
227 ; void foo1(int *a, std::atomic<bool> flag){
228 ;   *a = 100;
229 ;   atomic_thread_fence(std::memory_order_release);
230 ;   flag.store(true, std::memory_order_relaxed);
231 ; }
233 ; void bar(int *a, std::atomic<bool> flag){
234 ;   while(!flag.load(std::memory_order_relaxed))
235 ;     ;
237 ;   atomic_thread_fence(std::memory_order_acquire);
238 ;   int b = *a;
239 ; }
241 %"struct.std::atomic" = type { %"struct.std::__atomic_base" }
242 %"struct.std::__atomic_base" = type { i8 }
244 define void @foo1(ptr %arg, ptr %arg1) {
245 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn
246 ; CHECK-LABEL: define {{[^@]+}}@foo1
247 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ARG:%.*]], ptr nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ARG1:%.*]]) #[[ATTR6:[0-9]+]] {
248 ; CHECK-NEXT:    store i32 100, ptr [[ARG]], align 4
249 ; CHECK-NEXT:    fence release
250 ; CHECK-NEXT:    store atomic i8 1, ptr [[ARG1]] monotonic, align 1
251 ; CHECK-NEXT:    ret void
253   store i32 100, ptr %arg, align 4
254   fence release
255   store atomic i8 1, ptr %arg1 monotonic, align 1
256   ret void
259 define void @bar(ptr %arg, ptr %arg1) {
260 ; CHECK: Function Attrs: nofree norecurse nounwind
261 ; CHECK-LABEL: define {{[^@]+}}@bar
262 ; CHECK-SAME: (ptr nocapture nofree readnone [[ARG:%.*]], ptr nocapture nofree nonnull readonly dereferenceable(1) [[ARG1:%.*]]) #[[ATTR7:[0-9]+]] {
263 ; CHECK-NEXT:    br label [[BB2:%.*]]
264 ; CHECK:       bb2:
265 ; CHECK-NEXT:    [[I3:%.*]] = load atomic i8, ptr [[ARG1]] monotonic, align 1
266 ; CHECK-NEXT:    [[I4:%.*]] = and i8 [[I3]], 1
267 ; CHECK-NEXT:    [[I5:%.*]] = icmp eq i8 [[I4]], 0
268 ; CHECK-NEXT:    br i1 [[I5]], label [[BB2]], label [[BB6:%.*]]
269 ; CHECK:       bb6:
270 ; CHECK-NEXT:    fence acquire
271 ; CHECK-NEXT:    ret void
273   br label %bb2
275 bb2:
276   %i3 = load atomic i8, ptr %arg1 monotonic, align 1
277   %i4 = and i8 %i3, 1
278   %i5 = icmp eq i8 %i4, 0
279   br i1 %i5, label %bb2, label %bb6
281 bb6:
282   fence acquire
283   ret void
286 ; TEST 13 - Fence syncscope("singlethread") seq_cst
287 define void @foo1_singlethread(ptr %arg, ptr %arg1) {
288 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
289 ; CHECK-LABEL: define {{[^@]+}}@foo1_singlethread
290 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ARG:%.*]], ptr nocapture nofree noundef nonnull writeonly dereferenceable(1) [[ARG1:%.*]]) #[[ATTR8:[0-9]+]] {
291 ; CHECK-NEXT:    store i32 100, ptr [[ARG]], align 4
292 ; CHECK-NEXT:    fence syncscope("singlethread") release
293 ; CHECK-NEXT:    store atomic i8 1, ptr [[ARG1]] monotonic, align 1
294 ; CHECK-NEXT:    ret void
296   store i32 100, ptr %arg, align 4
297   fence syncscope("singlethread") release
298   store atomic i8 1, ptr %arg1 monotonic, align 1
299   ret void
302 define void @bar_singlethread(ptr %arg, ptr %arg1) {
303 ; CHECK: Function Attrs: nofree norecurse nosync nounwind
304 ; CHECK-LABEL: define {{[^@]+}}@bar_singlethread
305 ; CHECK-SAME: (ptr nocapture nofree readnone [[ARG:%.*]], ptr nocapture nofree nonnull readonly dereferenceable(1) [[ARG1:%.*]]) #[[ATTR9:[0-9]+]] {
306 ; CHECK-NEXT:    br label [[BB2:%.*]]
307 ; CHECK:       bb2:
308 ; CHECK-NEXT:    [[I3:%.*]] = load atomic i8, ptr [[ARG1]] monotonic, align 1
309 ; CHECK-NEXT:    [[I4:%.*]] = and i8 [[I3]], 1
310 ; CHECK-NEXT:    [[I5:%.*]] = icmp eq i8 [[I4]], 0
311 ; CHECK-NEXT:    br i1 [[I5]], label [[BB2]], label [[BB6:%.*]]
312 ; CHECK:       bb6:
313 ; CHECK-NEXT:    fence syncscope("singlethread") acquire
314 ; CHECK-NEXT:    ret void
316   br label %bb2
318 bb2:
319   %i3 = load atomic i8, ptr %arg1 monotonic, align 1
320   %i4 = and i8 %i3, 1
321   %i5 = icmp eq i8 %i4, 0
322   br i1 %i5, label %bb2, label %bb6
324 bb6:
325   fence syncscope("singlethread") acquire
326   ret void
329 declare void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)
330 declare void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 %len, i1 %isvolatile)
332 ; TEST 14 - negative, checking volatile intrinsics.
334 ; It is odd to add nocapture but a result of the llvm.memcpy nocapture.
336 define i32 @memcpy_volatile(ptr %ptr1, ptr %ptr2) {
337 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
338 ; CHECK-LABEL: define {{[^@]+}}@memcpy_volatile
339 ; CHECK-SAME: (ptr nocapture nofree writeonly [[PTR1:%.*]], ptr nocapture nofree readonly [[PTR2:%.*]]) #[[ATTR12:[0-9]+]] {
340 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr nocapture nofree writeonly [[PTR1]], ptr nocapture nofree readonly [[PTR2]], i32 noundef 8, i1 noundef true) #[[ATTR21:[0-9]+]]
341 ; CHECK-NEXT:    ret i32 4
343   call void @llvm.memcpy.p0.p0.i32(ptr %ptr1, ptr %ptr2, i32 8, i1 true)
344   ret i32 4
347 ; TEST 15 - positive, non-volatile intrinsic.
349 ; It is odd to add nocapture but a result of the llvm.memset nocapture.
351 define i32 @memset_non_volatile(ptr %ptr1, i8 %val) {
352 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
353 ; CHECK-LABEL: define {{[^@]+}}@memset_non_volatile
354 ; CHECK-SAME: (ptr nocapture nofree writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR13:[0-9]+]] {
355 ; CHECK-NEXT:    call void @llvm.memset.p0.i32(ptr nocapture nofree writeonly [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR22:[0-9]+]]
356 ; CHECK-NEXT:    ret i32 4
358   call void @llvm.memset.p0.i32(ptr %ptr1, i8 %val, i32 8, i1 false)
359   ret i32 4
362 ; TEST 16 - negative, inline assembly.
364 define i32 @inline_asm_test(i32 %x) {
365 ; CHECK-LABEL: define {{[^@]+}}@inline_asm_test
366 ; CHECK-SAME: (i32 [[X:%.*]]) {
367 ; CHECK-NEXT:    [[I:%.*]] = call i32 asm sideeffect "bswap $0", "=r,r"(i32 [[X]])
368 ; CHECK-NEXT:    ret i32 4
370   %i = call i32 asm sideeffect "bswap $0", "=r,r"(i32 %x)
371   ret i32 4
374 declare void @readnone_test() convergent readnone
376 ; TEST 17 - negative. Convergent
377 define void @convergent_readnone() {
378 ; CHECK: Function Attrs: memory(none)
379 ; CHECK-LABEL: define {{[^@]+}}@convergent_readnone
380 ; CHECK-SAME: () #[[ATTR15:[0-9]+]] {
381 ; CHECK-NEXT:    call void @readnone_test()
382 ; CHECK-NEXT:    ret void
384   call void @readnone_test()
385   ret void
388 ; CHECK: Function Attrs: nounwind
389 ; CHECK-NEXT: declare void @llvm.x86.sse2.clflush(ptr)
390 declare void @llvm.x86.sse2.clflush(ptr)
391 @a = common global i32 0, align 4
393 ; TEST 18 - negative. Synchronizing intrinsic
395 define void @i_totally_sync() {
396 ; CHECK: Function Attrs: nounwind
397 ; CHECK-LABEL: define {{[^@]+}}@i_totally_sync
398 ; CHECK-SAME: () #[[ATTR16:[0-9]+]] {
399 ; CHECK-NEXT:    tail call void @llvm.x86.sse2.clflush(ptr noundef nonnull align 4 dereferenceable(4) @a)
400 ; CHECK-NEXT:    ret void
402   tail call void @llvm.x86.sse2.clflush(ptr @a)
403   ret void
406 declare float @llvm.cos.f32(float %val) readnone
408 ; TEST 19 - positive, readnone & non-convergent intrinsic.
410 define i32 @cos_test(float %x) {
411 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
412 ; CHECK-LABEL: define {{[^@]+}}@cos_test
413 ; CHECK-SAME: (float [[X:%.*]]) #[[ATTR18:[0-9]+]] {
414 ; CHECK-NEXT:    ret i32 4
416   %i = call float @llvm.cos.f32(float %x)
417   ret i32 4
420 define float @cos_test2(float %x) {
421 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
422 ; CHECK-LABEL: define {{[^@]+}}@cos_test2
423 ; CHECK-SAME: (float nofpclass(inf) [[X:%.*]]) #[[ATTR18]] {
424 ; CHECK-NEXT:    [[C:%.*]] = call nofpclass(inf) float @llvm.cos.f32(float nofpclass(inf) [[X]]) #[[ATTR23:[0-9]+]]
425 ; CHECK-NEXT:    ret float [[C]]
427   %c = call float @llvm.cos.f32(float %x)
428   ret float %c
431 declare void @unknown()
432 define void @nosync_convergent_callee_test() {
433 ; CHECK: Function Attrs: nosync memory(none)
434 ; CHECK-LABEL: define {{[^@]+}}@nosync_convergent_callee_test
435 ; CHECK-SAME: () #[[ATTR19:[0-9]+]] {
436 ; CHECK-NEXT:    call void @unknown() #[[ATTR24:[0-9]+]]
437 ; CHECK-NEXT:    ret void
439   call void @unknown() nosync convergent readnone
440   ret void
443 ; CHECK: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind optsize ssp willreturn memory(none) uwtable }
444 ; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) uwtable }
445 ; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable }
446 ; CHECK: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable }
447 ; CHECK: attributes #[[ATTR4]] = { noinline nounwind uwtable }
448 ; CHECK: attributes #[[ATTR5]] = { nofree noinline nounwind memory(argmem: readwrite) uwtable }
449 ; CHECK: attributes #[[ATTR6]] = { mustprogress nofree norecurse nounwind willreturn }
450 ; CHECK: attributes #[[ATTR7]] = { nofree norecurse nounwind }
451 ; CHECK: attributes #[[ATTR8]] = { mustprogress nofree norecurse nosync nounwind willreturn }
452 ; CHECK: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind }
453 ; CHECK: attributes #[[ATTR10:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
454 ; CHECK: attributes #[[ATTR11:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
455 ; CHECK: attributes #[[ATTR12]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
456 ; CHECK: attributes #[[ATTR13]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
457 ; CHECK: attributes #[[ATTR14:[0-9]+]] = { convergent memory(none) }
458 ; CHECK: attributes #[[ATTR15]] = { memory(none) }
459 ; CHECK: attributes #[[ATTR16]] = { nounwind }
460 ; CHECK: attributes #[[ATTR17:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
461 ; CHECK: attributes #[[ATTR18]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
462 ; CHECK: attributes #[[ATTR19]] = { nosync memory(none) }
463 ; CHECK: attributes #[[ATTR20]] = { nofree nounwind }
464 ; CHECK: attributes #[[ATTR21]] = { nofree willreturn }
465 ; CHECK: attributes #[[ATTR22]] = { nofree willreturn memory(write) }
466 ; CHECK: attributes #[[ATTR23]] = { nofree nosync willreturn }
467 ; CHECK: attributes #[[ATTR24]] = { convergent nosync memory(none) }
469 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
470 ; CGSCC: {{.*}}
471 ; TUNIT: {{.*}}