xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/add-nsw.ll (revision 98e016d99732dc8fef8cfd61d6ce1edd042309a1)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4declare void @use(i1)
5declare void @llvm.assume(i1)
6
7define void @test.not.uge.ult(i8 %start, i8 %high) {
8; CHECK-LABEL: @test.not.uge.ult(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = add nsw i8 [[START:%.*]], 3
11; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[ADD_PTR_I]], [[HIGH:%.*]]
12; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
13; CHECK:       if.then:
14; CHECK-NEXT:    ret void
15; CHECK:       if.end:
16; CHECK-NEXT:    [[T_0:%.*]] = icmp ult i8 [[START]], [[HIGH]]
17; CHECK-NEXT:    call void @use(i1 [[T_0]])
18; CHECK-NEXT:    [[START_1:%.*]] = add nsw i8 [[START]], 1
19; CHECK-NEXT:    [[T_1:%.*]] = icmp ult i8 [[START_1]], [[HIGH]]
20; CHECK-NEXT:    call void @use(i1 [[T_1]])
21; CHECK-NEXT:    [[START_2:%.*]] = add nsw i8 [[START]], 2
22; CHECK-NEXT:    [[T_2:%.*]] = icmp ult i8 [[START_2]], [[HIGH]]
23; CHECK-NEXT:    call void @use(i1 [[T_2]])
24; CHECK-NEXT:    [[START_3:%.*]] = add nsw i8 [[START]], 3
25; CHECK-NEXT:    [[T_3:%.*]] = icmp ult i8 [[START_3]], [[HIGH]]
26; CHECK-NEXT:    call void @use(i1 [[T_3]])
27; CHECK-NEXT:    [[START_4:%.*]] = add nsw i8 [[START]], 4
28; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i8 [[START_4]], [[HIGH]]
29; CHECK-NEXT:    call void @use(i1 [[C_4]])
30; CHECK-NEXT:    ret void
31;
32entry:
33  %add.ptr.i = add nsw i8 %start, 3
34  %c.1 = icmp uge i8 %add.ptr.i, %high
35  br i1 %c.1, label %if.then, label %if.end
36
37if.then:                                          ; preds = %entry
38  ret void
39
40if.end:                                           ; preds = %entry
41  %t.0 = icmp ult i8 %start, %high
42  call void @use(i1 %t.0)
43  %start.1 = add nsw i8 %start, 1
44  %t.1 = icmp ult i8 %start.1, %high
45  call void @use(i1 %t.1)
46  %start.2 = add nsw i8 %start, 2
47  %t.2 = icmp ult i8 %start.2, %high
48  call void @use(i1 %t.2)
49  %start.3 = add nsw i8 %start, 3
50  %t.3 = icmp ult i8 %start.3, %high
51  call void @use(i1 %t.3)
52  %start.4 = add nsw i8 %start, 4
53  %c.4 = icmp ult i8 %start.4, %high
54  call void @use(i1 %c.4)
55  ret void
56}
57
58define void @test.not.sge.slt(i8 %start, i8 %high) {
59; CHECK-LABEL: @test.not.sge.slt(
60; CHECK-NEXT:  entry:
61; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = add nsw i8 [[START:%.*]], 3
62; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[ADD_PTR_I]], [[HIGH:%.*]]
63; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
64; CHECK:       if.then:
65; CHECK-NEXT:    ret void
66; CHECK:       if.end:
67; CHECK-NEXT:    call void @use(i1 true)
68; CHECK-NEXT:    [[START_1:%.*]] = add nsw i8 [[START]], 1
69; CHECK-NEXT:    call void @use(i1 true)
70; CHECK-NEXT:    [[START_2:%.*]] = add nsw i8 [[START]], 2
71; CHECK-NEXT:    call void @use(i1 true)
72; CHECK-NEXT:    [[START_3:%.*]] = add nsw i8 [[START]], 3
73; CHECK-NEXT:    call void @use(i1 true)
74; CHECK-NEXT:    [[START_4:%.*]] = add nsw i8 [[START]], 4
75; CHECK-NEXT:    [[C_4:%.*]] = icmp slt i8 [[START_4]], [[HIGH]]
76; CHECK-NEXT:    call void @use(i1 [[C_4]])
77; CHECK-NEXT:    ret void
78;
79entry:
80  %add.ptr.i = add nsw i8 %start, 3
81  %c.1 = icmp sge i8 %add.ptr.i, %high
82  br i1 %c.1, label %if.then, label %if.end
83
84if.then:                                          ; preds = %entry
85  ret void
86
87if.end:                                           ; preds = %entry
88  %t.0 = icmp slt i8 %start, %high
89  call void @use(i1 %t.0)
90  %start.1 = add nsw i8 %start, 1
91  %t.1 = icmp slt i8 %start.1, %high
92  call void @use(i1 %t.1)
93  %start.2 = add nsw i8 %start, 2
94  %t.2 = icmp slt i8 %start.2, %high
95  call void @use(i1 %t.2)
96  %start.3 = add nsw i8 %start, 3
97  %t.3 = icmp slt i8 %start.3, %high
98  call void @use(i1 %t.3)
99  %start.4 = add nsw i8 %start, 4
100  %c.4 = icmp slt i8 %start.4, %high
101  call void @use(i1 %c.4)
102  ret void
103}
104
105define void @test.decompose.nonconst(i8 %a, i8 %b, i8 %c, i8 %d) {
106; CHECK-LABEL: @test.decompose.nonconst(
107; CHECK-NEXT:  entry:
108; CHECK-NEXT:    [[C_0:%.*]] = icmp sge i8 [[A:%.*]], [[C:%.*]]
109; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[C]]
110; CHECK-NEXT:    [[AND_0:%.*]] = and i1 [[C_0]], [[C_1]]
111; CHECK-NEXT:    br i1 [[AND_0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
112; CHECK:       if.then:
113; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[A]], 0
114; CHECK-NEXT:    [[C_3:%.*]] = icmp sge i8 [[B]], 0
115; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[C_2]], [[C_3]]
116; CHECK-NEXT:    br i1 [[AND_1]], label [[IF_THEN_2:%.*]], label [[IF_END]]
117; CHECK:       if.then.2:
118; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i8 [[A]], [[B]]
119; CHECK-NEXT:    call void @use(i1 true)
120; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i8 [[A]], [[A]]
121; CHECK-NEXT:    call void @use(i1 true)
122; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i8 [[A]], [[D:%.*]]
123; CHECK-NEXT:    [[C_4:%.*]] = icmp sge i8 [[ADD_2]], [[C]]
124; CHECK-NEXT:    call void @use(i1 [[C_4]])
125; CHECK-NEXT:    ret void
126; CHECK:       if.end:
127; CHECK-NEXT:    ret void
128;
129entry:
130  %c.0 = icmp sge i8 %a, %c
131  %c.1 = icmp sge i8 %b, %c
132  %and.0 = and i1 %c.0, %c.1
133  br i1 %and.0, label %if.then, label %if.end
134
135if.then:                                          ; preds = %entry
136  %c.2 = icmp sge i8 %a, 0
137  %c.3 = icmp sge i8 %b, 0
138  %and.1 = and i1 %c.2, %c.3
139  br i1 %and.1, label %if.then.2, label %if.end
140
141if.then.2:
142  %add.0 = add nsw i8 %a, %b
143  %t.0 = icmp sge i8 %add.0, %c
144  call void @use(i1 %t.0)
145  %add.1 = add nsw i8 %a, %a
146  %t.1 = icmp sge i8 %add.0, %c
147  call void @use(i1 %t.1)
148  %add.2 = add nsw i8 %a, %d
149  %c.4 = icmp sge i8 %add.2, %c
150  call void @use(i1 %c.4)
151  ret void
152
153if.end:                                           ; preds = %entry
154  ret void
155}
156
157define void @test.decompose.nonconst.no.null.check(i8 %a, i8 %b, i8 %c, i8 %d) {
158; CHECK-LABEL: @test.decompose.nonconst.no.null.check(
159; CHECK-NEXT:  entry:
160; CHECK-NEXT:    [[C_0:%.*]] = icmp sge i8 [[A:%.*]], [[C:%.*]]
161; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[C]]
162; CHECK-NEXT:    [[AND_0:%.*]] = and i1 [[C_0]], [[C_1]]
163; CHECK-NEXT:    br i1 [[AND_0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
164; CHECK:       if.then:
165; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i8 [[A]], [[B]]
166; CHECK-NEXT:    [[T_0:%.*]] = icmp sge i8 [[ADD_0]], [[C]]
167; CHECK-NEXT:    call void @use(i1 [[T_0]])
168; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i8 [[A]], [[A]]
169; CHECK-NEXT:    [[T_1:%.*]] = icmp sge i8 [[ADD_0]], [[C]]
170; CHECK-NEXT:    call void @use(i1 [[T_1]])
171; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i8 [[A]], [[D:%.*]]
172; CHECK-NEXT:    [[C_4:%.*]] = icmp sge i8 [[ADD_2]], [[C]]
173; CHECK-NEXT:    call void @use(i1 [[C_4]])
174; CHECK-NEXT:    ret void
175; CHECK:       if.end:
176; CHECK-NEXT:    ret void
177;
178entry:
179  %c.0 = icmp sge i8 %a, %c
180  %c.1 = icmp sge i8 %b, %c
181  %and.0 = and i1 %c.0, %c.1
182  br i1 %and.0, label %if.then, label %if.end
183
184if.then:                                          ; preds = %entry
185  %add.0 = add nsw i8 %a, %b
186  %t.0 = icmp sge i8 %add.0, %c
187  call void @use(i1 %t.0)
188  %add.1 = add nsw i8 %a, %a
189  %t.1 = icmp sge i8 %add.0, %c
190  call void @use(i1 %t.1)
191  %add.2 = add nsw i8 %a, %d
192  %c.4 = icmp sge i8 %add.2, %c
193  call void @use(i1 %c.4)
194  ret void
195
196if.end:                                           ; preds = %entry
197  ret void
198}
199
200define void @test.sge.slt.add.neg(i8 %start, i8 %high) {
201; CHECK-LABEL: @test.sge.slt.add.neg(
202; CHECK-NEXT:  entry:
203; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = add nsw i8 [[START:%.*]], -3
204; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i8 [[ADD_PTR_I]], [[HIGH:%.*]]
205; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
206; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i8 [[START]], [[HIGH]]
207; CHECK-NEXT:    call void @use(i1 [[C_2]])
208; CHECK-NEXT:    [[START_1:%.*]] = add nsw i8 [[START]], 1
209; CHECK-NEXT:    [[C_3:%.*]] = icmp slt i8 [[START_1]], [[HIGH]]
210; CHECK-NEXT:    call void @use(i1 [[C_3]])
211; CHECK-NEXT:    [[START_2:%.*]] = add nsw i8 [[START]], -2
212; CHECK-NEXT:    [[C_4:%.*]] = icmp slt i8 [[START_2]], [[HIGH]]
213; CHECK-NEXT:    call void @use(i1 [[C_4]])
214; CHECK-NEXT:    [[START_3:%.*]] = add nsw i8 [[START]], -3
215; CHECK-NEXT:    call void @use(i1 true)
216; CHECK-NEXT:    [[START_4:%.*]] = add nsw i8 [[START]], -4
217; CHECK-NEXT:    call void @use(i1 true)
218; CHECK-NEXT:    ret void
219;
220entry:
221  %add.ptr.i = add nsw i8 %start, -3
222  %c.1 = icmp slt i8 %add.ptr.i, %high
223  call void @llvm.assume(i1 %c.1)
224  %c.2 = icmp slt i8 %start, %high
225  call void @use(i1 %c.2)
226  %start.1 = add nsw i8 %start,  1
227  %c.3 = icmp slt i8 %start.1, %high
228  call void @use(i1 %c.3)
229  %start.2 = add nsw i8 %start, -2
230  %c.4 = icmp slt i8 %start.2, %high
231  call void @use(i1 %c.4)
232  %start.3 = add nsw i8 %start, -3
233  %t.1 = icmp slt i8 %start.3, %high
234  call void @use(i1 %t.1)
235  %start.4 = add nsw i8 %start, -4
236  %t.2 = icmp slt i8 %start.4, %high
237  call void @use(i1 %t.2)
238  ret void
239}
240
241define i1 @test_ult_add_nsw_pos_1(i8 %start, i8 %high) {
242; CHECK-LABEL: @test_ult_add_nsw_pos_1(
243; CHECK-NEXT:  entry:
244; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
245; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
246; CHECK-NEXT:    [[ADD_EXT:%.*]] = add nsw i16 [[START_EXT]], 3
247; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
248; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
249; CHECK-NEXT:    ret i1 true
250;
251entry:
252  %high.ext = zext i8 %high to i16
253  %start.ext = zext i8 %start to i16
254  %add.ext = add nsw i16 %start.ext, 3
255  %c.1 = icmp ult i16 %add.ext, %high.ext
256  call void @llvm.assume(i1 %c.1)
257
258  %t = icmp ult i16 %start.ext, %high.ext
259  ret i1 %t
260}
261
262define i1 @test_ult_add_nsw_pos_1_assume_pos(i8 %start, i8 %high) {
263; CHECK-LABEL: @test_ult_add_nsw_pos_1_assume_pos(
264; CHECK-NEXT:  entry:
265; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
266; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
267; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], 3
268; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
269; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
270; CHECK-NEXT:    ret i1 true
271;
272entry:
273  %start.pos = icmp sge i8 %start, 0
274  call void @llvm.assume(i1 %start.pos)
275  %add = add nsw i8 %start, 3
276  %c.1 = icmp ult i8 %add, %high
277  call void @llvm.assume(i1 %c.1)
278
279  %t = icmp ult i8 %start, %high
280  ret i1 %t
281}
282
283define i1 @test_ult_add_nsw_pos_1_no_assume_pos(i8 %start, i8 %high) {
284; CHECK-LABEL: @test_ult_add_nsw_pos_1_no_assume_pos(
285; CHECK-NEXT:  entry:
286; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START:%.*]], 3
287; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
288; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
289; CHECK-NEXT:    [[T:%.*]] = icmp ult i8 [[START]], [[HIGH]]
290; CHECK-NEXT:    ret i1 [[T]]
291;
292entry:
293  %add = add nsw i8 %start, 3
294  %c.1 = icmp ult i8 %add, %high
295  call void @llvm.assume(i1 %c.1)
296
297  %t = icmp ult i8 %start, %high
298  ret i1 %t
299}
300
301define i1 @test_ult_add_nsw_pos_1_cmp_no_ext(i8 %start, i8 %high) {
302; CHECK-LABEL: @test_ult_add_nsw_pos_1_cmp_no_ext(
303; CHECK-NEXT:  entry:
304; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
305; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
306; CHECK-NEXT:    [[ADD_EXT:%.*]] = add nsw i16 [[START_EXT]], 3
307; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
308; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
309; CHECK-NEXT:    ret i1 true
310;
311entry:
312  %high.ext = zext i8 %high to i16
313  %start.ext = zext i8 %start to i16
314  %add.ext = add nsw i16 %start.ext, 3
315  %c.1 = icmp ult i16 %add.ext, %high.ext
316  call void @llvm.assume(i1 %c.1)
317
318  %t = icmp ult i8 %start, %high
319  ret i1 %t
320}
321
322define i1 @test_ult_add_nsw_pos_2(i8 %start, i8 %high) {
323; CHECK-LABEL: @test_ult_add_nsw_pos_2(
324; CHECK-NEXT:  entry:
325; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
326; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
327; CHECK-NEXT:    [[ADD_EXT:%.*]] = add nsw i16 [[START_EXT]], 3
328; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
329; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
330; CHECK-NEXT:    ret i1 false
331;
332entry:
333  %high.ext = zext i8 %high to i16
334  %start.ext = zext i8 %start to i16
335  %add.ext = add nsw i16 %start.ext, 3
336  %c.1 = icmp ult i16 %add.ext, %high.ext
337  call void @llvm.assume(i1 %c.1)
338
339  %f = icmp uge i16 %start.ext, %high.ext
340  ret i1 %f
341}
342
343define i1 @test_ult_add_nsw_pos_2_assume_pos(i8 %start, i8 %high) {
344; CHECK-LABEL: @test_ult_add_nsw_pos_2_assume_pos(
345; CHECK-NEXT:  entry:
346; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
347; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
348; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], 3
349; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
350; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
351; CHECK-NEXT:    ret i1 false
352;
353entry:
354  %start.pos = icmp sge i8 %start, 0
355  call void @llvm.assume(i1 %start.pos)
356  %add = add nsw i8 %start, 3
357  %c.1 = icmp ult i8 %add, %high
358  call void @llvm.assume(i1 %c.1)
359
360  %f = icmp uge i8 %start, %high
361  ret i1 %f
362}
363
364define i1 @test_ult_add_nsw_pos_2_cmp_no_ext(i8 %start, i8 %high) {
365; CHECK-LABEL: @test_ult_add_nsw_pos_2_cmp_no_ext(
366; CHECK-NEXT:  entry:
367; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
368; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
369; CHECK-NEXT:    [[ADD_EXT:%.*]] = add nsw i16 [[START_EXT]], 3
370; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
371; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
372; CHECK-NEXT:    ret i1 false
373;
374entry:
375  %high.ext = zext i8 %high to i16
376  %start.ext = zext i8 %start to i16
377  %add.ext = add nsw i16 %start.ext, 3
378  %c.1 = icmp ult i16 %add.ext, %high.ext
379  call void @llvm.assume(i1 %c.1)
380
381  %c = icmp uge i8 %start, %high
382  ret i1 %c
383}
384
385define i1 @test_ult_add_nsw_pos_3(i8 %start, i8 %high) {
386; CHECK-LABEL: @test_ult_add_nsw_pos_3(
387; CHECK-NEXT:  entry:
388; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
389; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
390; CHECK-NEXT:    [[ADD_EXT:%.*]] = add nsw i16 [[START_EXT]], 3
391; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
392; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
393; CHECK-NEXT:    [[ADD_4:%.*]] = add nsw i16 [[START_EXT]], 4
394; CHECK-NEXT:    [[C:%.*]] = icmp ult i16 [[ADD_4]], [[HIGH_EXT]]
395; CHECK-NEXT:    ret i1 [[C]]
396;
397entry:
398  %high.ext = zext i8 %high to i16
399  %start.ext = zext i8 %start to i16
400  %add.ext = add nsw i16 %start.ext, 3
401  %c.1 = icmp ult i16 %add.ext, %high.ext
402  call void @llvm.assume(i1 %c.1)
403
404  %add.4 = add nsw i16 %start.ext, 4
405  %c = icmp ult i16 %add.4, %high.ext
406  ret i1 %c
407}
408
409define i1 @test_ult_add_nsw_pos_3_assume_pos(i8 %start, i8 %high) {
410; CHECK-LABEL: @test_ult_add_nsw_pos_3_assume_pos(
411; CHECK-NEXT:  entry:
412; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
413; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
414; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], 3
415; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
416; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
417; CHECK-NEXT:    [[ADD_4:%.*]] = add nsw i8 [[START]], 4
418; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_4]], [[HIGH]]
419; CHECK-NEXT:    ret i1 [[C]]
420;
421entry:
422  %start.pos = icmp sge i8 %start, 0
423  call void @llvm.assume(i1 %start.pos)
424  %add = add nsw i8 %start, 3
425  %c.1 = icmp ult i8 %add, %high
426  call void @llvm.assume(i1 %c.1)
427
428  %add.4 = add nsw i8 %start, 4
429  %c = icmp ult i8 %add.4, %high
430  ret i1 %c
431}
432
433define i1 @test_ult_add_nsw_pos_4(i8 %start, i8 %high) {
434; CHECK-LABEL: @test_ult_add_nsw_pos_4(
435; CHECK-NEXT:  entry:
436; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
437; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
438; CHECK-NEXT:    [[ADD_EXT:%.*]] = add nsw i16 [[START_EXT]], 3
439; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
440; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
441; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i16 [[START_EXT]], 2
442; CHECK-NEXT:    ret i1 true
443;
444entry:
445  %high.ext = zext i8 %high to i16
446  %start.ext = zext i8 %start to i16
447  %add.ext = add nsw i16 %start.ext, 3
448  %c.1 = icmp ult i16 %add.ext, %high.ext
449  call void @llvm.assume(i1 %c.1)
450
451  %add.2 = add nsw i16 %start.ext, 2
452  %c = icmp ult i16 %add.2, %high.ext
453  ret i1 %c
454}
455
456define i1 @test_ult_add_nsw_pos_4_assume_pos(i8 %start, i8 %high) {
457; CHECK-LABEL: @test_ult_add_nsw_pos_4_assume_pos(
458; CHECK-NEXT:  entry:
459; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
460; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
461; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], 3
462; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
463; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
464; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i8 [[START]], 2
465; CHECK-NEXT:    ret i1 true
466;
467entry:
468  %start.pos = icmp sge i8 %start, 0
469  call void @llvm.assume(i1 %start.pos)
470  %add = add nsw i8 %start, 3
471  %c.1 = icmp ult i8 %add, %high
472  call void @llvm.assume(i1 %c.1)
473
474  %add.2 = add nsw i8 %start, 2
475  %c = icmp ult i8 %add.2, %high
476  ret i1 %c
477}
478
479define i1 @test_ult_add_nsw_neg_5(i8 %start, i8 %high) {
480; CHECK-LABEL: @test_ult_add_nsw_neg_5(
481; CHECK-NEXT:  entry:
482; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
483; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
484; CHECK-NEXT:    [[ADD_EXT:%.*]] = add nsw i16 [[START_EXT]], 3
485; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
486; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
487; CHECK-NEXT:    [[SUB_2:%.*]] = add nsw i16 [[START_EXT]], -2
488; CHECK-NEXT:    [[C:%.*]] = icmp ult i16 [[SUB_2]], [[HIGH_EXT]]
489; CHECK-NEXT:    ret i1 [[C]]
490;
491entry:
492  %high.ext = zext i8 %high to i16
493  %start.ext = zext i8 %start to i16
494  %add.ext = add nsw i16 %start.ext, 3
495  %c.1 = icmp ult i16 %add.ext, %high.ext
496  call void @llvm.assume(i1 %c.1)
497
498  %sub.2 = add nsw i16 %start.ext, -2
499  %c = icmp ult i16 %sub.2, %high.ext
500  ret i1 %c
501}
502
503define i1 @test_ult_add_nsw_neg_5_assume_pos(i8 %start, i8 %high) {
504; CHECK-LABEL: @test_ult_add_nsw_neg_5_assume_pos(
505; CHECK-NEXT:  entry:
506; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
507; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
508; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], 3
509; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
510; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
511; CHECK-NEXT:    [[SUB_2:%.*]] = add nsw i8 [[START]], -2
512; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[SUB_2]], [[HIGH]]
513; CHECK-NEXT:    ret i1 [[C]]
514;
515entry:
516  %start.pos = icmp sge i8 %start, 0
517  call void @llvm.assume(i1 %start.pos)
518  %add = add nsw i8 %start, 3
519  %c.1 = icmp ult i8 %add, %high
520  call void @llvm.assume(i1 %c.1)
521
522  %sub.2 = add nsw i8 %start, -2
523  %c = icmp ult i8 %sub.2, %high
524  ret i1 %c
525}
526
527define i1 @test_ult_add_no_nsw_pos_6(i8 %start, i8 %high) {
528; CHECK-LABEL: @test_ult_add_no_nsw_pos_6(
529; CHECK-NEXT:  entry:
530; CHECK-NEXT:    [[HIGH_EXT:%.*]] = zext i8 [[HIGH:%.*]] to i16
531; CHECK-NEXT:    [[START_EXT:%.*]] = zext i8 [[START:%.*]] to i16
532; CHECK-NEXT:    [[ADD_EXT:%.*]] = add i16 [[START_EXT]], 3
533; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
534; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
535; CHECK-NEXT:    [[ADD_2:%.*]] = add i16 [[START_EXT]], 2
536; CHECK-NEXT:    [[C:%.*]] = icmp ult i16 [[ADD_2]], [[HIGH_EXT]]
537; CHECK-NEXT:    ret i1 [[C]]
538;
539entry:
540  %high.ext = zext i8 %high to i16
541  %start.ext = zext i8 %start to i16
542  %add.ext = add i16 %start.ext, 3
543  %c.1 = icmp ult i16 %add.ext, %high.ext
544  call void @llvm.assume(i1 %c.1)
545
546  %add.2 = add i16 %start.ext, 2
547  %c = icmp ult i16 %add.2, %high.ext
548  ret i1 %c
549}
550
551define i1 @test_ult_add_no_nsw_pos_6_assume_pos(i8 %start, i8 %high) {
552; CHECK-LABEL: @test_ult_add_no_nsw_pos_6_assume_pos(
553; CHECK-NEXT:  entry:
554; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
555; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
556; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[START]], 3
557; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
558; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
559; CHECK-NEXT:    [[ADD_2:%.*]] = add i8 [[START]], 2
560; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_2]], [[HIGH]]
561; CHECK-NEXT:    ret i1 [[C]]
562;
563entry:
564  %start.pos = icmp sge i8 %start, 0
565  call void @llvm.assume(i1 %start.pos)
566  %add = add i8 %start, 3
567  %c.1 = icmp ult i8 %add, %high
568  call void @llvm.assume(i1 %c.1)
569
570  %add.2 = add i8 %start, 2
571  %c = icmp ult i8 %add.2, %high
572  ret i1 %c
573}
574
575define i1 @test_ult_add_nsw_var_7(i8 %start, i8 %off, i8 %high) {
576; CHECK-LABEL: @test_ult_add_nsw_var_7(
577; CHECK-NEXT:  entry:
578; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START:%.*]], [[OFF:%.*]]
579; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
580; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
581; CHECK-NEXT:    [[OFF_POS:%.*]] = icmp sge i8 [[OFF]], 0
582; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_POS]])
583; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[START]], [[HIGH]]
584; CHECK-NEXT:    ret i1 [[C]]
585;
586entry:
587  %add = add nsw i8 %start, %off
588  %c.1 = icmp ult i8 %add, %high
589  call void @llvm.assume(i1 %c.1)
590  %off.pos = icmp sge i8 %off, 0
591  call void @llvm.assume(i1 %off.pos)
592
593  %c = icmp ult i8 %start, %high
594  ret i1 %c
595}
596
597define i1 @test_ult_add_no_nsw_var_7(i8 %start, i8 %off, i8 %high) {
598; CHECK-LABEL: @test_ult_add_no_nsw_var_7(
599; CHECK-NEXT:  entry:
600; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[START:%.*]], [[OFF:%.*]]
601; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
602; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
603; CHECK-NEXT:    [[OFF_POS:%.*]] = icmp sge i8 [[OFF]], 0
604; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_POS]])
605; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[START]], [[HIGH]]
606; CHECK-NEXT:    ret i1 [[C]]
607;
608entry:
609  %add = add i8 %start, %off
610  %c.1 = icmp ult i8 %add, %high
611  call void @llvm.assume(i1 %c.1)
612  %off.pos = icmp sge i8 %off, 0
613  call void @llvm.assume(i1 %off.pos)
614
615  %c = icmp ult i8 %start, %high
616  ret i1 %c
617}
618
619define i1 @test_ult_add_nsw_var_8(i8 %start, i8 %off.1, i8 %off.2, i8 %high) {
620; CHECK-LABEL: @test_ult_add_nsw_var_8(
621; CHECK-NEXT:  entry:
622; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START:%.*]], [[OFF_2:%.*]]
623; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
624; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
625; CHECK-NEXT:    [[OFF_1_POS:%.*]] = icmp sge i8 [[OFF_1:%.*]], 0
626; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_POS]])
627; CHECK-NEXT:    [[OFF_2_POS:%.*]] = icmp sge i8 [[OFF_2]], 0
628; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_2_POS]])
629; CHECK-NEXT:    [[OFF_1_ULT:%.*]] = icmp ult i8 [[OFF_1]], [[OFF_2]]
630; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_ULT]])
631; CHECK-NEXT:    [[ADD_OFF_2:%.*]] = add nsw i8 [[START]], [[OFF_1]]
632; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_OFF_2]], [[HIGH]]
633; CHECK-NEXT:    ret i1 [[C]]
634;
635entry:
636  %add = add nsw i8 %start, %off.2
637  %c.1 = icmp ult i8 %add, %high
638  call void @llvm.assume(i1 %c.1)
639  %off.1.pos = icmp sge i8 %off.1, 0
640  call void @llvm.assume(i1 %off.1.pos)
641  %off.2.pos = icmp sge i8 %off.2, 0
642  call void @llvm.assume(i1 %off.2.pos)
643  %off.1.ult = icmp ult i8 %off.1, %off.2
644  call void @llvm.assume(i1 %off.1.ult)
645
646  %add.off.2 = add nsw i8 %start, %off.1
647  %c = icmp ult i8 %add.off.2, %high
648  ret i1 %c
649}
650
651define i1 @test_ult_add_nsw_var_8_all_pos(i8 %start, i8 %off.1, i8 %off.2, i8 %high) {
652; CHECK-LABEL: @test_ult_add_nsw_var_8_all_pos(
653; CHECK-NEXT:  entry:
654; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
655; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
656; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], [[OFF_2:%.*]]
657; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
658; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
659; CHECK-NEXT:    [[OFF_1_POS:%.*]] = icmp sge i8 [[OFF_1:%.*]], 0
660; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_POS]])
661; CHECK-NEXT:    [[OFF_2_POS:%.*]] = icmp sge i8 [[OFF_2]], 0
662; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_2_POS]])
663; CHECK-NEXT:    [[OFF_1_ULT:%.*]] = icmp ult i8 [[OFF_1]], [[OFF_2]]
664; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_ULT]])
665; CHECK-NEXT:    [[ADD_OFF_2:%.*]] = add nsw i8 [[START]], [[OFF_1]]
666; CHECK-NEXT:    ret i1 true
667;
668entry:
669  %start.pos = icmp sge i8 %start, 0
670  call void @llvm.assume(i1 %start.pos)
671  %add = add nsw i8 %start, %off.2
672  %c.1 = icmp ult i8 %add, %high
673  call void @llvm.assume(i1 %c.1)
674  %off.1.pos = icmp sge i8 %off.1, 0
675  call void @llvm.assume(i1 %off.1.pos)
676  %off.2.pos = icmp sge i8 %off.2, 0
677  call void @llvm.assume(i1 %off.2.pos)
678  %off.1.ult = icmp ult i8 %off.1, %off.2
679  call void @llvm.assume(i1 %off.1.ult)
680
681  %add.off.2 = add nsw i8 %start, %off.1
682  %c = icmp ult i8 %add.off.2, %high
683  ret i1 %c
684}
685
686define i1 @test_ult_add_no_nsw_var_8_all_pos(i8 %start, i8 %off.1, i8 %off.2, i8 %high) {
687; CHECK-LABEL: @test_ult_add_no_nsw_var_8_all_pos(
688; CHECK-NEXT:  entry:
689; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
690; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
691; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[START]], [[OFF_2:%.*]]
692; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
693; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
694; CHECK-NEXT:    [[OFF_1_POS:%.*]] = icmp sge i8 [[OFF_1:%.*]], 0
695; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_POS]])
696; CHECK-NEXT:    [[OFF_2_POS:%.*]] = icmp sge i8 [[OFF_2]], 0
697; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_2_POS]])
698; CHECK-NEXT:    [[OFF_1_ULT:%.*]] = icmp ult i8 [[OFF_1]], [[OFF_2]]
699; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_ULT]])
700; CHECK-NEXT:    [[ADD_OFF_2:%.*]] = add nsw i8 [[START]], [[OFF_1]]
701; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_OFF_2]], [[HIGH]]
702; CHECK-NEXT:    ret i1 [[C]]
703;
704entry:
705  %start.pos = icmp sge i8 %start, 0
706  call void @llvm.assume(i1 %start.pos)
707  %add = add i8 %start, %off.2
708  %c.1 = icmp ult i8 %add, %high
709  call void @llvm.assume(i1 %c.1)
710  %off.1.pos = icmp sge i8 %off.1, 0
711  call void @llvm.assume(i1 %off.1.pos)
712  %off.2.pos = icmp sge i8 %off.2, 0
713  call void @llvm.assume(i1 %off.2.pos)
714  %off.1.ult = icmp ult i8 %off.1, %off.2
715  call void @llvm.assume(i1 %off.1.ult)
716
717  %add.off.2 = add nsw i8 %start, %off.1
718  %c = icmp ult i8 %add.off.2, %high
719  ret i1 %c
720}
721
722define i1 @test_ult_add_nsw_var_9_all_pos(i8 %start, i8 %off.1, i8 %off.2, i8 %high) {
723; CHECK-LABEL: @test_ult_add_nsw_var_9_all_pos(
724; CHECK-NEXT:  entry:
725; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
726; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
727; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], [[OFF_2:%.*]]
728; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
729; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
730; CHECK-NEXT:    [[OFF_1_POS:%.*]] = icmp sge i8 [[OFF_1:%.*]], 0
731; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_POS]])
732; CHECK-NEXT:    [[OFF_2_POS:%.*]] = icmp sge i8 [[OFF_2]], 0
733; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_2_POS]])
734; CHECK-NEXT:    [[ADD_OFF_2:%.*]] = add nsw i8 [[START]], [[OFF_1]]
735; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_OFF_2]], [[HIGH]]
736; CHECK-NEXT:    ret i1 [[C]]
737;
738entry:
739  %start.pos = icmp sge i8 %start, 0
740  call void @llvm.assume(i1 %start.pos)
741  %add = add nsw i8 %start, %off.2
742  %c.1 = icmp ult i8 %add, %high
743  call void @llvm.assume(i1 %c.1)
744  %off.1.pos = icmp sge i8 %off.1, 0
745  call void @llvm.assume(i1 %off.1.pos)
746  %off.2.pos = icmp sge i8 %off.2, 0
747  call void @llvm.assume(i1 %off.2.pos)
748
749  %add.off.2 = add nsw i8 %start, %off.1
750  %c = icmp ult i8 %add.off.2, %high
751  ret i1 %c
752}
753
754define i1 @add_neg_1_known_sge_ult_1(i32 %a) {
755; CHECK-LABEL: @add_neg_1_known_sge_ult_1(
756; CHECK-NEXT:  entry:
757; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 1
758; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
759; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -1
760; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[SUB]], [[A]]
761; CHECK-NEXT:    ret i1 [[C]]
762;
763entry:
764  %a.sge = icmp sge i32 %a, 1
765  call void @llvm.assume(i1 %a.sge)
766  %sub = add nsw i32 %a, -1
767  %c = icmp ult i32 %sub, %a
768  ret i1 %c
769}
770
771define i1 @add_neg_1_known_sge_uge_1(i32 %a) {
772; CHECK-LABEL: @add_neg_1_known_sge_uge_1(
773; CHECK-NEXT:  entry:
774; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 1
775; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
776; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -1
777; CHECK-NEXT:    ret i1 true
778;
779entry:
780  %a.sge = icmp sge i32 %a, 1
781  call void @llvm.assume(i1 %a.sge)
782  %sub = add nsw i32 %a, -1
783  %c = icmp uge i32 %sub, 0
784  ret i1 %c
785}
786
787define i1 @add_neg_1_not_known_sge_ult_1(i32 %a) {
788; CHECK-LABEL: @add_neg_1_not_known_sge_ult_1(
789; CHECK-NEXT:  entry:
790; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 0
791; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
792; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -1
793; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[SUB]], [[A]]
794; CHECK-NEXT:    ret i1 [[C]]
795;
796entry:
797  %a.sge = icmp sge i32 %a, 0
798  call void @llvm.assume(i1 %a.sge)
799  %sub = add nsw i32 %a, -1
800  %c = icmp ult i32 %sub, %a
801  ret i1 %c
802}
803
804define i1 @add_neg_1_not_known_sge_uge_1(i32 %a) {
805; CHECK-LABEL: @add_neg_1_not_known_sge_uge_1(
806; CHECK-NEXT:  entry:
807; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 0
808; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
809; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -1
810; CHECK-NEXT:    ret i1 true
811;
812entry:
813  %a.sge = icmp sge i32 %a, 0
814  call void @llvm.assume(i1 %a.sge)
815  %sub = add nsw i32 %a, -1
816  %c = icmp uge i32 %sub, 0
817  ret i1 %c
818}
819
820define i1 @add_neg_3_known_sge_ult_1(i32 %a) {
821; CHECK-LABEL: @add_neg_3_known_sge_ult_1(
822; CHECK-NEXT:  entry:
823; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 3
824; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
825; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -3
826; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[SUB]], [[A]]
827; CHECK-NEXT:    ret i1 [[C]]
828;
829entry:
830  %a.sge = icmp sge i32 %a, 3
831  call void @llvm.assume(i1 %a.sge)
832  %sub = add nsw i32 %a, -3
833  %c = icmp ult i32 %sub, %a
834  ret i1 %c
835}
836
837define i1 @add_neg_3_known_sge_uge_1(i32 %a) {
838; CHECK-LABEL: @add_neg_3_known_sge_uge_1(
839; CHECK-NEXT:  entry:
840; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 4
841; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
842; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -3
843; CHECK-NEXT:    ret i1 true
844;
845entry:
846  %a.sge = icmp sge i32 %a, 4
847  call void @llvm.assume(i1 %a.sge)
848  %sub = add nsw i32 %a, -3
849  %c = icmp uge i32 %sub, 0
850  ret i1 %c
851}
852
853define i1 @add_neg_3_not_known_sge_ult_1(i32 %a) {
854; CHECK-LABEL: @add_neg_3_not_known_sge_ult_1(
855; CHECK-NEXT:  entry:
856; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 2
857; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
858; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -3
859; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[SUB]], [[A]]
860; CHECK-NEXT:    ret i1 [[C]]
861;
862entry:
863  %a.sge = icmp sge i32 %a, 2
864  call void @llvm.assume(i1 %a.sge)
865  %sub = add nsw i32 %a, -3
866  %c = icmp ult i32 %sub, %a
867  ret i1 %c
868}
869
870define i1 @add_neg_3_not_known_sge_uge_1(i32 %a) {
871; CHECK-LABEL: @add_neg_3_not_known_sge_uge_1(
872; CHECK-NEXT:  entry:
873; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], 2
874; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
875; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -3
876; CHECK-NEXT:    ret i1 true
877;
878entry:
879  %a.sge = icmp sge i32 %a, 2
880  call void @llvm.assume(i1 %a.sge)
881  %sub = add nsw i32 %a, -3
882  %c = icmp uge i32 %sub, 0
883  ret i1 %c
884}
885
886define i1 @add_neg_3_not_known_sge_ult_2(i32 %a, i32 %b) {
887; CHECK-LABEL: @add_neg_3_not_known_sge_ult_2(
888; CHECK-NEXT:  entry:
889; CHECK-NEXT:    [[A_SGE:%.*]] = icmp sge i32 [[A:%.*]], [[B:%.*]]
890; CHECK-NEXT:    call void @llvm.assume(i1 [[A_SGE]])
891; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[A]], -3
892; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[SUB]], [[A]]
893; CHECK-NEXT:    ret i1 [[C]]
894;
895entry:
896  %a.sge = icmp sge i32 %a, %b
897  call void @llvm.assume(i1 %a.sge)
898  %sub = add nsw i32 %a, -3
899  %c = icmp ult i32 %sub, %a
900  ret i1 %c
901}
902