Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / Attributor / value-simplify-reachability.ll
blob2dc2ec203692ab453995d44d814e663b30199bc6
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
5 @GInt1 = internal global i32 undef, align 4
6 @GInt2 = internal global i32 zeroinitializer, align 4
7 @GInt3 = internal global i32 undef, align 4
8 @GInt4 = internal global i32 zeroinitializer, align 4
9 @GInt5 = internal global i32 undef, align 4
11 declare void @llvm.assume(i1)
12 declare void @useI32(i32) nosync nocallback
13 declare void @free(ptr) allockind("free") "alloc-family"="malloc"
14 declare noalias ptr @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0, 1) "alloc-family"="malloc"
17 ; CHECK: @GInt1 = internal global i32 undef, align 4
18 ; CHECK: @GInt2 = internal global i32 0, align 4
19 ; CHECK: @GInt3 = internal global i32 undef, align 4
20 ; CHECK: @GInt4 = internal global i32 0, align 4
21 ; CHECK: @GInt5 = internal global i32 undef, align 4
22 ; CHECK: @B = global i32 0
24 define internal void @write1ToGInt1() {
25 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
26 ; CHECK-LABEL: define {{[^@]+}}@write1ToGInt1
27 ; CHECK-SAME: () #[[ATTR4:[0-9]+]] {
28 ; CHECK-NEXT:    store i32 1, ptr @GInt1, align 4
29 ; CHECK-NEXT:    ret void
31   store i32 1, ptr @GInt1
32   ret void
35 define internal void @write1ToGInt2() {
36 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
37 ; CHECK-LABEL: define {{[^@]+}}@write1ToGInt2
38 ; CHECK-SAME: () #[[ATTR4]] {
39 ; CHECK-NEXT:    store i32 1, ptr @GInt2, align 4
40 ; CHECK-NEXT:    ret void
42   store i32 1, ptr @GInt2
43   ret void
46 define void @entry1(i1 %c, i32 %v) {
47 ; TUNIT: Function Attrs: norecurse nosync
48 ; TUNIT-LABEL: define {{[^@]+}}@entry1
49 ; TUNIT-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR5:[0-9]+]] {
50 ; TUNIT-NEXT:    [[L0:%.*]] = load i32, ptr @GInt1, align 4
51 ; TUNIT-NEXT:    call void @useI32(i32 [[L0]])
52 ; TUNIT-NEXT:    call void @write1ToGInt1() #[[ATTR12:[0-9]+]]
53 ; TUNIT-NEXT:    [[L1:%.*]] = load i32, ptr @GInt1, align 4
54 ; TUNIT-NEXT:    call void @useI32(i32 [[L1]])
55 ; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
56 ; TUNIT:       T:
57 ; TUNIT-NEXT:    store i32 [[V]], ptr @GInt1, align 4
58 ; TUNIT-NEXT:    [[L2:%.*]] = load i32, ptr @GInt1, align 4
59 ; TUNIT-NEXT:    call void @useI32(i32 [[L2]])
60 ; TUNIT-NEXT:    br label [[F]]
61 ; TUNIT:       F:
62 ; TUNIT-NEXT:    [[L3:%.*]] = load i32, ptr @GInt1, align 4
63 ; TUNIT-NEXT:    call void @useI32(i32 [[L3]])
64 ; TUNIT-NEXT:    call void @write1ToGInt1() #[[ATTR12]]
65 ; TUNIT-NEXT:    [[L4:%.*]] = load i32, ptr @GInt1, align 4
66 ; TUNIT-NEXT:    call void @useI32(i32 [[L4]])
67 ; TUNIT-NEXT:    ret void
69 ; CGSCC: Function Attrs: nosync
70 ; CGSCC-LABEL: define {{[^@]+}}@entry1
71 ; CGSCC-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR5:[0-9]+]] {
72 ; CGSCC-NEXT:    [[L0:%.*]] = load i32, ptr @GInt1, align 4
73 ; CGSCC-NEXT:    call void @useI32(i32 [[L0]])
74 ; CGSCC-NEXT:    call void @write1ToGInt1() #[[ATTR13:[0-9]+]]
75 ; CGSCC-NEXT:    [[L1:%.*]] = load i32, ptr @GInt1, align 4
76 ; CGSCC-NEXT:    call void @useI32(i32 [[L1]])
77 ; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
78 ; CGSCC:       T:
79 ; CGSCC-NEXT:    store i32 [[V]], ptr @GInt1, align 4
80 ; CGSCC-NEXT:    [[L2:%.*]] = load i32, ptr @GInt1, align 4
81 ; CGSCC-NEXT:    call void @useI32(i32 [[L2]])
82 ; CGSCC-NEXT:    br label [[F]]
83 ; CGSCC:       F:
84 ; CGSCC-NEXT:    [[L3:%.*]] = load i32, ptr @GInt1, align 4
85 ; CGSCC-NEXT:    call void @useI32(i32 [[L3]])
86 ; CGSCC-NEXT:    call void @write1ToGInt1() #[[ATTR13]]
87 ; CGSCC-NEXT:    [[L4:%.*]] = load i32, ptr @GInt1, align 4
88 ; CGSCC-NEXT:    call void @useI32(i32 [[L4]])
89 ; CGSCC-NEXT:    ret void
91   %l0 = load i32, ptr @GInt1
92   call void @useI32(i32 %l0)
93   call void @write1ToGInt1();
94   %l1 = load i32, ptr @GInt1
95   call void @useI32(i32 %l1)
96   br i1 %c, label %T, label %F
98   store i32 %v, ptr @GInt1
99   %l2 = load i32, ptr @GInt1
100   call void @useI32(i32 %l2)
101   br label %F
103   %l3 = load i32, ptr @GInt1
104   call void @useI32(i32 %l3)
105   call void @write1ToGInt1();
106   %l4 = load i32, ptr @GInt1
107   call void @useI32(i32 %l4)
108   ret void
111 define void @entry2(i1 %c, i32 %v) {
112 ; TUNIT: Function Attrs: norecurse nosync
113 ; TUNIT-LABEL: define {{[^@]+}}@entry2
114 ; TUNIT-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR5]] {
115 ; TUNIT-NEXT:    [[L0:%.*]] = load i32, ptr @GInt2, align 4
116 ; TUNIT-NEXT:    call void @useI32(i32 [[L0]])
117 ; TUNIT-NEXT:    call void @write1ToGInt2() #[[ATTR12]]
118 ; TUNIT-NEXT:    [[L1:%.*]] = load i32, ptr @GInt2, align 4
119 ; TUNIT-NEXT:    call void @useI32(i32 [[L1]])
120 ; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
121 ; TUNIT:       T:
122 ; TUNIT-NEXT:    store i32 [[V]], ptr @GInt2, align 4
123 ; TUNIT-NEXT:    [[L2:%.*]] = load i32, ptr @GInt2, align 4
124 ; TUNIT-NEXT:    call void @useI32(i32 [[L2]])
125 ; TUNIT-NEXT:    br label [[F]]
126 ; TUNIT:       F:
127 ; TUNIT-NEXT:    [[L3:%.*]] = load i32, ptr @GInt2, align 4
128 ; TUNIT-NEXT:    call void @useI32(i32 [[L3]])
129 ; TUNIT-NEXT:    call void @write1ToGInt2() #[[ATTR12]]
130 ; TUNIT-NEXT:    [[L4:%.*]] = load i32, ptr @GInt2, align 4
131 ; TUNIT-NEXT:    call void @useI32(i32 [[L4]])
132 ; TUNIT-NEXT:    ret void
134 ; CGSCC: Function Attrs: nosync
135 ; CGSCC-LABEL: define {{[^@]+}}@entry2
136 ; CGSCC-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR5]] {
137 ; CGSCC-NEXT:    [[L0:%.*]] = load i32, ptr @GInt2, align 4
138 ; CGSCC-NEXT:    call void @useI32(i32 [[L0]])
139 ; CGSCC-NEXT:    call void @write1ToGInt2() #[[ATTR13]]
140 ; CGSCC-NEXT:    [[L1:%.*]] = load i32, ptr @GInt2, align 4
141 ; CGSCC-NEXT:    call void @useI32(i32 [[L1]])
142 ; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
143 ; CGSCC:       T:
144 ; CGSCC-NEXT:    store i32 [[V]], ptr @GInt2, align 4
145 ; CGSCC-NEXT:    [[L2:%.*]] = load i32, ptr @GInt2, align 4
146 ; CGSCC-NEXT:    call void @useI32(i32 [[L2]])
147 ; CGSCC-NEXT:    br label [[F]]
148 ; CGSCC:       F:
149 ; CGSCC-NEXT:    [[L3:%.*]] = load i32, ptr @GInt2, align 4
150 ; CGSCC-NEXT:    call void @useI32(i32 [[L3]])
151 ; CGSCC-NEXT:    call void @write1ToGInt2() #[[ATTR13]]
152 ; CGSCC-NEXT:    [[L4:%.*]] = load i32, ptr @GInt2, align 4
153 ; CGSCC-NEXT:    call void @useI32(i32 [[L4]])
154 ; CGSCC-NEXT:    ret void
156   %l0 = load i32, ptr @GInt2
157   call void @useI32(i32 %l0)
158   call void @write1ToGInt2();
159   %l1 = load i32, ptr @GInt2
160   call void @useI32(i32 %l1)
161   br i1 %c, label %T, label %F
163   store i32 %v, ptr @GInt2
164   %l2 = load i32, ptr @GInt2
165   call void @useI32(i32 %l2)
166   br label %F
168   %l3 = load i32, ptr @GInt2
169   call void @useI32(i32 %l3)
170   call void @write1ToGInt2();
171   %l4 = load i32, ptr @GInt2
172   call void @useI32(i32 %l4)
173   ret void
175 define void @entry3(i1 %c, i32 %v) {
176 ; TUNIT: Function Attrs: norecurse nosync
177 ; TUNIT-LABEL: define {{[^@]+}}@entry3
178 ; TUNIT-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR5]] {
179 ; TUNIT-NEXT:    call void @useI32(i32 1)
180 ; TUNIT-NEXT:    store i32 1, ptr @GInt3, align 4
181 ; TUNIT-NEXT:    call void @useI32(i32 noundef 1)
182 ; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
183 ; TUNIT:       T:
184 ; TUNIT-NEXT:    store i32 [[V]], ptr @GInt3, align 4
185 ; TUNIT-NEXT:    [[L2:%.*]] = load i32, ptr @GInt3, align 4
186 ; TUNIT-NEXT:    call void @useI32(i32 [[L2]])
187 ; TUNIT-NEXT:    br label [[F]]
188 ; TUNIT:       F:
189 ; TUNIT-NEXT:    [[L3:%.*]] = load i32, ptr @GInt3, align 4
190 ; TUNIT-NEXT:    call void @useI32(i32 [[L3]])
191 ; TUNIT-NEXT:    store i32 1, ptr @GInt3, align 4
192 ; TUNIT-NEXT:    call void @useI32(i32 noundef 1)
193 ; TUNIT-NEXT:    ret void
195 ; CGSCC: Function Attrs: norecurse nosync
196 ; CGSCC-LABEL: define {{[^@]+}}@entry3
197 ; CGSCC-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR6:[0-9]+]] {
198 ; CGSCC-NEXT:    call void @useI32(i32 1)
199 ; CGSCC-NEXT:    store i32 1, ptr @GInt3, align 4
200 ; CGSCC-NEXT:    call void @useI32(i32 noundef 1)
201 ; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
202 ; CGSCC:       T:
203 ; CGSCC-NEXT:    store i32 [[V]], ptr @GInt3, align 4
204 ; CGSCC-NEXT:    [[L2:%.*]] = load i32, ptr @GInt3, align 4
205 ; CGSCC-NEXT:    call void @useI32(i32 [[L2]])
206 ; CGSCC-NEXT:    br label [[F]]
207 ; CGSCC:       F:
208 ; CGSCC-NEXT:    [[L3:%.*]] = load i32, ptr @GInt3, align 4
209 ; CGSCC-NEXT:    call void @useI32(i32 [[L3]])
210 ; CGSCC-NEXT:    store i32 1, ptr @GInt3, align 4
211 ; CGSCC-NEXT:    call void @useI32(i32 noundef 1)
212 ; CGSCC-NEXT:    ret void
214   %l0 = load i32, ptr @GInt3
215   call void @useI32(i32 %l0)
216   store i32 1, ptr @GInt3
217   %l1 = load i32, ptr @GInt3
218   call void @useI32(i32 %l1)
219   br i1 %c, label %T, label %F
221   store i32 %v, ptr @GInt3
222   %l2 = load i32, ptr @GInt3
223   call void @useI32(i32 %l2)
224   br label %F
226   %l3 = load i32, ptr @GInt3
227   call void @useI32(i32 %l3)
228   store i32 1, ptr @GInt3
229   %l4 = load i32, ptr @GInt3
230   call void @useI32(i32 %l4)
231   ret void
234 define void @entry4(i1 %c, i32 %v) {
235 ; TUNIT: Function Attrs: norecurse nosync
236 ; TUNIT-LABEL: define {{[^@]+}}@entry4
237 ; TUNIT-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR5]] {
238 ; TUNIT-NEXT:    [[L0:%.*]] = load i32, ptr @GInt4, align 4
239 ; TUNIT-NEXT:    call void @useI32(i32 noundef [[L0]])
240 ; TUNIT-NEXT:    store i32 1, ptr @GInt4, align 4
241 ; TUNIT-NEXT:    call void @useI32(i32 noundef 1)
242 ; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
243 ; TUNIT:       T:
244 ; TUNIT-NEXT:    store i32 [[V]], ptr @GInt4, align 4
245 ; TUNIT-NEXT:    [[L2:%.*]] = load i32, ptr @GInt4, align 4
246 ; TUNIT-NEXT:    call void @useI32(i32 [[L2]])
247 ; TUNIT-NEXT:    br label [[F]]
248 ; TUNIT:       F:
249 ; TUNIT-NEXT:    [[L3:%.*]] = load i32, ptr @GInt4, align 4
250 ; TUNIT-NEXT:    call void @useI32(i32 [[L3]])
251 ; TUNIT-NEXT:    store i32 1, ptr @GInt4, align 4
252 ; TUNIT-NEXT:    call void @useI32(i32 noundef 1)
253 ; TUNIT-NEXT:    ret void
255 ; CGSCC: Function Attrs: norecurse nosync
256 ; CGSCC-LABEL: define {{[^@]+}}@entry4
257 ; CGSCC-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR6]] {
258 ; CGSCC-NEXT:    [[L0:%.*]] = load i32, ptr @GInt4, align 4
259 ; CGSCC-NEXT:    call void @useI32(i32 noundef [[L0]])
260 ; CGSCC-NEXT:    store i32 1, ptr @GInt4, align 4
261 ; CGSCC-NEXT:    call void @useI32(i32 noundef 1)
262 ; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
263 ; CGSCC:       T:
264 ; CGSCC-NEXT:    store i32 [[V]], ptr @GInt4, align 4
265 ; CGSCC-NEXT:    [[L2:%.*]] = load i32, ptr @GInt4, align 4
266 ; CGSCC-NEXT:    call void @useI32(i32 [[L2]])
267 ; CGSCC-NEXT:    br label [[F]]
268 ; CGSCC:       F:
269 ; CGSCC-NEXT:    [[L3:%.*]] = load i32, ptr @GInt4, align 4
270 ; CGSCC-NEXT:    call void @useI32(i32 [[L3]])
271 ; CGSCC-NEXT:    store i32 1, ptr @GInt4, align 4
272 ; CGSCC-NEXT:    call void @useI32(i32 noundef 1)
273 ; CGSCC-NEXT:    ret void
275   %l0 = load i32, ptr @GInt4
276   call void @useI32(i32 %l0)
277   store i32 1, ptr @GInt4
278   %l1 = load i32, ptr @GInt4
279   call void @useI32(i32 %l1)
280   br i1 %c, label %T, label %F
282   store i32 %v, ptr @GInt4
283   %l2 = load i32, ptr @GInt4
284   call void @useI32(i32 %l2)
285   br label %F
287   %l3 = load i32, ptr @GInt4
288   call void @useI32(i32 %l3)
289   store i32 1, ptr @GInt4
290   %l4 = load i32, ptr @GInt4
291   call void @useI32(i32 %l4)
292   ret void
295 ; TODO: In this test we can replace %l0, in the others above we cannot.
296 define void @entry5(i1 %c, i32 %v) {
297 ; TUNIT: Function Attrs: norecurse nosync
298 ; TUNIT-LABEL: define {{[^@]+}}@entry5
299 ; TUNIT-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR5]] {
300 ; TUNIT-NEXT:    call void @useI32(i32 1)
301 ; TUNIT-NEXT:    store i32 1, ptr @GInt5, align 4
302 ; TUNIT-NEXT:    call void @useI32(i32 noundef 1) #[[ATTR6:[0-9]+]]
303 ; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
304 ; TUNIT:       T:
305 ; TUNIT-NEXT:    store i32 [[V]], ptr @GInt5, align 4
306 ; TUNIT-NEXT:    [[L2:%.*]] = load i32, ptr @GInt5, align 4
307 ; TUNIT-NEXT:    call void @useI32(i32 [[L2]]) #[[ATTR6]]
308 ; TUNIT-NEXT:    br label [[F]]
309 ; TUNIT:       F:
310 ; TUNIT-NEXT:    [[L3:%.*]] = load i32, ptr @GInt5, align 4
311 ; TUNIT-NEXT:    call void @useI32(i32 [[L3]]) #[[ATTR6]]
312 ; TUNIT-NEXT:    store i32 1, ptr @GInt5, align 4
313 ; TUNIT-NEXT:    call void @useI32(i32 noundef 1) #[[ATTR6]]
314 ; TUNIT-NEXT:    ret void
316 ; CGSCC: Function Attrs: norecurse nosync
317 ; CGSCC-LABEL: define {{[^@]+}}@entry5
318 ; CGSCC-SAME: (i1 [[C:%.*]], i32 [[V:%.*]]) #[[ATTR6]] {
319 ; CGSCC-NEXT:    call void @useI32(i32 1)
320 ; CGSCC-NEXT:    store i32 1, ptr @GInt5, align 4
321 ; CGSCC-NEXT:    call void @useI32(i32 noundef 1) #[[ATTR7:[0-9]+]]
322 ; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
323 ; CGSCC:       T:
324 ; CGSCC-NEXT:    store i32 [[V]], ptr @GInt5, align 4
325 ; CGSCC-NEXT:    [[L2:%.*]] = load i32, ptr @GInt5, align 4
326 ; CGSCC-NEXT:    call void @useI32(i32 [[L2]]) #[[ATTR7]]
327 ; CGSCC-NEXT:    br label [[F]]
328 ; CGSCC:       F:
329 ; CGSCC-NEXT:    [[L3:%.*]] = load i32, ptr @GInt5, align 4
330 ; CGSCC-NEXT:    call void @useI32(i32 [[L3]]) #[[ATTR7]]
331 ; CGSCC-NEXT:    store i32 1, ptr @GInt5, align 4
332 ; CGSCC-NEXT:    call void @useI32(i32 noundef 1) #[[ATTR7]]
333 ; CGSCC-NEXT:    ret void
335   %l0 = load i32, ptr @GInt5
336   call void @useI32(i32 %l0)
337   store i32 1, ptr @GInt5
338   %l1 = load i32, ptr @GInt5
339   call void @useI32(i32 %l1) nocallback
340   br i1 %c, label %T, label %F
342   store i32 %v, ptr @GInt5
343   %l2 = load i32, ptr @GInt5
344   call void @useI32(i32 %l2) nocallback
345   br label %F
347   %l3 = load i32, ptr @GInt5
348   call void @useI32(i32 %l3) nocallback
349   store i32 1, ptr @GInt5
350   %l4 = load i32, ptr @GInt5
351   call void @useI32(i32 %l4) nocallback
352   ret void
356 declare void @use_4_i8(i8, i8, i8, i8) nocallback
358 define void @exclusion_set1(i1 %c1, i1 %c2, i1 %c3) {
359 ; CHECK-LABEL: define {{[^@]+}}@exclusion_set1
360 ; CHECK-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) {
361 ; CHECK-NEXT:  entry:
362 ; CHECK-NEXT:    [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1
363 ; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[CALL_H2S]], i8 0, i64 4, i1 false)
364 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[CALL_H2S]], i64 1
365 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[CALL_H2S]], i64 2
366 ; CHECK-NEXT:    [[GEP3:%.*]] = getelementptr inbounds i8, ptr [[CALL_H2S]], i64 3
367 ; CHECK-NEXT:    [[L0_A:%.*]] = load i8, ptr [[CALL_H2S]], align 1
368 ; CHECK-NEXT:    [[L1_A:%.*]] = load i8, ptr [[GEP1]], align 1
369 ; CHECK-NEXT:    [[L2_A:%.*]] = load i8, ptr [[GEP2]], align 1
370 ; CHECK-NEXT:    [[L3_A:%.*]] = load i8, ptr [[GEP3]], align 1
371 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef [[L0_A]], i8 noundef [[L1_A]], i8 noundef [[L2_A]], i8 noundef [[L3_A]])
372 ; CHECK-NEXT:    store i8 1, ptr [[CALL_H2S]], align 4
373 ; CHECK-NEXT:    [[L1_B:%.*]] = load i8, ptr [[GEP1]], align 1
374 ; CHECK-NEXT:    [[L2_B:%.*]] = load i8, ptr [[GEP2]], align 1
375 ; CHECK-NEXT:    [[L3_B:%.*]] = load i8, ptr [[GEP3]], align 1
376 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef [[L1_B]], i8 noundef [[L2_B]], i8 noundef [[L3_B]])
377 ; CHECK-NEXT:    br i1 [[C1]], label [[IF_MERGE1:%.*]], label [[IF_THEN:%.*]]
378 ; CHECK:       if.then:
379 ; CHECK-NEXT:    [[L1_C:%.*]] = load i8, ptr [[GEP1]], align 1
380 ; CHECK-NEXT:    [[L2_C:%.*]] = load i8, ptr [[GEP2]], align 1
381 ; CHECK-NEXT:    [[L3_C:%.*]] = load i8, ptr [[GEP3]], align 1
382 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef [[L1_C]], i8 noundef [[L2_C]], i8 noundef [[L3_C]])
383 ; CHECK-NEXT:    store i8 2, ptr [[GEP1]], align 4
384 ; CHECK-NEXT:    [[L2_D:%.*]] = load i8, ptr [[GEP2]], align 1
385 ; CHECK-NEXT:    [[L3_D:%.*]] = load i8, ptr [[GEP3]], align 1
386 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef [[L2_D]], i8 noundef [[L3_D]])
387 ; CHECK-NEXT:    br i1 [[C1]], label [[IF_MERGE1]], label [[IF_THEN2:%.*]]
388 ; CHECK:       if.then2:
389 ; CHECK-NEXT:    [[L2_E:%.*]] = load i8, ptr [[GEP2]], align 1
390 ; CHECK-NEXT:    [[L3_E:%.*]] = load i8, ptr [[GEP3]], align 1
391 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef [[L2_E]], i8 noundef [[L3_E]])
392 ; CHECK-NEXT:    store i8 3, ptr [[GEP2]], align 4
393 ; CHECK-NEXT:    [[L3_F:%.*]] = load i8, ptr [[GEP3]], align 1
394 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 noundef [[L3_F]])
395 ; CHECK-NEXT:    br i1 [[C2]], label [[IF_MERGE2:%.*]], label [[IF_THEN3:%.*]]
396 ; CHECK:       if.merge1:
397 ; CHECK-NEXT:    [[L1_G:%.*]] = load i8, ptr [[GEP1]], align 1
398 ; CHECK-NEXT:    [[L2_G:%.*]] = load i8, ptr [[GEP2]], align 1
399 ; CHECK-NEXT:    [[L3_G:%.*]] = load i8, ptr [[GEP3]], align 1
400 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef [[L1_G]], i8 noundef [[L2_G]], i8 noundef [[L3_G]])
401 ; CHECK-NEXT:    br label [[IF_MERGE2]]
402 ; CHECK:       if.merge2:
403 ; CHECK-NEXT:    [[L1_H:%.*]] = load i8, ptr [[GEP1]], align 1
404 ; CHECK-NEXT:    [[L2_H:%.*]] = load i8, ptr [[GEP2]], align 1
405 ; CHECK-NEXT:    [[L3_H:%.*]] = load i8, ptr [[GEP3]], align 1
406 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef [[L1_H]], i8 noundef [[L2_H]], i8 noundef [[L3_H]])
407 ; CHECK-NEXT:    br label [[IF_END:%.*]]
408 ; CHECK:       if.then3:
409 ; CHECK-NEXT:    [[L3_I:%.*]] = load i8, ptr [[GEP3]], align 1
410 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 noundef [[L3_I]])
411 ; CHECK-NEXT:    store i8 4, ptr [[GEP3]], align 4
412 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 noundef 4)
413 ; CHECK-NEXT:    br label [[IF_END]]
414 ; CHECK:       if.end:
415 ; CHECK-NEXT:    [[L1_K:%.*]] = load i8, ptr [[GEP1]], align 1
416 ; CHECK-NEXT:    [[L2_K:%.*]] = load i8, ptr [[GEP2]], align 1
417 ; CHECK-NEXT:    [[L3_K:%.*]] = load i8, ptr [[GEP3]], align 1
418 ; CHECK-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef [[L1_K]], i8 noundef [[L2_K]], i8 noundef [[L3_K]])
419 ; CHECK-NEXT:    ret void
421 entry:
422   %call = call noalias ptr @calloc(i64 1, i64 4) norecurse
423   %gep0 = getelementptr inbounds i8, ptr %call, i64 0
424   %gep1 = getelementptr inbounds i8, ptr %call, i64 1
425   %gep2 = getelementptr inbounds i8, ptr %call, i64 2
426   %gep3 = getelementptr inbounds i8, ptr %call, i64 3
428   %l0_a = load i8, ptr %gep0
429   %l1_a = load i8, ptr %gep1
430   %l2_a = load i8, ptr %gep2
431   %l3_a = load i8, ptr %gep3
432   call void @use_4_i8(i8 %l0_a, i8 %l1_a, i8 %l2_a, i8 %l3_a)
434   store i8 1, ptr %gep0, align 4
436   %l0_b = load i8, ptr %gep0
437   %l1_b = load i8, ptr %gep1
438   %l2_b = load i8, ptr %gep2
439   %l3_b = load i8, ptr %gep3
440   call void @use_4_i8(i8 %l0_b, i8 %l1_b, i8 %l2_b, i8 %l3_b)
442   br i1 %c1, label %if.merge1, label %if.then
444 if.then:
445   %l0_c = load i8, ptr %gep0
446   %l1_c = load i8, ptr %gep1
447   %l2_c = load i8, ptr %gep2
448   %l3_c = load i8, ptr %gep3
449   call void @use_4_i8(i8 %l0_c, i8 %l1_c, i8 %l2_c, i8 %l3_c)
451   store i8 2, ptr %gep1, align 4
453   %l0_d = load i8, ptr %gep0
454   %l1_d = load i8, ptr %gep1
455   %l2_d = load i8, ptr %gep2
456   %l3_d = load i8, ptr %gep3
457   call void @use_4_i8(i8 %l0_d, i8 %l1_d, i8 %l2_d, i8 %l3_d)
459   br i1 %c1, label %if.merge1, label %if.then2
461 if.then2:
462   %l0_e = load i8, ptr %gep0
463   %l1_e = load i8, ptr %gep1
464   %l2_e = load i8, ptr %gep2
465   %l3_e = load i8, ptr %gep3
466   call void @use_4_i8(i8 %l0_e, i8 %l1_e, i8 %l2_e, i8 %l3_e)
468   store i8 3, ptr %gep2, align 4
470   %l0_f = load i8, ptr %gep0
471   %l1_f = load i8, ptr %gep1
472   %l2_f = load i8, ptr %gep2
473   %l3_f = load i8, ptr %gep3
474   call void @use_4_i8(i8 %l0_f, i8 %l1_f, i8 %l2_f, i8 %l3_f)
476   br i1 %c2, label %if.merge2, label %if.then3
478 if.merge1:
480   %l0_g = load i8, ptr %gep0
481   %l1_g = load i8, ptr %gep1
482   %l2_g = load i8, ptr %gep2
483   %l3_g = load i8, ptr %gep3
484   call void @use_4_i8(i8 %l0_g, i8 %l1_g, i8 %l2_g, i8 %l3_g)
486   br label %if.merge2
488 if.merge2:
490   %l0_h = load i8, ptr %gep0
491   %l1_h = load i8, ptr %gep1
492   %l2_h = load i8, ptr %gep2
493   %l3_h = load i8, ptr %gep3
494   call void @use_4_i8(i8 %l0_h, i8 %l1_h, i8 %l2_h, i8 %l3_h)
496   br label %if.end
498 if.then3:
500   %l0_i = load i8, ptr %gep0
501   %l1_i = load i8, ptr %gep1
502   %l2_i = load i8, ptr %gep2
503   %l3_i = load i8, ptr %gep3
504   call void @use_4_i8(i8 %l0_i, i8 %l1_i, i8 %l2_i, i8 %l3_i)
506   store i8 4, ptr %gep3, align 4
508   %l0_j = load i8, ptr %gep0
509   %l1_j = load i8, ptr %gep1
510   %l2_j = load i8, ptr %gep2
511   %l3_j = load i8, ptr %gep3
512   call void @use_4_i8(i8 %l0_j, i8 %l1_j, i8 %l2_j, i8 %l3_j)
514   br label %if.end
516 if.end:
517   %l0_k = load i8, ptr %gep0
518   %l1_k = load i8, ptr %gep1
519   %l2_k = load i8, ptr %gep2
520   %l3_k = load i8, ptr %gep3
521   call void @use_4_i8(i8 %l0_k, i8 %l1_k, i8 %l2_k, i8 %l3_k)
523   call void @free(ptr %call) norecurse
524   ret void
527 define void @exclusion_set2(i1 %c1, i1 %c2, i1 %c3) {
528 ; TUNIT: Function Attrs: norecurse
529 ; TUNIT-LABEL: define {{[^@]+}}@exclusion_set2
530 ; TUNIT-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR7:[0-9]+]] {
531 ; TUNIT-NEXT:  entry:
532 ; TUNIT-NEXT:    call void @use_4_i8(i8 undef, i8 undef, i8 undef, i8 undef)
533 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 undef, i8 undef, i8 undef)
534 ; TUNIT-NEXT:    br i1 [[C1]], label [[IF_MERGE1:%.*]], label [[IF_THEN:%.*]]
535 ; TUNIT:       if.then:
536 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 undef, i8 undef, i8 undef)
537 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 undef, i8 undef)
538 ; TUNIT-NEXT:    br i1 [[C1]], label [[IF_MERGE1]], label [[IF_THEN2:%.*]]
539 ; TUNIT:       if.then2:
540 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 undef, i8 undef)
541 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 undef)
542 ; TUNIT-NEXT:    br i1 [[C2]], label [[IF_MERGE2:%.*]], label [[IF_THEN3:%.*]]
543 ; TUNIT:       if.merge1:
544 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 2, i8 undef, i8 undef)
545 ; TUNIT-NEXT:    br label [[IF_MERGE2]]
546 ; TUNIT:       if.merge2:
547 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 2, i8 3, i8 undef)
548 ; TUNIT-NEXT:    br label [[IF_END:%.*]]
549 ; TUNIT:       if.then3:
550 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 undef)
551 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 noundef 4)
552 ; TUNIT-NEXT:    br label [[IF_END]]
553 ; TUNIT:       if.end:
554 ; TUNIT-NEXT:    call void @use_4_i8(i8 noundef 1, i8 2, i8 3, i8 4)
555 ; TUNIT-NEXT:    ret void
557 ; CGSCC: Function Attrs: norecurse
558 ; CGSCC-LABEL: define {{[^@]+}}@exclusion_set2
559 ; CGSCC-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR8:[0-9]+]] {
560 ; CGSCC-NEXT:  entry:
561 ; CGSCC-NEXT:    call void @use_4_i8(i8 undef, i8 undef, i8 undef, i8 undef)
562 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 undef, i8 undef, i8 undef)
563 ; CGSCC-NEXT:    br i1 [[C1]], label [[IF_MERGE1:%.*]], label [[IF_THEN:%.*]]
564 ; CGSCC:       if.then:
565 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 undef, i8 undef, i8 undef)
566 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 undef, i8 undef)
567 ; CGSCC-NEXT:    br i1 [[C1]], label [[IF_MERGE1]], label [[IF_THEN2:%.*]]
568 ; CGSCC:       if.then2:
569 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 undef, i8 undef)
570 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 undef)
571 ; CGSCC-NEXT:    br i1 [[C2]], label [[IF_MERGE2:%.*]], label [[IF_THEN3:%.*]]
572 ; CGSCC:       if.merge1:
573 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 2, i8 undef, i8 undef)
574 ; CGSCC-NEXT:    br label [[IF_MERGE2]]
575 ; CGSCC:       if.merge2:
576 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 2, i8 3, i8 undef)
577 ; CGSCC-NEXT:    br label [[IF_END:%.*]]
578 ; CGSCC:       if.then3:
579 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 undef)
580 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 noundef 2, i8 noundef 3, i8 noundef 4)
581 ; CGSCC-NEXT:    br label [[IF_END]]
582 ; CGSCC:       if.end:
583 ; CGSCC-NEXT:    call void @use_4_i8(i8 noundef 1, i8 2, i8 3, i8 4)
584 ; CGSCC-NEXT:    ret void
586 entry:
587   %alloc = alloca i8, i32 4
588   %gep0 = getelementptr inbounds i8, ptr %alloc, i64 0
589   %gep1 = getelementptr inbounds i8, ptr %alloc, i64 1
590   %gep2 = getelementptr inbounds i8, ptr %alloc, i64 2
591   %gep3 = getelementptr inbounds i8, ptr %alloc, i64 3
593   %l0_a = load i8, ptr %gep0
594   %l1_a = load i8, ptr %gep1
595   %l2_a = load i8, ptr %gep2
596   %l3_a = load i8, ptr %gep3
597   call void @use_4_i8(i8 %l0_a, i8 %l1_a, i8 %l2_a, i8 %l3_a)
599   store i8 1, ptr %gep0, align 4
601   %l0_b = load i8, ptr %gep0
602   %l1_b = load i8, ptr %gep1
603   %l2_b = load i8, ptr %gep2
604   %l3_b = load i8, ptr %gep3
605   call void @use_4_i8(i8 %l0_b, i8 %l1_b, i8 %l2_b, i8 %l3_b)
607   br i1 %c1, label %if.merge1, label %if.then
609 if.then:
610   %l0_c = load i8, ptr %gep0
611   %l1_c = load i8, ptr %gep1
612   %l2_c = load i8, ptr %gep2
613   %l3_c = load i8, ptr %gep3
614   call void @use_4_i8(i8 %l0_c, i8 %l1_c, i8 %l2_c, i8 %l3_c)
616   store i8 2, ptr %gep1, align 4
618   %l0_d = load i8, ptr %gep0
619   %l1_d = load i8, ptr %gep1
620   %l2_d = load i8, ptr %gep2
621   %l3_d = load i8, ptr %gep3
622   call void @use_4_i8(i8 %l0_d, i8 %l1_d, i8 %l2_d, i8 %l3_d)
624   br i1 %c1, label %if.merge1, label %if.then2
626 if.then2:
627   %l0_e = load i8, ptr %gep0
628   %l1_e = load i8, ptr %gep1
629   %l2_e = load i8, ptr %gep2
630   %l3_e = load i8, ptr %gep3
631   call void @use_4_i8(i8 %l0_e, i8 %l1_e, i8 %l2_e, i8 %l3_e)
633   store i8 3, ptr %gep2, align 4
635   %l0_f = load i8, ptr %gep0
636   %l1_f = load i8, ptr %gep1
637   %l2_f = load i8, ptr %gep2
638   %l3_f = load i8, ptr %gep3
639   call void @use_4_i8(i8 %l0_f, i8 %l1_f, i8 %l2_f, i8 %l3_f)
641   br i1 %c2, label %if.merge2, label %if.then3
643 if.merge1:
645   %l0_g = load i8, ptr %gep0
646   %l1_g = load i8, ptr %gep1
647   %l2_g = load i8, ptr %gep2
648   %l3_g = load i8, ptr %gep3
649   call void @use_4_i8(i8 %l0_g, i8 %l1_g, i8 %l2_g, i8 %l3_g)
651   br label %if.merge2
653 if.merge2:
655   %l0_h = load i8, ptr %gep0
656   %l1_h = load i8, ptr %gep1
657   %l2_h = load i8, ptr %gep2
658   %l3_h = load i8, ptr %gep3
659   call void @use_4_i8(i8 %l0_h, i8 %l1_h, i8 %l2_h, i8 %l3_h)
661   br label %if.end
663 if.then3:
665   %l0_i = load i8, ptr %gep0
666   %l1_i = load i8, ptr %gep1
667   %l2_i = load i8, ptr %gep2
668   %l3_i = load i8, ptr %gep3
669   call void @use_4_i8(i8 %l0_i, i8 %l1_i, i8 %l2_i, i8 %l3_i)
671   store i8 4, ptr %gep3, align 4
673   %l0_j = load i8, ptr %gep0
674   %l1_j = load i8, ptr %gep1
675   %l2_j = load i8, ptr %gep2
676   %l3_j = load i8, ptr %gep3
677   call void @use_4_i8(i8 %l0_j, i8 %l1_j, i8 %l2_j, i8 %l3_j)
679   br label %if.end
681 if.end:
682   %l0_k = load i8, ptr %gep0
683   %l1_k = load i8, ptr %gep1
684   %l2_k = load i8, ptr %gep2
685   %l3_k = load i8, ptr %gep3
686   call void @use_4_i8(i8 %l0_k, i8 %l1_k, i8 %l2_k, i8 %l3_k)
688   ret void
691 declare void @usei32(i32) nocallback nosync
692 define internal void @exclusion_set3_helper(i1 %c, ptr %p) {
693 ; TUNIT: Function Attrs: nosync
694 ; TUNIT-LABEL: define {{[^@]+}}@exclusion_set3_helper
695 ; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR8:[0-9]+]] {
696 ; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
697 ; TUNIT:       t:
698 ; TUNIT-NEXT:    store i32 42, ptr [[P]], align 4
699 ; TUNIT-NEXT:    br label [[M:%.*]]
700 ; TUNIT:       f:
701 ; TUNIT-NEXT:    [[L:%.*]] = load i32, ptr [[P]], align 4
702 ; TUNIT-NEXT:    [[ADD:%.*]] = add i32 [[L]], 1
703 ; TUNIT-NEXT:    store i32 [[ADD]], ptr [[P]], align 4
704 ; TUNIT-NEXT:    [[CND:%.*]] = icmp eq i32 [[L]], 100
705 ; TUNIT-NEXT:    br i1 [[CND]], label [[F2:%.*]], label [[F]]
706 ; TUNIT:       f2:
707 ; TUNIT-NEXT:    [[USE1:%.*]] = load i32, ptr [[P]], align 4
708 ; TUNIT-NEXT:    call void @usei32(i32 [[USE1]])
709 ; TUNIT-NEXT:    store i32 77, ptr [[P]], align 4
710 ; TUNIT-NEXT:    call void @exclusion_set3_helper(i1 noundef true, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P]]) #[[ATTR8]]
711 ; TUNIT-NEXT:    [[USE2:%.*]] = load i32, ptr [[P]], align 4
712 ; TUNIT-NEXT:    call void @usei32(i32 noundef [[USE2]])
713 ; TUNIT-NEXT:    br label [[T]]
714 ; TUNIT:       m:
715 ; TUNIT-NEXT:    call void @usei32(i32 noundef 42)
716 ; TUNIT-NEXT:    ret void
718 ; CGSCC: Function Attrs: nosync
719 ; CGSCC-LABEL: define {{[^@]+}}@exclusion_set3_helper
720 ; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR5]] {
721 ; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
722 ; CGSCC:       t:
723 ; CGSCC-NEXT:    store i32 42, ptr [[P]], align 4
724 ; CGSCC-NEXT:    br label [[M:%.*]]
725 ; CGSCC:       f:
726 ; CGSCC-NEXT:    [[L:%.*]] = load i32, ptr [[P]], align 4
727 ; CGSCC-NEXT:    [[ADD:%.*]] = add i32 [[L]], 1
728 ; CGSCC-NEXT:    store i32 [[ADD]], ptr [[P]], align 4
729 ; CGSCC-NEXT:    [[CND:%.*]] = icmp eq i32 [[L]], 100
730 ; CGSCC-NEXT:    br i1 [[CND]], label [[F2:%.*]], label [[F]]
731 ; CGSCC:       f2:
732 ; CGSCC-NEXT:    [[USE1:%.*]] = load i32, ptr [[P]], align 4
733 ; CGSCC-NEXT:    call void @usei32(i32 [[USE1]])
734 ; CGSCC-NEXT:    store i32 77, ptr [[P]], align 4
735 ; CGSCC-NEXT:    call void @exclusion_set3_helper(i1 noundef true, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P]]) #[[ATTR5]]
736 ; CGSCC-NEXT:    [[USE2:%.*]] = load i32, ptr [[P]], align 4
737 ; CGSCC-NEXT:    call void @usei32(i32 [[USE2]])
738 ; CGSCC-NEXT:    br label [[T]]
739 ; CGSCC:       m:
740 ; CGSCC-NEXT:    [[USE3:%.*]] = load i32, ptr [[P]], align 4
741 ; CGSCC-NEXT:    call void @usei32(i32 [[USE3]])
742 ; CGSCC-NEXT:    ret void
744   br i1 %c, label %t, label %f
746   store i32 42, ptr %p
747   br label %m
749   %l = load i32, ptr %p
750   %add = add i32 %l, 1
751   store i32 %add, ptr %p
752   %cnd = icmp eq i32 %l, 100
753   br i1 %cnd, label %f2, label %f
755   %use1 = load i32, ptr %p
756   call void @usei32(i32 %use1)
757   store i32 77, ptr %p
758   call void @exclusion_set3_helper(i1 true, ptr %p)
759   %use2 = load i32, ptr %p
760   call void @usei32(i32 %use2)
761   br label %t
763   %use3 = load i32, ptr %p
764   call void @usei32(i32 %use3)
765   ret void
768 define i32 @exclusion_set3(i1 %c) {
769 ; TUNIT: Function Attrs: norecurse nosync
770 ; TUNIT-LABEL: define {{[^@]+}}@exclusion_set3
771 ; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR5]] {
772 ; TUNIT-NEXT:    [[A:%.*]] = alloca i32, align 4
773 ; TUNIT-NEXT:    store i32 3, ptr [[A]], align 4
774 ; TUNIT-NEXT:    call void @exclusion_set3_helper(i1 noundef [[C]], ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]]) #[[ATTR8]]
775 ; TUNIT-NEXT:    [[FINAL:%.*]] = load i32, ptr [[A]], align 4
776 ; TUNIT-NEXT:    ret i32 [[FINAL]]
778 ; CGSCC: Function Attrs: nosync
779 ; CGSCC-LABEL: define {{[^@]+}}@exclusion_set3
780 ; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR5]] {
781 ; CGSCC-NEXT:    [[A:%.*]] = alloca i32, align 4
782 ; CGSCC-NEXT:    store i32 3, ptr [[A]], align 4
783 ; CGSCC-NEXT:    call void @exclusion_set3_helper(i1 noundef [[C]], ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]])
784 ; CGSCC-NEXT:    [[FINAL:%.*]] = load i32, ptr [[A]], align 4
785 ; CGSCC-NEXT:    ret i32 [[FINAL]]
787   %a = alloca i32
788   store i32 3, ptr %a
789   call void @exclusion_set3_helper(i1 %c, ptr %a)
790   %final = load i32, ptr %a
791   ret i32 %final
794 @B = global i32 0
796 define internal i32 @readI32(ptr %a) {
797 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none)
798 ; TUNIT-LABEL: define {{[^@]+}}@readI32
799 ; TUNIT-SAME: (i32 [[TMP0:%.*]]) #[[ATTR9:[0-9]+]] {
800 ; TUNIT-NEXT:    [[A_PRIV:%.*]] = alloca i32, align 4
801 ; TUNIT-NEXT:    store i32 [[TMP0]], ptr [[A_PRIV]], align 4
802 ; TUNIT-NEXT:    [[R:%.*]] = load i32, ptr [[A_PRIV]], align 4
803 ; TUNIT-NEXT:    store i32 1, ptr @B, align 4
804 ; TUNIT-NEXT:    ret i32 [[R]]
806 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
807 ; CGSCC-LABEL: define {{[^@]+}}@readI32
808 ; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR9:[0-9]+]] {
809 ; CGSCC-NEXT:    [[R:%.*]] = load i32, ptr [[A]], align 4
810 ; CGSCC-NEXT:    store i32 1, ptr @B, align 4
811 ; CGSCC-NEXT:    ret i32 [[R]]
813   %r = load i32, ptr %a
814   store i32 1, ptr @B
815   ret i32 %r
818 define internal i32 @broker(ptr %a) {
819 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none)
820 ; TUNIT-LABEL: define {{[^@]+}}@broker
821 ; TUNIT-SAME: (i32 [[TMP0:%.*]]) #[[ATTR9]] {
822 ; TUNIT-NEXT:    [[A_PRIV:%.*]] = alloca i32, align 4
823 ; TUNIT-NEXT:    store i32 [[TMP0]], ptr [[A_PRIV]], align 4
824 ; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[A_PRIV]], align 4
825 ; TUNIT-NEXT:    [[R:%.*]] = call i32 @readI32(i32 [[TMP2]]) #[[ATTR13:[0-9]+]]
826 ; TUNIT-NEXT:    ret i32 [[R]]
828 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(readwrite, argmem: none)
829 ; CGSCC-LABEL: define {{[^@]+}}@broker
830 ; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR10:[0-9]+]] {
831 ; CGSCC-NEXT:    [[A_PRIV:%.*]] = alloca i32, align 4
832 ; CGSCC-NEXT:    store i32 [[TMP0]], ptr [[A_PRIV]], align 4
833 ; CGSCC-NEXT:    [[R:%.*]] = call i32 @readI32(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A_PRIV]]) #[[ATTR14:[0-9]+]]
834 ; CGSCC-NEXT:    ret i32 [[R]]
836   %r = call i32 @readI32(ptr %a)
837   ret i32 %r
840 ; FIXME: This function should return 1, not 0
841 define i32 @two_calls() {
842 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
843 ; TUNIT-LABEL: define {{[^@]+}}@two_calls
844 ; TUNIT-SAME: () #[[ATTR10:[0-9]+]] {
845 ; TUNIT-NEXT:    [[A:%.*]] = alloca i32, align 4
846 ; TUNIT-NEXT:    store i32 0, ptr [[A]], align 4
847 ; TUNIT-NEXT:    [[TMP1:%.*]] = load i32, ptr [[A]], align 4
848 ; TUNIT-NEXT:    [[D:%.*]] = call i32 @broker(i32 [[TMP1]]) #[[ATTR13]]
849 ; TUNIT-NEXT:    store i32 1, ptr [[A]], align 4
850 ; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[A]], align 4
851 ; TUNIT-NEXT:    [[R:%.*]] = call i32 @broker(i32 [[TMP2]]) #[[ATTR13]]
852 ; TUNIT-NEXT:    ret i32 [[R]]
854 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
855 ; CGSCC-LABEL: define {{[^@]+}}@two_calls
856 ; CGSCC-SAME: () #[[ATTR11:[0-9]+]] {
857 ; CGSCC-NEXT:    [[A:%.*]] = alloca i32, align 4
858 ; CGSCC-NEXT:    store i32 0, ptr [[A]], align 4
859 ; CGSCC-NEXT:    [[TMP1:%.*]] = load i32, ptr [[A]], align 4
860 ; CGSCC-NEXT:    [[D:%.*]] = call i32 @broker(i32 noundef [[TMP1]]) #[[ATTR14]]
861 ; CGSCC-NEXT:    store i32 1, ptr [[A]], align 4
862 ; CGSCC-NEXT:    [[R:%.*]] = call i32 @broker(i32 noundef 1) #[[ATTR14]]
863 ; CGSCC-NEXT:    ret i32 [[R]]
865   %a = alloca i32
866   store i32 0, ptr %a
867   %d = call i32 @broker(ptr %a)
868   store i32 1, ptr %a
869   %r = call i32 @broker(ptr %a)
870   ret i32 %r
874 ; TUNIT: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
875 ; TUNIT: attributes #[[ATTR1:[0-9]+]] = { nocallback nosync }
876 ; TUNIT: attributes #[[ATTR2:[0-9]+]] = { allockind("free") "alloc-family"="malloc" }
877 ; TUNIT: attributes #[[ATTR3:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" }
878 ; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
879 ; TUNIT: attributes #[[ATTR5]] = { norecurse nosync }
880 ; TUNIT: attributes #[[ATTR6]] = { nocallback }
881 ; TUNIT: attributes #[[ATTR7]] = { norecurse }
882 ; TUNIT: attributes #[[ATTR8]] = { nosync }
883 ; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none) }
884 ; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn }
885 ; TUNIT: attributes #[[ATTR11:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
886 ; TUNIT: attributes #[[ATTR12]] = { nosync nounwind memory(write) }
887 ; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn }
889 ; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
890 ; CGSCC: attributes #[[ATTR1:[0-9]+]] = { nocallback nosync }
891 ; CGSCC: attributes #[[ATTR2:[0-9]+]] = { allockind("free") "alloc-family"="malloc" }
892 ; CGSCC: attributes #[[ATTR3:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" }
893 ; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
894 ; CGSCC: attributes #[[ATTR5]] = { nosync }
895 ; CGSCC: attributes #[[ATTR6]] = { norecurse nosync }
896 ; CGSCC: attributes #[[ATTR7]] = { nocallback }
897 ; CGSCC: attributes #[[ATTR8]] = { norecurse }
898 ; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn }
899 ; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree nosync nounwind willreturn memory(readwrite, argmem: none) }
900 ; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree nosync nounwind willreturn }
901 ; CGSCC: attributes #[[ATTR12:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
902 ; CGSCC: attributes #[[ATTR13]] = { nounwind memory(write) }
903 ; CGSCC: attributes #[[ATTR14]] = { nofree nounwind willreturn }