xref: /llvm-project/llvm/test/Transforms/GVN/PRE/pre-loop-load-through-select.ll (revision 1aece0e5edf8d4fef1b5e226825a245dce5c382e)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes='require<domtree>,loop(loop-simplifycfg),gvn' -enable-split-backedge-in-load-pre -S %s | FileCheck %s
3
4define i32 @test_pointer_phi_select_same_object(ptr %ptr, ptr %end)  {
5; CHECK-LABEL: @test_pointer_phi_select_same_object(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
8; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
9; CHECK-NEXT:    br label [[LOOP:%.*]]
10; CHECK:       loop:
11; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
12; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
13; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
14; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
15; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
16; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
17; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
18; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
19; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
20; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
21; CHECK:       exit:
22; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
23; CHECK-NEXT:    ret i32 [[RES]]
24;
25entry:
26  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
27  br label %loop
28
29loop:
30  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
31  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
32  %l.1 = load i32, ptr %ptr.iv, align 4
33  %l.2 = load i32, ptr %min.ptr, align 4
34  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
35  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
36  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
37  %ec = icmp eq ptr %ptr.iv.next, %end
38  br i1 %ec, label %exit, label %loop
39
40exit:
41  %res = load i32, ptr %min.select, align 4
42  ret i32 %res
43}
44
45define i32 @test_pointer_phi_select_same_object_lcssa(ptr %ptr, ptr %end)  {
46; CHECK-LABEL: @test_pointer_phi_select_same_object_lcssa(
47; CHECK-NEXT:  entry:
48; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
49; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
50; CHECK-NEXT:    br label [[LOOP:%.*]]
51; CHECK:       loop:
52; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
53; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
54; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
55; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
56; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
57; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
58; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
59; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
60; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
61; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
62; CHECK:       exit:
63; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
64; CHECK-NEXT:    ret i32 [[RES]]
65;
66entry:
67  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
68  br label %loop
69
70loop:
71  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
72  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
73  %l.1 = load i32, ptr %ptr.iv, align 4
74  %l.2 = load i32, ptr %min.ptr, align 4
75  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
76  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
77  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
78  %ec = icmp eq ptr %ptr.iv.next, %end
79  br i1 %ec, label %exit, label %loop
80
81exit:
82  %lcssa.min = phi ptr [ %min.select, %loop ]
83  %res = load i32, ptr %lcssa.min, align 4
84  ret i32 %res
85}
86
87define i32 @test_pointer_phi_select_different_objects(ptr %A, ptr %B, ptr %end)  {
88; CHECK-LABEL: @test_pointer_phi_select_different_objects(
89; CHECK-NEXT:  entry:
90; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[B:%.*]], align 4
91; CHECK-NEXT:    br label [[LOOP:%.*]]
92; CHECK:       loop:
93; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
94; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[A:%.*]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
95; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[B]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
96; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
97; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
98; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
99; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
100; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
101; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
102; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
103; CHECK:       exit:
104; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
105; CHECK-NEXT:    ret i32 [[RES]]
106;
107entry:
108  br label %loop
109
110loop:
111  %ptr.iv = phi ptr [ %A, %entry ], [ %ptr.iv.next, %loop ]
112  %min.ptr = phi ptr [ %B, %entry ], [ %min.select, %loop ]
113  %l.1 = load i32, ptr %ptr.iv, align 4
114  %l.2 = load i32, ptr %min.ptr, align 4
115  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
116  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
117  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
118  %ec = icmp eq ptr %ptr.iv.next, %end
119  br i1 %ec, label %exit, label %loop
120
121exit:
122  %res = load i32, ptr %min.select, align 4
123  ret i32 %res
124}
125
126define i32 @test_pointer_phi_select_same_object_multiple_loads_1(ptr %ptr, ptr %end)  {
127; CHECK-LABEL: @test_pointer_phi_select_same_object_multiple_loads_1(
128; CHECK-NEXT:  entry:
129; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
130; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
131; CHECK-NEXT:    br label [[LOOP:%.*]]
132; CHECK:       loop:
133; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
134; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
135; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
136; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
137; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
138; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
139; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
140; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
141; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
142; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
143; CHECK:       exit:
144; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
145; CHECK-NEXT:    ret i32 [[RES]]
146;
147entry:
148  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
149  br label %loop
150
151loop:
152  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
153  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
154  %l.1 = load i32, ptr %ptr.iv, align 4
155  %l.2 = load i32, ptr %min.ptr, align 4
156  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
157  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
158  %l.3 = load i32, ptr %min.ptr, align 4
159  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
160  %ec = icmp eq ptr %ptr.iv.next, %end
161  br i1 %ec, label %exit, label %loop
162
163exit:
164  %res = load i32, ptr %min.select, align 4
165  ret i32 %res
166}
167
168define i32 @test_pointer_phi_select_same_object_multiple_loads_2(ptr %ptr, ptr %end)  {
169; CHECK-LABEL: @test_pointer_phi_select_same_object_multiple_loads_2(
170; CHECK-NEXT:  entry:
171; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
172; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
173; CHECK-NEXT:    br label [[LOOP:%.*]]
174; CHECK:       loop:
175; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
176; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
177; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
178; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
179; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
180; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
181; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
182; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
183; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
184; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
185; CHECK:       exit:
186; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
187; CHECK-NEXT:    ret i32 [[RES]]
188;
189entry:
190  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
191  br label %loop
192
193loop:
194  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
195  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
196  %l.1 = load i32, ptr %ptr.iv, align 4
197  %l.2 = load i32, ptr %min.ptr, align 4
198  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
199  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
200  %l.3 = load i32, ptr %ptr.iv, align 4
201  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
202  %ec = icmp eq ptr %ptr.iv.next, %end
203  br i1 %ec, label %exit, label %loop
204
205exit:
206  %res = load i32, ptr %min.select, align 4
207  ret i32 %res
208}
209
210define i32 @test_pointer_phi_select_load_after(ptr %A, ptr %B, ptr %end)  {
211; CHECK-LABEL: @test_pointer_phi_select_load_after(
212; CHECK-NEXT:  entry:
213; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[B:%.*]], align 4
214; CHECK-NEXT:    br label [[LOOP:%.*]]
215; CHECK:       loop:
216; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[L_3:%.*]], [[LOOP]] ]
217; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[A:%.*]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
218; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[B]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
219; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
220; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
221; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
222; CHECK-NEXT:    [[L_3]] = load i32, ptr [[MIN_SELECT]], align 4
223; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i32 [[L_3]]
224; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
225; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
226; CHECK:       exit:
227; CHECK-NEXT:    ret i32 [[L_3]]
228;
229entry:
230  br label %loop
231
232loop:
233  %ptr.iv = phi ptr [ %A, %entry ], [ %ptr.iv.next, %loop ]
234  %min.ptr = phi ptr [ %B, %entry ], [ %min.select, %loop ]
235  %l.1 = load i32, ptr %ptr.iv, align 4
236  %l.2 = load i32, ptr %min.ptr, align 4
237  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
238  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
239  %l.3 = load i32, ptr %min.select, align 4
240  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i32 %l.3
241  %ec = icmp eq ptr %ptr.iv.next, %end
242  br i1 %ec, label %exit, label %loop
243
244exit:
245  %res = load i32, ptr %min.select, align 4
246  ret i32 %res
247}
248
249define i32 @test_pointer_phi_select_same_object_split_edge(ptr %ptr, ptr %end, i1 %c)  {
250; CHECK-LABEL: @test_pointer_phi_select_same_object_split_edge(
251; CHECK-NEXT:  entry:
252; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
253; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
254; CHECK:       loop.preheader:
255; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
256; CHECK-NEXT:    br label [[LOOP:%.*]]
257; CHECK:       loop:
258; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[TMP0:%.*]], [[LOOP]] ], [ [[L_2_PRE]], [[LOOP_PREHEADER]] ]
259; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ], [ [[START_PTR]], [[LOOP_PREHEADER]] ]
260; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[MIN_SELECT:%.*]], [[LOOP]] ], [ [[PTR]], [[LOOP_PREHEADER]] ]
261; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
262; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
263; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
264; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
265; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
266; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
267; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_EXIT:%.*]], label [[LOOP]]
268; CHECK:       loop.exit:
269; CHECK-NEXT:    br label [[EXIT]]
270; CHECK:       exit:
271; CHECK-NEXT:    [[LCSSA_PHI_2:%.*]] = phi ptr [ [[END]], [[ENTRY:%.*]] ], [ [[MIN_SELECT]], [[LOOP_EXIT]] ]
272; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[LCSSA_PHI_2]], align 4
273; CHECK-NEXT:    ret i32 [[RES]]
274;
275entry:
276  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
277  br i1 %c, label %exit, label %loop
278
279loop:
280  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
281  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
282  %l.1 = load i32, ptr %ptr.iv, align 4
283  %l.2 = load i32, ptr %min.ptr, align 4
284  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
285  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
286  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
287  %ec = icmp eq ptr %ptr.iv.next, %end
288  br i1 %ec, label %loop.exit, label %loop
289
290loop.exit:
291  %lcssa.phi.1 = phi ptr [ %min.select, %loop ]
292  br label %exit
293
294exit:
295  %lcssa.phi.2 = phi ptr [ %end, %entry ], [ %lcssa.phi.1, %loop.exit ]
296  %res = load i32, ptr %lcssa.phi.2, align 4
297  ret i32 %res
298}
299
300
301declare void @may_throw() readonly
302
303define i32 @test_pointer_phi_select_load_may_not_execute_1(ptr %A, ptr %B, ptr %end)  {
304; CHECK-LABEL: @test_pointer_phi_select_load_may_not_execute_1(
305; CHECK-NEXT:  entry:
306; CHECK-NEXT:    br label [[LOOP:%.*]]
307; CHECK:       loop:
308; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[A:%.*]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
309; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[B:%.*]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
310; CHECK-NEXT:    call void @may_throw()
311; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
312; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
313; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
314; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
315; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
316; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
317; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
318; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
319; CHECK:       exit:
320; CHECK-NEXT:    ret i32 [[TMP0]]
321;
322entry:
323  br label %loop
324
325loop:
326  %ptr.iv = phi ptr [ %A, %entry ], [ %ptr.iv.next, %loop ]
327  %min.ptr = phi ptr [ %B, %entry ], [ %min.select, %loop ]
328  call void @may_throw()
329  %l.1 = load i32, ptr %ptr.iv, align 4
330  %l.2 = load i32, ptr %min.ptr, align 4
331  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
332  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
333  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
334  %ec = icmp eq ptr %ptr.iv.next, %end
335  br i1 %ec, label %exit, label %loop
336
337exit:
338  %res = load i32, ptr %min.select, align 4
339  ret i32 %res
340}
341
342define i32 @test_pointer_phi_select_load_may_not_execute_2(ptr %A, ptr %B, ptr %end)  {
343; CHECK-LABEL: @test_pointer_phi_select_load_may_not_execute_2(
344; CHECK-NEXT:  entry:
345; CHECK-NEXT:    br label [[LOOP:%.*]]
346; CHECK:       loop:
347; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[A:%.*]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
348; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[B:%.*]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
349; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
350; CHECK-NEXT:    call void @may_throw()
351; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
352; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
353; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
354; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
355; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
356; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
357; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
358; CHECK:       exit:
359; CHECK-NEXT:    ret i32 [[TMP0]]
360;
361entry:
362  br label %loop
363
364loop:
365  %ptr.iv = phi ptr [ %A, %entry ], [ %ptr.iv.next, %loop ]
366  %min.ptr = phi ptr [ %B, %entry ], [ %min.select, %loop ]
367  %l.1 = load i32, ptr %ptr.iv, align 4
368  call void @may_throw()
369  %l.2 = load i32, ptr %min.ptr, align 4
370  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
371  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
372  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
373  %ec = icmp eq ptr %ptr.iv.next, %end
374  br i1 %ec, label %exit, label %loop
375
376exit:
377  %res = load i32, ptr %min.select, align 4
378  ret i32 %res
379}
380
381define i32 @test_pointer_phi_select_same_object_store_1(ptr %ptr, ptr %end)  {
382; CHECK-LABEL: @test_pointer_phi_select_same_object_store_1(
383; CHECK-NEXT:  entry:
384; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
385; CHECK-NEXT:    br label [[LOOP:%.*]]
386; CHECK:       loop:
387; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
388; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
389; CHECK-NEXT:    store i32 3, ptr [[MIN_PTR]], align 4
390; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
391; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], 3
392; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
393; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
394; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
395; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
396; CHECK:       exit:
397; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
398; CHECK-NEXT:    ret i32 [[RES]]
399;
400entry:
401  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
402  br label %loop
403
404loop:
405  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
406  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
407  store i32 3, ptr %min.ptr
408  %l.1 = load i32, ptr %ptr.iv, align 4
409  %l.2 = load i32, ptr %min.ptr, align 4
410  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
411  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
412  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
413  %ec = icmp eq ptr %ptr.iv.next, %end
414  br i1 %ec, label %exit, label %loop
415
416exit:
417  %res = load i32, ptr %min.select, align 4
418  ret i32 %res
419}
420
421define i32 @test_pointer_phi_select_same_object_store_2(ptr %ptr, ptr %end)  {
422; CHECK-LABEL: @test_pointer_phi_select_same_object_store_2(
423; CHECK-NEXT:  entry:
424; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
425; CHECK-NEXT:    br label [[LOOP:%.*]]
426; CHECK:       loop:
427; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
428; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
429; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
430; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
431; CHECK-NEXT:    store i32 3, ptr [[MIN_PTR]], align 4
432; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
433; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
434; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
435; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
436; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
437; CHECK:       exit:
438; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
439; CHECK-NEXT:    ret i32 [[RES]]
440;
441entry:
442  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
443  br label %loop
444
445loop:
446  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
447  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
448  %l.1 = load i32, ptr %ptr.iv, align 4
449  %l.2 = load i32, ptr %min.ptr, align 4
450  store i32 3, ptr %min.ptr
451  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
452  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
453  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
454  %ec = icmp eq ptr %ptr.iv.next, %end
455  br i1 %ec, label %exit, label %loop
456
457exit:
458  %res = load i32, ptr %min.select, align 4
459  ret i32 %res
460}
461
462define i32 @test_pointer_phi_select_same_object_store_3(ptr %ptr, ptr %end)  {
463; CHECK-LABEL: @test_pointer_phi_select_same_object_store_3(
464; CHECK-NEXT:  entry:
465; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
466; CHECK-NEXT:    br label [[LOOP:%.*]]
467; CHECK:       loop:
468; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
469; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
470; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
471; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
472; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
473; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
474; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
475; CHECK-NEXT:    store i32 3, ptr [[MIN_PTR]], align 4
476; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
477; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
478; CHECK:       exit:
479; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
480; CHECK-NEXT:    ret i32 [[RES]]
481;
482entry:
483  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
484  br label %loop
485
486loop:
487  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
488  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
489  %l.1 = load i32, ptr %ptr.iv, align 4
490  %l.2 = load i32, ptr %min.ptr, align 4
491  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
492  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
493  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
494  store i32 3, ptr %min.ptr
495  %ec = icmp eq ptr %ptr.iv.next, %end
496  br i1 %ec, label %exit, label %loop
497
498exit:
499  %res = load i32, ptr %min.select, align 4
500  ret i32 %res
501}
502
503declare void @may_write()
504
505define i32 @test_pointer_phi_select_same_object_may_write_call_1(ptr %ptr, ptr %end)  {
506; CHECK-LABEL: @test_pointer_phi_select_same_object_may_write_call_1(
507; CHECK-NEXT:  entry:
508; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
509; CHECK-NEXT:    br label [[LOOP:%.*]]
510; CHECK:       loop:
511; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
512; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
513; CHECK-NEXT:    call void @may_write()
514; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
515; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
516; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
517; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
518; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
519; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
520; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
521; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
522; CHECK:       exit:
523; CHECK-NEXT:    ret i32 [[TMP0]]
524;
525entry:
526  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
527  br label %loop
528
529loop:
530  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
531  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
532  call void @may_write()
533  %l.1 = load i32, ptr %ptr.iv, align 4
534  %l.2 = load i32, ptr %min.ptr, align 4
535  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
536  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
537  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
538  %ec = icmp eq ptr %ptr.iv.next, %end
539  br i1 %ec, label %exit, label %loop
540
541exit:
542  %res = load i32, ptr %min.select, align 4
543  ret i32 %res
544}
545
546define i32 @test_pointer_phi_select_same_object_may_write_call_2(ptr %ptr, ptr %end)  {
547; CHECK-LABEL: @test_pointer_phi_select_same_object_may_write_call_2(
548; CHECK-NEXT:  entry:
549; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
550; CHECK-NEXT:    br label [[LOOP:%.*]]
551; CHECK:       loop:
552; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
553; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
554; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
555; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
556; CHECK-NEXT:    call void @may_write()
557; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
558; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
559; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
560; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
561; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
562; CHECK:       exit:
563; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
564; CHECK-NEXT:    ret i32 [[RES]]
565;
566entry:
567  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
568  br label %loop
569
570loop:
571  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
572  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
573  %l.1 = load i32, ptr %ptr.iv, align 4
574  %l.2 = load i32, ptr %min.ptr, align 4
575  call void @may_write()
576  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
577  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
578  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
579  %ec = icmp eq ptr %ptr.iv.next, %end
580  br i1 %ec, label %exit, label %loop
581
582exit:
583  %res = load i32, ptr %min.select, align 4
584  ret i32 %res
585}
586
587define i32 @test_pointer_phi_select_same_object_may_write_call_3(ptr %ptr, ptr %end)  {
588; CHECK-LABEL: @test_pointer_phi_select_same_object_may_write_call_3(
589; CHECK-NEXT:  entry:
590; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
591; CHECK-NEXT:    br label [[LOOP:%.*]]
592; CHECK:       loop:
593; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
594; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
595; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
596; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
597; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
598; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
599; CHECK-NEXT:    call void @may_write()
600; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
601; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
602; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
603; CHECK:       exit:
604; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
605; CHECK-NEXT:    ret i32 [[RES]]
606;
607entry:
608  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
609  br label %loop
610
611loop:
612  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
613  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
614  %l.1 = load i32, ptr %ptr.iv, align 4
615  %l.2 = load i32, ptr %min.ptr, align 4
616  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
617  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
618  call void @may_write()
619  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
620  %ec = icmp eq ptr %ptr.iv.next, %end
621  br i1 %ec, label %exit, label %loop
622
623exit:
624  %res = load i32, ptr %min.select, align 4
625  ret i32 %res
626}
627
628define i32 @test_pointer_phi_select_same_object_header_exit(ptr %ptr, ptr %end)  {
629; CHECK-LABEL: @test_pointer_phi_select_same_object_header_exit(
630; CHECK-NEXT:  entry:
631; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
632; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
633; CHECK:       loop.header:
634; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
635; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP_LATCH]] ]
636; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
637; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
638; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
639; CHECK:       loop.latch:
640; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
641; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
642; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
643; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
644; CHECK-NEXT:    br label [[LOOP_HEADER]]
645; CHECK:       exit:
646; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_PTR]], align 4
647; CHECK-NEXT:    ret i32 [[RES]]
648;
649entry:
650  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
651  br label %loop.header
652
653loop.header:
654  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop.latch ]
655  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop.latch ]
656  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
657  %ec = icmp eq ptr %ptr.iv.next, %end
658  br i1 %ec, label %exit, label %loop.latch
659
660loop.latch:
661  %l.1 = load i32, ptr %ptr.iv, align 4
662  %l.2 = load i32, ptr %min.ptr, align 4
663  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
664  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
665  br label %loop.header
666
667exit:
668  %res = load i32, ptr %min.ptr, align 4
669  ret i32 %res
670}
671
672define i32 @test_pointer_phi_select_same_object_ptr_use_cycle(ptr %ptr, ptr %end)  {
673; CHECK-LABEL: @test_pointer_phi_select_same_object_ptr_use_cycle(
674; CHECK-NEXT:  entry:
675; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
676; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
677; CHECK-NEXT:    br label [[LOOP:%.*]]
678; CHECK:       loop:
679; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
680; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
681; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
682; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
683; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
684; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
685; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
686; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
687; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
688; CHECK-NEXT:    br i1 [[EC]], label [[EXIT_PREHEADER:%.*]], label [[LOOP]]
689; CHECK:       exit.preheader:
690; CHECK-NEXT:    br label [[EXIT:%.*]]
691; CHECK:       exit:
692; CHECK-NEXT:    [[P:%.*]] = phi ptr [ [[P_NEXT:%.*]], [[EXIT]] ], [ [[MIN_SELECT]], [[EXIT_PREHEADER]] ]
693; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
694; CHECK-NEXT:    [[P_NEXT]] = getelementptr inbounds i32, ptr [[P]], i64 1
695; CHECK-NEXT:    br label [[EXIT]]
696;
697entry:
698  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
699  br label %loop
700
701loop:
702  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
703  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
704  %l.1 = load i32, ptr %ptr.iv, align 4
705  %l.2 = load i32, ptr %min.ptr, align 4
706  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
707  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
708  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
709  %ec = icmp eq ptr %ptr.iv.next, %end
710  br i1 %ec, label %exit, label %loop
711
712exit:
713  %p = phi ptr [ %min.select, %loop ], [ %p.next, %exit ]
714  store i32 0, ptr %p
715  %p.next = getelementptr inbounds i32, ptr %p, i64 1
716  br label %exit
717}
718
719define i32 @test_pointer_phi_select_same_object_maybe_clobbered_in_exit(ptr %ptr, ptr %end)  {
720; CHECK-LABEL: @test_pointer_phi_select_same_object_maybe_clobbered_in_exit(
721; CHECK-NEXT:  entry:
722; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
723; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
724; CHECK-NEXT:    br label [[LOOP:%.*]]
725; CHECK:       loop:
726; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
727; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
728; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
729; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
730; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
731; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
732; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
733; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
734; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
735; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
736; CHECK:       exit:
737; CHECK-NEXT:    store i32 0, ptr [[START_PTR]], align 4
738; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
739; CHECK-NEXT:    ret i32 [[RES]]
740;
741entry:
742  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
743  br label %loop
744
745loop:
746  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
747  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
748  %l.1 = load i32, ptr %ptr.iv, align 4
749  %l.2 = load i32, ptr %min.ptr, align 4
750  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
751  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
752  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
753  %ec = icmp eq ptr %ptr.iv.next, %end
754  br i1 %ec, label %exit, label %loop
755
756exit:
757  store i32 0, ptr %start.ptr
758  %res = load i32, ptr %min.select, align 4
759  ret i32 %res
760}
761
762define i32 @test_pointer_phi_select_same_object_maybe_clobbered_in_exit_2(ptr %ptr, ptr %end)  {
763; CHECK-LABEL: @test_pointer_phi_select_same_object_maybe_clobbered_in_exit_2(
764; CHECK-NEXT:  entry:
765; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
766; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
767; CHECK-NEXT:    br label [[LOOP:%.*]]
768; CHECK:       loop:
769; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
770; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
771; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
772; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
773; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
774; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
775; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
776; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
777; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
778; CHECK-NEXT:    br i1 [[EC]], label [[EXIT_1:%.*]], label [[LOOP]]
779; CHECK:       exit.1:
780; CHECK-NEXT:    store i32 0, ptr [[START_PTR]], align 4
781; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
782; CHECK-NEXT:    ret i32 [[RES]]
783;
784entry:
785  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
786  br label %loop
787
788loop:
789  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
790  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
791  %l.1 = load i32, ptr %ptr.iv, align 4
792  %l.2 = load i32, ptr %min.ptr, align 4
793  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
794  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
795  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
796  %ec = icmp eq ptr %ptr.iv.next, %end
797  br i1 %ec, label %exit.1, label %loop
798
799exit.1:
800  %lcssa.min = phi ptr [ %min.select, %loop ]
801  store i32 0, ptr %start.ptr
802  br label %exit.2
803
804exit.2:
805  %res = load i32, ptr %lcssa.min, align 4
806  ret i32 %res
807}
808
809declare i32 @__CxxFrameHandler3(...)
810
811define i32 @test_pointer_phi_select_same_object_invoke_in_chain(ptr %ptr, ptr %end)  personality ptr @__CxxFrameHandler3 {
812; CHECK-LABEL: @test_pointer_phi_select_same_object_invoke_in_chain(
813; CHECK-NEXT:  entry:
814; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
815; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
816; CHECK-NEXT:    br label [[LOOP:%.*]]
817; CHECK:       loop:
818; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
819; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
820; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
821; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
822; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
823; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
824; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
825; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
826; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
827; CHECK-NEXT:    br i1 [[EC]], label [[EXIT_1:%.*]], label [[LOOP]]
828; CHECK:       exit.1:
829; CHECK-NEXT:    store i32 0, ptr [[START_PTR]], align 4
830; CHECK-NEXT:    invoke void @may_throw()
831; CHECK-NEXT:    to label [[EXIT_2:%.*]] unwind label [[CATCH_OBJECT:%.*]]
832; CHECK:       exit.2:
833; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
834; CHECK-NEXT:    ret i32 [[RES]]
835; CHECK:       catch.object:
836; CHECK-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
837; CHECK-NEXT:    catch ptr null
838; CHECK-NEXT:    unreachable
839;
840entry:
841  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
842  br label %loop
843
844loop:
845  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
846  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
847  %l.1 = load i32, ptr %ptr.iv, align 4
848  %l.2 = load i32, ptr %min.ptr, align 4
849  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
850  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
851  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
852  %ec = icmp eq ptr %ptr.iv.next, %end
853  br i1 %ec, label %exit.1, label %loop
854
855exit.1:
856  %lcssa.min = phi ptr [ %min.select, %loop ]
857  store i32 0, ptr %start.ptr
858  invoke void @may_throw()
859  to label %exit.2 unwind label %catch.object
860
861exit.2:
862  %res = load i32, ptr %lcssa.min, align 4
863  ret i32 %res
864
865catch.object:
866  %lp = landingpad { ptr, i32 }
867  catch ptr null
868  unreachable
869}
870
871define i32 @test_pointer_phi_select_used_by_others_in_loop(ptr %ptr, ptr %end)  {
872; CHECK-LABEL: @test_pointer_phi_select_used_by_others_in_loop(
873; CHECK-NEXT:  entry:
874; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
875; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
876; CHECK-NEXT:    br label [[LOOP:%.*]]
877; CHECK:       loop:
878; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[L_3:%.*]], [[LOOP]] ]
879; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
880; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
881; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
882; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
883; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
884; CHECK-NEXT:    [[L_3]] = load i32, ptr [[MIN_SELECT]], align 4
885; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i32 [[L_3]]
886; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
887; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
888; CHECK:       exit:
889; CHECK-NEXT:    ret i32 [[L_3]]
890;
891entry:
892  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
893  br label %loop
894
895loop:
896  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
897  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
898  %l.1 = load i32, ptr %ptr.iv, align 4
899  %l.2 = load i32, ptr %min.ptr, align 4
900  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
901  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
902  %l.3 = load i32, ptr %min.select, align 4
903  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i32 %l.3
904  %ec = icmp eq ptr %ptr.iv.next, %end
905  br i1 %ec, label %exit, label %loop
906
907exit:
908  %res = load i32, ptr %min.select, align 4
909  ret i32 %res
910}
911
912define i32 @test_pointer_phi_used_by_others_in_loop_1(ptr %ptr, ptr %end)  {
913; CHECK-LABEL: @test_pointer_phi_used_by_others_in_loop_1(
914; CHECK-NEXT:  entry:
915; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
916; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
917; CHECK-NEXT:    br label [[LOOP:%.*]]
918; CHECK:       loop:
919; CHECK-NEXT:    [[L_3:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[L_3_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]
920; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY]] ], [ [[TMP0:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
921; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
922; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
923; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
924; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
925; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
926; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
927; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i32 [[L_3]]
928; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
929; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_LOOP_CRIT_EDGE]]
930; CHECK:       loop.loop_crit_edge:
931; CHECK-NEXT:    [[L_3_PRE]] = load i32, ptr [[MIN_SELECT]], align 4
932; CHECK-NEXT:    br label [[LOOP]]
933; CHECK:       exit:
934; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
935; CHECK-NEXT:    ret i32 [[RES]]
936;
937entry:
938  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
939  br label %loop
940
941loop:
942  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
943  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
944  %l.1 = load i32, ptr %ptr.iv, align 4
945  %l.2 = load i32, ptr %min.ptr, align 4
946  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
947  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
948  %l.3 = load i32, ptr %min.ptr, align 4
949  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i32 %l.3
950  %ec = icmp eq ptr %ptr.iv.next, %end
951  br i1 %ec, label %exit, label %loop
952
953exit:
954  %res = load i32, ptr %min.select, align 4
955  ret i32 %res
956}
957
958define i32 @test_pointer_phi_used_by_others_in_loop_2(ptr %ptr, ptr %end)  {
959; CHECK-LABEL: @test_pointer_phi_used_by_others_in_loop_2(
960; CHECK-NEXT:  entry:
961; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
962; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
963; CHECK-NEXT:    br label [[LOOP:%.*]]
964; CHECK:       loop:
965; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
966; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
967; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
968; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
969; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
970; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
971; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
972; CHECK-NEXT:    [[GEP_MIN_PTR:%.*]] = getelementptr inbounds i32, ptr [[MIN_PTR]], i32 1
973; CHECK-NEXT:    [[L_3:%.*]] = load i32, ptr [[GEP_MIN_PTR]], align 4
974; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i32 [[L_3]]
975; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
976; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
977; CHECK:       exit:
978; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
979; CHECK-NEXT:    ret i32 [[RES]]
980;
981entry:
982  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
983  br label %loop
984
985loop:
986  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
987  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
988  %l.1 = load i32, ptr %ptr.iv, align 4
989  %l.2 = load i32, ptr %min.ptr, align 4
990  %cmp.i.i.i = icmp ult i32 %l.1, %l.2
991  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
992  %gep.min.ptr = getelementptr inbounds i32, ptr %min.ptr, i32 1
993  %l.3 = load i32, ptr %gep.min.ptr, align 4
994  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i32 %l.3
995  %ec = icmp eq ptr %ptr.iv.next, %end
996  br i1 %ec, label %exit, label %loop
997
998exit:
999  %res = load i32, ptr %min.select, align 4
1000  ret i32 %res
1001}
1002
1003define i32 @test_pointer_phi_select_no_iter_load(ptr %ptr, ptr %end)  {
1004; CHECK-LABEL: @test_pointer_phi_select_no_iter_load(
1005; CHECK-NEXT:  entry:
1006; CHECK-NEXT:    [[START_PTR:%.*]] = getelementptr inbounds i32, ptr [[PTR:%.*]], i64 1
1007; CHECK-NEXT:    br label [[LOOP:%.*]]
1008; CHECK:       loop:
1009; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
1010; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
1011; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
1012; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 10, [[L_2]]
1013; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
1014; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
1015; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
1016; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
1017; CHECK:       exit:
1018; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
1019; CHECK-NEXT:    ret i32 [[RES]]
1020;
1021entry:
1022  %start.ptr = getelementptr inbounds i32, ptr %ptr, i64 1
1023  br label %loop
1024
1025loop:
1026  %ptr.iv = phi ptr [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
1027  %min.ptr = phi ptr [ %ptr, %entry ], [ %min.select, %loop ]
1028  %l.2 = load i32, ptr %min.ptr, align 4
1029  %cmp.i.i.i = icmp ult i32 10, %l.2
1030  %min.select  = select i1 %cmp.i.i.i, ptr %ptr.iv, ptr %min.ptr
1031  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i64 1
1032  %ec = icmp eq ptr %ptr.iv.next, %end
1033  br i1 %ec, label %exit, label %loop
1034
1035exit:
1036  %res = load i32, ptr %min.select, align 4
1037  ret i32 %res
1038}
1039