Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / InstCombine / sub-gep.ll
blob5f336b49323ec00707e027bc4d434cadde169681
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-p2:32:32"
6 define i64 @test_inbounds(ptr %base, i64 %idx) {
7 ; CHECK-LABEL: @test_inbounds(
8 ; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2
9 ; CHECK-NEXT:    ret i64 [[P2_IDX]]
11   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
12   %i1 = ptrtoint ptr %base to i64
13   %i2 = ptrtoint ptr %p2 to i64
14   %d = sub i64 %i2, %i1
15   ret i64 %d
18 define i64 @test_partial_inbounds1(ptr %base, i64 %idx) {
19 ; CHECK-LABEL: @test_partial_inbounds1(
20 ; CHECK-NEXT:    [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2
21 ; CHECK-NEXT:    ret i64 [[P2_IDX]]
23   %p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx
24   %i1 = ptrtoint ptr %base to i64
25   %i2 = ptrtoint ptr %p2 to i64
26   %d = sub i64 %i2, %i1
27   ret i64 %d
30 define i64 @test_partial_inbounds2(ptr %base, i64 %idx) {
31 ; CHECK-LABEL: @test_partial_inbounds2(
32 ; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2
33 ; CHECK-NEXT:    ret i64 [[P2_IDX]]
35   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
36   %i1 = ptrtoint ptr %base to i64
37   %i2 = ptrtoint ptr %p2 to i64
38   %d = sub i64 %i2, %i1
39   ret i64 %d
42 define i64 @test_inbounds_nuw(ptr %base, i64 %idx) {
43 ; CHECK-LABEL: @test_inbounds_nuw(
44 ; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nuw nsw i64 [[IDX:%.*]], 2
45 ; CHECK-NEXT:    ret i64 [[P2_IDX]]
47   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
48   %i1 = ptrtoint ptr %base to i64
49   %i2 = ptrtoint ptr %p2 to i64
50   %d = sub nuw i64 %i2, %i1
51   ret i64 %d
54 define i64 @test_nuw(ptr %base, i64 %idx) {
55 ; CHECK-LABEL: @test_nuw(
56 ; CHECK-NEXT:    [[P2_IDX:%.*]] = shl i64 [[IDX:%.*]], 2
57 ; CHECK-NEXT:    ret i64 [[P2_IDX]]
59   %p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx
60   %i1 = ptrtoint ptr %base to i64
61   %i2 = ptrtoint ptr %p2 to i64
62   %d = sub nuw i64 %i2, %i1
63   ret i64 %d
66 define i32 @test_inbounds_nuw_trunc(ptr %base, i64 %idx) {
67 ; CHECK-LABEL: @test_inbounds_nuw_trunc(
68 ; CHECK-NEXT:    [[IDX_TR:%.*]] = trunc i64 [[IDX:%.*]] to i32
69 ; CHECK-NEXT:    [[D:%.*]] = shl i32 [[IDX_TR]], 2
70 ; CHECK-NEXT:    ret i32 [[D]]
72   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
73   %i1 = ptrtoint ptr %base to i64
74   %i2 = ptrtoint ptr %p2 to i64
75   %t1 = trunc i64 %i1 to i32
76   %t2 = trunc i64 %i2 to i32
77   %d = sub nuw i32 %t2, %t1
78   ret i32 %d
81 define i64 @test_inbounds_nuw_swapped(ptr %base, i64 %idx) {
82 ; CHECK-LABEL: @test_inbounds_nuw_swapped(
83 ; CHECK-NEXT:    [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
84 ; CHECK-NEXT:    ret i64 [[P2_IDX_NEG]]
86   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
87   %i1 = ptrtoint ptr %p2 to i64
88   %i2 = ptrtoint ptr %base to i64
89   %d = sub nuw i64 %i2, %i1
90   ret i64 %d
93 define i64 @test_inbounds1_nuw_swapped(ptr %base, i64 %idx) {
94 ; CHECK-LABEL: @test_inbounds1_nuw_swapped(
95 ; CHECK-NEXT:    [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
96 ; CHECK-NEXT:    ret i64 [[P2_IDX_NEG]]
98   %p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx
99   %i1 = ptrtoint ptr %p2 to i64
100   %i2 = ptrtoint ptr %base to i64
101   %d = sub nuw i64 %i2, %i1
102   ret i64 %d
105 define i64 @test_inbounds2_nuw_swapped(ptr %base, i64 %idx) {
106 ; CHECK-LABEL: @test_inbounds2_nuw_swapped(
107 ; CHECK-NEXT:    [[P2_IDX_NEG:%.*]] = mul i64 [[IDX:%.*]], -4
108 ; CHECK-NEXT:    ret i64 [[P2_IDX_NEG]]
110   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
111   %i1 = ptrtoint ptr %p2 to i64
112   %i2 = ptrtoint ptr %base to i64
113   %d = sub nuw i64 %i2, %i1
114   ret i64 %d
117 define i64 @test_inbounds_two_gep(ptr %base, i64 %idx, i64 %idx2) {
118 ; CHECK-LABEL: @test_inbounds_two_gep(
119 ; CHECK-NEXT:    [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
120 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
121 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
123   %p1 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
124   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx2
125   %i1 = ptrtoint ptr %p1 to i64
126   %i2 = ptrtoint ptr %p2 to i64
127   %d = sub i64 %i2, %i1
128   ret i64 %d
131 define i64 @test_inbounds_nsw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
132 ; CHECK-LABEL: @test_inbounds_nsw_two_gep(
133 ; CHECK-NEXT:    [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
134 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
135 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
137   %p1 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
138   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx2
139   %i1 = ptrtoint ptr %p1 to i64
140   %i2 = ptrtoint ptr %p2 to i64
141   %d = sub nsw i64 %i2, %i1
142   ret i64 %d
145 define i64 @test_inbounds_nuw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
146 ; CHECK-LABEL: @test_inbounds_nuw_two_gep(
147 ; CHECK-NEXT:    [[TMP1:%.*]] = sub nsw i64 [[IDX2:%.*]], [[IDX:%.*]]
148 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nsw i64 [[TMP1]], 2
149 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
151   %p1 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx
152   %p2 = getelementptr inbounds [0 x i32], ptr %base, i64 0, i64 %idx2
153   %i1 = ptrtoint ptr %p1 to i64
154   %i2 = ptrtoint ptr %p2 to i64
155   %d = sub nuw i64 %i2, %i1
156   ret i64 %d
159 define i64 @test_nusw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
160 ; CHECK-LABEL: @test_nusw_two_gep(
161 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
162 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
163 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
165   %p1 = getelementptr nusw [0 x i32], ptr %base, i64 0, i64 %idx
166   %p2 = getelementptr nusw [0 x i32], ptr %base, i64 0, i64 %idx2
167   %i1 = ptrtoint ptr %p1 to i64
168   %i2 = ptrtoint ptr %p2 to i64
169   %d = sub i64 %i2, %i1
170   ret i64 %d
173 define i64 @test_nuw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
174 ; CHECK-LABEL: @test_nuw_two_gep(
175 ; CHECK-NEXT:    [[TMP1:%.*]] = sub nuw i64 [[IDX2:%.*]], [[IDX:%.*]]
176 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl nuw i64 [[TMP1]], 2
177 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
179   %p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
180   %p2 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx2
181   %i1 = ptrtoint ptr %p1 to i64
182   %i2 = ptrtoint ptr %p2 to i64
183   %d = sub nuw i64 %i2, %i1
184   ret i64 %d
187 define i64 @test_nuw_two_gep_missing_nuw_on_sub(ptr %base, i64 %idx, i64 %idx2) {
188 ; CHECK-LABEL: @test_nuw_two_gep_missing_nuw_on_sub(
189 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
190 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
191 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
193   %p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
194   %p2 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx2
195   %i1 = ptrtoint ptr %p1 to i64
196   %i2 = ptrtoint ptr %p2 to i64
197   %d = sub i64 %i2, %i1
198   ret i64 %d
201 define i64 @test_nuw_two_gep_missing_nuw_on_one_gep(ptr %base, i64 %idx, i64 %idx2) {
202 ; CHECK-LABEL: @test_nuw_two_gep_missing_nuw_on_one_gep(
203 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
204 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
205 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
207   %p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
208   %p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx2
209   %i1 = ptrtoint ptr %p1 to i64
210   %i2 = ptrtoint ptr %p2 to i64
211   %d = sub nuw i64 %i2, %i1
212   ret i64 %d
215 define i64 @test_inbounds_nuw_multi_index(ptr %base, i64 %idx, i64 %idx2) {
216 ; CHECK-LABEL: @test_inbounds_nuw_multi_index(
217 ; CHECK-NEXT:    [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 3
218 ; CHECK-NEXT:    [[P2_IDX1:%.*]] = shl nsw i64 [[IDX2:%.*]], 2
219 ; CHECK-NEXT:    [[P2_OFFS:%.*]] = add nsw i64 [[P2_IDX]], [[P2_IDX1]]
220 ; CHECK-NEXT:    ret i64 [[P2_OFFS]]
222   %p2 = getelementptr inbounds [0 x [2 x i32]], ptr %base, i64 0, i64 %idx, i64 %idx2
223   %i1 = ptrtoint ptr %base to i64
224   %i2 = ptrtoint ptr %p2 to i64
225   %d = sub nuw i64 %i2, %i1
226   ret i64 %d
229 ; rdar://7362831
230 define i32 @test23(ptr %P, i64 %A){
231 ; CHECK-LABEL: @test23(
232 ; CHECK-NEXT:    [[G:%.*]] = trunc i64 [[A:%.*]] to i32
233 ; CHECK-NEXT:    ret i32 [[G]]
235   %B = getelementptr inbounds i8, ptr %P, i64 %A
236   %C = ptrtoint ptr %B to i64
237   %D = trunc i64 %C to i32
238   %E = ptrtoint ptr %P to i64
239   %F = trunc i64 %E to i32
240   %G = sub i32 %D, %F
241   ret i32 %G
244 define i8 @test23_as1(ptr addrspace(1) %P, i16 %A) {
245 ; CHECK-LABEL: @test23_as1(
246 ; CHECK-NEXT:    [[G:%.*]] = trunc i16 [[A:%.*]] to i8
247 ; CHECK-NEXT:    ret i8 [[G]]
249   %B = getelementptr inbounds i8, ptr addrspace(1) %P, i16 %A
250   %C = ptrtoint ptr addrspace(1) %B to i16
251   %D = trunc i16 %C to i8
252   %E = ptrtoint ptr addrspace(1) %P to i16
253   %F = trunc i16 %E to i8
254   %G = sub i8 %D, %F
255   ret i8 %G
258 define i64 @test24(ptr %P, i64 %A){
259 ; CHECK-LABEL: @test24(
260 ; CHECK-NEXT:    ret i64 [[A:%.*]]
262   %B = getelementptr inbounds i8, ptr %P, i64 %A
263   %C = ptrtoint ptr %B to i64
264   %E = ptrtoint ptr %P to i64
265   %G = sub i64 %C, %E
266   ret i64 %G
269 define i16 @test24_as1(ptr addrspace(1) %P, i16 %A) {
270 ; CHECK-LABEL: @test24_as1(
271 ; CHECK-NEXT:    ret i16 [[A:%.*]]
273   %B = getelementptr inbounds i8, ptr addrspace(1) %P, i16 %A
274   %C = ptrtoint ptr addrspace(1) %B to i16
275   %E = ptrtoint ptr addrspace(1) %P to i16
276   %G = sub i16 %C, %E
277   ret i16 %G
280 define i64 @test24a(ptr %P, i64 %A){
281 ; CHECK-LABEL: @test24a(
282 ; CHECK-NEXT:    [[DIFF_NEG:%.*]] = sub i64 0, [[A:%.*]]
283 ; CHECK-NEXT:    ret i64 [[DIFF_NEG]]
285   %B = getelementptr inbounds i8, ptr %P, i64 %A
286   %C = ptrtoint ptr %B to i64
287   %E = ptrtoint ptr %P to i64
288   %G = sub i64 %E, %C
289   ret i64 %G
292 define i16 @test24a_as1(ptr addrspace(1) %P, i16 %A) {
293 ; CHECK-LABEL: @test24a_as1(
294 ; CHECK-NEXT:    [[DIFF_NEG:%.*]] = sub i16 0, [[A:%.*]]
295 ; CHECK-NEXT:    ret i16 [[DIFF_NEG]]
297   %B = getelementptr inbounds i8, ptr addrspace(1) %P, i16 %A
298   %C = ptrtoint ptr addrspace(1) %B to i16
299   %E = ptrtoint ptr addrspace(1) %P to i16
300   %G = sub i16 %E, %C
301   ret i16 %G
304 @Arr = external global [42 x i16]
306 define i64 @test24b(ptr %P, i64 %A){
307 ; CHECK-LABEL: @test24b(
308 ; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
309 ; CHECK-NEXT:    ret i64 [[B_IDX]]
311   %B = getelementptr inbounds [42 x i16], ptr @Arr, i64 0, i64 %A
312   %C = ptrtoint ptr %B to i64
313   %G = sub i64 %C, ptrtoint (ptr @Arr to i64)
314   ret i64 %G
317 define i64 @test25(ptr %P, i64 %A){
318 ; CHECK-LABEL: @test25(
319 ; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
320 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = add nsw i64 [[B_IDX]], -84
321 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
323   %B = getelementptr inbounds [42 x i16], ptr @Arr, i64 0, i64 %A
324   %C = ptrtoint ptr %B to i64
325   %G = sub i64 %C, ptrtoint (ptr getelementptr ([42 x i16], ptr @Arr, i64 1, i64 0) to i64)
326   ret i64 %G
329 define i64 @zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
330 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint(
331 ; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
332 ; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
333 ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
334 ; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 4294967294
335 ; CHECK-NEXT:    [[D:%.*]] = sub i64 [[C]], ptrtoint (ptr @Arr to i64)
336 ; CHECK-NEXT:    ret i64 [[D]]
338   %A = getelementptr bfloat, ptr @Arr, i32 %offset
339   %B = ptrtoint ptr %A to i32
340   %C = zext i32 %B to i64
341   %D = sub i64 %C, ptrtoint (ptr @Arr to i64)
342   ret i64 %D
345 define i64 @ptrtoint_sub_zext_ptrtoint(ptr %p, i32 %offset) {
346 ; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint(
347 ; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
348 ; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
349 ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
350 ; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 4294967294
351 ; CHECK-NEXT:    [[D:%.*]] = sub i64 ptrtoint (ptr @Arr to i64), [[C]]
352 ; CHECK-NEXT:    ret i64 [[D]]
354   %A = getelementptr bfloat, ptr @Arr, i32 %offset
355   %B = ptrtoint ptr %A to i32
356   %C = zext i32 %B to i64
357   %D = sub i64 ptrtoint (ptr @Arr to i64), %C
358   ret i64 %D
361 define i64 @negative_zext_ptrtoint_sub_ptrtoint(ptr %p, i32 %offset) {
362 ; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint(
363 ; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
364 ; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
365 ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
366 ; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 65534
367 ; CHECK-NEXT:    [[D:%.*]] = sub i64 [[C]], ptrtoint (ptr @Arr to i64)
368 ; CHECK-NEXT:    ret i64 [[D]]
370   %A = getelementptr bfloat, ptr @Arr, i32 %offset
371   %B = ptrtoint ptr %A to i16
372   %C = zext i16 %B to i64
373   %D = sub i64 %C, ptrtoint (ptr @Arr to i64)
374   ret i64 %D
377 define i64 @negative_ptrtoint_sub_zext_ptrtoint(ptr %p, i32 %offset) {
378 ; CHECK-LABEL: @negative_ptrtoint_sub_zext_ptrtoint(
379 ; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[OFFSET:%.*]] to i64
380 ; CHECK-NEXT:    [[A:%.*]] = getelementptr bfloat, ptr @Arr, i64 [[TMP1]]
381 ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
382 ; CHECK-NEXT:    [[C:%.*]] = and i64 [[TMP2]], 65534
383 ; CHECK-NEXT:    [[D:%.*]] = sub i64 ptrtoint (ptr @Arr to i64), [[C]]
384 ; CHECK-NEXT:    ret i64 [[D]]
386   %A = getelementptr bfloat, ptr @Arr, i32 %offset
387   %B = ptrtoint ptr %A to i16
388   %C = zext i16 %B to i64
389   %D = sub i64 ptrtoint (ptr @Arr to i64), %C
390   ret i64 %D
393 @Arr_as1 = external addrspace(1) global [42 x i16]
395 define i16 @test25_as1(ptr addrspace(1) %P, i64 %A) {
396 ; CHECK-LABEL: @test25_as1(
397 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i16
398 ; CHECK-NEXT:    [[B_IDX:%.*]] = shl nsw i16 [[TMP1]], 1
399 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = add nsw i16 [[B_IDX]], -84
400 ; CHECK-NEXT:    ret i16 [[GEPDIFF]]
402   %B = getelementptr inbounds [42 x i16], ptr addrspace(1) @Arr_as1, i64 0, i64 %A
403   %C = ptrtoint ptr addrspace(1) %B to i16
404   %G = sub i16 %C, ptrtoint (ptr addrspace(1) getelementptr ([42 x i16], ptr addrspace(1) @Arr_as1, i64 1, i64 0) to i16)
405   ret i16 %G
408 @Arr_as2 = external addrspace(2) global [42 x i16]
410 define i64 @ptrtoint_sub_zext_ptrtoint_as2_inbounds(i32 %offset) {
411 ; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2_inbounds(
412 ; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 [[OFFSET:%.*]]
413 ; CHECK-NEXT:    [[B:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
414 ; CHECK-NEXT:    [[C:%.*]] = zext i32 [[B]] to i64
415 ; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), [[C]]
416 ; CHECK-NEXT:    ret i64 [[D]]
418   %A = getelementptr inbounds bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
419   %B = ptrtoint ptr addrspace(2) %A to i32
420   %C = zext i32 %B to i64
421   %D = sub i64 ptrtoint (ptr addrspace(2) @Arr_as2 to i64), %C
422   ret i64 %D
425 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw(i32 %offset) {
426 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw(
427 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
428 ; CHECK-NEXT:    [[D:%.*]] = sext i32 [[A_IDX]] to i64
429 ; CHECK-NEXT:    ret i64 [[D]]
431   %A = getelementptr nusw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
432   %B = ptrtoint ptr addrspace(2) %A to i32
433   %C = zext i32 %B to i64
434   %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
435   ret i64 %D
438 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
439 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nuw(
440 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
441 ; CHECK-NEXT:    [[D:%.*]] = zext i32 [[A_IDX]] to i64
442 ; CHECK-NEXT:    ret i64 [[D]]
444   %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
445   %B = ptrtoint ptr addrspace(2) %A to i32
446   %C = zext i32 %B to i64
447   %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
448   ret i64 %D
451 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw(i32 %offset) {
452 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw(
453 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 1
454 ; CHECK-NEXT:    [[D:%.*]] = zext nneg i32 [[A_IDX]] to i64
455 ; CHECK-NEXT:    ret i64 [[D]]
457   %A = getelementptr nusw nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
458   %B = ptrtoint ptr addrspace(2) %A to i32
459   %C = zext i32 %B to i64
460   %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
461   ret i64 %D
464 define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw(i32 %offset) {
465 ; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw(
466 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
467 ; CHECK-NEXT:    [[E:%.*]] = sext i32 [[A_IDX]] to i64
468 ; CHECK-NEXT:    ret i64 [[E]]
470   %A = getelementptr nusw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
471   %B = ptrtoint ptr addrspace(2) %A to i32
472   %C = zext i32 %B to i64
473   %D = zext i32 ptrtoint (ptr addrspace(2) @Arr_as2 to i32) to i64
474   %E = sub i64 %C, %D
475   ret i64 %E
478 define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(i32 %offset) {
479 ; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw(
480 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
481 ; CHECK-NEXT:    [[E:%.*]] = zext i32 [[A_IDX]] to i64
482 ; CHECK-NEXT:    ret i64 [[E]]
484   %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
485   %B = ptrtoint ptr addrspace(2) %A to i32
486   %C = zext i32 %B to i64
487   %D = zext i32 ptrtoint (ptr addrspace(2) @Arr_as2 to i32) to i64
488   %E = sub i64 %C, %D
489   ret i64 %E
492 define i64 @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(i32 %offset) {
493 ; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw(
494 ; CHECK-NEXT:    [[A:%.*]] = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 [[OFFSET:%.*]]
495 ; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
496 ; CHECK-NEXT:    [[B_MASK:%.*]] = and i32 [[TMP1]], 65534
497 ; CHECK-NEXT:    [[C:%.*]] = zext nneg i32 [[B_MASK]] to i64
498 ; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 [[C]], ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
499 ; CHECK-NEXT:    ret i64 [[D]]
501   %A = getelementptr nuw bfloat, ptr addrspace(2) @Arr_as2, i32 %offset
502   %B = ptrtoint ptr addrspace(2) %A to i16
503   %C = zext i16 %B to i64
504   %D = sub i64 %C, ptrtoint (ptr addrspace(2) @Arr_as2 to i64)
505   ret i64 %D
508 define i64 @ptrtoint_sub_zext_ptrtoint_as2_inbounds_local(ptr addrspace(2) %p, i32 %offset) {
509 ; CHECK-LABEL: @ptrtoint_sub_zext_ptrtoint_as2_inbounds_local(
510 ; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds bfloat, ptr addrspace(2) [[P:%.*]], i32 [[OFFSET:%.*]]
511 ; CHECK-NEXT:    [[B:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
512 ; CHECK-NEXT:    [[C:%.*]] = zext i32 [[B]] to i64
513 ; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(2) [[P]] to i32
514 ; CHECK-NEXT:    [[CC:%.*]] = zext i32 [[TMP1]] to i64
515 ; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 [[CC]], [[C]]
516 ; CHECK-NEXT:    ret i64 [[D]]
518   %A = getelementptr inbounds bfloat, ptr addrspace(2) %p, i32 %offset
519   %B = ptrtoint ptr addrspace(2) %A to i32
520   %C = zext i32 %B to i64
521   %CC = ptrtoint ptr addrspace(2) %p to i64
522   %D = sub i64 %CC, %C
523   ret i64 %D
526 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_local(ptr addrspace(2) %p, i32 %offset) {
527 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw_local(
528 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
529 ; CHECK-NEXT:    [[D:%.*]] = sext i32 [[A_IDX]] to i64
530 ; CHECK-NEXT:    ret i64 [[D]]
532   %A = getelementptr nusw bfloat, ptr addrspace(2) %p, i32 %offset
533   %B = ptrtoint ptr addrspace(2) %A to i32
534   %C = zext i32 %B to i64
535   %CC = ptrtoint ptr addrspace(2) %p to i64
536   %D = sub i64 %C, %CC
537   ret i64 %D
540 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nuw_local(ptr addrspace(2) %p, i32 %offset) {
541 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nuw_local(
542 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
543 ; CHECK-NEXT:    [[D:%.*]] = zext i32 [[A_IDX]] to i64
544 ; CHECK-NEXT:    ret i64 [[D]]
546   %A = getelementptr nuw bfloat, ptr addrspace(2) %p, i32 %offset
547   %B = ptrtoint ptr addrspace(2) %A to i32
548   %C = zext i32 %B to i64
549   %CC = ptrtoint ptr addrspace(2) %p to i64
550   %D = sub i64 %C, %CC
551   ret i64 %D
554 define i64 @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw_local(ptr addrspace(2) %p, i32 %offset) {
555 ; CHECK-LABEL: @zext_ptrtoint_sub_ptrtoint_as2_nusw_nuw_local(
556 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 1
557 ; CHECK-NEXT:    [[D:%.*]] = zext nneg i32 [[A_IDX]] to i64
558 ; CHECK-NEXT:    ret i64 [[D]]
560   %A = getelementptr nusw nuw bfloat, ptr addrspace(2) %p, i32 %offset
561   %B = ptrtoint ptr addrspace(2) %A to i32
562   %C = zext i32 %B to i64
563   %CC = ptrtoint ptr addrspace(2) %p to i64
564   %D = sub i64 %C, %CC
565   ret i64 %D
568 define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw_local(ptr addrspace(2) %p, i32 %offset) {
569 ; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nusw_local(
570 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 1
571 ; CHECK-NEXT:    [[E:%.*]] = sext i32 [[A_IDX]] to i64
572 ; CHECK-NEXT:    ret i64 [[E]]
574   %A = getelementptr nusw bfloat, ptr addrspace(2) %p, i32 %offset
575   %B = ptrtoint ptr addrspace(2) %A to i32
576   %C = zext i32 %B to i64
577   %CC = ptrtoint ptr addrspace(2) %p to i32
578   %D = zext i32 %CC to i64
579   %E = sub i64 %C, %D
580   ret i64 %E
583 define i64 @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw_local(ptr addrspace(2) %p, i32 %offset) {
584 ; CHECK-LABEL: @zext_ptrtoint_sub_zext_ptrtoint_as2_nuw_local(
585 ; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw i32 [[OFFSET:%.*]], 1
586 ; CHECK-NEXT:    [[E:%.*]] = zext i32 [[A_IDX]] to i64
587 ; CHECK-NEXT:    ret i64 [[E]]
589   %A = getelementptr nuw bfloat, ptr addrspace(2) %p, i32 %offset
590   %B = ptrtoint ptr addrspace(2) %A to i32
591   %C = zext i32 %B to i64
592   %CC = ptrtoint ptr addrspace(2) %p to i32
593   %D = zext i32 %CC to i64
594   %E = sub i64 %C, %D
595   ret i64 %E
598 define i64 @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw_local(ptr addrspace(2) %p, i32 %offset) {
599 ; CHECK-LABEL: @negative_zext_ptrtoint_sub_ptrtoint_as2_nuw_local(
600 ; CHECK-NEXT:    [[A:%.*]] = getelementptr nuw bfloat, ptr addrspace(2) [[P:%.*]], i32 [[OFFSET:%.*]]
601 ; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr addrspace(2) [[A]] to i32
602 ; CHECK-NEXT:    [[B_MASK:%.*]] = and i32 [[TMP1]], 65535
603 ; CHECK-NEXT:    [[C:%.*]] = zext nneg i32 [[B_MASK]] to i64
604 ; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr addrspace(2) [[P]] to i32
605 ; CHECK-NEXT:    [[CC:%.*]] = zext i32 [[TMP2]] to i64
606 ; CHECK-NEXT:    [[D:%.*]] = sub nsw i64 [[C]], [[CC]]
607 ; CHECK-NEXT:    ret i64 [[D]]
609   %A = getelementptr nuw bfloat, ptr addrspace(2) %p, i32 %offset
610   %B = ptrtoint ptr addrspace(2) %A to i16
611   %C = zext i16 %B to i64
612   %CC = ptrtoint ptr addrspace(2) %p to i64
613   %D = sub i64 %C, %CC
614   ret i64 %D
617 define i64 @test30(ptr %foo, i64 %i, i64 %j) {
618 ; CHECK-LABEL: @test30(
619 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
620 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub nsw i64 [[GEP1_IDX]], [[J:%.*]]
621 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
623   %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i
624   %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
625   %cast1 = ptrtoint ptr %gep1 to i64
626   %cast2 = ptrtoint ptr %gep2 to i64
627   %sub = sub i64 %cast1, %cast2
628   ret i64 %sub
631 define i16 @test30_as1(ptr addrspace(1) %foo, i16 %i, i16 %j) {
632 ; CHECK-LABEL: @test30_as1(
633 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
634 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub nsw i16 [[GEP1_IDX]], [[J:%.*]]
635 ; CHECK-NEXT:    ret i16 [[GEPDIFF]]
637   %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i16 %i
638   %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i16 %j
639   %cast1 = ptrtoint ptr addrspace(1) %gep1 to i16
640   %cast2 = ptrtoint ptr addrspace(1) %gep2 to i16
641   %sub = sub i16 %cast1, %cast2
642   ret i16 %sub
645 ; Inbounds translates to 'nsw' on sub
647 define i64 @gep_diff_both_inbounds(ptr %foo, i64 %i, i64 %j) {
648 ; CHECK-LABEL: @gep_diff_both_inbounds(
649 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub nsw i64 [[I:%.*]], [[J:%.*]]
650 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
652   %gep1 = getelementptr inbounds i8, ptr %foo, i64 %i
653   %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
654   %cast1 = ptrtoint ptr %gep1 to i64
655   %cast2 = ptrtoint ptr %gep2 to i64
656   %sub = sub i64 %cast1, %cast2
657   ret i64 %sub
660 ; Negative test for 'nsw' - both geps must be inbounds
662 define i64 @gep_diff_first_inbounds(ptr %foo, i64 %i, i64 %j) {
663 ; CHECK-LABEL: @gep_diff_first_inbounds(
664 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
665 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
667   %gep1 = getelementptr inbounds i8, ptr %foo, i64 %i
668   %gep2 = getelementptr i8, ptr %foo, i64 %j
669   %cast1 = ptrtoint ptr %gep1 to i64
670   %cast2 = ptrtoint ptr %gep2 to i64
671   %sub = sub i64 %cast1, %cast2
672   ret i64 %sub
675 ; Negative test for 'nsw' - both geps must be inbounds
677 define i64 @gep_diff_second_inbounds(ptr %foo, i64 %i, i64 %j) {
678 ; CHECK-LABEL: @gep_diff_second_inbounds(
679 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
680 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
682   %gep1 = getelementptr i8, ptr %foo, i64 %i
683   %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j
684   %cast1 = ptrtoint ptr %gep1 to i64
685   %cast2 = ptrtoint ptr %gep2 to i64
686   %sub = sub i64 %cast1, %cast2
687   ret i64 %sub
690 define i64 @gep_diff_with_bitcast(ptr %p, i64 %idx) {
691 ; CHECK-LABEL: @gep_diff_with_bitcast(
692 ; CHECK-NEXT:    ret i64 [[IDX:%.*]]
694   %i1 = getelementptr inbounds [4 x i64], ptr %p, i64 %idx
695   %i3 = ptrtoint ptr %i1 to i64
696   %i4 = ptrtoint ptr %p to i64
697   %i5 = sub nuw i64 %i3, %i4
698   %i6 = lshr i64 %i5, 5
699   ret i64 %i6
702 define i64 @sub_scalable(ptr noundef %val1) {
703 ; CHECK-LABEL: @sub_scalable(
704 ; CHECK-NEXT:  entry:
705 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
706 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[TMP0]], 4
707 ; CHECK-NEXT:    ret i64 [[TMP1]]
709 entry:
710   %gep1 = getelementptr <vscale x 4 x i32>, ptr %val1, i64 1
711   %sub.ptr.lhs.cast.i = ptrtoint ptr %gep1 to i64
712   %sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
713   %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
714   ret i64 %sub.ptr.sub.i
717 define i64 @sub_scalable2(ptr noundef %val1) {
718 ; CHECK-LABEL: @sub_scalable2(
719 ; CHECK-NEXT:  entry:
720 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
721 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[TMP0]], 4
722 ; CHECK-NEXT:    [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
723 ; CHECK-NEXT:    [[GEP2_IDX:%.*]] = shl i64 [[TMP2]], 5
724 ; CHECK-NEXT:    [[GEPDIFF:%.*]] = sub i64 [[TMP1]], [[GEP2_IDX]]
725 ; CHECK-NEXT:    ret i64 [[GEPDIFF]]
727 entry:
728   %gep1 = getelementptr <vscale x 4 x i32>, ptr %val1, i64 1
729   %sub.ptr.lhs.cast.i = ptrtoint ptr %gep1 to i64
730   %gep2 = getelementptr <vscale x 4 x i32>, ptr %val1, i64 2
731   %sub.ptr.rhs.cast.i = ptrtoint ptr %gep2 to i64
732   %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
733   ret i64 %sub.ptr.sub.i
736 define i64 @nullptrtoint_scalable_c() {
737 ; CHECK-LABEL: @nullptrtoint_scalable_c(
738 ; CHECK-NEXT:  entry:
739 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
740 ; CHECK-NEXT:    [[PTR_IDX:%.*]] = shl i64 [[TMP0]], 7
741 ; CHECK-NEXT:    ret i64 [[PTR_IDX]]
743 entry:
744   %ptr = getelementptr inbounds <vscale x 4 x i32>, ptr null, i64 8
745   %ret = ptrtoint ptr %ptr to i64
746   ret i64 %ret
749 define i64 @nullptrtoint_scalable_x(i64 %x) {
750 ; CHECK-LABEL: @nullptrtoint_scalable_x(
751 ; CHECK-NEXT:  entry:
752 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
753 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[TMP0]], 4
754 ; CHECK-NEXT:    [[PTR_IDX:%.*]] = mul nsw i64 [[X:%.*]], [[TMP1]]
755 ; CHECK-NEXT:    ret i64 [[PTR_IDX]]
757 entry:
758   %ptr = getelementptr inbounds <vscale x 4 x i32>, ptr null, i64 %x
759   %ret = ptrtoint ptr %ptr to i64
760   ret i64 %ret
763 define i1 @_gep_phi1(ptr %str1) {
764 ; CHECK-LABEL: @_gep_phi1(
765 ; CHECK-NEXT:  entry:
766 ; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq ptr [[STR1:%.*]], null
767 ; CHECK-NEXT:    br i1 [[CMP_I]], label [[_Z3FOOPKC_EXIT:%.*]], label [[LOR_LHS_FALSE_I:%.*]]
768 ; CHECK:       lor.lhs.false.i:
769 ; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[STR1]], align 1
770 ; CHECK-NEXT:    [[CMP1_I:%.*]] = icmp eq i8 [[TMP0]], 0
771 ; CHECK-NEXT:    br i1 [[CMP1_I]], label [[_Z3FOOPKC_EXIT]], label [[WHILE_COND_I:%.*]]
772 ; CHECK:       while.cond.i:
773 ; CHECK-NEXT:    [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[STR1]], [[LOR_LHS_FALSE_I]] ]
774 ; CHECK-NEXT:    [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
775 ; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[TEST_0_I]], align 1
776 ; CHECK-NEXT:    [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP1]], 0
777 ; CHECK-NEXT:    br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
778 ; CHECK:       while.end.i:
779 ; CHECK-NEXT:    br label [[_Z3FOOPKC_EXIT]]
780 ; CHECK:       _Z3fooPKc.exit:
781 ; CHECK-NEXT:    [[TOBOOL:%.*]] = phi i1 [ true, [[WHILE_END_I]] ], [ false, [[LOR_LHS_FALSE_I]] ], [ false, [[ENTRY:%.*]] ]
782 ; CHECK-NEXT:    ret i1 [[TOBOOL]]
784 entry:
785   %cmp.i = icmp eq ptr %str1, null
786   br i1 %cmp.i, label %_Z3fooPKc.exit, label %lor.lhs.false.i
788 lor.lhs.false.i:
789   %0 = load i8, ptr %str1, align 1
790   %cmp1.i = icmp eq i8 %0, 0
791   br i1 %cmp1.i, label %_Z3fooPKc.exit, label %while.cond.i
793 while.cond.i:
794   %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %str1, %lor.lhs.false.i ]
795   %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
796   %1 = load i8, ptr %test.0.i, align 1
797   %cmp3.not.i = icmp eq i8 %1, 0
798   br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
800 while.end.i:
801   %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
802   %sub.ptr.rhs.cast.i = ptrtoint ptr %str1 to i64
803   %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
804   br label %_Z3fooPKc.exit
806 _Z3fooPKc.exit:
807   %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %lor.lhs.false.i ], [ 0, %entry ]
808   %tobool = icmp ne i64 %retval.0.i, 0
809   ret i1 %tobool
812 define i1 @_gep_phi2(ptr %str1, i64 %val2) {
813 ; CHECK-LABEL: @_gep_phi2(
814 ; CHECK-NEXT:  entry:
815 ; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq ptr [[STR1:%.*]], null
816 ; CHECK-NEXT:    br i1 [[CMP_I]], label [[_Z3FOOPKC_EXIT:%.*]], label [[LOR_LHS_FALSE_I:%.*]]
817 ; CHECK:       lor.lhs.false.i:
818 ; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[STR1]], align 1
819 ; CHECK-NEXT:    [[CMP1_I:%.*]] = icmp eq i8 [[TMP0]], 0
820 ; CHECK-NEXT:    br i1 [[CMP1_I]], label [[_Z3FOOPKC_EXIT]], label [[WHILE_COND_I:%.*]]
821 ; CHECK:       while.cond.i:
822 ; CHECK-NEXT:    [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[STR1]], [[LOR_LHS_FALSE_I]] ]
823 ; CHECK-NEXT:    [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
824 ; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[TEST_0_I]], align 1
825 ; CHECK-NEXT:    [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP1]], 0
826 ; CHECK-NEXT:    br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
827 ; CHECK:       while.end.i:
828 ; CHECK-NEXT:    br label [[_Z3FOOPKC_EXIT]]
829 ; CHECK:       _Z3fooPKc.exit:
830 ; CHECK-NEXT:    [[RETVAL_0_I:%.*]] = phi i64 [ 1, [[WHILE_END_I]] ], [ 0, [[LOR_LHS_FALSE_I]] ], [ 0, [[ENTRY:%.*]] ]
831 ; CHECK-NEXT:    [[TMP2:%.*]] = or i64 [[RETVAL_0_I]], [[VAL2:%.*]]
832 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[TMP2]], 0
833 ; CHECK-NEXT:    ret i1 [[TOBOOL]]
835 entry:
836   %cmp.i = icmp eq ptr %str1, null
837   br i1 %cmp.i, label %_Z3fooPKc.exit, label %lor.lhs.false.i
839 lor.lhs.false.i:
840   %0 = load i8, ptr %str1, align 1
841   %cmp1.i = icmp eq i8 %0, 0
842   br i1 %cmp1.i, label %_Z3fooPKc.exit, label %while.cond.i
844 while.cond.i:
845   %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %str1, %lor.lhs.false.i ]
846   %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
847   %1 = load i8, ptr %test.0.i, align 1
848   %cmp3.not.i = icmp eq i8 %1, 0
849   br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
851 while.end.i:
852   %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
853   %sub.ptr.rhs.cast.i = ptrtoint ptr %str1 to i64
854   %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
855   br label %_Z3fooPKc.exit
857 _Z3fooPKc.exit:
858   %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %lor.lhs.false.i ], [ 0, %entry ]
859   %2 = or i64 %retval.0.i, %val2
860   %tobool = icmp eq i64 %2, 0
861   ret i1 %tobool