xref: /llvm-project/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll (revision f7685af4a5bd188e6d548967d818d8569f10a70d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes='instcombine<no-verify-fixpoint>' -S  < %s | FileCheck %s
3
4; In many of these tests nuw can be inferred on the sunk GEP in the exit
5; block. However, the condition is only converted into the necessary form
6; after it has been sunk and revisited already.
7
8target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:64"
9
10define ptr@test1(ptr %A, i32 %Offset) {
11; CHECK-LABEL: @test1(
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
14; CHECK-NEXT:    br label [[BB:%.*]]
15; CHECK:       bb:
16; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
17; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
18; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
19; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
20; CHECK:       bb2:
21; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
22; CHECK-NEXT:    ret ptr [[RHS_PTR]]
23;
24entry:
25  %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
26  br label %bb
27
28bb:
29  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
30  %LHS = getelementptr inbounds i32, ptr %A, i32 100
31  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
32  %cond = icmp ult ptr %LHS, %RHS
33  br i1 %cond, label %bb2, label %bb
34
35bb2:
36  ret ptr %RHS
37}
38
39define ptr @test1_nuw(ptr %A, i32 %Offset) {
40; CHECK-LABEL: @test1_nuw(
41; CHECK-NEXT:  entry:
42; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 2
43; CHECK-NEXT:    br label [[BB:%.*]]
44; CHECK:       bb:
45; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
46; CHECK-NEXT:    [[RHS_ADD]] = add nuw nsw i32 [[RHS_IDX]], 4
47; CHECK-NEXT:    [[COND:%.*]] = icmp samesign ugt i32 [[RHS_IDX]], 400
48; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
49; CHECK:       bb2:
50; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
51; CHECK-NEXT:    ret ptr [[RHS_PTR]]
52;
53entry:
54  %tmp = getelementptr inbounds nuw i32, ptr %A, i32 %Offset
55  br label %bb
56
57bb:
58  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
59  %LHS = getelementptr inbounds nuw i32, ptr %A, i32 100
60  %RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 1
61  %cond = icmp ult ptr %LHS, %RHS
62  br i1 %cond, label %bb2, label %bb
63
64bb2:
65  ret ptr %RHS
66}
67
68define ptr @test1_not_all_nuw(ptr %A, i32 %Offset) {
69; CHECK-LABEL: @test1_not_all_nuw(
70; CHECK-NEXT:  entry:
71; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
72; CHECK-NEXT:    br label [[BB:%.*]]
73; CHECK:       bb:
74; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
75; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
76; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
77; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
78; CHECK:       bb2:
79; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
80; CHECK-NEXT:    ret ptr [[RHS_PTR]]
81;
82entry:
83  %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
84  br label %bb
85
86bb:
87  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
88  %LHS = getelementptr inbounds nuw i32, ptr %A, i32 100
89  %RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 1
90  %cond = icmp ult ptr %LHS, %RHS
91  br i1 %cond, label %bb2, label %bb
92
93bb2:
94  ret ptr %RHS
95}
96
97define ptr@test2(i32 %A, i32 %Offset) {
98; CHECK-LABEL: @test2(
99; CHECK-NEXT:  entry:
100; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
101; CHECK-NEXT:    br label [[BB:%.*]]
102; CHECK:       bb:
103; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
104; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
105; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
106; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
107; CHECK:       bb2:
108; CHECK-NEXT:    [[A_PTR:%.*]] = inttoptr i32 [[A:%.*]] to ptr
109; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
110; CHECK-NEXT:    ret ptr [[RHS_PTR]]
111;
112entry:
113  %A.ptr = inttoptr i32 %A to ptr
114  %tmp = getelementptr inbounds i32, ptr %A.ptr, i32 %Offset
115  br label %bb
116
117bb:
118  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
119  %LHS = getelementptr inbounds i32, ptr %A.ptr, i32 100
120  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
121  %cmp0 = ptrtoint ptr %LHS to i32
122  %cmp1 = ptrtoint ptr %RHS to i32
123  %cond = icmp ult i32 %cmp0, %cmp1
124  br i1 %cond, label %bb2, label %bb
125
126bb2:
127  ret ptr %RHS
128}
129
130; Perform the transformation only if we know that the GEPs used are inbounds.
131define ptr @test3_no_inbounds1(ptr %A, i32 %Offset) {
132; CHECK-LABEL: @test3_no_inbounds1(
133; CHECK-NEXT:  entry:
134; CHECK-NEXT:    [[TMP:%.*]] = getelementptr i32, ptr [[A:%.*]], i32 [[OFFSET:%.*]]
135; CHECK-NEXT:    br label [[BB:%.*]]
136; CHECK:       bb:
137; CHECK-NEXT:    [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
138; CHECK-NEXT:    [[LHS:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i32 400
139; CHECK-NEXT:    [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4
140; CHECK-NEXT:    [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
141; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
142; CHECK:       bb2:
143; CHECK-NEXT:    ret ptr [[RHS]]
144;
145entry:
146  %tmp = getelementptr i32, ptr %A, i32 %Offset
147  br label %bb
148
149bb:
150  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
151  %LHS = getelementptr inbounds i32, ptr %A, i32 100
152  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
153  %cond = icmp ult ptr %LHS, %RHS
154  br i1 %cond, label %bb2, label %bb
155
156bb2:
157  ret ptr %RHS
158}
159
160define ptr @test3_no_inbounds2(ptr %A, i32 %Offset) {
161; CHECK-LABEL: @test3_no_inbounds2(
162; CHECK-NEXT:  entry:
163; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[OFFSET:%.*]]
164; CHECK-NEXT:    br label [[BB:%.*]]
165; CHECK:       bb:
166; CHECK-NEXT:    [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
167; CHECK-NEXT:    [[LHS:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i32 400
168; CHECK-NEXT:    [[RHS_NEXT]] = getelementptr i8, ptr [[RHS]], i32 4
169; CHECK-NEXT:    [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
170; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
171; CHECK:       bb2:
172; CHECK-NEXT:    ret ptr [[RHS]]
173;
174entry:
175  %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
176  br label %bb
177
178bb:
179  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
180  %LHS = getelementptr inbounds i32, ptr %A, i32 100
181  %RHS.next = getelementptr i32, ptr %RHS, i64 1
182  %cond = icmp ult ptr %LHS, %RHS
183  br i1 %cond, label %bb2, label %bb
184
185bb2:
186  ret ptr %RHS
187}
188
189define ptr @test3_no_inbounds3(ptr %A, i32 %Offset) {
190; CHECK-LABEL: @test3_no_inbounds3(
191; CHECK-NEXT:  entry:
192; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[OFFSET:%.*]]
193; CHECK-NEXT:    br label [[BB:%.*]]
194; CHECK:       bb:
195; CHECK-NEXT:    [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
196; CHECK-NEXT:    [[LHS:%.*]] = getelementptr i8, ptr [[A]], i32 400
197; CHECK-NEXT:    [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4
198; CHECK-NEXT:    [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
199; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
200; CHECK:       bb2:
201; CHECK-NEXT:    ret ptr [[RHS]]
202;
203entry:
204  %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
205  br label %bb
206
207bb:
208  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
209  %LHS = getelementptr i32, ptr %A, i32 100
210  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
211  %cond = icmp ult ptr %LHS, %RHS
212  br i1 %cond, label %bb2, label %bb
213
214bb2:
215  ret ptr %RHS
216}
217
218; An inttoptr that requires an extension or truncation will be opaque when determining
219; the base pointer. In this case we can still perform the transformation by considering
220; A.ptr as being the base pointer.
221define ptr@test4(i16 %A, i32 %Offset) {
222; CHECK-LABEL: @test4(
223; CHECK-NEXT:  entry:
224; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
225; CHECK-NEXT:    br label [[BB:%.*]]
226; CHECK:       bb:
227; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
228; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
229; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
230; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
231; CHECK:       bb2:
232; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[A:%.*]] to i32
233; CHECK-NEXT:    [[A_PTR:%.*]] = inttoptr i32 [[TMP0]] to ptr
234; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
235; CHECK-NEXT:    ret ptr [[RHS_PTR]]
236;
237entry:
238  %A.ptr = inttoptr i16 %A to ptr
239  %tmp = getelementptr inbounds i32, ptr %A.ptr, i32 %Offset
240  br label %bb
241
242bb:
243  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
244  %LHS = getelementptr inbounds i32, ptr %A.ptr, i32 100
245  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
246  %cmp0 = ptrtoint ptr %LHS to i32
247  %cmp1 = ptrtoint ptr %RHS to i32
248  %cond = icmp ult i32 %cmp0, %cmp1
249  br i1 %cond, label %bb2, label %bb
250
251bb2:
252  ret ptr %RHS
253}
254
255declare ptr @fun_ptr()
256
257define ptr@test5(i32 %Offset) personality ptr @__gxx_personality_v0 {
258; CHECK-LABEL: @test5(
259; CHECK-NEXT:  entry:
260; CHECK-NEXT:    [[A:%.*]] = invoke ptr @fun_ptr()
261; CHECK-NEXT:            to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
262; CHECK:       cont:
263; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
264; CHECK-NEXT:    br label [[BB:%.*]]
265; CHECK:       bb:
266; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]
267; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
268; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
269; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
270; CHECK:       bb2:
271; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A]], i32 [[RHS_IDX]]
272; CHECK-NEXT:    ret ptr [[RHS_PTR]]
273; CHECK:       lpad:
274; CHECK-NEXT:    [[L:%.*]] = landingpad { ptr, i32 }
275; CHECK-NEXT:            cleanup
276; CHECK-NEXT:    ret ptr null
277;
278entry:
279  %A = invoke ptr@fun_ptr() to label %cont unwind label %lpad
280
281cont:
282  %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
283  br label %bb
284
285bb:
286  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %cont ]
287  %LHS = getelementptr inbounds i32, ptr %A, i32 100
288  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
289  %cond = icmp ult ptr %LHS, %RHS
290  br i1 %cond, label %bb2, label %bb
291
292bb2:
293  ret ptr %RHS
294
295lpad:
296  %l = landingpad { ptr, i32 } cleanup
297  ret ptr null
298}
299
300declare i32 @fun_i32()
301
302define ptr@test6(i32 %Offset) personality ptr @__gxx_personality_v0 {
303; CHECK-LABEL: @test6(
304; CHECK-NEXT:  entry:
305; CHECK-NEXT:    [[A:%.*]] = invoke i32 @fun_i32()
306; CHECK-NEXT:            to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
307; CHECK:       cont:
308; CHECK-NEXT:    [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
309; CHECK-NEXT:    br label [[BB:%.*]]
310; CHECK:       bb:
311; CHECK-NEXT:    [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]
312; CHECK-NEXT:    [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
313; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
314; CHECK-NEXT:    br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
315; CHECK:       bb2:
316; CHECK-NEXT:    [[A_PTR:%.*]] = inttoptr i32 [[A]] to ptr
317; CHECK-NEXT:    [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
318; CHECK-NEXT:    ret ptr [[RHS_PTR]]
319; CHECK:       lpad:
320; CHECK-NEXT:    [[L:%.*]] = landingpad { ptr, i32 }
321; CHECK-NEXT:            cleanup
322; CHECK-NEXT:    ret ptr null
323;
324entry:
325  %A = invoke i32 @fun_i32() to label %cont unwind label %lpad
326
327cont:
328  %A.ptr = inttoptr i32 %A to ptr
329  %tmp = getelementptr inbounds i32, ptr %A.ptr, i32 %Offset
330  br label %bb
331
332bb:
333  %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %cont ]
334  %LHS = getelementptr inbounds i32, ptr %A.ptr, i32 100
335  %RHS.next = getelementptr inbounds i32, ptr %RHS, i64 1
336  %cond = icmp ult ptr %LHS, %RHS
337  br i1 %cond, label %bb2, label %bb
338
339bb2:
340  ret ptr %RHS
341
342lpad:
343  %l = landingpad { ptr, i32 } cleanup
344  ret ptr null
345}
346
347
348@pr30402 = constant i64 3
349define i1 @test7() {
350; CHECK-LABEL: @test7(
351; CHECK-NEXT:  entry:
352; CHECK-NEXT:    br label [[BB7:%.*]]
353; CHECK:       bb7:
354; CHECK-NEXT:    [[CMP:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ true, [[BB7]] ]
355; CHECK-NEXT:    br i1 [[CMP]], label [[BB10:%.*]], label [[BB7]]
356; CHECK:       bb10:
357; CHECK-NEXT:    ret i1 true
358;
359entry:
360  br label %bb7
361
362bb7:                                              ; preds = %bb10, %entry-block
363  %phi = phi ptr [ @pr30402, %entry ], [ getelementptr inbounds (i64, ptr @pr30402, i32 1), %bb7 ]
364  %cmp = icmp eq ptr %phi, getelementptr inbounds (i64, ptr @pr30402, i32 1)
365  br i1 %cmp, label %bb10, label %bb7
366
367bb10:
368  ret i1 %cmp
369}
370
371declare i32 @__gxx_personality_v0(...)
372
373define i1 @test8(ptr %in, i64 %offset) {
374; CHECK-LABEL: @test8(
375; CHECK-NEXT:  entry:
376; CHECK-NEXT:    [[LD:%.*]] = load i64, ptr [[IN:%.*]], align 8
377; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[LD]] to i32
378; CHECK-NEXT:    [[CASTI8:%.*]] = inttoptr i32 [[TMP0]] to ptr
379; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[OFFSET:%.*]] to i32
380; CHECK-NEXT:    [[GEPI8:%.*]] = getelementptr inbounds i8, ptr [[CASTI8]], i32 [[TMP1]]
381; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[LD]] to i32
382; CHECK-NEXT:    [[PTRCAST:%.*]] = inttoptr i32 [[TMP2]] to ptr
383; CHECK-NEXT:    [[GEPI32:%.*]] = getelementptr inbounds nuw i8, ptr [[PTRCAST]], i32 4
384; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[GEPI32]], [[GEPI8]]
385; CHECK-NEXT:    ret i1 [[CMP]]
386;
387entry:
388  %ld = load i64, ptr %in, align 8
389  %casti8 = inttoptr i64 %ld to ptr
390  %gepi8 = getelementptr inbounds i8, ptr %casti8, i64 %offset
391  %ptrcast = inttoptr i64 %ld to ptr
392  %gepi32 = getelementptr inbounds ptr, ptr %ptrcast, i64 1
393  %cmp = icmp eq ptr %gepi32, %gepi8
394  ret i1 %cmp
395}
396
397define void @test_zero_offset_cycle(ptr %arg) {
398; CHECK-LABEL: @test_zero_offset_cycle(
399; CHECK-NEXT:  entry:
400; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG:%.*]], i32 8
401; CHECK-NEXT:    [[GEP_INT:%.*]] = ptrtoint ptr [[GEP]] to i32
402; CHECK-NEXT:    br label [[LOOP:%.*]]
403; CHECK:       loop:
404; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[GEP_INT]], [[ENTRY:%.*]] ], [ [[GEP_INT2:%.*]], [[LOOP_CONT:%.*]] ], [ [[PHI]], [[LOOP]] ]
405; CHECK-NEXT:    [[PHI_PTR:%.*]] = inttoptr i32 [[PHI]] to ptr
406; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[GEP]], [[PHI_PTR]]
407; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[LOOP_CONT]]
408; CHECK:       loop.cont:
409; CHECK-NEXT:    [[GEP_INT2]] = ptrtoint ptr [[GEP]] to i32
410; CHECK-NEXT:    br label [[LOOP]]
411;
412entry:
413  %gep = getelementptr inbounds { i64, i64 }, ptr %arg, i32 0, i32 1
414  %gep.int = ptrtoint ptr %gep to i32
415  br label %loop
416
417loop:
418  %phi = phi i32 [ %gep.int, %entry ], [ %gep.int2, %loop.cont ], [ %phi, %loop ]
419  %phi.ptr = inttoptr i32 %phi to ptr
420  %cmp = icmp eq ptr %gep, %phi.ptr
421  br i1 %cmp, label %loop, label %loop.cont
422
423loop.cont:
424  %gep.int2 = ptrtoint ptr %gep to i32
425  br label %loop
426}
427