[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / simplify-pointer-arithmetic.ll
blob7c3562943e16e12fc19b694d79d81838788f9b7f
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes
2 ; RUN: opt -passes=indvars -S %s | FileCheck %s
4 ; Test cases inspired by PR48965.
6 ; %len is zero-extended before being used to compute %p.end, which guarantees
7 ; the offset is positive. %i.ult.ext can be simplified.
8 define i1 @can_simplify_ult_i32_ptr_len_zext(ptr %p.base, i32 %len) {
9 ; CHECK-LABEL: @can_simplify_ult_i32_ptr_len_zext(
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
12 ; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, ptr [[P_BASE:%.*]], i64 [[EXT]]
13 ; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
14 ; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
15 ; CHECK:       header.preheader:
16 ; CHECK-NEXT:    br label [[HEADER:%.*]]
17 ; CHECK:       trap.loopexit:
18 ; CHECK-NEXT:    br label [[TRAP]]
19 ; CHECK:       trap:
20 ; CHECK-NEXT:    ret i1 false
21 ; CHECK:       header:
22 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
23 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
24 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
25 ; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ult i64 [[I]], [[EXT]]
26 ; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
27 ; CHECK:       latch:
28 ; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, ptr [[P]], i64 1
29 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[P_INC]], [[P_END]]
30 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
31 ; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
32 ; CHECK:       exit:
33 ; CHECK-NEXT:    ret i1 true
35 entry:
36   %ext = zext i32 %len to i64
37   %p.end = getelementptr inbounds i32, ptr %p.base, i64 %ext
38   %len.nonzero = icmp ne i32 %len, 0
39   br i1 %len.nonzero, label %header, label %trap
41 trap:
42   ret i1 false
44 header:
45   %p = phi ptr [ %p.base, %entry ], [ %p.inc, %latch ]
46   %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
47   %i.inc = add nsw nuw i64 %i, 1
48   %i.ult.ext = icmp ult i64 %i, %ext
49   br i1 %i.ult.ext, label %latch, label %trap
51 latch:
52   %p.inc = getelementptr inbounds i32, ptr %p, i64 1
53   %c = icmp ne ptr %p.inc, %p.end
54   store i32 0, ptr %p
55   br i1 %c, label %header, label %exit
57 exit:
58   ret i1 true
61 ; %len may be (signed) negative, %i.ult.ext cannot be simplified.
62 define i1 @cannot_simplify_ult_i32_ptr_len_ult(ptr %p.base, i64 %len) {
63 ; CHECK-LABEL: @cannot_simplify_ult_i32_ptr_len_ult(
64 ; CHECK-NEXT:  entry:
65 ; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, ptr [[P_BASE:%.*]], i64 [[LEN:%.*]]
66 ; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i64 [[LEN]], 0
67 ; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
68 ; CHECK:       header.preheader:
69 ; CHECK-NEXT:    br label [[HEADER:%.*]]
70 ; CHECK:       trap.loopexit:
71 ; CHECK-NEXT:    br label [[TRAP]]
72 ; CHECK:       trap:
73 ; CHECK-NEXT:    ret i1 false
74 ; CHECK:       header:
75 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
76 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
77 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
78 ; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ult i64 [[I]], [[LEN]]
79 ; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
80 ; CHECK:       latch:
81 ; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, ptr [[P]], i64 1
82 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[P_INC]], [[P_END]]
83 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
84 ; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
85 ; CHECK:       exit:
86 ; CHECK-NEXT:    ret i1 true
88 entry:
89   %p.end = getelementptr inbounds i32, ptr %p.base, i64 %len
90   %len.nonzero = icmp ne i64 %len, 0
91   br i1 %len.nonzero, label %header, label %trap
93 trap:
94   ret i1 false
96 header:
97   %p = phi ptr [ %p.base, %entry ], [ %p.inc, %latch ]
98   %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
99   %i.inc = add nsw nuw i64 %i, 1
100   %i.ult.ext = icmp ult i64 %i, %len
101   br i1 %i.ult.ext, label %latch, label %trap
103 latch:
104   %p.inc = getelementptr inbounds i32, ptr %p, i64 1
105   %c = icmp ne ptr %p.inc, %p.end
106   store i32 0, ptr %p
107   br i1 %c, label %header, label %exit
109 exit:
110   ret i1 true
113 ; Similar to can_simplify_ult_i32_ptr_len_zext, but %i has 1 as start value. %i.ult.ext cannot be simplified.
114 define i1 @cannot_simplify_ult_i32_ptr_len_zext(ptr %p.base, i32 %len) {
115 ; CHECK-LABEL: @cannot_simplify_ult_i32_ptr_len_zext(
116 ; CHECK-NEXT:  entry:
117 ; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
118 ; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, ptr [[P_BASE:%.*]], i64 [[EXT]]
119 ; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
120 ; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
121 ; CHECK:       header.preheader:
122 ; CHECK-NEXT:    br label [[HEADER:%.*]]
123 ; CHECK:       trap.loopexit:
124 ; CHECK-NEXT:    br label [[TRAP]]
125 ; CHECK:       trap:
126 ; CHECK-NEXT:    ret i1 false
127 ; CHECK:       header:
128 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
129 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 1, [[HEADER_PREHEADER]] ]
130 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
131 ; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ult i64 [[I]], [[EXT]]
132 ; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
133 ; CHECK:       latch:
134 ; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, ptr [[P]], i64 1
135 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[P_INC]], [[P_END]]
136 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
137 ; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
138 ; CHECK:       exit:
139 ; CHECK-NEXT:    ret i1 true
141 entry:
142   %ext = zext i32 %len to i64
143   %p.end = getelementptr inbounds i32, ptr %p.base, i64 %ext
144   %len.nonzero = icmp ne i32 %len, 0
145   br i1 %len.nonzero, label %header, label %trap
147 trap:
148   ret i1 false
150 header:
151   %p = phi ptr [ %p.base, %entry ], [ %p.inc, %latch ]
152   %i = phi i64 [ 1, %entry ], [ %i.inc, %latch]
153   %i.inc = add nsw nuw i64 %i, 1
154   %i.ult.ext = icmp ult i64 %i, %ext
155   br i1 %i.ult.ext, label %latch, label %trap
157 latch:
158   %p.inc = getelementptr inbounds i32, ptr %p, i64 1
159   %c = icmp ne ptr %p.inc, %p.end
160   store i32 0, ptr %p
161   br i1 %c, label %header, label %exit
163 exit:
164   ret i1 true
167 define i1 @can_simplify_ule_i32_ptr_len_zext(ptr %p.base, i32 %len) {
168 ; CHECK-LABEL: @can_simplify_ule_i32_ptr_len_zext(
169 ; CHECK-NEXT:  entry:
170 ; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
171 ; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, ptr [[P_BASE:%.*]], i64 [[EXT]]
172 ; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
173 ; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
174 ; CHECK:       header.preheader:
175 ; CHECK-NEXT:    br label [[HEADER:%.*]]
176 ; CHECK:       trap.loopexit:
177 ; CHECK-NEXT:    br label [[TRAP]]
178 ; CHECK:       trap:
179 ; CHECK-NEXT:    ret i1 false
180 ; CHECK:       header:
181 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
182 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 1, [[HEADER_PREHEADER]] ]
183 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
184 ; CHECK-NEXT:    [[I_ULT_EXT:%.*]] = icmp ule i64 [[I]], [[EXT]]
185 ; CHECK-NEXT:    br i1 [[I_ULT_EXT]], label [[LATCH]], label [[TRAP_LOOPEXIT:%.*]]
186 ; CHECK:       latch:
187 ; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, ptr [[P]], i64 1
188 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[P_INC]], [[P_END]]
189 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
190 ; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
191 ; CHECK:       exit:
192 ; CHECK-NEXT:    ret i1 true
194 entry:
195   %ext = zext i32 %len to i64
196   %p.end = getelementptr inbounds i32, ptr %p.base, i64 %ext
197   %len.nonzero = icmp ne i32 %len, 0
198   br i1 %len.nonzero, label %header, label %trap
200 trap:
201   ret i1 false
203 header:
204   %p = phi ptr [ %p.base, %entry ], [ %p.inc, %latch ]
205   %i = phi i64 [ 1, %entry ], [ %i.inc, %latch]
206   %i.inc = add nsw nuw i64 %i, 1
207   %i.ult.ext = icmp ule i64 %i, %ext
208   br i1 %i.ult.ext, label %latch, label %trap
210 latch:
211   %p.inc = getelementptr inbounds i32, ptr %p, i64 1
212   %c = icmp ne ptr %p.inc, %p.end
213   store i32 0, ptr %p
214   br i1 %c, label %header, label %exit
216 exit:
217   ret i1 true
220 ; %len is zero-extended before being used to compute %p.end, which guarantees
221 ; the offset is positive. %i.uge.ext can be simplified.
222 define i1 @can_simplify_uge_i32_ptr_len_zext(ptr %p.base, i32 %len) {
223 ; CHECK-LABEL: @can_simplify_uge_i32_ptr_len_zext(
224 ; CHECK-NEXT:  entry:
225 ; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
226 ; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, ptr [[P_BASE:%.*]], i64 [[EXT]]
227 ; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
228 ; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
229 ; CHECK:       header.preheader:
230 ; CHECK-NEXT:    br label [[HEADER:%.*]]
231 ; CHECK:       trap.loopexit:
232 ; CHECK-NEXT:    br label [[TRAP]]
233 ; CHECK:       trap:
234 ; CHECK-NEXT:    ret i1 false
235 ; CHECK:       header:
236 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
237 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
238 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
239 ; CHECK-NEXT:    [[I_UGE_EXT:%.*]] = icmp uge i64 [[I]], [[EXT]]
240 ; CHECK-NEXT:    br i1 [[I_UGE_EXT]], label [[TRAP_LOOPEXIT:%.*]], label [[LATCH]]
241 ; CHECK:       latch:
242 ; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, ptr [[P]], i64 1
243 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[P_INC]], [[P_END]]
244 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
245 ; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
246 ; CHECK:       exit:
247 ; CHECK-NEXT:    ret i1 true
249 entry:
250   %ext = zext i32 %len to i64
251   %p.end = getelementptr inbounds i32, ptr %p.base, i64 %ext
252   %len.nonzero = icmp ne i32 %len, 0
253   br i1 %len.nonzero, label %header, label %trap
255 trap:
256   ret i1 false
258 header:
259   %p = phi ptr [ %p.base, %entry ], [ %p.inc, %latch ]
260   %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
261   %i.inc = add nsw nuw i64 %i, 1
262   %i.uge.ext = icmp uge i64 %i, %ext
263   br i1 %i.uge.ext, label %trap, label %latch
265 latch:
266   %p.inc = getelementptr inbounds i32, ptr %p, i64 1
267   %c = icmp ne ptr %p.inc, %p.end
268   store i32 0, ptr %p
269   br i1 %c, label %header, label %exit
271 exit:
272   ret i1 true
275 define i1 @cannot_simplify_uge_i32_ptr_len(ptr %p.base, i64 %len) {
276 ; CHECK-LABEL: @cannot_simplify_uge_i32_ptr_len(
277 ; CHECK-NEXT:  entry:
278 ; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, ptr [[P_BASE:%.*]], i64 [[LEN:%.*]]
279 ; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i64 [[LEN]], 0
280 ; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
281 ; CHECK:       header.preheader:
282 ; CHECK-NEXT:    br label [[HEADER:%.*]]
283 ; CHECK:       trap.loopexit:
284 ; CHECK-NEXT:    br label [[TRAP]]
285 ; CHECK:       trap:
286 ; CHECK-NEXT:    ret i1 false
287 ; CHECK:       header:
288 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
289 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
290 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 1
291 ; CHECK-NEXT:    [[I_UGE_EXT:%.*]] = icmp uge i64 [[I]], [[LEN]]
292 ; CHECK-NEXT:    br i1 [[I_UGE_EXT]], label [[TRAP_LOOPEXIT:%.*]], label [[LATCH]]
293 ; CHECK:       latch:
294 ; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, ptr [[P]], i64 1
295 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[P_INC]], [[P_END]]
296 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
297 ; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
298 ; CHECK:       exit:
299 ; CHECK-NEXT:    ret i1 true
301 entry:
302   %p.end = getelementptr inbounds i32, ptr %p.base, i64 %len
303   %len.nonzero = icmp ne i64 %len, 0
304   br i1 %len.nonzero, label %header, label %trap
306 trap:
307   ret i1 false
309 header:
310   %p = phi ptr [ %p.base, %entry ], [ %p.inc, %latch ]
311   %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
312   %i.inc = add nsw nuw i64 %i, 1
313   %i.uge.ext = icmp uge i64 %i, %len
314   br i1 %i.uge.ext, label %trap, label %latch
316 latch:
317   %p.inc = getelementptr inbounds i32, ptr %p, i64 1
318   %c = icmp ne ptr %p.inc, %p.end
319   store i32 0, ptr %p
320   br i1 %c, label %header, label %exit
322 exit:
323   ret i1 true
326 define i1 @cannot_simplify_uge_i32_ptr_len_zext_step_2(ptr %p.base, i32 %len) {
327 ; CHECK-LABEL: @cannot_simplify_uge_i32_ptr_len_zext_step_2(
328 ; CHECK-NEXT:  entry:
329 ; CHECK-NEXT:    [[EXT:%.*]] = zext i32 [[LEN:%.*]] to i64
330 ; CHECK-NEXT:    [[P_END:%.*]] = getelementptr inbounds i32, ptr [[P_BASE:%.*]], i64 [[EXT]]
331 ; CHECK-NEXT:    [[LEN_NONZERO:%.*]] = icmp ne i32 [[LEN]], 0
332 ; CHECK-NEXT:    br i1 [[LEN_NONZERO]], label [[HEADER_PREHEADER:%.*]], label [[TRAP:%.*]]
333 ; CHECK:       header.preheader:
334 ; CHECK-NEXT:    br label [[HEADER:%.*]]
335 ; CHECK:       trap.loopexit:
336 ; CHECK-NEXT:    br label [[TRAP]]
337 ; CHECK:       trap:
338 ; CHECK-NEXT:    ret i1 false
339 ; CHECK:       header:
340 ; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_INC:%.*]], [[LATCH:%.*]] ], [ [[P_BASE]], [[HEADER_PREHEADER]] ]
341 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_INC:%.*]], [[LATCH]] ], [ 0, [[HEADER_PREHEADER]] ]
342 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i64 [[I]], 2
343 ; CHECK-NEXT:    [[I_UGE_EXT:%.*]] = icmp uge i64 [[I]], [[EXT]]
344 ; CHECK-NEXT:    br i1 [[I_UGE_EXT]], label [[TRAP_LOOPEXIT:%.*]], label [[LATCH]]
345 ; CHECK:       latch:
346 ; CHECK-NEXT:    [[P_INC]] = getelementptr inbounds i32, ptr [[P]], i64 1
347 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[P_INC]], [[P_END]]
348 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
349 ; CHECK-NEXT:    br i1 [[C]], label [[HEADER]], label [[EXIT:%.*]]
350 ; CHECK:       exit:
351 ; CHECK-NEXT:    ret i1 true
353 entry:
354   %ext = zext i32 %len to i64
355   %p.end = getelementptr inbounds i32, ptr %p.base, i64 %ext
356   %len.nonzero = icmp ne i32 %len, 0
357   br i1 %len.nonzero, label %header, label %trap
359 trap:
360   ret i1 false
362 header:
363   %p = phi ptr [ %p.base, %entry ], [ %p.inc, %latch ]
364   %i = phi i64 [ 0, %entry ], [ %i.inc, %latch]
365   %i.inc = add nsw nuw i64 %i, 2
366   %i.uge.ext = icmp uge i64 %i, %ext
367   br i1 %i.uge.ext, label %trap, label %latch
369 latch:
370   %p.inc = getelementptr inbounds i32, ptr %p, i64 1
371   %c = icmp ne ptr %p.inc, %p.end
372   store i32 0, ptr %p
373   br i1 %c, label %header, label %exit
375 exit:
376   ret i1 true