1; RUN: opt -passes='require<scalar-evolution>,require<aa>,loop(print-access-info)' -disable-output  < %s 2>&1 | FileCheck %s
2
3%s1 = type { [32000 x double], [32000 x double], [32000 x double] }
4
5define i32 @load_with_pointer_phi_no_runtime_checks(%s1* %data) {
6; CHECK-LABEL: load_with_pointer_phi_no_runtime_checks
7; CHECK-NEXT:  loop.header:
8; CHECK-NEXT:    Report: cannot identify array bounds
9;
10entry:
11  br label %loop.header
12
13loop.header:                                        ; preds = %loop.latch, %entry
14  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
15  %iv.next = add nuw nsw i64 %iv, 1
16  %cmp5 = icmp ult i64 %iv, 15999
17  %arrayidx = getelementptr inbounds %s1, %s1 * %data, i64 0, i32 0, i64 %iv
18  br i1 %cmp5, label %if.then, label %if.else
19
20if.then:                                          ; preds = %loop.header
21  %gep.1 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 1, i64 %iv
22  br label %loop.latch
23
24if.else:                                          ; preds = %loop.header
25  %gep.2 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 2, i64 %iv
26  br label %loop.latch
27
28loop.latch:                                          ; preds = %if.else, %if.then
29  %gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ]
30  %v8 = load double, double* %gep.2.sink, align 8
31  %mul16 = fmul double 3.0, %v8
32  store double %mul16, double* %arrayidx, align 8
33  %exitcond.not = icmp eq i64 %iv.next, 32000
34  br i1 %exitcond.not, label %exit, label %loop.header
35
36exit:                                             ; preds = %loop.latch
37  ret i32 10
38}
39
40define i32 @store_with_pointer_phi_no_runtime_checks(%s1* %data) {
41; CHECK-LABEL: 'store_with_pointer_phi_no_runtime_checks'
42; CHECK-NEXT:  loop.header:
43; CHECK-NEXT:    Report: cannot identify array bounds
44;
45entry:
46  br label %loop.header
47
48loop.header:                                        ; preds = %loop.latch, %entry
49  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
50  %iv.next = add nuw nsw i64 %iv, 1
51  %cmp5 = icmp ult i64 %iv, 15999
52  %arrayidx = getelementptr inbounds %s1, %s1 * %data, i64 0, i32 0, i64 %iv
53  br i1 %cmp5, label %if.then, label %if.else
54
55if.then:                                          ; preds = %loop.header
56  %gep.1 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 1, i64 %iv
57  br label %loop.latch
58
59if.else:                                          ; preds = %loop.header
60  %gep.2 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 2, i64 %iv
61  br label %loop.latch
62
63loop.latch:                                          ; preds = %if.else, %if.then
64  %gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ]
65  %v8 = load double, double* %arrayidx, align 8
66  %mul16 = fmul double 3.0, %v8
67  store double %mul16, double* %gep.2.sink, align 8
68  %exitcond.not = icmp eq i64 %iv.next, 32000
69  br i1 %exitcond.not, label %exit, label %loop.header
70
71exit:                                             ; preds = %loop.latch
72  ret i32 10
73}
74
75define i32 @store_with_pointer_phi_runtime_checks(double* %A, double* %B, double* %C) {
76; CHECK-LABEL: 'store_with_pointer_phi_runtime_checks'
77; CHECK-NEXT:  loop.header:
78; CHECK-NEXT:    Report: cannot identify array bounds
79;
80entry:
81  br label %loop.header
82
83loop.header:                                        ; preds = %loop.latch, %entry
84  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
85  %iv.next = add nuw nsw i64 %iv, 1
86  %cmp5 = icmp ult i64 %iv, 15999
87  %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
88  br i1 %cmp5, label %if.then, label %if.else
89
90if.then:                                          ; preds = %loop.header
91  %gep.1 = getelementptr inbounds double, double* %B, i64 %iv
92  br label %loop.latch
93
94if.else:                                          ; preds = %loop.header
95  %gep.2 = getelementptr inbounds double, double* %C, i64 %iv
96  br label %loop.latch
97
98loop.latch:                                          ; preds = %if.else, %if.then
99  %gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ]
100  %v8 = load double, double* %arrayidx, align 8
101  %mul16 = fmul double 3.0, %v8
102  store double %mul16, double* %gep.2.sink, align 8
103  %exitcond.not = icmp eq i64 %iv.next, 32000
104  br i1 %exitcond.not, label %exit, label %loop.header
105
106exit:                                             ; preds = %loop.latch
107  ret i32 10
108}
109
110define i32 @load_with_pointer_phi_outside_loop(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
111; CHECK-LABEL: 'load_with_pointer_phi_outside_loop'
112; CHECK-NEXT:  loop.header:
113; CHECK-NEXT:    Report: unsafe dependent memory operations in loop
114; CHECK-NEXT:    Dependences:
115; CHECK-NEXT:      Unknown:
116; CHECK-NEXT:          %v8 = load double, double* %ptr, align 8 ->
117; CHECK-NEXT:          store double %mul16, double* %arrayidx, align 8
118;
119entry:
120  br i1 %c.0, label %if.then, label %if.else
121
122if.then:
123  br label %loop.ph
124
125if.else:
126  %ptr.select = select i1 %c.1, double* %C, double* %B
127  br label %loop.ph
128
129loop.ph:
130  %ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ]
131  br label %loop.header
132
133loop.header:                                        ; preds = %loop.latch, %entry
134  %iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ]
135  %iv.next = add nuw nsw i64 %iv, 1
136  %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
137  %v8 = load double, double* %ptr, align 8
138  %mul16 = fmul double 3.0, %v8
139  store double %mul16, double* %arrayidx, align 8
140  %exitcond.not = icmp eq i64 %iv.next, 32000
141  br i1 %exitcond.not, label %exit, label %loop.header
142
143exit:                                             ; preds = %loop.latch
144  ret i32 10
145}
146
147define i32 @store_with_pointer_phi_outside_loop(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
148; CHECK-LABEL: 'store_with_pointer_phi_outside_loop'
149; CHECK-NEXT:  loop.header:
150; CHECK-NEXT:    Report: unsafe dependent memory operations in loop.
151; CHECK-NEXT:    Dependences:
152; CHECK-NEXT:      Unknown:
153; CHECK-NEXT:          %v8 = load double, double* %arrayidx, align 8 ->
154; CHECK-NEXT:          store double %mul16, double* %ptr, align 8
155;
156entry:
157  br i1 %c.0, label %if.then, label %if.else
158
159if.then:
160  br label %loop.ph
161
162if.else:
163  %ptr.select = select i1 %c.1, double* %C, double* %B
164  br label %loop.ph
165
166loop.ph:
167  %ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ]
168  br label %loop.header
169
170loop.header:                                        ; preds = %loop.latch, %entry
171  %iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ]
172  %iv.next = add nuw nsw i64 %iv, 1
173  %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
174  %v8 = load double, double* %arrayidx, align 8
175  %mul16 = fmul double 3.0, %v8
176  store double %mul16, double* %ptr, align 8
177  %exitcond.not = icmp eq i64 %iv.next, 32000
178  br i1 %exitcond.not, label %exit, label %loop.header
179
180exit:                                             ; preds = %loop.latch
181  ret i32 10
182}
183
184define i32 @store_with_pointer_phi_incoming_phi(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
185; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi'
186; CHECK-NEXT:  loop.header:
187; CHECK-NEXT:     Report: cannot identify array bounds
188; CHECK-NEXT:     Dependences:
189; CHECK-NEXT:     Run-time memory checks:
190; CHECK-NEXT:     Grouped accesses:
191; CHECK-EMPTY
192entry:
193  br label %loop.header
194
195loop.header:                                        ; preds = %loop.latch, %entry
196  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
197  %iv.next = add nuw nsw i64 %iv, 1
198  %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
199  %v8 = load double, double* %arrayidx, align 8
200  %mul16 = fmul double 3.0, %v8
201  br i1 %c.0, label %loop.then, label %loop.latch
202
203loop.then:
204  br i1 %c.0, label %loop.then.2, label %loop.else.2
205
206loop.then.2:
207  br label %merge.2
208
209loop.else.2:
210  br label %merge.2
211
212
213merge.2:
214  %ptr = phi double* [ %A, %loop.then.2 ], [ %B, %loop.else.2 ]
215  br label %loop.latch
216
217
218loop.latch:
219  %ptr.2 = phi double* [ %ptr, %merge.2], [ %C, %loop.header ]
220  store double %mul16, double* %ptr.2, align 8
221  %exitcond.not = icmp eq i64 %iv.next, 32000
222  br i1 %exitcond.not, label %exit, label %loop.header
223
224exit:                                             ; preds = %loop.latch
225  ret i32 10
226}
227
228; Test cases with pointer phis forming a cycle.
229define i32 @store_with_pointer_phi_incoming_phi_irreducible_cycle(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
230; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi_irreducible_cycle'
231; CHECK-NEXT:  loop.header:
232; CHECK-NEXT:     Report: cannot identify array bounds
233; CHECK-NEXT:     Dependences:
234; CHECK-NEXT:     Run-time memory checks:
235; CHECK-NEXT:     Grouped accesses:
236; CHECK-EMPTY
237entry:
238  br label %loop.header
239
240loop.header:                                        ; preds = %loop.latch, %entry
241  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
242  %iv.next = add nuw nsw i64 %iv, 1
243  %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
244  %v8 = load double, double* %arrayidx, align 8
245  %mul16 = fmul double 3.0, %v8
246  br i1 %c.0, label %loop.then, label %loop.latch
247
248loop.then:
249  br i1 %c.0, label %BB.A, label %BB.B
250
251BB.A:
252  %ptr = phi double* [ %A, %loop.then ], [ %ptr.2, %BB.B ]
253  br label %BB.B
254
255BB.B:
256  %ptr.2 = phi double* [ %ptr, %BB.A ], [ %B, %loop.then ]
257  br i1 %c.1, label %loop.latch, label %BB.A
258
259loop.latch:
260  %ptr.3 = phi double* [ %ptr.2, %BB.B ], [ %C, %loop.header ]
261  store double %mul16, double* %ptr.3, align 8
262  %exitcond.not = icmp eq i64 %iv.next, 32000
263  br i1 %exitcond.not, label %exit, label %loop.header
264
265exit:                                             ; preds = %loop.latch
266  ret i32 10
267}
268
269define i32 @store_with_pointer_phi_outside_loop_select(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
270; CHECK-LABEL: 'store_with_pointer_phi_outside_loop_select'
271; CHECK-NEXT:  loop.header:
272; CHECK-NEXT:    Report: unsafe dependent memory operations in loop.
273; CHECK-NEXT:    Dependences:
274; CHECK-NEXT:      Unknown:
275; CHECK-NEXT:          %v8 = load double, double* %arrayidx, align 8 ->
276; CHECK-NEXT:          store double %mul16, double* %ptr, align 8
277;
278entry:
279  br i1 %c.0, label %if.then, label %if.else
280
281if.then:
282  br label %loop.ph
283
284if.else:
285  %ptr.select = select i1 %c.1, double* %C, double* %B
286  br label %loop.ph
287
288loop.ph:
289  %ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ]
290  br label %loop.header
291
292loop.header:                                        ; preds = %loop.latch, %entry
293  %iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ]
294  %iv.next = add nuw nsw i64 %iv, 1
295  %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
296  %v8 = load double, double* %arrayidx, align 8
297  %mul16 = fmul double 3.0, %v8
298  store double %mul16, double* %ptr, align 8
299  %exitcond.not = icmp eq i64 %iv.next, 32000
300  br i1 %exitcond.not, label %exit, label %loop.header
301
302exit:                                             ; preds = %loop.latch
303  ret i32 10
304}
305
306define i32 @store_with_pointer_phi_in_same_bb_use_other_phi(double* %A, double* %B, double* %C, double* %D, i1 %c.0, i1 %c.1) {
307; CHECK-LABEL: Loop access info in function 'store_with_pointer_phi_in_same_bb_use_other_phi':
308; CHECK-NEXT:   loop.header:
309; CHECK-NEXT:     Report: cannot identify array bounds
310; CHECK-NEXT:     Dependences:
311; CHECK-NEXT:     Run-time memory checks:
312; CHECK-NEXT:     Grouped accesses:
313; CHECK-EMPTY:
314;
315entry:
316  br label %loop.header
317
318loop.header:                                        ; preds = %loop.latch, %entry
319  %ptr.0 = phi double* [ %C, %entry ], [ %D, %loop.header ]
320  %ptr.1 = phi double* [ %B, %entry ], [ %ptr.0, %loop.header ]
321  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.header ]
322  %iv.next = add nuw nsw i64 %iv, 1
323  %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
324  %v8 = load double, double* %arrayidx, align 8
325  %mul16 = fmul double 3.0, %v8
326  store double %mul16, double* %ptr.1, align 8
327  %exitcond.not = icmp eq i64 %iv.next, 32000
328  br i1 %exitcond.not, label %exit, label %loop.header
329
330exit:                                             ; preds = %loop.latch
331  ret i32 10
332}
333
334define void @phi_load_store_memdep_check(i1 %c, i16* %A, i16* %B, i16* %C) {
335; CHECK-LABEL: Loop access info in function 'phi_load_store_memdep_check':
336; CHECK-NEXT:   for.body:
337; CHECK-NEXT:     Report: cannot identify array bounds
338; CHECK-NEXT:     Dependences:
339; CHECK-NEXT:     Run-time memory checks:
340; CHECK-NEXT:     Grouped accesses:
341; CHECK-EMPTY:
342;
343entry:
344  br label %for.body
345
346for.body:                                         ; preds = %if.end, %entry
347  %iv = phi i16 [ 0, %entry ], [ %iv.next, %if.end ]
348  %lv = load i16, i16* %A, align 1
349  store i16 %lv, i16* %A, align 1
350  br i1 %c, label %if.then, label %if.end
351
352if.then:                                          ; preds = %for.body
353  %lv2 = load i16, i16* %A, align 1
354  br label %if.end
355
356if.end:                                           ; preds = %if.then, %for.body
357  %c.sink = phi i16* [ %B, %if.then ], [ %C, %for.body ]
358  %lv3 = load i16, i16* %c.sink
359  %add = add i16 %lv3, 10
360  store i16 %add, i16* %c.sink, align 1
361  %iv.next = add nuw nsw i16 %iv, 1
362  %tobool.not = icmp eq i16 %iv.next, 1000
363  br i1 %tobool.not, label %for.end.loopexit, label %for.body
364
365for.end.loopexit:                                 ; preds = %if.end
366  ret void
367}
368