[polly] r251945 - [FIX] Carefully rewrite parameters wrt. invariant equivalence classes

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 3 08:47:59 PST 2015


Author: jdoerfert
Date: Tue Nov  3 10:47:58 2015
New Revision: 251945

URL: http://llvm.org/viewvc/llvm-project?rev=251945&view=rev
Log:
[FIX] Carefully rewrite parameters wrt. invariant equivalence classes

  ScalarEvolution doesn't allow the operands of an AddRec to be variant in the
  loop of the AddRec. When we rewrite parameter SCEVs it might seem like the
  new SCEV violates this property and ScalarEvolution will trigger an
  assertion. To avoid this we move the start part out of an AddRec when we
  rewrite it, thus avoid the operands to be possibly variant completely.

Added:
    polly/trunk/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll
Modified:
    polly/trunk/lib/Analysis/ScopInfo.cpp

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=251945&r1=251944&r2=251945&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Tue Nov  3 10:47:58 2015
@@ -1421,8 +1421,89 @@ void Scop::setContext(__isl_take isl_set
   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) {

Added: polly/trunk/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll?rev=251945&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll (added)
+++ polly/trunk/test/ScopInfo/invalid_add_rec_after_invariant_load_remapping.ll Tue Nov  3 10:47:58 2015
@@ -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
+}




More information about the llvm-commits mailing list