xref: /llvm-project/polly/test/ScopDetect/base_pointer.ll (revision b332499a94df11870dfc7598645c59656deb933d)
1; RUN: opt %loadPolly -disable-basic-aa -polly-invariant-load-hoisting=true -polly-print-detect -disable-output < %s | FileCheck %s
2
3
4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
5
6define void @base_pointer_in_condition(ptr noalias %A_ptr, i64 %N) nounwind {
7entry:
8  fence seq_cst
9  br label %pre
10
11pre:
12  %A = load ptr, ptr %A_ptr
13  br i1 true, label %for.i, label %then
14
15for.i:
16  %indvar = phi i64 [ 0, %pre ], [ %indvar.next, %for.i ]
17  %scevgep = getelementptr i64, ptr %A, i64 %indvar
18  store i64 %indvar, ptr %scevgep
19  %indvar.next = add nsw i64 %indvar, 1
20  %exitcond = icmp eq i64 %indvar.next, %N
21  br i1 %exitcond, label %then, label %for.i
22
23then:
24  br label %return
25
26return:
27  fence seq_cst
28  ret void
29}
30
31; CHECK-LABEL: base_pointer_in_condition
32; CHECK: Valid Region for Scop: pre => return
33
34define void @base_pointer_is_argument(ptr %A, i64 %n) {
35entry:
36  br label %for.i
37
38for.i:
39  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
40  br label %S1
41
42S1:
43  %conv = sitofp i64 %indvar.i to float
44  %arrayidx5 = getelementptr float, ptr %A, i64 %indvar.i
45  store float %conv, ptr %arrayidx5, align 4
46  br label %for.i.inc
47
48for.i.inc:
49  %indvar.i.next = add i64 %indvar.i, 1
50  %exitcond.i = icmp ne i64 %indvar.i.next, %n
51  br i1 %exitcond.i, label %for.i, label %exit
52
53exit:
54  ret void
55}
56
57; CHECK-LABEL: base_pointer_is_argument
58; CHECK: Valid Region for Scop: for.i => exit
59
60define void @base_pointer_is_const_expr(i64 %n) {
61entry:
62  br label %for.i
63
64for.i:
65  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
66  br label %S1
67
68S1:
69  %conv = sitofp i64 %indvar.i to float
70  %arrayidx5 = getelementptr float, ptr inttoptr (i64 100 to ptr), i64 %indvar.i
71  store float %conv, ptr %arrayidx5, align 4
72  br label %for.i.inc
73
74for.i.inc:
75  %indvar.i.next = add i64 %indvar.i, 1
76  %exitcond.i = icmp ne i64 %indvar.i.next, %n
77  br i1 %exitcond.i, label %for.i, label %exit
78
79exit:
80  ret void
81}
82
83; CHECK-LABEL: base_pointer_is_const_expr
84; CHECK-LABEL: Valid Region for Scop: for.i => exit
85
86@A = external global float
87
88define void @base_pointer_is_global(i64 %n) {
89entry:
90  br label %for.i
91
92for.i:
93  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
94  br label %S1
95
96S1:
97  %conv = sitofp i64 %indvar.i to float
98  %arrayidx5 = getelementptr float, ptr @A, i64 %indvar.i
99  store float %conv, ptr %arrayidx5, align 4
100  br label %for.i.inc
101
102for.i.inc:
103  %indvar.i.next = add i64 %indvar.i, 1
104  %exitcond.i = icmp ne i64 %indvar.i.next, %n
105  br i1 %exitcond.i, label %for.i, label %exit
106
107exit:
108  ret void
109}
110
111; CHECK-LABEL: base_pointer_is_global
112; CHECK: Valid Region for Scop: for.i => exit
113
114declare ptr @foo()
115
116define void @base_pointer_is_inst_outside(i64 %n) {
117entry:
118  %A = call ptr @foo()
119  br label %for.i
120
121for.i:
122  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
123  br label %S1
124
125S1:
126  %conv = sitofp i64 %indvar.i to float
127  %arrayidx5 = getelementptr float, ptr %A, i64 %indvar.i
128  store float %conv, ptr %arrayidx5, align 4
129  br label %for.i.inc
130
131for.i.inc:
132  %indvar.i.next = add i64 %indvar.i, 1
133  %exitcond.i = icmp ne i64 %indvar.i.next, %n
134  br i1 %exitcond.i, label %for.i, label %exit
135
136exit:
137  ret void
138}
139
140; CHECK-LABEL: base_pointer_is_inst_outside
141; CHECK: Valid Region for Scop: for.i => exit
142
143declare ptr @getNextBasePtr(ptr) readnone nounwind
144
145define void @base_pointer_is_phi_node(i64 %n, ptr %A) {
146entry:
147  br label %for.i
148
149for.i:
150  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
151  %ptr = phi ptr [ %ptr.next, %for.i.inc ], [ %A, %entry ]
152; To get a PHI node inside a SCoP that can not be analyzed but
153; for which the surrounding SCoP is normally still valid we use a function
154; without any side effects.
155  %ptr.next = call ptr @getNextBasePtr(ptr %ptr)
156  br label %S1
157
158S1:
159  %conv = sitofp i64 %indvar.i to float
160  %arrayidx5 = getelementptr float, ptr %ptr, i64 %indvar.i
161  store float %conv, ptr %arrayidx5, align 4
162  br label %for.i.inc
163
164for.i.inc:
165  %indvar.i.next = add i64 %indvar.i, 1
166  %exitcond.i = icmp ne i64 %indvar.i.next, %n
167  br i1 %exitcond.i, label %for.i, label %exit
168
169exit:
170  ret void
171}
172
173; CHECK-LABEL: base_pointer_is_phi_node
174; CHECK-NOT: Valid Region for Scop
175
176define void @base_pointer_is_inst_inside_invariant_1(i64 %n, ptr %A) {
177entry:
178  br label %for.i
179
180for.i:
181  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
182; A function return value, even with readnone nounwind attributes, is not
183; considered a valid base pointer because it can return a pointer that aliases
184; with something else (e.g. %A or a global) or return a different pointer at
185; every call (e.g. malloc)
186  %ptr = call ptr @getNextBasePtr(ptr %A)
187  br label %S1
188
189S1:
190  %conv = sitofp i64 %indvar.i to float
191  %arrayidx5 = getelementptr float, ptr %ptr, i64 %indvar.i
192  store float %conv, ptr %arrayidx5, align 4
193  br label %for.i.inc
194
195for.i.inc:
196  %indvar.i.next = add i64 %indvar.i, 1
197  %exitcond.i = icmp ne i64 %indvar.i.next, %n
198  br i1 %exitcond.i, label %for.i, label %exit
199
200exit:
201  ret void
202}
203
204; CHECK-LABEL: base_pointer_is_inst_inside_invariant_1
205; CHECK-NOT: Valid Region for Scop
206
207declare ptr @getNextBasePtr2(ptr) readnone nounwind
208
209define void @base_pointer_is_inst_inside_invariant_2(i64 %n, ptr %A) {
210entry:
211  br label %for.i
212
213for.i:
214  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
215  %ptr = call ptr @getNextBasePtr2(ptr %A)
216  %ptr2 = call ptr @getNextBasePtr(ptr %ptr)
217  br label %S1
218
219S1:
220  %conv = sitofp i64 %indvar.i to float
221  %arrayidx5 = getelementptr float, ptr %ptr2, i64 %indvar.i
222  store float %conv, ptr %arrayidx5, align 4
223  br label %for.i.inc
224
225for.i.inc:
226  %indvar.i.next = add i64 %indvar.i, 1
227  %exitcond.i = icmp ne i64 %indvar.i.next, %n
228  br i1 %exitcond.i, label %for.i, label %exit
229
230exit:
231  ret void
232}
233
234; CHECK-LABEL: base_pointer_is_inst_inside_invariant_2
235; CHECK-NOT: Valid Region for Scop
236
237declare ptr @getNextBasePtr3(ptr, i64) readnone nounwind
238
239define void @base_pointer_is_inst_inside_variant(i64 %n, ptr %A) {
240entry:
241  br label %for.i
242
243for.i:
244  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
245  %ptr = call ptr @getNextBasePtr3(ptr %A, i64 %indvar.i)
246  %ptr2 = call ptr @getNextBasePtr(ptr %ptr)
247  br label %S1
248
249S1:
250  %conv = sitofp i64 %indvar.i to float
251  %arrayidx5 = getelementptr float, ptr %ptr2, i64 %indvar.i
252  store float %conv, ptr %arrayidx5, align 4
253  br label %for.i.inc
254
255for.i.inc:
256  %indvar.i.next = add i64 %indvar.i, 1
257  %exitcond.i = icmp ne i64 %indvar.i.next, %n
258  br i1 %exitcond.i, label %for.i, label %exit
259
260exit:
261  ret void
262}
263
264; CHECK: base_pointer_is_inst_inside_variant
265; CHECK-NOT: Valid Region for Scop
266
267define void @base_pointer_is_ptr2ptr(ptr noalias %A, i64 %n) {
268entry:
269  br label %for.i
270
271for.i:
272  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
273  %arrayidx = getelementptr ptr, ptr %A, i64 %indvar.i
274  br label %for.j
275
276for.j:
277  %indvar.j = phi i64 [ 0, %for.i ], [ %indvar.j.next, %for.j ]
278  %conv = sitofp i64 %indvar.i to float
279  %basepointer = load ptr, ptr %arrayidx, align 8
280  %arrayidx5 = getelementptr float, ptr %basepointer, i64 %indvar.j
281  store float %conv, ptr %arrayidx5, align 4
282  %indvar.j.next = add i64 %indvar.j, 1
283  %exitcond.j = icmp ne i64 %indvar.j.next, %n
284  br i1 %exitcond.j, label %for.j, label %for.i.inc
285
286for.i.inc:
287  %indvar.i.next = add i64 %indvar.i, 1
288  %exitcond.i = icmp ne i64 %indvar.i.next, %n
289  br i1 %exitcond.i, label %for.i, label %exit
290
291exit:
292  ret void
293}
294
295; CHECK: base_pointer_is_ptr2ptr
296; CHECK: Valid Region for Scop: for.j => for.i.inc
297