xref: /llvm-project/llvm/test/Transforms/Attributor/value-simplify-assume.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
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
5@Gstatic_int1 = internal global i32 zeroinitializer, align 4
6@Gstatic_int2 = internal global i32 zeroinitializer, align 4
7
8declare void @llvm.assume(i1)
9declare void @useI1p(ptr)
10declare void @unknown()
11
12;.
13; CHECK: @Gstatic_int1 = internal global i32 0, align 4
14; CHECK: @Gstatic_int2 = internal global i32 0, align 4
15;.
16define i1 @readI1p(ptr %p) {
17; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
18; CHECK-LABEL: define {{[^@]+}}@readI1p
19; CHECK-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(1) [[P:%.*]]) #[[ATTR1:[0-9]+]] {
20; CHECK-NEXT:    [[L:%.*]] = load i1, ptr [[P]], align 1
21; CHECK-NEXT:    ret i1 [[L]]
22;
23  %l = load i1, ptr %p
24  ret i1 %l
25}
26
27define i1 @keep_assume_1c_nr() norecurse {
28; CHECK: Function Attrs: norecurse
29; CHECK-LABEL: define {{[^@]+}}@keep_assume_1c_nr
30; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
31; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
32; CHECK-NEXT:    store i1 true, ptr [[STACK]], align 1
33; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
34; CHECK-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
35; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L]])
36; CHECK-NEXT:    ret i1 [[L]]
37;
38  %stack = alloca i1
39  store i1 true, ptr %stack
40  call void @useI1p(ptr %stack)
41  %l = load i1, ptr %stack
42  call void @llvm.assume(i1 %l)
43  ret i1 %l
44}
45
46define i1 @drop_assume_1c_nr() norecurse {
47; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
48; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1c_nr
49; TUNIT-SAME: () #[[ATTR3:[0-9]+]] {
50; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR7:[0-9]+]]
51; TUNIT-NEXT:    ret i1 true
52;
53; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
54; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1c_nr
55; CGSCC-SAME: () #[[ATTR3:[0-9]+]] {
56; CGSCC-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR8:[0-9]+]]
57; CGSCC-NEXT:    ret i1 true
58;
59  %stack = alloca i1
60  store i1 true, ptr %stack
61  %l = load i1, ptr %stack
62  call void @llvm.assume(i1 %l)
63  ret i1 %l
64}
65
66define i1 @keep_assume_2c_nr() norecurse {
67; CHECK: Function Attrs: norecurse
68; CHECK-LABEL: define {{[^@]+}}@keep_assume_2c_nr
69; CHECK-SAME: () #[[ATTR2]] {
70; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
71; CHECK-NEXT:    store i1 true, ptr [[STACK]], align 1
72; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
73; CHECK-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
74; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L1]])
75; CHECK-NEXT:    call void @unknown()
76; CHECK-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
77; CHECK-NEXT:    ret i1 [[L2]]
78;
79  %stack = alloca i1
80  store i1 true, ptr %stack
81  call void @useI1p(ptr %stack)
82  %l1 = load i1, ptr %stack
83  call void @llvm.assume(i1 %l1)
84  call void @unknown()
85  %l2 = load i1, ptr %stack
86  ret i1 %l2
87}
88
89define i1 @keep_assume_3c_nr() norecurse {
90;
91; TUNIT: Function Attrs: norecurse
92; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3c_nr
93; TUNIT-SAME: () #[[ATTR2]] {
94; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
95; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
96; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
97; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
98; TUNIT-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
99; TUNIT-NEXT:    ret i1 [[L]]
100;
101; CGSCC: Function Attrs: norecurse
102; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3c_nr
103; CGSCC-SAME: () #[[ATTR2]] {
104; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
105; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
106; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
107; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
108; CGSCC-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
109; CGSCC-NEXT:    ret i1 [[L]]
110;
111  %stack = alloca i1
112  store i1 true, ptr %stack
113  %l = load i1, ptr %stack
114  call void @llvm.assume(i1 %l)
115  call void @useI1p(ptr %stack)
116  ret i1 %l
117}
118define i1 @keep_assume_4c_nr() norecurse {
119;
120; TUNIT: Function Attrs: norecurse
121; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4c_nr
122; TUNIT-SAME: () #[[ATTR2]] {
123; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
124; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
125; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR7]]
126; TUNIT-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
127; TUNIT-NEXT:    ret i1 true
128;
129; CGSCC: Function Attrs: norecurse
130; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4c_nr
131; CGSCC-SAME: () #[[ATTR2]] {
132; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
133; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
134; CGSCC-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR8]]
135; CGSCC-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
136; CGSCC-NEXT:    ret i1 true
137;
138  %stack = alloca i1
139  store i1 true, ptr %stack
140  %l4 = load i1, ptr %stack
141  call void @llvm.assume(i1 %l4)
142  call void @useI1p(ptr nocapture %stack)
143  ret i1 %l4
144}
145
146define i1 @keep_assume_1_nr(i1 %arg) norecurse {
147; CHECK: Function Attrs: norecurse
148; CHECK-LABEL: define {{[^@]+}}@keep_assume_1_nr
149; CHECK-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] {
150; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
151; CHECK-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
152; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
153; CHECK-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
154; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L]])
155; CHECK-NEXT:    ret i1 [[L]]
156;
157  %stack = alloca i1
158  store i1 %arg, ptr %stack
159  call void @useI1p(ptr %stack)
160  %l = load i1, ptr %stack
161  call void @llvm.assume(i1 %l)
162  ret i1 %l
163}
164
165define i1 @drop_assume_1_nr(i1 %arg) norecurse {
166; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
167; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1_nr
168; TUNIT-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
169; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
170; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
171; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]]
172; TUNIT-NEXT:    ret i1 [[ARG]]
173;
174; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
175; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1_nr
176; CGSCC-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
177; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
178; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
179; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]]
180; CGSCC-NEXT:    ret i1 [[ARG]]
181;
182  %stack = alloca i1
183  store i1 %arg, ptr %stack
184  %l = load i1, ptr %stack
185  call void @llvm.assume(i1 %l)
186  ret i1 %l
187}
188
189define i1 @keep_assume_2_nr(i1 %arg) norecurse {
190; CHECK: Function Attrs: norecurse
191; CHECK-LABEL: define {{[^@]+}}@keep_assume_2_nr
192; CHECK-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] {
193; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
194; CHECK-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
195; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
196; CHECK-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
197; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L1]])
198; CHECK-NEXT:    call void @unknown()
199; CHECK-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
200; CHECK-NEXT:    ret i1 [[L2]]
201;
202  %stack = alloca i1
203  store i1 %arg, ptr %stack
204  call void @useI1p(ptr %stack)
205  %l1 = load i1, ptr %stack
206  call void @llvm.assume(i1 %l1)
207  call void @unknown()
208  %l2 = load i1, ptr %stack
209  ret i1 %l2
210}
211
212define i1 @keep_assume_3_nr(i1 %arg) norecurse {
213;
214; TUNIT: Function Attrs: norecurse
215; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3_nr
216; TUNIT-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] {
217; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
218; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
219; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
220; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
221; TUNIT-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
222; TUNIT-NEXT:    ret i1 [[L]]
223;
224; CGSCC: Function Attrs: norecurse
225; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3_nr
226; CGSCC-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] {
227; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
228; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
229; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
230; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
231; CGSCC-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
232; CGSCC-NEXT:    ret i1 [[L]]
233;
234  %stack = alloca i1
235  store i1 %arg, ptr %stack
236  %l = load i1, ptr %stack
237  call void @llvm.assume(i1 %l)
238  call void @useI1p(ptr %stack)
239  ret i1 %l
240}
241
242define i1 @keep_assume_4_nr(i1 %arg) norecurse {
243;
244; TUNIT: Function Attrs: norecurse
245; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4_nr
246; TUNIT-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR2]] {
247; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
248; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
249; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]]
250; TUNIT-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
251; TUNIT-NEXT:    ret i1 [[ARG]]
252;
253; CGSCC: Function Attrs: norecurse
254; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4_nr
255; CGSCC-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR2]] {
256; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
257; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
258; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]]
259; CGSCC-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
260; CGSCC-NEXT:    ret i1 [[ARG]]
261;
262  %stack = alloca i1
263  store i1 %arg, ptr %stack
264  %l = load i1, ptr %stack
265  call void @llvm.assume(i1 %l)
266  call void @useI1p(ptr nocapture %stack)
267  ret i1 %l
268}
269
270define i1 @assume_1_nr(i1 %arg, i1 %cond) norecurse {
271; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
272; TUNIT-LABEL: define {{[^@]+}}@assume_1_nr
273; TUNIT-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
274; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
275; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
276; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]]
277; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
278; TUNIT:       t:
279; TUNIT-NEXT:    br label [[M:%.*]]
280; TUNIT:       f:
281; TUNIT-NEXT:    br label [[M]]
282; TUNIT:       m:
283; TUNIT-NEXT:    ret i1 [[ARG]]
284;
285; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
286; CGSCC-LABEL: define {{[^@]+}}@assume_1_nr
287; CGSCC-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
288; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
289; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
290; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]]
291; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
292; CGSCC:       t:
293; CGSCC-NEXT:    br label [[M:%.*]]
294; CGSCC:       f:
295; CGSCC-NEXT:    br label [[M]]
296; CGSCC:       m:
297; CGSCC-NEXT:    ret i1 [[ARG]]
298;
299  %stack = alloca i1
300  store i1 %arg, ptr %stack
301  %l = load i1, ptr %stack
302  call void @llvm.assume(i1 %l)
303  br i1 %cond, label %t, label %f
304t:
305  store i1 true, ptr %stack
306  br label %m
307f:
308  store i1 false, ptr %stack
309  br label %m
310m:
311  ret i1 %l
312}
313
314define void @assume_1b_nr(i1 %arg, i1 %cond) norecurse {
315; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
316; CHECK-LABEL: define {{[^@]+}}@assume_1b_nr
317; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4:[0-9]+]] {
318; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
319; CHECK:       t:
320; CHECK-NEXT:    br label [[M:%.*]]
321; CHECK:       f:
322; CHECK-NEXT:    br label [[M]]
323; CHECK:       m:
324; CHECK-NEXT:    ret void
325;
326  %stack = alloca i1
327  store i1 %arg, ptr %stack
328  %l = load i1, ptr %stack
329  call void @llvm.assume(i1 %l)
330  br i1 %cond, label %t, label %f
331t:
332  store i1 true, ptr %stack
333  br label %m
334f:
335  store i1 false, ptr %stack
336  br label %m
337m:
338  ret void
339}
340
341define i1 @assume_2_nr(i1 %arg, i1 %cond) norecurse {
342; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
343; TUNIT-LABEL: define {{[^@]+}}@assume_2_nr
344; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
345; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
346; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
347; TUNIT:       t:
348; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
349; TUNIT-NEXT:    br label [[M:%.*]]
350; TUNIT:       f:
351; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
352; TUNIT-NEXT:    br label [[M]]
353; TUNIT:       m:
354; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
355; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
356; TUNIT-NEXT:    ret i1 [[L]]
357;
358; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
359; CGSCC-LABEL: define {{[^@]+}}@assume_2_nr
360; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
361; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
362; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
363; CGSCC:       t:
364; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
365; CGSCC-NEXT:    br label [[M:%.*]]
366; CGSCC:       f:
367; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
368; CGSCC-NEXT:    br label [[M]]
369; CGSCC:       m:
370; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
371; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
372; CGSCC-NEXT:    ret i1 [[L]]
373;
374  %stack = alloca i1
375  store i1 %arg, ptr %stack
376  br i1 %cond, label %t, label %f
377t:
378  store i1 true, ptr %stack
379  br label %m
380f:
381  store i1 false, ptr %stack
382  br label %m
383m:
384  %l = load i1, ptr %stack
385  call void @llvm.assume(i1 %l)
386  ret i1 %l
387}
388
389define void @assume_2b_nr(i1 %arg, i1 %cond) norecurse {
390; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
391; CHECK-LABEL: define {{[^@]+}}@assume_2b_nr
392; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
393; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
394; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
395; CHECK:       t:
396; CHECK-NEXT:    br label [[M:%.*]]
397; CHECK:       f:
398; CHECK-NEXT:    br label [[M]]
399; CHECK:       m:
400; CHECK-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
401; CHECK-NEXT:    ret void
402;
403  %stack = alloca i1
404  store i1 %arg, ptr %stack
405  br i1 %cond, label %t, label %f
406t:
407  store i1 true, ptr %stack
408  br label %m
409f:
410  store i1 false, ptr %stack
411  br label %m
412m:
413  %l = load i1, ptr %stack
414  call void @llvm.assume(i1 %l)
415  ret void
416}
417
418define i1 @assume_3_nr(i1 %arg, i1 %cond) norecurse {
419; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
420; TUNIT-LABEL: define {{[^@]+}}@assume_3_nr
421; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
422; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
423; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
424; TUNIT:       t:
425; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
426; TUNIT-NEXT:    br label [[M:%.*]]
427; TUNIT:       f:
428; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
429; TUNIT-NEXT:    br label [[M]]
430; TUNIT:       m:
431; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8:[0-9]+]]
432; TUNIT-NEXT:    ret i1 [[R]]
433;
434; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
435; CGSCC-LABEL: define {{[^@]+}}@assume_3_nr
436; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
437; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
438; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
439; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
440; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
441; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
442; CGSCC:       t:
443; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
444; CGSCC-NEXT:    br label [[M:%.*]]
445; CGSCC:       f:
446; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
447; CGSCC-NEXT:    br label [[M]]
448; CGSCC:       m:
449; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR9:[0-9]+]]
450; CGSCC-NEXT:    ret i1 [[R]]
451;
452  %stack = alloca i1
453  store i1 %arg, ptr %stack
454  %l = load i1, ptr %stack
455  call void @llvm.assume(i1 %l)
456  br i1 %cond, label %t, label %f
457t:
458  store i1 true, ptr %stack
459  br label %m
460f:
461  store i1 false, ptr %stack
462  br label %m
463m:
464  %r = call i1 @readI1p(ptr %stack)
465  ret i1 %r
466}
467
468define i1 @assume_4_nr(i1 %arg, i1 %cond) norecurse {
469; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
470; TUNIT-LABEL: define {{[^@]+}}@assume_4_nr
471; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
472; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
473; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
474; TUNIT:       t:
475; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
476; TUNIT-NEXT:    br label [[M:%.*]]
477; TUNIT:       f:
478; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
479; TUNIT-NEXT:    br label [[M]]
480; TUNIT:       m:
481; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
482; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
483; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8]]
484; TUNIT-NEXT:    ret i1 [[R]]
485;
486; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
487; CGSCC-LABEL: define {{[^@]+}}@assume_4_nr
488; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
489; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
490; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
491; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
492; CGSCC:       t:
493; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
494; CGSCC-NEXT:    br label [[M:%.*]]
495; CGSCC:       f:
496; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
497; CGSCC-NEXT:    br label [[M]]
498; CGSCC:       m:
499; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
500; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
501; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR9]]
502; CGSCC-NEXT:    ret i1 [[R]]
503;
504  %stack = alloca i1
505  store i1 %arg, ptr %stack
506  br i1 %cond, label %t, label %f
507t:
508  store i1 true, ptr %stack
509  br label %m
510f:
511  store i1 false, ptr %stack
512  br label %m
513m:
514  %l = load i1, ptr %stack
515  call void @llvm.assume(i1 %l)
516  %r = call i1 @readI1p(ptr %stack)
517  ret i1 %r
518}
519
520define i1 @assume_5_nr(i1 %arg, i1 %cond) norecurse {
521; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
522; TUNIT-LABEL: define {{[^@]+}}@assume_5_nr
523; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
524; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
525; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
526; TUNIT:       t:
527; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
528; TUNIT-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
529; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]]
530; TUNIT-NEXT:    br label [[M:%.*]]
531; TUNIT:       f:
532; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
533; TUNIT-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
534; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]]
535; TUNIT-NEXT:    br label [[M]]
536; TUNIT:       m:
537; TUNIT-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
538; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9:[0-9]+]]
539; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8]]
540; TUNIT-NEXT:    ret i1 [[R]]
541;
542; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
543; CGSCC-LABEL: define {{[^@]+}}@assume_5_nr
544; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
545; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
546; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
547; CGSCC-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
548; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]]
549; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
550; CGSCC:       t:
551; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
552; CGSCC-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
553; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10:[0-9]+]]
554; CGSCC-NEXT:    br label [[M:%.*]]
555; CGSCC:       f:
556; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
557; CGSCC-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
558; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]]
559; CGSCC-NEXT:    br label [[M]]
560; CGSCC:       m:
561; CGSCC-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
562; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]]
563; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR10]]
564; CGSCC-NEXT:    ret i1 [[R]]
565;
566  %stack = alloca i1
567  store i1 %arg, ptr %stack
568  %l1 = load i1, ptr %stack
569  call void @llvm.assume(i1 %l1)
570  br i1 %cond, label %t, label %f
571t:
572  store i1 true, ptr %stack
573  %l2 = load i1, ptr %stack
574  call void @llvm.assume(i1 %l2)
575  br label %m
576f:
577  store i1 false, ptr %stack
578  %l3 = load i1, ptr %stack
579  call void @llvm.assume(i1 %l3)
580  br label %m
581m:
582  %l4 = load i1, ptr %stack
583  call void @llvm.assume(i1 %l4)
584  %r = call i1 @readI1p(ptr %stack)
585  ret i1 %r
586}
587
588define i1 @assume_5c_nr(i1 %cond) norecurse {
589; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
590; TUNIT-LABEL: define {{[^@]+}}@assume_5c_nr
591; TUNIT-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] {
592; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
593; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR7]]
594; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
595; TUNIT:       t:
596; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
597; TUNIT-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
598; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]]
599; TUNIT-NEXT:    br label [[M:%.*]]
600; TUNIT:       f:
601; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
602; TUNIT-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
603; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]]
604; TUNIT-NEXT:    br label [[M]]
605; TUNIT:       m:
606; TUNIT-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
607; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9]]
608; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8]]
609; TUNIT-NEXT:    ret i1 [[R]]
610;
611; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
612; CGSCC-LABEL: define {{[^@]+}}@assume_5c_nr
613; CGSCC-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] {
614; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
615; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
616; CGSCC-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
617; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]]
618; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
619; CGSCC:       t:
620; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
621; CGSCC-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
622; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10]]
623; CGSCC-NEXT:    br label [[M:%.*]]
624; CGSCC:       f:
625; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
626; CGSCC-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
627; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]]
628; CGSCC-NEXT:    br label [[M]]
629; CGSCC:       m:
630; CGSCC-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
631; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]]
632; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR10]]
633; CGSCC-NEXT:    ret i1 [[R]]
634;
635  %stack = alloca i1
636  store i1 true, ptr %stack
637  %l1 = load i1, ptr %stack
638  call void @llvm.assume(i1 %l1)
639  br i1 %cond, label %t, label %f
640t:
641  store i1 true, ptr %stack
642  %l2 = load i1, ptr %stack
643  call void @llvm.assume(i1 %l2)
644  br label %m
645f:
646  store i1 false, ptr %stack
647  %l3 = load i1, ptr %stack
648  call void @llvm.assume(i1 %l3)
649  br label %m
650m:
651  %l4 = load i1, ptr %stack
652  call void @llvm.assume(i1 %l4)
653  %r = call i1 @readI1p(ptr %stack)
654  ret i1 %r
655}
656
657
658define i1 @keep_assume_1c() {
659; CHECK-LABEL: define {{[^@]+}}@keep_assume_1c() {
660; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
661; CHECK-NEXT:    store i1 true, ptr [[STACK]], align 1
662; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
663; CHECK-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
664; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L]])
665; CHECK-NEXT:    ret i1 [[L]]
666;
667  %stack = alloca i1
668  store i1 true, ptr %stack
669  call void @useI1p(ptr %stack)
670  %l = load i1, ptr %stack
671  call void @llvm.assume(i1 %l)
672  ret i1 %l
673}
674
675define i1 @drop_assume_1c() {
676; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
677; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1c
678; TUNIT-SAME: () #[[ATTR3]] {
679; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR7]]
680; TUNIT-NEXT:    ret i1 true
681;
682; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
683; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1c
684; CGSCC-SAME: () #[[ATTR3]] {
685; CGSCC-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR8]]
686; CGSCC-NEXT:    ret i1 true
687;
688  %stack = alloca i1
689  store i1 true, ptr %stack
690  %l = load i1, ptr %stack
691  call void @llvm.assume(i1 %l)
692  ret i1 %l
693}
694
695define i1 @keep_assume_2c() {
696; CHECK-LABEL: define {{[^@]+}}@keep_assume_2c() {
697; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
698; CHECK-NEXT:    store i1 true, ptr [[STACK]], align 1
699; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
700; CHECK-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
701; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L1]])
702; CHECK-NEXT:    call void @unknown()
703; CHECK-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
704; CHECK-NEXT:    ret i1 [[L2]]
705;
706  %stack = alloca i1
707  store i1 true, ptr %stack
708  call void @useI1p(ptr %stack)
709  %l1 = load i1, ptr %stack
710  call void @llvm.assume(i1 %l1)
711  call void @unknown()
712  %l2 = load i1, ptr %stack
713  ret i1 %l2
714}
715
716define i1 @keep_assume_3c() {
717;
718; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3c() {
719; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
720; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
721; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
722; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
723; TUNIT-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
724; TUNIT-NEXT:    ret i1 [[L]]
725;
726; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3c() {
727; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
728; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
729; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
730; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
731; CGSCC-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
732; CGSCC-NEXT:    ret i1 [[L]]
733;
734  %stack = alloca i1
735  store i1 true, ptr %stack
736  %l = load i1, ptr %stack
737  call void @llvm.assume(i1 %l)
738  call void @useI1p(ptr %stack)
739  ret i1 %l
740}
741define i1 @keep_assume_4c() {
742;
743; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4c() {
744; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
745; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
746; TUNIT-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
747; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR7]]
748; TUNIT-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
749; TUNIT-NEXT:    ret i1 [[L4]]
750;
751; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4c() {
752; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
753; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
754; CGSCC-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
755; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR8]]
756; CGSCC-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
757; CGSCC-NEXT:    ret i1 [[L4]]
758;
759  %stack = alloca i1
760  store i1 true, ptr %stack
761  %l4 = load i1, ptr %stack
762  call void @llvm.assume(i1 %l4)
763  call void @useI1p(ptr nocapture %stack)
764  ret i1 %l4
765}
766
767define i1 @keep_assume_1(i1 %arg) {
768; CHECK-LABEL: define {{[^@]+}}@keep_assume_1
769; CHECK-SAME: (i1 [[ARG:%.*]]) {
770; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
771; CHECK-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
772; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
773; CHECK-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
774; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L]])
775; CHECK-NEXT:    ret i1 [[L]]
776;
777  %stack = alloca i1
778  store i1 %arg, ptr %stack
779  call void @useI1p(ptr %stack)
780  %l = load i1, ptr %stack
781  call void @llvm.assume(i1 %l)
782  ret i1 %l
783}
784
785define i1 @drop_assume_1(i1 %arg) {
786; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
787; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1
788; TUNIT-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4]] {
789; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
790; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
791; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]]
792; TUNIT-NEXT:    ret i1 [[ARG]]
793;
794; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
795; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1
796; CGSCC-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4]] {
797; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
798; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
799; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]]
800; CGSCC-NEXT:    ret i1 [[ARG]]
801;
802  %stack = alloca i1
803  store i1 %arg, ptr %stack
804  %l = load i1, ptr %stack
805  call void @llvm.assume(i1 %l)
806  ret i1 %l
807}
808
809define i1 @keep_assume_2(i1 %arg) {
810; CHECK-LABEL: define {{[^@]+}}@keep_assume_2
811; CHECK-SAME: (i1 [[ARG:%.*]]) {
812; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
813; CHECK-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
814; CHECK-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
815; CHECK-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
816; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[L1]])
817; CHECK-NEXT:    call void @unknown()
818; CHECK-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
819; CHECK-NEXT:    ret i1 [[L2]]
820;
821  %stack = alloca i1
822  store i1 %arg, ptr %stack
823  call void @useI1p(ptr %stack)
824  %l1 = load i1, ptr %stack
825  call void @llvm.assume(i1 %l1)
826  call void @unknown()
827  %l2 = load i1, ptr %stack
828  ret i1 %l2
829}
830
831define i1 @keep_assume_3(i1 %arg) {
832;
833; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3
834; TUNIT-SAME: (i1 [[ARG:%.*]]) {
835; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
836; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
837; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
838; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
839; TUNIT-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
840; TUNIT-NEXT:    ret i1 [[L]]
841;
842; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3
843; CGSCC-SAME: (i1 [[ARG:%.*]]) {
844; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
845; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
846; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
847; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
848; CGSCC-NEXT:    call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]])
849; CGSCC-NEXT:    ret i1 [[L]]
850;
851  %stack = alloca i1
852  store i1 %arg, ptr %stack
853  %l = load i1, ptr %stack
854  call void @llvm.assume(i1 %l)
855  call void @useI1p(ptr %stack)
856  ret i1 %l
857}
858
859define i1 @keep_assume_4(i1 %arg) {
860;
861; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4
862; TUNIT-SAME: (i1 [[ARG:%.*]]) {
863; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
864; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
865; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
866; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
867; TUNIT-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
868; TUNIT-NEXT:    ret i1 [[L]]
869;
870; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4
871; CGSCC-SAME: (i1 [[ARG:%.*]]) {
872; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
873; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
874; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
875; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
876; CGSCC-NEXT:    call void @useI1p(ptr noalias noundef nonnull captures(none) dereferenceable(1) [[STACK]])
877; CGSCC-NEXT:    ret i1 [[L]]
878;
879  %stack = alloca i1
880  store i1 %arg, ptr %stack
881  %l = load i1, ptr %stack
882  call void @llvm.assume(i1 %l)
883  call void @useI1p(ptr nocapture %stack)
884  ret i1 %l
885}
886
887define i1 @assume_1(i1 %arg, i1 %cond) {
888; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
889; TUNIT-LABEL: define {{[^@]+}}@assume_1
890; TUNIT-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
891; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
892; TUNIT-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
893; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]]
894; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
895; TUNIT:       t:
896; TUNIT-NEXT:    br label [[M:%.*]]
897; TUNIT:       f:
898; TUNIT-NEXT:    br label [[M]]
899; TUNIT:       m:
900; TUNIT-NEXT:    ret i1 [[ARG]]
901;
902; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
903; CGSCC-LABEL: define {{[^@]+}}@assume_1
904; CGSCC-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
905; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
906; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
907; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]]
908; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
909; CGSCC:       t:
910; CGSCC-NEXT:    br label [[M:%.*]]
911; CGSCC:       f:
912; CGSCC-NEXT:    br label [[M]]
913; CGSCC:       m:
914; CGSCC-NEXT:    ret i1 [[ARG]]
915;
916  %stack = alloca i1
917  store i1 %arg, ptr %stack
918  %l = load i1, ptr %stack
919  call void @llvm.assume(i1 %l)
920  br i1 %cond, label %t, label %f
921t:
922  store i1 true, ptr %stack
923  br label %m
924f:
925  store i1 false, ptr %stack
926  br label %m
927m:
928  ret i1 %l
929}
930
931define void @assume_1b(i1 %arg, i1 %cond) {
932; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
933; CHECK-LABEL: define {{[^@]+}}@assume_1b
934; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
935; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
936; CHECK:       t:
937; CHECK-NEXT:    br label [[M:%.*]]
938; CHECK:       f:
939; CHECK-NEXT:    br label [[M]]
940; CHECK:       m:
941; CHECK-NEXT:    ret void
942;
943  %stack = alloca i1
944  store i1 %arg, ptr %stack
945  %l = load i1, ptr %stack
946  call void @llvm.assume(i1 %l)
947  br i1 %cond, label %t, label %f
948t:
949  store i1 true, ptr %stack
950  br label %m
951f:
952  store i1 false, ptr %stack
953  br label %m
954m:
955  ret void
956}
957
958define i1 @assume_2(i1 %arg, i1 %cond) {
959; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
960; TUNIT-LABEL: define {{[^@]+}}@assume_2
961; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
962; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
963; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
964; TUNIT:       t:
965; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
966; TUNIT-NEXT:    br label [[M:%.*]]
967; TUNIT:       f:
968; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
969; TUNIT-NEXT:    br label [[M]]
970; TUNIT:       m:
971; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
972; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
973; TUNIT-NEXT:    ret i1 [[L]]
974;
975; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
976; CGSCC-LABEL: define {{[^@]+}}@assume_2
977; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
978; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
979; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
980; CGSCC:       t:
981; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
982; CGSCC-NEXT:    br label [[M:%.*]]
983; CGSCC:       f:
984; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
985; CGSCC-NEXT:    br label [[M]]
986; CGSCC:       m:
987; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
988; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
989; CGSCC-NEXT:    ret i1 [[L]]
990;
991  %stack = alloca i1
992  store i1 %arg, ptr %stack
993  br i1 %cond, label %t, label %f
994t:
995  store i1 true, ptr %stack
996  br label %m
997f:
998  store i1 false, ptr %stack
999  br label %m
1000m:
1001  %l = load i1, ptr %stack
1002  call void @llvm.assume(i1 %l)
1003  ret i1 %l
1004}
1005
1006define void @assume_2b(i1 %arg, i1 %cond) {
1007; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1008; CHECK-LABEL: define {{[^@]+}}@assume_2b
1009; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
1010; CHECK-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1011; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1012; CHECK:       t:
1013; CHECK-NEXT:    br label [[M:%.*]]
1014; CHECK:       f:
1015; CHECK-NEXT:    br label [[M]]
1016; CHECK:       m:
1017; CHECK-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
1018; CHECK-NEXT:    ret void
1019;
1020  %stack = alloca i1
1021  store i1 %arg, ptr %stack
1022  br i1 %cond, label %t, label %f
1023t:
1024  store i1 true, ptr %stack
1025  br label %m
1026f:
1027  store i1 false, ptr %stack
1028  br label %m
1029m:
1030  %l = load i1, ptr %stack
1031  call void @llvm.assume(i1 %l)
1032  ret void
1033}
1034
1035define i1 @assume_3(i1 %arg, i1 %cond) {
1036; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1037; TUNIT-LABEL: define {{[^@]+}}@assume_3
1038; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
1039; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1040; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1041; TUNIT:       t:
1042; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
1043; TUNIT-NEXT:    br label [[M:%.*]]
1044; TUNIT:       f:
1045; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
1046; TUNIT-NEXT:    br label [[M]]
1047; TUNIT:       m:
1048; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8]]
1049; TUNIT-NEXT:    ret i1 [[R]]
1050;
1051; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1052; CGSCC-LABEL: define {{[^@]+}}@assume_3
1053; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR5:[0-9]+]] {
1054; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1055; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
1056; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
1057; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
1058; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1059; CGSCC:       t:
1060; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
1061; CGSCC-NEXT:    br label [[M:%.*]]
1062; CGSCC:       f:
1063; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
1064; CGSCC-NEXT:    br label [[M]]
1065; CGSCC:       m:
1066; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR9]]
1067; CGSCC-NEXT:    ret i1 [[R]]
1068;
1069  %stack = alloca i1
1070  store i1 %arg, ptr %stack
1071  %l = load i1, ptr %stack
1072  call void @llvm.assume(i1 %l)
1073  br i1 %cond, label %t, label %f
1074t:
1075  store i1 true, ptr %stack
1076  br label %m
1077f:
1078  store i1 false, ptr %stack
1079  br label %m
1080m:
1081  %r = call i1 @readI1p(ptr %stack)
1082  ret i1 %r
1083}
1084
1085define i1 @assume_4(i1 %arg, i1 %cond) {
1086; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1087; TUNIT-LABEL: define {{[^@]+}}@assume_4
1088; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
1089; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1090; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1091; TUNIT:       t:
1092; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
1093; TUNIT-NEXT:    br label [[M:%.*]]
1094; TUNIT:       f:
1095; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
1096; TUNIT-NEXT:    br label [[M]]
1097; TUNIT:       m:
1098; TUNIT-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
1099; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]]
1100; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8]]
1101; TUNIT-NEXT:    ret i1 [[R]]
1102;
1103; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1104; CGSCC-LABEL: define {{[^@]+}}@assume_4
1105; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR5]] {
1106; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1107; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
1108; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1109; CGSCC:       t:
1110; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
1111; CGSCC-NEXT:    br label [[M:%.*]]
1112; CGSCC:       f:
1113; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
1114; CGSCC-NEXT:    br label [[M]]
1115; CGSCC:       m:
1116; CGSCC-NEXT:    [[L:%.*]] = load i1, ptr [[STACK]], align 1
1117; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]]
1118; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR9]]
1119; CGSCC-NEXT:    ret i1 [[R]]
1120;
1121  %stack = alloca i1
1122  store i1 %arg, ptr %stack
1123  br i1 %cond, label %t, label %f
1124t:
1125  store i1 true, ptr %stack
1126  br label %m
1127f:
1128  store i1 false, ptr %stack
1129  br label %m
1130m:
1131  %l = load i1, ptr %stack
1132  call void @llvm.assume(i1 %l)
1133  %r = call i1 @readI1p(ptr %stack)
1134  ret i1 %r
1135}
1136
1137define i1 @assume_5(i1 %arg, i1 %cond) {
1138; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1139; TUNIT-LABEL: define {{[^@]+}}@assume_5
1140; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] {
1141; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1142; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1143; TUNIT:       t:
1144; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
1145; TUNIT-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
1146; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]]
1147; TUNIT-NEXT:    br label [[M:%.*]]
1148; TUNIT:       f:
1149; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
1150; TUNIT-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
1151; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]]
1152; TUNIT-NEXT:    br label [[M]]
1153; TUNIT:       m:
1154; TUNIT-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
1155; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9]]
1156; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8]]
1157; TUNIT-NEXT:    ret i1 [[R]]
1158;
1159; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1160; CGSCC-LABEL: define {{[^@]+}}@assume_5
1161; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR5]] {
1162; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1163; CGSCC-NEXT:    store i1 [[ARG]], ptr [[STACK]], align 1
1164; CGSCC-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
1165; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]]
1166; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1167; CGSCC:       t:
1168; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
1169; CGSCC-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
1170; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10]]
1171; CGSCC-NEXT:    br label [[M:%.*]]
1172; CGSCC:       f:
1173; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
1174; CGSCC-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
1175; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]]
1176; CGSCC-NEXT:    br label [[M]]
1177; CGSCC:       m:
1178; CGSCC-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
1179; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]]
1180; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR10]]
1181; CGSCC-NEXT:    ret i1 [[R]]
1182;
1183  %stack = alloca i1
1184  store i1 %arg, ptr %stack
1185  %l1 = load i1, ptr %stack
1186  call void @llvm.assume(i1 %l1)
1187  br i1 %cond, label %t, label %f
1188t:
1189  store i1 true, ptr %stack
1190  %l2 = load i1, ptr %stack
1191  call void @llvm.assume(i1 %l2)
1192  br label %m
1193f:
1194  store i1 false, ptr %stack
1195  %l3 = load i1, ptr %stack
1196  call void @llvm.assume(i1 %l3)
1197  br label %m
1198m:
1199  %l4 = load i1, ptr %stack
1200  call void @llvm.assume(i1 %l4)
1201  %r = call i1 @readI1p(ptr %stack)
1202  ret i1 %r
1203}
1204
1205define i1 @assume_5c(i1 %cond) {
1206; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1207; TUNIT-LABEL: define {{[^@]+}}@assume_5c
1208; TUNIT-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] {
1209; TUNIT-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1210; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR7]]
1211; TUNIT-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1212; TUNIT:       t:
1213; TUNIT-NEXT:    store i1 true, ptr [[STACK]], align 1
1214; TUNIT-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
1215; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]]
1216; TUNIT-NEXT:    br label [[M:%.*]]
1217; TUNIT:       f:
1218; TUNIT-NEXT:    store i1 false, ptr [[STACK]], align 1
1219; TUNIT-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
1220; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]]
1221; TUNIT-NEXT:    br label [[M]]
1222; TUNIT:       m:
1223; TUNIT-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
1224; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9]]
1225; TUNIT-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR8]]
1226; TUNIT-NEXT:    ret i1 [[R]]
1227;
1228; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite)
1229; CGSCC-LABEL: define {{[^@]+}}@assume_5c
1230; CGSCC-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR5]] {
1231; CGSCC-NEXT:    [[STACK:%.*]] = alloca i1, align 1
1232; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
1233; CGSCC-NEXT:    [[L1:%.*]] = load i1, ptr [[STACK]], align 1
1234; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]]
1235; CGSCC-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[F:%.*]]
1236; CGSCC:       t:
1237; CGSCC-NEXT:    store i1 true, ptr [[STACK]], align 1
1238; CGSCC-NEXT:    [[L2:%.*]] = load i1, ptr [[STACK]], align 1
1239; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10]]
1240; CGSCC-NEXT:    br label [[M:%.*]]
1241; CGSCC:       f:
1242; CGSCC-NEXT:    store i1 false, ptr [[STACK]], align 1
1243; CGSCC-NEXT:    [[L3:%.*]] = load i1, ptr [[STACK]], align 1
1244; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]]
1245; CGSCC-NEXT:    br label [[M]]
1246; CGSCC:       m:
1247; CGSCC-NEXT:    [[L4:%.*]] = load i1, ptr [[STACK]], align 1
1248; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]]
1249; CGSCC-NEXT:    [[R:%.*]] = call i1 @readI1p(ptr noalias nofree noundef nonnull readonly captures(none) dereferenceable(1) [[STACK]]) #[[ATTR10]]
1250; CGSCC-NEXT:    ret i1 [[R]]
1251;
1252  %stack = alloca i1
1253  store i1 true, ptr %stack
1254  %l1 = load i1, ptr %stack
1255  call void @llvm.assume(i1 %l1)
1256  br i1 %cond, label %t, label %f
1257t:
1258  store i1 true, ptr %stack
1259  %l2 = load i1, ptr %stack
1260  call void @llvm.assume(i1 %l2)
1261  br label %m
1262f:
1263  store i1 false, ptr %stack
1264  %l3 = load i1, ptr %stack
1265  call void @llvm.assume(i1 %l3)
1266  br label %m
1267m:
1268  %l4 = load i1, ptr %stack
1269  call void @llvm.assume(i1 %l4)
1270  %r = call i1 @readI1p(ptr %stack)
1271  ret i1 %r
1272}
1273
1274define i32 @assume_read_global_good() {
1275;
1276;
1277; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
1278; TUNIT-LABEL: define {{[^@]+}}@assume_read_global_good
1279; TUNIT-SAME: () #[[ATTR5:[0-9]+]] {
1280; TUNIT-NEXT:    [[LGS1:%.*]] = load i32, ptr @Gstatic_int1, align 4
1281; TUNIT-NEXT:    [[C:%.*]] = icmp eq i32 [[LGS1]], 42
1282; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[C]]) #[[ATTR7]]
1283; TUNIT-NEXT:    [[LGS2:%.*]] = load i32, ptr @Gstatic_int1, align 4
1284; TUNIT-NEXT:    store i32 17, ptr @Gstatic_int1, align 4
1285; TUNIT-NEXT:    [[LGS3:%.*]] = load i32, ptr @Gstatic_int1, align 4
1286; TUNIT-NEXT:    [[ADD:%.*]] = add i32 [[LGS2]], [[LGS3]]
1287; TUNIT-NEXT:    ret i32 [[ADD]]
1288;
1289; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
1290; CGSCC-LABEL: define {{[^@]+}}@assume_read_global_good
1291; CGSCC-SAME: () #[[ATTR6:[0-9]+]] {
1292; CGSCC-NEXT:    [[LGS1:%.*]] = load i32, ptr @Gstatic_int1, align 4
1293; CGSCC-NEXT:    [[C:%.*]] = icmp eq i32 [[LGS1]], 42
1294; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[C]]) #[[ATTR8]]
1295; CGSCC-NEXT:    [[LGS2:%.*]] = load i32, ptr @Gstatic_int1, align 4
1296; CGSCC-NEXT:    store i32 17, ptr @Gstatic_int1, align 4
1297; CGSCC-NEXT:    [[LGS3:%.*]] = load i32, ptr @Gstatic_int1, align 4
1298; CGSCC-NEXT:    [[ADD:%.*]] = add i32 [[LGS2]], [[LGS3]]
1299; CGSCC-NEXT:    ret i32 [[ADD]]
1300;
1301  %lgs1 = load i32, ptr @Gstatic_int1
1302  %c = icmp eq i32 %lgs1, 42
1303  call void @llvm.assume(i1 %c)
1304  %lgs2 = load i32, ptr @Gstatic_int1
1305  store i32 13, ptr @Gstatic_int1, align 4
1306  store i32 17, ptr @Gstatic_int1, align 4
1307  %lgs3 = load i32, ptr @Gstatic_int1
1308  %add = add i32 %lgs2, %lgs3
1309  ret i32 %add
1310}
1311
1312; TODO: Technically we could still utilize the assumption if we employ AA.
1313define i32 @assume_read_global_bad(ptr %p) {
1314;
1315; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
1316; TUNIT-LABEL: define {{[^@]+}}@assume_read_global_bad
1317; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR5]] {
1318; TUNIT-NEXT:    [[LGS1:%.*]] = load i32, ptr @Gstatic_int2, align 4
1319; TUNIT-NEXT:    [[C:%.*]] = icmp eq i32 [[LGS1]], 42
1320; TUNIT-NEXT:    store i32 13, ptr [[P]], align 4
1321; TUNIT-NEXT:    call void @llvm.assume(i1 noundef [[C]]) #[[ATTR7]]
1322; TUNIT-NEXT:    [[LGS2:%.*]] = load i32, ptr @Gstatic_int2, align 4
1323; TUNIT-NEXT:    store i32 17, ptr @Gstatic_int2, align 4
1324; TUNIT-NEXT:    ret i32 [[LGS2]]
1325;
1326; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
1327; CGSCC-LABEL: define {{[^@]+}}@assume_read_global_bad
1328; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR6]] {
1329; CGSCC-NEXT:    [[LGS1:%.*]] = load i32, ptr @Gstatic_int2, align 4
1330; CGSCC-NEXT:    [[C:%.*]] = icmp eq i32 [[LGS1]], 42
1331; CGSCC-NEXT:    store i32 13, ptr [[P]], align 4
1332; CGSCC-NEXT:    call void @llvm.assume(i1 noundef [[C]]) #[[ATTR8]]
1333; CGSCC-NEXT:    [[LGS2:%.*]] = load i32, ptr @Gstatic_int2, align 4
1334; CGSCC-NEXT:    store i32 17, ptr @Gstatic_int2, align 4
1335; CGSCC-NEXT:    ret i32 [[LGS2]]
1336;
1337  %lgs1 = load i32, ptr @Gstatic_int2
1338  %c = icmp eq i32 %lgs1, 42
1339  store i32 13, ptr %p, align 4
1340  call void @llvm.assume(i1 %c)
1341  %lgs2 = load i32, ptr @Gstatic_int2
1342  store i32 17, ptr @Gstatic_int2, align 4
1343  ret i32 %lgs2
1344}
1345
1346define void @assume_write_globals() {
1347;
1348; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
1349; TUNIT-LABEL: define {{[^@]+}}@assume_write_globals
1350; TUNIT-SAME: () #[[ATTR6:[0-9]+]] {
1351; TUNIT-NEXT:    store i32 42, ptr @Gstatic_int1, align 4
1352; TUNIT-NEXT:    store i32 42, ptr @Gstatic_int2, align 4
1353; TUNIT-NEXT:    ret void
1354;
1355; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
1356; CGSCC-LABEL: define {{[^@]+}}@assume_write_globals
1357; CGSCC-SAME: () #[[ATTR7:[0-9]+]] {
1358; CGSCC-NEXT:    store i32 42, ptr @Gstatic_int1, align 4
1359; CGSCC-NEXT:    store i32 42, ptr @Gstatic_int2, align 4
1360; CGSCC-NEXT:    ret void
1361;
1362  store i32 42, ptr @Gstatic_int1, align 4
1363  store i32 42, ptr @Gstatic_int2, align 4
1364  ret void
1365}
1366
1367;.
1368; TUNIT: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
1369; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
1370; TUNIT: attributes #[[ATTR2]] = { norecurse }
1371; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) }
1372; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
1373; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn }
1374; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
1375; TUNIT: attributes #[[ATTR7]] = { nofree willreturn memory(write) }
1376; TUNIT: attributes #[[ATTR8]] = { nofree nosync nounwind willreturn memory(read) }
1377; TUNIT: attributes #[[ATTR9]] = { nofree willreturn }
1378;.
1379; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
1380; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
1381; CGSCC: attributes #[[ATTR2]] = { norecurse }
1382; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) }
1383; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
1384; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
1385; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn }
1386; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
1387; CGSCC: attributes #[[ATTR8]] = { nofree willreturn memory(write) }
1388; CGSCC: attributes #[[ATTR9]] = { nofree willreturn memory(read) }
1389; CGSCC: attributes #[[ATTR10]] = { nofree willreturn }
1390;.
1391