[lib/Object] - Remove objdump-file-header.test
[llvm-complete.git] / test / Transforms / FunctionAttrs / nosync.ll
blobc86facb819215c8306960ea236a49292d0d8ed6a
1 ; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
2 ; RUN: opt -attributor -attributor-disable=false -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 ; Test cases designed for the nosync function attribute.
6 ; FIXME's are used to indicate problems and missing attributes.
8 ; struct RT {
9 ;   char A;
10 ;   int B[10][20];
11 ;   char C;
12 ; };
13 ; struct ST {
14 ;   int X;
15 ;   double Y;
16 ;   struct RT Z;
17 ; };
19 ; int *foo(struct ST *s) {
20 ;   return &s[1].Z.B[5][13];
21 ; }
23 ; TEST 1
24 ; non-convergent and readnone implies nosync
25 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
26 %struct.ST = type { i32, double, %struct.RT }
28 ; FNATTR: Function Attrs: norecurse nounwind optsize readnone ssp uwtable
29 ; FNATTR-NEXT: define nonnull i32* @foo(%struct.ST* readnone %s)
30 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable
31 ; ATTRIBUTOR-NEXT: define nonnull i32* @foo(%struct.ST* %s)
32 define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
33 entry:
34   %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
35   ret i32* %arrayidx
38 ; TEST 2
39 ; atomic load with monotonic ordering
40 ; int load_monotonic(_Atomic int *num) {
41 ;   int n = atomic_load_explicit(num, memory_order_relaxed);
42 ;   return n;
43 ; }
45 ; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
46 ; FNATTR-NEXT: define i32 @load_monotonic(i32* nocapture readonly %0)
47 ; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable
48 ; ATTRIBUTOR-NEXT: define i32 @load_monotonic(i32* nocapture readonly %0)
49 define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable {
50   %2 = load atomic i32, i32* %0 monotonic, align 4
51   ret i32 %2
55 ; TEST 3
56 ; atomic store with monotonic ordering.
57 ; void store_monotonic(_Atomic int *num) {
58 ;   atomic_load_explicit(num, memory_order_relaxed);
59 ; }
61 ; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
62 ; FNATTR-NEXT: define void @store_monotonic(i32* nocapture %0)
63 ; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable
64 ; ATTRIBUTOR-NEXT: define void @store_monotonic(i32* nocapture %0)
65 define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable {
66   store atomic i32 10, i32* %0 monotonic, align 4
67   ret void
70 ; TEST 4 - negative, should not deduce nosync
71 ; atomic load with acquire ordering.
72 ; int load_acquire(_Atomic int *num) {
73 ;   int n = atomic_load_explicit(num, memory_order_acquire);
74 ;   return n;
75 ; }
77 ; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
78 ; FNATTR-NEXT: define i32 @load_acquire(i32* nocapture readonly %0)
79 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
80 ; ATTRIBUTOR-NOT: nosync
81 ; ATTRIBUTOR-NEXT: define i32 @load_acquire(i32* nocapture readonly %0)
82 define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable {
83   %2 = load atomic i32, i32* %0 acquire, align 4
84   ret i32 %2
87 ; TEST 5 - negative, should not deduce nosync
88 ; atomic load with release ordering
89 ; void load_release(_Atomic int *num) {
90 ;   atomic_store_explicit(num, 10, memory_order_release);
91 ; }
93 ; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
94 ; FNATTR-NEXT: define void @load_release(i32* nocapture %0)
95 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
96 ; ATTRIBUTOR-NOT: nosync
97 ; ATTRIBUTOR-NEXT: define void @load_release(i32* nocapture %0)
98 define void @load_release(i32* nocapture %0) norecurse nounwind uwtable {
99   store atomic volatile i32 10, i32* %0 release, align 4
100   ret void
103 ; TEST 6 - negative volatile, relaxed atomic
105 ; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
106 ; FNATTR-NEXT: define void @load_volatile_release(i32* nocapture %0)
107 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
108 ; ATTRIBUTOR-NOT: nosync
109 ; ATTRIBUTOR-NEXT: define void @load_volatile_release(i32* nocapture %0)
110 define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable {
111   store atomic volatile i32 10, i32* %0 release, align 4
112   ret void
115 ; TEST 7 - negative, should not deduce nosync
116 ; volatile store.
117 ; void volatile_store(volatile int *num) {
118 ;   *num = 14;
119 ; }
121 ; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
122 ; FNATTR-NEXT: define void @volatile_store(i32* %0)
123 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
124 ; ATTRIBUTOR-NOT: nosync
125 ; ATTRIBUTOR-NEXT: define void @volatile_store(i32* %0)
126 define void @volatile_store(i32* %0) norecurse nounwind uwtable {
127   store volatile i32 14, i32* %0, align 4
128   ret void
131 ; TEST 8 - negative, should not deduce nosync
132 ; volatile load.
133 ; int volatile_load(volatile int *num) {
134 ;   int n = *num;
135 ;   return n;
136 ; }
138 ; FNATTR: Function Attrs: nofree norecurse nounwind uwtable
139 ; FNATTR-NEXT: define i32 @volatile_load(i32* %0)
140 ; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable
141 ; ATTRIBUTOR-NOT: nosync
142 ; ATTRIBUTOR-NEXT: define i32 @volatile_load(i32* %0)
143 define i32 @volatile_load(i32* %0) norecurse nounwind uwtable {
144   %2 = load volatile i32, i32* %0, align 4
145   ret i32 %2
148 ; TEST 9
150 ; FNATTR: Function Attrs: noinline nosync nounwind uwtable
151 ; FNATTR-NEXT: declare void @nosync_function()
152 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
153 ; ATTRIBUTOR-NEXT: declare void @nosync_function()
154 declare void @nosync_function() noinline nounwind uwtable nosync
156 ; FNATTR: Function Attrs: noinline nounwind uwtable
157 ; FNATTR-NEXT: define void @call_nosync_function()
158 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
159 ; ATTRIBUTOR-next: define void @call_nosync_function()
160 define void @call_nosync_function() nounwind uwtable noinline {
161   tail call void @nosync_function() noinline nounwind uwtable
162   ret void
165 ; TEST 10 - negative, should not deduce nosync
167 ; FNATTR: Function Attrs: noinline nounwind uwtable
168 ; FNATTR-NEXT: declare void @might_sync()
169 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
170 ; ATTRIBUTOR-NEXT: declare void @might_sync()
171 declare void @might_sync() noinline nounwind uwtable
173 ; FNATTR: Function Attrs: noinline nounwind uwtable
174 ; FNATTR-NEXT: define void @call_might_sync()
175 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
176 ; ATTRIBUTOR-NOT: nosync
177 ; ATTRIBUTOR-NEXT: define void @call_might_sync()
178 define void @call_might_sync() nounwind uwtable noinline {
179   tail call void @might_sync() noinline nounwind uwtable
180   ret void
183 ; TEST 11 - positive, should deduce nosync
184 ; volatile operation in same scc but dead. Call volatile_load defined in TEST 8.
186 ; FNATTR: Function Attrs: nofree noinline nounwind uwtable
187 ; FNATTR-NEXT: define i32 @scc1(i32* %0)
188 ; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind uwtable
189 ; ATTRIBUTOR-NEXT: define i32 @scc1(i32* %0)
190 define i32 @scc1(i32* %0) noinline nounwind uwtable {
191   tail call void @scc2(i32* %0);
192   %val = tail call i32 @volatile_load(i32* %0);
193   ret i32 %val;
196 ; FNATTR: Function Attrs: nofree noinline nounwind uwtable
197 ; FNATTR-NEXT: define void @scc2(i32* %0)
198 ; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind uwtable
199 ; ATTRIBUTOR-NEXT: define void @scc2(i32* %0)
200 define void @scc2(i32* %0) noinline nounwind uwtable {
201   tail call i32 @scc1(i32* %0);
202   ret void;
205 ; TEST 12 - fences, negative
207 ; void foo1(int *a, std::atomic<bool> flag){
208 ;   *a = 100;
209 ;   atomic_thread_fence(std::memory_order_release);
210 ;   flag.store(true, std::memory_order_relaxed);
211 ; }
213 ; void bar(int *a, std::atomic<bool> flag){
214 ;   while(!flag.load(std::memory_order_relaxed))
215 ;     ;
217 ;   atomic_thread_fence(std::memory_order_acquire);
218 ;   int b = *a;
219 ; }
221 %"struct.std::atomic" = type { %"struct.std::__atomic_base" }
222 %"struct.std::__atomic_base" = type { i8 }
224 ; FNATTR: Function Attrs: nofree norecurse nounwind
225 ; FNATTR-NEXT: define void @foo1(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
226 ; ATTRIBUTOR-NOT: nosync
227 ; ATTRIBUTOR: define void @foo1(i32* %0, %"struct.std::atomic"* %1)
228 define void @foo1(i32* %0, %"struct.std::atomic"* %1) {
229   store i32 100, i32* %0, align 4
230   fence release
231   %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
232   store atomic i8 1, i8* %3 monotonic, align 1
233   ret void
236 ; FNATTR: Function Attrs: nofree norecurse nounwind
237 ; FNATTR-NEXT: define void @bar(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1)
238 ; ATTRIBUTOR-NOT: nosync
239 ; ATTRIBUTOR: define void @bar(i32* %0, %"struct.std::atomic"* %1)
240 define void @bar(i32* %0, %"struct.std::atomic"* %1) {
241   %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
242   br label %4
244 4:                                                ; preds = %4, %2
245   %5 = load atomic i8, i8* %3  monotonic, align 1
246   %6 = and i8 %5, 1
247   %7 = icmp eq i8 %6, 0
248   br i1 %7, label %4, label %8
250 8:                                                ; preds = %4
251   fence acquire
252   ret void
255 ; TEST 13 - Fence syncscope("singlethread") seq_cst
256 ; FNATTR: Function Attrs: nofree norecurse nounwind
257 ; FNATTR-NEXT: define void @foo1_singlethread(i32* nocapture %0, %"struct.std::atomic"* nocapture %1)
258 ; ATTRIBUTOR: Function Attrs: nofree nosync
259 ; ATTRIBUTOR: define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1)
260 define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) {
261   store i32 100, i32* %0, align 4
262   fence syncscope("singlethread") release
263   %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
264   store atomic i8 1, i8* %3 monotonic, align 1
265   ret void
268 ; FNATTR: Function Attrs: nofree norecurse nounwind
269 ; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1)
270 ; ATTRIBUTOR: Function Attrs: nofree nosync
271 ; ATTRIBUTOR: define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1)
272 define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) {
273   %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0
274   br label %4
276 4:                                                ; preds = %4, %2
277   %5 = load atomic i8, i8* %3  monotonic, align 1
278   %6 = and i8 %5, 1
279   %7 = icmp eq i8 %6, 0
280   br i1 %7, label %4, label %8
282 8:                                                ; preds = %4
283   fence syncscope("singlethread") acquire
284   ret void
287 declare void @llvm.memcpy(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
288 declare void @llvm.memset(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
290 ; TEST 14 - negative, checking volatile intrinsics.
292 ; ATTRIBUTOR: Function Attrs: nounwind
293 ; ATTRIBUTOR-NOT: nosync
294 ; ATTRIBUTOR-NEXT: define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2)
295 define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) {
296   call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1)
297   ret i32 4
300 ; TEST 15 - positive, non-volatile intrinsic.
302 ; ATTRIBUTOR: Function Attrs: nosync
303 ; ATTRIBUTOR-NEXT: define i32 @memset_non_volatile(i8* %ptr1, i8 %val)
304 define i32 @memset_non_volatile(i8* %ptr1, i8 %val) {
305   call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0)
306   ret i32 4
309 ; TEST 16 - negative, inline assembly.
311 ; ATTRIBUTOR: define i32 @inline_asm_test(i32 %x)
312 define i32 @inline_asm_test(i32 %x) {
313   call i32 asm "bswap $0", "=r,r"(i32 %x)
314   ret i32 4
317 declare void @readnone_test() convergent readnone
319 ; ATTRIBUTOR: define void @convergent_readnone()
320 ; TEST 17 - negative. Convergent
321 define void @convergent_readnone(){
322     call void @readnone_test()
323     ret void
326 ; ATTRIBUTOR: Function Attrs: nounwind
327 ; ATTRIBUTOR-NEXT: declare void @llvm.x86.sse2.clflush(i8*)
328 declare void @llvm.x86.sse2.clflush(i8*)
329 @a = common global i32 0, align 4
331 ; TEST 18 - negative. Synchronizing intrinsic
333 ; ATTRIBUTOR: Function Attrs: nounwind
334 ; ATTRIBUTOR-NOT: nosync
335 ; ATTRIBUTOR-NEXT: define void @i_totally_sync()
336 define void @i_totally_sync() {
337   tail call void @llvm.x86.sse2.clflush(i8* bitcast (i32* @a to i8*))
338   ret void
341 declare float @llvm.cos(float %val) readnone
343 ; TEST 19 - positive, readnone & non-convergent intrinsic.
345 ; ATTRIBUTOR: Function Attrs: nosync nounwind
346 ; ATTRIBUTOR-NEXT: define i32 @cos_test(float %x)
347 define i32 @cos_test(float %x) {
348   call float @llvm.cos(float %x)
349   ret i32 4