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