xref: /llvm-project/llvm/test/Transforms/GuardWidening/range-check-merging.ll (revision 0e0ff8573de69286536e4f49098226eda0c4c7f5)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=guard-widening < %s | FileCheck %s
3
4declare void @llvm.experimental.guard(i1,...)
5
6define void @f_0(i32 %x, ptr %length_buf) {
7; CHECK-LABEL: @f_0(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
10; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0:![0-9]+]], !noundef !1
11; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
12; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
13; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
14; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
15; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
16; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
17; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]]
18; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
19; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
20; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]]
21; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
22; CHECK-NEXT:    ret void
23;
24entry:
25  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
26  %chk0 = icmp ult i32 %x, %length
27  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
28
29  %x.inc1 = add i32 %x, 1
30  %chk1 = icmp ult i32 %x.inc1, %length
31  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
32
33  %x.inc2 = add i32 %x, 2
34  %chk2 = icmp ult i32 %x.inc2, %length
35  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
36
37  %x.inc3 = add i32 %x, 3
38  %chk3 = icmp ult i32 %x.inc3, %length
39  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
40  ret void
41}
42
43define void @f_1(i32 %x, ptr %length_buf) {
44; CHECK-LABEL: @f_1(
45; CHECK-NEXT:  entry:
46; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
47; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
48; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
49; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
50; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
51; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
52; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_INC1]], 2
53; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
54; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]]
55; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_INC2]], 3
56; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
57; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]]
58; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
59; CHECK-NEXT:    ret void
60;
61entry:
62  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
63  %chk0 = icmp ult i32 %x, %length
64  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
65
66  %x.inc1 = add i32 %x, 1
67  %chk1 = icmp ult i32 %x.inc1, %length
68  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
69
70  %x.inc2 = add i32 %x.inc1, 2
71  %chk2 = icmp ult i32 %x.inc2, %length
72  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
73
74  %x.inc3 = add i32 %x.inc2, 3
75  %chk3 = icmp ult i32 %x.inc3, %length
76  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
77  ret void
78}
79
80define void @f_2(i32 %a, ptr %length_buf) {
81; CHECK-LABEL: @f_2(
82; CHECK-NEXT:  entry:
83; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
84; CHECK-NEXT:    [[X:%.*]] = and i32 [[A_GW_FR]], -256
85; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
86; CHECK-NEXT:    [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]]
87; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH_GW_FR]]
88; CHECK-NEXT:    [[X_INC1:%.*]] = or i32 [[X]], 1
89; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]]
90; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
91; CHECK-NEXT:    [[X_INC2:%.*]] = or i32 [[X]], 2
92; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_GW_FR]]
93; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]]
94; CHECK-NEXT:    [[X_INC3:%.*]] = or i32 [[X]], 3
95; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_GW_FR]]
96; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[CHK3]]
97; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
98; CHECK-NEXT:    ret void
99;
100entry:
101  %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00
102  %length = load i32, ptr %length_buf, !range !0
103  %chk0 = icmp ult i32 %x, %length
104  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
105
106  %x.inc1 = or i32 %x, 1
107  %chk1 = icmp ult i32 %x.inc1, %length
108  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
109
110  %x.inc2 = or i32 %x, 2
111  %chk2 = icmp ult i32 %x.inc2, %length
112  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
113
114  %x.inc3 = or i32 %x, 3
115  %chk3 = icmp ult i32 %x.inc3, %length
116  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
117  ret void
118}
119
120define void @f_3(i32 %a, ptr %length_buf) {
121; CHECK-LABEL: @f_3(
122; CHECK-NEXT:  entry:
123; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
124; CHECK-NEXT:    [[X:%.*]] = and i32 [[A_GW_FR]], -256
125; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
126; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH]]
127; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], 1
128; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
129; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
130; CHECK-NEXT:    [[X_INC2:%.*]] = or i32 [[X_INC1]], 2
131; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
132; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]]
133; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_INC2]], 3
134; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
135; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]]
136; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
137; CHECK-NEXT:    ret void
138;
139entry:
140  %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00
141  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
142  %chk0 = icmp ult i32 %x, %length
143  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
144
145  %x.inc1 = add i32 %x, 1
146  %chk1 = icmp ult i32 %x.inc1, %length
147  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
148
149  %x.inc2 = or i32 %x.inc1, 2
150  %chk2 = icmp ult i32 %x.inc2, %length
151  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
152
153  %x.inc3 = add i32 %x.inc2, 3
154  %chk3 = icmp ult i32 %x.inc3, %length
155  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
156  ret void
157}
158
159define void @f_4(i32 %x, ptr %length_buf) {
160; CHECK-LABEL: @f_4(
161; CHECK-NEXT:  entry:
162; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
163; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
164; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
165; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -1024
166; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
167; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
168; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
169; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
170; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK1]]
171; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
172; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
173; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK1]]
174; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
175; CHECK-NEXT:    ret void
176;
177
178; Note: we NOT guarding on "and i1 %chk3, %chk0", that would be incorrect.
179entry:
180  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
181  %chk0 = icmp ult i32 %x, %length
182  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
183
184  %x.inc1 = add i32 %x, -1024
185  %chk1 = icmp ult i32 %x.inc1, %length
186  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
187
188  %x.inc2 = add i32 %x, 2
189  %chk2 = icmp ult i32 %x.inc2, %length
190  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
191
192  %x.inc3 = add i32 %x, 3
193  %chk3 = icmp ult i32 %x.inc3, %length
194  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
195  ret void
196}
197
198define void @f_5(i32 %x, ptr %length_buf) {
199; CHECK-LABEL: @f_5(
200; CHECK-NEXT:  entry:
201; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
202; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
203; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
204; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
205; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
206; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
207; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_INC1]], -200
208; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
209; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK1]], [[CHK2]]
210; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK1]], [[CHK2]]
211; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
212; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_INC2]], 3
213; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
214; CHECK-NEXT:    ret void
215;
216entry:
217  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
218  %chk0 = icmp ult i32 %x, %length
219  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
220
221  %x.inc1 = add i32 %x, 1
222  %chk1 = icmp ult i32 %x.inc1, %length
223  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
224
225  %x.inc2 = add i32 %x.inc1, -200
226  %chk2 = icmp ult i32 %x.inc2, %length
227  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
228
229  %x.inc3 = add i32 %x.inc2, 3
230  %chk3 = icmp ult i32 %x.inc3, %length
231  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
232  ret void
233}
234
235
236; Negative test: we can't merge these checks into
237;
238;  (%x + -2147483647) u< L && (%x + 3) u< L
239;
240; because if %length == INT_MAX and %x == -3 then
241;
242; (%x + -2147483647) == i32 2147483646  u< L   (L is 2147483647)
243; (%x + 3) == 0 u< L
244;
245; But (%x + 2) == -1 is not u< L
246;
247define void @f_6(i32 %x, ptr %length_buf) {
248; CHECK-LABEL: @f_6(
249; CHECK-NEXT:  entry:
250; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
251; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
252; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
253; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -2147483647
254; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
255; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
256; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
257; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
258; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]]
259; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
260; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
261; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[CHK3]]
262; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
263; CHECK-NEXT:    ret void
264;
265entry:
266  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
267  %chk0 = icmp ult i32 %x, %length
268  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
269
270  %x.inc1 = add i32 %x, -2147483647 ;; -2147483647 == (i32 INT_MIN)+1 == -(i32 INT_MAX)
271  %chk1 = icmp ult i32 %x.inc1, %length
272  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
273
274  %x.inc2 = add i32 %x, 2
275  %chk2 = icmp ult i32 %x.inc2, %length
276  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
277
278  %x.inc3 = add i32 %x, 3
279  %chk3 = icmp ult i32 %x.inc3, %length
280  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
281  ret void
282}
283
284
285define void @f_7(i32 %x, ptr %length_buf) {
286; CHECK-LABEL: @f_7(
287; CHECK-NEXT:  entry:
288; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
289; CHECK-NEXT:    [[LENGTH_A:%.*]] = load volatile i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
290; CHECK-NEXT:    [[LENGTH_B:%.*]] = load volatile i32, ptr [[LENGTH_BUF]], align 4, !range [[RNG0]], !noundef !1
291; CHECK-NEXT:    [[CHK0_A:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_A]]
292; CHECK-NEXT:    [[CHK0_B:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_B]]
293; CHECK-NEXT:    [[CHK0:%.*]] = and i1 [[CHK0_A]], [[CHK0_B]]
294; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
295; CHECK-NEXT:    [[CHK1_B:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_B]]
296; CHECK-NEXT:    [[CHK1_A:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_A]]
297; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[CHK1_B]], [[CHK1_A]]
298; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[TMP0]]
299; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
300; CHECK-NEXT:    [[CHK2_A:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_A]]
301; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[CHK2_A]], [[CHK0_A]]
302; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[CHK0_B]], [[TMP1]]
303; CHECK-NEXT:    [[CHK2_B:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_B]]
304; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2_B]], [[TMP2]]
305; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
306; CHECK-NEXT:    [[CHK3_A:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_A]]
307; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[CHK3_A]], [[CHK0_A]]
308; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[CHK0_B]], [[TMP3]]
309; CHECK-NEXT:    [[CHK3_B:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_B]]
310; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3_B]], [[TMP4]]
311; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
312; CHECK-NEXT:    [[CHK1:%.*]] = and i1 [[CHK1_A]], [[CHK1_B]]
313; CHECK-NEXT:    [[CHK2:%.*]] = and i1 [[CHK2_A]], [[CHK2_B]]
314; CHECK-NEXT:    [[CHK3:%.*]] = and i1 [[CHK3_A]], [[CHK3_B]]
315; CHECK-NEXT:    ret void
316;
317
318
319entry:
320  %length_a = load volatile i32, ptr %length_buf, !range !0, !noundef !{}
321  %length_b = load volatile i32, ptr %length_buf, !range !0, !noundef !{}
322  %chk0.a = icmp ult i32 %x, %length_a
323  %chk0.b = icmp ult i32 %x, %length_b
324  %chk0 = and i1 %chk0.a, %chk0.b
325  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
326
327  %x.inc1 = add i32 %x, 1
328  %chk1.a = icmp ult i32 %x.inc1, %length_a
329  %chk1.b = icmp ult i32 %x.inc1, %length_b
330  %chk1 = and i1 %chk1.a, %chk1.b
331  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
332
333  %x.inc2 = add i32 %x, 2
334  %chk2.a = icmp ult i32 %x.inc2, %length_a
335  %chk2.b = icmp ult i32 %x.inc2, %length_b
336  %chk2 = and i1 %chk2.a, %chk2.b
337  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
338
339  %x.inc3 = add i32 %x, 3
340  %chk3.a = icmp ult i32 %x.inc3, %length_a
341  %chk3.b = icmp ult i32 %x.inc3, %length_b
342  %chk3 = and i1 %chk3.a, %chk3.b
343  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
344  ret void
345}
346
347define void @f_8(i32 %x, ptr %length_buf) {
348; Check that we clean nuw nsw flags
349; CHECK-LABEL: @f_8(
350; CHECK-NEXT:  entry:
351; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
352; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
353; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
354; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
355; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
356; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
357; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
358; CHECK-NEXT:    ret void
359;
360entry:
361  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
362  %chk0 = icmp ult i32 %x, %length
363  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
364
365  %x.inc1 = add nuw nsw i32 %x, 1
366  %chk1 = icmp ult i32 %x.inc1, %length
367  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
368  ret void
369}
370
371
372
373!0 = !{i32 0, i32 2147483648}
374