summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--polly/lib/Analysis/ScopInfo.cpp83
-rw-r--r--polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll57
2 files changed, 139 insertions, 1 deletions
diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index 496aadfe72d..3cb53299ed7 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -1421,8 +1421,89 @@ void Scop::setContext(__isl_take isl_set *NewContext) {
Context = NewContext;
}
+/// @brief Remap parameter values but keep AddRecs valid wrt. invariant loads.
+struct SCEVSensitiveParameterRewriter
+ : public SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *> {
+ ValueToValueMap &VMap;
+ ScalarEvolution &SE;
+
+public:
+ SCEVSensitiveParameterRewriter(ValueToValueMap &VMap, ScalarEvolution &SE)
+ : VMap(VMap), SE(SE) {}
+
+ static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE,
+ ValueToValueMap &VMap) {
+ SCEVSensitiveParameterRewriter SSPR(VMap, SE);
+ return SSPR.visit(E);
+ }
+
+ const SCEV *visit(const SCEV *E) {
+ return SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *>::visit(E);
+ }
+
+ const SCEV *visitConstant(const SCEVConstant *E) { return E; }
+
+ const SCEV *visitTruncateExpr(const SCEVTruncateExpr *E) {
+ return SE.getTruncateExpr(visit(E->getOperand()), E->getType());
+ }
+
+ const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *E) {
+ return SE.getZeroExtendExpr(visit(E->getOperand()), E->getType());
+ }
+
+ const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *E) {
+ return SE.getSignExtendExpr(visit(E->getOperand()), E->getType());
+ }
+
+ const SCEV *visitAddExpr(const SCEVAddExpr *E) {
+ SmallVector<const SCEV *, 4> Operands;
+ for (int i = 0, e = E->getNumOperands(); i < e; ++i)
+ Operands.push_back(visit(E->getOperand(i)));
+ return SE.getAddExpr(Operands);
+ }
+
+ const SCEV *visitMulExpr(const SCEVMulExpr *E) {
+ SmallVector<const SCEV *, 4> Operands;
+ for (int i = 0, e = E->getNumOperands(); i < e; ++i)
+ Operands.push_back(visit(E->getOperand(i)));
+ return SE.getMulExpr(Operands);
+ }
+
+ const SCEV *visitSMaxExpr(const SCEVSMaxExpr *E) {
+ SmallVector<const SCEV *, 4> Operands;
+ for (int i = 0, e = E->getNumOperands(); i < e; ++i)
+ Operands.push_back(visit(E->getOperand(i)));
+ return SE.getSMaxExpr(Operands);
+ }
+
+ const SCEV *visitUMaxExpr(const SCEVUMaxExpr *E) {
+ SmallVector<const SCEV *, 4> Operands;
+ for (int i = 0, e = E->getNumOperands(); i < e; ++i)
+ Operands.push_back(visit(E->getOperand(i)));
+ return SE.getUMaxExpr(Operands);
+ }
+
+ const SCEV *visitUDivExpr(const SCEVUDivExpr *E) {
+ return SE.getUDivExpr(visit(E->getLHS()), visit(E->getRHS()));
+ }
+
+ const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) {
+ auto *Start = visit(E->getStart());
+ auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0),
+ visit(E->getStepRecurrence(SE)),
+ E->getLoop(), SCEV::FlagAnyWrap);
+ return SE.getAddExpr(Start, AddRec);
+ }
+
+ const SCEV *visitUnknown(const SCEVUnknown *E) {
+ if (auto *NewValue = VMap.lookup(E->getValue()))
+ return SE.getUnknown(NewValue);
+ return E;
+ }
+};
+
const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *S) {
- return SCEVParameterRewriter::rewrite(S, *SE, InvEquivClassVMap);
+ return SCEVSensitiveParameterRewriter::rewrite(S, *SE, InvEquivClassVMap);
}
void Scop::addParams(std::vector<const SCEV *> NewParameters) {
diff --git a/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll b/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll
new file mode 100644
index 00000000000..df909d0c6cf
--- /dev/null
+++ b/polly/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll
@@ -0,0 +1,57 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s
+;
+; This crased at some point as we place %1 and %4 in the same equivalence class
+; for invariant loads and when we remap SCEVs to use %4 instead of %1 AddRec SCEVs
+; for the for.body.10 loop caused a crash as their operands were not invariant
+; in the loop. While we know they are, ScalarEvolution does not. However, we can simply
+; rewrite the AddRecs to hoist everything from the "start" out of the AddRec.
+;
+; Check we do not crash.
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.codebook.48.118.748.1882.2972 = type { i64, i64, i64, %struct.static_codebook.19.89.719.1853.2971*, float*, i32*, i32*, i8*, i32*, i32, i32 }
+%struct.static_codebook.19.89.719.1853.2971 = type { i64, i64, i64*, i32, i64, i64, i32, i32, i64*, %struct.encode_aux_nearestmatch.16.86.716.1850.2968*, %struct.encode_aux_threshmatch.17.87.717.1851.2969*, %struct.encode_aux_pigeonhole.18.88.718.1852.2970*, i32 }
+%struct.encode_aux_nearestmatch.16.86.716.1850.2968 = type { i64*, i64*, i64*, i64*, i64, i64 }
+%struct.encode_aux_threshmatch.17.87.717.1851.2969 = type { float*, i64*, i32, i32 }
+%struct.encode_aux_pigeonhole.18.88.718.1852.2970 = type { float, float, i32, i32, i64*, i64, i64*, i64*, i64* }
+
+; Function Attrs: inlinehint nounwind uwtable
+declare i64 @decode_packed_entry_number() #0
+
+; Function Attrs: nounwind uwtable
+define void @vorbis_book_decodev_set(%struct.codebook.48.118.748.1882.2972* %book) #1 {
+entry:
+ br i1 undef, label %for.body, label %return
+
+for.cond.loopexit: ; preds = %for.body.10, %if.end
+ br i1 undef, label %for.body, label %return
+
+for.body: ; preds = %for.cond.loopexit, %entry
+ %call = tail call i64 @decode_packed_entry_number()
+ br i1 undef, label %return, label %if.end
+
+if.end: ; preds = %for.body
+ %valuelist = getelementptr inbounds %struct.codebook.48.118.748.1882.2972, %struct.codebook.48.118.748.1882.2972* %book, i64 0, i32 4
+ %0 = load float*, float** %valuelist, align 8
+ %sext = shl i64 %call, 32
+ %conv4 = ashr exact i64 %sext, 32
+ %dim = getelementptr inbounds %struct.codebook.48.118.748.1882.2972, %struct.codebook.48.118.748.1882.2972* %book, i64 0, i32 0
+ %1 = load i64, i64* %dim, align 8
+ %mul = mul nsw i64 %1, %conv4
+ %add.ptr = getelementptr inbounds float, float* %0, i64 %mul
+ %cmp8.7 = icmp sgt i64 %1, 0
+ br i1 %cmp8.7, label %for.body.10, label %for.cond.loopexit
+
+for.body.10: ; preds = %for.body.10, %if.end
+ %indvars.iv15 = phi i64 [ %indvars.iv.next16, %for.body.10 ], [ 0, %if.end ]
+ %indvars.iv.next16 = add nuw nsw i64 %indvars.iv15, 1
+ %arrayidx = getelementptr inbounds float, float* %add.ptr, i64 %indvars.iv15
+ %2 = bitcast float* %arrayidx to i32*
+ %3 = load i32, i32* %2, align 4
+ %4 = load i64, i64* %dim, align 8
+ %cmp8 = icmp slt i64 %indvars.iv.next16, %4
+ br i1 %cmp8, label %for.body.10, label %for.cond.loopexit
+
+return: ; preds = %for.body, %for.cond.loopexit, %entry
+ ret void
+}
OpenPOWER on IntegriCloud