xref: /llvm-project/llvm/test/Transforms/InstCombine/sub-gep.ll (revision 23a239267e8a1d20ed10d3545feaf2a2bb70b085)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4target 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"
5
6define 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]]
10;
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
16}
17
18define 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]]
22;
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
28}
29
30define 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]]
34;
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
40}
41
42define 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]]
46;
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
52}
53
54define 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]]
58;
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
64}
65
66define 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]]
71;
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
79}
80
81define 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]]
85;
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
91}
92
93define 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]]
97;
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
103}
104
105define 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]]
109;
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
115}
116
117define 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]]
122;
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
129}
130
131define 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]]
136;
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
143}
144
145define 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]]
150;
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
157}
158
159define 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]]
164;
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
171}
172
173define 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]]
178;
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
185}
186
187define 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]]
192;
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
199}
200
201define 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]]
206;
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
213}
214
215define 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]]
221;
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
227}
228
229; rdar://7362831
230define 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]]
234;
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
242}
243
244define 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]]
248;
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
256}
257
258define i64 @test24(ptr %P, i64 %A){
259; CHECK-LABEL: @test24(
260; CHECK-NEXT:    ret i64 [[A:%.*]]
261;
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
267}
268
269define i16 @test24_as1(ptr addrspace(1) %P, i16 %A) {
270; CHECK-LABEL: @test24_as1(
271; CHECK-NEXT:    ret i16 [[A:%.*]]
272;
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
278}
279
280define 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]]
284;
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
290}
291
292define 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]]
296;
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
302}
303
304@Arr = external global [42 x i16]
305
306define 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]]
310;
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
315}
316
317define 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]]
322;
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
327}
328
329define 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]]
337;
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
343}
344
345define 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]]
353;
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
359}
360
361define 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]]
369;
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
375}
376
377define 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]]
385;
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
391}
392
393@Arr_as1 = external addrspace(1) global [42 x i16]
394
395define 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]]
401;
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
406}
407
408@Arr_as2 = external addrspace(2) global [42 x i16]
409
410define 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]]
417;
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
423}
424
425define 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]]
430;
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
436}
437
438define 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]]
443;
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
449}
450
451define 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]]
456;
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
462}
463
464define 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]]
469;
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
476}
477
478define 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]]
483;
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
490}
491
492define 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]]
500;
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
506}
507
508define 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]]
517;
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
524}
525
526define 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]]
531;
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
538}
539
540define 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]]
545;
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
552}
553
554define 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]]
559;
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
566}
567
568define 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]]
573;
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
581}
582
583define 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]]
588;
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
596}
597
598define 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]]
608;
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
615}
616
617define 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]]
622;
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
629}
630
631define 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]]
636;
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
643}
644
645; Inbounds translates to 'nsw' on sub
646
647define 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]]
651;
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
658}
659
660; Negative test for 'nsw' - both geps must be inbounds
661
662define 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]]
666;
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
673}
674
675; Negative test for 'nsw' - both geps must be inbounds
676
677define 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]]
681;
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
688}
689
690define i64 @gep_diff_with_bitcast(ptr %p, i64 %idx) {
691; CHECK-LABEL: @gep_diff_with_bitcast(
692; CHECK-NEXT:    ret i64 [[IDX:%.*]]
693;
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
700}
701
702define 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]]
708;
709entry:
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
715}
716
717define 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]]
726;
727entry:
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
734}
735
736define 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]]
742;
743entry:
744  %ptr = getelementptr inbounds <vscale x 4 x i32>, ptr null, i64 8
745  %ret = ptrtoint ptr %ptr to i64
746  ret i64 %ret
747}
748
749define 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]]
756;
757entry:
758  %ptr = getelementptr inbounds <vscale x 4 x i32>, ptr null, i64 %x
759  %ret = ptrtoint ptr %ptr to i64
760  ret i64 %ret
761}
762
763define 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 nuw 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]]
783;
784entry:
785  %cmp.i = icmp eq ptr %str1, null
786  br i1 %cmp.i, label %_Z3fooPKc.exit, label %lor.lhs.false.i
787
788lor.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
792
793while.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
799
800while.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
805
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
810}
811
812define 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 nuw 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]]
834;
835entry:
836  %cmp.i = icmp eq ptr %str1, null
837  br i1 %cmp.i, label %_Z3fooPKc.exit, label %lor.lhs.false.i
838
839lor.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
843
844while.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
850
851while.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
856
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
862}
863