1 ; RUN: opt %loadPolly -disable-basicaa -polly-detect -polly-invariant-load-hoisting=true -analyze < %s | FileCheck %s
4 target 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"
6 define void @base_pointer_in_condition(i64** noalias %A_ptr, i64 %N) nounwind {
12 %A = load i64*, i64** %A_ptr
13 br i1 true, label %for.i, label %then
16 %indvar = phi i64 [ 0, %pre ], [ %indvar.next, %for.i ]
17 %scevgep = getelementptr i64, i64* %A, i64 %indvar
18 store i64 %indvar, i64* %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
31 ; CHECK-LABEL: base_pointer_in_condition
32 ; CHECK: Valid Region for Scop: pre => return
34 define void @base_pointer_is_argument(float* %A, i64 %n) {
39 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
43 %conv = sitofp i64 %indvar.i to float
44 %arrayidx5 = getelementptr float, float* %A, i64 %indvar.i
45 store float %conv, float* %arrayidx5, align 4
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
57 ; CHECK-LABEL: base_pointer_is_argument
58 ; CHECK: Valid Region for Scop: for.i => exit
60 define void @base_pointer_is_const_expr(i64 %n) {
65 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
69 %conv = sitofp i64 %indvar.i to float
70 %arrayidx5 = getelementptr float, float* inttoptr (i64 100 to float*), i64 %indvar.i
71 store float %conv, float* %arrayidx5, align 4
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
83 ; CHECK-LABEL: base_pointer_is_const_expr
84 ; CHECK-LABEL: Valid Region for Scop: for.i => exit
86 @A = external global float
88 define void @base_pointer_is_global(i64 %n) {
93 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
97 %conv = sitofp i64 %indvar.i to float
98 %arrayidx5 = getelementptr float, float* @A, i64 %indvar.i
99 store float %conv, float* %arrayidx5, align 4
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
111 ; CHECK-LABEL: base_pointer_is_global
112 ; CHECK: Valid Region for Scop: for.i => exit
114 declare float *@foo()
116 define void @base_pointer_is_inst_outside(i64 %n) {
118 %A = call float *@foo()
122 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
126 %conv = sitofp i64 %indvar.i to float
127 %arrayidx5 = getelementptr float, float* %A, i64 %indvar.i
128 store float %conv, float* %arrayidx5, align 4
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
140 ; CHECK-LABEL: base_pointer_is_inst_outside
141 ; CHECK: Valid Region for Scop: for.i => exit
143 declare float* @getNextBasePtr(float*) readnone nounwind
145 define void @base_pointer_is_phi_node(i64 %n, float* %A) {
150 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
151 %ptr = phi float* [ %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 float* @getNextBasePtr(float* %ptr)
159 %conv = sitofp i64 %indvar.i to float
160 %arrayidx5 = getelementptr float, float* %ptr, i64 %indvar.i
161 store float %conv, float* %arrayidx5, align 4
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
173 ; CHECK-LABEL: base_pointer_is_phi_node
174 ; CHECK-NOT: Valid Region for Scop
176 define void @base_pointer_is_inst_inside_invariant_1(i64 %n, float* %A) {
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 float* @getNextBasePtr(float* %A)
190 %conv = sitofp i64 %indvar.i to float
191 %arrayidx5 = getelementptr float, float* %ptr, i64 %indvar.i
192 store float %conv, float* %arrayidx5, align 4
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
204 ; CHECK-LABEL: base_pointer_is_inst_inside_invariant_1
205 ; CHECK-NOT: Valid Region for Scop
207 declare float* @getNextBasePtr2(float*) readnone nounwind
209 define void @base_pointer_is_inst_inside_invariant_2(i64 %n, float* %A) {
214 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
215 %ptr = call float* @getNextBasePtr2(float* %A)
216 %ptr2 = call float* @getNextBasePtr(float* %ptr)
220 %conv = sitofp i64 %indvar.i to float
221 %arrayidx5 = getelementptr float, float* %ptr2, i64 %indvar.i
222 store float %conv, float* %arrayidx5, align 4
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
234 ; CHECK-LABEL: base_pointer_is_inst_inside_invariant_2
235 ; CHECK-NOT: Valid Region for Scop
237 declare float* @getNextBasePtr3(float*, i64) readnone nounwind
239 define void @base_pointer_is_inst_inside_variant(i64 %n, float* %A) {
244 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
245 %ptr = call float* @getNextBasePtr3(float* %A, i64 %indvar.i)
246 %ptr2 = call float* @getNextBasePtr(float* %ptr)
250 %conv = sitofp i64 %indvar.i to float
251 %arrayidx5 = getelementptr float, float* %ptr2, i64 %indvar.i
252 store float %conv, float* %arrayidx5, align 4
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
264 ; CHECK: base_pointer_is_inst_inside_variant
265 ; CHECK-NOT: Valid Region for Scop
267 define void @base_pointer_is_ptr2ptr(float** noalias %A, i64 %n) {
272 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]
273 %arrayidx = getelementptr float*, float** %A, i64 %indvar.i
277 %indvar.j = phi i64 [ 0, %for.i ], [ %indvar.j.next, %for.j ]
278 %conv = sitofp i64 %indvar.i to float
279 %basepointer = load float*, float** %arrayidx, align 8
280 %arrayidx5 = getelementptr float, float* %basepointer, i64 %indvar.j
281 store float %conv, float* %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
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
295 ; CHECK: base_pointer_is_ptr2ptr
296 ; CHECK: Valid Region for Scop: for.j => for.i.inc