xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/transfer-signed-facts-to-unsigned.ll (revision ba0e871db81d8527382a051a0abf1ce2a171d8bf)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4define i1 @len_known_positive_via_idx_1(i8 %len, i8 %idx) {
5; CHECK-LABEL: @len_known_positive_via_idx_1(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i8 [[IDX:%.*]], 0
8; CHECK-NEXT:    [[IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX]], [[LEN:%.*]]
9; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[IDX_POS]], [[IDX_SLT_LEN]]
10; CHECK-NEXT:    br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
11; CHECK:       then.1:
12; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[LEN]], 2
13; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[LEN]], 2
14; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
15; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
16; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[C_2]]
17; CHECK-NEXT:    ret i1 [[RES_3]]
18; CHECK:       else:
19; CHECK-NEXT:    ret i1 false
20;
21entry:
22  %idx.pos = icmp sge i8 %idx, 0
23  %idx.slt.len  = icmp slt i8 %idx, %len
24  %and.1 = and i1 %idx.pos, %idx.slt.len
25  br i1 %and.1, label %then.1, label %else
26
27then.1:
28  %t.1 = icmp ult i8 %idx, %len
29  %t.2 = icmp sge i8 %len, 0
30  %c.1 = icmp sge i8 %len, 2
31  %c.2 = icmp sge i8 %len, 2
32  %res.1 = xor i1 %t.1, %t.2
33  %res.2 = xor i1 %res.1, %c.1
34  %res.3 = xor i1 %res.2, %c.2
35  ret i1 %res.3
36
37else:
38  ret i1 0
39}
40
41define i1 @len_known_positive_via_idx_2(i8 %len, i8 %idx) {
42; CHECK-LABEL: @len_known_positive_via_idx_2(
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    [[IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN:%.*]]
45; CHECK-NEXT:    [[IDX_POS:%.*]] = icmp sge i8 [[IDX]], 0
46; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[IDX_SLT_LEN]], [[IDX_POS]]
47; CHECK-NEXT:    br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
48; CHECK:       then.1:
49; CHECK-NEXT:    [[C_1:%.*]] = icmp sge i8 [[LEN]], 2
50; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[LEN]], 2
51; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
52; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
53; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[C_2]]
54; CHECK-NEXT:    ret i1 [[RES_3]]
55; CHECK:       else:
56; CHECK-NEXT:    ret i1 false
57;
58entry:
59  %idx.slt.len  = icmp slt i8 %idx, %len
60  %idx.pos = icmp sge i8 %idx, 0
61  %and.1 = and i1 %idx.slt.len, %idx.pos
62  br i1 %and.1, label %then.1, label %else
63
64then.1:
65  %t.1 = icmp ult i8 %idx, %len
66  %t.2 = icmp sge i8 %len, 0
67  %c.1 = icmp sge i8 %len, 2
68  %c.2 = icmp sge i8 %len, 2
69  %res.1 = xor i1 %t.1, %t.2
70  %res.2 = xor i1 %res.1, %c.1
71  %res.3 = xor i1 %res.2, %c.2
72  ret i1 %res.3
73
74else:
75  ret i1 0
76}
77
78define i1 @len_not_known_positive1(i8 %len, i8 %idx) {
79; CHECK-LABEL: @len_not_known_positive1(
80; CHECK-NEXT:  entry:
81; CHECK-NEXT:    [[IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN:%.*]]
82; CHECK-NEXT:    br i1 [[IDX_SLT_LEN]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
83; CHECK:       then.1:
84; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[IDX]], [[LEN]]
85; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[LEN]], 0
86; CHECK-NEXT:    [[C_3:%.*]] = icmp sge i8 [[LEN]], 2
87; CHECK-NEXT:    [[C_4:%.*]] = icmp sge i8 [[LEN]], 2
88; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]]
89; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_3]]
90; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[C_4]]
91; CHECK-NEXT:    ret i1 [[RES_3]]
92; CHECK:       else:
93; CHECK-NEXT:    ret i1 false
94;
95entry:
96  %idx.slt.len  = icmp slt i8 %idx, %len
97  br i1 %idx.slt.len, label %then.1, label %else
98
99then.1:
100  %c.1 = icmp ult i8 %idx, %len
101  %c.2 = icmp sge i8 %len, 0
102  %c.3 = icmp sge i8 %len, 2
103  %c.4 = icmp sge i8 %len, 2
104  %res.1 = xor i1 %c.1, %c.2
105  %res.2 = xor i1 %res.1, %c.3
106  %res.3 = xor i1 %res.2, %c.4
107  ret i1 %res.3
108
109else:
110  ret i1 0
111}
112
113define i1 @len_not_known_positive2(i8 %len, i8 %idx) {
114; CHECK-LABEL: @len_not_known_positive2(
115; CHECK-NEXT:  entry:
116; CHECK-NEXT:    [[IDX_SLT_LEN:%.*]] = icmp slt i8 [[IDX:%.*]], [[LEN:%.*]]
117; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[IDX_SLT_LEN]], true
118; CHECK-NEXT:    br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
119; CHECK:       then.1:
120; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[IDX]], [[LEN]]
121; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[LEN]], 0
122; CHECK-NEXT:    [[C_3:%.*]] = icmp sge i8 [[LEN]], 2
123; CHECK-NEXT:    [[C_4:%.*]] = icmp sge i8 [[LEN]], 2
124; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[C_1]], [[C_2]]
125; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_3]]
126; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], [[C_4]]
127; CHECK-NEXT:    ret i1 [[RES_3]]
128; CHECK:       else:
129; CHECK-NEXT:    ret i1 false
130;
131entry:
132  %idx.slt.len  = icmp slt i8 %idx, %len
133  %idx.pos = icmp uge i8 %idx, 0
134  %and.1 = and i1 %idx.slt.len, %idx.pos
135  br i1 %and.1, label %then.1, label %else
136
137then.1:
138  %c.1 = icmp ult i8 %idx, %len
139  %c.2 = icmp sge i8 %len, 0
140  %c.3 = icmp sge i8 %len, 2
141  %c.4 = icmp sge i8 %len, 2
142  %res.1 = xor i1 %c.1, %c.2
143  %res.2 = xor i1 %res.1, %c.3
144  %res.3 = xor i1 %res.2, %c.4
145  ret i1 %res.3
146
147else:
148  ret i1 0
149}
150
151declare void @sink(ptr)
152declare void @llvm.assume(i1)
153
154define i1 @cnt_positive_sgt_against_base(ptr %p, i32 %cnt) {
155; CHECK-LABEL: @cnt_positive_sgt_against_base(
156; CHECK-NEXT:  entry:
157; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CNT:%.*]], -1
158; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
159; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[CNT]]
160; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE:%.*]]
161; CHECK:       then:
162; CHECK-NEXT:    ret i1 false
163; CHECK:       else:
164; CHECK-NEXT:    ret i1 true
165;
166entry:
167  %cmp = icmp sgt i32 %cnt, -1
168  tail call void @llvm.assume(i1 %cmp)
169  %add.ptr = getelementptr inbounds i32, ptr %p, i32 %cnt
170  %cmp.1 = icmp uge ptr %add.ptr, %p
171  br i1 %cmp.1, label %then, label %else
172
173then:
174  ret i1 0
175
176else:
177  ret i1 1
178}
179
180define i1 @cnt_not_known_positive_sgt_against_base(ptr %p, i32 %cnt) {
181; CHECK-LABEL: @cnt_not_known_positive_sgt_against_base(
182; CHECK-NEXT:  entry:
183; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CNT:%.*]], -2
184; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
185; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[CNT]]
186; CHECK-NEXT:    [[CMP_1:%.*]] = icmp uge ptr [[ADD_PTR]], [[P]]
187; CHECK-NEXT:    br i1 [[CMP_1]], label [[THEN:%.*]], label [[ELSE:%.*]]
188; CHECK:       then:
189; CHECK-NEXT:    ret i1 false
190; CHECK:       else:
191; CHECK-NEXT:    ret i1 true
192;
193entry:
194  %cmp = icmp sgt i32 %cnt, -2
195  tail call void @llvm.assume(i1 %cmp)
196  %add.ptr = getelementptr inbounds i32, ptr %p, i32 %cnt
197  %cmp.1 = icmp uge ptr %add.ptr, %p
198  br i1 %cmp.1, label %then, label %else
199
200then:
201  ret i1 0
202
203else:
204  ret i1 1
205}
206
207define i1 @cnt_not_known_positive_uge_against_base(ptr %p, i32 %cnt) {
208; CHECK-LABEL: @cnt_not_known_positive_uge_against_base(
209; CHECK-NEXT:  entry:
210; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[CNT:%.*]], 0
211; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
212; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[CNT]]
213; CHECK-NEXT:    [[CMP_1:%.*]] = icmp uge ptr [[ADD_PTR]], [[P]]
214; CHECK-NEXT:    br i1 [[CMP_1]], label [[THEN:%.*]], label [[ELSE:%.*]]
215; CHECK:       then:
216; CHECK-NEXT:    ret i1 false
217; CHECK:       else:
218; CHECK-NEXT:    ret i1 true
219;
220entry:
221  %cmp = icmp ugt i32 %cnt, 0
222  tail call void @llvm.assume(i1 %cmp)
223  %add.ptr = getelementptr inbounds i32, ptr %p, i32 %cnt
224  %cmp.1 = icmp uge ptr %add.ptr, %p
225  br i1 %cmp.1, label %then, label %else
226
227then:
228  ret i1 0
229
230else:
231  ret i1 1
232}
233
234define i1 @cnt_positive_sgt_against_base_with_zext(ptr %p, i32 %cnt) {
235; CHECK-LABEL: @cnt_positive_sgt_against_base_with_zext(
236; CHECK-NEXT:  entry:
237; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CNT:%.*]], -1
238; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
239; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[CNT]] to i64
240; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[EXT]]
241; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE:%.*]]
242; CHECK:       then:
243; CHECK-NEXT:    ret i1 false
244; CHECK:       else:
245; CHECK-NEXT:    ret i1 true
246;
247entry:
248  %cmp = icmp sgt i32 %cnt, -1
249  tail call void @llvm.assume(i1 %cmp)
250  %ext = zext i32 %cnt to i64
251  %add.ptr = getelementptr inbounds i32, ptr %p, i64 %ext
252  %cmp.1 = icmp uge ptr %add.ptr, %p
253  br i1 %cmp.1, label %then, label %else
254
255then:
256  ret i1 0
257
258else:
259  ret i1 1
260}
261
262define i1 @cnt_positive_sge_against_base_with_zext(ptr %p, i32 %cnt) {
263; CHECK-LABEL: @cnt_positive_sge_against_base_with_zext(
264; CHECK-NEXT:  entry:
265; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[CNT:%.*]], 0
266; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
267; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[CNT]] to i64
268; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[EXT]]
269; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE:%.*]]
270; CHECK:       then:
271; CHECK-NEXT:    ret i1 false
272; CHECK:       else:
273; CHECK-NEXT:    ret i1 true
274;
275entry:
276  %cmp = icmp sge i32 %cnt, 0
277  tail call void @llvm.assume(i1 %cmp)
278  %ext = zext i32 %cnt to i64
279  %add.ptr = getelementptr inbounds i32, ptr %p, i64 %ext
280  %cmp.1 = icmp uge ptr %add.ptr, %p
281  br i1 %cmp.1, label %then, label %else
282
283then:
284  ret i1 0
285
286else:
287  ret i1 1
288}
289
290define i1 @cnt_not_known_positive_sgt_against_base_with_zext(ptr %p, i32 %cnt) {
291; CHECK-LABEL: @cnt_not_known_positive_sgt_against_base_with_zext(
292; CHECK-NEXT:  entry:
293; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CNT:%.*]], -2
294; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
295; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[CNT]] to i64
296; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[EXT]]
297; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE:%.*]]
298; CHECK:       then:
299; CHECK-NEXT:    ret i1 false
300; CHECK:       else:
301; CHECK-NEXT:    ret i1 true
302;
303entry:
304  %cmp = icmp sgt i32 %cnt, -2
305  tail call void @llvm.assume(i1 %cmp)
306  %ext = zext i32 %cnt to i64
307  %add.ptr = getelementptr inbounds i32, ptr %p, i64 %ext
308  %cmp.1 = icmp uge ptr %add.ptr, %p
309  br i1 %cmp.1, label %then, label %else
310
311then:
312  ret i1 0
313
314else:
315  ret i1 1
316}
317
318define i1 @cnt_not_known_positive_sge_against_base_with_zext(ptr %p, i32 %cnt) {
319; CHECK-LABEL: @cnt_not_known_positive_sge_against_base_with_zext(
320; CHECK-NEXT:  entry:
321; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[CNT:%.*]], -1
322; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
323; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[CNT]] to i64
324; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[EXT]]
325; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE:%.*]]
326; CHECK:       then:
327; CHECK-NEXT:    ret i1 false
328; CHECK:       else:
329; CHECK-NEXT:    ret i1 true
330;
331entry:
332  %cmp = icmp sge i32 %cnt, -1
333  tail call void @llvm.assume(i1 %cmp)
334  %ext = zext i32 %cnt to i64
335  %add.ptr = getelementptr inbounds i32, ptr %p, i64 %ext
336  %cmp.1 = icmp uge ptr %add.ptr, %p
337  br i1 %cmp.1, label %then, label %else
338
339then:
340  ret i1 0
341
342else:
343  ret i1 1
344}
345
346; TODO: Even though %cnt is not known signed positive %cmp can be simplified
347; because %add.ptr uses it zero-extended.
348define i1 @cnt_not_signed_positive_uge_against_base_with_zext(ptr %p, i32 %cnt) {
349; CHECK-LABEL: @cnt_not_signed_positive_uge_against_base_with_zext(
350; CHECK-NEXT:  entry:
351; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[CNT:%.*]], 0
352; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
353; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i32 [[CNT]]
354; CHECK-NEXT:    [[CMP_1:%.*]] = icmp uge ptr [[ADD_PTR]], [[P]]
355; CHECK-NEXT:    br i1 [[CMP_1]], label [[THEN:%.*]], label [[ELSE:%.*]]
356; CHECK:       then:
357; CHECK-NEXT:    ret i1 false
358; CHECK:       else:
359; CHECK-NEXT:    ret i1 true
360;
361entry:
362  %cmp = icmp uge i32 %cnt, 0
363  tail call void @llvm.assume(i1 %cmp)
364  %add.ptr = getelementptr inbounds i32, ptr %p, i32 %cnt
365  %cmp.1 = icmp uge ptr %add.ptr, %p
366  br i1 %cmp.1, label %then, label %else
367
368then:
369  ret i1 0
370
371else:
372  ret i1 1
373}
374
375%t = type { i32, [10 x i32] }
376
377define i1 @cnt_positive_from_assume_check_against_base_struct_ugt_with_zext(ptr %p, i32 %cnt) {
378; CHECK-LABEL: @cnt_positive_from_assume_check_against_base_struct_ugt_with_zext(
379; CHECK-NEXT:  entry:
380; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CNT:%.*]], -1
381; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
382; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[CNT]] to i64
383; CHECK-NEXT:    [[GEP_EXT:%.*]] = getelementptr inbounds [[T:%.*]], ptr [[P:%.*]], i64 0, i32 1, i64 [[EXT]]
384; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE:%.*]]
385; CHECK:       then:
386; CHECK-NEXT:    ret i1 false
387; CHECK:       else:
388; CHECK-NEXT:    tail call void @sink(ptr nonnull [[P]])
389; CHECK-NEXT:    ret i1 true
390;
391entry:
392  %cmp = icmp sgt i32 %cnt, -1
393  tail call void @llvm.assume(i1 %cmp)
394  %ext = zext i32 %cnt to i64
395  %gep.ext = getelementptr inbounds %t, ptr %p, i64 0, i32 1, i64 %ext
396  %cmp.1 = icmp ugt ptr %gep.ext, %p
397  br i1 %cmp.1, label %then, label %else
398
399then:
400  ret i1 0
401
402else:
403  tail call void @sink(ptr nonnull %p)
404  ret i1 1
405}
406
407define i1 @cnt_positive_from_branch_check_against_base_struct_ugt_with_zext(ptr %p, i32 %cnt) {
408; CHECK-LABEL: @cnt_positive_from_branch_check_against_base_struct_ugt_with_zext(
409; CHECK-NEXT:  entry:
410; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CNT:%.*]], -1
411; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK:%.*]], label [[ELSE:%.*]]
412; CHECK:       check:
413; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[CNT]] to i64
414; CHECK-NEXT:    [[GEP_EXT:%.*]] = getelementptr inbounds [[T:%.*]], ptr [[P:%.*]], i64 0, i32 1, i64 [[EXT]]
415; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE]]
416; CHECK:       then:
417; CHECK-NEXT:    ret i1 false
418; CHECK:       else:
419; CHECK-NEXT:    tail call void @sink(ptr nonnull [[P]])
420; CHECK-NEXT:    ret i1 true
421;
422entry:
423  %cmp = icmp sgt i32 %cnt, -1
424  br i1 %cmp, label %check, label %else
425
426check:
427  %ext = zext i32 %cnt to i64
428  %gep.ext = getelementptr inbounds %t, ptr %p, i64 0, i32 1, i64 %ext
429  %cmp.1 = icmp ugt ptr %gep.ext, %p
430  br i1 %cmp.1, label %then, label %else
431
432then:
433  ret i1 0
434
435else:
436  tail call void @sink(ptr nonnull %p)
437  ret i1 1
438}
439
440; because %add.ptr uses it zero-extended.
441define i1 @cnt_not_known_positive_from_branch_check_against_base_struct_ugt_with_zext(ptr %p, i32 %cnt) {
442; CHECK-LABEL: @cnt_not_known_positive_from_branch_check_against_base_struct_ugt_with_zext(
443; CHECK-NEXT:  entry:
444; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CNT:%.*]], -2
445; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK:%.*]], label [[ELSE:%.*]]
446; CHECK:       check:
447; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[CNT]] to i64
448; CHECK-NEXT:    [[GEP_EXT:%.*]] = getelementptr inbounds [[T:%.*]], ptr [[P:%.*]], i64 0, i32 1, i64 [[EXT]]
449; CHECK-NEXT:    br i1 true, label [[THEN:%.*]], label [[ELSE]]
450; CHECK:       then:
451; CHECK-NEXT:    ret i1 false
452; CHECK:       else:
453; CHECK-NEXT:    tail call void @sink(ptr nonnull [[P]])
454; CHECK-NEXT:    ret i1 true
455;
456entry:
457  %cmp = icmp sgt i32 %cnt, -2
458  br i1 %cmp, label %check, label %else
459
460check:
461  %ext = zext i32 %cnt to i64
462  %gep.ext = getelementptr inbounds %t, ptr %p, i64 0, i32 1, i64 %ext
463  %cmp.1 = icmp ugt ptr %gep.ext, %p
464  br i1 %cmp.1, label %then, label %else
465
466then:
467  ret i1 0
468
469else:
470  tail call void @sink(ptr nonnull %p)
471  ret i1 1
472}
473
474define i1 @sge_2(i8 %idx) {
475; CHECK-LABEL: @sge_2(
476; CHECK-NEXT:  entry:
477; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[IDX:%.*]], 2
478; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
479; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
480; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i8 [[IDX]], 3
481; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
482; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[RES_2]], false
483; CHECK-NEXT:    ret i1 [[RES_3]]
484;
485entry:
486  %cmp = icmp sge i8 %idx, 2
487  call void @llvm.assume(i1 %cmp)
488  %t.1 = icmp uge i8 %idx, 2
489  %t.2 = icmp uge i8 %idx, 1
490  %res.1 = xor i1 %t.1, %t.2
491  %c.1 = icmp uge i8 %idx, 3
492  %res.2 = xor i1 %res.1, %c.1
493  %f.1 = icmp ult i8 %idx, 2
494  %res.3 = xor i1 %res.2, %f.1
495  ret i1 %res.3
496}
497
498define i32 @sge_2_gep(i32 %idx, ptr %src, i32 %idx.2) {
499; CHECK-LABEL: @sge_2_gep(
500; CHECK-NEXT:  entry:
501; CHECK-NEXT:    [[IDX_EXT:%.*]] = sext i32 [[IDX:%.*]] to i64
502; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i64 [[IDX_EXT]]
503; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[IDX]], 2
504; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
505; CHECK-NEXT:    [[ADD_PTR_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i32 [[IDX_2:%.*]]
506; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[SRC]], [[ADD_PTR_2]]
507; CHECK-NEXT:    [[X_1:%.*]] = xor i1 true, [[C_1]]
508; CHECK-NEXT:    [[X_2:%.*]] = xor i1 [[X_1]], false
509; CHECK-NEXT:    br i1 [[X_2]], label [[THEN:%.*]], label [[ELSE:%.*]]
510; CHECK:       then:
511; CHECK-NEXT:    ret i32 0
512; CHECK:       else:
513; CHECK-NEXT:    ret i32 10
514;
515entry:
516  %idx.ext = sext i32 %idx to i64
517  %add.ptr = getelementptr inbounds i32, ptr %src, i64 %idx.ext
518  %cmp = icmp sge i32 %idx, 2
519  call void @llvm.assume(i1 %cmp)
520  %add.ptr.2 = getelementptr inbounds i32, ptr %src, i32 %idx.2
521  %t.1 = icmp ult ptr %src, %add.ptr
522  %c.1 = icmp ult ptr %src, %add.ptr.2
523  %x.1 = xor i1 %t.1, %c.1
524  %f.1 = icmp uge ptr %src, %add.ptr
525  %x.2 = xor i1 %x.1, %f.1
526  br i1 %x.2, label %then, label %else
527
528then:
529  ret i32 0
530
531else:
532  ret i32 10
533}
534
535define i1 @sgt_known_neg(i8 %idx) {
536; CHECK-LABEL: @sgt_known_neg(
537; CHECK-NEXT:  entry:
538; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[IDX:%.*]], -1
539; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
540; CHECK-NEXT:    [[T_2:%.*]] = icmp uge i8 [[IDX]], 1
541; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, [[T_2]]
542; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[IDX]], -1
543; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
544; CHECK-NEXT:    ret i1 [[RES_2]]
545;
546entry:
547  %cmp = icmp sgt i8 %idx, -1
548  call void @llvm.assume(i1 %cmp)
549  %t.1 = icmp uge i8 %idx, 0
550  %t.2 = icmp uge i8 %idx, 1
551  %res.1 = xor i1 %t.1, %t.2
552  %c.1 = icmp ugt i8 %idx, -1
553  %res.2 = xor i1 %res.1, %c.1
554  ret i1 %res.2
555}
556
557define i1 @sgt_known_pos(i8 %idx) {
558; CHECK-LABEL: @sgt_known_pos(
559; CHECK-NEXT:  entry:
560; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[IDX:%.*]], 2
561; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
562; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
563; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[IDX]], 3
564; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
565; CHECK-NEXT:    ret i1 [[RES_2]]
566;
567entry:
568  %cmp = icmp sgt i8 %idx, 2
569  call void @llvm.assume(i1 %cmp)
570  %t.1 = icmp ugt i8 %idx, 2
571  %t.2 = icmp ugt i8 %idx, 1
572  %res.1 = xor i1 %t.1, %t.2
573  %c.1 = icmp ugt i8 %idx, 3
574  %res.2 = xor i1 %res.1, %c.1
575  ret i1 %res.2
576}
577
578define i1 @sgt_to_ugt(i8 %a) {
579; CHECK-LABEL: @sgt_to_ugt(
580; CHECK-NEXT:  entry:
581; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], 2
582; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
583; CHECK-NEXT:    ret i1 true
584;
585entry:
586  %cmp = icmp sgt i8 %a, 2
587  call void @llvm.assume(i1 %cmp)
588  %t.1 = icmp ugt i8 %a, 2
589  ret i1 %t.1
590}
591
592define i1 @sgt_to_ugt_less(i8 %a) {
593; CHECK-LABEL: @sgt_to_ugt_less(
594; CHECK-NEXT:  entry:
595; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], 2
596; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
597; CHECK-NEXT:    ret i1 true
598;
599entry:
600  %cmp = icmp sgt i8 %a, 2
601  call void @llvm.assume(i1 %cmp)
602  %t.1 = icmp ugt i8 %a, 1
603  ret i1 %t.1
604}
605
606define i1 @sgt_to_ugt_var(i8 %a, i8 %b) {
607; CHECK-LABEL: @sgt_to_ugt_var(
608; CHECK-NEXT:  entry:
609; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
610; CHECK-NEXT:    [[CMP_2:%.*]] = icmp sgt i8 [[B]], 0
611; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
612; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_2]])
613; CHECK-NEXT:    ret i1 true
614;
615entry:
616  %cmp = icmp sgt i8 %a, %b
617  %cmp.2 = icmp sgt i8 %b, 0
618  call void @llvm.assume(i1 %cmp)
619  call void @llvm.assume(i1 %cmp.2)
620  %t.1 = icmp ugt i8 %a, %b
621  ret i1 %t.1
622}
623
624define i1 @sgt_to_ugt_no_range_info(i8 %a, i8 %b) {
625; CHECK-LABEL: @sgt_to_ugt_no_range_info(
626; CHECK-NEXT:  entry:
627; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
628; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
629; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[A]], [[B]]
630; CHECK-NEXT:    ret i1 [[C_1]]
631;
632entry:
633  %cmp = icmp sgt i8 %a, %b
634  call void @llvm.assume(i1 %cmp)
635  %c.1 = icmp ugt i8 %a, %b
636  ret i1 %c.1
637}
638
639define i1 @sgt_to_ugt_neg(i8 %a) {
640; CHECK-LABEL: @sgt_to_ugt_neg(
641; CHECK-NEXT:  entry:
642; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], -1
643; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
644; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[A]], -1
645; CHECK-NEXT:    ret i1 [[C_1]]
646;
647entry:
648  %cmp = icmp sgt i8 %a, -1
649  call void @llvm.assume(i1 %cmp)
650  %c.1 = icmp ugt i8 %a, -1
651  ret i1 %c.1
652}
653
654define i1 @sgt_to_ugt_neg2(i8 %a) {
655; CHECK-LABEL: @sgt_to_ugt_neg2(
656; CHECK-NEXT:  entry:
657; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], -2
658; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
659; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[A]], -2
660; CHECK-NEXT:    ret i1 [[C_1]]
661;
662entry:
663  %cmp = icmp sgt i8 %a, -2
664  call void @llvm.assume(i1 %cmp)
665  %c.1 = icmp ugt i8 %a, -2
666  ret i1 %c.1
667}
668
669define i1 @sgt_to_ugt_var_neg(i8 %a, i8 %b) {
670; CHECK-LABEL: @sgt_to_ugt_var_neg(
671; CHECK-NEXT:  entry:
672; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
673; CHECK-NEXT:    [[CMP_2:%.*]] = icmp sgt i8 [[B]], -2
674; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
675; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_2]])
676; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[A]], [[B]]
677; CHECK-NEXT:    ret i1 [[C_1]]
678;
679entry:
680  %cmp = icmp sgt i8 %a, %b
681  %cmp.2 = icmp sgt i8 %b, -2
682  call void @llvm.assume(i1 %cmp)
683  call void @llvm.assume(i1 %cmp.2)
684  %c.1 = icmp ugt i8 %a, %b
685  ret i1 %c.1
686}
687
688define i1 @slt_first_op_known_pos(i8 %idx) {
689; CHECK-LABEL: @slt_first_op_known_pos(
690; CHECK-NEXT:  entry:
691; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 2, [[IDX:%.*]]
692; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
693; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
694; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 3, [[IDX]]
695; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
696; CHECK-NEXT:    ret i1 [[RES_2]]
697;
698entry:
699  %cmp = icmp slt i8 2, %idx
700  call void @llvm.assume(i1 %cmp)
701  %t.1 = icmp ult i8 2, %idx
702  %t.2 = icmp ult i8 1, %idx
703  %res.1 = xor i1 %t.1, %t.2
704  %c.1 = icmp ult i8 3, %idx
705  %res.2 = xor i1 %res.1, %c.1
706  ret i1 %res.2
707}
708
709define i1 @slt_first_op_known_neg(i8 %idx) {
710; CHECK-LABEL: @slt_first_op_known_neg(
711; CHECK-NEXT:  entry:
712; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 -2, [[IDX:%.*]]
713; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
714; CHECK-NEXT:    [[T_1:%.*]] = icmp ult i8 2, [[IDX]]
715; CHECK-NEXT:    [[T_2:%.*]] = icmp ult i8 1, [[IDX]]
716; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]]
717; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 3, [[IDX]]
718; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_1]]
719; CHECK-NEXT:    ret i1 [[RES_2]]
720;
721entry:
722  %cmp = icmp slt i8 -2, %idx
723  call void @llvm.assume(i1 %cmp)
724  %t.1 = icmp ult i8 2, %idx
725  %t.2 = icmp ult i8 1, %idx
726  %res.1 = xor i1 %t.1, %t.2
727  %c.1 = icmp ult i8 3, %idx
728  %res.2 = xor i1 %res.1, %c.1
729  ret i1 %res.2
730}
731