Index: include/llvm/Analysis/ScalarEvolutionExpressions.h =================================================================== --- include/llvm/Analysis/ScalarEvolutionExpressions.h +++ include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -317,6 +317,10 @@ return getNumOperands() == 2; } + /// isAffineRecursive - Return true if all SCEVAddRexExprs contained in + /// this expression are affine. + bool isAffineRecursive() const; + /// isQuadratic - Return true if this represents an expression /// A + B*x + C*x^2 where A, B and C are loop invariant values. /// This corresponds to an addrec of the form {L,+,M,+,N} Index: lib/Analysis/DependenceAnalysis.cpp =================================================================== --- lib/Analysis/DependenceAnalysis.cpp +++ lib/Analysis/DependenceAnalysis.cpp @@ -3278,7 +3278,8 @@ const SCEVAddRecExpr *SrcAR = dyn_cast(SrcSCEV); const SCEVAddRecExpr *DstAR = dyn_cast(DstSCEV); - if (!SrcAR || !DstAR || !SrcAR->isAffine() || !DstAR->isAffine()) + if (!SrcAR || !DstAR || !SrcAR->isAffineRecursive() || + !DstAR->isAffineRecursive()) return false; // First step: collect parametric terms in both array references. Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -1070,6 +1070,29 @@ return Result; } +/// isAffineRecursive - Return true if all SCEVAddRexExprs contained in this +/// expression are affine. +bool SCEVAddRecExpr::isAffineRecursive() const { + + // Local struct for the SCEVTraversal. Traverse this expression until a + // SCEVAddRecExpr is found that is not affine. + struct IsAffineRecursive { + bool IsAffine; + IsAffineRecursive() : IsAffine(true) {} + bool follow(const SCEV *S) { + if (auto *AddRec = dyn_cast(S)) + IsAffine = AddRec->isAffine(); + return true; + } + bool isDone() { return !IsAffine; } + }; + + IsAffineRecursive Check; + SCEVTraversal ST(Check); + ST.visitAll(this); + return Check.IsAffine; +} + //===----------------------------------------------------------------------===// // SCEV Expression folder implementations //===----------------------------------------------------------------------===// Index: test/Analysis/DependenceAnalysis/AffineSCEVAddRecExpr.ll =================================================================== --- /dev/null +++ test/Analysis/DependenceAnalysis/AffineSCEVAddRecExpr.ll @@ -0,0 +1,36 @@ +; REQUIRES: asserts +; RUN: opt < %s -analyze -basicaa -da-delinearize -da +; +; This is a reduced test case from a benchmark in spec2006. We check that this +; code does not abort. +; +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" +target triple = "thumbv7--linux-gnueabi" + +define void @f(i32** %a, i32 %n) align 2 { +for.preheader: + %t.0 = ashr exact i32 %n, 3 + br label %for.body.1 + +for.body.1: + %i.1 = phi i32 [ %t.5, %for.inc ], [ 0, %for.preheader ] + %i.2 = phi i32 [ %i.5, %for.inc ], [ %t.0, %for.preheader ] + br i1 undef, label %for.inc, label %for.body.2 + +for.body.2: + %i.3 = phi i32 [ %t.1, %for.body.2 ], [ %i.1, %for.body.1 ] + %t.1 = add i32 %i.3, 1 + %t.2 = load i32*, i32** %a, align 4 + %t.3 = getelementptr inbounds i32, i32* %t.2, i32 %i.3 + %t.4 = load i32, i32* %t.3, align 4 + br i1 undef, label %for.inc, label %for.body.2 + +for.inc: + %i.4 = phi i32 [ %i.2, %for.body.1 ], [ %i.2, %for.body.2 ] + %t.5 = add i32 %i.1, %i.4 + %i.5 = add i32 %i.2, -1 + br i1 undef, label %for.exit, label %for.body.1 + +for.exit: + ret void +}