xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/geps-signed-predicates.ll (revision c5e1ddb6fddef6f0d0ffc9acc9b0a2f3534b303f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4define i32 @test.slt(ptr readonly %src, ptr readnone %min, ptr readnone %max) {
5; CHECK-LABEL: @test.slt(
6; CHECK-NEXT:  check.0.min:
7; CHECK-NEXT:    [[C_MIN_0:%.*]] = icmp slt ptr [[SRC:%.*]], [[MIN:%.*]]
8; CHECK-NEXT:    br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]]
9; CHECK:       trap:
10; CHECK-NEXT:    ret i32 10
11; CHECK:       check.0.max:
12; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[SRC]], [[MAX:%.*]]
13; CHECK-NEXT:    br i1 [[C_MAX_0]], label [[CHECK_3_MIN:%.*]], label [[TRAP]]
14; CHECK:       check.3.min:
15; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[SRC]], align 4
16; CHECK-NEXT:    [[ADD_PTR_I36:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3
17; CHECK-NEXT:    [[C_3_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MIN]]
18; CHECK-NEXT:    br i1 [[C_3_MIN]], label [[TRAP]], label [[CHECK_3_MAX:%.*]]
19; CHECK:       check.3.max:
20; CHECK-NEXT:    [[C_3_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MAX]]
21; CHECK-NEXT:    br i1 [[C_3_MAX]], label [[CHECK_1_MIN:%.*]], label [[TRAP]]
22; CHECK:       check.1.min:
23; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[ADD_PTR_I36]], align 4
24; CHECK-NEXT:    [[ADD_PTR_I29:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 1
25; CHECK-NEXT:    [[C_1_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MIN]]
26; CHECK-NEXT:    br i1 [[C_1_MIN]], label [[TRAP]], label [[CHECK_1_MAX:%.*]]
27; CHECK:       check.1.max:
28; CHECK-NEXT:    [[C_1_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MAX]]
29; CHECK-NEXT:    br i1 [[C_1_MAX]], label [[CHECK_2_MIN:%.*]], label [[TRAP]]
30; CHECK:       check.2.min:
31; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[ADD_PTR_I29]], align 4
32; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 2
33; CHECK-NEXT:    [[C_2_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MIN]]
34; CHECK-NEXT:    br i1 [[C_2_MIN]], label [[TRAP]], label [[CHECK_2_MAX:%.*]]
35; CHECK:       check.2.max:
36; CHECK-NEXT:    [[C_2_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MAX]]
37; CHECK-NEXT:    br i1 [[C_2_MAX]], label [[EXIT:%.*]], label [[TRAP]]
38; CHECK:       exit:
39; CHECK-NEXT:    [[L3:%.*]] = load i32, ptr [[ADD_PTR_I]], align 4
40; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[L1]], [[L0]]
41; CHECK-NEXT:    [[ADD8:%.*]] = add nsw i32 [[ADD]], [[L2]]
42; CHECK-NEXT:    [[ADD9:%.*]] = add nsw i32 [[ADD8]], [[L3]]
43; CHECK-NEXT:    ret i32 [[ADD9]]
44;
45check.0.min:
46  %c.min.0 = icmp slt ptr %src, %min
47  br i1 %c.min.0, label %trap, label %check.0.max
48
49trap:
50  ret i32 10
51
52check.0.max:
53  %c.max.0 = icmp slt ptr %src, %max
54  br i1 %c.max.0, label %check.3.min, label %trap
55
56check.3.min:
57  %l0 = load i32, ptr %src, align 4
58  %add.ptr.i36 = getelementptr inbounds i32, ptr %src, i64 3
59  %c.3.min = icmp slt ptr %add.ptr.i36, %min
60  br i1 %c.3.min, label %trap, label %check.3.max
61
62check.3.max:
63  %c.3.max = icmp slt ptr %add.ptr.i36, %max
64  br i1 %c.3.max, label %check.1.min, label %trap
65
66check.1.min:
67  %l1 = load i32, ptr %add.ptr.i36, align 4
68  %add.ptr.i29 = getelementptr inbounds i32, ptr %src, i64 1
69  %c.1.min = icmp slt ptr %add.ptr.i29, %min
70  br i1 %c.1.min, label %trap, label %check.1.max
71
72check.1.max:
73  %c.1.max = icmp slt ptr %add.ptr.i29, %max
74  br i1 %c.1.max, label %check.2.min, label %trap
75
76check.2.min:
77  %l2 = load i32, ptr %add.ptr.i29, align 4
78  %add.ptr.i = getelementptr inbounds i32, ptr %src, i64 2
79  %c.2.min = icmp slt ptr %add.ptr.i, %min
80  br i1 %c.2.min, label %trap, label %check.2.max
81
82check.2.max:
83  %c.2.max = icmp slt ptr %add.ptr.i, %max
84  br i1 %c.2.max, label %exit, label %trap
85
86exit:
87  %l3 = load i32, ptr %add.ptr.i, align 4
88  %add = add nsw i32 %l1, %l0
89  %add8 = add nsw i32 %add, %l2
90  %add9 = add nsw i32 %add8, %l3
91  ret i32 %add9
92}
93
94; Same as test.slt, but without inbounds.
95define i32 @test.slt_no_inbounds(ptr readonly %src, ptr readnone %min, ptr readnone %max) {
96; CHECK-LABEL: @test.slt_no_inbounds(
97; CHECK-NEXT:  check.0.min:
98; CHECK-NEXT:    [[C_MIN_0:%.*]] = icmp slt ptr [[SRC:%.*]], [[MIN:%.*]]
99; CHECK-NEXT:    br i1 [[C_MIN_0]], label [[TRAP:%.*]], label [[CHECK_0_MAX:%.*]]
100; CHECK:       trap:
101; CHECK-NEXT:    ret i32 10
102; CHECK:       check.0.max:
103; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[SRC]], [[MAX:%.*]]
104; CHECK-NEXT:    br i1 [[C_MAX_0]], label [[CHECK_3_MIN:%.*]], label [[TRAP]]
105; CHECK:       check.3.min:
106; CHECK-NEXT:    [[L0:%.*]] = load i32, ptr [[SRC]], align 4
107; CHECK-NEXT:    [[ADD_PTR_I36:%.*]] = getelementptr i32, ptr [[SRC]], i64 3
108; CHECK-NEXT:    [[C_3_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MIN]]
109; CHECK-NEXT:    br i1 [[C_3_MIN]], label [[TRAP]], label [[CHECK_3_MAX:%.*]]
110; CHECK:       check.3.max:
111; CHECK-NEXT:    [[C_3_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I36]], [[MAX]]
112; CHECK-NEXT:    br i1 [[C_3_MAX]], label [[CHECK_1_MIN:%.*]], label [[TRAP]]
113; CHECK:       check.1.min:
114; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[ADD_PTR_I36]], align 4
115; CHECK-NEXT:    [[ADD_PTR_I29:%.*]] = getelementptr i32, ptr [[SRC]], i64 1
116; CHECK-NEXT:    [[C_1_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MIN]]
117; CHECK-NEXT:    br i1 [[C_1_MIN]], label [[TRAP]], label [[CHECK_1_MAX:%.*]]
118; CHECK:       check.1.max:
119; CHECK-NEXT:    [[C_1_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I29]], [[MAX]]
120; CHECK-NEXT:    br i1 [[C_1_MAX]], label [[CHECK_2_MIN:%.*]], label [[TRAP]]
121; CHECK:       check.2.min:
122; CHECK-NEXT:    [[L2:%.*]] = load i32, ptr [[ADD_PTR_I29]], align 4
123; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr i32, ptr [[SRC]], i64 2
124; CHECK-NEXT:    [[C_2_MIN:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MIN]]
125; CHECK-NEXT:    br i1 [[C_2_MIN]], label [[TRAP]], label [[CHECK_2_MAX:%.*]]
126; CHECK:       check.2.max:
127; CHECK-NEXT:    [[C_2_MAX:%.*]] = icmp slt ptr [[ADD_PTR_I]], [[MAX]]
128; CHECK-NEXT:    br i1 [[C_2_MAX]], label [[EXIT:%.*]], label [[TRAP]]
129; CHECK:       exit:
130; CHECK-NEXT:    [[L3:%.*]] = load i32, ptr [[ADD_PTR_I]], align 4
131; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[L1]], [[L0]]
132; CHECK-NEXT:    [[ADD8:%.*]] = add nsw i32 [[ADD]], [[L2]]
133; CHECK-NEXT:    [[ADD9:%.*]] = add nsw i32 [[ADD8]], [[L3]]
134; CHECK-NEXT:    ret i32 [[ADD9]]
135;
136check.0.min:
137  %c.min.0 = icmp slt ptr %src, %min
138  br i1 %c.min.0, label %trap, label %check.0.max
139
140trap:
141  ret i32 10
142
143check.0.max:
144  %c.max.0 = icmp slt ptr %src, %max
145  br i1 %c.max.0, label %check.3.min, label %trap
146
147check.3.min:
148  %l0 = load i32, ptr %src, align 4
149  %add.ptr.i36 = getelementptr i32, ptr %src, i64 3
150  %c.3.min = icmp slt ptr %add.ptr.i36, %min
151  br i1 %c.3.min, label %trap, label %check.3.max
152
153check.3.max:
154  %c.3.max = icmp slt ptr %add.ptr.i36, %max
155  br i1 %c.3.max, label %check.1.min, label %trap
156
157check.1.min:
158  %l1 = load i32, ptr %add.ptr.i36, align 4
159  %add.ptr.i29 = getelementptr i32, ptr %src, i64 1
160  %c.1.min = icmp slt ptr %add.ptr.i29, %min
161  br i1 %c.1.min, label %trap, label %check.1.max
162
163check.1.max:
164  %c.1.max = icmp slt ptr %add.ptr.i29, %max
165  br i1 %c.1.max, label %check.2.min, label %trap
166
167check.2.min:
168  %l2 = load i32, ptr %add.ptr.i29, align 4
169  %add.ptr.i = getelementptr i32, ptr %src, i64 2
170  %c.2.min = icmp slt ptr %add.ptr.i, %min
171  br i1 %c.2.min, label %trap, label %check.2.max
172
173check.2.max:
174  %c.2.max = icmp slt ptr %add.ptr.i, %max
175  br i1 %c.2.max, label %exit, label %trap
176
177exit:
178  %l3 = load i32, ptr %add.ptr.i, align 4
179  %add = add nsw i32 %l1, %l0
180  %add8 = add nsw i32 %add, %l2
181  %add9 = add nsw i32 %add8, %l3
182  ret i32 %add9
183}
184
185define void @test.not.sge.slt(ptr %start, ptr %low, ptr %high) {
186; CHECK-LABEL: @test.not.sge.slt(
187; CHECK-NEXT:  entry:
188; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
189; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
190; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
191; CHECK:       if.then:
192; CHECK-NEXT:    ret void
193; CHECK:       if.end:
194; CHECK-NEXT:    [[T_0:%.*]] = icmp slt ptr [[START]], [[HIGH]]
195; CHECK-NEXT:    call void @use(i1 [[T_0]])
196; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
197; CHECK-NEXT:    [[T_1:%.*]] = icmp slt ptr [[START_1]], [[HIGH]]
198; CHECK-NEXT:    call void @use(i1 [[T_1]])
199; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
200; CHECK-NEXT:    [[T_2:%.*]] = icmp slt ptr [[START_2]], [[HIGH]]
201; CHECK-NEXT:    call void @use(i1 [[T_2]])
202; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
203; CHECK-NEXT:    [[T_3:%.*]] = icmp slt ptr [[START_3]], [[HIGH]]
204; CHECK-NEXT:    call void @use(i1 [[T_3]])
205; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
206; CHECK-NEXT:    [[C_4:%.*]] = icmp slt ptr [[START_4]], [[HIGH]]
207; CHECK-NEXT:    call void @use(i1 [[C_4]])
208; CHECK-NEXT:    ret void
209;
210entry:
211  %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
212  %c.1 = icmp sge ptr %add.ptr.i, %high
213  br i1 %c.1, label %if.then, label %if.end
214
215if.then:
216  ret void
217
218if.end:
219  %t.0 = icmp slt ptr %start, %high
220  call void @use(i1 %t.0)
221  %start.1 = getelementptr inbounds i8, ptr %start, i64 1
222  %t.1 = icmp slt ptr %start.1, %high
223  call void @use(i1 %t.1)
224  %start.2 = getelementptr inbounds i8, ptr %start, i64 2
225  %t.2 = icmp slt ptr %start.2, %high
226  call void @use(i1 %t.2)
227  %start.3 = getelementptr inbounds i8, ptr %start, i64 3
228  %t.3 = icmp slt ptr %start.3, %high
229  call void @use(i1 %t.3)
230  %start.4 = getelementptr inbounds i8, ptr %start, i64 4
231  %c.4 = icmp slt ptr %start.4, %high
232  call void @use(i1 %c.4)
233  ret void
234}
235
236; Same as test.not.sge.slt, but without inbounds GEPs.
237define void @test.not.sge.slt_no_inbounds(ptr %start, ptr %low, ptr %high) {
238; CHECK-LABEL: @test.not.sge.slt_no_inbounds(
239; CHECK-NEXT:  entry:
240; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr i8, ptr [[START:%.*]], i64 3
241; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
242; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
243; CHECK:       if.then:
244; CHECK-NEXT:    ret void
245; CHECK:       if.end:
246; CHECK-NEXT:    [[T_0:%.*]] = icmp slt ptr [[START]], [[HIGH]]
247; CHECK-NEXT:    call void @use(i1 [[T_0]])
248; CHECK-NEXT:    [[START_1:%.*]] = getelementptr i8, ptr [[START]], i64 1
249; CHECK-NEXT:    [[T_1:%.*]] = icmp slt ptr [[START_1]], [[HIGH]]
250; CHECK-NEXT:    call void @use(i1 [[T_1]])
251; CHECK-NEXT:    [[START_2:%.*]] = getelementptr i8, ptr [[START]], i64 2
252; CHECK-NEXT:    [[T_2:%.*]] = icmp slt ptr [[START_2]], [[HIGH]]
253; CHECK-NEXT:    call void @use(i1 [[T_2]])
254; CHECK-NEXT:    [[START_3:%.*]] = getelementptr i8, ptr [[START]], i64 3
255; CHECK-NEXT:    [[T_3:%.*]] = icmp slt ptr [[START_3]], [[HIGH]]
256; CHECK-NEXT:    call void @use(i1 [[T_3]])
257; CHECK-NEXT:    [[START_4:%.*]] = getelementptr i8, ptr [[START]], i64 4
258; CHECK-NEXT:    [[C_4:%.*]] = icmp slt ptr [[START_4]], [[HIGH]]
259; CHECK-NEXT:    call void @use(i1 [[C_4]])
260; CHECK-NEXT:    ret void
261;
262entry:
263  %add.ptr.i = getelementptr i8, ptr %start, i64 3
264  %c.1 = icmp sge ptr %add.ptr.i, %high
265  br i1 %c.1, label %if.then, label %if.end
266
267if.then:
268  ret void
269
270if.end:
271  %t.0 = icmp slt ptr %start, %high
272  call void @use(i1 %t.0)
273  %start.1 = getelementptr i8, ptr %start, i64 1
274  %t.1 = icmp slt ptr %start.1, %high
275  call void @use(i1 %t.1)
276  %start.2 = getelementptr i8, ptr %start, i64 2
277  %t.2 = icmp slt ptr %start.2, %high
278  call void @use(i1 %t.2)
279  %start.3 = getelementptr i8, ptr %start, i64 3
280  %t.3 = icmp slt ptr %start.3, %high
281  call void @use(i1 %t.3)
282  %start.4 = getelementptr i8, ptr %start, i64 4
283  %c.4 = icmp slt ptr %start.4, %high
284  call void @use(i1 %c.4)
285  ret void
286}
287
288define void @test.not.sge.sle(ptr %start, ptr %low, ptr %high) {
289; CHECK-LABEL: @test.not.sge.sle(
290; CHECK-NEXT:  entry:
291; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
292; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
293; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
294; CHECK:       if.then:
295; CHECK-NEXT:    ret void
296; CHECK:       if.end:
297; CHECK-NEXT:    [[T_0:%.*]] = icmp sle ptr [[START]], [[HIGH]]
298; CHECK-NEXT:    call void @use(i1 [[T_0]])
299; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
300; CHECK-NEXT:    [[T_1:%.*]] = icmp sle ptr [[START_1]], [[HIGH]]
301; CHECK-NEXT:    call void @use(i1 [[T_1]])
302; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
303; CHECK-NEXT:    [[T_2:%.*]] = icmp sle ptr [[START_2]], [[HIGH]]
304; CHECK-NEXT:    call void @use(i1 [[T_2]])
305; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
306; CHECK-NEXT:    [[T_3:%.*]] = icmp sle ptr [[START_3]], [[HIGH]]
307; CHECK-NEXT:    call void @use(i1 [[T_3]])
308; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
309; CHECK-NEXT:    [[T_4:%.*]] = icmp sle ptr [[START_4]], [[HIGH]]
310; CHECK-NEXT:    call void @use(i1 [[T_4]])
311; CHECK-NEXT:    [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5
312; CHECK-NEXT:    [[C_5:%.*]] = icmp sle ptr [[START_5]], [[HIGH]]
313; CHECK-NEXT:    call void @use(i1 [[C_5]])
314; CHECK-NEXT:    ret void
315;
316entry:
317  %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
318  %c.1 = icmp sge ptr %add.ptr.i, %high
319  br i1 %c.1, label %if.then, label %if.end
320
321if.then:
322  ret void
323
324if.end:
325  %t.0 = icmp sle ptr %start, %high
326  call void @use(i1 %t.0)
327  %start.1 = getelementptr inbounds i8, ptr %start, i64 1
328  %t.1 = icmp sle ptr %start.1, %high
329  call void @use(i1 %t.1)
330  %start.2 = getelementptr inbounds i8, ptr %start, i64 2
331  %t.2 = icmp sle ptr %start.2, %high
332  call void @use(i1 %t.2)
333  %start.3 = getelementptr inbounds i8, ptr %start, i64 3
334  %t.3 = icmp sle ptr %start.3, %high
335  call void @use(i1 %t.3)
336  %start.4 = getelementptr inbounds i8, ptr %start, i64 4
337  %t.4 = icmp sle ptr %start.4, %high
338  call void @use(i1 %t.4)
339  %start.5 = getelementptr inbounds i8, ptr %start, i64 5
340  %c.5 = icmp sle ptr %start.5, %high
341  call void @use(i1 %c.5)
342  ret void
343}
344
345define void @test.not.sge.sgt(ptr %start, ptr %low, ptr %high) {
346; CHECK-LABEL: @test.not.sge.sgt(
347; CHECK-NEXT:  entry:
348; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
349; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
350; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
351; CHECK:       if.then:
352; CHECK-NEXT:    ret void
353; CHECK:       if.end:
354; CHECK-NEXT:    [[F_0:%.*]] = icmp sgt ptr [[START]], [[HIGH]]
355; CHECK-NEXT:    call void @use(i1 [[F_0]])
356; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
357; CHECK-NEXT:    [[F_1:%.*]] = icmp sgt ptr [[START_1]], [[HIGH]]
358; CHECK-NEXT:    call void @use(i1 [[F_1]])
359; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
360; CHECK-NEXT:    [[F_2:%.*]] = icmp sgt ptr [[START_2]], [[HIGH]]
361; CHECK-NEXT:    call void @use(i1 [[F_2]])
362; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
363; CHECK-NEXT:    [[F_3:%.*]] = icmp sgt ptr [[START_3]], [[HIGH]]
364; CHECK-NEXT:    call void @use(i1 [[F_3]])
365; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
366; CHECK-NEXT:    [[F_4:%.*]] = icmp sgt ptr [[START_4]], [[HIGH]]
367; CHECK-NEXT:    call void @use(i1 [[F_4]])
368; CHECK-NEXT:    [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5
369; CHECK-NEXT:    [[C_5:%.*]] = icmp sgt ptr [[START_5]], [[HIGH]]
370; CHECK-NEXT:    call void @use(i1 [[C_5]])
371; CHECK-NEXT:    ret void
372;
373entry:
374  %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
375  %c.1 = icmp sge ptr %add.ptr.i, %high
376  br i1 %c.1, label %if.then, label %if.end
377
378if.then:
379  ret void
380
381if.end:
382  %f.0 = icmp sgt ptr %start, %high
383  call void @use(i1 %f.0)
384  %start.1 = getelementptr inbounds i8, ptr %start, i64 1
385  %f.1 = icmp sgt ptr %start.1, %high
386  call void @use(i1 %f.1)
387  %start.2 = getelementptr inbounds i8, ptr %start, i64 2
388  %f.2 = icmp sgt ptr %start.2, %high
389  call void @use(i1 %f.2)
390  %start.3 = getelementptr inbounds i8, ptr %start, i64 3
391  %f.3 = icmp sgt ptr %start.3, %high
392  call void @use(i1 %f.3)
393  %start.4 = getelementptr inbounds i8, ptr %start, i64 4
394  %f.4 = icmp sgt ptr %start.4, %high
395  call void @use(i1 %f.4)
396  %start.5 = getelementptr inbounds i8, ptr %start, i64 5
397  %c.5 = icmp sgt ptr %start.5, %high
398  call void @use(i1 %c.5)
399  ret void
400}
401
402define void @test.not.sge.sge(ptr %start, ptr %low, ptr %high) {
403; CHECK-LABEL: @test.not.sge.sge(
404; CHECK-NEXT:  entry:
405; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i64 3
406; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
407; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
408; CHECK:       if.then:
409; CHECK-NEXT:    ret void
410; CHECK:       if.end:
411; CHECK-NEXT:    [[F_0:%.*]] = icmp sgt ptr [[START]], [[HIGH]]
412; CHECK-NEXT:    call void @use(i1 [[F_0]])
413; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
414; CHECK-NEXT:    [[F_1:%.*]] = icmp sge ptr [[START_1]], [[HIGH]]
415; CHECK-NEXT:    call void @use(i1 [[F_1]])
416; CHECK-NEXT:    [[START_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 2
417; CHECK-NEXT:    [[F_2:%.*]] = icmp sge ptr [[START_2]], [[HIGH]]
418; CHECK-NEXT:    call void @use(i1 [[F_2]])
419; CHECK-NEXT:    [[START_3:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 3
420; CHECK-NEXT:    [[F_3:%.*]] = icmp sge ptr [[START_3]], [[HIGH]]
421; CHECK-NEXT:    call void @use(i1 [[F_3]])
422; CHECK-NEXT:    [[START_4:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 4
423; CHECK-NEXT:    [[C_4:%.*]] = icmp sge ptr [[START_4]], [[HIGH]]
424; CHECK-NEXT:    call void @use(i1 [[C_4]])
425; CHECK-NEXT:    [[START_5:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 5
426; CHECK-NEXT:    [[C_5:%.*]] = icmp sge ptr [[START_5]], [[HIGH]]
427; CHECK-NEXT:    call void @use(i1 [[C_5]])
428; CHECK-NEXT:    ret void
429;
430entry:
431  %add.ptr.i = getelementptr inbounds i8, ptr %start, i64 3
432  %c.1 = icmp sge ptr %add.ptr.i, %high
433  br i1 %c.1, label %if.then, label %if.end
434
435if.then:
436  ret void
437
438if.end:
439  %f.0 = icmp sgt ptr %start, %high
440  call void @use(i1 %f.0)
441  %start.1 = getelementptr inbounds i8, ptr %start, i64 1
442  %f.1 = icmp sge ptr %start.1, %high
443  call void @use(i1 %f.1)
444  %start.2 = getelementptr inbounds i8, ptr %start, i64 2
445  %f.2 = icmp sge ptr %start.2, %high
446  call void @use(i1 %f.2)
447  %start.3 = getelementptr inbounds i8, ptr %start, i64 3
448  %f.3 = icmp sge ptr %start.3, %high
449  call void @use(i1 %f.3)
450  %start.4 = getelementptr inbounds i8, ptr %start, i64 4
451  %c.4 = icmp sge ptr %start.4, %high
452  call void @use(i1 %c.4)
453  %start.5 = getelementptr inbounds i8, ptr %start, i64 5
454  %c.5 = icmp sge ptr %start.5, %high
455  call void @use(i1 %c.5)
456  ret void
457}
458
459define void @test.not.sge.sge.nonconst(ptr %start, ptr %low, ptr %high, i8 %off) {
460; CHECK-LABEL: @test.not.sge.sge.nonconst(
461; CHECK-NEXT:  entry:
462; CHECK-NEXT:    [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i8 [[OFF:%.*]]
463; CHECK-NEXT:    [[C_1:%.*]] = icmp sge ptr [[ADD_PTR_I]], [[HIGH:%.*]]
464; CHECK-NEXT:    br i1 [[C_1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
465; CHECK:       if.then:
466; CHECK-NEXT:    [[START_OFF_2:%.*]] = getelementptr inbounds i8, ptr [[START]], i8 [[OFF]]
467; CHECK-NEXT:    [[T_0:%.*]] = icmp sge ptr [[START_OFF_2]], [[HIGH]]
468; CHECK-NEXT:    call void @use(i1 [[T_0]])
469; CHECK-NEXT:    ret void
470; CHECK:       if.end:
471; CHECK-NEXT:    [[START_1:%.*]] = getelementptr inbounds i8, ptr [[START]], i64 1
472; CHECK-NEXT:    [[C_0:%.*]] = icmp sge ptr [[START_1]], [[HIGH]]
473; CHECK-NEXT:    call void @use(i1 [[C_0]])
474; CHECK-NEXT:    [[START_OFF:%.*]] = getelementptr inbounds i8, ptr [[START]], i8 [[OFF]]
475; CHECK-NEXT:    [[F_0:%.*]] = icmp sge ptr [[START_OFF]], [[HIGH]]
476; CHECK-NEXT:    call void @use(i1 [[F_0]])
477; CHECK-NEXT:    ret void
478;
479entry:
480  %add.ptr.i = getelementptr inbounds i8, ptr %start, i8 %off
481  %c.1 = icmp sge ptr %add.ptr.i, %high
482  br i1 %c.1, label %if.then, label %if.end
483
484if.then:
485  %start.off.2 = getelementptr inbounds i8, ptr %start, i8 %off
486  %t.0 = icmp sge ptr %start.off.2, %high
487  call void @use(i1 %t.0)
488  ret void
489
490if.end:
491  %start.1 = getelementptr inbounds i8, ptr %start, i64 1
492  %c.0 = icmp sge ptr %start.1, %high
493  call void @use(i1 %c.0)
494  %start.off = getelementptr inbounds i8, ptr %start, i8 %off
495  %f.0 = icmp sge ptr %start.off, %high
496  call void @use(i1 %f.0)
497  ret void
498}
499
500; Test which requires decomposing GEP %ptr, SHL().
501define void @test.slt.gep.shl(ptr readonly %src, ptr readnone %max, i8 %idx) {
502; CHECK-LABEL: @test.slt.gep.shl(
503; CHECK-NEXT:  check.0.min:
504; CHECK-NEXT:    [[ADD_10:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i32 10
505; CHECK-NEXT:    [[C_ADD_10_MAX:%.*]] = icmp sgt ptr [[ADD_10]], [[MAX:%.*]]
506; CHECK-NEXT:    br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
507; CHECK:       trap:
508; CHECK-NEXT:    ret void
509; CHECK:       check.idx:
510; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[IDX:%.*]], 5
511; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
512; CHECK:       check.max:
513; CHECK-NEXT:    [[IDX_SHL_1:%.*]] = shl nuw i8 [[IDX]], 1
514; CHECK-NEXT:    [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_1]]
515; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[ADD_PTR_SHL_1]], [[MAX]]
516; CHECK-NEXT:    call void @use(i1 [[C_MAX_0]])
517; CHECK-NEXT:    [[IDX_SHL_2:%.*]] = shl nuw i8 [[IDX]], 2
518; CHECK-NEXT:    [[ADD_PTR_SHL_2:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_2]]
519; CHECK-NEXT:    [[C_MAX_1:%.*]] = icmp slt ptr [[ADD_PTR_SHL_2]], [[MAX]]
520; CHECK-NEXT:    call void @use(i1 [[C_MAX_1]])
521; CHECK-NEXT:    [[IDX_SHL_NOT_NUW:%.*]] = shl i8 [[IDX]], 1
522; CHECK-NEXT:    [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_NOT_NUW]]
523; CHECK-NEXT:    [[C_MAX_2:%.*]] = icmp slt ptr [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
524; CHECK-NEXT:    call void @use(i1 [[C_MAX_2]])
525; CHECK-NEXT:    [[IDX_SHL_3:%.*]] = shl nuw i8 [[IDX]], 3
526; CHECK-NEXT:    [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i8 [[IDX_SHL_3]]
527; CHECK-NEXT:    [[C_MAX_3:%.*]] = icmp slt ptr [[ADD_PTR_SHL_3]], [[MAX]]
528; CHECK-NEXT:    call void @use(i1 [[C_MAX_3]])
529; CHECK-NEXT:    ret void
530;
531check.0.min:
532  %add.10 = getelementptr inbounds i32, ptr %src, i32 10
533  %c.add.10.max = icmp sgt ptr %add.10, %max
534  br i1 %c.add.10.max, label %trap, label %check.idx
535
536trap:
537  ret void
538
539check.idx:
540  %cmp = icmp slt i8 %idx, 5
541  br i1 %cmp, label %check.max, label %trap
542
543check.max:
544  %idx.shl.1 = shl nuw i8 %idx, 1
545  %add.ptr.shl.1 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.1
546  %c.max.0 = icmp slt ptr %add.ptr.shl.1, %max
547  call void @use(i1 %c.max.0)
548  %idx.shl.2 = shl nuw i8 %idx, 2
549  %add.ptr.shl.2 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.2
550  %c.max.1 = icmp slt ptr %add.ptr.shl.2, %max
551  call void @use(i1 %c.max.1)
552  %idx.shl.not.nuw = shl i8 %idx, 1
553  %add.ptr.shl.not.nuw = getelementptr inbounds i32, ptr %src, i8 %idx.shl.not.nuw
554  %c.max.2 = icmp slt ptr %add.ptr.shl.not.nuw, %max
555  call void @use(i1 %c.max.2)
556  %idx.shl.3 = shl nuw i8 %idx, 3
557  %add.ptr.shl.3 = getelementptr inbounds i32, ptr %src, i8 %idx.shl.3
558  %c.max.3 = icmp slt ptr %add.ptr.shl.3, %max
559  call void @use(i1 %c.max.3)
560  ret void
561}
562
563; Test which requires decomposing GEP %ptr, ZEXT(SHL()).
564define void @test.slt.gep.shl.zext(ptr readonly %src, ptr readnone %max, i32 %idx, i32 %j) {
565; CHECK-LABEL: @test.slt.gep.shl.zext(
566; CHECK-NEXT:  check.0.min:
567; CHECK-NEXT:    [[ADD_10:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i32 10
568; CHECK-NEXT:    [[C_ADD_10_MAX:%.*]] = icmp sgt ptr [[ADD_10]], [[MAX:%.*]]
569; CHECK-NEXT:    br i1 [[C_ADD_10_MAX]], label [[TRAP:%.*]], label [[CHECK_IDX:%.*]]
570; CHECK:       trap:
571; CHECK-NEXT:    ret void
572; CHECK:       check.idx:
573; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IDX:%.*]], 5
574; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP]]
575; CHECK:       check.max:
576; CHECK-NEXT:    [[IDX_SHL:%.*]] = shl nuw i32 [[IDX]], 1
577; CHECK-NEXT:    [[EXT_1:%.*]] = zext i32 [[IDX_SHL]] to i64
578; CHECK-NEXT:    [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_1]]
579; CHECK-NEXT:    [[C_MAX_0:%.*]] = icmp slt ptr [[ADD_PTR_SHL]], [[MAX]]
580; CHECK-NEXT:    call void @use(i1 [[C_MAX_0]])
581; CHECK-NEXT:    [[IDX_SHL_NOT_NUW:%.*]] = shl i32 [[IDX]], 1
582; CHECK-NEXT:    [[EXT_2:%.*]] = zext i32 [[IDX_SHL_NOT_NUW]] to i64
583; CHECK-NEXT:    [[ADD_PTR_SHL_NOT_NUW:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_2]]
584; CHECK-NEXT:    [[C_MAX_1:%.*]] = icmp slt ptr [[ADD_PTR_SHL_NOT_NUW]], [[MAX]]
585; CHECK-NEXT:    call void @use(i1 [[C_MAX_1]])
586; CHECK-NEXT:    [[IDX_SHL_3:%.*]] = shl nuw i32 [[IDX]], 2
587; CHECK-NEXT:    [[EXT_3:%.*]] = zext i32 [[IDX_SHL_3]] to i64
588; CHECK-NEXT:    [[ADD_PTR_SHL_3:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 [[EXT_3]]
589; CHECK-NEXT:    [[C_MAX_2:%.*]] = icmp slt ptr [[ADD_PTR_SHL_3]], [[MAX]]
590; CHECK-NEXT:    call void @use(i1 [[C_MAX_2]])
591; CHECK-NEXT:    ret void
592;
593check.0.min:
594  %add.10 = getelementptr inbounds i32, ptr %src, i32 10
595  %c.add.10.max = icmp sgt ptr %add.10, %max
596  br i1 %c.add.10.max, label %trap, label %check.idx
597
598trap:
599  ret void
600
601check.idx:
602  %cmp = icmp slt i32 %idx, 5
603  br i1 %cmp, label %check.max, label %trap
604
605check.max:
606  %idx.shl = shl nuw i32 %idx, 1
607  %ext.1 = zext i32 %idx.shl to i64
608  %add.ptr.shl = getelementptr inbounds i32, ptr %src, i64 %ext.1
609  %c.max.0 = icmp slt ptr %add.ptr.shl, %max
610  call void @use(i1 %c.max.0)
611  %idx.shl.not.nuw = shl i32 %idx, 1
612  %ext.2 = zext i32 %idx.shl.not.nuw to i64
613  %add.ptr.shl.not.nuw = getelementptr inbounds i32, ptr %src, i64 %ext.2
614  %c.max.1 = icmp slt ptr %add.ptr.shl.not.nuw, %max
615  call void @use(i1 %c.max.1)
616  %idx.shl.3 = shl nuw i32 %idx, 2
617  %ext.3 = zext i32 %idx.shl.3 to i64
618  %add.ptr.shl.3 = getelementptr inbounds i32, ptr %src, i64 %ext.3
619  %c.max.2 = icmp slt ptr %add.ptr.shl.3, %max
620  call void @use(i1 %c.max.2)
621  ret void
622}
623
624; Make sure non-constant shift amounts are handled correctly.
625define i1 @test.slt.gep.shl.nonconst.zext(i16 %B, ptr readonly %src, ptr readnone %max, i16 %idx, i16 %j) {
626; CHECK-LABEL: @test.slt.gep.shl.nonconst.zext(
627; CHECK-NEXT:  check.0.min:
628; CHECK-NEXT:    [[ADD_10:%.*]] = getelementptr inbounds i16, ptr [[SRC:%.*]], i16 10
629; CHECK-NEXT:    [[C_ADD_10_MAX:%.*]] = icmp sgt ptr [[ADD_10]], [[MAX:%.*]]
630; CHECK-NEXT:    br i1 [[C_ADD_10_MAX]], label [[EXIT_1:%.*]], label [[CHECK_IDX:%.*]]
631; CHECK:       exit.1:
632; CHECK-NEXT:    ret i1 true
633; CHECK:       check.idx:
634; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[IDX:%.*]], 5
635; CHECK-NEXT:    br i1 [[CMP]], label [[CHECK_MAX:%.*]], label [[TRAP:%.*]]
636; CHECK:       check.max:
637; CHECK-NEXT:    [[IDX_SHL:%.*]] = shl nuw i16 [[IDX]], [[B:%.*]]
638; CHECK-NEXT:    [[EXT:%.*]] = zext i16 [[IDX_SHL]] to i64
639; CHECK-NEXT:    [[ADD_PTR_SHL:%.*]] = getelementptr inbounds i16, ptr [[SRC]], i64 [[EXT]]
640; CHECK-NEXT:    [[C_MAX:%.*]] = icmp slt ptr [[ADD_PTR_SHL]], [[MAX]]
641; CHECK-NEXT:    ret i1 [[C_MAX]]
642; CHECK:       trap:
643; CHECK-NEXT:    [[IDX_SHL_1:%.*]] = shl nuw i16 [[IDX]], [[B]]
644; CHECK-NEXT:    [[EXT_1:%.*]] = zext i16 [[IDX_SHL_1]] to i64
645; CHECK-NEXT:    [[ADD_PTR_SHL_1:%.*]] = getelementptr inbounds i16, ptr [[SRC]], i64 [[EXT_1]]
646; CHECK-NEXT:    [[C_MAX_1:%.*]] = icmp slt ptr [[ADD_PTR_SHL_1]], [[MAX]]
647; CHECK-NEXT:    ret i1 [[C_MAX_1]]
648;
649check.0.min:
650  %add.10 = getelementptr inbounds i16, ptr %src, i16 10
651  %c.add.10.max = icmp sgt ptr %add.10, %max
652  br i1 %c.add.10.max, label %exit.1, label %check.idx
653
654exit.1:
655  ret i1 true
656
657check.idx:
658  %cmp = icmp slt i16 %idx, 5
659  br i1 %cmp, label %check.max, label %trap
660
661check.max:
662  %idx.shl = shl nuw i16 %idx, %B
663  %ext = zext i16 %idx.shl to i64
664  %add.ptr.shl = getelementptr inbounds i16, ptr %src, i64 %ext
665  %c.max = icmp slt ptr %add.ptr.shl, %max
666  ret i1 %c.max
667
668trap:
669  %idx.shl.1 = shl nuw i16 %idx, %B
670  %ext.1 = zext i16 %idx.shl.1 to i64
671  %add.ptr.shl.1 = getelementptr inbounds i16, ptr %src, i64 %ext.1
672  %c.max.1 = icmp slt ptr %add.ptr.shl.1, %max
673  ret i1 %c.max.1
674}
675
676declare void @use(i1)
677