1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7
8; Test cases designed for the nosync function attribute.
9; FIXME's are used to indicate problems and missing attributes.
10
11; struct RT {
12;   char A;
13;   int B[10][20];
14;   char C;
15; };
16; struct ST {
17;   int X;
18;   double Y;
19;   struct RT Z;
20; };
21;
22; int *foo(struct ST *s) {
23;   return &s[1].Z.B[5][13];
24; }
25
26; TEST 1
27; non-convergent and readnone implies nosync
28%struct.RT = type { i8, [10 x [20 x i32]], i8 }
29%struct.ST = type { i32, double, %struct.RT }
30
31;.
32; CHECK: @[[A:[a-zA-Z0-9_$"\\.-]+]] = common global i32 0, align 4
33;.
34define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
35; CHECK: Function Attrs: nofree norecurse nosync nounwind optsize readnone ssp willreturn uwtable
36; CHECK-LABEL: define {{[^@]+}}@foo
37; CHECK-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]]) #[[ATTR0:[0-9]+]] {
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13
40; CHECK-NEXT:    ret i32* [[ARRAYIDX]]
41;
42entry:
43  %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
44  ret i32* %arrayidx
45}
46
47; TEST 2
48; atomic load with monotonic ordering
49; int load_monotonic(_Atomic int *num) {
50;   int n = atomic_load_explicit(num, memory_order_relaxed);
51;   return n;
52; }
53
54define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable {
55; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn uwtable
56; CHECK-LABEL: define {{[^@]+}}@load_monotonic
57; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] {
58; CHECK-NEXT:    [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] monotonic, align 4
59; CHECK-NEXT:    ret i32 [[TMP2]]
60;
61  %2 = load atomic i32, i32* %0 monotonic, align 4
62  ret i32 %2
63}
64
65
66; TEST 3
67; atomic store with monotonic ordering.
68; void store_monotonic(_Atomic int *num) {
69;   atomic_load_explicit(num, memory_order_relaxed);
70; }
71
72define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable {
73; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn uwtable
74; CHECK-LABEL: define {{[^@]+}}@store_monotonic
75; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR1]] {
76; CHECK-NEXT:    store atomic i32 10, i32* [[TMP0]] monotonic, align 4
77; CHECK-NEXT:    ret void
78;
79  store atomic i32 10, i32* %0 monotonic, align 4
80  ret void
81}
82
83; TEST 4 - negative, should not deduce nosync
84; atomic load with acquire ordering.
85; int load_acquire(_Atomic int *num) {
86;   int n = atomic_load_explicit(num, memory_order_acquire);
87;   return n;
88; }
89
90define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable {
91; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable
92; CHECK-LABEL: define {{[^@]+}}@load_acquire
93; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] {
94; CHECK-NEXT:    [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] acquire, align 4
95; CHECK-NEXT:    ret i32 [[TMP2]]
96;
97  %2 = load atomic i32, i32* %0 acquire, align 4
98  ret i32 %2
99}
100
101; TEST 5 - negative, should not deduce nosync
102; atomic load with release ordering
103; void load_release(_Atomic int *num) {
104;   atomic_store_explicit(num, 10, memory_order_release);
105; }
106
107define void @load_release(i32* nocapture %0) norecurse nounwind uwtable {
108; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable
109; CHECK-LABEL: define {{[^@]+}}@load_release
110; CHECK-SAME: (i32* nocapture nofree noundef writeonly align 4 [[TMP0:%.*]]) #[[ATTR2]] {
111; CHECK-NEXT:    store atomic volatile i32 10, i32* [[TMP0]] release, align 4
112; CHECK-NEXT:    ret void
113;
114  store atomic volatile i32 10, i32* %0 release, align 4
115  ret void
116}
117
118; TEST 6 - negative volatile, relaxed atomic
119
120define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable {
121; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable
122; CHECK-LABEL: define {{[^@]+}}@load_volatile_release
123; CHECK-SAME: (i32* nocapture nofree noundef writeonly align 4 [[TMP0:%.*]]) #[[ATTR2]] {
124; CHECK-NEXT:    store atomic volatile i32 10, i32* [[TMP0]] release, align 4
125; CHECK-NEXT:    ret void
126;
127  store atomic volatile i32 10, i32* %0 release, align 4
128  ret void
129}
130
131; TEST 7 - negative, should not deduce nosync
132; volatile store.
133; void volatile_store(volatile int *num) {
134;   *num = 14;
135; }
136
137define void @volatile_store(i32* %0) norecurse nounwind uwtable {
138; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable
139; CHECK-LABEL: define {{[^@]+}}@volatile_store
140; CHECK-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR2]] {
141; CHECK-NEXT:    store volatile i32 14, i32* [[TMP0]], align 4
142; CHECK-NEXT:    ret void
143;
144  store volatile i32 14, i32* %0, align 4
145  ret void
146}
147
148; TEST 8 - negative, should not deduce nosync
149; volatile load.
150; int volatile_load(volatile int *num) {
151;   int n = *num;
152;   return n;
153; }
154
155define i32 @volatile_load(i32* %0) norecurse nounwind uwtable {
156; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable
157; CHECK-LABEL: define {{[^@]+}}@volatile_load
158; CHECK-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR2]] {
159; CHECK-NEXT:    [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4
160; CHECK-NEXT:    ret i32 [[TMP2]]
161;
162  %2 = load volatile i32, i32* %0, align 4
163  ret i32 %2
164}
165
166; TEST 9
167
168; CHECK: Function Attrs: noinline nosync nounwind uwtable
169; CHECK-NEXT: declare void @nosync_function()
170declare void @nosync_function() noinline nounwind uwtable nosync
171
172define void @call_nosync_function() nounwind uwtable noinline {
173; CHECK: Function Attrs: noinline nosync nounwind uwtable
174; CHECK-LABEL: define {{[^@]+}}@call_nosync_function
175; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
176; CHECK-NEXT:    tail call void @nosync_function() #[[ATTR4:[0-9]+]]
177; CHECK-NEXT:    ret void
178;
179  tail call void @nosync_function() noinline nounwind uwtable
180  ret void
181}
182
183; TEST 10 - negative, should not deduce nosync
184
185; CHECK: Function Attrs: noinline nounwind uwtable
186; CHECK-NEXT: declare void @might_sync()
187declare void @might_sync() noinline nounwind uwtable
188
189define void @call_might_sync() nounwind uwtable noinline {
190; CHECK: Function Attrs: noinline nounwind uwtable
191; CHECK-LABEL: define {{[^@]+}}@call_might_sync
192; CHECK-SAME: () #[[ATTR4]] {
193; CHECK-NEXT:    tail call void @might_sync() #[[ATTR4]]
194; CHECK-NEXT:    ret void
195;
196  tail call void @might_sync() noinline nounwind uwtable
197  ret void
198}
199
200; TEST 11 - positive, should deduce nosync
201; volatile operation in same scc but dead. Call volatile_load defined in TEST 8.
202
203define i32 @scc1(i32* %0) noinline nounwind uwtable {
204; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nounwind uwtable
205; IS__TUNIT____-LABEL: define {{[^@]+}}@scc1
206; IS__TUNIT____-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] {
207; IS__TUNIT____-NEXT:    tail call void @scc2(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]]
208; IS__TUNIT____-NEXT:    [[VAL:%.*]] = tail call i32 @volatile_load(i32* nofree align 4 [[TMP0]]) #[[ATTR19]]
209; IS__TUNIT____-NEXT:    ret i32 [[VAL]]
210;
211; IS__CGSCC_OPM: Function Attrs: argmemonly nofree noinline nounwind uwtable
212; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@scc1
213; IS__CGSCC_OPM-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] {
214; IS__CGSCC_OPM-NEXT:    tail call void @scc2(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]]
215; IS__CGSCC_OPM-NEXT:    [[VAL:%.*]] = tail call i32 @volatile_load(i32* nofree noundef align 4 [[TMP0]]) #[[ATTR20:[0-9]+]]
216; IS__CGSCC_OPM-NEXT:    ret i32 [[VAL]]
217;
218; IS__CGSCC_NPM: Function Attrs: argmemonly nofree noinline nounwind uwtable
219; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc1
220; IS__CGSCC_NPM-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] {
221; IS__CGSCC_NPM-NEXT:    tail call void @scc2(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]]
222; IS__CGSCC_NPM-NEXT:    [[VAL:%.*]] = tail call i32 @volatile_load(i32* nofree noundef align 4 [[TMP0]]) #[[ATTR14:[0-9]+]]
223; IS__CGSCC_NPM-NEXT:    ret i32 [[VAL]]
224;
225  tail call void @scc2(i32* %0);
226  %val = tail call i32 @volatile_load(i32* %0);
227  ret i32 %val;
228}
229
230define void @scc2(i32* %0) noinline nounwind uwtable {
231; CHECK: Function Attrs: argmemonly nofree noinline nounwind uwtable
232; CHECK-LABEL: define {{[^@]+}}@scc2
233; CHECK-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] {
234; CHECK-NEXT:    [[TMP2:%.*]] = tail call i32 @scc1(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]]
235; CHECK-NEXT:    ret void
236;
237  tail call i32 @scc1(i32* %0);
238  ret void;
239}
240
241; TEST 12 - fences, negative
242;
243; void foo1(int *a, std::atomic<bool> flag){
244;   *a = 100;
245;   atomic_thread_fence(std::memory_order_release);
246;   flag.store(true, std::memory_order_relaxed);
247; }
248;
249; void bar(int *a, std::atomic<bool> flag){
250;   while(!flag.load(std::memory_order_relaxed))
251;     ;
252;
253;   atomic_thread_fence(std::memory_order_acquire);
254;   int b = *a;
255; }
256
257%"struct.std::atomic" = type { %"struct.std::__atomic_base" }
258%"struct.std::__atomic_base" = type { i8 }
259
260define void @foo1(i32* %0, %"struct.std::atomic"* %1) {
261; CHECK: Function Attrs: nofree norecurse nounwind willreturn
262; CHECK-LABEL: define {{[^@]+}}@foo1
263; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR6:[0-9]+]] {
264; CHECK-NEXT:    store i32 100, i32* [[TMP0]], align 4
265; CHECK-NEXT:    fence release
266; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
267; CHECK-NEXT:    store atomic i8 1, i8* [[TMP3]] monotonic, align 1
268; CHECK-NEXT:    ret void
269;
270  store i32 100, i32* %0, align 4
271  fence release
272  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
273  store atomic i8 1, i8* %3 monotonic, align 1
274  ret void
275}
276
277define void @bar(i32* %0, %"struct.std::atomic"* %1) {
278; CHECK: Function Attrs: nofree norecurse nounwind
279; CHECK-LABEL: define {{[^@]+}}@bar
280; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR7:[0-9]+]] {
281; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
282; CHECK-NEXT:    br label [[TMP4:%.*]]
283; CHECK:       4:
284; CHECK-NEXT:    [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1
285; CHECK-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 1
286; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0
287; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]]
288; CHECK:       8:
289; CHECK-NEXT:    fence acquire
290; CHECK-NEXT:    ret void
291;
292  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
293  br label %4
294
2954:                                                ; preds = %4, %2
296  %5 = load atomic i8, i8* %3  monotonic, align 1
297  %6 = and i8 %5, 1
298  %7 = icmp eq i8 %6, 0
299  br i1 %7, label %4, label %8
300
3018:                                                ; preds = %4
302  fence acquire
303  ret void
304}
305
306; TEST 13 - Fence syncscope("singlethread") seq_cst
307define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) {
308; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn
309; CHECK-LABEL: define {{[^@]+}}@foo1_singlethread
310; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR8:[0-9]+]] {
311; CHECK-NEXT:    store i32 100, i32* [[TMP0]], align 4
312; CHECK-NEXT:    fence syncscope("singlethread") release
313; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
314; CHECK-NEXT:    store atomic i8 1, i8* [[TMP3]] monotonic, align 1
315; CHECK-NEXT:    ret void
316;
317  store i32 100, i32* %0, align 4
318  fence syncscope("singlethread") release
319  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
320  store atomic i8 1, i8* %3 monotonic, align 1
321  ret void
322}
323
324define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) {
325; CHECK: Function Attrs: nofree norecurse nosync nounwind
326; CHECK-LABEL: define {{[^@]+}}@bar_singlethread
327; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR9:[0-9]+]] {
328; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0
329; CHECK-NEXT:    br label [[TMP4:%.*]]
330; CHECK:       4:
331; CHECK-NEXT:    [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1
332; CHECK-NEXT:    [[TMP6:%.*]] = and i8 [[TMP5]], 1
333; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0
334; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]]
335; CHECK:       8:
336; CHECK-NEXT:    fence syncscope("singlethread") acquire
337; CHECK-NEXT:    ret void
338;
339  %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
340  br label %4
341
3424:                                                ; preds = %4, %2
343  %5 = load atomic i8, i8* %3  monotonic, align 1
344  %6 = and i8 %5, 1
345  %7 = icmp eq i8 %6, 0
346  br i1 %7, label %4, label %8
347
3488:                                                ; preds = %4
349  fence syncscope("singlethread") acquire
350  ret void
351}
352
353declare void @llvm.memcpy(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
354declare void @llvm.memset(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
355
356; TEST 14 - negative, checking volatile intrinsics.
357
358; It is odd to add nocapture but a result of the llvm.memcpy nocapture.
359;
360define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) {
361; NOT_CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nounwind willreturn
362; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@memcpy_volatile
363; NOT_CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8* nocapture nofree readonly [[PTR2:%.*]]) #[[ATTR10:[0-9]+]] {
364; NOT_CGSCC_OPM-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[PTR1]], i8* noalias nocapture nofree readonly [[PTR2]], i32 noundef 8, i1 noundef true) #[[ATTR20:[0-9]+]]
365; NOT_CGSCC_OPM-NEXT:    ret i32 4
366;
367; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nounwind willreturn
368; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@memcpy_volatile
369; IS__CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8* nocapture nofree readonly [[PTR2:%.*]]) #[[ATTR10:[0-9]+]] {
370; IS__CGSCC_OPM-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[PTR1]], i8* noalias nocapture nofree readonly [[PTR2]], i32 noundef 8, i1 noundef true) #[[ATTR21:[0-9]+]]
371; IS__CGSCC_OPM-NEXT:    ret i32 4
372;
373  call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1)
374  ret i32 4
375}
376
377; TEST 15 - positive, non-volatile intrinsic.
378
379; It is odd to add nocapture but a result of the llvm.memset nocapture.
380;
381define i32 @memset_non_volatile(i8* %ptr1, i8 %val) {
382; NOT_CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
383; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@memset_non_volatile
384; NOT_CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR11:[0-9]+]] {
385; NOT_CGSCC_OPM-NEXT:    call void @llvm.memset.p0i8.i32(i8* nocapture nofree writeonly [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR21:[0-9]+]]
386; NOT_CGSCC_OPM-NEXT:    ret i32 4
387;
388; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
389; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@memset_non_volatile
390; IS__CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR11:[0-9]+]] {
391; IS__CGSCC_OPM-NEXT:    call void @llvm.memset.p0i8.i32(i8* nocapture nofree writeonly [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR22:[0-9]+]]
392; IS__CGSCC_OPM-NEXT:    ret i32 4
393;
394  call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0)
395  ret i32 4
396}
397
398; TEST 16 - negative, inline assembly.
399
400define i32 @inline_asm_test(i32 %x) {
401; CHECK-LABEL: define {{[^@]+}}@inline_asm_test
402; CHECK-SAME: (i32 [[X:%.*]]) {
403; CHECK-NEXT:    [[TMP1:%.*]] = call i32 asm "bswap $0", "=r,r"(i32 [[X]])
404; CHECK-NEXT:    ret i32 4
405;
406  call i32 asm "bswap $0", "=r,r"(i32 %x)
407  ret i32 4
408}
409
410declare void @readnone_test() convergent readnone
411
412; TEST 17 - negative. Convergent
413define void @convergent_readnone(){
414; CHECK: Function Attrs: readnone
415; CHECK-LABEL: define {{[^@]+}}@convergent_readnone
416; CHECK-SAME: () #[[ATTR13:[0-9]+]] {
417; CHECK-NEXT:    call void @readnone_test()
418; CHECK-NEXT:    ret void
419;
420  call void @readnone_test()
421  ret void
422}
423
424; CHECK: Function Attrs: nounwind
425; CHECK-NEXT: declare void @llvm.x86.sse2.clflush(i8*)
426declare void @llvm.x86.sse2.clflush(i8*)
427@a = common global i32 0, align 4
428
429; TEST 18 - negative. Synchronizing intrinsic
430
431define void @i_totally_sync() {
432; CHECK: Function Attrs: nounwind
433; CHECK-LABEL: define {{[^@]+}}@i_totally_sync
434; CHECK-SAME: () #[[ATTR14:[0-9]+]] {
435; CHECK-NEXT:    tail call void @llvm.x86.sse2.clflush(i8* noundef nonnull align 4 dereferenceable(4) bitcast (i32* @a to i8*))
436; CHECK-NEXT:    ret void
437;
438  tail call void @llvm.x86.sse2.clflush(i8* bitcast (i32* @a to i8*))
439  ret void
440}
441
442declare float @llvm.cos(float %val) readnone
443
444; TEST 19 - positive, readnone & non-convergent intrinsic.
445
446define i32 @cos_test(float %x) {
447; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
448; CHECK-LABEL: define {{[^@]+}}@cos_test
449; CHECK-SAME: (float [[X:%.*]]) #[[ATTR15:[0-9]+]] {
450; CHECK-NEXT:    ret i32 4
451;
452  call float @llvm.cos(float %x)
453  ret i32 4
454}
455
456define float @cos_test2(float %x) {
457; NOT_CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
458; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@cos_test2
459; NOT_CGSCC_OPM-SAME: (float [[X:%.*]]) #[[ATTR15]] {
460; NOT_CGSCC_OPM-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR22:[0-9]+]]
461; NOT_CGSCC_OPM-NEXT:    ret float [[C]]
462;
463; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
464; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@cos_test2
465; IS__CGSCC_OPM-SAME: (float [[X:%.*]]) #[[ATTR15]] {
466; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR23:[0-9]+]]
467; IS__CGSCC_OPM-NEXT:    ret float [[C]]
468;
469  %c = call float @llvm.cos(float %x)
470  ret float %c
471}
472;.
473; NOT_CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp willreturn uwtable }
474; NOT_CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn uwtable }
475; NOT_CGSCC_OPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nounwind willreturn uwtable }
476; NOT_CGSCC_OPM: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable }
477; NOT_CGSCC_OPM: attributes #[[ATTR4]] = { noinline nounwind uwtable }
478; NOT_CGSCC_OPM: attributes #[[ATTR5]] = { argmemonly nofree noinline nounwind uwtable }
479; NOT_CGSCC_OPM: attributes #[[ATTR6]] = { nofree norecurse nounwind willreturn }
480; NOT_CGSCC_OPM: attributes #[[ATTR7]] = { nofree norecurse nounwind }
481; NOT_CGSCC_OPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn }
482; NOT_CGSCC_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind }
483; NOT_CGSCC_OPM: attributes #[[ATTR10]] = { argmemonly nofree norecurse nounwind willreturn }
484; NOT_CGSCC_OPM: attributes #[[ATTR11]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
485; NOT_CGSCC_OPM: attributes #[[ATTR12:[0-9]+]] = { convergent readnone }
486; NOT_CGSCC_OPM: attributes #[[ATTR13]] = { readnone }
487; NOT_CGSCC_OPM: attributes #[[ATTR14]] = { nounwind }
488; NOT_CGSCC_OPM: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind readnone willreturn }
489; NOT_CGSCC_OPM: attributes #[[ATTR16:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn }
490; NOT_CGSCC_OPM: attributes #[[ATTR17:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn writeonly }
491; NOT_CGSCC_OPM: attributes #[[ATTR18:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn }
492; NOT_CGSCC_OPM: attributes #[[ATTR19]] = { nofree nounwind }
493; NOT_CGSCC_OPM: attributes #[[ATTR20]] = { willreturn }
494; NOT_CGSCC_OPM: attributes #[[ATTR21]] = { willreturn writeonly }
495; NOT_CGSCC_OPM: attributes #[[ATTR22]] = { readnone willreturn }
496;.
497; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp willreturn uwtable }
498; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn uwtable }
499; IS__CGSCC_OPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nounwind willreturn uwtable }
500; IS__CGSCC_OPM: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable }
501; IS__CGSCC_OPM: attributes #[[ATTR4]] = { noinline nounwind uwtable }
502; IS__CGSCC_OPM: attributes #[[ATTR5]] = { argmemonly nofree noinline nounwind uwtable }
503; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nofree norecurse nounwind willreturn }
504; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nofree norecurse nounwind }
505; IS__CGSCC_OPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn }
506; IS__CGSCC_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind }
507; IS__CGSCC_OPM: attributes #[[ATTR10]] = { argmemonly nofree norecurse nounwind willreturn }
508; IS__CGSCC_OPM: attributes #[[ATTR11]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
509; IS__CGSCC_OPM: attributes #[[ATTR12:[0-9]+]] = { convergent readnone }
510; IS__CGSCC_OPM: attributes #[[ATTR13]] = { readnone }
511; IS__CGSCC_OPM: attributes #[[ATTR14]] = { nounwind }
512; IS__CGSCC_OPM: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind readnone willreturn }
513; IS__CGSCC_OPM: attributes #[[ATTR16:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn }
514; IS__CGSCC_OPM: attributes #[[ATTR17:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn writeonly }
515; IS__CGSCC_OPM: attributes #[[ATTR18:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn }
516; IS__CGSCC_OPM: attributes #[[ATTR19]] = { nofree nounwind }
517; IS__CGSCC_OPM: attributes #[[ATTR20]] = { nounwind willreturn }
518; IS__CGSCC_OPM: attributes #[[ATTR21]] = { willreturn }
519; IS__CGSCC_OPM: attributes #[[ATTR22]] = { willreturn writeonly }
520; IS__CGSCC_OPM: attributes #[[ATTR23]] = { readnone willreturn }
521;.
522