Index: include/llvm/Analysis/ScalarEvolution.h =================================================================== --- include/llvm/Analysis/ScalarEvolution.h +++ include/llvm/Analysis/ScalarEvolution.h @@ -587,7 +587,9 @@ const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getUMaxExpr(SmallVectorImpl &Operands); const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getSMinExpr(SmallVectorImpl &Operands); const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMinExpr(SmallVectorImpl &Operands); const SCEV *getUnknown(Value *V); const SCEV *getCouldNotCompute(); Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -3552,12 +3552,27 @@ return getNotSCEV(getSMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS))); } +const SCEV *ScalarEvolution::getSMinExpr(SmallVectorImpl &Ops) { + // ~smax(~x, ~y, ~z) == smin(x, y, z). + SmallVector NotOps; + for (auto *S : Ops) + NotOps.push_back(getNotSCEV(S)); + return getNotSCEV(getSMaxExpr(NotOps)); +} + const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, const SCEV *RHS) { - // ~umax(~x, ~y) == umin(x, y) + // ~umax(~x, ~y, ~z) == umin(x, y, z). return getNotSCEV(getUMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS))); } +const SCEV *ScalarEvolution::getUMinExpr(SmallVectorImpl &Ops) { + SmallVector NotOps; + for (auto *S : Ops) + NotOps.push_back(getNotSCEV(S)); + return getNotSCEV(getUMaxExpr(NotOps)); +} + const SCEV *ScalarEvolution::getSizeOfExpr(Type *IntTy, Type *AllocTy) { // We can bypass creating a target-independent // constant expression and then folding it back into a ConstantInt. @@ -6666,7 +6681,6 @@ if (!isComplete() || ExitNotTaken.empty()) return SE->getCouldNotCompute(); - const SCEV *BECount = nullptr; const BasicBlock *Latch = L->getLoopLatch(); // All exiting blocks we have collected must dominate the only backedge. if (!Latch) @@ -6674,16 +6688,20 @@ // All exiting blocks we have gathered dominate loop's latch, so exact trip // count is simply a minimum out of all these calculated exit counts. + SmallVector Ops; + Type *MaxType = nullptr; for (auto &ENT : ExitNotTaken) { - assert(ENT.ExactNotTaken != SE->getCouldNotCompute() && "Bad exit SCEV!"); + const SCEV *BECount = ENT.ExactNotTaken; + assert(BECount != SE->getCouldNotCompute() && "Bad exit SCEV!"); assert(SE->DT.dominates(ENT.ExitingBlock, Latch) && "We should only have known counts for exiting blocks that dominate " "latch!"); - if (!BECount) - BECount = ENT.ExactNotTaken; - else if (BECount != ENT.ExactNotTaken) - BECount = SE->getUMinFromMismatchedTypes(BECount, ENT.ExactNotTaken); + if (Ops.empty()) + MaxType = BECount->getType(); + else + MaxType = SE->getWiderType(MaxType, BECount->getType()); + Ops.push_back(BECount); if (Preds && !ENT.hasAlwaysTruePredicate()) Preds->add(ENT.Predicate.get()); @@ -6692,8 +6710,11 @@ "Predicate should be always true!"); } - assert(BECount && "Invalid not taken count for loop exit"); - return BECount; + assert(!Ops.empty() && "Loop without exits"); + for (unsigned i = 0; i < Ops.size(); i++) + Ops[i] = SE->getNoopOrZeroExtend(Ops[i], MaxType); + + return SE->getUMinExpr(Ops); } /// Get the exact not taken count for this loop exit.