diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 590ebe4b30f..8073b270e1c 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -7192,7 +7192,7 @@ findGCD(ScalarEvolution &SE, SmallVectorImpl &Terms) { return GCD; } -static void findArrayDimensionsRec(ScalarEvolution &SE, +static bool findArrayDimensionsRec(ScalarEvolution &SE, SmallVectorImpl &Terms, SmallVectorImpl &Sizes) { // The GCD of all Terms is the dimension of the innermost dimension. @@ -7210,14 +7210,18 @@ static void findArrayDimensionsRec(ScalarEvolution &SE, } Sizes.push_back(GCD); - return; + return true; } for (const SCEV *&Term : Terms) { // Normalize the terms before the next call to findArrayDimensionsRec. const SCEV *Q, *R; SCEVDivision::divide(SE, Term, GCD, &Q, &R); - assert(R->isZero() && "GCD does not evenly divide one of the terms"); + + // Bail out when GCD does not evenly divide one of the terms. + if (!R->isZero()) + return false; + Term = Q; } @@ -7228,8 +7232,11 @@ static void findArrayDimensionsRec(ScalarEvolution &SE, Terms.end()); if (Terms.size() > 0) - findArrayDimensionsRec(SE, Terms, Sizes); + if (!findArrayDimensionsRec(SE, Terms, Sizes)) + return false; + Sizes.push_back(GCD); + return true; } namespace { @@ -7315,7 +7322,12 @@ void ScalarEvolution::findArrayDimensions( }); ScalarEvolution &SE = *const_cast(this); - findArrayDimensionsRec(SE, Terms, Sizes); + bool Res = findArrayDimensionsRec(SE, Terms, Sizes); + + if (!Res) { + Sizes.clear(); + return; + } DEBUG({ dbgs() << "Sizes:\n"; @@ -7329,11 +7341,12 @@ void ScalarEvolution::findArrayDimensions( const SCEV *SCEVAddRecExpr::computeAccessFunctions( ScalarEvolution &SE, SmallVectorImpl &Subscripts, SmallVectorImpl &Sizes) const { - // Early exit in case this SCEV is not an affine multivariate function. - const SCEV *Zero = SE.getConstant(this->getType(), 0); - if (!this->isAffine()) - return Zero; + // Early exit in case this SCEV is not an affine multivariate function. + if (Sizes.empty() || !this->isAffine()) + return NULL; + + const SCEV *Zero = SE.getConstant(this->getType(), 0); const SCEV *Res = this, *Remainder = Zero; int Last = Sizes.size() - 1; for (int i = Last; i >= 0; i--) { @@ -7432,12 +7445,21 @@ SCEVAddRecExpr::delinearize(ScalarEvolution &SE, SmallVector Terms; collectParametricTerms(SE, Terms); + if (Terms.empty()) + return NULL; + // Second step: find subscript sizes. SE.findArrayDimensions(Terms, Sizes); + if (Sizes.empty()) + return NULL; + // Third step: compute the access functions for each subscript. const SCEV *Remainder = computeAccessFunctions(SE, Subscripts, Sizes); + if (!Remainder || Subscripts.empty()) + return NULL; + DEBUG({ dbgs() << "succeeded to delinearize " << *this << "\n"; dbgs() << "ArrayDecl[UnknownSize]"; diff --git a/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll b/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll new file mode 100644 index 00000000000..6a98507340a --- /dev/null +++ b/test/Analysis/Delinearization/multidim_two_accesses_different_delinearization.ll @@ -0,0 +1,43 @@ +; RUN: opt -basicaa -da -analyze -da-delinearize < %s +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-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Derived from the following code: +; +; void foo(long n, long m, double *A) { +; for (long i = 0; i < n; i++) +; for (long j = 0; j < m; j++) +; *(A + i * n + j) = 1.0; +; *(A + j * m + i) = 2.0; +; } + +define void @foo(i64 %n, i64 %m, double* %A) { +entry: + br label %for.i + +for.i: + %i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.inc ] + br label %for.j + +for.j: + %j = phi i64 [ 0, %for.i ], [ %j.inc, %for.j ] + %tmp = mul nsw i64 %i, %m + %vlaarrayidx.sum = add i64 %j, %tmp + %arrayidx = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum + store double 1.0, double* %arrayidx + %tmp1 = mul nsw i64 %j, %n + %vlaarrayidx.sum1 = add i64 %i, %tmp1 + %arrayidx1 = getelementptr inbounds double* %A, i64 %vlaarrayidx.sum1 + store double 1.0, double* %arrayidx1 + %j.inc = add nsw i64 %j, 1 + %j.exitcond = icmp eq i64 %j.inc, %m + br i1 %j.exitcond, label %for.i.inc, label %for.j + +for.i.inc: + %i.inc = add nsw i64 %i, 1 + %i.exitcond = icmp eq i64 %i.inc, %n + br i1 %i.exitcond, label %end, label %for.i + +end: + ret void +}