297 lines · plain
1; RUN: opt %loadNPMPolly --aa-pipeline= -polly-invariant-load-hoisting=true '-passes=polly-custom<detect>' -polly-print-detect -disable-output < %s | FileCheck %s2 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_cst9 br label %pre10 11pre:12 %A = load ptr, ptr %A_ptr13 br i1 true, label %for.i, label %then14 15for.i:16 %indvar = phi i64 [ 0, %pre ], [ %indvar.next, %for.i ]17 %scevgep = getelementptr i64, ptr %A, i64 %indvar18 store i64 %indvar, ptr %scevgep19 %indvar.next = add nsw i64 %indvar, 120 %exitcond = icmp eq i64 %indvar.next, %N21 br i1 %exitcond, label %then, label %for.i22 23then:24 br label %return25 26return:27 fence seq_cst28 ret void29}30 31; CHECK-LABEL: base_pointer_in_condition32; CHECK: Valid Region for Scop: pre => return33 34define void @base_pointer_is_argument(ptr %A, i64 %n) {35entry:36 br label %for.i37 38for.i:39 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]40 br label %S141 42S1:43 %conv = sitofp i64 %indvar.i to float44 %arrayidx5 = getelementptr float, ptr %A, i64 %indvar.i45 store float %conv, ptr %arrayidx5, align 446 br label %for.i.inc47 48for.i.inc:49 %indvar.i.next = add i64 %indvar.i, 150 %exitcond.i = icmp ne i64 %indvar.i.next, %n51 br i1 %exitcond.i, label %for.i, label %exit52 53exit:54 ret void55}56 57; CHECK-LABEL: base_pointer_is_argument58; CHECK: Valid Region for Scop: for.i => exit59 60define void @base_pointer_is_const_expr(i64 %n) {61entry:62 br label %for.i63 64for.i:65 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]66 br label %S167 68S1:69 %conv = sitofp i64 %indvar.i to float70 %arrayidx5 = getelementptr float, ptr inttoptr (i64 100 to ptr), i64 %indvar.i71 store float %conv, ptr %arrayidx5, align 472 br label %for.i.inc73 74for.i.inc:75 %indvar.i.next = add i64 %indvar.i, 176 %exitcond.i = icmp ne i64 %indvar.i.next, %n77 br i1 %exitcond.i, label %for.i, label %exit78 79exit:80 ret void81}82 83; CHECK-LABEL: base_pointer_is_const_expr84; CHECK-LABEL: Valid Region for Scop: for.i => exit85 86@A = external global float87 88define void @base_pointer_is_global(i64 %n) {89entry:90 br label %for.i91 92for.i:93 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]94 br label %S195 96S1:97 %conv = sitofp i64 %indvar.i to float98 %arrayidx5 = getelementptr float, ptr @A, i64 %indvar.i99 store float %conv, ptr %arrayidx5, align 4100 br label %for.i.inc101 102for.i.inc:103 %indvar.i.next = add i64 %indvar.i, 1104 %exitcond.i = icmp ne i64 %indvar.i.next, %n105 br i1 %exitcond.i, label %for.i, label %exit106 107exit:108 ret void109}110 111; CHECK-LABEL: base_pointer_is_global112; CHECK: Valid Region for Scop: for.i => exit113 114declare ptr @foo()115 116define void @base_pointer_is_inst_outside(i64 %n) {117entry:118 %A = call ptr @foo()119 br label %for.i120 121for.i:122 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]123 br label %S1124 125S1:126 %conv = sitofp i64 %indvar.i to float127 %arrayidx5 = getelementptr float, ptr %A, i64 %indvar.i128 store float %conv, ptr %arrayidx5, align 4129 br label %for.i.inc130 131for.i.inc:132 %indvar.i.next = add i64 %indvar.i, 1133 %exitcond.i = icmp ne i64 %indvar.i.next, %n134 br i1 %exitcond.i, label %for.i, label %exit135 136exit:137 ret void138}139 140; CHECK-LABEL: base_pointer_is_inst_outside141; CHECK: Valid Region for Scop: for.i => exit142 143declare ptr @getNextBasePtr(ptr) readnone nounwind144 145define void @base_pointer_is_phi_node(i64 %n, ptr %A) {146entry:147 br label %for.i148 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 but153; for which the surrounding SCoP is normally still valid we use a function154; without any side effects.155 %ptr.next = call ptr @getNextBasePtr(ptr %ptr)156 br label %S1157 158S1:159 %conv = sitofp i64 %indvar.i to float160 %arrayidx5 = getelementptr float, ptr %ptr, i64 %indvar.i161 store float %conv, ptr %arrayidx5, align 4162 br label %for.i.inc163 164for.i.inc:165 %indvar.i.next = add i64 %indvar.i, 1166 %exitcond.i = icmp ne i64 %indvar.i.next, %n167 br i1 %exitcond.i, label %for.i, label %exit168 169exit:170 ret void171}172 173; CHECK-LABEL: base_pointer_is_phi_node174; CHECK-NOT: Valid Region for Scop175 176define void @base_pointer_is_inst_inside_invariant_1(i64 %n, ptr %A) {177entry:178 br label %for.i179 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 not183; considered a valid base pointer because it can return a pointer that aliases184; with something else (e.g. %A or a global) or return a different pointer at185; every call (e.g. malloc)186 %ptr = call ptr @getNextBasePtr(ptr %A)187 br label %S1188 189S1:190 %conv = sitofp i64 %indvar.i to float191 %arrayidx5 = getelementptr float, ptr %ptr, i64 %indvar.i192 store float %conv, ptr %arrayidx5, align 4193 br label %for.i.inc194 195for.i.inc:196 %indvar.i.next = add i64 %indvar.i, 1197 %exitcond.i = icmp ne i64 %indvar.i.next, %n198 br i1 %exitcond.i, label %for.i, label %exit199 200exit:201 ret void202}203 204; CHECK-LABEL: base_pointer_is_inst_inside_invariant_1205; CHECK-NOT: Valid Region for Scop206 207declare ptr @getNextBasePtr2(ptr) readnone nounwind208 209define void @base_pointer_is_inst_inside_invariant_2(i64 %n, ptr %A) {210entry:211 br label %for.i212 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 %S1218 219S1:220 %conv = sitofp i64 %indvar.i to float221 %arrayidx5 = getelementptr float, ptr %ptr2, i64 %indvar.i222 store float %conv, ptr %arrayidx5, align 4223 br label %for.i.inc224 225for.i.inc:226 %indvar.i.next = add i64 %indvar.i, 1227 %exitcond.i = icmp ne i64 %indvar.i.next, %n228 br i1 %exitcond.i, label %for.i, label %exit229 230exit:231 ret void232}233 234; CHECK-LABEL: base_pointer_is_inst_inside_invariant_2235; CHECK-NOT: Valid Region for Scop236 237declare ptr @getNextBasePtr3(ptr, i64) readnone nounwind238 239define void @base_pointer_is_inst_inside_variant(i64 %n, ptr %A) {240entry:241 br label %for.i242 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 %S1248 249S1:250 %conv = sitofp i64 %indvar.i to float251 %arrayidx5 = getelementptr float, ptr %ptr2, i64 %indvar.i252 store float %conv, ptr %arrayidx5, align 4253 br label %for.i.inc254 255for.i.inc:256 %indvar.i.next = add i64 %indvar.i, 1257 %exitcond.i = icmp ne i64 %indvar.i.next, %n258 br i1 %exitcond.i, label %for.i, label %exit259 260exit:261 ret void262}263 264; CHECK: base_pointer_is_inst_inside_variant265; CHECK-NOT: Valid Region for Scop266 267define void @base_pointer_is_ptr2ptr(ptr noalias %A, i64 %n) {268entry:269 br label %for.i270 271for.i:272 %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]273 %arrayidx = getelementptr ptr, ptr %A, i64 %indvar.i274 br label %for.j275 276for.j:277 %indvar.j = phi i64 [ 0, %for.i ], [ %indvar.j.next, %for.j ]278 %conv = sitofp i64 %indvar.i to float279 %basepointer = load ptr, ptr %arrayidx, align 8280 %arrayidx5 = getelementptr float, ptr %basepointer, i64 %indvar.j281 store float %conv, ptr %arrayidx5, align 4282 %indvar.j.next = add i64 %indvar.j, 1283 %exitcond.j = icmp ne i64 %indvar.j.next, %n284 br i1 %exitcond.j, label %for.j, label %for.i.inc285 286for.i.inc:287 %indvar.i.next = add i64 %indvar.i, 1288 %exitcond.i = icmp ne i64 %indvar.i.next, %n289 br i1 %exitcond.i, label %for.i, label %exit290 291exit:292 ret void293}294 295; CHECK: base_pointer_is_ptr2ptr296; CHECK: Valid Region for Scop: for.j => for.i.inc297