+/// HowManyLessThans - Return the number of times a backedge containing the
+/// specified less-than comparison will execute. If not computable, return
+/// UnknownValue.
+SCEVHandle ScalarEvolutionsImpl::
+HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L, bool isSigned) {
+ // Only handle: "ADDREC < LoopInvariant".
+ if (!RHS->isLoopInvariant(L)) return UnknownValue;
+
+ SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(LHS);
+ if (!AddRec || AddRec->getLoop() != L)
+ return UnknownValue;
+
+ if (AddRec->isAffine()) {
+ // FORNOW: We only support unit strides.
+ SCEVHandle One = SCEVUnknown::getIntegerSCEV(1, RHS->getType());
+ if (AddRec->getOperand(1) != One)
+ return UnknownValue;
+
+ // The number of iterations for "[n,+,1] < m", is m-n. However, we don't
+ // know that m is >= n on input to the loop. If it is, the condition return
+ // true zero times. What we really should return, for full generality, is
+ // SMAX(0, m-n). Since we cannot check this, we will instead check for a
+ // canonical loop form: most do-loops will have a check that dominates the
+ // loop, that only enters the loop if [n-1]<m. If we can find this check,
+ // we know that the SMAX will evaluate to m-n, because we know that m >= n.
+
+ // Search for the check.
+ BasicBlock *Preheader = L->getLoopPreheader();
+ BasicBlock *PreheaderDest = L->getHeader();
+ if (Preheader == 0) return UnknownValue;
+
+ BranchInst *LoopEntryPredicate =
+ dyn_cast<BranchInst>(Preheader->getTerminator());
+ if (!LoopEntryPredicate) return UnknownValue;
+
+ // This might be a critical edge broken out. If the loop preheader ends in
+ // an unconditional branch to the loop, check to see if the preheader has a
+ // single predecessor, and if so, look for its terminator.
+ while (LoopEntryPredicate->isUnconditional()) {
+ PreheaderDest = Preheader;
+ Preheader = Preheader->getSinglePredecessor();
+ if (!Preheader) return UnknownValue; // Multiple preds.
+
+ LoopEntryPredicate =
+ dyn_cast<BranchInst>(Preheader->getTerminator());
+ if (!LoopEntryPredicate) return UnknownValue;
+ }
+
+ // Now that we found a conditional branch that dominates the loop, check to
+ // see if it is the comparison we are looking for.
+ if (ICmpInst *ICI = dyn_cast<ICmpInst>(LoopEntryPredicate->getCondition())){
+ Value *PreCondLHS = ICI->getOperand(0);
+ Value *PreCondRHS = ICI->getOperand(1);
+ ICmpInst::Predicate Cond;
+ if (LoopEntryPredicate->getSuccessor(0) == PreheaderDest)
+ Cond = ICI->getPredicate();
+ else
+ Cond = ICI->getInversePredicate();
+
+ switch (Cond) {
+ case ICmpInst::ICMP_UGT:
+ if (isSigned) return UnknownValue;
+ std::swap(PreCondLHS, PreCondRHS);
+ Cond = ICmpInst::ICMP_ULT;
+ break;
+ case ICmpInst::ICMP_SGT:
+ if (!isSigned) return UnknownValue;
+ std::swap(PreCondLHS, PreCondRHS);
+ Cond = ICmpInst::ICMP_SLT;
+ break;
+ case ICmpInst::ICMP_ULT:
+ if (isSigned) return UnknownValue;
+ break;
+ case ICmpInst::ICMP_SLT:
+ if (!isSigned) return UnknownValue;
+ break;
+ default:
+ return UnknownValue;
+ }
+
+ if (PreCondLHS->getType()->isInteger()) {
+ if (RHS != getSCEV(PreCondRHS))
+ return UnknownValue; // Not a comparison against 'm'.
+
+ if (SCEV::getMinusSCEV(AddRec->getOperand(0), One)
+ != getSCEV(PreCondLHS))
+ return UnknownValue; // Not a comparison against 'n-1'.
+ }
+ else return UnknownValue;
+
+ // cerr << "Computed Loop Trip Count as: "
+ // << // *SCEV::getMinusSCEV(RHS, AddRec->getOperand(0)) << "\n";
+ return SCEV::getMinusSCEV(RHS, AddRec->getOperand(0));
+ }
+ else
+ return UnknownValue;
+ }
+
+ return UnknownValue;
+}
+