[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / loops-header-tested-pointer-cmps.ll
blob6a347db138a415cf0c36870b39de0f50db74e864
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -constraint-elimination -S %s | FileCheck %s
4 declare void @use(i1)
6 define void @test1(i8* %src, i8* noundef %lower, i8* noundef %upper, i8 %N) {
7 ; CHECK-LABEL: @test1(
8 ; CHECK-NEXT:  entry:
9 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i8 [[N:%.*]]
10 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
11 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
12 ; CHECK-NEXT:    [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
13 ; CHECK-NEXT:    br i1 [[OR_0]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]]
14 ; CHECK:       trap.bb:
15 ; CHECK-NEXT:    ret void
16 ; CHECK:       loop.header:
17 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ]
18 ; CHECK-NEXT:    [[EC:%.*]] = icmp uge i8 [[IV]], [[N]]
19 ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]]
20 ; CHECK:       loop.body:
21 ; CHECK-NEXT:    [[SRC_IV:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[IV]]
22 ; CHECK-NEXT:    [[CMP_IV_START:%.*]] = icmp ult i8* [[SRC_IV]], [[LOWER]]
23 ; CHECK-NEXT:    [[CMP_IV_END:%.*]] = icmp uge i8* [[SRC_IV]], [[UPPER]]
24 ; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[CMP_IV_START]], false
25 ; CHECK-NEXT:    br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]]
26 ; CHECK:       loop.body.1:
27 ; CHECK-NEXT:    [[PTR_SRC_IV:%.*]] = bitcast i8* [[SRC_IV]] to i32*
28 ; CHECK-NEXT:    store i32 0, i32* [[PTR_SRC_IV]], align 4
29 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[IV]], 1
30 ; CHECK-NEXT:    [[SRC_IV_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_1]]
31 ; CHECK-NEXT:    [[CMP_IV_1_START:%.*]] = icmp ult i8* [[SRC_IV_1]], [[LOWER]]
32 ; CHECK-NEXT:    [[CMP_IV_1_END:%.*]] = icmp uge i8* [[SRC_IV_1]], [[UPPER]]
33 ; CHECK-NEXT:    [[OR_2:%.*]] = or i1 false, false
34 ; CHECK-NEXT:    br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]]
35 ; CHECK:       loop.body.2:
36 ; CHECK-NEXT:    [[PTR_SRC_IV_1:%.*]] = bitcast i8* [[SRC_IV_1]] to i32*
37 ; CHECK-NEXT:    store i32 0, i32* [[PTR_SRC_IV_1]], align 4
38 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2
39 ; CHECK-NEXT:    [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]]
40 ; CHECK-NEXT:    [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]]
41 ; CHECK-NEXT:    [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]]
42 ; CHECK-NEXT:    [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]]
43 ; CHECK-NEXT:    br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]]
44 ; CHECK:       loop.latch:
45 ; CHECK-NEXT:    [[PTR_SRC_IV_2:%.*]] = bitcast i8* [[SRC_IV_2]] to i32*
46 ; CHECK-NEXT:    store i32 0, i32* [[PTR_SRC_IV_2]], align 4
47 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
48 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
49 ; CHECK:       exit:
50 ; CHECK-NEXT:    ret void
52 entry:
53   %src.end = getelementptr inbounds i8, i8* %src, i8 %N
54   %cmp.src.start = icmp ult i8* %src, %lower
55   %cmp.src.end = icmp uge i8* %src.end, %upper
56   %or.0 = or i1 %cmp.src.start, %cmp.src.end
57   br i1 %or.0, label %trap.bb, label %loop.header
59 trap.bb:
60   ret void
62 loop.header:
63   %iv = phi i8 [ %iv.next, %loop.latch ], [ 0, %entry ]
64   %ec = icmp uge i8 %iv, %N
65   br i1 %ec, label %exit, label %loop.body
67 loop.body:
68   %src.iv = getelementptr inbounds i8, i8* %src, i8 %iv
69   %cmp.iv.start = icmp ult i8* %src.iv, %lower
70   %cmp.iv.end = icmp uge i8* %src.iv, %upper
71   %or.1 = or i1 %cmp.iv.start, %cmp.iv.end
72   br i1 %or.1, label %trap.bb, label %loop.body.1
74 loop.body.1:
75   %ptr.src.iv = bitcast i8* %src.iv to i32*
76   store i32 0, i32* %ptr.src.iv, align 4
77   %add.1 = add nuw nsw i8 %iv, 1
78   %src.iv.1 = getelementptr inbounds i8, i8* %src, i8 %add.1
79   %cmp.iv.1.start = icmp ult i8* %src.iv.1, %lower
80   %cmp.iv.1.end = icmp uge i8* %src.iv.1, %upper
81   %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end
82   br i1 %or.2, label %trap.bb, label %loop.body.2
84 loop.body.2:
85   %ptr.src.iv.1 = bitcast i8* %src.iv.1 to i32*
86   store i32 0, i32* %ptr.src.iv.1, align 4
87   %add.2 = add nuw nsw i8 %iv, 2
88   %src.iv.2 = getelementptr inbounds i8, i8* %src, i8 %add.2
89   %cmp.iv.2.start = icmp ult i8* %src.iv.2, %lower
90   %cmp.iv.2.end = icmp uge i8* %src.iv.2, %upper
91   %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end
92   br i1 %or.3, label %trap.bb, label %loop.latch
95 loop.latch:
96   %ptr.src.iv.2 = bitcast i8* %src.iv.2 to i32*
97   store i32 0, i32* %ptr.src.iv.2, align 4
98   %iv.next = add nuw nsw i8 %iv, 1
99   br label %loop.header
101 exit:
102   ret void
105 define void @test2(i8* %src, i8* %lower, i8* %upper, i8 %N) {
106 ; CHECK-LABEL: @test2(
107 ; CHECK-NEXT:  entry:
108 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i8 [[N:%.*]]
109 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
110 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
111 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt i8* [[SRC]], [[SRC_END]]
112 ; CHECK-NEXT:    [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
113 ; CHECK-NEXT:    [[OR_11:%.*]] = or i1 [[OR_0]], [[CMP_OVERFLOW]]
114 ; CHECK-NEXT:    br i1 [[OR_11]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]]
115 ; CHECK:       trap.bb:
116 ; CHECK-NEXT:    ret void
117 ; CHECK:       loop.header:
118 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ]
119 ; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i8 [[IV]], 2
120 ; CHECK-NEXT:    [[EC:%.*]] = icmp uge i8 [[NEXT]], [[N]]
121 ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]]
122 ; CHECK:       loop.body:
123 ; CHECK-NEXT:    [[SRC_IV:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[IV]]
124 ; CHECK-NEXT:    [[CMP_IV_START:%.*]] = icmp ult i8* [[SRC_IV]], [[LOWER]]
125 ; CHECK-NEXT:    [[CMP_IV_END:%.*]] = icmp uge i8* [[SRC_IV]], [[UPPER]]
126 ; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[CMP_IV_START]], [[CMP_IV_END]]
127 ; CHECK-NEXT:    br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]]
128 ; CHECK:       loop.body.1:
129 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[IV]], 1
130 ; CHECK-NEXT:    [[SRC_IV_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_1]]
131 ; CHECK-NEXT:    [[CMP_IV_1_START:%.*]] = icmp ult i8* [[SRC_IV_1]], [[LOWER]]
132 ; CHECK-NEXT:    [[CMP_IV_1_END:%.*]] = icmp uge i8* [[SRC_IV_1]], [[UPPER]]
133 ; CHECK-NEXT:    [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]]
134 ; CHECK-NEXT:    br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]]
135 ; CHECK:       loop.body.2:
136 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2
137 ; CHECK-NEXT:    [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]]
138 ; CHECK-NEXT:    [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]]
139 ; CHECK-NEXT:    [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]]
140 ; CHECK-NEXT:    [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]]
141 ; CHECK-NEXT:    br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]]
142 ; CHECK:       loop.latch:
143 ; CHECK-NEXT:    [[PTR:%.*]] = bitcast i8* [[SRC_IV]] to i32*
144 ; CHECK-NEXT:    store i32 0, i32* [[PTR]], align 4
145 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
146 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
147 ; CHECK:       exit:
148 ; CHECK-NEXT:    ret void
150 entry:
151   %src.end = getelementptr inbounds i8, i8* %src, i8 %N
152   %cmp.src.start = icmp ult i8* %src, %lower
153   %cmp.src.end = icmp uge i8* %src.end, %upper
154   %cmp.overflow = icmp ugt i8* %src, %src.end
155   %or.0 = or i1 %cmp.src.start, %cmp.src.end
156   %or.11 = or i1 %or.0, %cmp.overflow
157   br i1 %or.11, label %trap.bb, label %loop.header
159 trap.bb:
160   ret void
162 loop.header:
163   %iv = phi i8 [ %iv.next, %loop.latch ], [ 1, %entry ]
164   %next = add nsw nuw i8 %iv, 2
165   %ec = icmp uge i8 %next, %N
166   br i1 %ec, label %exit, label %loop.body
168 loop.body:
169   %src.iv = getelementptr inbounds i8, i8* %src, i8 %iv
170   %cmp.iv.start = icmp ult i8* %src.iv, %lower
171   %cmp.iv.end = icmp uge i8* %src.iv, %upper
172   %or.1 = or i1 %cmp.iv.start, %cmp.iv.end
173   br i1 %or.1, label %trap.bb, label %loop.body.1
175 loop.body.1:
176   %add.1 = add nsw nuw i8 %iv, 1
177   %src.iv.1 = getelementptr inbounds i8, i8* %src, i8 %add.1
178   %cmp.iv.1.start = icmp ult i8* %src.iv.1, %lower
179   %cmp.iv.1.end = icmp uge i8* %src.iv.1, %upper
180   %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end
181   br i1 %or.2, label %trap.bb, label %loop.body.2
183 loop.body.2:
184   %add.2 = add nsw nuw i8 %iv, 2
185   %src.iv.2 = getelementptr inbounds i8, i8* %src, i8 %add.2
186   %cmp.iv.2.start = icmp ult i8* %src.iv.2, %lower
187   %cmp.iv.2.end = icmp uge i8* %src.iv.2, %upper
188   %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end
189   br i1 %or.3, label %trap.bb, label %loop.latch
191 loop.latch:
192   %ptr = bitcast i8* %src.iv to i32*
193   store i32 0, i32* %ptr, align 4
194   %iv.next = add nuw nsw i8 %iv, 1
195   br label %loop.header
197 exit:
198   ret void
201 define void @test2_with_ne(i8* %src, i8* %lower, i8* %upper, i8 %N) {
202 ; CHECK-LABEL: @test2_with_ne(
203 ; CHECK-NEXT:  entry:
204 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i8 [[N:%.*]]
205 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
206 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
207 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt i8* [[SRC]], [[SRC_END]]
208 ; CHECK-NEXT:    [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
209 ; CHECK-NEXT:    [[OR_11:%.*]] = or i1 [[OR_0]], [[CMP_OVERFLOW]]
210 ; CHECK-NEXT:    br i1 [[OR_11]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]]
211 ; CHECK:       trap.bb:
212 ; CHECK-NEXT:    ret void
213 ; CHECK:       loop.header:
214 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ]
215 ; CHECK-NEXT:    [[NEXT:%.*]] = add nuw nsw i8 [[IV]], 1
216 ; CHECK-NEXT:    [[EC:%.*]] = icmp eq i8 [[NEXT]], [[N]]
217 ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_BODY:%.*]]
218 ; CHECK:       loop.body:
219 ; CHECK-NEXT:    [[SRC_IV:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[IV]]
220 ; CHECK-NEXT:    [[CMP_IV_START:%.*]] = icmp ult i8* [[SRC_IV]], [[LOWER]]
221 ; CHECK-NEXT:    [[CMP_IV_END:%.*]] = icmp uge i8* [[SRC_IV]], [[UPPER]]
222 ; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[CMP_IV_START]], [[CMP_IV_END]]
223 ; CHECK-NEXT:    br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]]
224 ; CHECK:       loop.body.1:
225 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[IV]], 1
226 ; CHECK-NEXT:    [[SRC_IV_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_1]]
227 ; CHECK-NEXT:    [[CMP_IV_1_START:%.*]] = icmp ult i8* [[SRC_IV_1]], [[LOWER]]
228 ; CHECK-NEXT:    [[CMP_IV_1_END:%.*]] = icmp uge i8* [[SRC_IV_1]], [[UPPER]]
229 ; CHECK-NEXT:    [[OR_2:%.*]] = or i1 false, [[CMP_IV_1_END]]
230 ; CHECK-NEXT:    br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]]
231 ; CHECK:       loop.body.2:
232 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2
233 ; CHECK-NEXT:    [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]]
234 ; CHECK-NEXT:    [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]]
235 ; CHECK-NEXT:    [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]]
236 ; CHECK-NEXT:    [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]]
237 ; CHECK-NEXT:    br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]]
238 ; CHECK:       loop.latch:
239 ; CHECK-NEXT:    [[PTR:%.*]] = bitcast i8* [[SRC_IV]] to i32*
240 ; CHECK-NEXT:    store i32 0, i32* [[PTR]], align 4
241 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
242 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
243 ; CHECK:       exit:
244 ; CHECK-NEXT:    ret void
246 entry:
247   %src.end = getelementptr inbounds i8, i8* %src, i8 %N
248   %cmp.src.start = icmp ult i8* %src, %lower
249   %cmp.src.end = icmp uge i8* %src.end, %upper
250   %cmp.overflow = icmp ugt i8* %src, %src.end
251   %or.0 = or i1 %cmp.src.start, %cmp.src.end
252   %or.11 = or i1 %or.0, %cmp.overflow
253   br i1 %or.11, label %trap.bb, label %loop.header
255 trap.bb:
256   ret void
258 loop.header:
259   %iv = phi i8 [ %iv.next, %loop.latch ], [ 1, %entry ]
260   %next = add nsw nuw i8 %iv, 1
261   %ec = icmp eq i8 %next, %N
262   br i1 %ec, label %exit, label %loop.body
264 loop.body:
265   %src.iv = getelementptr inbounds i8, i8* %src, i8 %iv
266   %cmp.iv.start = icmp ult i8* %src.iv, %lower
267   %cmp.iv.end = icmp uge i8* %src.iv, %upper
268   %or.1 = or i1 %cmp.iv.start, %cmp.iv.end
269   br i1 %or.1, label %trap.bb, label %loop.body.1
271 loop.body.1:
272   %add.1 = add nsw nuw i8 %iv, 1
273   %src.iv.1 = getelementptr inbounds i8, i8* %src, i8 %add.1
274   %cmp.iv.1.start = icmp ult i8* %src.iv.1, %lower
275   %cmp.iv.1.end = icmp uge i8* %src.iv.1, %upper
276   %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end
277   br i1 %or.2, label %trap.bb, label %loop.body.2
279 loop.body.2:
280   %add.2 = add nsw nuw i8 %iv, 2
281   %src.iv.2 = getelementptr inbounds i8, i8* %src, i8 %add.2
282   %cmp.iv.2.start = icmp ult i8* %src.iv.2, %lower
283   %cmp.iv.2.end = icmp uge i8* %src.iv.2, %upper
284   %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end
285   br i1 %or.3, label %trap.bb, label %loop.latch
287 loop.latch:
288   %ptr = bitcast i8* %src.iv to i32*
289   store i32 0, i32* %ptr, align 4
290   %iv.next = add nuw nsw i8 %iv, 1
291   br label %loop.header
293 exit:
294   ret void
298 define void @test3(i8* %src, i8* %lower, i8* %upper, i8 %N) {
299 ; CHECK-LABEL: @test3(
300 ; CHECK-NEXT:  entry:
301 ; CHECK-NEXT:    [[SRC_END:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i8 [[N:%.*]]
302 ; CHECK-NEXT:    [[CMP_SRC_START:%.*]] = icmp ult i8* [[SRC]], [[LOWER:%.*]]
303 ; CHECK-NEXT:    [[CMP_SRC_END:%.*]] = icmp uge i8* [[SRC_END]], [[UPPER:%.*]]
304 ; CHECK-NEXT:    [[CMP_OVERFLOW:%.*]] = icmp ugt i8* [[SRC]], [[SRC_END]]
305 ; CHECK-NEXT:    [[OR_0:%.*]] = or i1 [[CMP_SRC_START]], [[CMP_SRC_END]]
306 ; CHECK-NEXT:    [[OR_11:%.*]] = or i1 [[OR_0]], [[CMP_OVERFLOW]]
307 ; CHECK-NEXT:    br i1 [[OR_11]], label [[TRAP_BB:%.*]], label [[LOOP_HEADER:%.*]]
308 ; CHECK:       trap.bb:
309 ; CHECK-NEXT:    ret void
310 ; CHECK:       loop.header:
311 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ]
312 ; CHECK-NEXT:    [[NEXT:%.*]] = or i8 [[IV]], 1
313 ; CHECK-NEXT:    [[EC:%.*]] = icmp ult i8 [[NEXT]], [[N]]
314 ; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_BODY:%.*]], label [[EXIT:%.*]]
315 ; CHECK:       loop.body:
316 ; CHECK-NEXT:    [[SRC_IV:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[IV]]
317 ; CHECK-NEXT:    [[CMP_IV_START:%.*]] = icmp ult i8* [[SRC_IV]], [[LOWER]]
318 ; CHECK-NEXT:    [[CMP_IV_END:%.*]] = icmp uge i8* [[SRC_IV]], [[UPPER]]
319 ; CHECK-NEXT:    [[OR_1:%.*]] = or i1 [[CMP_IV_START]], [[CMP_IV_END]]
320 ; CHECK-NEXT:    br i1 [[OR_1]], label [[TRAP_BB]], label [[LOOP_BODY_1:%.*]]
321 ; CHECK:       loop.body.1:
322 ; CHECK-NEXT:    [[SRC_IV_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[NEXT]]
323 ; CHECK-NEXT:    [[CMP_IV_1_START:%.*]] = icmp ult i8* [[SRC_IV_1]], [[LOWER]]
324 ; CHECK-NEXT:    [[CMP_IV_1_END:%.*]] = icmp uge i8* [[SRC_IV_1]], [[UPPER]]
325 ; CHECK-NEXT:    [[OR_2:%.*]] = or i1 [[CMP_IV_1_START]], [[CMP_IV_1_END]]
326 ; CHECK-NEXT:    br i1 [[OR_2]], label [[TRAP_BB]], label [[LOOP_BODY_2:%.*]]
327 ; CHECK:       loop.body.2:
328 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[IV]], 2
329 ; CHECK-NEXT:    [[SRC_IV_2:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i8 [[ADD_2]]
330 ; CHECK-NEXT:    [[CMP_IV_2_START:%.*]] = icmp ult i8* [[SRC_IV_2]], [[LOWER]]
331 ; CHECK-NEXT:    [[CMP_IV_2_END:%.*]] = icmp uge i8* [[SRC_IV_2]], [[UPPER]]
332 ; CHECK-NEXT:    [[OR_3:%.*]] = or i1 false, [[CMP_IV_2_END]]
333 ; CHECK-NEXT:    br i1 [[OR_3]], label [[TRAP_BB]], label [[LOOP_LATCH]]
334 ; CHECK:       loop.latch:
335 ; CHECK-NEXT:    [[PTR:%.*]] = bitcast i8* [[SRC_IV]] to i32*
336 ; CHECK-NEXT:    store i32 0, i32* [[PTR]], align 4
337 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
338 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
339 ; CHECK:       exit:
340 ; CHECK-NEXT:    ret void
342 entry:
343   %src.end = getelementptr inbounds i8, i8* %src, i8 %N
344   %cmp.src.start = icmp ult i8* %src, %lower
345   %cmp.src.end = icmp uge i8* %src.end, %upper
346   %cmp.overflow = icmp ugt i8* %src, %src.end
347   %or.0 = or i1 %cmp.src.start, %cmp.src.end
348   %or.11 = or i1 %or.0, %cmp.overflow
349   br i1 %or.11, label %trap.bb, label %loop.header
351 trap.bb:
352   ret void
354 loop.header:
355   %iv = phi i8 [ %iv.next, %loop.latch ], [ 1, %entry ]
356   %next = or i8 %iv, 1
357   %ec = icmp ult i8 %next, %N
358   br i1 %ec, label %loop.body, label %exit
360 loop.body:
361   %src.iv = getelementptr inbounds i8, i8* %src, i8 %iv
362   %cmp.iv.start = icmp ult i8* %src.iv, %lower
363   %cmp.iv.end = icmp uge i8* %src.iv, %upper
364   %or.1 = or i1 %cmp.iv.start, %cmp.iv.end
365   br i1 %or.1, label %trap.bb, label %loop.body.1
367 loop.body.1:
368   %src.iv.1 = getelementptr inbounds i8, i8* %src, i8 %next
369   %cmp.iv.1.start = icmp ult i8* %src.iv.1, %lower
370   %cmp.iv.1.end = icmp uge i8* %src.iv.1, %upper
371   %or.2 = or i1 %cmp.iv.1.start, %cmp.iv.1.end
372   br i1 %or.2, label %trap.bb, label %loop.body.2
374 loop.body.2:
375   %add.2 = add nsw nuw i8 %iv, 2
376   %src.iv.2 = getelementptr inbounds i8, i8* %src, i8 %add.2
377   %cmp.iv.2.start = icmp ult i8* %src.iv.2, %lower
378   %cmp.iv.2.end = icmp uge i8* %src.iv.2, %upper
379   %or.3 = or i1 %cmp.iv.2.start, %cmp.iv.2.end
380   br i1 %or.3, label %trap.bb, label %loop.latch
382 loop.latch:
383   %ptr = bitcast i8* %src.iv to i32*
384   store i32 0, i32* %ptr, align 4
385   %iv.next = add nuw nsw i8 %iv, 1
386   br label %loop.header
388 exit:
389   ret void
392 ; Cannot remove checks, because %n may be negative.
393 define void @ne_check_in_loop_no_zext_n_may_be_negative(i8* %ptr, i8* %lower, i8* %upper, i16 %n) {
394 ; CHECK-LABEL: @ne_check_in_loop_no_zext_n_may_be_negative(
395 ; CHECK-NEXT:  entry:
396 ; CHECK-NEXT:    [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
397 ; CHECK-NEXT:    br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE:%.*]]
398 ; CHECK:       pre:
399 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[N:%.*]]
400 ; CHECK-NEXT:    [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[ADD_PTR]], [[UPPER:%.*]]
401 ; CHECK-NEXT:    br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]]
402 ; CHECK:       for.cond.preheader:
403 ; CHECK-NEXT:    br label [[FOR_HEADER:%.*]]
404 ; CHECK:       trap:
405 ; CHECK-NEXT:    ret void
406 ; CHECK:       for.header:
407 ; CHECK-NEXT:    [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ]
408 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[N]]
409 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
410 ; CHECK:       for.body:
411 ; CHECK-NEXT:    [[GEP_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[IV]]
412 ; CHECK-NEXT:    [[CMP_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV]]
413 ; CHECK-NEXT:    [[CMP_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV]]
414 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP_IV_LOWER]], [[CMP_IV_UPPER]]
415 ; CHECK-NEXT:    br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]]
416 ; CHECK:       for.body.1:
417 ; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1
418 ; CHECK-NEXT:    [[GEP_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[ADD]]
419 ; CHECK-NEXT:    [[CMP_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV_1]]
420 ; CHECK-NEXT:    [[CMP_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV_1]]
421 ; CHECK-NEXT:    [[OR_1:%.*]] = or i1 false, [[CMP_IV_1_UPPER]]
422 ; CHECK-NEXT:    br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]]
423 ; CHECK:       for.latch:
424 ; CHECK-NEXT:    store i8 0, i8* [[GEP_IV]], align 4
425 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1
426 ; CHECK-NEXT:    br label [[FOR_HEADER]]
427 ; CHECK:       for.end:
428 ; CHECK-NEXT:    ret void
430 entry:
431   %cmp.ptr.lower = icmp ult i8* %ptr, %lower
432   br i1 %cmp.ptr.lower, label %trap, label %pre
434 pre:
435   %add.ptr = getelementptr inbounds i8, i8* %ptr, i16 %n
436   %cmp.ptr.n.upper = icmp ult i8* %add.ptr, %upper
437   br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap
439 for.cond.preheader:
440   br label %for.header
442 trap:
443   ret void
445 for.header:
446   %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ]
447   %exitcond = icmp ne i16 %iv, %n
448   br i1 %exitcond, label %for.body, label %for.end
450 for.body:
451   %gep.iv = getelementptr inbounds i8, i8* %ptr, i16 %iv
452   %cmp.iv.lower = icmp ugt i8* %lower, %gep.iv
453   %cmp.iv.upper = icmp ule i8* %upper, %gep.iv
454   %or = or i1 %cmp.iv.lower, %cmp.iv.upper
455   br i1 %or, label %trap, label %for.body.1
457 for.body.1:
458   %add = add nuw nsw i16 %iv, 1
459   %gep.iv.1 = getelementptr inbounds i8, i8* %ptr, i16 %add
460   %cmp.iv.1.lower = icmp ugt i8* %lower, %gep.iv.1
461   %cmp.iv.1.upper = icmp ule i8* %upper, %gep.iv.1
462   %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper
463   br i1 %or.1, label %trap, label %for.latch
465 for.latch:
466   store i8 0, i8* %gep.iv, align 4
467   %iv.next = add nuw nsw i16 %iv, 1
468   br label %for.header
470 for.end:
471   ret void
474 ; Should be able to remove the checks in the loop, because %n is signed positive.
475 define void @ne_check_in_loop_no_zext_n_positive_check(i8* %ptr, i8* %lower, i8* %upper, i16 %n) {
476 ; CHECK-LABEL: @ne_check_in_loop_no_zext_n_positive_check(
477 ; CHECK-NEXT:  entry:
478 ; CHECK-NEXT:    [[N_SIGNED_POSITIVE:%.*]] = icmp slt i16 [[N:%.*]], 0
479 ; CHECK-NEXT:    [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
480 ; CHECK-NEXT:    [[OR_T:%.*]] = or i1 [[N_SIGNED_POSITIVE]], [[CMP_PTR_LOWER]]
481 ; CHECK-NEXT:    br i1 [[OR_T]], label [[TRAP:%.*]], label [[PRE:%.*]]
482 ; CHECK:       pre:
483 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[N]]
484 ; CHECK-NEXT:    [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[ADD_PTR]], [[UPPER:%.*]]
485 ; CHECK-NEXT:    br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]]
486 ; CHECK:       for.cond.preheader:
487 ; CHECK-NEXT:    br label [[FOR_HEADER:%.*]]
488 ; CHECK:       trap:
489 ; CHECK-NEXT:    ret void
490 ; CHECK:       for.header:
491 ; CHECK-NEXT:    [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ]
492 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[N]]
493 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
494 ; CHECK:       for.body:
495 ; CHECK-NEXT:    [[GEP_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[IV]]
496 ; CHECK-NEXT:    [[CMP_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV]]
497 ; CHECK-NEXT:    [[CMP_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV]]
498 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP_IV_LOWER]], [[CMP_IV_UPPER]]
499 ; CHECK-NEXT:    br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]]
500 ; CHECK:       for.body.1:
501 ; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1
502 ; CHECK-NEXT:    [[GEP_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[ADD]]
503 ; CHECK-NEXT:    [[CMP_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV_1]]
504 ; CHECK-NEXT:    [[CMP_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV_1]]
505 ; CHECK-NEXT:    [[OR_1:%.*]] = or i1 false, [[CMP_IV_1_UPPER]]
506 ; CHECK-NEXT:    br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]]
507 ; CHECK:       for.latch:
508 ; CHECK-NEXT:    store i8 0, i8* [[GEP_IV]], align 4
509 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1
510 ; CHECK-NEXT:    br label [[FOR_HEADER]]
511 ; CHECK:       for.end:
512 ; CHECK-NEXT:    ret void
514 entry:
515   %n.signed.positive = icmp slt i16 %n, 0
516   %cmp.ptr.lower = icmp ult i8* %ptr, %lower
517   %or.t = or i1 %n.signed.positive, %cmp.ptr.lower
518   br i1 %or.t, label %trap, label %pre
520 pre:
521   %add.ptr = getelementptr inbounds i8, i8* %ptr, i16 %n
522   %cmp.ptr.n.upper = icmp ult i8* %add.ptr, %upper
523   br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap
525 for.cond.preheader:
526   br label %for.header
528 trap:
529   ret void
531 for.header:
532   %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ]
533   %exitcond = icmp ne i16 %iv, %n
534   br i1 %exitcond, label %for.body, label %for.end
536 for.body:
537   %gep.iv = getelementptr inbounds i8, i8* %ptr, i16 %iv
538   %cmp.iv.lower = icmp ugt i8* %lower, %gep.iv
539   %cmp.iv.upper = icmp ule i8* %upper, %gep.iv
540   %or = or i1 %cmp.iv.lower, %cmp.iv.upper
541   br i1 %or, label %trap, label %for.body.1
543 for.body.1:
544   %add = add nuw nsw i16 %iv, 1
545   %gep.iv.1 = getelementptr inbounds i8, i8* %ptr, i16 %add
546   %cmp.iv.1.lower = icmp ugt i8* %lower, %gep.iv.1
547   %cmp.iv.1.upper = icmp ule i8* %upper, %gep.iv.1
548   %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper
549   br i1 %or.1, label %trap, label %for.latch
551 for.latch:
552   store i8 0, i8* %gep.iv, align 4
553   %iv.next = add nuw nsw i16 %iv, 1
554   br label %for.header
556 for.end:
557   ret void
560 ; Make sure icmp ne of the induction variable in the loop body can be handled
561 ; and is treated as ule.
562 define void @ne_check_in_loop_with_zext(i8* %ptr, i8* %lower, i8* %upper, i8 %n) {
563 ; CHECK-LABEL: @ne_check_in_loop_with_zext(
564 ; CHECK-NEXT:  entry:
565 ; CHECK-NEXT:    [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
566 ; CHECK-NEXT:    br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE:%.*]]
567 ; CHECK:       pre:
568 ; CHECK-NEXT:    [[IDX_EXT:%.*]] = zext i8 [[N:%.*]] to i16
569 ; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[IDX_EXT]]
570 ; CHECK-NEXT:    [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[ADD_PTR]], [[UPPER:%.*]]
571 ; CHECK-NEXT:    br i1 [[CMP_PTR_N_UPPER]], label [[FOR_COND_PREHEADER:%.*]], label [[TRAP]]
572 ; CHECK:       for.cond.preheader:
573 ; CHECK-NEXT:    br label [[FOR_HEADER:%.*]]
574 ; CHECK:       trap:
575 ; CHECK-NEXT:    ret void
576 ; CHECK:       for.header:
577 ; CHECK-NEXT:    [[IV:%.*]] = phi i16 [ 0, [[FOR_COND_PREHEADER]] ], [ [[IV_NEXT:%.*]], [[FOR_LATCH:%.*]] ]
578 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i16 [[IV]], [[IDX_EXT]]
579 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
580 ; CHECK:       for.body:
581 ; CHECK-NEXT:    [[GEP_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[IV]]
582 ; CHECK-NEXT:    [[CMP_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV]]
583 ; CHECK-NEXT:    [[CMP_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV]]
584 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP_IV_LOWER]], [[CMP_IV_UPPER]]
585 ; CHECK-NEXT:    br i1 [[OR]], label [[TRAP]], label [[FOR_BODY_1:%.*]]
586 ; CHECK:       for.body.1:
587 ; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i16 [[IV]], 1
588 ; CHECK-NEXT:    [[GEP_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i16 [[ADD]]
589 ; CHECK-NEXT:    [[CMP_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[GEP_IV_1]]
590 ; CHECK-NEXT:    [[CMP_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[GEP_IV_1]]
591 ; CHECK-NEXT:    [[OR_1:%.*]] = or i1 false, [[CMP_IV_1_UPPER]]
592 ; CHECK-NEXT:    br i1 [[OR_1]], label [[TRAP]], label [[FOR_LATCH]]
593 ; CHECK:       for.latch:
594 ; CHECK-NEXT:    store i8 0, i8* [[GEP_IV]], align 4
595 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1
596 ; CHECK-NEXT:    br label [[FOR_HEADER]]
597 ; CHECK:       for.end:
598 ; CHECK-NEXT:    ret void
600 entry:
601   %cmp.ptr.lower = icmp ult i8* %ptr, %lower
602   br i1 %cmp.ptr.lower, label %trap, label %pre
604 pre:
605   %idx.ext = zext i8 %n to i16
606   %add.ptr = getelementptr inbounds i8, i8* %ptr, i16 %idx.ext
607   %cmp.ptr.n.upper = icmp ult i8* %add.ptr, %upper
608   br i1 %cmp.ptr.n.upper, label %for.cond.preheader, label %trap
610 for.cond.preheader:
611   br label %for.header
613 trap:
614   ret void
616 for.header:
617   %iv = phi i16 [ 0, %for.cond.preheader ], [ %iv.next, %for.latch ]
618   %exitcond = icmp ne i16 %iv, %idx.ext
619   br i1 %exitcond, label %for.body, label %for.end
621 for.body:
622   %gep.iv = getelementptr inbounds i8, i8* %ptr, i16 %iv
623   %cmp.iv.lower = icmp ugt i8* %lower, %gep.iv
624   %cmp.iv.upper = icmp ule i8* %upper, %gep.iv
625   %or = or i1 %cmp.iv.lower, %cmp.iv.upper
626   br i1 %or, label %trap, label %for.body.1
628 for.body.1:
629   %add = add nuw nsw i16 %iv, 1
630   %gep.iv.1 = getelementptr inbounds i8, i8* %ptr, i16 %add
631   %cmp.iv.1.lower = icmp ugt i8* %lower, %gep.iv.1
632   %cmp.iv.1.upper = icmp ule i8* %upper, %gep.iv.1
633   %or.1 = or i1 %cmp.iv.1.lower, %cmp.iv.1.upper
634   br i1 %or.1, label %trap, label %for.latch
636 for.latch:
637   store i8 0, i8* %gep.iv, align 4
638   %iv.next = add nuw nsw i16 %iv, 1
639   br label %for.header
641 for.end:
642   ret void
645 define void @test_ptr_need_one_upper_check(i32* readonly %src, i32* %dst, i32 %n) {
646 ; CHECK-LABEL: @test_ptr_need_one_upper_check(
647 ; CHECK-NEXT:  entry:
648 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
649 ; CHECK:       loop.header:
650 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[LOOP_LATCH_2:%.*]] ]
651 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[I_0]], [[N:%.*]]
652 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP_CHECK_1:%.*]], label [[EXIT:%.*]]
653 ; CHECK:       loop.check.1:
654 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[N]] to i64
655 ; CHECK-NEXT:    [[SRC_UPPER:%.*]] = getelementptr inbounds i32, i32* [[SRC:%.*]], i64 [[TMP0]]
656 ; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_0]], 2
657 ; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[ADD]] to i64
658 ; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[IDXPROM]]
659 ; CHECK-NEXT:    [[CMP_SRC_IDX_UPPER:%.*]] = icmp ult i32* [[SRC_IDX]], [[SRC_UPPER]]
660 ; CHECK-NEXT:    call void @use(i1 [[CMP_SRC_IDX_UPPER]])
661 ; CHECK-NEXT:    br i1 [[CMP_SRC_IDX_UPPER]], label [[LOOP_LATCH:%.*]], label [[EXIT]]
662 ; CHECK:       loop.latch:
663 ; CHECK-NEXT:    [[DST_UPPER:%.*]] = getelementptr inbounds i32, i32* [[DST:%.*]], i64 [[TMP0]]
664 ; CHECK-NEXT:    [[DST_IDX:%.*]] = getelementptr inbounds i32, i32* [[DST]], i64 [[IDXPROM]]
665 ; CHECK-NEXT:    [[CMP_DST_IDX_UPPER:%.*]] = icmp ult i32* [[DST_IDX]], [[DST_UPPER]]
666 ; CHECK-NEXT:    call void @use(i1 true)
667 ; CHECK-NEXT:    br i1 true, label [[LOOP_LATCH_2]], label [[EXIT]]
668 ; CHECK:       loop.latch.2:
669 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
670 ; CHECK:       exit:
671 ; CHECK-NEXT:    ret void
673 entry:
674   br label %loop.header
676 loop.header:
677   %i.0 = phi i32 [ 0, %entry ], [ %add, %loop.latch.2 ]
678   %cmp = icmp ult i32 %i.0, %n
679   br i1 %cmp, label %loop.check.1, label %exit
681 loop.check.1:
682   %0 = zext i32 %n to i64
683   %src.upper = getelementptr inbounds i32, i32* %src, i64 %0
684   %add = add nuw nsw i32 %i.0, 2
685   %idxprom = zext i32 %add to i64
686   %src.idx = getelementptr inbounds i32, i32* %src, i64 %idxprom
687   %cmp.src.idx.upper = icmp ult i32* %src.idx, %src.upper
688   call void @use(i1 %cmp.src.idx.upper)
689   br i1 %cmp.src.idx.upper, label %loop.latch, label %exit
691 loop.latch:
692   %dst.upper = getelementptr inbounds i32, i32* %dst, i64 %0
693   %dst.idx = getelementptr inbounds i32, i32* %dst, i64 %idxprom
694   %cmp.dst.idx.upper = icmp ult i32* %dst.idx, %dst.upper
695   call void @use(i1 %cmp.dst.idx.upper)
696   br i1 %cmp.dst.idx.upper, label %loop.latch.2, label %exit
698 loop.latch.2:
699   br label %loop.header
701 exit:
702   ret void
705 ; Same as test_ptr_need_one_upper_check, but without inbounds GEP.
706 define void @test_ptr_need_one_upper_check_no_inbounds(i32* readonly %src, i32* %dst, i32 %n) {
707 ; CHECK-LABEL: @test_ptr_need_one_upper_check_no_inbounds(
708 ; CHECK-NEXT:  entry:
709 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
710 ; CHECK:       loop.header:
711 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[LOOP_LATCH_2:%.*]] ]
712 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[I_0]], [[N:%.*]]
713 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP_CHECK_1:%.*]], label [[EXIT:%.*]]
714 ; CHECK:       loop.check.1:
715 ; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[N]] to i64
716 ; CHECK-NEXT:    [[SRC_UPPER:%.*]] = getelementptr i32, i32* [[SRC:%.*]], i64 [[TMP0]]
717 ; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_0]], 2
718 ; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[ADD]] to i64
719 ; CHECK-NEXT:    [[SRC_IDX:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 [[IDXPROM]]
720 ; CHECK-NEXT:    [[CMP_SRC_IDX_UPPER:%.*]] = icmp ult i32* [[SRC_IDX]], [[SRC_UPPER]]
721 ; CHECK-NEXT:    call void @use(i1 [[CMP_SRC_IDX_UPPER]])
722 ; CHECK-NEXT:    br i1 [[CMP_SRC_IDX_UPPER]], label [[LOOP_LATCH:%.*]], label [[EXIT]]
723 ; CHECK:       loop.latch:
724 ; CHECK-NEXT:    [[DST_UPPER:%.*]] = getelementptr i32, i32* [[DST:%.*]], i64 [[TMP0]]
725 ; CHECK-NEXT:    [[DST_IDX:%.*]] = getelementptr inbounds i32, i32* [[DST]], i64 [[IDXPROM]]
726 ; CHECK-NEXT:    [[CMP_DST_IDX_UPPER:%.*]] = icmp ult i32* [[DST_IDX]], [[DST_UPPER]]
727 ; CHECK-NEXT:    call void @use(i1 [[CMP_DST_IDX_UPPER]])
728 ; CHECK-NEXT:    br i1 [[CMP_DST_IDX_UPPER]], label [[LOOP_LATCH_2]], label [[EXIT]]
729 ; CHECK:       loop.latch.2:
730 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
731 ; CHECK:       exit:
732 ; CHECK-NEXT:    ret void
734 entry:
735   br label %loop.header
737 loop.header:
738   %i.0 = phi i32 [ 0, %entry ], [ %add, %loop.latch.2 ]
739   %cmp = icmp ult i32 %i.0, %n
740   br i1 %cmp, label %loop.check.1, label %exit
742 loop.check.1:
743   %0 = zext i32 %n to i64
744   %src.upper = getelementptr i32, i32* %src, i64 %0
745   %add = add nuw nsw i32 %i.0, 2
746   %idxprom = zext i32 %add to i64
747   %src.idx = getelementptr inbounds i32, i32* %src, i64 %idxprom
748   %cmp.src.idx.upper = icmp ult i32* %src.idx, %src.upper
749   call void @use(i1 %cmp.src.idx.upper)
750   br i1 %cmp.src.idx.upper, label %loop.latch, label %exit
752 loop.latch:
753   %dst.upper = getelementptr i32, i32* %dst, i64 %0
754   %dst.idx = getelementptr inbounds i32, i32* %dst, i64 %idxprom
755   %cmp.dst.idx.upper = icmp ult i32* %dst.idx, %dst.upper
756   call void @use(i1 %cmp.dst.idx.upper)
757   br i1 %cmp.dst.idx.upper, label %loop.latch.2, label %exit
759 loop.latch.2:
760   br label %loop.header
762 exit:
763   ret void