Index: include/llvm/Analysis/ScalarEvolutionExpander.h =================================================================== --- include/llvm/Analysis/ScalarEvolutionExpander.h +++ include/llvm/Analysis/ScalarEvolutionExpander.h @@ -77,9 +77,13 @@ /// Phis that complete an IV chain. Reuse DenseSet> ChainedPhis; - /// When true, expressions are expanded in "canonical" form. In particular, - /// addrecs are expanded as arithmetic based on a canonical induction - /// variable. When false, expression are expanded in a more literal form. + /// When true, SCEVExpander tries to expand expressions in "canonical" form. + /// When false, expressions are expanded in a more literal form. + /// + /// In "canonical" form addrecs are expanded as arithmetic based on a + /// canonical induction variable. Note that CanonicalMode doesn't guarantee + /// that all expressions are expanded in "canonical" form. For some + /// expressions literal mode can be preferred. bool CanonicalMode; /// When invoked from LSR, the expander is in "strength reduction" mode. The Index: include/llvm/Analysis/ScalarEvolutionExpressions.h =================================================================== --- include/llvm/Analysis/ScalarEvolutionExpressions.h +++ include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -343,6 +343,10 @@ /// Return the value of this chain of recurrences at the specified /// iteration number. + /// + /// Note that SCEVCouldNotCompute is returned if evaluation attempt failed. + /// For example, if precision of \p It is less than required to perform an + /// evaluation instance of SCEVCouldNotCompute is returned. const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const; /// Return the number of iterations of this loop that produce Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -1204,6 +1204,13 @@ IntegerType *CalculationTy = IntegerType::get(SE.getContext(), CalculationBits); const SCEV *Dividend = SE.getTruncateOrZeroExtend(It, CalculationTy); + + // Zero extension indicates insufficient precision of incoming "It". + // In this case result of calculations may be incorrect. Go ahead and return + // SCEVCouldNotCompute. + if (isa(Dividend)) + return SE.getCouldNotCompute(); + for (unsigned i = 1; i != K; ++i) { const SCEV *S = SE.getMinusSCEV(It, SE.getConstant(It->getType(), i)); Dividend = SE.getMulExpr(Dividend, @@ -11660,7 +11667,7 @@ return (L && !L->contains(I)) ? LoopInvariant : LoopVariant; return LoopInvariant; case scCouldNotCompute: - llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return LoopVariant; } llvm_unreachable("Unknown SCEV kind!"); } Index: lib/Analysis/ScalarEvolutionExpander.cpp =================================================================== --- lib/Analysis/ScalarEvolutionExpander.cpp +++ lib/Analysis/ScalarEvolutionExpander.cpp @@ -1486,7 +1486,18 @@ } Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { - if (!CanonicalMode) return expandAddRecExprLiterally(S); + // In canonical mode we compute the addrec as an expression of a canonical IV + // using evaluateAtIteration and expand the resulting SCEV expression. This + // way we avoid introducing new IVs to carry on the comutation of the addrec + // throughout the loop. + // + // For nested addrecs evaluateAtIteration might need a canonical IV of a + // type wider than the addrec itself. Emitting a canonical IV of the + // proper type might produce non-legal types, for example expanding an i64 + // {0,+,2,+,1} addrec would need an i65 canonical IV. To avoid this just fall + // back to non-canonical mode for nested addrecs. + if (!CanonicalMode || (S->getNumOperands() > 2)) + return expandAddRecExprLiterally(S); Type *Ty = SE.getEffectiveSCEVType(S->getType()); const Loop *L = S->getLoop(); Index: test/Transforms/IndVarSimplify/exit_value_tests.ll =================================================================== --- test/Transforms/IndVarSimplify/exit_value_tests.ll +++ test/Transforms/IndVarSimplify/exit_value_tests.ll @@ -45,34 +45,6 @@ ret i32 %Y } -define i32 @NSquareOver2(i32 %N) { -;