//===- ScalarEvolution.cpp - Scalar Evolution Analysis --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the implementation of the scalar evolution analysis
// engine, which is used primarily to analyze expressions involving induction
// variables in loops.
//
// There are several aspects to this library.  First is the representation of
// scalar expressions, which are represented as subclasses of the SCEV class.
// These classes are used to represent certain types of subexpressions that we
// can handle. We only create one SCEV of a particular shape, so
// pointer-comparisons for equality are legal.
//
// One important aspect of the SCEV objects is that they are never cyclic, even
// if there is a cycle in the dataflow for an expression (ie, a PHI node).  If
// the PHI node is one of the idioms that we can represent (e.g., a polynomial
// recurrence) then we represent it directly as a recurrence node, otherwise we
// represent it as a SCEVUnknown node.
//
// In addition to being able to represent expressions of various types, we also
// have folders that are used to build the *canonical* representation for a
// particular expression.  These folders are capable of using a variety of
// rewrite rules to simplify the expressions.
//
// Once the folders are defined, we can implement the more interesting
// higher-level code, such as the code that recognizes PHI nodes of various
// types, computes the execution count of a loop, etc.
//
// TODO: We should use these routines and value representations to implement
// dependence analysis!
//
//===----------------------------------------------------------------------===//
//
// There are several good references for the techniques used in this analysis.
//
//  Chains of recurrences -- a method to expedite the evaluation
//  of closed-form functions
//  Olaf Bachmann, Paul S. Wang, Eugene V. Zima
//
//  On computational properties of chains of recurrences
//  Eugene V. Zima
//
//  Symbolic Evaluation of Chains of Recurrences for Loop Optimization
//  Robert A. van Engelen
//
//  Efficient Symbolic Analysis for Optimizing Compilers
//  Robert A. van Engelen
//
//  Using the chains of recurrences algebra for data dependence testing and
//  induction variable substitution
//  MS Thesis, Johnie Birch
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Verifier.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <tuple>
#include <utility>
#include <vector>

using namespace llvm;
using namespace PatternMatch;

#define DEBUG_TYPE "scalar-evolution"

STATISTIC(NumExitCountsComputed,
          "Number of loop exits with predictable exit counts");
STATISTIC(NumExitCountsNotComputed,
          "Number of loop exits without predictable exit counts");
STATISTIC(NumBruteForceTripCountsComputed,
          "Number of loops with trip counts computed by force");

#ifdef EXPENSIVE_CHECKS
bool llvm::VerifySCEV = true;
#else
bool llvm::VerifySCEV = false;
#endif

static cl::opt<unsigned>
    MaxBruteForceIterations("scalar-evolution-max-iterations", cl::ReallyHidden,
                            cl::desc("Maximum number of iterations SCEV will "
                                     "symbolically execute a constant "
                                     "derived loop"),
                            cl::init(100));

static cl::opt<bool, true> VerifySCEVOpt(
    "verify-scev", cl::Hidden, cl::location(VerifySCEV),
    cl::desc("Verify ScalarEvolution's backedge taken counts (slow)"));
static cl::opt<bool> VerifySCEVStrict(
    "verify-scev-strict", cl::Hidden,
    cl::desc("Enable stricter verification with -verify-scev is passed"));

static cl::opt<bool> VerifyIR(
    "scev-verify-ir", cl::Hidden,
    cl::desc("Verify IR correctness when making sensitive SCEV queries (slow)"),
    cl::init(false));

static cl::opt<unsigned> MulOpsInlineThreshold(
    "scev-mulops-inline-threshold", cl::Hidden,
    cl::desc("Threshold for inlining multiplication operands into a SCEV"),
    cl::init(32));

static cl::opt<unsigned> AddOpsInlineThreshold(
    "scev-addops-inline-threshold", cl::Hidden,
    cl::desc("Threshold for inlining addition operands into a SCEV"),
    cl::init(500));

static cl::opt<unsigned> MaxSCEVCompareDepth(
    "scalar-evolution-max-scev-compare-depth", cl::Hidden,
    cl::desc("Maximum depth of recursive SCEV complexity comparisons"),
    cl::init(32));

static cl::opt<unsigned> MaxSCEVOperationsImplicationDepth(
    "scalar-evolution-max-scev-operations-implication-depth", cl::Hidden,
    cl::desc("Maximum depth of recursive SCEV operations implication analysis"),
    cl::init(2));

static cl::opt<unsigned> MaxValueCompareDepth(
    "scalar-evolution-max-value-compare-depth", cl::Hidden,
    cl::desc("Maximum depth of recursive value complexity comparisons"),
    cl::init(2));

static cl::opt<unsigned>
    MaxArithDepth("scalar-evolution-max-arith-depth", cl::Hidden,
                  cl::desc("Maximum depth of recursive arithmetics"),
                  cl::init(32));

static cl::opt<unsigned> MaxConstantEvolvingDepth(
    "scalar-evolution-max-constant-evolving-depth", cl::Hidden,
    cl::desc("Maximum depth of recursive constant evolving"), cl::init(32));

static cl::opt<unsigned>
    MaxCastDepth("scalar-evolution-max-cast-depth", cl::Hidden,
                 cl::desc("Maximum depth of recursive SExt/ZExt/Trunc"),
                 cl::init(8));

static cl::opt<unsigned>
    MaxAddRecSize("scalar-evolution-max-add-rec-size", cl::Hidden,
                  cl::desc("Max coefficients in AddRec during evolving"),
                  cl::init(8));

static cl::opt<unsigned>
    HugeExprThreshold("scalar-evolution-huge-expr-threshold", cl::Hidden,
                  cl::desc("Size of the expression which is considered huge"),
                  cl::init(4096));

static cl::opt<unsigned> RangeIterThreshold(
    "scev-range-iter-threshold", cl::Hidden,
    cl::desc("Threshold for switching to iteratively computing SCEV ranges"),
    cl::init(32));

static cl::opt<bool>
ClassifyExpressions("scalar-evolution-classify-expressions",
    cl::Hidden, cl::init(true),
    cl::desc("When printing analysis, include information on every instruction"));

static cl::opt<bool> UseExpensiveRangeSharpening(
    "scalar-evolution-use-expensive-range-sharpening", cl::Hidden,
    cl::init(false),
    cl::desc("Use more powerful methods of sharpening expression ranges. May "
             "be costly in terms of compile time"));

static cl::opt<unsigned> MaxPhiSCCAnalysisSize(
    "scalar-evolution-max-scc-analysis-depth", cl::Hidden,
    cl::desc("Maximum amount of nodes to process while searching SCEVUnknown "
             "Phi strongly connected components"),
    cl::init(8));

static cl::opt<bool>
    EnableFiniteLoopControl("scalar-evolution-finite-loop", cl::Hidden,
                            cl::desc("Handle <= and >= in finite loops"),
                            cl::init(true));

static cl::opt<bool> UseContextForNoWrapFlagInference(
    "scalar-evolution-use-context-for-no-wrap-flag-strenghening", cl::Hidden,
    cl::desc("Infer nuw/nsw flags using context where suitable"),
    cl::init(true));

//===----------------------------------------------------------------------===//
//                           SCEV class definitions
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Implementation of the SCEV class.
//

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void SCEV::dump() const {
  print(dbgs());
  dbgs() << '\n';
}
#endif

void SCEV::print(raw_ostream &OS) const {
  switch (getSCEVType()) {
  case scConstant:
    cast<SCEVConstant>(this)->getValue()->printAsOperand(OS, false);
    return;
  case scVScale:
    OS << "vscale";
    return;
  case scPtrToInt: {
    const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(this);
    const SCEV *Op = PtrToInt->getOperand();
    OS << "(ptrtoint " << *Op->getType() << " " << *Op << " to "
       << *PtrToInt->getType() << ")";
    return;
  }
  case scTruncate: {
    const SCEVTruncateExpr *Trunc = cast<SCEVTruncateExpr>(this);
    const SCEV *Op = Trunc->getOperand();
    OS << "(trunc " << *Op->getType() << " " << *Op << " to "
       << *Trunc->getType() << ")";
    return;
  }
  case scZeroExtend: {
    const SCEVZeroExtendExpr *ZExt = cast<SCEVZeroExtendExpr>(this);
    const SCEV *Op = ZExt->getOperand();
    OS << "(zext " << *Op->getType() << " " << *Op << " to "
       << *ZExt->getType() << ")";
    return;
  }
  case scSignExtend: {
    const SCEVSignExtendExpr *SExt = cast<SCEVSignExtendExpr>(this);
    const SCEV *Op = SExt->getOperand();
    OS << "(sext " << *Op->getType() << " " << *Op << " to "
       << *SExt->getType() << ")";
    return;
  }
  case scAddRecExpr: {
    const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(this);
    OS << "{" << *AR->getOperand(0);
    for (unsigned i = 1, e = AR->getNumOperands(); i != e; ++i)
      OS << ",+," << *AR->getOperand(i);
    OS << "}<";
    if (AR->hasNoUnsignedWrap())
      OS << "nuw><";
    if (AR->hasNoSignedWrap())
      OS << "nsw><";
    if (AR->hasNoSelfWrap() &&
        !AR->getNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)))
      OS << "nw><";
    AR->getLoop()->getHeader()->printAsOperand(OS, /*PrintType=*/false);
    OS << ">";
    return;
  }
  case scAddExpr:
  case scMulExpr:
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scSequentialUMinExpr: {
    const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(this);
    const char *OpStr = nullptr;
    switch (NAry->getSCEVType()) {
    case scAddExpr: OpStr = " + "; break;
    case scMulExpr: OpStr = " * "; break;
    case scUMaxExpr: OpStr = " umax "; break;
    case scSMaxExpr: OpStr = " smax "; break;
    case scUMinExpr:
      OpStr = " umin ";
      break;
    case scSMinExpr:
      OpStr = " smin ";
      break;
    case scSequentialUMinExpr:
      OpStr = " umin_seq ";
      break;
    default:
      llvm_unreachable("There are no other nary expression types.");
    }
    OS << "(";
    ListSeparator LS(OpStr);
    for (const SCEV *Op : NAry->operands())
      OS << LS << *Op;
    OS << ")";
    switch (NAry->getSCEVType()) {
    case scAddExpr:
    case scMulExpr:
      if (NAry->hasNoUnsignedWrap())
        OS << "<nuw>";
      if (NAry->hasNoSignedWrap())
        OS << "<nsw>";
      break;
    default:
      // Nothing to print for other nary expressions.
      break;
    }
    return;
  }
  case scUDivExpr: {
    const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(this);
    OS << "(" << *UDiv->getLHS() << " /u " << *UDiv->getRHS() << ")";
    return;
  }
  case scUnknown:
    cast<SCEVUnknown>(this)->getValue()->printAsOperand(OS, false);
    return;
  case scCouldNotCompute:
    OS << "***COULDNOTCOMPUTE***";
    return;
  }
  llvm_unreachable("Unknown SCEV kind!");
}

Type *SCEV::getType() const {
  switch (getSCEVType()) {
  case scConstant:
    return cast<SCEVConstant>(this)->getType();
  case scVScale:
    return cast<SCEVVScale>(this)->getType();
  case scPtrToInt:
  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
    return cast<SCEVCastExpr>(this)->getType();
  case scAddRecExpr:
    return cast<SCEVAddRecExpr>(this)->getType();
  case scMulExpr:
    return cast<SCEVMulExpr>(this)->getType();
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
    return cast<SCEVMinMaxExpr>(this)->getType();
  case scSequentialUMinExpr:
    return cast<SCEVSequentialMinMaxExpr>(this)->getType();
  case scAddExpr:
    return cast<SCEVAddExpr>(this)->getType();
  case scUDivExpr:
    return cast<SCEVUDivExpr>(this)->getType();
  case scUnknown:
    return cast<SCEVUnknown>(this)->getType();
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

ArrayRef<const SCEV *> SCEV::operands() const {
  switch (getSCEVType()) {
  case scConstant:
  case scVScale:
  case scUnknown:
    return {};
  case scPtrToInt:
  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
    return cast<SCEVCastExpr>(this)->operands();
  case scAddRecExpr:
  case scAddExpr:
  case scMulExpr:
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scSequentialUMinExpr:
    return cast<SCEVNAryExpr>(this)->operands();
  case scUDivExpr:
    return cast<SCEVUDivExpr>(this)->operands();
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

bool SCEV::isZero() const {
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(this))
    return SC->getValue()->isZero();
  return false;
}

bool SCEV::isOne() const {
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(this))
    return SC->getValue()->isOne();
  return false;
}

bool SCEV::isAllOnesValue() const {
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(this))
    return SC->getValue()->isMinusOne();
  return false;
}

bool SCEV::isNonConstantNegative() const {
  const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(this);
  if (!Mul) return false;

  // If there is a constant factor, it will be first.
  const SCEVConstant *SC = dyn_cast<SCEVConstant>(Mul->getOperand(0));
  if (!SC) return false;

  // Return true if the value is negative, this matches things like (-42 * V).
  return SC->getAPInt().isNegative();
}

SCEVCouldNotCompute::SCEVCouldNotCompute() :
  SCEV(FoldingSetNodeIDRef(), scCouldNotCompute, 0) {}

bool SCEVCouldNotCompute::classof(const SCEV *S) {
  return S->getSCEVType() == scCouldNotCompute;
}

const SCEV *ScalarEvolution::getConstant(ConstantInt *V) {
  FoldingSetNodeID ID;
  ID.AddInteger(scConstant);
  ID.AddPointer(V);
  void *IP = nullptr;
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
  SCEV *S = new (SCEVAllocator) SCEVConstant(ID.Intern(SCEVAllocator), V);
  UniqueSCEVs.InsertNode(S, IP);
  return S;
}

const SCEV *ScalarEvolution::getConstant(const APInt &Val) {
  return getConstant(ConstantInt::get(getContext(), Val));
}

const SCEV *
ScalarEvolution::getConstant(Type *Ty, uint64_t V, bool isSigned) {
  IntegerType *ITy = cast<IntegerType>(getEffectiveSCEVType(Ty));
  return getConstant(ConstantInt::get(ITy, V, isSigned));
}

const SCEV *ScalarEvolution::getVScale(Type *Ty) {
  FoldingSetNodeID ID;
  ID.AddInteger(scVScale);
  ID.AddPointer(Ty);
  void *IP = nullptr;
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
    return S;
  SCEV *S = new (SCEVAllocator) SCEVVScale(ID.Intern(SCEVAllocator), Ty);
  UniqueSCEVs.InsertNode(S, IP);
  return S;
}

SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
                           const SCEV *op, Type *ty)
    : SCEV(ID, SCEVTy, computeExpressionSize(op)), Op(op), Ty(ty) {}

SCEVPtrToIntExpr::SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op,
                                   Type *ITy)
    : SCEVCastExpr(ID, scPtrToInt, Op, ITy) {
  assert(getOperand()->getType()->isPointerTy() && Ty->isIntegerTy() &&
         "Must be a non-bit-width-changing pointer-to-integer cast!");
}

SCEVIntegralCastExpr::SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID,
                                           SCEVTypes SCEVTy, const SCEV *op,
                                           Type *ty)
    : SCEVCastExpr(ID, SCEVTy, op, ty) {}

SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID, const SCEV *op,
                                   Type *ty)
    : SCEVIntegralCastExpr(ID, scTruncate, op, ty) {
  assert(getOperand()->getType()->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot truncate non-integer value!");
}

SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
                                       const SCEV *op, Type *ty)
    : SCEVIntegralCastExpr(ID, scZeroExtend, op, ty) {
  assert(getOperand()->getType()->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot zero extend non-integer value!");
}

SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
                                       const SCEV *op, Type *ty)
    : SCEVIntegralCastExpr(ID, scSignExtend, op, ty) {
  assert(getOperand()->getType()->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot sign extend non-integer value!");
}

void SCEVUnknown::deleted() {
  // Clear this SCEVUnknown from various maps.
  SE->forgetMemoizedResults(this);

  // Remove this SCEVUnknown from the uniquing map.
  SE->UniqueSCEVs.RemoveNode(this);

  // Release the value.
  setValPtr(nullptr);
}

void SCEVUnknown::allUsesReplacedWith(Value *New) {
  // Clear this SCEVUnknown from various maps.
  SE->forgetMemoizedResults(this);

  // Remove this SCEVUnknown from the uniquing map.
  SE->UniqueSCEVs.RemoveNode(this);

  // Replace the value pointer in case someone is still using this SCEVUnknown.
  setValPtr(New);
}

//===----------------------------------------------------------------------===//
//                               SCEV Utilities
//===----------------------------------------------------------------------===//

/// Compare the two values \p LV and \p RV in terms of their "complexity" where
/// "complexity" is a partial (and somewhat ad-hoc) relation used to order
/// operands in SCEV expressions.  \p EqCache is a set of pairs of values that
/// have been previously deemed to be "equally complex" by this routine.  It is
/// intended to avoid exponential time complexity in cases like:
///
///   %a = f(%x, %y)
///   %b = f(%a, %a)
///   %c = f(%b, %b)
///
///   %d = f(%x, %y)
///   %e = f(%d, %d)
///   %f = f(%e, %e)
///
///   CompareValueComplexity(%f, %c)
///
/// Since we do not continue running this routine on expression trees once we
/// have seen unequal values, there is no need to track them in the cache.
static int
CompareValueComplexity(EquivalenceClasses<const Value *> &EqCacheValue,
                       const LoopInfo *const LI, Value *LV, Value *RV,
                       unsigned Depth) {
  if (Depth > MaxValueCompareDepth || EqCacheValue.isEquivalent(LV, RV))
    return 0;

  // Order pointer values after integer values. This helps SCEVExpander form
  // GEPs.
  bool LIsPointer = LV->getType()->isPointerTy(),
       RIsPointer = RV->getType()->isPointerTy();
  if (LIsPointer != RIsPointer)
    return (int)LIsPointer - (int)RIsPointer;

  // Compare getValueID values.
  unsigned LID = LV->getValueID(), RID = RV->getValueID();
  if (LID != RID)
    return (int)LID - (int)RID;

  // Sort arguments by their position.
  if (const auto *LA = dyn_cast<Argument>(LV)) {
    const auto *RA = cast<Argument>(RV);
    unsigned LArgNo = LA->getArgNo(), RArgNo = RA->getArgNo();
    return (int)LArgNo - (int)RArgNo;
  }

  if (const auto *LGV = dyn_cast<GlobalValue>(LV)) {
    const auto *RGV = cast<GlobalValue>(RV);

    const auto IsGVNameSemantic = [&](const GlobalValue *GV) {
      auto LT = GV->getLinkage();
      return !(GlobalValue::isPrivateLinkage(LT) ||
               GlobalValue::isInternalLinkage(LT));
    };

    // Use the names to distinguish the two values, but only if the
    // names are semantically important.
    if (IsGVNameSemantic(LGV) && IsGVNameSemantic(RGV))
      return LGV->getName().compare(RGV->getName());
  }

  // For instructions, compare their loop depth, and their operand count.  This
  // is pretty loose.
  if (const auto *LInst = dyn_cast<Instruction>(LV)) {
    const auto *RInst = cast<Instruction>(RV);

    // Compare loop depths.
    const BasicBlock *LParent = LInst->getParent(),
                     *RParent = RInst->getParent();
    if (LParent != RParent) {
      unsigned LDepth = LI->getLoopDepth(LParent),
               RDepth = LI->getLoopDepth(RParent);
      if (LDepth != RDepth)
        return (int)LDepth - (int)RDepth;
    }

    // Compare the number of operands.
    unsigned LNumOps = LInst->getNumOperands(),
             RNumOps = RInst->getNumOperands();
    if (LNumOps != RNumOps)
      return (int)LNumOps - (int)RNumOps;

    for (unsigned Idx : seq(0u, LNumOps)) {
      int Result =
          CompareValueComplexity(EqCacheValue, LI, LInst->getOperand(Idx),
                                 RInst->getOperand(Idx), Depth + 1);
      if (Result != 0)
        return Result;
    }
  }

  EqCacheValue.unionSets(LV, RV);
  return 0;
}

// Return negative, zero, or positive, if LHS is less than, equal to, or greater
// than RHS, respectively. A three-way result allows recursive comparisons to be
// more efficient.
// If the max analysis depth was reached, return std::nullopt, assuming we do
// not know if they are equivalent for sure.
static std::optional<int>
CompareSCEVComplexity(EquivalenceClasses<const SCEV *> &EqCacheSCEV,
                      EquivalenceClasses<const Value *> &EqCacheValue,
                      const LoopInfo *const LI, const SCEV *LHS,
                      const SCEV *RHS, DominatorTree &DT, unsigned Depth = 0) {
  // Fast-path: SCEVs are uniqued so we can do a quick equality check.
  if (LHS == RHS)
    return 0;

  // Primarily, sort the SCEVs by their getSCEVType().
  SCEVTypes LType = LHS->getSCEVType(), RType = RHS->getSCEVType();
  if (LType != RType)
    return (int)LType - (int)RType;

  if (EqCacheSCEV.isEquivalent(LHS, RHS))
    return 0;

  if (Depth > MaxSCEVCompareDepth)
    return std::nullopt;

  // Aside from the getSCEVType() ordering, the particular ordering
  // isn't very important except that it's beneficial to be consistent,
  // so that (a + b) and (b + a) don't end up as different expressions.
  switch (LType) {
  case scUnknown: {
    const SCEVUnknown *LU = cast<SCEVUnknown>(LHS);
    const SCEVUnknown *RU = cast<SCEVUnknown>(RHS);

    int X = CompareValueComplexity(EqCacheValue, LI, LU->getValue(),
                                   RU->getValue(), Depth + 1);
    if (X == 0)
      EqCacheSCEV.unionSets(LHS, RHS);
    return X;
  }

  case scConstant: {
    const SCEVConstant *LC = cast<SCEVConstant>(LHS);
    const SCEVConstant *RC = cast<SCEVConstant>(RHS);

    // Compare constant values.
    const APInt &LA = LC->getAPInt();
    const APInt &RA = RC->getAPInt();
    unsigned LBitWidth = LA.getBitWidth(), RBitWidth = RA.getBitWidth();
    if (LBitWidth != RBitWidth)
      return (int)LBitWidth - (int)RBitWidth;
    return LA.ult(RA) ? -1 : 1;
  }

  case scVScale: {
    const auto *LTy = cast<IntegerType>(cast<SCEVVScale>(LHS)->getType());
    const auto *RTy = cast<IntegerType>(cast<SCEVVScale>(RHS)->getType());
    return LTy->getBitWidth() - RTy->getBitWidth();
  }

  case scAddRecExpr: {
    const SCEVAddRecExpr *LA = cast<SCEVAddRecExpr>(LHS);
    const SCEVAddRecExpr *RA = cast<SCEVAddRecExpr>(RHS);

    // There is always a dominance between two recs that are used by one SCEV,
    // so we can safely sort recs by loop header dominance. We require such
    // order in getAddExpr.
    const Loop *LLoop = LA->getLoop(), *RLoop = RA->getLoop();
    if (LLoop != RLoop) {
      const BasicBlock *LHead = LLoop->getHeader(), *RHead = RLoop->getHeader();
      assert(LHead != RHead && "Two loops share the same header?");
      if (DT.dominates(LHead, RHead))
        return 1;
      assert(DT.dominates(RHead, LHead) &&
             "No dominance between recurrences used by one SCEV?");
      return -1;
    }

    [[fallthrough]];
  }

  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
  case scPtrToInt:
  case scAddExpr:
  case scMulExpr:
  case scUDivExpr:
  case scSMaxExpr:
  case scUMaxExpr:
  case scSMinExpr:
  case scUMinExpr:
  case scSequentialUMinExpr: {
    ArrayRef<const SCEV *> LOps = LHS->operands();
    ArrayRef<const SCEV *> ROps = RHS->operands();

    // Lexicographically compare n-ary-like expressions.
    unsigned LNumOps = LOps.size(), RNumOps = ROps.size();
    if (LNumOps != RNumOps)
      return (int)LNumOps - (int)RNumOps;

    for (unsigned i = 0; i != LNumOps; ++i) {
      auto X = CompareSCEVComplexity(EqCacheSCEV, EqCacheValue, LI, LOps[i],
                                     ROps[i], DT, Depth + 1);
      if (X != 0)
        return X;
    }
    EqCacheSCEV.unionSets(LHS, RHS);
    return 0;
  }

  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

/// Given a list of SCEV objects, order them by their complexity, and group
/// objects of the same complexity together by value.  When this routine is
/// finished, we know that any duplicates in the vector are consecutive and that
/// complexity is monotonically increasing.
///
/// Note that we go take special precautions to ensure that we get deterministic
/// results from this routine.  In other words, we don't want the results of
/// this to depend on where the addresses of various SCEV objects happened to
/// land in memory.
static void GroupByComplexity(SmallVectorImpl<const SCEV *> &Ops,
                              LoopInfo *LI, DominatorTree &DT) {
  if (Ops.size() < 2) return;  // Noop

  EquivalenceClasses<const SCEV *> EqCacheSCEV;
  EquivalenceClasses<const Value *> EqCacheValue;

  // Whether LHS has provably less complexity than RHS.
  auto IsLessComplex = [&](const SCEV *LHS, const SCEV *RHS) {
    auto Complexity =
        CompareSCEVComplexity(EqCacheSCEV, EqCacheValue, LI, LHS, RHS, DT);
    return Complexity && *Complexity < 0;
  };
  if (Ops.size() == 2) {
    // This is the common case, which also happens to be trivially simple.
    // Special case it.
    const SCEV *&LHS = Ops[0], *&RHS = Ops[1];
    if (IsLessComplex(RHS, LHS))
      std::swap(LHS, RHS);
    return;
  }

  // Do the rough sort by complexity.
  llvm::stable_sort(Ops, [&](const SCEV *LHS, const SCEV *RHS) {
    return IsLessComplex(LHS, RHS);
  });

  // Now that we are sorted by complexity, group elements of the same
  // complexity.  Note that this is, at worst, N^2, but the vector is likely to
  // be extremely short in practice.  Note that we take this approach because we
  // do not want to depend on the addresses of the objects we are grouping.
  for (unsigned i = 0, e = Ops.size(); i != e-2; ++i) {
    const SCEV *S = Ops[i];
    unsigned Complexity = S->getSCEVType();

    // If there are any objects of the same complexity and same value as this
    // one, group them.
    for (unsigned j = i+1; j != e && Ops[j]->getSCEVType() == Complexity; ++j) {
      if (Ops[j] == S) { // Found a duplicate.
        // Move it to immediately after i'th element.
        std::swap(Ops[i+1], Ops[j]);
        ++i;   // no need to rescan it.
        if (i == e-2) return;  // Done!
      }
    }
  }
}

/// Returns true if \p Ops contains a huge SCEV (the subtree of S contains at
/// least HugeExprThreshold nodes).
static bool hasHugeExpression(ArrayRef<const SCEV *> Ops) {
  return any_of(Ops, [](const SCEV *S) {
    return S->getExpressionSize() >= HugeExprThreshold;
  });
}

//===----------------------------------------------------------------------===//
//                      Simple SCEV method implementations
//===----------------------------------------------------------------------===//

/// Compute BC(It, K).  The result has width W.  Assume, K > 0.
static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K,
                                       ScalarEvolution &SE,
                                       Type *ResultTy) {
  // Handle the simplest case efficiently.
  if (K == 1)
    return SE.getTruncateOrZeroExtend(It, ResultTy);

  // We are using the following formula for BC(It, K):
  //
  //   BC(It, K) = (It * (It - 1) * ... * (It - K + 1)) / K!
  //
  // Suppose, W is the bitwidth of the return value.  We must be prepared for
  // overflow.  Hence, we must assure that the result of our computation is
  // equal to the accurate one modulo 2^W.  Unfortunately, division isn't
  // safe in modular arithmetic.
  //
  // However, this code doesn't use exactly that formula; the formula it uses
  // is something like the following, where T is the number of factors of 2 in
  // K! (i.e. trailing zeros in the binary representation of K!), and ^ is
  // exponentiation:
  //
  //   BC(It, K) = (It * (It - 1) * ... * (It - K + 1)) / 2^T / (K! / 2^T)
  //
  // This formula is trivially equivalent to the previous formula.  However,
  // this formula can be implemented much more efficiently.  The trick is that
  // K! / 2^T is odd, and exact division by an odd number *is* safe in modular
  // arithmetic.  To do exact division in modular arithmetic, all we have
  // to do is multiply by the inverse.  Therefore, this step can be done at
  // width W.
  //
  // The next issue is how to safely do the division by 2^T.  The way this
  // is done is by doing the multiplication step at a width of at least W + T
  // bits.  This way, the bottom W+T bits of the product are accurate. Then,
  // when we perform the division by 2^T (which is equivalent to a right shift
  // by T), the bottom W bits are accurate.  Extra bits are okay; they'll get
  // truncated out after the division by 2^T.
  //
  // In comparison to just directly using the first formula, this technique
  // is much more efficient; using the first formula requires W * K bits,
  // but this formula less than W + K bits. Also, the first formula requires
  // a division step, whereas this formula only requires multiplies and shifts.
  //
  // It doesn't matter whether the subtraction step is done in the calculation
  // width or the input iteration count's width; if the subtraction overflows,
  // the result must be zero anyway.  We prefer here to do it in the width of
  // the induction variable because it helps a lot for certain cases; CodeGen
  // isn't smart enough to ignore the overflow, which leads to much less
  // efficient code if the width of the subtraction is wider than the native
  // register width.
  //
  // (It's possible to not widen at all by pulling out factors of 2 before
  // the multiplication; for example, K=2 can be calculated as
  // It/2*(It+(It*INT_MIN/INT_MIN)+-1). However, it requires
  // extra arithmetic, so it's not an obvious win, and it gets
  // much more complicated for K > 3.)

  // Protection from insane SCEVs; this bound is conservative,
  // but it probably doesn't matter.
  if (K > 1000)
    return SE.getCouldNotCompute();

  unsigned W = SE.getTypeSizeInBits(ResultTy);

  // Calculate K! / 2^T and T; we divide out the factors of two before
  // multiplying for calculating K! / 2^T to avoid overflow.
  // Other overflow doesn't matter because we only care about the bottom
  // W bits of the result.
  APInt OddFactorial(W, 1);
  unsigned T = 1;
  for (unsigned i = 3; i <= K; ++i) {
    APInt Mult(W, i);
    unsigned TwoFactors = Mult.countr_zero();
    T += TwoFactors;
    Mult.lshrInPlace(TwoFactors);
    OddFactorial *= Mult;
  }

  // We need at least W + T bits for the multiplication step
  unsigned CalculationBits = W + T;

  // Calculate 2^T, at width T+W.
  APInt DivFactor = APInt::getOneBitSet(CalculationBits, T);

  // Calculate the multiplicative inverse of K! / 2^T;
  // this multiplication factor will perform the exact division by
  // K! / 2^T.
  APInt Mod = APInt::getSignedMinValue(W+1);
  APInt MultiplyFactor = OddFactorial.zext(W+1);
  MultiplyFactor = MultiplyFactor.multiplicativeInverse(Mod);
  MultiplyFactor = MultiplyFactor.trunc(W);

  // Calculate the product, at width T+W
  IntegerType *CalculationTy = IntegerType::get(SE.getContext(),
                                                      CalculationBits);
  const SCEV *Dividend = SE.getTruncateOrZeroExtend(It, CalculationTy);
  for (unsigned i = 1; i != K; ++i) {
    const SCEV *S = SE.getMinusSCEV(It, SE.getConstant(It->getType(), i));
    Dividend = SE.getMulExpr(Dividend,
                             SE.getTruncateOrZeroExtend(S, CalculationTy));
  }

  // Divide by 2^T
  const SCEV *DivResult = SE.getUDivExpr(Dividend, SE.getConstant(DivFactor));

  // Truncate the result, and divide by K! / 2^T.

  return SE.getMulExpr(SE.getConstant(MultiplyFactor),
                       SE.getTruncateOrZeroExtend(DivResult, ResultTy));
}

/// Return the value of this chain of recurrences at the specified iteration
/// number.  We can evaluate this recurrence by multiplying each element in the
/// chain by the binomial coefficient corresponding to it.  In other words, we
/// can evaluate {A,+,B,+,C,+,D} as:
///
///   A*BC(It, 0) + B*BC(It, 1) + C*BC(It, 2) + D*BC(It, 3)
///
/// where BC(It, k) stands for binomial coefficient.
const SCEV *SCEVAddRecExpr::evaluateAtIteration(const SCEV *It,
                                                ScalarEvolution &SE) const {
  return evaluateAtIteration(operands(), It, SE);
}

const SCEV *
SCEVAddRecExpr::evaluateAtIteration(ArrayRef<const SCEV *> Operands,
                                    const SCEV *It, ScalarEvolution &SE) {
  assert(Operands.size() > 0);
  const SCEV *Result = Operands[0];
  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
    // The computation is correct in the face of overflow provided that the
    // multiplication is performed _after_ the evaluation of the binomial
    // coefficient.
    const SCEV *Coeff = BinomialCoefficient(It, i, SE, Result->getType());
    if (isa<SCEVCouldNotCompute>(Coeff))
      return Coeff;

    Result = SE.getAddExpr(Result, SE.getMulExpr(Operands[i], Coeff));
  }
  return Result;
}

//===----------------------------------------------------------------------===//
//                    SCEV Expression folder implementations
//===----------------------------------------------------------------------===//

const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
                                                     unsigned Depth) {
  assert(Depth <= 1 &&
         "getLosslessPtrToIntExpr() should self-recurse at most once.");

  // We could be called with an integer-typed operands during SCEV rewrites.
  // Since the operand is an integer already, just perform zext/trunc/self cast.
  if (!Op->getType()->isPointerTy())
    return Op;

  // What would be an ID for such a SCEV cast expression?
  FoldingSetNodeID ID;
  ID.AddInteger(scPtrToInt);
  ID.AddPointer(Op);

  void *IP = nullptr;

  // Is there already an expression for such a cast?
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
    return S;

  // It isn't legal for optimizations to construct new ptrtoint expressions
  // for non-integral pointers.
  if (getDataLayout().isNonIntegralPointerType(Op->getType()))
    return getCouldNotCompute();

  Type *IntPtrTy = getDataLayout().getIntPtrType(Op->getType());

  // We can only trivially model ptrtoint if SCEV's effective (integer) type
  // is sufficiently wide to represent all possible pointer values.
  // We could theoretically teach SCEV to truncate wider pointers, but
  // that isn't implemented for now.
  if (getDataLayout().getTypeSizeInBits(getEffectiveSCEVType(Op->getType())) !=
      getDataLayout().getTypeSizeInBits(IntPtrTy))
    return getCouldNotCompute();

  // If not, is this expression something we can't reduce any further?
  if (auto *U = dyn_cast<SCEVUnknown>(Op)) {
    // Perform some basic constant folding. If the operand of the ptr2int cast
    // is a null pointer, don't create a ptr2int SCEV expression (that will be
    // left as-is), but produce a zero constant.
    // NOTE: We could handle a more general case, but lack motivational cases.
    if (isa<ConstantPointerNull>(U->getValue()))
      return getZero(IntPtrTy);

    // Create an explicit cast node.
    // We can reuse the existing insert position since if we get here,
    // we won't have made any changes which would invalidate it.
    SCEV *S = new (SCEVAllocator)
        SCEVPtrToIntExpr(ID.Intern(SCEVAllocator), Op, IntPtrTy);
    UniqueSCEVs.InsertNode(S, IP);
    registerUser(S, Op);
    return S;
  }

  assert(Depth == 0 && "getLosslessPtrToIntExpr() should not self-recurse for "
                       "non-SCEVUnknown's.");

  // Otherwise, we've got some expression that is more complex than just a
  // single SCEVUnknown. But we don't want to have a SCEVPtrToIntExpr of an
  // arbitrary expression, we want to have SCEVPtrToIntExpr of an SCEVUnknown
  // only, and the expressions must otherwise be integer-typed.
  // So sink the cast down to the SCEVUnknown's.

  /// The SCEVPtrToIntSinkingRewriter takes a scalar evolution expression,
  /// which computes a pointer-typed value, and rewrites the whole expression
  /// tree so that *all* the computations are done on integers, and the only
  /// pointer-typed operands in the expression are SCEVUnknown.
  class SCEVPtrToIntSinkingRewriter
      : public SCEVRewriteVisitor<SCEVPtrToIntSinkingRewriter> {
    using Base = SCEVRewriteVisitor<SCEVPtrToIntSinkingRewriter>;

  public:
    SCEVPtrToIntSinkingRewriter(ScalarEvolution &SE) : SCEVRewriteVisitor(SE) {}

    static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE) {
      SCEVPtrToIntSinkingRewriter Rewriter(SE);
      return Rewriter.visit(Scev);
    }

    const SCEV *visit(const SCEV *S) {
      Type *STy = S->getType();
      // If the expression is not pointer-typed, just keep it as-is.
      if (!STy->isPointerTy())
        return S;
      // Else, recursively sink the cast down into it.
      return Base::visit(S);
    }

    const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
      SmallVector<const SCEV *, 2> Operands;
      bool Changed = false;
      for (const auto *Op : Expr->operands()) {
        Operands.push_back(visit(Op));
        Changed |= Op != Operands.back();
      }
      return !Changed ? Expr : SE.getAddExpr(Operands, Expr->getNoWrapFlags());
    }

    const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
      SmallVector<const SCEV *, 2> Operands;
      bool Changed = false;
      for (const auto *Op : Expr->operands()) {
        Operands.push_back(visit(Op));
        Changed |= Op != Operands.back();
      }
      return !Changed ? Expr : SE.getMulExpr(Operands, Expr->getNoWrapFlags());
    }

    const SCEV *visitUnknown(const SCEVUnknown *Expr) {
      assert(Expr->getType()->isPointerTy() &&
             "Should only reach pointer-typed SCEVUnknown's.");
      return SE.getLosslessPtrToIntExpr(Expr, /*Depth=*/1);
    }
  };

  // And actually perform the cast sinking.
  const SCEV *IntOp = SCEVPtrToIntSinkingRewriter::rewrite(Op, *this);
  assert(IntOp->getType()->isIntegerTy() &&
         "We must have succeeded in sinking the cast, "
         "and ending up with an integer-typed expression!");
  return IntOp;
}

const SCEV *ScalarEvolution::getPtrToIntExpr(const SCEV *Op, Type *Ty) {
  assert(Ty->isIntegerTy() && "Target type must be an integer type!");

  const SCEV *IntOp = getLosslessPtrToIntExpr(Op);
  if (isa<SCEVCouldNotCompute>(IntOp))
    return IntOp;

  return getTruncateOrZeroExtend(IntOp, Ty);
}

const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
                                             unsigned Depth) {
  assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) &&
         "This is not a truncating conversion!");
  assert(isSCEVable(Ty) &&
         "This is not a conversion to a SCEVable type!");
  assert(!Op->getType()->isPointerTy() && "Can't truncate pointer!");
  Ty = getEffectiveSCEVType(Ty);

  FoldingSetNodeID ID;
  ID.AddInteger(scTruncate);
  ID.AddPointer(Op);
  ID.AddPointer(Ty);
  void *IP = nullptr;
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;

  // Fold if the operand is constant.
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(Op))
    return getConstant(
      cast<ConstantInt>(ConstantExpr::getTrunc(SC->getValue(), Ty)));

  // trunc(trunc(x)) --> trunc(x)
  if (const SCEVTruncateExpr *ST = dyn_cast<SCEVTruncateExpr>(Op))
    return getTruncateExpr(ST->getOperand(), Ty, Depth + 1);

  // trunc(sext(x)) --> sext(x) if widening or trunc(x) if narrowing
  if (const SCEVSignExtendExpr *SS = dyn_cast<SCEVSignExtendExpr>(Op))
    return getTruncateOrSignExtend(SS->getOperand(), Ty, Depth + 1);

  // trunc(zext(x)) --> zext(x) if widening or trunc(x) if narrowing
  if (const SCEVZeroExtendExpr *SZ = dyn_cast<SCEVZeroExtendExpr>(Op))
    return getTruncateOrZeroExtend(SZ->getOperand(), Ty, Depth + 1);

  if (Depth > MaxCastDepth) {
    SCEV *S =
        new (SCEVAllocator) SCEVTruncateExpr(ID.Intern(SCEVAllocator), Op, Ty);
    UniqueSCEVs.InsertNode(S, IP);
    registerUser(S, Op);
    return S;
  }

  // trunc(x1 + ... + xN) --> trunc(x1) + ... + trunc(xN) and
  // trunc(x1 * ... * xN) --> trunc(x1) * ... * trunc(xN),
  // if after transforming we have at most one truncate, not counting truncates
  // that replace other casts.
  if (isa<SCEVAddExpr>(Op) || isa<SCEVMulExpr>(Op)) {
    auto *CommOp = cast<SCEVCommutativeExpr>(Op);
    SmallVector<const SCEV *, 4> Operands;
    unsigned numTruncs = 0;
    for (unsigned i = 0, e = CommOp->getNumOperands(); i != e && numTruncs < 2;
         ++i) {
      const SCEV *S = getTruncateExpr(CommOp->getOperand(i), Ty, Depth + 1);
      if (!isa<SCEVIntegralCastExpr>(CommOp->getOperand(i)) &&
          isa<SCEVTruncateExpr>(S))
        numTruncs++;
      Operands.push_back(S);
    }
    if (numTruncs < 2) {
      if (isa<SCEVAddExpr>(Op))
        return getAddExpr(Operands);
      if (isa<SCEVMulExpr>(Op))
        return getMulExpr(Operands);
      llvm_unreachable("Unexpected SCEV type for Op.");
    }
    // Although we checked in the beginning that ID is not in the cache, it is
    // possible that during recursion and different modification ID was inserted
    // into the cache. So if we find it, just return it.
    if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
      return S;
  }

  // If the input value is a chrec scev, truncate the chrec's operands.
  if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Op)) {
    SmallVector<const SCEV *, 4> Operands;
    for (const SCEV *Op : AddRec->operands())
      Operands.push_back(getTruncateExpr(Op, Ty, Depth + 1));
    return getAddRecExpr(Operands, AddRec->getLoop(), SCEV::FlagAnyWrap);
  }

  // Return zero if truncating to known zeros.
  uint32_t MinTrailingZeros = getMinTrailingZeros(Op);
  if (MinTrailingZeros >= getTypeSizeInBits(Ty))
    return getZero(Ty);

  // The cast wasn't folded; create an explicit cast node. We can reuse
  // the existing insert position since if we get here, we won't have
  // made any changes which would invalidate it.
  SCEV *S = new (SCEVAllocator) SCEVTruncateExpr(ID.Intern(SCEVAllocator),
                                                 Op, Ty);
  UniqueSCEVs.InsertNode(S, IP);
  registerUser(S, Op);
  return S;
}

// Get the limit of a recurrence such that incrementing by Step cannot cause
// signed overflow as long as the value of the recurrence within the
// loop does not exceed this limit before incrementing.
static const SCEV *getSignedOverflowLimitForStep(const SCEV *Step,
                                                 ICmpInst::Predicate *Pred,
                                                 ScalarEvolution *SE) {
  unsigned BitWidth = SE->getTypeSizeInBits(Step->getType());
  if (SE->isKnownPositive(Step)) {
    *Pred = ICmpInst::ICMP_SLT;
    return SE->getConstant(APInt::getSignedMinValue(BitWidth) -
                           SE->getSignedRangeMax(Step));
  }
  if (SE->isKnownNegative(Step)) {
    *Pred = ICmpInst::ICMP_SGT;
    return SE->getConstant(APInt::getSignedMaxValue(BitWidth) -
                           SE->getSignedRangeMin(Step));
  }
  return nullptr;
}

// Get the limit of a recurrence such that incrementing by Step cannot cause
// unsigned overflow as long as the value of the recurrence within the loop does
// not exceed this limit before incrementing.
static const SCEV *getUnsignedOverflowLimitForStep(const SCEV *Step,
                                                   ICmpInst::Predicate *Pred,
                                                   ScalarEvolution *SE) {
  unsigned BitWidth = SE->getTypeSizeInBits(Step->getType());
  *Pred = ICmpInst::ICMP_ULT;

  return SE->getConstant(APInt::getMinValue(BitWidth) -
                         SE->getUnsignedRangeMax(Step));
}

namespace {

struct ExtendOpTraitsBase {
  typedef const SCEV *(ScalarEvolution::*GetExtendExprTy)(const SCEV *, Type *,
                                                          unsigned);
};

// Used to make code generic over signed and unsigned overflow.
template <typename ExtendOp> struct ExtendOpTraits {
  // Members present:
  //
  // static const SCEV::NoWrapFlags WrapType;
  //
  // static const ExtendOpTraitsBase::GetExtendExprTy GetExtendExpr;
  //
  // static const SCEV *getOverflowLimitForStep(const SCEV *Step,
  //                                           ICmpInst::Predicate *Pred,
  //                                           ScalarEvolution *SE);
};

template <>
struct ExtendOpTraits<SCEVSignExtendExpr> : public ExtendOpTraitsBase {
  static const SCEV::NoWrapFlags WrapType = SCEV::FlagNSW;

  static const GetExtendExprTy GetExtendExpr;

  static const SCEV *getOverflowLimitForStep(const SCEV *Step,
                                             ICmpInst::Predicate *Pred,
                                             ScalarEvolution *SE) {
    return getSignedOverflowLimitForStep(Step, Pred, SE);
  }
};

const ExtendOpTraitsBase::GetExtendExprTy ExtendOpTraits<
    SCEVSignExtendExpr>::GetExtendExpr = &ScalarEvolution::getSignExtendExpr;

template <>
struct ExtendOpTraits<SCEVZeroExtendExpr> : public ExtendOpTraitsBase {
  static const SCEV::NoWrapFlags WrapType = SCEV::FlagNUW;

  static const GetExtendExprTy GetExtendExpr;

  static const SCEV *getOverflowLimitForStep(const SCEV *Step,
                                             ICmpInst::Predicate *Pred,
                                             ScalarEvolution *SE) {
    return getUnsignedOverflowLimitForStep(Step, Pred, SE);
  }
};

const ExtendOpTraitsBase::GetExtendExprTy ExtendOpTraits<
    SCEVZeroExtendExpr>::GetExtendExpr = &ScalarEvolution::getZeroExtendExpr;

} // end anonymous namespace

// The recurrence AR has been shown to have no signed/unsigned wrap or something
// close to it. Typically, if we can prove NSW/NUW for AR, then we can just as
// easily prove NSW/NUW for its preincrement or postincrement sibling. This
// allows normalizing a sign/zero extended AddRec as such: {sext/zext(Step +
// Start),+,Step} => {(Step + sext/zext(Start),+,Step} As a result, the
// expression "Step + sext/zext(PreIncAR)" is congruent with
// "sext/zext(PostIncAR)"
template <typename ExtendOpTy>
static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
                                        ScalarEvolution *SE, unsigned Depth) {
  auto WrapType = ExtendOpTraits<ExtendOpTy>::WrapType;
  auto GetExtendExpr = ExtendOpTraits<ExtendOpTy>::GetExtendExpr;

  const Loop *L = AR->getLoop();
  const SCEV *Start = AR->getStart();
  const SCEV *Step = AR->getStepRecurrence(*SE);

  // Check for a simple looking step prior to loop entry.
  const SCEVAddExpr *SA = dyn_cast<SCEVAddExpr>(Start);
  if (!SA)
    return nullptr;

  // Create an AddExpr for "PreStart" after subtracting Step. Full SCEV
  // subtraction is expensive. For this purpose, perform a quick and dirty
  // difference, by checking for Step in the operand list.
  SmallVector<const SCEV *, 4> DiffOps;
  for (const SCEV *Op : SA->operands())
    if (Op != Step)
      DiffOps.push_back(Op);

  if (DiffOps.size() == SA->getNumOperands())
    return nullptr;

  // Try to prove `WrapType` (SCEV::FlagNSW or SCEV::FlagNUW) on `PreStart` +
  // `Step`:

  // 1. NSW/NUW flags on the step increment.
  auto PreStartFlags =
    ScalarEvolution::maskFlags(SA->getNoWrapFlags(), SCEV::FlagNUW);
  const SCEV *PreStart = SE->getAddExpr(DiffOps, PreStartFlags);
  const SCEVAddRecExpr *PreAR = dyn_cast<SCEVAddRecExpr>(
      SE->getAddRecExpr(PreStart, Step, L, SCEV::FlagAnyWrap));

  // "{S,+,X} is <nsw>/<nuw>" and "the backedge is taken at least once" implies
  // "S+X does not sign/unsign-overflow".
  //

  const SCEV *BECount = SE->getBackedgeTakenCount(L);
  if (PreAR && PreAR->getNoWrapFlags(WrapType) &&
      !isa<SCEVCouldNotCompute>(BECount) && SE->isKnownPositive(BECount))
    return PreStart;

  // 2. Direct overflow check on the step operation's expression.
  unsigned BitWidth = SE->getTypeSizeInBits(AR->getType());
  Type *WideTy = IntegerType::get(SE->getContext(), BitWidth * 2);
  const SCEV *OperandExtendedStart =
      SE->getAddExpr((SE->*GetExtendExpr)(PreStart, WideTy, Depth),
                     (SE->*GetExtendExpr)(Step, WideTy, Depth));
  if ((SE->*GetExtendExpr)(Start, WideTy, Depth) == OperandExtendedStart) {
    if (PreAR && AR->getNoWrapFlags(WrapType)) {
      // If we know `AR` == {`PreStart`+`Step`,+,`Step`} is `WrapType` (FlagNSW
      // or FlagNUW) and that `PreStart` + `Step` is `WrapType` too, then
      // `PreAR` == {`PreStart`,+,`Step`} is also `WrapType`.  Cache this fact.
      SE->setNoWrapFlags(const_cast<SCEVAddRecExpr *>(PreAR), WrapType);
    }
    return PreStart;
  }

  // 3. Loop precondition.
  ICmpInst::Predicate Pred;
  const SCEV *OverflowLimit =
      ExtendOpTraits<ExtendOpTy>::getOverflowLimitForStep(Step, &Pred, SE);

  if (OverflowLimit &&
      SE->isLoopEntryGuardedByCond(L, Pred, PreStart, OverflowLimit))
    return PreStart;

  return nullptr;
}

// Get the normalized zero or sign extended expression for this AddRec's Start.
template <typename ExtendOpTy>
static const SCEV *getExtendAddRecStart(const SCEVAddRecExpr *AR, Type *Ty,
                                        ScalarEvolution *SE,
                                        unsigned Depth) {
  auto GetExtendExpr = ExtendOpTraits<ExtendOpTy>::GetExtendExpr;

  const SCEV *PreStart = getPreStartForExtend<ExtendOpTy>(AR, Ty, SE, Depth);
  if (!PreStart)
    return (SE->*GetExtendExpr)(AR->getStart(), Ty, Depth);

  return SE->getAddExpr((SE->*GetExtendExpr)(AR->getStepRecurrence(*SE), Ty,
                                             Depth),
                        (SE->*GetExtendExpr)(PreStart, Ty, Depth));
}

// Try to prove away overflow by looking at "nearby" add recurrences.  A
// motivating example for this rule: if we know `{0,+,4}` is `ult` `-1` and it
// does not itself wrap then we can conclude that `{1,+,4}` is `nuw`.
//
// Formally:
//
//     {S,+,X} == {S-T,+,X} + T
//  => Ext({S,+,X}) == Ext({S-T,+,X} + T)
//
// If ({S-T,+,X} + T) does not overflow  ... (1)
//
//  RHS == Ext({S-T,+,X} + T) == Ext({S-T,+,X}) + Ext(T)
//
// If {S-T,+,X} does not overflow  ... (2)
//
//  RHS == Ext({S-T,+,X}) + Ext(T) == {Ext(S-T),+,Ext(X)} + Ext(T)
//      == {Ext(S-T)+Ext(T),+,Ext(X)}
//
// If (S-T)+T does not overflow  ... (3)
//
//  RHS == {Ext(S-T)+Ext(T),+,Ext(X)} == {Ext(S-T+T),+,Ext(X)}
//      == {Ext(S),+,Ext(X)} == LHS
//
// Thus, if (1), (2) and (3) are true for some T, then
//   Ext({S,+,X}) == {Ext(S),+,Ext(X)}
//
// (3) is implied by (1) -- "(S-T)+T does not overflow" is simply "({S-T,+,X}+T)
// does not overflow" restricted to the 0th iteration.  Therefore we only need
// to check for (1) and (2).
//
// In the current context, S is `Start`, X is `Step`, Ext is `ExtendOpTy` and T
// is `Delta` (defined below).
template <typename ExtendOpTy>
bool ScalarEvolution::proveNoWrapByVaryingStart(const SCEV *Start,
                                                const SCEV *Step,
                                                const Loop *L) {
  auto WrapType = ExtendOpTraits<ExtendOpTy>::WrapType;

  // We restrict `Start` to a constant to prevent SCEV from spending too much
  // time here.  It is correct (but more expensive) to continue with a
  // non-constant `Start` and do a general SCEV subtraction to compute
  // `PreStart` below.
  const SCEVConstant *StartC = dyn_cast<SCEVConstant>(Start);
  if (!StartC)
    return false;

  APInt StartAI = StartC->getAPInt();

  for (unsigned Delta : {-2, -1, 1, 2}) {
    const SCEV *PreStart = getConstant(StartAI - Delta);

    FoldingSetNodeID ID;
    ID.AddInteger(scAddRecExpr);
    ID.AddPointer(PreStart);
    ID.AddPointer(Step);
    ID.AddPointer(L);
    void *IP = nullptr;
    const auto *PreAR =
      static_cast<SCEVAddRecExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));

    // Give up if we don't already have the add recurrence we need because
    // actually constructing an add recurrence is relatively expensive.
    if (PreAR && PreAR->getNoWrapFlags(WrapType)) {  // proves (2)
      const SCEV *DeltaS = getConstant(StartC->getType(), Delta);
      ICmpInst::Predicate Pred = ICmpInst::BAD_ICMP_PREDICATE;
      const SCEV *Limit = ExtendOpTraits<ExtendOpTy>::getOverflowLimitForStep(
          DeltaS, &Pred, this);
      if (Limit && isKnownPredicate(Pred, PreAR, Limit))  // proves (1)
        return true;
    }
  }

  return false;
}

// Finds an integer D for an expression (C + x + y + ...) such that the top
// level addition in (D + (C - D + x + y + ...)) would not wrap (signed or
// unsigned) and the number of trailing zeros of (C - D + x + y + ...) is
// maximized, where C is the \p ConstantTerm, x, y, ... are arbitrary SCEVs, and
// the (C + x + y + ...) expression is \p WholeAddExpr.
static APInt extractConstantWithoutWrapping(ScalarEvolution &SE,
                                            const SCEVConstant *ConstantTerm,
                                            const SCEVAddExpr *WholeAddExpr) {
  const APInt &C = ConstantTerm->getAPInt();
  const unsigned BitWidth = C.getBitWidth();
  // Find number of trailing zeros of (x + y + ...) w/o the C first:
  uint32_t TZ = BitWidth;
  for (unsigned I = 1, E = WholeAddExpr->getNumOperands(); I < E && TZ; ++I)
    TZ = std::min(TZ, SE.getMinTrailingZeros(WholeAddExpr->getOperand(I)));
  if (TZ) {
    // Set D to be as many least significant bits of C as possible while still
    // guaranteeing that adding D to (C - D + x + y + ...) won't cause a wrap:
    return TZ < BitWidth ? C.trunc(TZ).zext(BitWidth) : C;
  }
  return APInt(BitWidth, 0);
}

// Finds an integer D for an affine AddRec expression {C,+,x} such that the top
// level addition in (D + {C-D,+,x}) would not wrap (signed or unsigned) and the
// number of trailing zeros of (C - D + x * n) is maximized, where C is the \p
// ConstantStart, x is an arbitrary \p Step, and n is the loop trip count.
static APInt extractConstantWithoutWrapping(ScalarEvolution &SE,
                                            const APInt &ConstantStart,
                                            const SCEV *Step) {
  const unsigned BitWidth = ConstantStart.getBitWidth();
  const uint32_t TZ = SE.getMinTrailingZeros(Step);
  if (TZ)
    return TZ < BitWidth ? ConstantStart.trunc(TZ).zext(BitWidth)
                         : ConstantStart;
  return APInt(BitWidth, 0);
}

static void insertFoldCacheEntry(
    const ScalarEvolution::FoldID &ID, const SCEV *S,
    DenseMap<ScalarEvolution::FoldID, const SCEV *> &FoldCache,
    DenseMap<const SCEV *, SmallVector<ScalarEvolution::FoldID, 2>>
        &FoldCacheUser) {
  auto I = FoldCache.insert({ID, S});
  if (!I.second) {
    // Remove FoldCacheUser entry for ID when replacing an existing FoldCache
    // entry.
    auto &UserIDs = FoldCacheUser[I.first->second];
    assert(count(UserIDs, ID) == 1 && "unexpected duplicates in UserIDs");
    for (unsigned I = 0; I != UserIDs.size(); ++I)
      if (UserIDs[I] == ID) {
        std::swap(UserIDs[I], UserIDs.back());
        break;
      }
    UserIDs.pop_back();
    I.first->second = S;
  }
  auto R = FoldCacheUser.insert({S, {}});
  R.first->second.push_back(ID);
}

const SCEV *
ScalarEvolution::getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) {
  assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
         "This is not an extending conversion!");
  assert(isSCEVable(Ty) &&
         "This is not a conversion to a SCEVable type!");
  assert(!Op->getType()->isPointerTy() && "Can't extend pointer!");
  Ty = getEffectiveSCEVType(Ty);

  FoldID ID(scZeroExtend, Op, Ty);
  auto Iter = FoldCache.find(ID);
  if (Iter != FoldCache.end())
    return Iter->second;

  const SCEV *S = getZeroExtendExprImpl(Op, Ty, Depth);
  if (!isa<SCEVZeroExtendExpr>(S))
    insertFoldCacheEntry(ID, S, FoldCache, FoldCacheUser);
  return S;
}

const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
                                                   unsigned Depth) {
  assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
         "This is not an extending conversion!");
  assert(isSCEVable(Ty) && "This is not a conversion to a SCEVable type!");
  assert(!Op->getType()->isPointerTy() && "Can't extend pointer!");

  // Fold if the operand is constant.
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(Op))
    return getConstant(
      cast<ConstantInt>(ConstantExpr::getZExt(SC->getValue(), Ty)));

  // zext(zext(x)) --> zext(x)
  if (const SCEVZeroExtendExpr *SZ = dyn_cast<SCEVZeroExtendExpr>(Op))
    return getZeroExtendExpr(SZ->getOperand(), Ty, Depth + 1);

  // Before doing any expensive analysis, check to see if we've already
  // computed a SCEV for this Op and Ty.
  FoldingSetNodeID ID;
  ID.AddInteger(scZeroExtend);
  ID.AddPointer(Op);
  ID.AddPointer(Ty);
  void *IP = nullptr;
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
  if (Depth > MaxCastDepth) {
    SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator),
                                                     Op, Ty);
    UniqueSCEVs.InsertNode(S, IP);
    registerUser(S, Op);
    return S;
  }

  // zext(trunc(x)) --> zext(x) or x or trunc(x)
  if (const SCEVTruncateExpr *ST = dyn_cast<SCEVTruncateExpr>(Op)) {
    // It's possible the bits taken off by the truncate were all zero bits. If
    // so, we should be able to simplify this further.
    const SCEV *X = ST->getOperand();
    ConstantRange CR = getUnsignedRange(X);
    unsigned TruncBits = getTypeSizeInBits(ST->getType());
    unsigned NewBits = getTypeSizeInBits(Ty);
    if (CR.truncate(TruncBits).zeroExtend(NewBits).contains(
            CR.zextOrTrunc(NewBits)))
      return getTruncateOrZeroExtend(X, Ty, Depth);
  }

  // If the input value is a chrec scev, and we can prove that the value
  // did not overflow the old, smaller, value, we can zero extend all of the
  // operands (often constants).  This allows analysis of something like
  // this:  for (unsigned char X = 0; X < 100; ++X) { int Y = X; }
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op))
    if (AR->isAffine()) {
      const SCEV *Start = AR->getStart();
      const SCEV *Step = AR->getStepRecurrence(*this);
      unsigned BitWidth = getTypeSizeInBits(AR->getType());
      const Loop *L = AR->getLoop();

      // If we have special knowledge that this addrec won't overflow,
      // we don't need to do any further analysis.
      if (AR->hasNoUnsignedWrap()) {
        Start =
            getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Depth + 1);
        Step = getZeroExtendExpr(Step, Ty, Depth + 1);
        return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
      }

      // Check whether the backedge-taken count is SCEVCouldNotCompute.
      // Note that this serves two purposes: It filters out loops that are
      // simply not analyzable, and it covers the case where this code is
      // being called from within backedge-taken count analysis, such that
      // attempting to ask for the backedge-taken count would likely result
      // in infinite recursion. In the later case, the analysis code will
      // cope with a conservative value, and it will take care to purge
      // that value once it has finished.
      const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);
      if (!isa<SCEVCouldNotCompute>(MaxBECount)) {
        // Manually compute the final value for AR, checking for overflow.

        // Check whether the backedge-taken count can be losslessly casted to
        // the addrec's type. The count is always unsigned.
        const SCEV *CastedMaxBECount =
            getTruncateOrZeroExtend(MaxBECount, Start->getType(), Depth);
        const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(
            CastedMaxBECount, MaxBECount->getType(), Depth);
        if (MaxBECount == RecastedMaxBECount) {
          Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
          // Check whether Start+Step*MaxBECount has no unsigned overflow.
          const SCEV *ZMul = getMulExpr(CastedMaxBECount, Step,
                                        SCEV::FlagAnyWrap, Depth + 1);
          const SCEV *ZAdd = getZeroExtendExpr(getAddExpr(Start, ZMul,
                                                          SCEV::FlagAnyWrap,
                                                          Depth + 1),
                                               WideTy, Depth + 1);
          const SCEV *WideStart = getZeroExtendExpr(Start, WideTy, Depth + 1);
          const SCEV *WideMaxBECount =
            getZeroExtendExpr(CastedMaxBECount, WideTy, Depth + 1);
          const SCEV *OperandExtendedAdd =
            getAddExpr(WideStart,
                       getMulExpr(WideMaxBECount,
                                  getZeroExtendExpr(Step, WideTy, Depth + 1),
                                  SCEV::FlagAnyWrap, Depth + 1),
                       SCEV::FlagAnyWrap, Depth + 1);
          if (ZAdd == OperandExtendedAdd) {
            // Cache knowledge of AR NUW, which is propagated to this AddRec.
            setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNUW);
            // Return the expression with the addrec on the outside.
            Start = getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this,
                                                             Depth + 1);
            Step = getZeroExtendExpr(Step, Ty, Depth + 1);
            return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
          }
          // Similar to above, only this time treat the step value as signed.
          // This covers loops that count down.
          OperandExtendedAdd =
            getAddExpr(WideStart,
                       getMulExpr(WideMaxBECount,
                                  getSignExtendExpr(Step, WideTy, Depth + 1),
                                  SCEV::FlagAnyWrap, Depth + 1),
                       SCEV::FlagAnyWrap, Depth + 1);
          if (ZAdd == OperandExtendedAdd) {
            // Cache knowledge of AR NW, which is propagated to this AddRec.
            // Negative step causes unsigned wrap, but it still can't self-wrap.
            setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNW);
            // Return the expression with the addrec on the outside.
            Start = getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this,
                                                             Depth + 1);
            Step = getSignExtendExpr(Step, Ty, Depth + 1);
            return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
          }
        }
      }

      // Normally, in the cases we can prove no-overflow via a
      // backedge guarding condition, we can also compute a backedge
      // taken count for the loop.  The exceptions are assumptions and
      // guards present in the loop -- SCEV is not great at exploiting
      // these to compute max backedge taken counts, but can still use
      // these to prove lack of overflow.  Use this fact to avoid
      // doing extra work that may not pay off.
      if (!isa<SCEVCouldNotCompute>(MaxBECount) || HasGuards ||
          !AC.assumptions().empty()) {

        auto NewFlags = proveNoUnsignedWrapViaInduction(AR);
        setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), NewFlags);
        if (AR->hasNoUnsignedWrap()) {
          // Same as nuw case above - duplicated here to avoid a compile time
          // issue.  It's not clear that the order of checks does matter, but
          // it's one of two issue possible causes for a change which was
          // reverted.  Be conservative for the moment.
          Start =
              getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Depth + 1);
          Step = getZeroExtendExpr(Step, Ty, Depth + 1);
          return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
        }
        
        // For a negative step, we can extend the operands iff doing so only
        // traverses values in the range zext([0,UINT_MAX]). 
        if (isKnownNegative(Step)) {
          const SCEV *N = getConstant(APInt::getMaxValue(BitWidth) -
                                      getSignedRangeMin(Step));
          if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, AR, N) ||
              isKnownOnEveryIteration(ICmpInst::ICMP_UGT, AR, N)) {
            // Cache knowledge of AR NW, which is propagated to this
            // AddRec.  Negative step causes unsigned wrap, but it
            // still can't self-wrap.
            setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNW);
            // Return the expression with the addrec on the outside.
            Start = getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this,
                                                             Depth + 1);
            Step = getSignExtendExpr(Step, Ty, Depth + 1);
            return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
          }
        }
      }

      // zext({C,+,Step}) --> (zext(D) + zext({C-D,+,Step}))<nuw><nsw>
      // if D + (C - D + Step * n) could be proven to not unsigned wrap
      // where D maximizes the number of trailing zeros of (C - D + Step * n)
      if (const auto *SC = dyn_cast<SCEVConstant>(Start)) {
        const APInt &C = SC->getAPInt();
        const APInt &D = extractConstantWithoutWrapping(*this, C, Step);
        if (D != 0) {
          const SCEV *SZExtD = getZeroExtendExpr(getConstant(D), Ty, Depth);
          const SCEV *SResidual =
              getAddRecExpr(getConstant(C - D), Step, L, AR->getNoWrapFlags());
          const SCEV *SZExtR = getZeroExtendExpr(SResidual, Ty, Depth + 1);
          return getAddExpr(SZExtD, SZExtR,
                            (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                            Depth + 1);
        }
      }

      if (proveNoWrapByVaryingStart<SCEVZeroExtendExpr>(Start, Step, L)) {
        setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNUW);
        Start =
            getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, Depth + 1);
        Step = getZeroExtendExpr(Step, Ty, Depth + 1);
        return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
      }
    }

  // zext(A % B) --> zext(A) % zext(B)
  {
    const SCEV *LHS;
    const SCEV *RHS;
    if (matchURem(Op, LHS, RHS))
      return getURemExpr(getZeroExtendExpr(LHS, Ty, Depth + 1),
                         getZeroExtendExpr(RHS, Ty, Depth + 1));
  }

  // zext(A / B) --> zext(A) / zext(B).
  if (auto *Div = dyn_cast<SCEVUDivExpr>(Op))
    return getUDivExpr(getZeroExtendExpr(Div->getLHS(), Ty, Depth + 1),
                       getZeroExtendExpr(Div->getRHS(), Ty, Depth + 1));

  if (auto *SA = dyn_cast<SCEVAddExpr>(Op)) {
    // zext((A + B + ...)<nuw>) --> (zext(A) + zext(B) + ...)<nuw>
    if (SA->hasNoUnsignedWrap()) {
      // If the addition does not unsign overflow then we can, by definition,
      // commute the zero extension with the addition operation.
      SmallVector<const SCEV *, 4> Ops;
      for (const auto *Op : SA->operands())
        Ops.push_back(getZeroExtendExpr(Op, Ty, Depth + 1));
      return getAddExpr(Ops, SCEV::FlagNUW, Depth + 1);
    }

    // zext(C + x + y + ...) --> (zext(D) + zext((C - D) + x + y + ...))
    // if D + (C - D + x + y + ...) could be proven to not unsigned wrap
    // where D maximizes the number of trailing zeros of (C - D + x + y + ...)
    //
    // Often address arithmetics contain expressions like
    // (zext (add (shl X, C1), C2)), for instance, (zext (5 + (4 * X))).
    // This transformation is useful while proving that such expressions are
    // equal or differ by a small constant amount, see LoadStoreVectorizer pass.
    if (const auto *SC = dyn_cast<SCEVConstant>(SA->getOperand(0))) {
      const APInt &D = extractConstantWithoutWrapping(*this, SC, SA);
      if (D != 0) {
        const SCEV *SZExtD = getZeroExtendExpr(getConstant(D), Ty, Depth);
        const SCEV *SResidual =
            getAddExpr(getConstant(-D), SA, SCEV::FlagAnyWrap, Depth);
        const SCEV *SZExtR = getZeroExtendExpr(SResidual, Ty, Depth + 1);
        return getAddExpr(SZExtD, SZExtR,
                          (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                          Depth + 1);
      }
    }
  }

  if (auto *SM = dyn_cast<SCEVMulExpr>(Op)) {
    // zext((A * B * ...)<nuw>) --> (zext(A) * zext(B) * ...)<nuw>
    if (SM->hasNoUnsignedWrap()) {
      // If the multiply does not unsign overflow then we can, by definition,
      // commute the zero extension with the multiply operation.
      SmallVector<const SCEV *, 4> Ops;
      for (const auto *Op : SM->operands())
        Ops.push_back(getZeroExtendExpr(Op, Ty, Depth + 1));
      return getMulExpr(Ops, SCEV::FlagNUW, Depth + 1);
    }

    // zext(2^K * (trunc X to iN)) to iM ->
    // 2^K * (zext(trunc X to i{N-K}) to iM)<nuw>
    //
    // Proof:
    //
    //     zext(2^K * (trunc X to iN)) to iM
    //   = zext((trunc X to iN) << K) to iM
    //   = zext((trunc X to i{N-K}) << K)<nuw> to iM
    //     (because shl removes the top K bits)
    //   = zext((2^K * (trunc X to i{N-K}))<nuw>) to iM
    //   = (2^K * (zext(trunc X to i{N-K}) to iM))<nuw>.
    //
    if (SM->getNumOperands() == 2)
      if (auto *MulLHS = dyn_cast<SCEVConstant>(SM->getOperand(0)))
        if (MulLHS->getAPInt().isPowerOf2())
          if (auto *TruncRHS = dyn_cast<SCEVTruncateExpr>(SM->getOperand(1))) {
            int NewTruncBits = getTypeSizeInBits(TruncRHS->getType()) -
                               MulLHS->getAPInt().logBase2();
            Type *NewTruncTy = IntegerType::get(getContext(), NewTruncBits);
            return getMulExpr(
                getZeroExtendExpr(MulLHS, Ty),
                getZeroExtendExpr(
                    getTruncateExpr(TruncRHS->getOperand(), NewTruncTy), Ty),
                SCEV::FlagNUW, Depth + 1);
          }
  }

  // zext(umin(x, y)) -> umin(zext(x), zext(y))
  // zext(umax(x, y)) -> umax(zext(x), zext(y))
  if (isa<SCEVUMinExpr>(Op) || isa<SCEVUMaxExpr>(Op)) {
    auto *MinMax = cast<SCEVMinMaxExpr>(Op);
    SmallVector<const SCEV *, 4> Operands;
    for (auto *Operand : MinMax->operands())
      Operands.push_back(getZeroExtendExpr(Operand, Ty));
    if (isa<SCEVUMinExpr>(MinMax))
      return getUMinExpr(Operands);
    return getUMaxExpr(Operands);
  }

  // zext(umin_seq(x, y)) -> umin_seq(zext(x), zext(y))
  if (auto *MinMax = dyn_cast<SCEVSequentialMinMaxExpr>(Op)) {
    assert(isa<SCEVSequentialUMinExpr>(MinMax) && "Not supported!");
    SmallVector<const SCEV *, 4> Operands;
    for (auto *Operand : MinMax->operands())
      Operands.push_back(getZeroExtendExpr(Operand, Ty));
    return getUMinExpr(Operands, /*Sequential*/ true);
  }

  // The cast wasn't folded; create an explicit cast node.
  // Recompute the insert position, as it may have been invalidated.
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
  SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator),
                                                   Op, Ty);
  UniqueSCEVs.InsertNode(S, IP);
  registerUser(S, Op);
  return S;
}

const SCEV *
ScalarEvolution::getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) {
  assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
         "This is not an extending conversion!");
  assert(isSCEVable(Ty) &&
         "This is not a conversion to a SCEVable type!");
  assert(!Op->getType()->isPointerTy() && "Can't extend pointer!");
  Ty = getEffectiveSCEVType(Ty);

  FoldID ID(scSignExtend, Op, Ty);
  auto Iter = FoldCache.find(ID);
  if (Iter != FoldCache.end())
    return Iter->second;

  const SCEV *S = getSignExtendExprImpl(Op, Ty, Depth);
  if (!isa<SCEVSignExtendExpr>(S))
    insertFoldCacheEntry(ID, S, FoldCache, FoldCacheUser);
  return S;
}

const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
                                                   unsigned Depth) {
  assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
         "This is not an extending conversion!");
  assert(isSCEVable(Ty) && "This is not a conversion to a SCEVable type!");
  assert(!Op->getType()->isPointerTy() && "Can't extend pointer!");
  Ty = getEffectiveSCEVType(Ty);

  // Fold if the operand is constant.
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(Op))
    return getConstant(
      cast<ConstantInt>(ConstantExpr::getSExt(SC->getValue(), Ty)));

  // sext(sext(x)) --> sext(x)
  if (const SCEVSignExtendExpr *SS = dyn_cast<SCEVSignExtendExpr>(Op))
    return getSignExtendExpr(SS->getOperand(), Ty, Depth + 1);

  // sext(zext(x)) --> zext(x)
  if (const SCEVZeroExtendExpr *SZ = dyn_cast<SCEVZeroExtendExpr>(Op))
    return getZeroExtendExpr(SZ->getOperand(), Ty, Depth + 1);

  // Before doing any expensive analysis, check to see if we've already
  // computed a SCEV for this Op and Ty.
  FoldingSetNodeID ID;
  ID.AddInteger(scSignExtend);
  ID.AddPointer(Op);
  ID.AddPointer(Ty);
  void *IP = nullptr;
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
  // Limit recursion depth.
  if (Depth > MaxCastDepth) {
    SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator),
                                                     Op, Ty);
    UniqueSCEVs.InsertNode(S, IP);
    registerUser(S, Op);
    return S;
  }

  // sext(trunc(x)) --> sext(x) or x or trunc(x)
  if (const SCEVTruncateExpr *ST = dyn_cast<SCEVTruncateExpr>(Op)) {
    // It's possible the bits taken off by the truncate were all sign bits. If
    // so, we should be able to simplify this further.
    const SCEV *X = ST->getOperand();
    ConstantRange CR = getSignedRange(X);
    unsigned TruncBits = getTypeSizeInBits(ST->getType());
    unsigned NewBits = getTypeSizeInBits(Ty);
    if (CR.truncate(TruncBits).signExtend(NewBits).contains(
            CR.sextOrTrunc(NewBits)))
      return getTruncateOrSignExtend(X, Ty, Depth);
  }

  if (auto *SA = dyn_cast<SCEVAddExpr>(Op)) {
    // sext((A + B + ...)<nsw>) --> (sext(A) + sext(B) + ...)<nsw>
    if (SA->hasNoSignedWrap()) {
      // If the addition does not sign overflow then we can, by definition,
      // commute the sign extension with the addition operation.
      SmallVector<const SCEV *, 4> Ops;
      for (const auto *Op : SA->operands())
        Ops.push_back(getSignExtendExpr(Op, Ty, Depth + 1));
      return getAddExpr(Ops, SCEV::FlagNSW, Depth + 1);
    }

    // sext(C + x + y + ...) --> (sext(D) + sext((C - D) + x + y + ...))
    // if D + (C - D + x + y + ...) could be proven to not signed wrap
    // where D maximizes the number of trailing zeros of (C - D + x + y + ...)
    //
    // For instance, this will bring two seemingly different expressions:
    //     1 + sext(5 + 20 * %x + 24 * %y)  and
    //         sext(6 + 20 * %x + 24 * %y)
    // to the same form:
    //     2 + sext(4 + 20 * %x + 24 * %y)
    if (const auto *SC = dyn_cast<SCEVConstant>(SA->getOperand(0))) {
      const APInt &D = extractConstantWithoutWrapping(*this, SC, SA);
      if (D != 0) {
        const SCEV *SSExtD = getSignExtendExpr(getConstant(D), Ty, Depth);
        const SCEV *SResidual =
            getAddExpr(getConstant(-D), SA, SCEV::FlagAnyWrap, Depth);
        const SCEV *SSExtR = getSignExtendExpr(SResidual, Ty, Depth + 1);
        return getAddExpr(SSExtD, SSExtR,
                          (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                          Depth + 1);
      }
    }
  }
  // If the input value is a chrec scev, and we can prove that the value
  // did not overflow the old, smaller, value, we can sign extend all of the
  // operands (often constants).  This allows analysis of something like
  // this:  for (signed char X = 0; X < 100; ++X) { int Y = X; }
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op))
    if (AR->isAffine()) {
      const SCEV *Start = AR->getStart();
      const SCEV *Step = AR->getStepRecurrence(*this);
      unsigned BitWidth = getTypeSizeInBits(AR->getType());
      const Loop *L = AR->getLoop();

      // If we have special knowledge that this addrec won't overflow,
      // we don't need to do any further analysis.
      if (AR->hasNoSignedWrap()) {
        Start =
            getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
        Step = getSignExtendExpr(Step, Ty, Depth + 1);
        return getAddRecExpr(Start, Step, L, SCEV::FlagNSW);
      }

      // Check whether the backedge-taken count is SCEVCouldNotCompute.
      // Note that this serves two purposes: It filters out loops that are
      // simply not analyzable, and it covers the case where this code is
      // being called from within backedge-taken count analysis, such that
      // attempting to ask for the backedge-taken count would likely result
      // in infinite recursion. In the later case, the analysis code will
      // cope with a conservative value, and it will take care to purge
      // that value once it has finished.
      const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);
      if (!isa<SCEVCouldNotCompute>(MaxBECount)) {
        // Manually compute the final value for AR, checking for
        // overflow.

        // Check whether the backedge-taken count can be losslessly casted to
        // the addrec's type. The count is always unsigned.
        const SCEV *CastedMaxBECount =
            getTruncateOrZeroExtend(MaxBECount, Start->getType(), Depth);
        const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(
            CastedMaxBECount, MaxBECount->getType(), Depth);
        if (MaxBECount == RecastedMaxBECount) {
          Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
          // Check whether Start+Step*MaxBECount has no signed overflow.
          const SCEV *SMul = getMulExpr(CastedMaxBECount, Step,
                                        SCEV::FlagAnyWrap, Depth + 1);
          const SCEV *SAdd = getSignExtendExpr(getAddExpr(Start, SMul,
                                                          SCEV::FlagAnyWrap,
                                                          Depth + 1),
                                               WideTy, Depth + 1);
          const SCEV *WideStart = getSignExtendExpr(Start, WideTy, Depth + 1);
          const SCEV *WideMaxBECount =
            getZeroExtendExpr(CastedMaxBECount, WideTy, Depth + 1);
          const SCEV *OperandExtendedAdd =
            getAddExpr(WideStart,
                       getMulExpr(WideMaxBECount,
                                  getSignExtendExpr(Step, WideTy, Depth + 1),
                                  SCEV::FlagAnyWrap, Depth + 1),
                       SCEV::FlagAnyWrap, Depth + 1);
          if (SAdd == OperandExtendedAdd) {
            // Cache knowledge of AR NSW, which is propagated to this AddRec.
            setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNSW);
            // Return the expression with the addrec on the outside.
            Start = getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this,
                                                             Depth + 1);
            Step = getSignExtendExpr(Step, Ty, Depth + 1);
            return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
          }
          // Similar to above, only this time treat the step value as unsigned.
          // This covers loops that count up with an unsigned step.
          OperandExtendedAdd =
            getAddExpr(WideStart,
                       getMulExpr(WideMaxBECount,
                                  getZeroExtendExpr(Step, WideTy, Depth + 1),
                                  SCEV::FlagAnyWrap, Depth + 1),
                       SCEV::FlagAnyWrap, Depth + 1);
          if (SAdd == OperandExtendedAdd) {
            // If AR wraps around then
            //
            //    abs(Step) * MaxBECount > unsigned-max(AR->getType())
            // => SAdd != OperandExtendedAdd
            //
            // Thus (AR is not NW => SAdd != OperandExtendedAdd) <=>
            // (SAdd == OperandExtendedAdd => AR is NW)

            setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNW);

            // Return the expression with the addrec on the outside.
            Start = getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this,
                                                             Depth + 1);
            Step = getZeroExtendExpr(Step, Ty, Depth + 1);
            return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
          }
        }
      }

      auto NewFlags = proveNoSignedWrapViaInduction(AR);
      setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), NewFlags);
      if (AR->hasNoSignedWrap()) {
        // Same as nsw case above - duplicated here to avoid a compile time
        // issue.  It's not clear that the order of checks does matter, but
        // it's one of two issue possible causes for a change which was
        // reverted.  Be conservative for the moment.
        Start =
            getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
        Step = getSignExtendExpr(Step, Ty, Depth + 1);
        return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
      }

      // sext({C,+,Step}) --> (sext(D) + sext({C-D,+,Step}))<nuw><nsw>
      // if D + (C - D + Step * n) could be proven to not signed wrap
      // where D maximizes the number of trailing zeros of (C - D + Step * n)
      if (const auto *SC = dyn_cast<SCEVConstant>(Start)) {
        const APInt &C = SC->getAPInt();
        const APInt &D = extractConstantWithoutWrapping(*this, C, Step);
        if (D != 0) {
          const SCEV *SSExtD = getSignExtendExpr(getConstant(D), Ty, Depth);
          const SCEV *SResidual =
              getAddRecExpr(getConstant(C - D), Step, L, AR->getNoWrapFlags());
          const SCEV *SSExtR = getSignExtendExpr(SResidual, Ty, Depth + 1);
          return getAddExpr(SSExtD, SSExtR,
                            (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                            Depth + 1);
        }
      }

      if (proveNoWrapByVaryingStart<SCEVSignExtendExpr>(Start, Step, L)) {
        setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNSW);
        Start =
            getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
        Step = getSignExtendExpr(Step, Ty, Depth + 1);
        return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
      }
    }

  // If the input value is provably positive and we could not simplify
  // away the sext build a zext instead.
  if (isKnownNonNegative(Op))
    return getZeroExtendExpr(Op, Ty, Depth + 1);

  // sext(smin(x, y)) -> smin(sext(x), sext(y))
  // sext(smax(x, y)) -> smax(sext(x), sext(y))
  if (isa<SCEVSMinExpr>(Op) || isa<SCEVSMaxExpr>(Op)) {
    auto *MinMax = cast<SCEVMinMaxExpr>(Op);
    SmallVector<const SCEV *, 4> Operands;
    for (auto *Operand : MinMax->operands())
      Operands.push_back(getSignExtendExpr(Operand, Ty));
    if (isa<SCEVSMinExpr>(MinMax))
      return getSMinExpr(Operands);
    return getSMaxExpr(Operands);
  }

  // The cast wasn't folded; create an explicit cast node.
  // Recompute the insert position, as it may have been invalidated.
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
  SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator),
                                                   Op, Ty);
  UniqueSCEVs.InsertNode(S, IP);
  registerUser(S, { Op });
  return S;
}

const SCEV *ScalarEvolution::getCastExpr(SCEVTypes Kind, const SCEV *Op,
                                         Type *Ty) {
  switch (Kind) {
  case scTruncate:
    return getTruncateExpr(Op, Ty);
  case scZeroExtend:
    return getZeroExtendExpr(Op, Ty);
  case scSignExtend:
    return getSignExtendExpr(Op, Ty);
  case scPtrToInt:
    return getPtrToIntExpr(Op, Ty);
  default:
    llvm_unreachable("Not a SCEV cast expression!");
  }
}

/// getAnyExtendExpr - Return a SCEV for the given operand extended with
/// unspecified bits out to the given type.
const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op,
                                              Type *Ty) {
  assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
         "This is not an extending conversion!");
  assert(isSCEVable(Ty) &&
         "This is not a conversion to a SCEVable type!");
  Ty = getEffectiveSCEVType(Ty);

  // Sign-extend negative constants.
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(Op))
    if (SC->getAPInt().isNegative())
      return getSignExtendExpr(Op, Ty);

  // Peel off a truncate cast.
  if (const SCEVTruncateExpr *T = dyn_cast<SCEVTruncateExpr>(Op)) {
    const SCEV *NewOp = T->getOperand();
    if (getTypeSizeInBits(NewOp->getType()) < getTypeSizeInBits(Ty))
      return getAnyExtendExpr(NewOp, Ty);
    return getTruncateOrNoop(NewOp, Ty);
  }

  // Next try a zext cast. If the cast is folded, use it.
  const SCEV *ZExt = getZeroExtendExpr(Op, Ty);
  if (!isa<SCEVZeroExtendExpr>(ZExt))
    return ZExt;

  // Next try a sext cast. If the cast is folded, use it.
  const SCEV *SExt = getSignExtendExpr(Op, Ty);
  if (!isa<SCEVSignExtendExpr>(SExt))
    return SExt;

  // Force the cast to be folded into the operands of an addrec.
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op)) {
    SmallVector<const SCEV *, 4> Ops;
    for (const SCEV *Op : AR->operands())
      Ops.push_back(getAnyExtendExpr(Op, Ty));
    return getAddRecExpr(Ops, AR->getLoop(), SCEV::FlagNW);
  }

  // If the expression is obviously signed, use the sext cast value.
  if (isa<SCEVSMaxExpr>(Op))
    return SExt;

  // Absent any other information, use the zext cast value.
  return ZExt;
}

/// Process the given Ops list, which is a list of operands to be added under
/// the given scale, update the given map. This is a helper function for
/// getAddRecExpr. As an example of what it does, given a sequence of operands
/// that would form an add expression like this:
///
///    m + n + 13 + (A * (o + p + (B * (q + m + 29)))) + r + (-1 * r)
///
/// where A and B are constants, update the map with these values:
///
///    (m, 1+A*B), (n, 1), (o, A), (p, A), (q, A*B), (r, 0)
///
/// and add 13 + A*B*29 to AccumulatedConstant.
/// This will allow getAddRecExpr to produce this:
///
///    13+A*B*29 + n + (m * (1+A*B)) + ((o + p) * A) + (q * A*B)
///
/// This form often exposes folding opportunities that are hidden in
/// the original operand list.
///
/// Return true iff it appears that any interesting folding opportunities
/// may be exposed. This helps getAddRecExpr short-circuit extra work in
/// the common case where no interesting opportunities are present, and
/// is also used as a check to avoid infinite recursion.
static bool
CollectAddOperandsWithScales(DenseMap<const SCEV *, APInt> &M,
                             SmallVectorImpl<const SCEV *> &NewOps,
                             APInt &AccumulatedConstant,
                             ArrayRef<const SCEV *> Ops, const APInt &Scale,
                             ScalarEvolution &SE) {
  bool Interesting = false;

  // Iterate over the add operands. They are sorted, with constants first.
  unsigned i = 0;
  while (const SCEVConstant *C = dyn_cast<SCEVConstant>(Ops[i])) {
    ++i;
    // Pull a buried constant out to the outside.
    if (Scale != 1 || AccumulatedConstant != 0 || C->getValue()->isZero())
      Interesting = true;
    AccumulatedConstant += Scale * C->getAPInt();
  }

  // Next comes everything else. We're especially interested in multiplies
  // here, but they're in the middle, so just visit the rest with one loop.
  for (; i != Ops.size(); ++i) {
    const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[i]);
    if (Mul && isa<SCEVConstant>(Mul->getOperand(0))) {
      APInt NewScale =
          Scale * cast<SCEVConstant>(Mul->getOperand(0))->getAPInt();
      if (Mul->getNumOperands() == 2 && isa<SCEVAddExpr>(Mul->getOperand(1))) {
        // A multiplication of a constant with another add; recurse.
        const SCEVAddExpr *Add = cast<SCEVAddExpr>(Mul->getOperand(1));
        Interesting |=
          CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant,
                                       Add->operands(), NewScale, SE);
      } else {
        // A multiplication of a constant with some other value. Update
        // the map.
        SmallVector<const SCEV *, 4> MulOps(drop_begin(Mul->operands()));
        const SCEV *Key = SE.getMulExpr(MulOps);
        auto Pair = M.insert({Key, NewScale});
        if (Pair.second) {
          NewOps.push_back(Pair.first->first);
        } else {
          Pair.first->second += NewScale;
          // The map already had an entry for this value, which may indicate
          // a folding opportunity.
          Interesting = true;
        }
      }
    } else {
      // An ordinary operand. Update the map.
      std::pair<DenseMap<const SCEV *, APInt>::iterator, bool> Pair =
          M.insert({Ops[i], Scale});
      if (Pair.second) {
        NewOps.push_back(Pair.first->first);
      } else {
        Pair.first->second += Scale;
        // The map already had an entry for this value, which may indicate
        // a folding opportunity.
        Interesting = true;
      }
    }
  }

  return Interesting;
}

bool ScalarEvolution::willNotOverflow(Instruction::BinaryOps BinOp, bool Signed,
                                      const SCEV *LHS, const SCEV *RHS,
                                      const Instruction *CtxI) {
  const SCEV *(ScalarEvolution::*Operation)(const SCEV *, const SCEV *,
                                            SCEV::NoWrapFlags, unsigned);
  switch (BinOp) {
  default:
    llvm_unreachable("Unsupported binary op");
  case Instruction::Add:
    Operation = &ScalarEvolution::getAddExpr;
    break;
  case Instruction::Sub:
    Operation = &ScalarEvolution::getMinusSCEV;
    break;
  case Instruction::Mul:
    Operation = &ScalarEvolution::getMulExpr;
    break;
  }

  const SCEV *(ScalarEvolution::*Extension)(const SCEV *, Type *, unsigned) =
      Signed ? &ScalarEvolution::getSignExtendExpr
             : &ScalarEvolution::getZeroExtendExpr;

  // Check ext(LHS op RHS) == ext(LHS) op ext(RHS)
  auto *NarrowTy = cast<IntegerType>(LHS->getType());
  auto *WideTy =
      IntegerType::get(NarrowTy->getContext(), NarrowTy->getBitWidth() * 2);

  const SCEV *A = (this->*Extension)(
      (this->*Operation)(LHS, RHS, SCEV::FlagAnyWrap, 0), WideTy, 0);
  const SCEV *LHSB = (this->*Extension)(LHS, WideTy, 0);
  const SCEV *RHSB = (this->*Extension)(RHS, WideTy, 0);
  const SCEV *B = (this->*Operation)(LHSB, RHSB, SCEV::FlagAnyWrap, 0);
  if (A == B)
    return true;
  // Can we use context to prove the fact we need?
  if (!CtxI)
    return false;
  // TODO: Support mul.
  if (BinOp == Instruction::Mul)
    return false;
  auto *RHSC = dyn_cast<SCEVConstant>(RHS);
  // TODO: Lift this limitation.
  if (!RHSC)
    return false;
  APInt C = RHSC->getAPInt();
  unsigned NumBits = C.getBitWidth();
  bool IsSub = (BinOp == Instruction::Sub);
  bool IsNegativeConst = (Signed && C.isNegative());
  // Compute the direction and magnitude by which we need to check overflow.
  bool OverflowDown = IsSub ^ IsNegativeConst;
  APInt Magnitude = C;
  if (IsNegativeConst) {
    if (C == APInt::getSignedMinValue(NumBits))
      // TODO: SINT_MIN on inversion gives the same negative value, we don't
      // want to deal with that.
      return false;
    Magnitude = -C;
  }

  ICmpInst::Predicate Pred = Signed ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
  if (OverflowDown) {
    // To avoid overflow down, we need to make sure that MIN + Magnitude <= LHS.
    APInt Min = Signed ? APInt::getSignedMinValue(NumBits)
                       : APInt::getMinValue(NumBits);
    APInt Limit = Min + Magnitude;
    return isKnownPredicateAt(Pred, getConstant(Limit), LHS, CtxI);
  } else {
    // To avoid overflow up, we need to make sure that LHS <= MAX - Magnitude.
    APInt Max = Signed ? APInt::getSignedMaxValue(NumBits)
                       : APInt::getMaxValue(NumBits);
    APInt Limit = Max - Magnitude;
    return isKnownPredicateAt(Pred, LHS, getConstant(Limit), CtxI);
  }
}

std::optional<SCEV::NoWrapFlags>
ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(
    const OverflowingBinaryOperator *OBO) {
  // It cannot be done any better.
  if (OBO->hasNoUnsignedWrap() && OBO->hasNoSignedWrap())
    return std::nullopt;

  SCEV::NoWrapFlags Flags = SCEV::NoWrapFlags::FlagAnyWrap;

  if (OBO->hasNoUnsignedWrap())
    Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
  if (OBO->hasNoSignedWrap())
    Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW);

  bool Deduced = false;

  if (OBO->getOpcode() != Instruction::Add &&
      OBO->getOpcode() != Instruction::Sub &&
      OBO->getOpcode() != Instruction::Mul)
    return std::nullopt;

  const SCEV *LHS = getSCEV(OBO->getOperand(0));
  const SCEV *RHS = getSCEV(OBO->getOperand(1));

  const Instruction *CtxI =
      UseContextForNoWrapFlagInference ? dyn_cast<Instruction>(OBO) : nullptr;
  if (!OBO->hasNoUnsignedWrap() &&
      willNotOverflow((Instruction::BinaryOps)OBO->getOpcode(),
                      /* Signed */ false, LHS, RHS, CtxI)) {
    Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
    Deduced = true;
  }

  if (!OBO->hasNoSignedWrap() &&
      willNotOverflow((Instruction::BinaryOps)OBO->getOpcode(),
                      /* Signed */ true, LHS, RHS, CtxI)) {
    Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW);
    Deduced = true;
  }

  if (Deduced)
    return Flags;
  return std::nullopt;
}

// We're trying to construct a SCEV of type `Type' with `Ops' as operands and
// `OldFlags' as can't-wrap behavior.  Infer a more aggressive set of
// can't-overflow flags for the operation if possible.
static SCEV::NoWrapFlags
StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type,
                      const ArrayRef<const SCEV *> Ops,
                      SCEV::NoWrapFlags Flags) {
  using namespace std::placeholders;

  using OBO = OverflowingBinaryOperator;

  bool CanAnalyze =
      Type == scAddExpr || Type == scAddRecExpr || Type == scMulExpr;
  (void)CanAnalyze;
  assert(CanAnalyze && "don't call from other places!");

  int SignOrUnsignMask = SCEV::FlagNUW | SCEV::FlagNSW;
  SCEV::NoWrapFlags SignOrUnsignWrap =
      ScalarEvolution::maskFlags(Flags, SignOrUnsignMask);

  // If FlagNSW is true and all the operands are non-negative, infer FlagNUW.
  auto IsKnownNonNegative = [&](const SCEV *S) {
    return SE->isKnownNonNegative(S);
  };

  if (SignOrUnsignWrap == SCEV::FlagNSW && all_of(Ops, IsKnownNonNegative))
    Flags =
        ScalarEvolution::setFlags(Flags, (SCEV::NoWrapFlags)SignOrUnsignMask);

  SignOrUnsignWrap = ScalarEvolution::maskFlags(Flags, SignOrUnsignMask);

  if (SignOrUnsignWrap != SignOrUnsignMask &&
      (Type == scAddExpr || Type == scMulExpr) && Ops.size() == 2 &&
      isa<SCEVConstant>(Ops[0])) {

    auto Opcode = [&] {
      switch (Type) {
      case scAddExpr:
        return Instruction::Add;
      case scMulExpr:
        return Instruction::Mul;
      default:
        llvm_unreachable("Unexpected SCEV op.");
      }
    }();

    const APInt &C = cast<SCEVConstant>(Ops[0])->getAPInt();

    // (A <opcode> C) --> (A <opcode> C)<nsw> if the op doesn't sign overflow.
    if (!(SignOrUnsignWrap & SCEV::FlagNSW)) {
      auto NSWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
          Opcode, C, OBO::NoSignedWrap);
      if (NSWRegion.contains(SE->getSignedRange(Ops[1])))
        Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW);
    }

    // (A <opcode> C) --> (A <opcode> C)<nuw> if the op doesn't unsign overflow.
    if (!(SignOrUnsignWrap & SCEV::FlagNUW)) {
      auto NUWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
          Opcode, C, OBO::NoUnsignedWrap);
      if (NUWRegion.contains(SE->getUnsignedRange(Ops[1])))
        Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
    }
  }

  // <0,+,nonnegative><nw> is also nuw
  // TODO: Add corresponding nsw case
  if (Type == scAddRecExpr && ScalarEvolution::hasFlags(Flags, SCEV::FlagNW) &&
      !ScalarEvolution::hasFlags(Flags, SCEV::FlagNUW) && Ops.size() == 2 &&
      Ops[0]->isZero() && IsKnownNonNegative(Ops[1]))
    Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);

  // both (udiv X, Y) * Y and Y * (udiv X, Y) are always NUW
  if (Type == scMulExpr && !ScalarEvolution::hasFlags(Flags, SCEV::FlagNUW) &&
      Ops.size() == 2) {
    if (auto *UDiv = dyn_cast<SCEVUDivExpr>(Ops[0]))
      if (UDiv->getOperand(1) == Ops[1])
        Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
    if (auto *UDiv = dyn_cast<SCEVUDivExpr>(Ops[1]))
      if (UDiv->getOperand(1) == Ops[0])
        Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
  }

  return Flags;
}

bool ScalarEvolution::isAvailableAtLoopEntry(const SCEV *S, const Loop *L) {
  return isLoopInvariant(S, L) && properlyDominates(S, L->getHeader());
}

/// Get a canonical add expression, or something simpler if possible.
const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
                                        SCEV::NoWrapFlags OrigFlags,
                                        unsigned Depth) {
  assert(!(OrigFlags & ~(SCEV::FlagNUW | SCEV::FlagNSW)) &&
         "only nuw or nsw allowed");
  assert(!Ops.empty() && "Cannot get empty add!");
  if (Ops.size() == 1) return Ops[0];
#ifndef NDEBUG
  Type *ETy = getEffectiveSCEVType(Ops[0]->getType());
  for (unsigned i = 1, e = Ops.size(); i != e; ++i)
    assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy &&
           "SCEVAddExpr operand types don't match!");
  unsigned NumPtrs = count_if(
      Ops, [](const SCEV *Op) { return Op->getType()->isPointerTy(); });
  assert(NumPtrs <= 1 && "add has at most one pointer operand");
#endif

  // Sort by complexity, this groups all similar expression types together.
  GroupByComplexity(Ops, &LI, DT);

  // If there are any constants, fold them together.
  unsigned Idx = 0;
  if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) {
    ++Idx;
    assert(Idx < Ops.size());
    while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) {
      // We found two constants, fold them together!
      Ops[0] = getConstant(LHSC->getAPInt() + RHSC->getAPInt());
      if (Ops.size() == 2) return Ops[0];
      Ops.erase(Ops.begin()+1);  // Erase the folded element
      LHSC = cast<SCEVConstant>(Ops[0]);
    }

    // If we are left with a constant zero being added, strip it off.
    if (LHSC->getValue()->isZero()) {
      Ops.erase(Ops.begin());
      --Idx;
    }

    if (Ops.size() == 1) return Ops[0];
  }

  // Delay expensive flag strengthening until necessary.
  auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) {
    return StrengthenNoWrapFlags(this, scAddExpr, Ops, OrigFlags);
  };

  // Limit recursion calls depth.
  if (Depth > MaxArithDepth || hasHugeExpression(Ops))
    return getOrCreateAddExpr(Ops, ComputeFlags(Ops));

  if (SCEV *S = findExistingSCEVInCache(scAddExpr, Ops)) {
    // Don't strengthen flags if we have no new information.
    SCEVAddExpr *Add = static_cast<SCEVAddExpr *>(S);
    if (Add->getNoWrapFlags(OrigFlags) != OrigFlags)
      Add->setNoWrapFlags(ComputeFlags(Ops));
    return S;
  }

  // Okay, check to see if the same value occurs in the operand list more than
  // once.  If so, merge them together into an multiply expression.  Since we
  // sorted the list, these values are required to be adjacent.
  Type *Ty = Ops[0]->getType();
  bool FoundMatch = false;
  for (unsigned i = 0, e = Ops.size(); i != e-1; ++i)
    if (Ops[i] == Ops[i+1]) {      //  X + Y + Y  -->  X + Y*2
      // Scan ahead to count how many equal operands there are.
      unsigned Count = 2;
      while (i+Count != e && Ops[i+Count] == Ops[i])
        ++Count;
      // Merge the values into a multiply.
      const SCEV *Scale = getConstant(Ty, Count);
      const SCEV *Mul = getMulExpr(Scale, Ops[i], SCEV::FlagAnyWrap, Depth + 1);
      if (Ops.size() == Count)
        return Mul;
      Ops[i] = Mul;
      Ops.erase(Ops.begin()+i+1, Ops.begin()+i+Count);
      --i; e -= Count - 1;
      FoundMatch = true;
    }
  if (FoundMatch)
    return getAddExpr(Ops, OrigFlags, Depth + 1);

  // Check for truncates. If all the operands are truncated from the same
  // type, see if factoring out the truncate would permit the result to be
  // folded. eg., n*trunc(x) + m*trunc(y) --> trunc(trunc(m)*x + trunc(n)*y)
  // if the contents of the resulting outer trunc fold to something simple.
  auto FindTruncSrcType = [&]() -> Type * {
    // We're ultimately looking to fold an addrec of truncs and muls of only
    // constants and truncs, so if we find any other types of SCEV
    // as operands of the addrec then we bail and return nullptr here.
    // Otherwise, we return the type of the operand of a trunc that we find.
    if (auto *T = dyn_cast<SCEVTruncateExpr>(Ops[Idx]))
      return T->getOperand()->getType();
    if (const auto *Mul = dyn_cast<SCEVMulExpr>(Ops[Idx])) {
      const auto *LastOp = Mul->getOperand(Mul->getNumOperands() - 1);
      if (const auto *T = dyn_cast<SCEVTruncateExpr>(LastOp))
        return T->getOperand()->getType();
    }
    return nullptr;
  };
  if (auto *SrcType = FindTruncSrcType()) {
    SmallVector<const SCEV *, 8> LargeOps;
    bool Ok = true;
    // Check all the operands to see if they can be represented in the
    // source type of the truncate.
    for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
      if (const SCEVTruncateExpr *T = dyn_cast<SCEVTruncateExpr>(Ops[i])) {
        if (T->getOperand()->getType() != SrcType) {
          Ok = false;
          break;
        }
        LargeOps.push_back(T->getOperand());
      } else if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Ops[i])) {
        LargeOps.push_back(getAnyExtendExpr(C, SrcType));
      } else if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Ops[i])) {
        SmallVector<const SCEV *, 8> LargeMulOps;
        for (unsigned j = 0, f = M->getNumOperands(); j != f && Ok; ++j) {
          if (const SCEVTruncateExpr *T =
                dyn_cast<SCEVTruncateExpr>(M->getOperand(j))) {
            if (T->getOperand()->getType() != SrcType) {
              Ok = false;
              break;
            }
            LargeMulOps.push_back(T->getOperand());
          } else if (const auto *C = dyn_cast<SCEVConstant>(M->getOperand(j))) {
            LargeMulOps.push_back(getAnyExtendExpr(C, SrcType));
          } else {
            Ok = false;
            break;
          }
        }
        if (Ok)
          LargeOps.push_back(getMulExpr(LargeMulOps, SCEV::FlagAnyWrap, Depth + 1));
      } else {
        Ok = false;
        break;
      }
    }
    if (Ok) {
      // Evaluate the expression in the larger type.
      const SCEV *Fold = getAddExpr(LargeOps, SCEV::FlagAnyWrap, Depth + 1);
      // If it folds to something simple, use it. Otherwise, don't.
      if (isa<SCEVConstant>(Fold) || isa<SCEVUnknown>(Fold))
        return getTruncateExpr(Fold, Ty);
    }
  }

  if (Ops.size() == 2) {
    // Check if we have an expression of the form ((X + C1) - C2), where C1 and
    // C2 can be folded in a way that allows retaining wrapping flags of (X +
    // C1).
    const SCEV *A = Ops[0];
    const SCEV *B = Ops[1];
    auto *AddExpr = dyn_cast<SCEVAddExpr>(B);
    auto *C = dyn_cast<SCEVConstant>(A);
    if (AddExpr && C && isa<SCEVConstant>(AddExpr->getOperand(0))) {
      auto C1 = cast<SCEVConstant>(AddExpr->getOperand(0))->getAPInt();
      auto C2 = C->getAPInt();
      SCEV::NoWrapFlags PreservedFlags = SCEV::FlagAnyWrap;

      APInt ConstAdd = C1 + C2;
      auto AddFlags = AddExpr->getNoWrapFlags();
      // Adding a smaller constant is NUW if the original AddExpr was NUW.
      if (ScalarEvolution::hasFlags(AddFlags, SCEV::FlagNUW) &&
          ConstAdd.ule(C1)) {
        PreservedFlags =
            ScalarEvolution::setFlags(PreservedFlags, SCEV::FlagNUW);
      }

      // Adding a constant with the same sign and small magnitude is NSW, if the
      // original AddExpr was NSW.
      if (ScalarEvolution::hasFlags(AddFlags, SCEV::FlagNSW) &&
          C1.isSignBitSet() == ConstAdd.isSignBitSet() &&
          ConstAdd.abs().ule(C1.abs())) {
        PreservedFlags =
            ScalarEvolution::setFlags(PreservedFlags, SCEV::FlagNSW);
      }

      if (PreservedFlags != SCEV::FlagAnyWrap) {
        SmallVector<const SCEV *, 4> NewOps(AddExpr->operands());
        NewOps[0] = getConstant(ConstAdd);
        return getAddExpr(NewOps, PreservedFlags);
      }
    }
  }

  // Canonicalize (-1 * urem X, Y) + X --> (Y * X/Y)
  if (Ops.size() == 2) {
    const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[0]);
    if (Mul && Mul->getNumOperands() == 2 &&
        Mul->getOperand(0)->isAllOnesValue()) {
      const SCEV *X;
      const SCEV *Y;
      if (matchURem(Mul->getOperand(1), X, Y) && X == Ops[1]) {
        return getMulExpr(Y, getUDivExpr(X, Y));
      }
    }
  }

  // Skip past any other cast SCEVs.
  while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddExpr)
    ++Idx;

  // If there are add operands they would be next.
  if (Idx < Ops.size()) {
    bool DeletedAdd = false;
    // If the original flags and all inlined SCEVAddExprs are NUW, use the
    // common NUW flag for expression after inlining. Other flags cannot be
    // preserved, because they may depend on the original order of operations.
    SCEV::NoWrapFlags CommonFlags = maskFlags(OrigFlags, SCEV::FlagNUW);
    while (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[Idx])) {
      if (Ops.size() > AddOpsInlineThreshold ||
          Add->getNumOperands() > AddOpsInlineThreshold)
        break;
      // If we have an add, expand the add operands onto the end of the operands
      // list.
      Ops.erase(Ops.begin()+Idx);
      append_range(Ops, Add->operands());
      DeletedAdd = true;
      CommonFlags = maskFlags(CommonFlags, Add->getNoWrapFlags());
    }

    // If we deleted at least one add, we added operands to the end of the list,
    // and they are not necessarily sorted.  Recurse to resort and resimplify
    // any operands we just acquired.
    if (DeletedAdd)
      return getAddExpr(Ops, CommonFlags, Depth + 1);
  }

  // Skip over the add expression until we get to a multiply.
  while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scMulExpr)
    ++Idx;

  // Check to see if there are any folding opportunities present with
  // operands multiplied by constant values.
  if (Idx < Ops.size() && isa<SCEVMulExpr>(Ops[Idx])) {
    uint64_t BitWidth = getTypeSizeInBits(Ty);
    DenseMap<const SCEV *, APInt> M;
    SmallVector<const SCEV *, 8> NewOps;
    APInt AccumulatedConstant(BitWidth, 0);
    if (CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant,
                                     Ops, APInt(BitWidth, 1), *this)) {
      struct APIntCompare {
        bool operator()(const APInt &LHS, const APInt &RHS) const {
          return LHS.ult(RHS);
        }
      };

      // Some interesting folding opportunity is present, so its worthwhile to
      // re-generate the operands list. Group the operands by constant scale,
      // to avoid multiplying by the same constant scale multiple times.
      std::map<APInt, SmallVector<const SCEV *, 4>, APIntCompare> MulOpLists;
      for (const SCEV *NewOp : NewOps)
        MulOpLists[M.find(NewOp)->second].push_back(NewOp);
      // Re-generate the operands list.
      Ops.clear();
      if (AccumulatedConstant != 0)
        Ops.push_back(getConstant(AccumulatedConstant));
      for (auto &MulOp : MulOpLists) {
        if (MulOp.first == 1) {
          Ops.push_back(getAddExpr(MulOp.second, SCEV::FlagAnyWrap, Depth + 1));
        } else if (MulOp.first != 0) {
          Ops.push_back(getMulExpr(
              getConstant(MulOp.first),
              getAddExpr(MulOp.second, SCEV::FlagAnyWrap, Depth + 1),
              SCEV::FlagAnyWrap, Depth + 1));
        }
      }
      if (Ops.empty())
        return getZero(Ty);
      if (Ops.size() == 1)
        return Ops[0];
      return getAddExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
    }
  }

  // If we are adding something to a multiply expression, make sure the
  // something is not already an operand of the multiply.  If so, merge it into
  // the multiply.
  for (; Idx < Ops.size() && isa<SCEVMulExpr>(Ops[Idx]); ++Idx) {
    const SCEVMulExpr *Mul = cast<SCEVMulExpr>(Ops[Idx]);
    for (unsigned MulOp = 0, e = Mul->getNumOperands(); MulOp != e; ++MulOp) {
      const SCEV *MulOpSCEV = Mul->getOperand(MulOp);
      if (isa<SCEVConstant>(MulOpSCEV))
        continue;
      for (unsigned AddOp = 0, e = Ops.size(); AddOp != e; ++AddOp)
        if (MulOpSCEV == Ops[AddOp]) {
          // Fold W + X + (X * Y * Z)  -->  W + (X * ((Y*Z)+1))
          const SCEV *InnerMul = Mul->getOperand(MulOp == 0);
          if (Mul->getNumOperands() != 2) {
            // If the multiply has more than two operands, we must get the
            // Y*Z term.
            SmallVector<const SCEV *, 4> MulOps(
                Mul->operands().take_front(MulOp));
            append_range(MulOps, Mul->operands().drop_front(MulOp + 1));
            InnerMul = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
          }
          SmallVector<const SCEV *, 2> TwoOps = {getOne(Ty), InnerMul};
          const SCEV *AddOne = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
          const SCEV *OuterMul = getMulExpr(AddOne, MulOpSCEV,
                                            SCEV::FlagAnyWrap, Depth + 1);
          if (Ops.size() == 2) return OuterMul;
          if (AddOp < Idx) {
            Ops.erase(Ops.begin()+AddOp);
            Ops.erase(Ops.begin()+Idx-1);
          } else {
            Ops.erase(Ops.begin()+Idx);
            Ops.erase(Ops.begin()+AddOp-1);
          }
          Ops.push_back(OuterMul);
          return getAddExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
        }

      // Check this multiply against other multiplies being added together.
      for (unsigned OtherMulIdx = Idx+1;
           OtherMulIdx < Ops.size() && isa<SCEVMulExpr>(Ops[OtherMulIdx]);
           ++OtherMulIdx) {
        const SCEVMulExpr *OtherMul = cast<SCEVMulExpr>(Ops[OtherMulIdx]);
        // If MulOp occurs in OtherMul, we can fold the two multiplies
        // together.
        for (unsigned OMulOp = 0, e = OtherMul->getNumOperands();
             OMulOp != e; ++OMulOp)
          if (OtherMul->getOperand(OMulOp) == MulOpSCEV) {
            // Fold X + (A*B*C) + (A*D*E) --> X + (A*(B*C+D*E))
            const SCEV *InnerMul1 = Mul->getOperand(MulOp == 0);
            if (Mul->getNumOperands() != 2) {
              SmallVector<const SCEV *, 4> MulOps(
                  Mul->operands().take_front(MulOp));
              append_range(MulOps, Mul->operands().drop_front(MulOp+1));
              InnerMul1 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
            }
            const SCEV *InnerMul2 = OtherMul->getOperand(OMulOp == 0);
            if (OtherMul->getNumOperands() != 2) {
              SmallVector<const SCEV *, 4> MulOps(
                  OtherMul->operands().take_front(OMulOp));
              append_range(MulOps, OtherMul->operands().drop_front(OMulOp+1));
              InnerMul2 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
            }
            SmallVector<const SCEV *, 2> TwoOps = {InnerMul1, InnerMul2};
            const SCEV *InnerMulSum =
                getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
            const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum,
                                              SCEV::FlagAnyWrap, Depth + 1);
            if (Ops.size() == 2) return OuterMul;
            Ops.erase(Ops.begin()+Idx);
            Ops.erase(Ops.begin()+OtherMulIdx-1);
            Ops.push_back(OuterMul);
            return getAddExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
          }
      }
    }
  }

  // If there are any add recurrences in the operands list, see if any other
  // added values are loop invariant.  If so, we can fold them into the
  // recurrence.
  while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddRecExpr)
    ++Idx;

  // Scan over all recurrences, trying to fold loop invariants into them.
  for (; Idx < Ops.size() && isa<SCEVAddRecExpr>(Ops[Idx]); ++Idx) {
    // Scan all of the other operands to this add and add them to the vector if
    // they are loop invariant w.r.t. the recurrence.
    SmallVector<const SCEV *, 8> LIOps;
    const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
    const Loop *AddRecLoop = AddRec->getLoop();
    for (unsigned i = 0, e = Ops.size(); i != e; ++i)
      if (isAvailableAtLoopEntry(Ops[i], AddRecLoop)) {
        LIOps.push_back(Ops[i]);
        Ops.erase(Ops.begin()+i);
        --i; --e;
      }

    // If we found some loop invariants, fold them into the recurrence.
    if (!LIOps.empty()) {
      // Compute nowrap flags for the addition of the loop-invariant ops and
      // the addrec. Temporarily push it as an operand for that purpose. These
      // flags are valid in the scope of the addrec only.
      LIOps.push_back(AddRec);
      SCEV::NoWrapFlags Flags = ComputeFlags(LIOps);
      LIOps.pop_back();

      //  NLI + LI + {Start,+,Step}  -->  NLI + {LI+Start,+,Step}
      LIOps.push_back(AddRec->getStart());

      SmallVector<const SCEV *, 4> AddRecOps(AddRec->operands());

      // It is not in general safe to propagate flags valid on an add within
      // the addrec scope to one outside it.  We must prove that the inner
      // scope is guaranteed to execute if the outer one does to be able to
      // safely propagate.  We know the program is undefined if poison is
      // produced on the inner scoped addrec.  We also know that *for this use*
      // the outer scoped add can't overflow (because of the flags we just
      // computed for the inner scoped add) without the program being undefined.
      // Proving that entry to the outer scope neccesitates entry to the inner
      // scope, thus proves the program undefined if the flags would be violated
      // in the outer scope.
      SCEV::NoWrapFlags AddFlags = Flags;
      if (AddFlags != SCEV::FlagAnyWrap) {
        auto *DefI = getDefiningScopeBound(LIOps);
        auto *ReachI = &*AddRecLoop->getHeader()->begin();
        if (!isGuaranteedToTransferExecutionTo(DefI, ReachI))
          AddFlags = SCEV::FlagAnyWrap;
      }
      AddRecOps[0] = getAddExpr(LIOps, AddFlags, Depth + 1);

      // Build the new addrec. Propagate the NUW and NSW flags if both the
      // outer add and the inner addrec are guaranteed to have no overflow.
      // Always propagate NW.
      Flags = AddRec->getNoWrapFlags(setFlags(Flags, SCEV::FlagNW));
      const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRecLoop, Flags);

      // If all of the other operands were loop invariant, we are done.
      if (Ops.size() == 1) return NewRec;

      // Otherwise, add the folded AddRec by the non-invariant parts.
      for (unsigned i = 0;; ++i)
        if (Ops[i] == AddRec) {
          Ops[i] = NewRec;
          break;
        }
      return getAddExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
    }

    // Okay, if there weren't any loop invariants to be folded, check to see if
    // there are multiple AddRec's with the same loop induction variable being
    // added together.  If so, we can fold them.
    for (unsigned OtherIdx = Idx+1;
         OtherIdx < Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
         ++OtherIdx) {
      // We expect the AddRecExpr's to be sorted in reverse dominance order,
      // so that the 1st found AddRecExpr is dominated by all others.
      assert(DT.dominates(
           cast<SCEVAddRecExpr>(Ops[OtherIdx])->getLoop()->getHeader(),
           AddRec->getLoop()->getHeader()) &&
        "AddRecExprs are not sorted in reverse dominance order?");
      if (AddRecLoop == cast<SCEVAddRecExpr>(Ops[OtherIdx])->getLoop()) {
        // Other + {A,+,B}<L> + {C,+,D}<L>  -->  Other + {A+C,+,B+D}<L>
        SmallVector<const SCEV *, 4> AddRecOps(AddRec->operands());
        for (; OtherIdx != Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
             ++OtherIdx) {
          const auto *OtherAddRec = cast<SCEVAddRecExpr>(Ops[OtherIdx]);
          if (OtherAddRec->getLoop() == AddRecLoop) {
            for (unsigned i = 0, e = OtherAddRec->getNumOperands();
                 i != e; ++i) {
              if (i >= AddRecOps.size()) {
                append_range(AddRecOps, OtherAddRec->operands().drop_front(i));
                break;
              }
              SmallVector<const SCEV *, 2> TwoOps = {
                  AddRecOps[i], OtherAddRec->getOperand(i)};
              AddRecOps[i] = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
            }
            Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
          }
        }
        // Step size has changed, so we cannot guarantee no self-wraparound.
        Ops[Idx] = getAddRecExpr(AddRecOps, AddRecLoop, SCEV::FlagAnyWrap);
        return getAddExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
      }
    }

    // Otherwise couldn't fold anything into this recurrence.  Move onto the
    // next one.
  }

  // Okay, it looks like we really DO need an add expr.  Check to see if we
  // already have one, otherwise create a new one.
  return getOrCreateAddExpr(Ops, ComputeFlags(Ops));
}

const SCEV *
ScalarEvolution::getOrCreateAddExpr(ArrayRef<const SCEV *> Ops,
                                    SCEV::NoWrapFlags Flags) {
  FoldingSetNodeID ID;
  ID.AddInteger(scAddExpr);
  for (const SCEV *Op : Ops)
    ID.AddPointer(Op);
  void *IP = nullptr;
  SCEVAddExpr *S =
      static_cast<SCEVAddExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
  if (!S) {
    const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
    std::uninitialized_copy(Ops.begin(), Ops.end(), O);
    S = new (SCEVAllocator)
        SCEVAddExpr(ID.Intern(SCEVAllocator), O, Ops.size());
    UniqueSCEVs.InsertNode(S, IP);
    registerUser(S, Ops);
  }
  S->setNoWrapFlags(Flags);
  return S;
}

const SCEV *
ScalarEvolution::getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops,
                                       const Loop *L, SCEV::NoWrapFlags Flags) {
  FoldingSetNodeID ID;
  ID.AddInteger(scAddRecExpr);
  for (const SCEV *Op : Ops)
    ID.AddPointer(Op);
  ID.AddPointer(L);
  void *IP = nullptr;
  SCEVAddRecExpr *S =
      static_cast<SCEVAddRecExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
  if (!S) {
    const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
    std::uninitialized_copy(Ops.begin(), Ops.end(), O);
    S = new (SCEVAllocator)
        SCEVAddRecExpr(ID.Intern(SCEVAllocator), O, Ops.size(), L);
    UniqueSCEVs.InsertNode(S, IP);
    LoopUsers[L].push_back(S);
    registerUser(S, Ops);
  }
  setNoWrapFlags(S, Flags);
  return S;
}

const SCEV *
ScalarEvolution::getOrCreateMulExpr(ArrayRef<const SCEV *> Ops,
                                    SCEV::NoWrapFlags Flags) {
  FoldingSetNodeID ID;
  ID.AddInteger(scMulExpr);
  for (const SCEV *Op : Ops)
    ID.AddPointer(Op);
  void *IP = nullptr;
  SCEVMulExpr *S =
    static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
  if (!S) {
    const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
    std::uninitialized_copy(Ops.begin(), Ops.end(), O);
    S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator),
                                        O, Ops.size());
    UniqueSCEVs.InsertNode(S, IP);
    registerUser(S, Ops);
  }
  S->setNoWrapFlags(Flags);
  return S;
}

static uint64_t umul_ov(uint64_t i, uint64_t j, bool &Overflow) {
  uint64_t k = i*j;
  if (j > 1 && k / j != i) Overflow = true;
  return k;
}

/// Compute the result of "n choose k", the binomial coefficient.  If an
/// intermediate computation overflows, Overflow will be set and the return will
/// be garbage. Overflow is not cleared on absence of overflow.
static uint64_t Choose(uint64_t n, uint64_t k, bool &Overflow) {
  // We use the multiplicative formula:
  //     n(n-1)(n-2)...(n-(k-1)) / k(k-1)(k-2)...1 .
  // At each iteration, we take the n-th term of the numeral and divide by the
  // (k-n)th term of the denominator.  This division will always produce an
  // integral result, and helps reduce the chance of overflow in the
  // intermediate computations. However, we can still overflow even when the
  // final result would fit.

  if (n == 0 || n == k) return 1;
  if (k > n) return 0;

  if (k > n/2)
    k = n-k;

  uint64_t r = 1;
  for (uint64_t i = 1; i <= k; ++i) {
    r = umul_ov(r, n-(i-1), Overflow);
    r /= i;
  }
  return r;
}

/// Determine if any of the operands in this SCEV are a constant or if
/// any of the add or multiply expressions in this SCEV contain a constant.
static bool containsConstantInAddMulChain(const SCEV *StartExpr) {
  struct FindConstantInAddMulChain {
    bool FoundConstant = false;

    bool follow(const SCEV *S) {
      FoundConstant |= isa<SCEVConstant>(S);
      return isa<SCEVAddExpr>(S) || isa<SCEVMulExpr>(S);
    }

    bool isDone() const {
      return FoundConstant;
    }
  };

  FindConstantInAddMulChain F;
  SCEVTraversal<FindConstantInAddMulChain> ST(F);
  ST.visitAll(StartExpr);
  return F.FoundConstant;
}

/// Get a canonical multiply expression, or something simpler if possible.
const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
                                        SCEV::NoWrapFlags OrigFlags,
                                        unsigned Depth) {
  assert(OrigFlags == maskFlags(OrigFlags, SCEV::FlagNUW | SCEV::FlagNSW) &&
         "only nuw or nsw allowed");
  assert(!Ops.empty() && "Cannot get empty mul!");
  if (Ops.size() == 1) return Ops[0];
#ifndef NDEBUG
  Type *ETy = Ops[0]->getType();
  assert(!ETy->isPointerTy());
  for (unsigned i = 1, e = Ops.size(); i != e; ++i)
    assert(Ops[i]->getType() == ETy &&
           "SCEVMulExpr operand types don't match!");
#endif

  // Sort by complexity, this groups all similar expression types together.
  GroupByComplexity(Ops, &LI, DT);

  // If there are any constants, fold them together.
  unsigned Idx = 0;
  if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) {
    ++Idx;
    assert(Idx < Ops.size());
    while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) {
      // We found two constants, fold them together!
      Ops[0] = getConstant(LHSC->getAPInt() * RHSC->getAPInt());
      if (Ops.size() == 2) return Ops[0];
      Ops.erase(Ops.begin()+1);  // Erase the folded element
      LHSC = cast<SCEVConstant>(Ops[0]);
    }

    // If we have a multiply of zero, it will always be zero.
    if (LHSC->getValue()->isZero())
      return LHSC;

    // If we are left with a constant one being multiplied, strip it off.
    if (LHSC->getValue()->isOne()) {
      Ops.erase(Ops.begin());
      --Idx;
    }

    if (Ops.size() == 1)
      return Ops[0];
  }

  // Delay expensive flag strengthening until necessary.
  auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) {
    return StrengthenNoWrapFlags(this, scMulExpr, Ops, OrigFlags);
  };

  // Limit recursion calls depth.
  if (Depth > MaxArithDepth || hasHugeExpression(Ops))
    return getOrCreateMulExpr(Ops, ComputeFlags(Ops));

  if (SCEV *S = findExistingSCEVInCache(scMulExpr, Ops)) {
    // Don't strengthen flags if we have no new information.
    SCEVMulExpr *Mul = static_cast<SCEVMulExpr *>(S);
    if (Mul->getNoWrapFlags(OrigFlags) != OrigFlags)
      Mul->setNoWrapFlags(ComputeFlags(Ops));
    return S;
  }

  if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) {
    if (Ops.size() == 2) {
      // C1*(C2+V) -> C1*C2 + C1*V
      if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1]))
        // If any of Add's ops are Adds or Muls with a constant, apply this
        // transformation as well.
        //
        // TODO: There are some cases where this transformation is not
        // profitable; for example, Add = (C0 + X) * Y + Z.  Maybe the scope of
        // this transformation should be narrowed down.
        if (Add->getNumOperands() == 2 && containsConstantInAddMulChain(Add)) {
          const SCEV *LHS = getMulExpr(LHSC, Add->getOperand(0),
                                       SCEV::FlagAnyWrap, Depth + 1);
          const SCEV *RHS = getMulExpr(LHSC, Add->getOperand(1),
                                       SCEV::FlagAnyWrap, Depth + 1);
          return getAddExpr(LHS, RHS, SCEV::FlagAnyWrap, Depth + 1);
        }

      if (Ops[0]->isAllOnesValue()) {
        // If we have a mul by -1 of an add, try distributing the -1 among the
        // add operands.
        if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1])) {
          SmallVector<const SCEV *, 4> NewOps;
          bool AnyFolded = false;
          for (const SCEV *AddOp : Add->operands()) {
            const SCEV *Mul = getMulExpr(Ops[0], AddOp, SCEV::FlagAnyWrap,
                                         Depth + 1);
            if (!isa<SCEVMulExpr>(Mul)) AnyFolded = true;
            NewOps.push_back(Mul);
          }
          if (AnyFolded)
            return getAddExpr(NewOps, SCEV::FlagAnyWrap, Depth + 1);
        } else if (const auto *AddRec = dyn_cast<SCEVAddRecExpr>(Ops[1])) {
          // Negation preserves a recurrence's no self-wrap property.
          SmallVector<const SCEV *, 4> Operands;
          for (const SCEV *AddRecOp : AddRec->operands())
            Operands.push_back(getMulExpr(Ops[0], AddRecOp, SCEV::FlagAnyWrap,
                                          Depth + 1));
          // Let M be the minimum representable signed value. AddRec with nsw
          // multiplied by -1 can have signed overflow if and only if it takes a
          // value of M: M * (-1) would stay M and (M + 1) * (-1) would be the
          // maximum signed value. In all other cases signed overflow is
          // impossible.
          auto FlagsMask = SCEV::FlagNW;
          if (hasFlags(AddRec->getNoWrapFlags(), SCEV::FlagNSW)) {
            auto MinInt =
                APInt::getSignedMinValue(getTypeSizeInBits(AddRec->getType()));
            if (getSignedRangeMin(AddRec) != MinInt)
              FlagsMask = setFlags(FlagsMask, SCEV::FlagNSW);
          }
          return getAddRecExpr(Operands, AddRec->getLoop(),
                               AddRec->getNoWrapFlags(FlagsMask));
        }
      }
    }
  }

  // Skip over the add expression until we get to a multiply.
  while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scMulExpr)
    ++Idx;

  // If there are mul operands inline them all into this expression.
  if (Idx < Ops.size()) {
    bool DeletedMul = false;
    while (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[Idx])) {
      if (Ops.size() > MulOpsInlineThreshold)
        break;
      // If we have an mul, expand the mul operands onto the end of the
      // operands list.
      Ops.erase(Ops.begin()+Idx);
      append_range(Ops, Mul->operands());
      DeletedMul = true;
    }

    // If we deleted at least one mul, we added operands to the end of the
    // list, and they are not necessarily sorted.  Recurse to resort and
    // resimplify any operands we just acquired.
    if (DeletedMul)
      return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
  }

  // If there are any add recurrences in the operands list, see if any other
  // added values are loop invariant.  If so, we can fold them into the
  // recurrence.
  while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddRecExpr)
    ++Idx;

  // Scan over all recurrences, trying to fold loop invariants into them.
  for (; Idx < Ops.size() && isa<SCEVAddRecExpr>(Ops[Idx]); ++Idx) {
    // Scan all of the other operands to this mul and add them to the vector
    // if they are loop invariant w.r.t. the recurrence.
    SmallVector<const SCEV *, 8> LIOps;
    const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
    for (unsigned i = 0, e = Ops.size(); i != e; ++i)
      if (isAvailableAtLoopEntry(Ops[i], AddRec->getLoop())) {
        LIOps.push_back(Ops[i]);
        Ops.erase(Ops.begin()+i);
        --i; --e;
      }

    // If we found some loop invariants, fold them into the recurrence.
    if (!LIOps.empty()) {
      //  NLI * LI * {Start,+,Step}  -->  NLI * {LI*Start,+,LI*Step}
      SmallVector<const SCEV *, 4> NewOps;
      NewOps.reserve(AddRec->getNumOperands());
      const SCEV *Scale = getMulExpr(LIOps, SCEV::FlagAnyWrap, Depth + 1);
      for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i)
        NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i),
                                    SCEV::FlagAnyWrap, Depth + 1));

      // Build the new addrec. Propagate the NUW and NSW flags if both the
      // outer mul and the inner addrec are guaranteed to have no overflow.
      //
      // No self-wrap cannot be guaranteed after changing the step size, but
      // will be inferred if either NUW or NSW is true.
      SCEV::NoWrapFlags Flags = ComputeFlags({Scale, AddRec});
      const SCEV *NewRec = getAddRecExpr(
          NewOps, AddRec->getLoop(), AddRec->getNoWrapFlags(Flags));

      // If all of the other operands were loop invariant, we are done.
      if (Ops.size() == 1) return NewRec;

      // Otherwise, multiply the folded AddRec by the non-invariant parts.
      for (unsigned i = 0;; ++i)
        if (Ops[i] == AddRec) {
          Ops[i] = NewRec;
          break;
        }
      return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
    }

    // Okay, if there weren't any loop invariants to be folded, check to see
    // if there are multiple AddRec's with the same loop induction variable
    // being multiplied together.  If so, we can fold them.

    // {A1,+,A2,+,...,+,An}<L> * {B1,+,B2,+,...,+,Bn}<L>
    // = {x=1 in [ sum y=x..2x [ sum z=max(y-x, y-n)..min(x,n) [
    //       choose(x, 2x)*choose(2x-y, x-z)*A_{y-z}*B_z
    //   ]]],+,...up to x=2n}.
    // Note that the arguments to choose() are always integers with values
    // known at compile time, never SCEV objects.
    //
    // The implementation avoids pointless extra computations when the two
    // addrec's are of different length (mathematically, it's equivalent to
    // an infinite stream of zeros on the right).
    bool OpsModified = false;
    for (unsigned OtherIdx = Idx+1;
         OtherIdx != Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
         ++OtherIdx) {
      const SCEVAddRecExpr *OtherAddRec =
        dyn_cast<SCEVAddRecExpr>(Ops[OtherIdx]);
      if (!OtherAddRec || OtherAddRec->getLoop() != AddRec->getLoop())
        continue;

      // Limit max number of arguments to avoid creation of unreasonably big
      // SCEVAddRecs with very complex operands.
      if (AddRec->getNumOperands() + OtherAddRec->getNumOperands() - 1 >
          MaxAddRecSize || hasHugeExpression({AddRec, OtherAddRec}))
        continue;

      bool Overflow = false;
      Type *Ty = AddRec->getType();
      bool LargerThan64Bits = getTypeSizeInBits(Ty) > 64;
      SmallVector<const SCEV*, 7> AddRecOps;
      for (int x = 0, xe = AddRec->getNumOperands() +
             OtherAddRec->getNumOperands() - 1; x != xe && !Overflow; ++x) {
        SmallVector <const SCEV *, 7> SumOps;
        for (int y = x, ye = 2*x+1; y != ye && !Overflow; ++y) {
          uint64_t Coeff1 = Choose(x, 2*x - y, Overflow);
          for (int z = std::max(y-x, y-(int)AddRec->getNumOperands()+1),
                 ze = std::min(x+1, (int)OtherAddRec->getNumOperands());
               z < ze && !Overflow; ++z) {
            uint64_t Coeff2 = Choose(2*x - y, x-z, Overflow);
            uint64_t Coeff;
            if (LargerThan64Bits)
              Coeff = umul_ov(Coeff1, Coeff2, Overflow);
            else
              Coeff = Coeff1*Coeff2;
            const SCEV *CoeffTerm = getConstant(Ty, Coeff);
            const SCEV *Term1 = AddRec->getOperand(y-z);
            const SCEV *Term2 = OtherAddRec->getOperand(z);
            SumOps.push_back(getMulExpr(CoeffTerm, Term1, Term2,
                                        SCEV::FlagAnyWrap, Depth + 1));
          }
        }
        if (SumOps.empty())
          SumOps.push_back(getZero(Ty));
        AddRecOps.push_back(getAddExpr(SumOps, SCEV::FlagAnyWrap, Depth + 1));
      }
      if (!Overflow) {
        const SCEV *NewAddRec = getAddRecExpr(AddRecOps, AddRec->getLoop(),
                                              SCEV::FlagAnyWrap);
        if (Ops.size() == 2) return NewAddRec;
        Ops[Idx] = NewAddRec;
        Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
        OpsModified = true;
        AddRec = dyn_cast<SCEVAddRecExpr>(NewAddRec);
        if (!AddRec)
          break;
      }
    }
    if (OpsModified)
      return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);

    // Otherwise couldn't fold anything into this recurrence.  Move onto the
    // next one.
  }

  // Okay, it looks like we really DO need an mul expr.  Check to see if we
  // already have one, otherwise create a new one.
  return getOrCreateMulExpr(Ops, ComputeFlags(Ops));
}

/// Represents an unsigned remainder expression based on unsigned division.
const SCEV *ScalarEvolution::getURemExpr(const SCEV *LHS,
                                         const SCEV *RHS) {
  assert(getEffectiveSCEVType(LHS->getType()) ==
         getEffectiveSCEVType(RHS->getType()) &&
         "SCEVURemExpr operand types don't match!");

  // Short-circuit easy cases
  if (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
    // If constant is one, the result is trivial
    if (RHSC->getValue()->isOne())
      return getZero(LHS->getType()); // X urem 1 --> 0

    // If constant is a power of two, fold into a zext(trunc(LHS)).
    if (RHSC->getAPInt().isPowerOf2()) {
      Type *FullTy = LHS->getType();
      Type *TruncTy =
          IntegerType::get(getContext(), RHSC->getAPInt().logBase2());
      return getZeroExtendExpr(getTruncateExpr(LHS, TruncTy), FullTy);
    }
  }

  // Fallback to %a == %x urem %y == %x -<nuw> ((%x udiv %y) *<nuw> %y)
  const SCEV *UDiv = getUDivExpr(LHS, RHS);
  const SCEV *Mult = getMulExpr(UDiv, RHS, SCEV::FlagNUW);
  return getMinusSCEV(LHS, Mult, SCEV::FlagNUW);
}

/// Get a canonical unsigned division expression, or something simpler if
/// possible.
const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
                                         const SCEV *RHS) {
  assert(!LHS->getType()->isPointerTy() &&
         "SCEVUDivExpr operand can't be pointer!");
  assert(LHS->getType() == RHS->getType() &&
         "SCEVUDivExpr operand types don't match!");

  FoldingSetNodeID ID;
  ID.AddInteger(scUDivExpr);
  ID.AddPointer(LHS);
  ID.AddPointer(RHS);
  void *IP = nullptr;
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
    return S;

  // 0 udiv Y == 0
  if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS))
    if (LHSC->getValue()->isZero())
      return LHS;

  if (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
    if (RHSC->getValue()->isOne())
      return LHS;                               // X udiv 1 --> x
    // If the denominator is zero, the result of the udiv is undefined. Don't
    // try to analyze it, because the resolution chosen here may differ from
    // the resolution chosen in other parts of the compiler.
    if (!RHSC->getValue()->isZero()) {
      // Determine if the division can be folded into the operands of
      // its operands.
      // TODO: Generalize this to non-constants by using known-bits information.
      Type *Ty = LHS->getType();
      unsigned LZ = RHSC->getAPInt().countl_zero();
      unsigned MaxShiftAmt = getTypeSizeInBits(Ty) - LZ - 1;
      // For non-power-of-two values, effectively round the value up to the
      // nearest power of two.
      if (!RHSC->getAPInt().isPowerOf2())
        ++MaxShiftAmt;
      IntegerType *ExtTy =
        IntegerType::get(getContext(), getTypeSizeInBits(Ty) + MaxShiftAmt);
      if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(LHS))
        if (const SCEVConstant *Step =
            dyn_cast<SCEVConstant>(AR->getStepRecurrence(*this))) {
          // {X,+,N}/C --> {X/C,+,N/C} if safe and N/C can be folded.
          const APInt &StepInt = Step->getAPInt();
          const APInt &DivInt = RHSC->getAPInt();
          if (!StepInt.urem(DivInt) &&
              getZeroExtendExpr(AR, ExtTy) ==
              getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
                            getZeroExtendExpr(Step, ExtTy),
                            AR->getLoop(), SCEV::FlagAnyWrap)) {
            SmallVector<const SCEV *, 4> Operands;
            for (const SCEV *Op : AR->operands())
              Operands.push_back(getUDivExpr(Op, RHS));
            return getAddRecExpr(Operands, AR->getLoop(), SCEV::FlagNW);
          }
          /// Get a canonical UDivExpr for a recurrence.
          /// {X,+,N}/C => {Y,+,N}/C where Y=X-(X%N). Safe when C%N=0.
          // We can currently only fold X%N if X is constant.
          const SCEVConstant *StartC = dyn_cast<SCEVConstant>(AR->getStart());
          if (StartC && !DivInt.urem(StepInt) &&
              getZeroExtendExpr(AR, ExtTy) ==
              getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
                            getZeroExtendExpr(Step, ExtTy),
                            AR->getLoop(), SCEV::FlagAnyWrap)) {
            const APInt &StartInt = StartC->getAPInt();
            const APInt &StartRem = StartInt.urem(StepInt);
            if (StartRem != 0) {
              const SCEV *NewLHS =
                  getAddRecExpr(getConstant(StartInt - StartRem), Step,
                                AR->getLoop(), SCEV::FlagNW);
              if (LHS != NewLHS) {
                LHS = NewLHS;

                // Reset the ID to include the new LHS, and check if it is
                // already cached.
                ID.clear();
                ID.AddInteger(scUDivExpr);
                ID.AddPointer(LHS);
                ID.AddPointer(RHS);
                IP = nullptr;
                if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
                  return S;
              }
            }
          }
        }
      // (A*B)/C --> A*(B/C) if safe and B/C can be folded.
      if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(LHS)) {
        SmallVector<const SCEV *, 4> Operands;
        for (const SCEV *Op : M->operands())
          Operands.push_back(getZeroExtendExpr(Op, ExtTy));
        if (getZeroExtendExpr(M, ExtTy) == getMulExpr(Operands))
          // Find an operand that's safely divisible.
          for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) {
            const SCEV *Op = M->getOperand(i);
            const SCEV *Div = getUDivExpr(Op, RHSC);
            if (!isa<SCEVUDivExpr>(Div) && getMulExpr(Div, RHSC) == Op) {
              Operands = SmallVector<const SCEV *, 4>(M->operands());
              Operands[i] = Div;
              return getMulExpr(Operands);
            }
          }
      }

      // (A/B)/C --> A/(B*C) if safe and B*C can be folded.
      if (const SCEVUDivExpr *OtherDiv = dyn_cast<SCEVUDivExpr>(LHS)) {
        if (auto *DivisorConstant =
                dyn_cast<SCEVConstant>(OtherDiv->getRHS())) {
          bool Overflow = false;
          APInt NewRHS =
              DivisorConstant->getAPInt().umul_ov(RHSC->getAPInt(), Overflow);
          if (Overflow) {
            return getConstant(RHSC->getType(), 0, false);
          }
          return getUDivExpr(OtherDiv->getLHS(), getConstant(NewRHS));
        }
      }

      // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded.
      if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(LHS)) {
        SmallVector<const SCEV *, 4> Operands;
        for (const SCEV *Op : A->operands())
          Operands.push_back(getZeroExtendExpr(Op, ExtTy));
        if (getZeroExtendExpr(A, ExtTy) == getAddExpr(Operands)) {
          Operands.clear();
          for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) {
            const SCEV *Op = getUDivExpr(A->getOperand(i), RHS);
            if (isa<SCEVUDivExpr>(Op) ||
                getMulExpr(Op, RHS) != A->getOperand(i))
              break;
            Operands.push_back(Op);
          }
          if (Operands.size() == A->getNumOperands())
            return getAddExpr(Operands);
        }
      }

      // Fold if both operands are constant.
      if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS))
        return getConstant(LHSC->getAPInt().udiv(RHSC->getAPInt()));
    }
  }

  // The Insertion Point (IP) might be invalid by now (due to UniqueSCEVs
  // changes). Make sure we get a new one.
  IP = nullptr;
  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
  SCEV *S = new (SCEVAllocator) SCEVUDivExpr(ID.Intern(SCEVAllocator),
                                             LHS, RHS);
  UniqueSCEVs.InsertNode(S, IP);
  registerUser(S, {LHS, RHS});
  return S;
}

APInt gcd(const SCEVConstant *C1, const SCEVConstant *C2) {
  APInt A = C1->getAPInt().abs();
  APInt B = C2->getAPInt().abs();
  uint32_t ABW = A.getBitWidth();
  uint32_t BBW = B.getBitWidth();

  if (ABW > BBW)
    B = B.zext(ABW);
  else if (ABW < BBW)
    A = A.zext(BBW);

  return APIntOps::GreatestCommonDivisor(std::move(A), std::move(B));
}

/// Get a canonical unsigned division expression, or something simpler if
/// possible. There is no representation for an exact udiv in SCEV IR, but we
/// can attempt to remove factors from the LHS and RHS.  We can't do this when
/// it's not exact because the udiv may be clearing bits.
const SCEV *ScalarEvolution::getUDivExactExpr(const SCEV *LHS,
                                              const SCEV *RHS) {
  // TODO: we could try to find factors in all sorts of things, but for now we
  // just deal with u/exact (multiply, constant). See SCEVDivision towards the
  // end of this file for inspiration.

  const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(LHS);
  if (!Mul || !Mul->hasNoUnsignedWrap())
    return getUDivExpr(LHS, RHS);

  if (const SCEVConstant *RHSCst = dyn_cast<SCEVConstant>(RHS)) {
    // If the mulexpr multiplies by a constant, then that constant must be the
    // first element of the mulexpr.
    if (const auto *LHSCst = dyn_cast<SCEVConstant>(Mul->getOperand(0))) {
      if (LHSCst == RHSCst) {
        SmallVector<const SCEV *, 2> Operands(drop_begin(Mul->operands()));
        return getMulExpr(Operands);
      }

      // We can't just assume that LHSCst divides RHSCst cleanly, it could be
      // that there's a factor provided by one of the other terms. We need to
      // check.
      APInt Factor = gcd(LHSCst, RHSCst);
      if (!Factor.isIntN(1)) {
        LHSCst =
            cast<SCEVConstant>(getConstant(LHSCst->getAPInt().udiv(Factor)));
        RHSCst =
            cast<SCEVConstant>(getConstant(RHSCst->getAPInt().udiv(Factor)));
        SmallVector<const SCEV *, 2> Operands;
        Operands.push_back(LHSCst);
        append_range(Operands, Mul->operands().drop_front());
        LHS = getMulExpr(Operands);
        RHS = RHSCst;
        Mul = dyn_cast<SCEVMulExpr>(LHS);
        if (!Mul)
          return getUDivExactExpr(LHS, RHS);
      }
    }
  }

  for (int i = 0, e = Mul->getNumOperands(); i != e; ++i) {
    if (Mul->getOperand(i) == RHS) {
      SmallVector<const SCEV *, 2> Operands;
      append_range(Operands, Mul->operands().take_front(i));
      append_range(Operands, Mul->operands().drop_front(i + 1));
      return getMulExpr(Operands);
    }
  }

  return getUDivExpr(LHS, RHS);
}

/// Get an add recurrence expression for the specified loop.  Simplify the
/// expression as much as possible.
const SCEV *ScalarEvolution::getAddRecExpr(const SCEV *Start, const SCEV *Step,
                                           const Loop *L,
                                           SCEV::NoWrapFlags Flags) {
  SmallVector<const SCEV *, 4> Operands;
  Operands.push_back(Start);
  if (const SCEVAddRecExpr *StepChrec = dyn_cast<SCEVAddRecExpr>(Step))
    if (StepChrec->getLoop() == L) {
      append_range(Operands, StepChrec->operands());
      return getAddRecExpr(Operands, L, maskFlags(Flags, SCEV::FlagNW));
    }

  Operands.push_back(Step);
  return getAddRecExpr(Operands, L, Flags);
}

/// Get an add recurrence expression for the specified loop.  Simplify the
/// expression as much as possible.
const SCEV *
ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
                               const Loop *L, SCEV::NoWrapFlags Flags) {
  if (Operands.size() == 1) return Operands[0];
#ifndef NDEBUG
  Type *ETy = getEffectiveSCEVType(Operands[0]->getType());
  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
    assert(getEffectiveSCEVType(Operands[i]->getType()) == ETy &&
           "SCEVAddRecExpr operand types don't match!");
    assert(!Operands[i]->getType()->isPointerTy() && "Step must be integer");
  }
  for (unsigned i = 0, e = Operands.size(); i != e; ++i)
    assert(isLoopInvariant(Operands[i], L) &&
           "SCEVAddRecExpr operand is not loop-invariant!");
#endif

  if (Operands.back()->isZero()) {
    Operands.pop_back();
    return getAddRecExpr(Operands, L, SCEV::FlagAnyWrap); // {X,+,0}  -->  X
  }

  // It's tempting to want to call getConstantMaxBackedgeTakenCount count here and
  // use that information to infer NUW and NSW flags. However, computing a
  // BE count requires calling getAddRecExpr, so we may not yet have a
  // meaningful BE count at this point (and if we don't, we'd be stuck
  // with a SCEVCouldNotCompute as the cached BE count).

  Flags = StrengthenNoWrapFlags(this, scAddRecExpr, Operands, Flags);

  // Canonicalize nested AddRecs in by nesting them in order of loop depth.
  if (const SCEVAddRecExpr *NestedAR = dyn_cast<SCEVAddRecExpr>(Operands[0])) {
    const Loop *NestedLoop = NestedAR->getLoop();
    if (L->contains(NestedLoop)
            ? (L->getLoopDepth() < NestedLoop->getLoopDepth())
            : (!NestedLoop->contains(L) &&
               DT.dominates(L->getHeader(), NestedLoop->getHeader()))) {
      SmallVector<const SCEV *, 4> NestedOperands(NestedAR->operands());
      Operands[0] = NestedAR->getStart();
      // AddRecs require their operands be loop-invariant with respect to their
      // loops. Don't perform this transformation if it would break this
      // requirement.
      bool AllInvariant = all_of(
          Operands, [&](const SCEV *Op) { return isLoopInvariant(Op, L); });

      if (AllInvariant) {
        // Create a recurrence for the outer loop with the same step size.
        //
        // The outer recurrence keeps its NW flag but only keeps NUW/NSW if the
        // inner recurrence has the same property.
        SCEV::NoWrapFlags OuterFlags =
          maskFlags(Flags, SCEV::FlagNW | NestedAR->getNoWrapFlags());

        NestedOperands[0] = getAddRecExpr(Operands, L, OuterFlags);
        AllInvariant = all_of(NestedOperands, [&](const SCEV *Op) {
          return isLoopInvariant(Op, NestedLoop);
        });

        if (AllInvariant) {
          // Ok, both add recurrences are valid after the transformation.
          //
          // The inner recurrence keeps its NW flag but only keeps NUW/NSW if
          // the outer recurrence has the same property.
          SCEV::NoWrapFlags InnerFlags =
            maskFlags(NestedAR->getNoWrapFlags(), SCEV::FlagNW | Flags);
          return getAddRecExpr(NestedOperands, NestedLoop, InnerFlags);
        }
      }
      // Reset Operands to its original state.
      Operands[0] = NestedAR;
    }
  }

  // Okay, it looks like we really DO need an addrec expr.  Check to see if we
  // already have one, otherwise create a new one.
  return getOrCreateAddRecExpr(Operands, L, Flags);
}

const SCEV *
ScalarEvolution::getGEPExpr(GEPOperator *GEP,
                            const SmallVectorImpl<const SCEV *> &IndexExprs) {
  const SCEV *BaseExpr = getSCEV(GEP->getPointerOperand());
  // getSCEV(Base)->getType() has the same address space as Base->getType()
  // because SCEV::getType() preserves the address space.
  Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
  const bool AssumeInBoundsFlags = [&]() {
    if (!GEP->isInBounds())
      return false;

    // We'd like to propagate flags from the IR to the corresponding SCEV nodes,
    // but to do that, we have to ensure that said flag is valid in the entire
    // defined scope of the SCEV.
    auto *GEPI = dyn_cast<Instruction>(GEP);
    // TODO: non-instructions have global scope.  We might be able to prove
    // some global scope cases
    return GEPI && isSCEVExprNeverPoison(GEPI);
  }();

  SCEV::NoWrapFlags OffsetWrap =
    AssumeInBoundsFlags ? SCEV::FlagNSW : SCEV::FlagAnyWrap;

  Type *CurTy = GEP->getType();
  bool FirstIter = true;
  SmallVector<const SCEV *, 4> Offsets;
  for (const SCEV *IndexExpr : IndexExprs) {
    // Compute the (potentially symbolic) offset in bytes for this index.
    if (StructType *STy = dyn_cast<StructType>(CurTy)) {
      // For a struct, add the member offset.
      ConstantInt *Index = cast<SCEVConstant>(IndexExpr)->getValue();
      unsigned FieldNo = Index->getZExtValue();
      const SCEV *FieldOffset = getOffsetOfExpr(IntIdxTy, STy, FieldNo);
      Offsets.push_back(FieldOffset);

      // Update CurTy to the type of the field at Index.
      CurTy = STy->getTypeAtIndex(Index);
    } else {
      // Update CurTy to its element type.
      if (FirstIter) {
        assert(isa<PointerType>(CurTy) &&
               "The first index of a GEP indexes a pointer");
        CurTy = GEP->getSourceElementType();
        FirstIter = false;
      } else {
        CurTy = GetElementPtrInst::getTypeAtIndex(CurTy, (uint64_t)0);
      }
      // For an array, add the element offset, explicitly scaled.
      const SCEV *ElementSize = getSizeOfExpr(IntIdxTy, CurTy);
      // Getelementptr indices are signed.
      IndexExpr = getTruncateOrSignExtend(IndexExpr, IntIdxTy);

      // Multiply the index by the element size to compute the element offset.
      const SCEV *LocalOffset = getMulExpr(IndexExpr, ElementSize, OffsetWrap);
      Offsets.push_back(LocalOffset);
    }
  }

  // Handle degenerate case of GEP without offsets.
  if (Offsets.empty())
    return BaseExpr;

  // Add the offsets together, assuming nsw if inbounds.
  const SCEV *Offset = getAddExpr(Offsets, OffsetWrap);
  // Add the base address and the offset. We cannot use the nsw flag, as the
  // base address is unsigned. However, if we know that the offset is
  // non-negative, we can use nuw.
  SCEV::NoWrapFlags BaseWrap = AssumeInBoundsFlags && isKnownNonNegative(Offset)
                                   ? SCEV::FlagNUW : SCEV::FlagAnyWrap;
  auto *GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
  assert(BaseExpr->getType() == GEPExpr->getType() &&
         "GEP should not change type mid-flight.");
  return GEPExpr;
}

SCEV *ScalarEvolution::findExistingSCEVInCache(SCEVTypes SCEVType,
                                               ArrayRef<const SCEV *> Ops) {
  FoldingSetNodeID ID;
  ID.AddInteger(SCEVType);
  for (const SCEV *Op : Ops)
    ID.AddPointer(Op);
  void *IP = nullptr;
  return UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
}

const SCEV *ScalarEvolution::getAbsExpr(const SCEV *Op, bool IsNSW) {
  SCEV::NoWrapFlags Flags = IsNSW ? SCEV::FlagNSW : SCEV::FlagAnyWrap;
  return getSMaxExpr(Op, getNegativeSCEV(Op, Flags));
}

const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind,
                                           SmallVectorImpl<const SCEV *> &Ops) {
  assert(SCEVMinMaxExpr::isMinMaxType(Kind) && "Not a SCEVMinMaxExpr!");
  assert(!Ops.empty() && "Cannot get empty (u|s)(min|max)!");
  if (Ops.size() == 1) return Ops[0];
#ifndef NDEBUG
  Type *ETy = getEffectiveSCEVType(Ops[0]->getType());
  for (unsigned i = 1, e = Ops.size(); i != e; ++i) {
    assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy &&
           "Operand types don't match!");
    assert(Ops[0]->getType()->isPointerTy() ==
               Ops[i]->getType()->isPointerTy() &&
           "min/max should be consistently pointerish");
  }
#endif

  bool IsSigned = Kind == scSMaxExpr || Kind == scSMinExpr;
  bool IsMax = Kind == scSMaxExpr || Kind == scUMaxExpr;

  // Sort by complexity, this groups all similar expression types together.
  GroupByComplexity(Ops, &LI, DT);

  // Check if we have created the same expression before.
  if (const SCEV *S = findExistingSCEVInCache(Kind, Ops)) {
    return S;
  }

  // If there are any constants, fold them together.
  unsigned Idx = 0;
  if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) {
    ++Idx;
    assert(Idx < Ops.size());
    auto FoldOp = [&](const APInt &LHS, const APInt &RHS) {
      switch (Kind) {
      case scSMaxExpr:
        return APIntOps::smax(LHS, RHS);
      case scSMinExpr:
        return APIntOps::smin(LHS, RHS);
      case scUMaxExpr:
        return APIntOps::umax(LHS, RHS);
      case scUMinExpr:
        return APIntOps::umin(LHS, RHS);
      default:
        llvm_unreachable("Unknown SCEV min/max opcode");
      }
    };

    while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) {
      // We found two constants, fold them together!
      ConstantInt *Fold = ConstantInt::get(
          getContext(), FoldOp(LHSC->getAPInt(), RHSC->getAPInt()));
      Ops[0] = getConstant(Fold);
      Ops.erase(Ops.begin()+1);  // Erase the folded element
      if (Ops.size() == 1) return Ops[0];
      LHSC = cast<SCEVConstant>(Ops[0]);
    }

    bool IsMinV = LHSC->getValue()->isMinValue(IsSigned);
    bool IsMaxV = LHSC->getValue()->isMaxValue(IsSigned);

    if (IsMax ? IsMinV : IsMaxV) {
      // If we are left with a constant minimum(/maximum)-int, strip it off.
      Ops.erase(Ops.begin());
      --Idx;
    } else if (IsMax ? IsMaxV : IsMinV) {
      // If we have a max(/min) with a constant maximum(/minimum)-int,
      // it will always be the extremum.
      return LHSC;
    }

    if (Ops.size() == 1) return Ops[0];
  }

  // Find the first operation of the same kind
  while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < Kind)
    ++Idx;

  // Check to see if one of the operands is of the same kind. If so, expand its
  // operands onto our operand list, and recurse to simplify.
  if (Idx < Ops.size()) {
    bool DeletedAny = false;
    while (Ops[Idx]->getSCEVType() == Kind) {
      const SCEVMinMaxExpr *SMME = cast<SCEVMinMaxExpr>(Ops[Idx]);
      Ops.erase(Ops.begin()+Idx);
      append_range(Ops, SMME->operands());
      DeletedAny = true;
    }

    if (DeletedAny)
      return getMinMaxExpr(Kind, Ops);
  }

  // Okay, check to see if the same value occurs in the operand list twice.  If
  // so, delete one.  Since we sorted the list, these values are required to
  // be adjacent.
  llvm::CmpInst::Predicate GEPred =
      IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
  llvm::CmpInst::Predicate LEPred =
      IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
  llvm::CmpInst::Predicate FirstPred = IsMax ? GEPred : LEPred;
  llvm::CmpInst::Predicate SecondPred = IsMax ? LEPred : GEPred;
  for (unsigned i = 0, e = Ops.size() - 1; i != e; ++i) {
    if (Ops[i] == Ops[i + 1] ||
        isKnownViaNonRecursiveReasoning(FirstPred, Ops[i], Ops[i + 1])) {
      //  X op Y op Y  -->  X op Y
      //  X op Y       -->  X, if we know X, Y are ordered appropriately
      Ops.erase(Ops.begin() + i + 1, Ops.begin() + i + 2);
      --i;
      --e;
    } else if (isKnownViaNonRecursiveReasoning(SecondPred, Ops[i],
                                               Ops[i + 1])) {
      //  X op Y       -->  Y, if we know X, Y are ordered appropriately
      Ops.erase(Ops.begin() + i, Ops.begin() + i + 1);
      --i;
      --e;
    }
  }

  if (Ops.size() == 1) return Ops[0];

  assert(!Ops.empty() && "Reduced smax down to nothing!");

  // Okay, it looks like we really DO need an expr.  Check to see if we
  // already have one, otherwise create a new one.
  FoldingSetNodeID ID;
  ID.AddInteger(Kind);
  for (unsigned i = 0, e = Ops.size(); i != e; ++i)
    ID.AddPointer(Ops[i]);
  void *IP = nullptr;
  const SCEV *ExistingSCEV = UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
  if (ExistingSCEV)
    return ExistingSCEV;
  const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
  std::uninitialized_copy(Ops.begin(), Ops.end(), O);
  SCEV *S = new (SCEVAllocator)
      SCEVMinMaxExpr(ID.Intern(SCEVAllocator), Kind, O, Ops.size());

  UniqueSCEVs.InsertNode(S, IP);
  registerUser(S, Ops);
  return S;
}

namespace {

class SCEVSequentialMinMaxDeduplicatingVisitor final
    : public SCEVVisitor<SCEVSequentialMinMaxDeduplicatingVisitor,
                         std::optional<const SCEV *>> {
  using RetVal = std::optional<const SCEV *>;
  using Base = SCEVVisitor<SCEVSequentialMinMaxDeduplicatingVisitor, RetVal>;

  ScalarEvolution &SE;
  const SCEVTypes RootKind; // Must be a sequential min/max expression.
  const SCEVTypes NonSequentialRootKind; // Non-sequential variant of RootKind.
  SmallPtrSet<const SCEV *, 16> SeenOps;

  bool canRecurseInto(SCEVTypes Kind) const {
    // We can only recurse into the SCEV expression of the same effective type
    // as the type of our root SCEV expression.
    return RootKind == Kind || NonSequentialRootKind == Kind;
  };

  RetVal visitAnyMinMaxExpr(const SCEV *S) {
    assert((isa<SCEVMinMaxExpr>(S) || isa<SCEVSequentialMinMaxExpr>(S)) &&
           "Only for min/max expressions.");
    SCEVTypes Kind = S->getSCEVType();

    if (!canRecurseInto(Kind))
      return S;

    auto *NAry = cast<SCEVNAryExpr>(S);
    SmallVector<const SCEV *> NewOps;
    bool Changed = visit(Kind, NAry->operands(), NewOps);

    if (!Changed)
      return S;
    if (NewOps.empty())
      return std::nullopt;

    return isa<SCEVSequentialMinMaxExpr>(S)
               ? SE.getSequentialMinMaxExpr(Kind, NewOps)
               : SE.getMinMaxExpr(Kind, NewOps);
  }

  RetVal visit(const SCEV *S) {
    // Has the whole operand been seen already?
    if (!SeenOps.insert(S).second)
      return std::nullopt;
    return Base::visit(S);
  }

public:
  SCEVSequentialMinMaxDeduplicatingVisitor(ScalarEvolution &SE,
                                           SCEVTypes RootKind)
      : SE(SE), RootKind(RootKind),
        NonSequentialRootKind(
            SCEVSequentialMinMaxExpr::getEquivalentNonSequentialSCEVType(
                RootKind)) {}

  bool /*Changed*/ visit(SCEVTypes Kind, ArrayRef<const SCEV *> OrigOps,
                         SmallVectorImpl<const SCEV *> &NewOps) {
    bool Changed = false;
    SmallVector<const SCEV *> Ops;
    Ops.reserve(OrigOps.size());

    for (const SCEV *Op : OrigOps) {
      RetVal NewOp = visit(Op);
      if (NewOp != Op)
        Changed = true;
      if (NewOp)
        Ops.emplace_back(*NewOp);
    }

    if (Changed)
      NewOps = std::move(Ops);
    return Changed;
  }

  RetVal visitConstant(const SCEVConstant *Constant) { return Constant; }

  RetVal visitVScale(const SCEVVScale *VScale) { return VScale; }

  RetVal visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) { return Expr; }

  RetVal visitTruncateExpr(const SCEVTruncateExpr *Expr) { return Expr; }

  RetVal visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { return Expr; }

  RetVal visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { return Expr; }

  RetVal visitAddExpr(const SCEVAddExpr *Expr) { return Expr; }

  RetVal visitMulExpr(const SCEVMulExpr *Expr) { return Expr; }

  RetVal visitUDivExpr(const SCEVUDivExpr *Expr) { return Expr; }

  RetVal visitAddRecExpr(const SCEVAddRecExpr *Expr) { return Expr; }

  RetVal visitSMaxExpr(const SCEVSMaxExpr *Expr) {
    return visitAnyMinMaxExpr(Expr);
  }

  RetVal visitUMaxExpr(const SCEVUMaxExpr *Expr) {
    return visitAnyMinMaxExpr(Expr);
  }

  RetVal visitSMinExpr(const SCEVSMinExpr *Expr) {
    return visitAnyMinMaxExpr(Expr);
  }

  RetVal visitUMinExpr(const SCEVUMinExpr *Expr) {
    return visitAnyMinMaxExpr(Expr);
  }

  RetVal visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) {
    return visitAnyMinMaxExpr(Expr);
  }

  RetVal visitUnknown(const SCEVUnknown *Expr) { return Expr; }

  RetVal visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { return Expr; }
};

} // namespace

static bool scevUnconditionallyPropagatesPoisonFromOperands(SCEVTypes Kind) {
  switch (Kind) {
  case scConstant:
  case scVScale:
  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
  case scPtrToInt:
  case scAddExpr:
  case scMulExpr:
  case scUDivExpr:
  case scAddRecExpr:
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scUnknown:
    // If any operand is poison, the whole expression is poison.
    return true;
  case scSequentialUMinExpr:
    // FIXME: if the *first* operand is poison, the whole expression is poison.
    return false; // Pessimistically, say that it does not propagate poison.
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

/// Return true if V is poison given that AssumedPoison is already poison.
static bool impliesPoison(const SCEV *AssumedPoison, const SCEV *S) {
  // The only way poison may be introduced in a SCEV expression is from a
  // poison SCEVUnknown (ConstantExprs are also represented as SCEVUnknown,
  // not SCEVConstant). Notably, nowrap flags in SCEV nodes can *not*
  // introduce poison -- they encode guaranteed, non-speculated knowledge.
  //
  // Additionally, all SCEV nodes propagate poison from inputs to outputs,
  // with the notable exception of umin_seq, where only poison from the first
  // operand is (unconditionally) propagated.
  struct SCEVPoisonCollector {
    bool LookThroughMaybePoisonBlocking;
    SmallPtrSet<const SCEV *, 4> MaybePoison;
    SCEVPoisonCollector(bool LookThroughMaybePoisonBlocking)
        : LookThroughMaybePoisonBlocking(LookThroughMaybePoisonBlocking) {}

    bool follow(const SCEV *S) {
      if (!LookThroughMaybePoisonBlocking &&
          !scevUnconditionallyPropagatesPoisonFromOperands(S->getSCEVType()))
        return false;

      if (auto *SU = dyn_cast<SCEVUnknown>(S)) {
        if (!isGuaranteedNotToBePoison(SU->getValue()))
          MaybePoison.insert(S);
      }
      return true;
    }
    bool isDone() const { return false; }
  };

  // First collect all SCEVs that might result in AssumedPoison to be poison.
  // We need to look through potentially poison-blocking operations here,
  // because we want to find all SCEVs that *might* result in poison, not only
  // those that are *required* to.
  SCEVPoisonCollector PC1(/* LookThroughMaybePoisonBlocking */ true);
  visitAll(AssumedPoison, PC1);

  // AssumedPoison is never poison. As the assumption is false, the implication
  // is true. Don't bother walking the other SCEV in this case.
  if (PC1.MaybePoison.empty())
    return true;

  // Collect all SCEVs in S that, if poison, *will* result in S being poison
  // as well. We cannot look through potentially poison-blocking operations
  // here, as their arguments only *may* make the result poison.
  SCEVPoisonCollector PC2(/* LookThroughMaybePoisonBlocking */ false);
  visitAll(S, PC2);

  // Make sure that no matter which SCEV in PC1.MaybePoison is actually poison,
  // it will also make S poison by being part of PC2.MaybePoison.
  return all_of(PC1.MaybePoison,
                [&](const SCEV *S) { return PC2.MaybePoison.contains(S); });
}

const SCEV *
ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
                                         SmallVectorImpl<const SCEV *> &Ops) {
  assert(SCEVSequentialMinMaxExpr::isSequentialMinMaxType(Kind) &&
         "Not a SCEVSequentialMinMaxExpr!");
  assert(!Ops.empty() && "Cannot get empty (u|s)(min|max)!");
  if (Ops.size() == 1)
    return Ops[0];
#ifndef NDEBUG
  Type *ETy = getEffectiveSCEVType(Ops[0]->getType());
  for (unsigned i = 1, e = Ops.size(); i != e; ++i) {
    assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy &&
           "Operand types don't match!");
    assert(Ops[0]->getType()->isPointerTy() ==
               Ops[i]->getType()->isPointerTy() &&
           "min/max should be consistently pointerish");
  }
#endif

  // Note that SCEVSequentialMinMaxExpr is *NOT* commutative,
  // so we can *NOT* do any kind of sorting of the expressions!

  // Check if we have created the same expression before.
  if (const SCEV *S = findExistingSCEVInCache(Kind, Ops))
    return S;

  // FIXME: there are *some* simplifications that we can do here.

  // Keep only the first instance of an operand.
  {
    SCEVSequentialMinMaxDeduplicatingVisitor Deduplicator(*this, Kind);
    bool Changed = Deduplicator.visit(Kind, Ops, Ops);
    if (Changed)
      return getSequentialMinMaxExpr(Kind, Ops);
  }

  // Check to see if one of the operands is of the same kind. If so, expand its
  // operands onto our operand list, and recurse to simplify.
  {
    unsigned Idx = 0;
    bool DeletedAny = false;
    while (Idx < Ops.size()) {
      if (Ops[Idx]->getSCEVType() != Kind) {
        ++Idx;
        continue;
      }
      const auto *SMME = cast<SCEVSequentialMinMaxExpr>(Ops[Idx]);
      Ops.erase(Ops.begin() + Idx);
      Ops.insert(Ops.begin() + Idx, SMME->operands().begin(),
                 SMME->operands().end());
      DeletedAny = true;
    }

    if (DeletedAny)
      return getSequentialMinMaxExpr(Kind, Ops);
  }

  const SCEV *SaturationPoint;
  ICmpInst::Predicate Pred;
  switch (Kind) {
  case scSequentialUMinExpr:
    SaturationPoint = getZero(Ops[0]->getType());
    Pred = ICmpInst::ICMP_ULE;
    break;
  default:
    llvm_unreachable("Not a sequential min/max type.");
  }

  for (unsigned i = 1, e = Ops.size(); i != e; ++i) {
    // We can replace %x umin_seq %y with %x umin %y if either:
    //  * %y being poison implies %x is also poison.
    //  * %x cannot be the saturating value (e.g. zero for umin).
    if (::impliesPoison(Ops[i], Ops[i - 1]) ||
        isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_NE, Ops[i - 1],
                                        SaturationPoint)) {
      SmallVector<const SCEV *> SeqOps = {Ops[i - 1], Ops[i]};
      Ops[i - 1] = getMinMaxExpr(
          SCEVSequentialMinMaxExpr::getEquivalentNonSequentialSCEVType(Kind),
          SeqOps);
      Ops.erase(Ops.begin() + i);
      return getSequentialMinMaxExpr(Kind, Ops);
    }
    // Fold %x umin_seq %y to %x if %x ule %y.
    // TODO: We might be able to prove the predicate for a later operand.
    if (isKnownViaNonRecursiveReasoning(Pred, Ops[i - 1], Ops[i])) {
      Ops.erase(Ops.begin() + i);
      return getSequentialMinMaxExpr(Kind, Ops);
    }
  }

  // Okay, it looks like we really DO need an expr.  Check to see if we
  // already have one, otherwise create a new one.
  FoldingSetNodeID ID;
  ID.AddInteger(Kind);
  for (unsigned i = 0, e = Ops.size(); i != e; ++i)
    ID.AddPointer(Ops[i]);
  void *IP = nullptr;
  const SCEV *ExistingSCEV = UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
  if (ExistingSCEV)
    return ExistingSCEV;

  const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
  std::uninitialized_copy(Ops.begin(), Ops.end(), O);
  SCEV *S = new (SCEVAllocator)
      SCEVSequentialMinMaxExpr(ID.Intern(SCEVAllocator), Kind, O, Ops.size());

  UniqueSCEVs.InsertNode(S, IP);
  registerUser(S, Ops);
  return S;
}

const SCEV *ScalarEvolution::getSMaxExpr(const SCEV *LHS, const SCEV *RHS) {
  SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
  return getSMaxExpr(Ops);
}

const SCEV *ScalarEvolution::getSMaxExpr(SmallVectorImpl<const SCEV *> &Ops) {
  return getMinMaxExpr(scSMaxExpr, Ops);
}

const SCEV *ScalarEvolution::getUMaxExpr(const SCEV *LHS, const SCEV *RHS) {
  SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
  return getUMaxExpr(Ops);
}

const SCEV *ScalarEvolution::getUMaxExpr(SmallVectorImpl<const SCEV *> &Ops) {
  return getMinMaxExpr(scUMaxExpr, Ops);
}

const SCEV *ScalarEvolution::getSMinExpr(const SCEV *LHS,
                                         const SCEV *RHS) {
  SmallVector<const SCEV *, 2> Ops = { LHS, RHS };
  return getSMinExpr(Ops);
}

const SCEV *ScalarEvolution::getSMinExpr(SmallVectorImpl<const SCEV *> &Ops) {
  return getMinMaxExpr(scSMinExpr, Ops);
}

const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, const SCEV *RHS,
                                         bool Sequential) {
  SmallVector<const SCEV *, 2> Ops = { LHS, RHS };
  return getUMinExpr(Ops, Sequential);
}

const SCEV *ScalarEvolution::getUMinExpr(SmallVectorImpl<const SCEV *> &Ops,
                                         bool Sequential) {
  return Sequential ? getSequentialMinMaxExpr(scSequentialUMinExpr, Ops)
                    : getMinMaxExpr(scUMinExpr, Ops);
}

const SCEV *
ScalarEvolution::getSizeOfExpr(Type *IntTy, TypeSize Size) {
  const SCEV *Res = getConstant(IntTy, Size.getKnownMinValue());
  if (Size.isScalable())
    Res = getMulExpr(Res, getVScale(IntTy));
  return Res;
}

const SCEV *ScalarEvolution::getSizeOfExpr(Type *IntTy, Type *AllocTy) {
  return getSizeOfExpr(IntTy, getDataLayout().getTypeAllocSize(AllocTy));
}

const SCEV *ScalarEvolution::getStoreSizeOfExpr(Type *IntTy, Type *StoreTy) {
  return getSizeOfExpr(IntTy, getDataLayout().getTypeStoreSize(StoreTy));
}

const SCEV *ScalarEvolution::getOffsetOfExpr(Type *IntTy,
                                             StructType *STy,
                                             unsigned FieldNo) {
  // We can bypass creating a target-independent constant expression and then
  // folding it back into a ConstantInt. This is just a compile-time
  // optimization.
  const StructLayout *SL = getDataLayout().getStructLayout(STy);
  assert(!SL->getSizeInBits().isScalable() &&
         "Cannot get offset for structure containing scalable vector types");
  return getConstant(IntTy, SL->getElementOffset(FieldNo));
}

const SCEV *ScalarEvolution::getUnknown(Value *V) {
  // Don't attempt to do anything other than create a SCEVUnknown object
  // here.  createSCEV only calls getUnknown after checking for all other
  // interesting possibilities, and any other code that calls getUnknown
  // is doing so in order to hide a value from SCEV canonicalization.

  FoldingSetNodeID ID;
  ID.AddInteger(scUnknown);
  ID.AddPointer(V);
  void *IP = nullptr;
  if (SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) {
    assert(cast<SCEVUnknown>(S)->getValue() == V &&
           "Stale SCEVUnknown in uniquing map!");
    return S;
  }
  SCEV *S = new (SCEVAllocator) SCEVUnknown(ID.Intern(SCEVAllocator), V, this,
                                            FirstUnknown);
  FirstUnknown = cast<SCEVUnknown>(S);
  UniqueSCEVs.InsertNode(S, IP);
  return S;
}

//===----------------------------------------------------------------------===//
//            Basic SCEV Analysis and PHI Idiom Recognition Code
//

/// Test if values of the given type are analyzable within the SCEV
/// framework. This primarily includes integer types, and it can optionally
/// include pointer types if the ScalarEvolution class has access to
/// target-specific information.
bool ScalarEvolution::isSCEVable(Type *Ty) const {
  // Integers and pointers are always SCEVable.
  return Ty->isIntOrPtrTy();
}

/// Return the size in bits of the specified type, for which isSCEVable must
/// return true.
uint64_t ScalarEvolution::getTypeSizeInBits(Type *Ty) const {
  assert(isSCEVable(Ty) && "Type is not SCEVable!");
  if (Ty->isPointerTy())
    return getDataLayout().getIndexTypeSizeInBits(Ty);
  return getDataLayout().getTypeSizeInBits(Ty);
}

/// Return a type with the same bitwidth as the given type and which represents
/// how SCEV will treat the given type, for which isSCEVable must return
/// true. For pointer types, this is the pointer index sized integer type.
Type *ScalarEvolution::getEffectiveSCEVType(Type *Ty) const {
  assert(isSCEVable(Ty) && "Type is not SCEVable!");

  if (Ty->isIntegerTy())
    return Ty;

  // The only other support type is pointer.
  assert(Ty->isPointerTy() && "Unexpected non-pointer non-integer type!");
  return getDataLayout().getIndexType(Ty);
}

Type *ScalarEvolution::getWiderType(Type *T1, Type *T2) const {
  return  getTypeSizeInBits(T1) >= getTypeSizeInBits(T2) ? T1 : T2;
}

bool ScalarEvolution::instructionCouldExistWitthOperands(const SCEV *A,
                                                         const SCEV *B) {
  /// For a valid use point to exist, the defining scope of one operand
  /// must dominate the other.
  bool PreciseA, PreciseB;
  auto *ScopeA = getDefiningScopeBound({A}, PreciseA);
  auto *ScopeB = getDefiningScopeBound({B}, PreciseB);
  if (!PreciseA || !PreciseB)
    // Can't tell.
    return false;
  return (ScopeA == ScopeB) || DT.dominates(ScopeA, ScopeB) ||
    DT.dominates(ScopeB, ScopeA);
}


const SCEV *ScalarEvolution::getCouldNotCompute() {
  return CouldNotCompute.get();
}

bool ScalarEvolution::checkValidity(const SCEV *S) const {
  bool ContainsNulls = SCEVExprContains(S, [](const SCEV *S) {
    auto *SU = dyn_cast<SCEVUnknown>(S);
    return SU && SU->getValue() == nullptr;
  });

  return !ContainsNulls;
}

bool ScalarEvolution::containsAddRecurrence(const SCEV *S) {
  HasRecMapType::iterator I = HasRecMap.find(S);
  if (I != HasRecMap.end())
    return I->second;

  bool FoundAddRec =
      SCEVExprContains(S, [](const SCEV *S) { return isa<SCEVAddRecExpr>(S); });
  HasRecMap.insert({S, FoundAddRec});
  return FoundAddRec;
}

/// Return the ValueOffsetPair set for \p S. \p S can be represented
/// by the value and offset from any ValueOffsetPair in the set.
ArrayRef<Value *> ScalarEvolution::getSCEVValues(const SCEV *S) {
  ExprValueMapType::iterator SI = ExprValueMap.find_as(S);
  if (SI == ExprValueMap.end())
    return std::nullopt;
  return SI->second.getArrayRef();
}

/// Erase Value from ValueExprMap and ExprValueMap. ValueExprMap.erase(V)
/// cannot be used separately. eraseValueFromMap should be used to remove
/// V from ValueExprMap and ExprValueMap at the same time.
void ScalarEvolution::eraseValueFromMap(Value *V) {
  ValueExprMapType::iterator I = ValueExprMap.find_as(V);
  if (I != ValueExprMap.end()) {
    auto EVIt = ExprValueMap.find(I->second);
    bool Removed = EVIt->second.remove(V);
    (void) Removed;
    assert(Removed && "Value not in ExprValueMap?");
    ValueExprMap.erase(I);
  }
}

void ScalarEvolution::insertValueToMap(Value *V, const SCEV *S) {
  // A recursive query may have already computed the SCEV. It should be
  // equivalent, but may not necessarily be exactly the same, e.g. due to lazily
  // inferred nowrap flags.
  auto It = ValueExprMap.find_as(V);
  if (It == ValueExprMap.end()) {
    ValueExprMap.insert({SCEVCallbackVH(V, this), S});
    ExprValueMap[S].insert(V);
  }
}

/// Determine whether this instruction is either not SCEVable or will always
/// produce a SCEVUnknown. We do not have to walk past such instructions when
/// invalidating.
static bool isAlwaysUnknown(const Instruction *I) {
  switch (I->getOpcode()) {
  case Instruction::Load:
    return true;
  default:
    return false;
  }
}

/// Return an existing SCEV if it exists, otherwise analyze the expression and
/// create a new one.
const SCEV *ScalarEvolution::getSCEV(Value *V) {
  assert(isSCEVable(V->getType()) && "Value is not SCEVable!");

  if (const SCEV *S = getExistingSCEV(V))
    return S;
  const SCEV *S = createSCEVIter(V);
  assert((!isa<Instruction>(V) || !isAlwaysUnknown(cast<Instruction>(V)) ||
          isa<SCEVUnknown>(S)) &&
         "isAlwaysUnknown() instruction is not SCEVUnknown");
  return S;
}

const SCEV *ScalarEvolution::getExistingSCEV(Value *V) {
  assert(isSCEVable(V->getType()) && "Value is not SCEVable!");

  ValueExprMapType::iterator I = ValueExprMap.find_as(V);
  if (I != ValueExprMap.end()) {
    const SCEV *S = I->second;
    assert(checkValidity(S) &&
           "existing SCEV has not been properly invalidated");
    return S;
  }
  return nullptr;
}

/// Return a SCEV corresponding to -V = -1*V
const SCEV *ScalarEvolution::getNegativeSCEV(const SCEV *V,
                                             SCEV::NoWrapFlags Flags) {
  if (const SCEVConstant *VC = dyn_cast<SCEVConstant>(V))
    return getConstant(
               cast<ConstantInt>(ConstantExpr::getNeg(VC->getValue())));

  Type *Ty = V->getType();
  Ty = getEffectiveSCEVType(Ty);
  return getMulExpr(V, getMinusOne(Ty), Flags);
}

/// If Expr computes ~A, return A else return nullptr
static const SCEV *MatchNotExpr(const SCEV *Expr) {
  const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Expr);
  if (!Add || Add->getNumOperands() != 2 ||
      !Add->getOperand(0)->isAllOnesValue())
    return nullptr;

  const SCEVMulExpr *AddRHS = dyn_cast<SCEVMulExpr>(Add->getOperand(1));
  if (!AddRHS || AddRHS->getNumOperands() != 2 ||
      !AddRHS->getOperand(0)->isAllOnesValue())
    return nullptr;

  return AddRHS->getOperand(1);
}

/// Return a SCEV corresponding to ~V = -1-V
const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) {
  assert(!V->getType()->isPointerTy() && "Can't negate pointer");

  if (const SCEVConstant *VC = dyn_cast<SCEVConstant>(V))
    return getConstant(
                cast<ConstantInt>(ConstantExpr::getNot(VC->getValue())));

  // Fold ~(u|s)(min|max)(~x, ~y) to (u|s)(max|min)(x, y)
  if (const SCEVMinMaxExpr *MME = dyn_cast<SCEVMinMaxExpr>(V)) {
    auto MatchMinMaxNegation = [&](const SCEVMinMaxExpr *MME) {
      SmallVector<const SCEV *, 2> MatchedOperands;
      for (const SCEV *Operand : MME->operands()) {
        const SCEV *Matched = MatchNotExpr(Operand);
        if (!Matched)
          return (const SCEV *)nullptr;
        MatchedOperands.push_back(Matched);
      }
      return getMinMaxExpr(SCEVMinMaxExpr::negate(MME->getSCEVType()),
                           MatchedOperands);
    };
    if (const SCEV *Replaced = MatchMinMaxNegation(MME))
      return Replaced;
  }

  Type *Ty = V->getType();
  Ty = getEffectiveSCEVType(Ty);
  return getMinusSCEV(getMinusOne(Ty), V);
}

const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
  assert(P->getType()->isPointerTy());

  if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(P)) {
    // The base of an AddRec is the first operand.
    SmallVector<const SCEV *> Ops{AddRec->operands()};
    Ops[0] = removePointerBase(Ops[0]);
    // Don't try to transfer nowrap flags for now. We could in some cases
    // (for example, if pointer operand of the AddRec is a SCEVUnknown).
    return getAddRecExpr(Ops, AddRec->getLoop(), SCEV::FlagAnyWrap);
  }
  if (auto *Add = dyn_cast<SCEVAddExpr>(P)) {
    // The base of an Add is the pointer operand.
    SmallVector<const SCEV *> Ops{Add->operands()};
    const SCEV **PtrOp = nullptr;
    for (const SCEV *&AddOp : Ops) {
      if (AddOp->getType()->isPointerTy()) {
        assert(!PtrOp && "Cannot have multiple pointer ops");
        PtrOp = &AddOp;
      }
    }
    *PtrOp = removePointerBase(*PtrOp);
    // Don't try to transfer nowrap flags for now. We could in some cases
    // (for example, if the pointer operand of the Add is a SCEVUnknown).
    return getAddExpr(Ops);
  }
  // Any other expression must be a pointer base.
  return getZero(P->getType());
}

const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
                                          SCEV::NoWrapFlags Flags,
                                          unsigned Depth) {
  // Fast path: X - X --> 0.
  if (LHS == RHS)
    return getZero(LHS->getType());

  // If we subtract two pointers with different pointer bases, bail.
  // Eventually, we're going to add an assertion to getMulExpr that we
  // can't multiply by a pointer.
  if (RHS->getType()->isPointerTy()) {
    if (!LHS->getType()->isPointerTy() ||
        getPointerBase(LHS) != getPointerBase(RHS))
      return getCouldNotCompute();
    LHS = removePointerBase(LHS);
    RHS = removePointerBase(RHS);
  }

  // We represent LHS - RHS as LHS + (-1)*RHS. This transformation
  // makes it so that we cannot make much use of NUW.
  auto AddFlags = SCEV::FlagAnyWrap;
  const bool RHSIsNotMinSigned =
      !getSignedRangeMin(RHS).isMinSignedValue();
  if (hasFlags(Flags, SCEV::FlagNSW)) {
    // Let M be the minimum representable signed value. Then (-1)*RHS
    // signed-wraps if and only if RHS is M. That can happen even for
    // a NSW subtraction because e.g. (-1)*M signed-wraps even though
    // -1 - M does not. So to transfer NSW from LHS - RHS to LHS +
    // (-1)*RHS, we need to prove that RHS != M.
    //
    // If LHS is non-negative and we know that LHS - RHS does not
    // signed-wrap, then RHS cannot be M. So we can rule out signed-wrap
    // either by proving that RHS > M or that LHS >= 0.
    if (RHSIsNotMinSigned || isKnownNonNegative(LHS)) {
      AddFlags = SCEV::FlagNSW;
    }
  }

  // FIXME: Find a correct way to transfer NSW to (-1)*M when LHS -
  // RHS is NSW and LHS >= 0.
  //
  // The difficulty here is that the NSW flag may have been proven
  // relative to a loop that is to be found in a recurrence in LHS and
  // not in RHS. Applying NSW to (-1)*M may then let the NSW have a
  // larger scope than intended.
  auto NegFlags = RHSIsNotMinSigned ? SCEV::FlagNSW : SCEV::FlagAnyWrap;

  return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags, Depth);
}

const SCEV *ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
                                                     unsigned Depth) {
  Type *SrcTy = V->getType();
  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot truncate or zero extend with non-integer arguments!");
  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
    return V;  // No conversion
  if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty))
    return getTruncateExpr(V, Ty, Depth);
  return getZeroExtendExpr(V, Ty, Depth);
}

const SCEV *ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, Type *Ty,
                                                     unsigned Depth) {
  Type *SrcTy = V->getType();
  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot truncate or zero extend with non-integer arguments!");
  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
    return V;  // No conversion
  if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty))
    return getTruncateExpr(V, Ty, Depth);
  return getSignExtendExpr(V, Ty, Depth);
}

const SCEV *
ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, Type *Ty) {
  Type *SrcTy = V->getType();
  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot noop or zero extend with non-integer arguments!");
  assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) &&
         "getNoopOrZeroExtend cannot truncate!");
  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
    return V;  // No conversion
  return getZeroExtendExpr(V, Ty);
}

const SCEV *
ScalarEvolution::getNoopOrSignExtend(const SCEV *V, Type *Ty) {
  Type *SrcTy = V->getType();
  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot noop or sign extend with non-integer arguments!");
  assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) &&
         "getNoopOrSignExtend cannot truncate!");
  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
    return V;  // No conversion
  return getSignExtendExpr(V, Ty);
}

const SCEV *
ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, Type *Ty) {
  Type *SrcTy = V->getType();
  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot noop or any extend with non-integer arguments!");
  assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) &&
         "getNoopOrAnyExtend cannot truncate!");
  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
    return V;  // No conversion
  return getAnyExtendExpr(V, Ty);
}

const SCEV *
ScalarEvolution::getTruncateOrNoop(const SCEV *V, Type *Ty) {
  Type *SrcTy = V->getType();
  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
         "Cannot truncate or noop with non-integer arguments!");
  assert(getTypeSizeInBits(SrcTy) >= getTypeSizeInBits(Ty) &&
         "getTruncateOrNoop cannot extend!");
  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
    return V;  // No conversion
  return getTruncateExpr(V, Ty);
}

const SCEV *ScalarEvolution::getUMaxFromMismatchedTypes(const SCEV *LHS,
                                                        const SCEV *RHS) {
  const SCEV *PromotedLHS = LHS;
  const SCEV *PromotedRHS = RHS;

  if (getTypeSizeInBits(LHS->getType()) > getTypeSizeInBits(RHS->getType()))
    PromotedRHS = getZeroExtendExpr(RHS, LHS->getType());
  else
    PromotedLHS = getNoopOrZeroExtend(LHS, RHS->getType());

  return getUMaxExpr(PromotedLHS, PromotedRHS);
}

const SCEV *ScalarEvolution::getUMinFromMismatchedTypes(const SCEV *LHS,
                                                        const SCEV *RHS,
                                                        bool Sequential) {
  SmallVector<const SCEV *, 2> Ops = { LHS, RHS };
  return getUMinFromMismatchedTypes(Ops, Sequential);
}

const SCEV *
ScalarEvolution::getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
                                            bool Sequential) {
  assert(!Ops.empty() && "At least one operand must be!");
  // Trivial case.
  if (Ops.size() == 1)
    return Ops[0];

  // Find the max type first.
  Type *MaxType = nullptr;
  for (const auto *S : Ops)
    if (MaxType)
      MaxType = getWiderType(MaxType, S->getType());
    else
      MaxType = S->getType();
  assert(MaxType && "Failed to find maximum type!");

  // Extend all ops to max type.
  SmallVector<const SCEV *, 2> PromotedOps;
  for (const auto *S : Ops)
    PromotedOps.push_back(getNoopOrZeroExtend(S, MaxType));

  // Generate umin.
  return getUMinExpr(PromotedOps, Sequential);
}

const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) {
  // A pointer operand may evaluate to a nonpointer expression, such as null.
  if (!V->getType()->isPointerTy())
    return V;

  while (true) {
    if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V)) {
      V = AddRec->getStart();
    } else if (auto *Add = dyn_cast<SCEVAddExpr>(V)) {
      const SCEV *PtrOp = nullptr;
      for (const SCEV *AddOp : Add->operands()) {
        if (AddOp->getType()->isPointerTy()) {
          assert(!PtrOp && "Cannot have multiple pointer ops");
          PtrOp = AddOp;
        }
      }
      assert(PtrOp && "Must have pointer op");
      V = PtrOp;
    } else // Not something we can look further into.
      return V;
  }
}

/// Push users of the given Instruction onto the given Worklist.
static void PushDefUseChildren(Instruction *I,
                               SmallVectorImpl<Instruction *> &Worklist,
                               SmallPtrSetImpl<Instruction *> &Visited) {
  // Push the def-use children onto the Worklist stack.
  for (User *U : I->users()) {
    auto *UserInsn = cast<Instruction>(U);
    if (isAlwaysUnknown(UserInsn))
      continue;
    if (Visited.insert(UserInsn).second)
      Worklist.push_back(UserInsn);
  }
}

namespace {

/// Takes SCEV S and Loop L. For each AddRec sub-expression, use its start
/// expression in case its Loop is L. If it is not L then
/// if IgnoreOtherLoops is true then use AddRec itself
/// otherwise rewrite cannot be done.
/// If SCEV contains non-invariant unknown SCEV rewrite cannot be done.
class SCEVInitRewriter : public SCEVRewriteVisitor<SCEVInitRewriter> {
public:
  static const SCEV *rewrite(const SCEV *S, const Loop *L, ScalarEvolution &SE,
                             bool IgnoreOtherLoops = true) {
    SCEVInitRewriter Rewriter(L, SE);
    const SCEV *Result = Rewriter.visit(S);
    if (Rewriter.hasSeenLoopVariantSCEVUnknown())
      return SE.getCouldNotCompute();
    return Rewriter.hasSeenOtherLoops() && !IgnoreOtherLoops
               ? SE.getCouldNotCompute()
               : Result;
  }

  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
    if (!SE.isLoopInvariant(Expr, L))
      SeenLoopVariantSCEVUnknown = true;
    return Expr;
  }

  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
    // Only re-write AddRecExprs for this loop.
    if (Expr->getLoop() == L)
      return Expr->getStart();
    SeenOtherLoops = true;
    return Expr;
  }

  bool hasSeenLoopVariantSCEVUnknown() { return SeenLoopVariantSCEVUnknown; }

  bool hasSeenOtherLoops() { return SeenOtherLoops; }

private:
  explicit SCEVInitRewriter(const Loop *L, ScalarEvolution &SE)
      : SCEVRewriteVisitor(SE), L(L) {}

  const Loop *L;
  bool SeenLoopVariantSCEVUnknown = false;
  bool SeenOtherLoops = false;
};

/// Takes SCEV S and Loop L. For each AddRec sub-expression, use its post
/// increment expression in case its Loop is L. If it is not L then
/// use AddRec itself.
/// If SCEV contains non-invariant unknown SCEV rewrite cannot be done.
class SCEVPostIncRewriter : public SCEVRewriteVisitor<SCEVPostIncRewriter> {
public:
  static const SCEV *rewrite(const SCEV *S, const Loop *L, ScalarEvolution &SE) {
    SCEVPostIncRewriter Rewriter(L, SE);
    const SCEV *Result = Rewriter.visit(S);
    return Rewriter.hasSeenLoopVariantSCEVUnknown()
        ? SE.getCouldNotCompute()
        : Result;
  }

  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
    if (!SE.isLoopInvariant(Expr, L))
      SeenLoopVariantSCEVUnknown = true;
    return Expr;
  }

  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
    // Only re-write AddRecExprs for this loop.
    if (Expr->getLoop() == L)
      return Expr->getPostIncExpr(SE);
    SeenOtherLoops = true;
    return Expr;
  }

  bool hasSeenLoopVariantSCEVUnknown() { return SeenLoopVariantSCEVUnknown; }

  bool hasSeenOtherLoops() { return SeenOtherLoops; }

private:
  explicit SCEVPostIncRewriter(const Loop *L, ScalarEvolution &SE)
      : SCEVRewriteVisitor(SE), L(L) {}

  const Loop *L;
  bool SeenLoopVariantSCEVUnknown = false;
  bool SeenOtherLoops = false;
};

/// This class evaluates the compare condition by matching it against the
/// condition of loop latch. If there is a match we assume a true value
/// for the condition while building SCEV nodes.
class SCEVBackedgeConditionFolder
    : public SCEVRewriteVisitor<SCEVBackedgeConditionFolder> {
public:
  static const SCEV *rewrite(const SCEV *S, const Loop *L,
                             ScalarEvolution &SE) {
    bool IsPosBECond = false;
    Value *BECond = nullptr;
    if (BasicBlock *Latch = L->getLoopLatch()) {
      BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator());
      if (BI && BI->isConditional()) {
        assert(BI->getSuccessor(0) != BI->getSuccessor(1) &&
               "Both outgoing branches should not target same header!");
        BECond = BI->getCondition();
        IsPosBECond = BI->getSuccessor(0) == L->getHeader();
      } else {
        return S;
      }
    }
    SCEVBackedgeConditionFolder Rewriter(L, BECond, IsPosBECond, SE);
    return Rewriter.visit(S);
  }

  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
    const SCEV *Result = Expr;
    bool InvariantF = SE.isLoopInvariant(Expr, L);

    if (!InvariantF) {
      Instruction *I = cast<Instruction>(Expr->getValue());
      switch (I->getOpcode()) {
      case Instruction::Select: {
        SelectInst *SI = cast<SelectInst>(I);
        std::optional<const SCEV *> Res =
            compareWithBackedgeCondition(SI->getCondition());
        if (Res) {
          bool IsOne = cast<SCEVConstant>(*Res)->getValue()->isOne();
          Result = SE.getSCEV(IsOne ? SI->getTrueValue() : SI->getFalseValue());
        }
        break;
      }
      default: {
        std::optional<const SCEV *> Res = compareWithBackedgeCondition(I);
        if (Res)
          Result = *Res;
        break;
      }
      }
    }
    return Result;
  }

private:
  explicit SCEVBackedgeConditionFolder(const Loop *L, Value *BECond,
                                       bool IsPosBECond, ScalarEvolution &SE)
      : SCEVRewriteVisitor(SE), L(L), BackedgeCond(BECond),
        IsPositiveBECond(IsPosBECond) {}

  std::optional<const SCEV *> compareWithBackedgeCondition(Value *IC);

  const Loop *L;
  /// Loop back condition.
  Value *BackedgeCond = nullptr;
  /// Set to true if loop back is on positive branch condition.
  bool IsPositiveBECond;
};

std::optional<const SCEV *>
SCEVBackedgeConditionFolder::compareWithBackedgeCondition(Value *IC) {

  // If value matches the backedge condition for loop latch,
  // then return a constant evolution node based on loopback
  // branch taken.
  if (BackedgeCond == IC)
    return IsPositiveBECond ? SE.getOne(Type::getInt1Ty(SE.getContext()))
                            : SE.getZero(Type::getInt1Ty(SE.getContext()));
  return std::nullopt;
}

class SCEVShiftRewriter : public SCEVRewriteVisitor<SCEVShiftRewriter> {
public:
  static const SCEV *rewrite(const SCEV *S, const Loop *L,
                             ScalarEvolution &SE) {
    SCEVShiftRewriter Rewriter(L, SE);
    const SCEV *Result = Rewriter.visit(S);
    return Rewriter.isValid() ? Result : SE.getCouldNotCompute();
  }

  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
    // Only allow AddRecExprs for this loop.
    if (!SE.isLoopInvariant(Expr, L))
      Valid = false;
    return Expr;
  }

  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
    if (Expr->getLoop() == L && Expr->isAffine())
      return SE.getMinusSCEV(Expr, Expr->getStepRecurrence(SE));
    Valid = false;
    return Expr;
  }

  bool isValid() { return Valid; }

private:
  explicit SCEVShiftRewriter(const Loop *L, ScalarEvolution &SE)
      : SCEVRewriteVisitor(SE), L(L) {}

  const Loop *L;
  bool Valid = true;
};

} // end anonymous namespace

SCEV::NoWrapFlags
ScalarEvolution::proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR) {
  if (!AR->isAffine())
    return SCEV::FlagAnyWrap;

  using OBO = OverflowingBinaryOperator;

  SCEV::NoWrapFlags Result = SCEV::FlagAnyWrap;

  if (!AR->hasNoSelfWrap()) {
    const SCEV *BECount = getConstantMaxBackedgeTakenCount(AR->getLoop());
    if (const SCEVConstant *BECountMax = dyn_cast<SCEVConstant>(BECount)) {
      ConstantRange StepCR = getSignedRange(AR->getStepRecurrence(*this));
      const APInt &BECountAP = BECountMax->getAPInt();
      unsigned NoOverflowBitWidth =
        BECountAP.getActiveBits() + StepCR.getMinSignedBits();
      if (NoOverflowBitWidth <= getTypeSizeInBits(AR->getType()))
        Result = ScalarEvolution::setFlags(Result, SCEV::FlagNW);
    }
  }

  if (!AR->hasNoSignedWrap()) {
    ConstantRange AddRecRange = getSignedRange(AR);
    ConstantRange IncRange = getSignedRange(AR->getStepRecurrence(*this));

    auto NSWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
        Instruction::Add, IncRange, OBO::NoSignedWrap);
    if (NSWRegion.contains(AddRecRange))
      Result = ScalarEvolution::setFlags(Result, SCEV::FlagNSW);
  }

  if (!AR->hasNoUnsignedWrap()) {
    ConstantRange AddRecRange = getUnsignedRange(AR);
    ConstantRange IncRange = getUnsignedRange(AR->getStepRecurrence(*this));

    auto NUWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
        Instruction::Add, IncRange, OBO::NoUnsignedWrap);
    if (NUWRegion.contains(AddRecRange))
      Result = ScalarEvolution::setFlags(Result, SCEV::FlagNUW);
  }

  return Result;
}

SCEV::NoWrapFlags
ScalarEvolution::proveNoSignedWrapViaInduction(const SCEVAddRecExpr *AR) {
  SCEV::NoWrapFlags Result = AR->getNoWrapFlags();

  if (AR->hasNoSignedWrap())
    return Result;

  if (!AR->isAffine())
    return Result;

  // This function can be expensive, only try to prove NSW once per AddRec.
  if (!SignedWrapViaInductionTried.insert(AR).second)
    return Result;

  const SCEV *Step = AR->getStepRecurrence(*this);
  const Loop *L = AR->getLoop();

  // Check whether the backedge-taken count is SCEVCouldNotCompute.
  // Note that this serves two purposes: It filters out loops that are
  // simply not analyzable, and it covers the case where this code is
  // being called from within backedge-taken count analysis, such that
  // attempting to ask for the backedge-taken count would likely result
  // in infinite recursion. In the later case, the analysis code will
  // cope with a conservative value, and it will take care to purge
  // that value once it has finished.
  const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);

  // Normally, in the cases we can prove no-overflow via a
  // backedge guarding condition, we can also compute a backedge
  // taken count for the loop.  The exceptions are assumptions and
  // guards present in the loop -- SCEV is not great at exploiting
  // these to compute max backedge taken counts, but can still use
  // these to prove lack of overflow.  Use this fact to avoid
  // doing extra work that may not pay off.

  if (isa<SCEVCouldNotCompute>(MaxBECount) && !HasGuards &&
      AC.assumptions().empty())
    return Result;

  // If the backedge is guarded by a comparison with the pre-inc  value the
  // addrec is safe. Also, if the entry is guarded by a comparison with the
  // start value and the backedge is guarded by a comparison with the post-inc
  // value, the addrec is safe.
  ICmpInst::Predicate Pred;
  const SCEV *OverflowLimit =
    getSignedOverflowLimitForStep(Step, &Pred, this);
  if (OverflowLimit &&
      (isLoopBackedgeGuardedByCond(L, Pred, AR, OverflowLimit) ||
       isKnownOnEveryIteration(Pred, AR, OverflowLimit))) {
    Result = setFlags(Result, SCEV::FlagNSW);
  }
  return Result;
}
SCEV::NoWrapFlags
ScalarEvolution::proveNoUnsignedWrapViaInduction(const SCEVAddRecExpr *AR) {
  SCEV::NoWrapFlags Result = AR->getNoWrapFlags();

  if (AR->hasNoUnsignedWrap())
    return Result;

  if (!AR->isAffine())
    return Result;

  // This function can be expensive, only try to prove NUW once per AddRec.
  if (!UnsignedWrapViaInductionTried.insert(AR).second)
    return Result;

  const SCEV *Step = AR->getStepRecurrence(*this);
  unsigned BitWidth = getTypeSizeInBits(AR->getType());
  const Loop *L = AR->getLoop();

  // Check whether the backedge-taken count is SCEVCouldNotCompute.
  // Note that this serves two purposes: It filters out loops that are
  // simply not analyzable, and it covers the case where this code is
  // being called from within backedge-taken count analysis, such that
  // attempting to ask for the backedge-taken count would likely result
  // in infinite recursion. In the later case, the analysis code will
  // cope with a conservative value, and it will take care to purge
  // that value once it has finished.
  const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);

  // Normally, in the cases we can prove no-overflow via a
  // backedge guarding condition, we can also compute a backedge
  // taken count for the loop.  The exceptions are assumptions and
  // guards present in the loop -- SCEV is not great at exploiting
  // these to compute max backedge taken counts, but can still use
  // these to prove lack of overflow.  Use this fact to avoid
  // doing extra work that may not pay off.

  if (isa<SCEVCouldNotCompute>(MaxBECount) && !HasGuards &&
      AC.assumptions().empty())
    return Result;

  // If the backedge is guarded by a comparison with the pre-inc  value the
  // addrec is safe. Also, if the entry is guarded by a comparison with the
  // start value and the backedge is guarded by a comparison with the post-inc
  // value, the addrec is safe.
  if (isKnownPositive(Step)) {
    const SCEV *N = getConstant(APInt::getMinValue(BitWidth) -
                                getUnsignedRangeMax(Step));
    if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N) ||
        isKnownOnEveryIteration(ICmpInst::ICMP_ULT, AR, N)) {
      Result = setFlags(Result, SCEV::FlagNUW);
    }
  }

  return Result;
}

namespace {

/// Represents an abstract binary operation.  This may exist as a
/// normal instruction or constant expression, or may have been
/// derived from an expression tree.
struct BinaryOp {
  unsigned Opcode;
  Value *LHS;
  Value *RHS;
  bool IsNSW = false;
  bool IsNUW = false;

  /// Op is set if this BinaryOp corresponds to a concrete LLVM instruction or
  /// constant expression.
  Operator *Op = nullptr;

  explicit BinaryOp(Operator *Op)
      : Opcode(Op->getOpcode()), LHS(Op->getOperand(0)), RHS(Op->getOperand(1)),
        Op(Op) {
    if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(Op)) {
      IsNSW = OBO->hasNoSignedWrap();
      IsNUW = OBO->hasNoUnsignedWrap();
    }
  }

  explicit BinaryOp(unsigned Opcode, Value *LHS, Value *RHS, bool IsNSW = false,
                    bool IsNUW = false)
      : Opcode(Opcode), LHS(LHS), RHS(RHS), IsNSW(IsNSW), IsNUW(IsNUW) {}
};

} // end anonymous namespace

/// Try to map \p V into a BinaryOp, and return \c std::nullopt on failure.
static std::optional<BinaryOp> MatchBinaryOp(Value *V, const DataLayout &DL,
                                             AssumptionCache &AC,
                                             const DominatorTree &DT,
                                             const Instruction *CxtI) {
  auto *Op = dyn_cast<Operator>(V);
  if (!Op)
    return std::nullopt;

  // Implementation detail: all the cleverness here should happen without
  // creating new SCEV expressions -- our caller knowns tricks to avoid creating
  // SCEV expressions when possible, and we should not break that.

  switch (Op->getOpcode()) {
  case Instruction::Add:
  case Instruction::Sub:
  case Instruction::Mul:
  case Instruction::UDiv:
  case Instruction::URem:
  case Instruction::And:
  case Instruction::AShr:
  case Instruction::Shl:
    return BinaryOp(Op);

  case Instruction::Or: {
    // LLVM loves to convert `add` of operands with no common bits
    // into an `or`. But SCEV really doesn't deal with `or` that well,
    // so try extra hard to recognize this `or` as an `add`.
    if (haveNoCommonBitsSet(Op->getOperand(0), Op->getOperand(1), DL, &AC, CxtI,
                            &DT, /*UseInstrInfo=*/true))
      return BinaryOp(Instruction::Add, Op->getOperand(0), Op->getOperand(1),
                      /*IsNSW=*/true, /*IsNUW=*/true);
    return BinaryOp(Op);
  }

  case Instruction::Xor:
    if (auto *RHSC = dyn_cast<ConstantInt>(Op->getOperand(1)))
      // If the RHS of the xor is a signmask, then this is just an add.
      // Instcombine turns add of signmask into xor as a strength reduction step.
      if (RHSC->getValue().isSignMask())
        return BinaryOp(Instruction::Add, Op->getOperand(0), Op->getOperand(1));
    // Binary `xor` is a bit-wise `add`.
    if (V->getType()->isIntegerTy(1))
      return BinaryOp(Instruction::Add, Op->getOperand(0), Op->getOperand(1));
    return BinaryOp(Op);

  case Instruction::LShr:
    // Turn logical shift right of a constant into a unsigned divide.
    if (ConstantInt *SA = dyn_cast<ConstantInt>(Op->getOperand(1))) {
      uint32_t BitWidth = cast<IntegerType>(Op->getType())->getBitWidth();

      // If the shift count is not less than the bitwidth, the result of
      // the shift is undefined. Don't try to analyze it, because the
      // resolution chosen here may differ from the resolution chosen in
      // other parts of the compiler.
      if (SA->getValue().ult(BitWidth)) {
        Constant *X =
            ConstantInt::get(SA->getContext(),
                             APInt::getOneBitSet(BitWidth, SA->getZExtValue()));
        return BinaryOp(Instruction::UDiv, Op->getOperand(0), X);
      }
    }
    return BinaryOp(Op);

  case Instruction::ExtractValue: {
    auto *EVI = cast<ExtractValueInst>(Op);
    if (EVI->getNumIndices() != 1 || EVI->getIndices()[0] != 0)
      break;

    auto *WO = dyn_cast<WithOverflowInst>(EVI->getAggregateOperand());
    if (!WO)
      break;

    Instruction::BinaryOps BinOp = WO->getBinaryOp();
    bool Signed = WO->isSigned();
    // TODO: Should add nuw/nsw flags for mul as well.
    if (BinOp == Instruction::Mul || !isOverflowIntrinsicNoWrap(WO, DT))
      return BinaryOp(BinOp, WO->getLHS(), WO->getRHS());

    // Now that we know that all uses of the arithmetic-result component of
    // CI are guarded by the overflow check, we can go ahead and pretend
    // that the arithmetic is non-overflowing.
    return BinaryOp(BinOp, WO->getLHS(), WO->getRHS(),
                    /* IsNSW = */ Signed, /* IsNUW = */ !Signed);
  }

  default:
    break;
  }

  // Recognise intrinsic loop.decrement.reg, and as this has exactly the same
  // semantics as a Sub, return a binary sub expression.
  if (auto *II = dyn_cast<IntrinsicInst>(V))
    if (II->getIntrinsicID() == Intrinsic::loop_decrement_reg)
      return BinaryOp(Instruction::Sub, II->getOperand(0), II->getOperand(1));

  return std::nullopt;
}

/// Helper function to createAddRecFromPHIWithCasts. We have a phi
/// node whose symbolic (unknown) SCEV is \p SymbolicPHI, which is updated via
/// the loop backedge by a SCEVAddExpr, possibly also with a few casts on the
/// way. This function checks if \p Op, an operand of this SCEVAddExpr,
/// follows one of the following patterns:
/// Op == (SExt ix (Trunc iy (%SymbolicPHI) to ix) to iy)
/// Op == (ZExt ix (Trunc iy (%SymbolicPHI) to ix) to iy)
/// If the SCEV expression of \p Op conforms with one of the expected patterns
/// we return the type of the truncation operation, and indicate whether the
/// truncated type should be treated as signed/unsigned by setting
/// \p Signed to true/false, respectively.
static Type *isSimpleCastedPHI(const SCEV *Op, const SCEVUnknown *SymbolicPHI,
                               bool &Signed, ScalarEvolution &SE) {
  // The case where Op == SymbolicPHI (that is, with no type conversions on
  // the way) is handled by the regular add recurrence creating logic and
  // would have already been triggered in createAddRecForPHI. Reaching it here
  // means that createAddRecFromPHI had failed for this PHI before (e.g.,
  // because one of the other operands of the SCEVAddExpr updating this PHI is
  // not invariant).
  //
  // Here we look for the case where Op = (ext(trunc(SymbolicPHI))), and in
  // this case predicates that allow us to prove that Op == SymbolicPHI will
  // be added.
  if (Op == SymbolicPHI)
    return nullptr;

  unsigned SourceBits = SE.getTypeSizeInBits(SymbolicPHI->getType());
  unsigned NewBits = SE.getTypeSizeInBits(Op->getType());
  if (SourceBits != NewBits)
    return nullptr;

  const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(Op);
  const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(Op);
  if (!SExt && !ZExt)
    return nullptr;
  const SCEVTruncateExpr *Trunc =
      SExt ? dyn_cast<SCEVTruncateExpr>(SExt->getOperand())
           : dyn_cast<SCEVTruncateExpr>(ZExt->getOperand());
  if (!Trunc)
    return nullptr;
  const SCEV *X = Trunc->getOperand();
  if (X != SymbolicPHI)
    return nullptr;
  Signed = SExt != nullptr;
  return Trunc->getType();
}

static const Loop *isIntegerLoopHeaderPHI(const PHINode *PN, LoopInfo &LI) {
  if (!PN->getType()->isIntegerTy())
    return nullptr;
  const Loop *L = LI.getLoopFor(PN->getParent());
  if (!L || L->getHeader() != PN->getParent())
    return nullptr;
  return L;
}

// Analyze \p SymbolicPHI, a SCEV expression of a phi node, and check if the
// computation that updates the phi follows the following pattern:
//   (SExt/ZExt ix (Trunc iy (%SymbolicPHI) to ix) to iy) + InvariantAccum
// which correspond to a phi->trunc->sext/zext->add->phi update chain.
// If so, try to see if it can be rewritten as an AddRecExpr under some
// Predicates. If successful, return them as a pair. Also cache the results
// of the analysis.
//
// Example usage scenario:
//    Say the Rewriter is called for the following SCEV:
//         8 * ((sext i32 (trunc i64 %X to i32) to i64) + %Step)
//    where:
//         %X = phi i64 (%Start, %BEValue)
//    It will visitMul->visitAdd->visitSExt->visitTrunc->visitUnknown(%X),
//    and call this function with %SymbolicPHI = %X.
//
//    The analysis will find that the value coming around the backedge has
//    the following SCEV:
//         BEValue = ((sext i32 (trunc i64 %X to i32) to i64) + %Step)
//    Upon concluding that this matches the desired pattern, the function
//    will return the pair {NewAddRec, SmallPredsVec} where:
//         NewAddRec = {%Start,+,%Step}
//         SmallPredsVec = {P1, P2, P3} as follows:
//           P1(WrapPred): AR: {trunc(%Start),+,(trunc %Step)}<nsw> Flags: <nssw>
//           P2(EqualPred): %Start == (sext i32 (trunc i64 %Start to i32) to i64)
//           P3(EqualPred): %Step == (sext i32 (trunc i64 %Step to i32) to i64)
//    The returned pair means that SymbolicPHI can be rewritten into NewAddRec
//    under the predicates {P1,P2,P3}.
//    This predicated rewrite will be cached in PredicatedSCEVRewrites:
//         PredicatedSCEVRewrites[{%X,L}] = {NewAddRec, {P1,P2,P3)}
//
// TODO's:
//
// 1) Extend the Induction descriptor to also support inductions that involve
//    casts: When needed (namely, when we are called in the context of the
//    vectorizer induction analysis), a Set of cast instructions will be
//    populated by this method, and provided back to isInductionPHI. This is
//    needed to allow the vectorizer to properly record them to be ignored by
//    the cost model and to avoid vectorizing them (otherwise these casts,
//    which are redundant under the runtime overflow checks, will be
//    vectorized, which can be costly).
//
// 2) Support additional induction/PHISCEV patterns: We also want to support
//    inductions where the sext-trunc / zext-trunc operations (partly) occur
//    after the induction update operation (the induction increment):
//
//      (Trunc iy (SExt/ZExt ix (%SymbolicPHI + InvariantAccum) to iy) to ix)
//    which correspond to a phi->add->trunc->sext/zext->phi update chain.
//
//      (Trunc iy ((SExt/ZExt ix (%SymbolicPhi) to iy) + InvariantAccum) to ix)
//    which correspond to a phi->trunc->add->sext/zext->phi update chain.
//
// 3) Outline common code with createAddRecFromPHI to avoid duplication.
std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI) {
  SmallVector<const SCEVPredicate *, 3> Predicates;

  // *** Part1: Analyze if we have a phi-with-cast pattern for which we can
  // return an AddRec expression under some predicate.

  auto *PN = cast<PHINode>(SymbolicPHI->getValue());
  const Loop *L = isIntegerLoopHeaderPHI(PN, LI);
  assert(L && "Expecting an integer loop header phi");

  // The loop may have multiple entrances or multiple exits; we can analyze
  // this phi as an addrec if it has a unique entry value and a unique
  // backedge value.
  Value *BEValueV = nullptr, *StartValueV = nullptr;
  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
    Value *V = PN->getIncomingValue(i);
    if (L->contains(PN->getIncomingBlock(i))) {
      if (!BEValueV) {
        BEValueV = V;
      } else if (BEValueV != V) {
        BEValueV = nullptr;
        break;
      }
    } else if (!StartValueV) {
      StartValueV = V;
    } else if (StartValueV != V) {
      StartValueV = nullptr;
      break;
    }
  }
  if (!BEValueV || !StartValueV)
    return std::nullopt;

  const SCEV *BEValue = getSCEV(BEValueV);

  // If the value coming around the backedge is an add with the symbolic
  // value we just inserted, possibly with casts that we can ignore under
  // an appropriate runtime guard, then we found a simple induction variable!
  const auto *Add = dyn_cast<SCEVAddExpr>(BEValue);
  if (!Add)
    return std::nullopt;

  // If there is a single occurrence of the symbolic value, possibly
  // casted, replace it with a recurrence.
  unsigned FoundIndex = Add->getNumOperands();
  Type *TruncTy = nullptr;
  bool Signed;
  for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
    if ((TruncTy =
             isSimpleCastedPHI(Add->getOperand(i), SymbolicPHI, Signed, *this)))
      if (FoundIndex == e) {
        FoundIndex = i;
        break;
      }

  if (FoundIndex == Add->getNumOperands())
    return std::nullopt;

  // Create an add with everything but the specified operand.
  SmallVector<const SCEV *, 8> Ops;
  for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
    if (i != FoundIndex)
      Ops.push_back(Add->getOperand(i));
  const SCEV *Accum = getAddExpr(Ops);

  // The runtime checks will not be valid if the step amount is
  // varying inside the loop.
  if (!isLoopInvariant(Accum, L))
    return std::nullopt;

  // *** Part2: Create the predicates

  // Analysis was successful: we have a phi-with-cast pattern for which we
  // can return an AddRec expression under the following predicates:
  //
  // P1: A Wrap predicate that guarantees that Trunc(Start) + i*Trunc(Accum)
  //     fits within the truncated type (does not overflow) for i = 0 to n-1.
  // P2: An Equal predicate that guarantees that
  //     Start = (Ext ix (Trunc iy (Start) to ix) to iy)
  // P3: An Equal predicate that guarantees that
  //     Accum = (Ext ix (Trunc iy (Accum) to ix) to iy)
  //
  // As we next prove, the above predicates guarantee that:
  //     Start + i*Accum = (Ext ix (Trunc iy ( Start + i*Accum ) to ix) to iy)
  //
  //
  // More formally, we want to prove that:
  //     Expr(i+1) = Start + (i+1) * Accum
  //               = (Ext ix (Trunc iy (Expr(i)) to ix) to iy) + Accum
  //
  // Given that:
  // 1) Expr(0) = Start
  // 2) Expr(1) = Start + Accum
  //            = (Ext ix (Trunc iy (Start) to ix) to iy) + Accum :: from P2
  // 3) Induction hypothesis (step i):
  //    Expr(i) = (Ext ix (Trunc iy (Expr(i-1)) to ix) to iy) + Accum
  //
  // Proof:
  //  Expr(i+1) =
  //   = Start + (i+1)*Accum
  //   = (Start + i*Accum) + Accum
  //   = Expr(i) + Accum
  //   = (Ext ix (Trunc iy (Expr(i-1)) to ix) to iy) + Accum + Accum
  //                                                             :: from step i
  //
  //   = (Ext ix (Trunc iy (Start + (i-1)*Accum) to ix) to iy) + Accum + Accum
  //
  //   = (Ext ix (Trunc iy (Start + (i-1)*Accum) to ix) to iy)
  //     + (Ext ix (Trunc iy (Accum) to ix) to iy)
  //     + Accum                                                     :: from P3
  //
  //   = (Ext ix (Trunc iy ((Start + (i-1)*Accum) + Accum) to ix) to iy)
  //     + Accum                            :: from P1: Ext(x)+Ext(y)=>Ext(x+y)
  //
  //   = (Ext ix (Trunc iy (Start + i*Accum) to ix) to iy) + Accum
  //   = (Ext ix (Trunc iy (Expr(i)) to ix) to iy) + Accum
  //
  // By induction, the same applies to all iterations 1<=i<n:
  //

  // Create a truncated addrec for which we will add a no overflow check (P1).
  const SCEV *StartVal = getSCEV(StartValueV);
  const SCEV *PHISCEV =
      getAddRecExpr(getTruncateExpr(StartVal, TruncTy),
                    getTruncateExpr(Accum, TruncTy), L, SCEV::FlagAnyWrap);

  // PHISCEV can be either a SCEVConstant or a SCEVAddRecExpr.
  // ex: If truncated Accum is 0 and StartVal is a constant, then PHISCEV
  // will be constant.
  //
  //  If PHISCEV is a constant, then P1 degenerates into P2 or P3, so we don't
  // add P1.
  if (const auto *AR = dyn_cast<SCEVAddRecExpr>(PHISCEV)) {
    SCEVWrapPredicate::IncrementWrapFlags AddedFlags =
        Signed ? SCEVWrapPredicate::IncrementNSSW
               : SCEVWrapPredicate::IncrementNUSW;
    const SCEVPredicate *AddRecPred = getWrapPredicate(AR, AddedFlags);
    Predicates.push_back(AddRecPred);
  }

  // Create the Equal Predicates P2,P3:

  // It is possible that the predicates P2 and/or P3 are computable at
  // compile time due to StartVal and/or Accum being constants.
  // If either one is, then we can check that now and escape if either P2
  // or P3 is false.

  // Construct the extended SCEV: (Ext ix (Trunc iy (Expr) to ix) to iy)
  // for each of StartVal and Accum
  auto getExtendedExpr = [&](const SCEV *Expr,
                             bool CreateSignExtend) -> const SCEV * {
    assert(isLoopInvariant(Expr, L) && "Expr is expected to be invariant");
    const SCEV *TruncatedExpr = getTruncateExpr(Expr, TruncTy);
    const SCEV *ExtendedExpr =
        CreateSignExtend ? getSignExtendExpr(TruncatedExpr, Expr->getType())
                         : getZeroExtendExpr(TruncatedExpr, Expr->getType());
    return ExtendedExpr;
  };

  // Given:
  //  ExtendedExpr = (Ext ix (Trunc iy (Expr) to ix) to iy
  //               = getExtendedExpr(Expr)
  // Determine whether the predicate P: Expr == ExtendedExpr
  // is known to be false at compile time
  auto PredIsKnownFalse = [&](const SCEV *Expr,
                              const SCEV *ExtendedExpr) -> bool {
    return Expr != ExtendedExpr &&
           isKnownPredicate(ICmpInst::ICMP_NE, Expr, ExtendedExpr);
  };

  const SCEV *StartExtended = getExtendedExpr(StartVal, Signed);
  if (PredIsKnownFalse(StartVal, StartExtended)) {
    LLVM_DEBUG(dbgs() << "P2 is compile-time false\n";);
    return std::nullopt;
  }

  // The Step is always Signed (because the overflow checks are either
  // NSSW or NUSW)
  const SCEV *AccumExtended = getExtendedExpr(Accum, /*CreateSignExtend=*/true);
  if (PredIsKnownFalse(Accum, AccumExtended)) {
    LLVM_DEBUG(dbgs() << "P3 is compile-time false\n";);
    return std::nullopt;
  }

  auto AppendPredicate = [&](const SCEV *Expr,
                             const SCEV *ExtendedExpr) -> void {
    if (Expr != ExtendedExpr &&
        !isKnownPredicate(ICmpInst::ICMP_EQ, Expr, ExtendedExpr)) {
      const SCEVPredicate *Pred = getEqualPredicate(Expr, ExtendedExpr);
      LLVM_DEBUG(dbgs() << "Added Predicate: " << *Pred);
      Predicates.push_back(Pred);
    }
  };

  AppendPredicate(StartVal, StartExtended);
  AppendPredicate(Accum, AccumExtended);

  // *** Part3: Predicates are ready. Now go ahead and create the new addrec in
  // which the casts had been folded away. The caller can rewrite SymbolicPHI
  // into NewAR if it will also add the runtime overflow checks specified in
  // Predicates.
  auto *NewAR = getAddRecExpr(StartVal, Accum, L, SCEV::FlagAnyWrap);

  std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>> PredRewrite =
      std::make_pair(NewAR, Predicates);
  // Remember the result of the analysis for this SCEV at this locayyytion.
  PredicatedSCEVRewrites[{SymbolicPHI, L}] = PredRewrite;
  return PredRewrite;
}

std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
ScalarEvolution::createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI) {
  auto *PN = cast<PHINode>(SymbolicPHI->getValue());
  const Loop *L = isIntegerLoopHeaderPHI(PN, LI);
  if (!L)
    return std::nullopt;

  // Check to see if we already analyzed this PHI.
  auto I = PredicatedSCEVRewrites.find({SymbolicPHI, L});
  if (I != PredicatedSCEVRewrites.end()) {
    std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>> Rewrite =
        I->second;
    // Analysis was done before and failed to create an AddRec:
    if (Rewrite.first == SymbolicPHI)
      return std::nullopt;
    // Analysis was done before and succeeded to create an AddRec under
    // a predicate:
    assert(isa<SCEVAddRecExpr>(Rewrite.first) && "Expected an AddRec");
    assert(!(Rewrite.second).empty() && "Expected to find Predicates");
    return Rewrite;
  }

  std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
    Rewrite = createAddRecFromPHIWithCastsImpl(SymbolicPHI);

  // Record in the cache that the analysis failed
  if (!Rewrite) {
    SmallVector<const SCEVPredicate *, 3> Predicates;
    PredicatedSCEVRewrites[{SymbolicPHI, L}] = {SymbolicPHI, Predicates};
    return std::nullopt;
  }

  return Rewrite;
}

// FIXME: This utility is currently required because the Rewriter currently
// does not rewrite this expression:
// {0, +, (sext ix (trunc iy to ix) to iy)}
// into {0, +, %step},
// even when the following Equal predicate exists:
// "%step == (sext ix (trunc iy to ix) to iy)".
bool PredicatedScalarEvolution::areAddRecsEqualWithPreds(
    const SCEVAddRecExpr *AR1, const SCEVAddRecExpr *AR2) const {
  if (AR1 == AR2)
    return true;

  auto areExprsEqual = [&](const SCEV *Expr1, const SCEV *Expr2) -> bool {
    if (Expr1 != Expr2 && !Preds->implies(SE.getEqualPredicate(Expr1, Expr2)) &&
        !Preds->implies(SE.getEqualPredicate(Expr2, Expr1)))
      return false;
    return true;
  };

  if (!areExprsEqual(AR1->getStart(), AR2->getStart()) ||
      !areExprsEqual(AR1->getStepRecurrence(SE), AR2->getStepRecurrence(SE)))
    return false;
  return true;
}

/// A helper function for createAddRecFromPHI to handle simple cases.
///
/// This function tries to find an AddRec expression for the simplest (yet most
/// common) cases: PN = PHI(Start, OP(Self, LoopInvariant)).
/// If it fails, createAddRecFromPHI will use a more general, but slow,
/// technique for finding the AddRec expression.
const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
                                                      Value *BEValueV,
                                                      Value *StartValueV) {
  const Loop *L = LI.getLoopFor(PN->getParent());
  assert(L && L->getHeader() == PN->getParent());
  assert(BEValueV && StartValueV);

  auto BO = MatchBinaryOp(BEValueV, getDataLayout(), AC, DT, PN);
  if (!BO)
    return nullptr;

  if (BO->Opcode != Instruction::Add)
    return nullptr;

  const SCEV *Accum = nullptr;
  if (BO->LHS == PN && L->isLoopInvariant(BO->RHS))
    Accum = getSCEV(BO->RHS);
  else if (BO->RHS == PN && L->isLoopInvariant(BO->LHS))
    Accum = getSCEV(BO->LHS);

  if (!Accum)
    return nullptr;

  SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;
  if (BO->IsNUW)
    Flags = setFlags(Flags, SCEV::FlagNUW);
  if (BO->IsNSW)
    Flags = setFlags(Flags, SCEV::FlagNSW);

  const SCEV *StartVal = getSCEV(StartValueV);
  const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);
  insertValueToMap(PN, PHISCEV);

  if (auto *AR = dyn_cast<SCEVAddRecExpr>(PHISCEV)) {
    setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
                   (SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
                                       proveNoWrapViaConstantRanges(AR)));
  }

  // We can add Flags to the post-inc expression only if we
  // know that it is *undefined behavior* for BEValueV to
  // overflow.
  if (auto *BEInst = dyn_cast<Instruction>(BEValueV)) {
    assert(isLoopInvariant(Accum, L) &&
           "Accum is defined outside L, but is not invariant?");
    if (isAddRecNeverPoison(BEInst, L))
      (void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags);
  }

  return PHISCEV;
}

const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
  const Loop *L = LI.getLoopFor(PN->getParent());
  if (!L || L->getHeader() != PN->getParent())
    return nullptr;

  // The loop may have multiple entrances or multiple exits; we can analyze
  // this phi as an addrec if it has a unique entry value and a unique
  // backedge value.
  Value *BEValueV = nullptr, *StartValueV = nullptr;
  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
    Value *V = PN->getIncomingValue(i);
    if (L->contains(PN->getIncomingBlock(i))) {
      if (!BEValueV) {
        BEValueV = V;
      } else if (BEValueV != V) {
        BEValueV = nullptr;
        break;
      }
    } else if (!StartValueV) {
      StartValueV = V;
    } else if (StartValueV != V) {
      StartValueV = nullptr;
      break;
    }
  }
  if (!BEValueV || !StartValueV)
    return nullptr;

  assert(ValueExprMap.find_as(PN) == ValueExprMap.end() &&
         "PHI node already processed?");

  // First, try to find AddRec expression without creating a fictituos symbolic
  // value for PN.
  if (auto *S = createSimpleAffineAddRec(PN, BEValueV, StartValueV))
    return S;

  // Handle PHI node value symbolically.
  const SCEV *SymbolicName = getUnknown(PN);
  insertValueToMap(PN, SymbolicName);

  // Using this symbolic name for the PHI, analyze the value coming around
  // the back-edge.
  const SCEV *BEValue = getSCEV(BEValueV);

  // NOTE: If BEValue is loop invariant, we know that the PHI node just
  // has a special value for the first iteration of the loop.

  // If the value coming around the backedge is an add with the symbolic
  // value we just inserted, then we found a simple induction variable!
  if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(BEValue)) {
    // If there is a single occurrence of the symbolic value, replace it
    // with a recurrence.
    unsigned FoundIndex = Add->getNumOperands();
    for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
      if (Add->getOperand(i) == SymbolicName)
        if (FoundIndex == e) {
          FoundIndex = i;
          break;
        }

    if (FoundIndex != Add->getNumOperands()) {
      // Create an add with everything but the specified operand.
      SmallVector<const SCEV *, 8> Ops;
      for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
        if (i != FoundIndex)
          Ops.push_back(SCEVBackedgeConditionFolder::rewrite(Add->getOperand(i),
                                                             L, *this));
      const SCEV *Accum = getAddExpr(Ops);

      // This is not a valid addrec if the step amount is varying each
      // loop iteration, but is not itself an addrec in this loop.
      if (isLoopInvariant(Accum, L) ||
          (isa<SCEVAddRecExpr>(Accum) &&
           cast<SCEVAddRecExpr>(Accum)->getLoop() == L)) {
        SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;

        if (auto BO = MatchBinaryOp(BEValueV, getDataLayout(), AC, DT, PN)) {
          if (BO->Opcode == Instruction::Add && BO->LHS == PN) {
            if (BO->IsNUW)
              Flags = setFlags(Flags, SCEV::FlagNUW);
            if (BO->IsNSW)
              Flags = setFlags(Flags, SCEV::FlagNSW);
          }
        } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(BEValueV)) {
          // If the increment is an inbounds GEP, then we know the address
          // space cannot be wrapped around. We cannot make any guarantee
          // about signed or unsigned overflow because pointers are
          // unsigned but we may have a negative index from the base
          // pointer. We can guarantee that no unsigned wrap occurs if the
          // indices form a positive value.
          if (GEP->isInBounds() && GEP->getOperand(0) == PN) {
            Flags = setFlags(Flags, SCEV::FlagNW);
            if (isKnownPositive(Accum))
              Flags = setFlags(Flags, SCEV::FlagNUW);
          }

          // We cannot transfer nuw and nsw flags from subtraction
          // operations -- sub nuw X, Y is not the same as add nuw X, -Y
          // for instance.
        }

        const SCEV *StartVal = getSCEV(StartValueV);
        const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);

        // Okay, for the entire analysis of this edge we assumed the PHI
        // to be symbolic.  We now need to go back and purge all of the
        // entries for the scalars that use the symbolic expression.
        forgetMemoizedResults(SymbolicName);
        insertValueToMap(PN, PHISCEV);

        if (auto *AR = dyn_cast<SCEVAddRecExpr>(PHISCEV)) {
          setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
                         (SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
                                             proveNoWrapViaConstantRanges(AR)));
        }

        // We can add Flags to the post-inc expression only if we
        // know that it is *undefined behavior* for BEValueV to
        // overflow.
        if (auto *BEInst = dyn_cast<Instruction>(BEValueV))
          if (isLoopInvariant(Accum, L) && isAddRecNeverPoison(BEInst, L))
            (void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags);

        return PHISCEV;
      }
    }
  } else {
    // Otherwise, this could be a loop like this:
    //     i = 0;  for (j = 1; ..; ++j) { ....  i = j; }
    // In this case, j = {1,+,1}  and BEValue is j.
    // Because the other in-value of i (0) fits the evolution of BEValue
    // i really is an addrec evolution.
    //
    // We can generalize this saying that i is the shifted value of BEValue
    // by one iteration:
    //   PHI(f(0), f({1,+,1})) --> f({0,+,1})
    const SCEV *Shifted = SCEVShiftRewriter::rewrite(BEValue, L, *this);
    const SCEV *Start = SCEVInitRewriter::rewrite(Shifted, L, *this, false);
    if (Shifted != getCouldNotCompute() &&
        Start != getCouldNotCompute()) {
      const SCEV *StartVal = getSCEV(StartValueV);
      if (Start == StartVal) {
        // Okay, for the entire analysis of this edge we assumed the PHI
        // to be symbolic.  We now need to go back and purge all of the
        // entries for the scalars that use the symbolic expression.
        forgetMemoizedResults(SymbolicName);
        insertValueToMap(PN, Shifted);
        return Shifted;
      }
    }
  }

  // Remove the temporary PHI node SCEV that has been inserted while intending
  // to create an AddRecExpr for this PHI node. We can not keep this temporary
  // as it will prevent later (possibly simpler) SCEV expressions to be added
  // to the ValueExprMap.
  eraseValueFromMap(PN);

  return nullptr;
}

// Try to match a control flow sequence that branches out at BI and merges back
// at Merge into a "C ? LHS : RHS" select pattern.  Return true on a successful
// match.
static bool BrPHIToSelect(DominatorTree &DT, BranchInst *BI, PHINode *Merge,
                          Value *&C, Value *&LHS, Value *&RHS) {
  C = BI->getCondition();

  BasicBlockEdge LeftEdge(BI->getParent(), BI->getSuccessor(0));
  BasicBlockEdge RightEdge(BI->getParent(), BI->getSuccessor(1));

  if (!LeftEdge.isSingleEdge())
    return false;

  assert(RightEdge.isSingleEdge() && "Follows from LeftEdge.isSingleEdge()");

  Use &LeftUse = Merge->getOperandUse(0);
  Use &RightUse = Merge->getOperandUse(1);

  if (DT.dominates(LeftEdge, LeftUse) && DT.dominates(RightEdge, RightUse)) {
    LHS = LeftUse;
    RHS = RightUse;
    return true;
  }

  if (DT.dominates(LeftEdge, RightUse) && DT.dominates(RightEdge, LeftUse)) {
    LHS = RightUse;
    RHS = LeftUse;
    return true;
  }

  return false;
}

const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
  auto IsReachable =
      [&](BasicBlock *BB) { return DT.isReachableFromEntry(BB); };
  if (PN->getNumIncomingValues() == 2 && all_of(PN->blocks(), IsReachable)) {
    // Try to match
    //
    //  br %cond, label %left, label %right
    // left:
    //  br label %merge
    // right:
    //  br label %merge
    // merge:
    //  V = phi [ %x, %left ], [ %y, %right ]
    //
    // as "select %cond, %x, %y"

    BasicBlock *IDom = DT[PN->getParent()]->getIDom()->getBlock();
    assert(IDom && "At least the entry block should dominate PN");

    auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
    Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;

    if (BI && BI->isConditional() &&
        BrPHIToSelect(DT, BI, PN, Cond, LHS, RHS) &&
        properlyDominates(getSCEV(LHS), PN->getParent()) &&
        properlyDominates(getSCEV(RHS), PN->getParent()))
      return createNodeForSelectOrPHI(PN, Cond, LHS, RHS);
  }

  return nullptr;
}

const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
  if (const SCEV *S = createAddRecFromPHI(PN))
    return S;

  if (Value *V = simplifyInstruction(PN, {getDataLayout(), &TLI, &DT, &AC}))
    return getSCEV(V);

  if (const SCEV *S = createNodeFromSelectLikePHI(PN))
    return S;

  // If it's not a loop phi, we can't handle it yet.
  return getUnknown(PN);
}

bool SCEVMinMaxExprContains(const SCEV *Root, const SCEV *OperandToFind,
                            SCEVTypes RootKind) {
  struct FindClosure {
    const SCEV *OperandToFind;
    const SCEVTypes RootKind; // Must be a sequential min/max expression.
    const SCEVTypes NonSequentialRootKind; // Non-seq variant of RootKind.

    bool Found = false;

    bool canRecurseInto(SCEVTypes Kind) const {
      // We can only recurse into the SCEV expression of the same effective type
      // as the type of our root SCEV expression, and into zero-extensions.
      return RootKind == Kind || NonSequentialRootKind == Kind ||
             scZeroExtend == Kind;
    };

    FindClosure(const SCEV *OperandToFind, SCEVTypes RootKind)
        : OperandToFind(OperandToFind), RootKind(RootKind),
          NonSequentialRootKind(
              SCEVSequentialMinMaxExpr::getEquivalentNonSequentialSCEVType(
                  RootKind)) {}

    bool follow(const SCEV *S) {
      Found = S == OperandToFind;

      return !isDone() && canRecurseInto(S->getSCEVType());
    }

    bool isDone() const { return Found; }
  };

  FindClosure FC(OperandToFind, RootKind);
  visitAll(Root, FC);
  return FC.Found;
}

std::optional<const SCEV *>
ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
                                                              ICmpInst *Cond,
                                                              Value *TrueVal,
                                                              Value *FalseVal) {
  // Try to match some simple smax or umax patterns.
  auto *ICI = Cond;

  Value *LHS = ICI->getOperand(0);
  Value *RHS = ICI->getOperand(1);

  switch (ICI->getPredicate()) {
  case ICmpInst::ICMP_SLT:
  case ICmpInst::ICMP_SLE:
  case ICmpInst::ICMP_ULT:
  case ICmpInst::ICMP_ULE:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_SGT:
  case ICmpInst::ICMP_SGE:
  case ICmpInst::ICMP_UGT:
  case ICmpInst::ICMP_UGE:
    // a > b ? a+x : b+x  ->  max(a, b)+x
    // a > b ? b+x : a+x  ->  min(a, b)+x
    if (getTypeSizeInBits(LHS->getType()) <= getTypeSizeInBits(Ty)) {
      bool Signed = ICI->isSigned();
      const SCEV *LA = getSCEV(TrueVal);
      const SCEV *RA = getSCEV(FalseVal);
      const SCEV *LS = getSCEV(LHS);
      const SCEV *RS = getSCEV(RHS);
      if (LA->getType()->isPointerTy()) {
        // FIXME: Handle cases where LS/RS are pointers not equal to LA/RA.
        // Need to make sure we can't produce weird expressions involving
        // negated pointers.
        if (LA == LS && RA == RS)
          return Signed ? getSMaxExpr(LS, RS) : getUMaxExpr(LS, RS);
        if (LA == RS && RA == LS)
          return Signed ? getSMinExpr(LS, RS) : getUMinExpr(LS, RS);
      }
      auto CoerceOperand = [&](const SCEV *Op) -> const SCEV * {
        if (Op->getType()->isPointerTy()) {
          Op = getLosslessPtrToIntExpr(Op);
          if (isa<SCEVCouldNotCompute>(Op))
            return Op;
        }
        if (Signed)
          Op = getNoopOrSignExtend(Op, Ty);
        else
          Op = getNoopOrZeroExtend(Op, Ty);
        return Op;
      };
      LS = CoerceOperand(LS);
      RS = CoerceOperand(RS);
      if (isa<SCEVCouldNotCompute>(LS) || isa<SCEVCouldNotCompute>(RS))
        break;
      const SCEV *LDiff = getMinusSCEV(LA, LS);
      const SCEV *RDiff = getMinusSCEV(RA, RS);
      if (LDiff == RDiff)
        return getAddExpr(Signed ? getSMaxExpr(LS, RS) : getUMaxExpr(LS, RS),
                          LDiff);
      LDiff = getMinusSCEV(LA, RS);
      RDiff = getMinusSCEV(RA, LS);
      if (LDiff == RDiff)
        return getAddExpr(Signed ? getSMinExpr(LS, RS) : getUMinExpr(LS, RS),
                          LDiff);
    }
    break;
  case ICmpInst::ICMP_NE:
    // x != 0 ? x+y : C+y  ->  x == 0 ? C+y : x+y
    std::swap(TrueVal, FalseVal);
    [[fallthrough]];
  case ICmpInst::ICMP_EQ:
    // x == 0 ? C+y : x+y  ->  umax(x, C)+y   iff C u<= 1
    if (getTypeSizeInBits(LHS->getType()) <= getTypeSizeInBits(Ty) &&
        isa<ConstantInt>(RHS) && cast<ConstantInt>(RHS)->isZero()) {
      const SCEV *X = getNoopOrZeroExtend(getSCEV(LHS), Ty);
      const SCEV *TrueValExpr = getSCEV(TrueVal);    // C+y
      const SCEV *FalseValExpr = getSCEV(FalseVal);  // x+y
      const SCEV *Y = getMinusSCEV(FalseValExpr, X); // y = (x+y)-x
      const SCEV *C = getMinusSCEV(TrueValExpr, Y);  // C = (C+y)-y
      if (isa<SCEVConstant>(C) && cast<SCEVConstant>(C)->getAPInt().ule(1))
        return getAddExpr(getUMaxExpr(X, C), Y);
    }
    // x == 0 ? 0 : umin    (..., x, ...)  ->  umin_seq(x, umin    (...))
    // x == 0 ? 0 : umin_seq(..., x, ...)  ->  umin_seq(x, umin_seq(...))
    // x == 0 ? 0 : umin    (..., umin_seq(..., x, ...), ...)
    //                    ->  umin_seq(x, umin (..., umin_seq(...), ...))
    if (isa<ConstantInt>(RHS) && cast<ConstantInt>(RHS)->isZero() &&
        isa<ConstantInt>(TrueVal) && cast<ConstantInt>(TrueVal)->isZero()) {
      const SCEV *X = getSCEV(LHS);
      while (auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(X))
        X = ZExt->getOperand();
      if (getTypeSizeInBits(X->getType()) <= getTypeSizeInBits(Ty)) {
        const SCEV *FalseValExpr = getSCEV(FalseVal);
        if (SCEVMinMaxExprContains(FalseValExpr, X, scSequentialUMinExpr))
          return getUMinExpr(getNoopOrZeroExtend(X, Ty), FalseValExpr,
                             /*Sequential=*/true);
      }
    }
    break;
  default:
    break;
  }

  return std::nullopt;
}

static std::optional<const SCEV *>
createNodeForSelectViaUMinSeq(ScalarEvolution *SE, const SCEV *CondExpr,
                              const SCEV *TrueExpr, const SCEV *FalseExpr) {
  assert(CondExpr->getType()->isIntegerTy(1) &&
         TrueExpr->getType() == FalseExpr->getType() &&
         TrueExpr->getType()->isIntegerTy(1) &&
         "Unexpected operands of a select.");

  // i1 cond ? i1 x : i1 C  -->  C + (i1  cond ? (i1 x - i1 C) : i1 0)
  //                        -->  C + (umin_seq  cond, x - C)
  //
  // i1 cond ? i1 C : i1 x  -->  C + (i1  cond ? i1 0 : (i1 x - i1 C))
  //                        -->  C + (i1 ~cond ? (i1 x - i1 C) : i1 0)
  //                        -->  C + (umin_seq ~cond, x - C)

  // FIXME: while we can't legally model the case where both of the hands
  // are fully variable, we only require that the *difference* is constant.
  if (!isa<SCEVConstant>(TrueExpr) && !isa<SCEVConstant>(FalseExpr))
    return std::nullopt;

  const SCEV *X, *C;
  if (isa<SCEVConstant>(TrueExpr)) {
    CondExpr = SE->getNotSCEV(CondExpr);
    X = FalseExpr;
    C = TrueExpr;
  } else {
    X = TrueExpr;
    C = FalseExpr;
  }
  return SE->getAddExpr(C, SE->getUMinExpr(CondExpr, SE->getMinusSCEV(X, C),
                                           /*Sequential=*/true));
}

static std::optional<const SCEV *>
createNodeForSelectViaUMinSeq(ScalarEvolution *SE, Value *Cond, Value *TrueVal,
                              Value *FalseVal) {
  if (!isa<ConstantInt>(TrueVal) && !isa<ConstantInt>(FalseVal))
    return std::nullopt;

  const auto *SECond = SE->getSCEV(Cond);
  const auto *SETrue = SE->getSCEV(TrueVal);
  const auto *SEFalse = SE->getSCEV(FalseVal);
  return createNodeForSelectViaUMinSeq(SE, SECond, SETrue, SEFalse);
}

const SCEV *ScalarEvolution::createNodeForSelectOrPHIViaUMinSeq(
    Value *V, Value *Cond, Value *TrueVal, Value *FalseVal) {
  assert(Cond->getType()->isIntegerTy(1) && "Select condition is not an i1?");
  assert(TrueVal->getType() == FalseVal->getType() &&
         V->getType() == TrueVal->getType() &&
         "Types of select hands and of the result must match.");

  // For now, only deal with i1-typed `select`s.
  if (!V->getType()->isIntegerTy(1))
    return getUnknown(V);

  if (std::optional<const SCEV *> S =
          createNodeForSelectViaUMinSeq(this, Cond, TrueVal, FalseVal))
    return *S;

  return getUnknown(V);
}

const SCEV *ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
                                                      Value *TrueVal,
                                                      Value *FalseVal) {
  // Handle "constant" branch or select. This can occur for instance when a
  // loop pass transforms an inner loop and moves on to process the outer loop.
  if (auto *CI = dyn_cast<ConstantInt>(Cond))
    return getSCEV(CI->isOne() ? TrueVal : FalseVal);

  if (auto *I = dyn_cast<Instruction>(V)) {
    if (auto *ICI = dyn_cast<ICmpInst>(Cond)) {
      if (std::optional<const SCEV *> S =
              createNodeForSelectOrPHIInstWithICmpInstCond(I->getType(), ICI,
                                                           TrueVal, FalseVal))
        return *S;
    }
  }

  return createNodeForSelectOrPHIViaUMinSeq(V, Cond, TrueVal, FalseVal);
}

/// Expand GEP instructions into add and multiply operations. This allows them
/// to be analyzed by regular SCEV code.
const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
  assert(GEP->getSourceElementType()->isSized() &&
         "GEP source element type must be sized");

  SmallVector<const SCEV *, 4> IndexExprs;
  for (Value *Index : GEP->indices())
    IndexExprs.push_back(getSCEV(Index));
  return getGEPExpr(GEP, IndexExprs);
}

APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S) {
  uint64_t BitWidth = getTypeSizeInBits(S->getType());
  auto GetShiftedByZeros = [BitWidth](uint32_t TrailingZeros) {
    return TrailingZeros >= BitWidth
               ? APInt::getZero(BitWidth)
               : APInt::getOneBitSet(BitWidth, TrailingZeros);
  };
  auto GetGCDMultiple = [this](const SCEVNAryExpr *N) {
    // The result is GCD of all operands results.
    APInt Res = getConstantMultiple(N->getOperand(0));
    for (unsigned I = 1, E = N->getNumOperands(); I < E && Res != 1; ++I)
      Res = APIntOps::GreatestCommonDivisor(
          Res, getConstantMultiple(N->getOperand(I)));
    return Res;
  };

  switch (S->getSCEVType()) {
  case scConstant:
    return cast<SCEVConstant>(S)->getAPInt();
  case scPtrToInt:
    return getConstantMultiple(cast<SCEVPtrToIntExpr>(S)->getOperand());
  case scUDivExpr:
  case scVScale:
    return APInt(BitWidth, 1);
  case scTruncate: {
    // Only multiples that are a power of 2 will hold after truncation.
    const SCEVTruncateExpr *T = cast<SCEVTruncateExpr>(S);
    uint32_t TZ = getMinTrailingZeros(T->getOperand());
    return GetShiftedByZeros(TZ);
  }
  case scZeroExtend: {
    const SCEVZeroExtendExpr *Z = cast<SCEVZeroExtendExpr>(S);
    return getConstantMultiple(Z->getOperand()).zext(BitWidth);
  }
  case scSignExtend: {
    const SCEVSignExtendExpr *E = cast<SCEVSignExtendExpr>(S);
    return getConstantMultiple(E->getOperand()).sext(BitWidth);
  }
  case scMulExpr: {
    const SCEVMulExpr *M = cast<SCEVMulExpr>(S);
    if (M->hasNoUnsignedWrap()) {
      // The result is the product of all operand results.
      APInt Res = getConstantMultiple(M->getOperand(0));
      for (const SCEV *Operand : M->operands().drop_front())
        Res = Res * getConstantMultiple(Operand);
      return Res;
    }

    // If there are no wrap guarentees, find the trailing zeros, which is the
    // sum of trailing zeros for all its operands.
    uint32_t TZ = 0;
    for (const SCEV *Operand : M->operands())
      TZ += getMinTrailingZeros(Operand);
    return GetShiftedByZeros(TZ);
  }
  case scAddExpr:
  case scAddRecExpr: {
    const SCEVNAryExpr *N = cast<SCEVNAryExpr>(S);
    if (N->hasNoUnsignedWrap())
        return GetGCDMultiple(N);
    // Find the trailing bits, which is the minimum of its operands.
    uint32_t TZ = getMinTrailingZeros(N->getOperand(0));
    for (const SCEV *Operand : N->operands().drop_front())
      TZ = std::min(TZ, getMinTrailingZeros(Operand));
    return GetShiftedByZeros(TZ);
  }
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scSequentialUMinExpr:
    return GetGCDMultiple(cast<SCEVNAryExpr>(S));
  case scUnknown: {
    // ask ValueTracking for known bits
    const SCEVUnknown *U = cast<SCEVUnknown>(S);
    unsigned Known =
        computeKnownBits(U->getValue(), getDataLayout(), 0, &AC, nullptr, &DT)
            .countMinTrailingZeros();
    return GetShiftedByZeros(Known);
  }
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

APInt ScalarEvolution::getConstantMultiple(const SCEV *S) {
  auto I = ConstantMultipleCache.find(S);
  if (I != ConstantMultipleCache.end())
    return I->second;

  APInt Result = getConstantMultipleImpl(S);
  auto InsertPair = ConstantMultipleCache.insert({S, Result});
  assert(InsertPair.second && "Should insert a new key");
  return InsertPair.first->second;
}

APInt ScalarEvolution::getNonZeroConstantMultiple(const SCEV *S) {
  APInt Multiple = getConstantMultiple(S);
  return Multiple == 0 ? APInt(Multiple.getBitWidth(), 1) : Multiple;
}

uint32_t ScalarEvolution::getMinTrailingZeros(const SCEV *S) {
  return std::min(getConstantMultiple(S).countTrailingZeros(),
                  (unsigned)getTypeSizeInBits(S->getType()));
}

/// Helper method to assign a range to V from metadata present in the IR.
static std::optional<ConstantRange> GetRangeFromMetadata(Value *V) {
  if (Instruction *I = dyn_cast<Instruction>(V))
    if (MDNode *MD = I->getMetadata(LLVMContext::MD_range))
      return getConstantRangeFromMetadata(*MD);

  return std::nullopt;
}

void ScalarEvolution::setNoWrapFlags(SCEVAddRecExpr *AddRec,
                                     SCEV::NoWrapFlags Flags) {
  if (AddRec->getNoWrapFlags(Flags) != Flags) {
    AddRec->setNoWrapFlags(Flags);
    UnsignedRanges.erase(AddRec);
    SignedRanges.erase(AddRec);
    ConstantMultipleCache.erase(AddRec);
  }
}

ConstantRange ScalarEvolution::
getRangeForUnknownRecurrence(const SCEVUnknown *U) {
  const DataLayout &DL = getDataLayout();

  unsigned BitWidth = getTypeSizeInBits(U->getType());
  const ConstantRange FullSet(BitWidth, /*isFullSet=*/true);

  // Match a simple recurrence of the form: <start, ShiftOp, Step>, and then
  // use information about the trip count to improve our available range.  Note
  // that the trip count independent cases are already handled by known bits.
  // WARNING: The definition of recurrence used here is subtly different than
  // the one used by AddRec (and thus most of this file).  Step is allowed to
  // be arbitrarily loop varying here, where AddRec allows only loop invariant
  // and other addrecs in the same loop (for non-affine addrecs).  The code
  // below intentionally handles the case where step is not loop invariant.
  auto *P = dyn_cast<PHINode>(U->getValue());
  if (!P)
    return FullSet;

  // Make sure that no Phi input comes from an unreachable block. Otherwise,
  // even the values that are not available in these blocks may come from them,
  // and this leads to false-positive recurrence test.
  for (auto *Pred : predecessors(P->getParent()))
    if (!DT.isReachableFromEntry(Pred))
      return FullSet;

  BinaryOperator *BO;
  Value *Start, *Step;
  if (!matchSimpleRecurrence(P, BO, Start, Step))
    return FullSet;

  // If we found a recurrence in reachable code, we must be in a loop. Note
  // that BO might be in some subloop of L, and that's completely okay.
  auto *L = LI.getLoopFor(P->getParent());
  assert(L && L->getHeader() == P->getParent());
  if (!L->contains(BO->getParent()))
    // NOTE: This bailout should be an assert instead.  However, asserting
    // the condition here exposes a case where LoopFusion is querying SCEV
    // with malformed loop information during the midst of the transform.
    // There doesn't appear to be an obvious fix, so for the moment bailout
    // until the caller issue can be fixed.  PR49566 tracks the bug.
    return FullSet;

  // TODO: Extend to other opcodes such as mul, and div
  switch (BO->getOpcode()) {
  default:
    return FullSet;
  case Instruction::AShr:
  case Instruction::LShr:
  case Instruction::Shl:
    break;
  };

  if (BO->getOperand(0) != P)
    // TODO: Handle the power function forms some day.
    return FullSet;

  unsigned TC = getSmallConstantMaxTripCount(L);
  if (!TC || TC >= BitWidth)
    return FullSet;

  auto KnownStart = computeKnownBits(Start, DL, 0, &AC, nullptr, &DT);
  auto KnownStep = computeKnownBits(Step, DL, 0, &AC, nullptr, &DT);
  assert(KnownStart.getBitWidth() == BitWidth &&
         KnownStep.getBitWidth() == BitWidth);

  // Compute total shift amount, being careful of overflow and bitwidths.
  auto MaxShiftAmt = KnownStep.getMaxValue();
  APInt TCAP(BitWidth, TC-1);
  bool Overflow = false;
  auto TotalShift = MaxShiftAmt.umul_ov(TCAP, Overflow);
  if (Overflow)
    return FullSet;

  switch (BO->getOpcode()) {
  default:
    llvm_unreachable("filtered out above");
  case Instruction::AShr: {
    // For each ashr, three cases:
    //   shift = 0 => unchanged value
    //   saturation => 0 or -1
    //   other => a value closer to zero (of the same sign)
    // Thus, the end value is closer to zero than the start.
    auto KnownEnd = KnownBits::ashr(KnownStart,
                                    KnownBits::makeConstant(TotalShift));
    if (KnownStart.isNonNegative())
      // Analogous to lshr (simply not yet canonicalized)
      return ConstantRange::getNonEmpty(KnownEnd.getMinValue(),
                                        KnownStart.getMaxValue() + 1);
    if (KnownStart.isNegative())
      // End >=u Start && End <=s Start
      return ConstantRange::getNonEmpty(KnownStart.getMinValue(),
                                        KnownEnd.getMaxValue() + 1);
    break;
  }
  case Instruction::LShr: {
    // For each lshr, three cases:
    //   shift = 0 => unchanged value
    //   saturation => 0
    //   other => a smaller positive number
    // Thus, the low end of the unsigned range is the last value produced.
    auto KnownEnd = KnownBits::lshr(KnownStart,
                                    KnownBits::makeConstant(TotalShift));
    return ConstantRange::getNonEmpty(KnownEnd.getMinValue(),
                                      KnownStart.getMaxValue() + 1);
  }
  case Instruction::Shl: {
    // Iff no bits are shifted out, value increases on every shift.
    auto KnownEnd = KnownBits::shl(KnownStart,
                                   KnownBits::makeConstant(TotalShift));
    if (TotalShift.ult(KnownStart.countMinLeadingZeros()))
      return ConstantRange(KnownStart.getMinValue(),
                           KnownEnd.getMaxValue() + 1);
    break;
  }
  };
  return FullSet;
}

const ConstantRange &
ScalarEvolution::getRangeRefIter(const SCEV *S,
                                 ScalarEvolution::RangeSignHint SignHint) {
  DenseMap<const SCEV *, ConstantRange> &Cache =
      SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? UnsignedRanges
                                                       : SignedRanges;
  SmallVector<const SCEV *> WorkList;
  SmallPtrSet<const SCEV *, 8> Seen;

  // Add Expr to the worklist, if Expr is either an N-ary expression or a
  // SCEVUnknown PHI node.
  auto AddToWorklist = [&WorkList, &Seen, &Cache](const SCEV *Expr) {
    if (!Seen.insert(Expr).second)
      return;
    if (Cache.contains(Expr))
      return;
    switch (Expr->getSCEVType()) {
    case scUnknown:
      if (!isa<PHINode>(cast<SCEVUnknown>(Expr)->getValue()))
        break;
      [[fallthrough]];
    case scConstant:
    case scVScale:
    case scTruncate:
    case scZeroExtend:
    case scSignExtend:
    case scPtrToInt:
    case scAddExpr:
    case scMulExpr:
    case scUDivExpr:
    case scAddRecExpr:
    case scUMaxExpr:
    case scSMaxExpr:
    case scUMinExpr:
    case scSMinExpr:
    case scSequentialUMinExpr:
      WorkList.push_back(Expr);
      break;
    case scCouldNotCompute:
      llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
    }
  };
  AddToWorklist(S);

  // Build worklist by queuing operands of N-ary expressions and phi nodes.
  for (unsigned I = 0; I != WorkList.size(); ++I) {
    const SCEV *P = WorkList[I];
    auto *UnknownS = dyn_cast<SCEVUnknown>(P);
    // If it is not a `SCEVUnknown`, just recurse into operands.
    if (!UnknownS) {
      for (const SCEV *Op : P->operands())
        AddToWorklist(Op);
      continue;
    }
    // `SCEVUnknown`'s require special treatment.
    if (const PHINode *P = dyn_cast<PHINode>(UnknownS->getValue())) {
      if (!PendingPhiRangesIter.insert(P).second)
        continue;
      for (auto &Op : reverse(P->operands()))
        AddToWorklist(getSCEV(Op));
    }
  }

  if (!WorkList.empty()) {
    // Use getRangeRef to compute ranges for items in the worklist in reverse
    // order. This will force ranges for earlier operands to be computed before
    // their users in most cases.
    for (const SCEV *P :
         reverse(make_range(WorkList.begin() + 1, WorkList.end()))) {
      getRangeRef(P, SignHint);

      if (auto *UnknownS = dyn_cast<SCEVUnknown>(P))
        if (const PHINode *P = dyn_cast<PHINode>(UnknownS->getValue()))
          PendingPhiRangesIter.erase(P);
    }
  }

  return getRangeRef(S, SignHint, 0);
}

/// Determine the range for a particular SCEV.  If SignHint is
/// HINT_RANGE_UNSIGNED (resp. HINT_RANGE_SIGNED) then getRange prefers ranges
/// with a "cleaner" unsigned (resp. signed) representation.
const ConstantRange &ScalarEvolution::getRangeRef(
    const SCEV *S, ScalarEvolution::RangeSignHint SignHint, unsigned Depth) {
  DenseMap<const SCEV *, ConstantRange> &Cache =
      SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? UnsignedRanges
                                                       : SignedRanges;
  ConstantRange::PreferredRangeType RangeType =
      SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? ConstantRange::Unsigned
                                                       : ConstantRange::Signed;

  // See if we've computed this range already.
  DenseMap<const SCEV *, ConstantRange>::iterator I = Cache.find(S);
  if (I != Cache.end())
    return I->second;

  if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
    return setRange(C, SignHint, ConstantRange(C->getAPInt()));

  // Switch to iteratively computing the range for S, if it is part of a deeply
  // nested expression.
  if (Depth > RangeIterThreshold)
    return getRangeRefIter(S, SignHint);

  unsigned BitWidth = getTypeSizeInBits(S->getType());
  ConstantRange ConservativeResult(BitWidth, /*isFullSet=*/true);
  using OBO = OverflowingBinaryOperator;

  // If the value has known zeros, the maximum value will have those known zeros
  // as well.
  if (SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED) {
    APInt Multiple = getNonZeroConstantMultiple(S);
    APInt Remainder = APInt::getMaxValue(BitWidth).urem(Multiple);
    if (!Remainder.isZero())
      ConservativeResult =
          ConstantRange(APInt::getMinValue(BitWidth),
                        APInt::getMaxValue(BitWidth) - Remainder + 1);
  }
  else {
    uint32_t TZ = getMinTrailingZeros(S);
    if (TZ != 0) {
      ConservativeResult = ConstantRange(
          APInt::getSignedMinValue(BitWidth),
          APInt::getSignedMaxValue(BitWidth).ashr(TZ).shl(TZ) + 1);
    }
  }

  switch (S->getSCEVType()) {
  case scConstant:
    llvm_unreachable("Already handled above.");
  case scVScale:
    return setRange(S, SignHint, getVScaleRange(&F, BitWidth));
  case scTruncate: {
    const SCEVTruncateExpr *Trunc = cast<SCEVTruncateExpr>(S);
    ConstantRange X = getRangeRef(Trunc->getOperand(), SignHint, Depth + 1);
    return setRange(
        Trunc, SignHint,
        ConservativeResult.intersectWith(X.truncate(BitWidth), RangeType));
  }
  case scZeroExtend: {
    const SCEVZeroExtendExpr *ZExt = cast<SCEVZeroExtendExpr>(S);
    ConstantRange X = getRangeRef(ZExt->getOperand(), SignHint, Depth + 1);
    return setRange(
        ZExt, SignHint,
        ConservativeResult.intersectWith(X.zeroExtend(BitWidth), RangeType));
  }
  case scSignExtend: {
    const SCEVSignExtendExpr *SExt = cast<SCEVSignExtendExpr>(S);
    ConstantRange X = getRangeRef(SExt->getOperand(), SignHint, Depth + 1);
    return setRange(
        SExt, SignHint,
        ConservativeResult.intersectWith(X.signExtend(BitWidth), RangeType));
  }
  case scPtrToInt: {
    const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(S);
    ConstantRange X = getRangeRef(PtrToInt->getOperand(), SignHint, Depth + 1);
    return setRange(PtrToInt, SignHint, X);
  }
  case scAddExpr: {
    const SCEVAddExpr *Add = cast<SCEVAddExpr>(S);
    ConstantRange X = getRangeRef(Add->getOperand(0), SignHint, Depth + 1);
    unsigned WrapType = OBO::AnyWrap;
    if (Add->hasNoSignedWrap())
      WrapType |= OBO::NoSignedWrap;
    if (Add->hasNoUnsignedWrap())
      WrapType |= OBO::NoUnsignedWrap;
    for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i)
      X = X.addWithNoWrap(getRangeRef(Add->getOperand(i), SignHint, Depth + 1),
                          WrapType, RangeType);
    return setRange(Add, SignHint,
                    ConservativeResult.intersectWith(X, RangeType));
  }
  case scMulExpr: {
    const SCEVMulExpr *Mul = cast<SCEVMulExpr>(S);
    ConstantRange X = getRangeRef(Mul->getOperand(0), SignHint, Depth + 1);
    for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i)
      X = X.multiply(getRangeRef(Mul->getOperand(i), SignHint, Depth + 1));
    return setRange(Mul, SignHint,
                    ConservativeResult.intersectWith(X, RangeType));
  }
  case scUDivExpr: {
    const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
    ConstantRange X = getRangeRef(UDiv->getLHS(), SignHint, Depth + 1);
    ConstantRange Y = getRangeRef(UDiv->getRHS(), SignHint, Depth + 1);
    return setRange(UDiv, SignHint,
                    ConservativeResult.intersectWith(X.udiv(Y), RangeType));
  }
  case scAddRecExpr: {
    const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(S);
    // If there's no unsigned wrap, the value will never be less than its
    // initial value.
    if (AddRec->hasNoUnsignedWrap()) {
      APInt UnsignedMinValue = getUnsignedRangeMin(AddRec->getStart());
      if (!UnsignedMinValue.isZero())
        ConservativeResult = ConservativeResult.intersectWith(
            ConstantRange(UnsignedMinValue, APInt(BitWidth, 0)), RangeType);
    }

    // If there's no signed wrap, and all the operands except initial value have
    // the same sign or zero, the value won't ever be:
    // 1: smaller than initial value if operands are non negative,
    // 2: bigger than initial value if operands are non positive.
    // For both cases, value can not cross signed min/max boundary.
    if (AddRec->hasNoSignedWrap()) {
      bool AllNonNeg = true;
      bool AllNonPos = true;
      for (unsigned i = 1, e = AddRec->getNumOperands(); i != e; ++i) {
        if (!isKnownNonNegative(AddRec->getOperand(i)))
          AllNonNeg = false;
        if (!isKnownNonPositive(AddRec->getOperand(i)))
          AllNonPos = false;
      }
      if (AllNonNeg)
        ConservativeResult = ConservativeResult.intersectWith(
            ConstantRange::getNonEmpty(getSignedRangeMin(AddRec->getStart()),
                                       APInt::getSignedMinValue(BitWidth)),
            RangeType);
      else if (AllNonPos)
        ConservativeResult = ConservativeResult.intersectWith(
            ConstantRange::getNonEmpty(APInt::getSignedMinValue(BitWidth),
                                       getSignedRangeMax(AddRec->getStart()) +
                                           1),
            RangeType);
    }

    // TODO: non-affine addrec
    if (AddRec->isAffine()) {
      const SCEV *MaxBEScev =
          getConstantMaxBackedgeTakenCount(AddRec->getLoop());
      if (!isa<SCEVCouldNotCompute>(MaxBEScev)) {
        APInt MaxBECount = cast<SCEVConstant>(MaxBEScev)->getAPInt();

        // Adjust MaxBECount to the same bitwidth as AddRec. We can truncate if
        // MaxBECount's active bits are all <= AddRec's bit width.
        if (MaxBECount.getBitWidth() > BitWidth &&
            MaxBECount.getActiveBits() <= BitWidth)
          MaxBECount = MaxBECount.trunc(BitWidth);
        else if (MaxBECount.getBitWidth() < BitWidth)
          MaxBECount = MaxBECount.zext(BitWidth);

        if (MaxBECount.getBitWidth() == BitWidth) {
          auto RangeFromAffine = getRangeForAffineAR(
              AddRec->getStart(), AddRec->getStepRecurrence(*this), MaxBECount);
          ConservativeResult =
              ConservativeResult.intersectWith(RangeFromAffine, RangeType);

          auto RangeFromFactoring = getRangeViaFactoring(
              AddRec->getStart(), AddRec->getStepRecurrence(*this), MaxBECount);
          ConservativeResult =
              ConservativeResult.intersectWith(RangeFromFactoring, RangeType);
        }
      }

      // Now try symbolic BE count and more powerful methods.
      if (UseExpensiveRangeSharpening) {
        const SCEV *SymbolicMaxBECount =
            getSymbolicMaxBackedgeTakenCount(AddRec->getLoop());
        if (!isa<SCEVCouldNotCompute>(SymbolicMaxBECount) &&
            getTypeSizeInBits(MaxBEScev->getType()) <= BitWidth &&
            AddRec->hasNoSelfWrap()) {
          auto RangeFromAffineNew = getRangeForAffineNoSelfWrappingAR(
              AddRec, SymbolicMaxBECount, BitWidth, SignHint);
          ConservativeResult =
              ConservativeResult.intersectWith(RangeFromAffineNew, RangeType);
        }
      }
    }

    return setRange(AddRec, SignHint, std::move(ConservativeResult));
  }
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scSequentialUMinExpr: {
    Intrinsic::ID ID;
    switch (S->getSCEVType()) {
    case scUMaxExpr:
      ID = Intrinsic::umax;
      break;
    case scSMaxExpr:
      ID = Intrinsic::smax;
      break;
    case scUMinExpr:
    case scSequentialUMinExpr:
      ID = Intrinsic::umin;
      break;
    case scSMinExpr:
      ID = Intrinsic::smin;
      break;
    default:
      llvm_unreachable("Unknown SCEVMinMaxExpr/SCEVSequentialMinMaxExpr.");
    }

    const auto *NAry = cast<SCEVNAryExpr>(S);
    ConstantRange X = getRangeRef(NAry->getOperand(0), SignHint, Depth + 1);
    for (unsigned i = 1, e = NAry->getNumOperands(); i != e; ++i)
      X = X.intrinsic(
          ID, {X, getRangeRef(NAry->getOperand(i), SignHint, Depth + 1)});
    return setRange(S, SignHint,
                    ConservativeResult.intersectWith(X, RangeType));
  }
  case scUnknown: {
    const SCEVUnknown *U = cast<SCEVUnknown>(S);
    Value *V = U->getValue();

    // Check if the IR explicitly contains !range metadata.
    std::optional<ConstantRange> MDRange = GetRangeFromMetadata(V);
    if (MDRange)
      ConservativeResult =
          ConservativeResult.intersectWith(*MDRange, RangeType);

    // Use facts about recurrences in the underlying IR.  Note that add
    // recurrences are AddRecExprs and thus don't hit this path.  This
    // primarily handles shift recurrences.
    auto CR = getRangeForUnknownRecurrence(U);
    ConservativeResult = ConservativeResult.intersectWith(CR);

    // See if ValueTracking can give us a useful range.
    const DataLayout &DL = getDataLayout();
    KnownBits Known = computeKnownBits(V, DL, 0, &AC, nullptr, &DT);
    if (Known.getBitWidth() != BitWidth)
      Known = Known.zextOrTrunc(BitWidth);

    // ValueTracking may be able to compute a tighter result for the number of
    // sign bits than for the value of those sign bits.
    unsigned NS = ComputeNumSignBits(V, DL, 0, &AC, nullptr, &DT);
    if (U->getType()->isPointerTy()) {
      // If the pointer size is larger than the index size type, this can cause
      // NS to be larger than BitWidth. So compensate for this.
      unsigned ptrSize = DL.getPointerTypeSizeInBits(U->getType());
      int ptrIdxDiff = ptrSize - BitWidth;
      if (ptrIdxDiff > 0 && ptrSize > BitWidth && NS > (unsigned)ptrIdxDiff)
        NS -= ptrIdxDiff;
    }

    if (NS > 1) {
      // If we know any of the sign bits, we know all of the sign bits.
      if (!Known.Zero.getHiBits(NS).isZero())
        Known.Zero.setHighBits(NS);
      if (!Known.One.getHiBits(NS).isZero())
        Known.One.setHighBits(NS);
    }

    if (Known.getMinValue() != Known.getMaxValue() + 1)
      ConservativeResult = ConservativeResult.intersectWith(
          ConstantRange(Known.getMinValue(), Known.getMaxValue() + 1),
          RangeType);
    if (NS > 1)
      ConservativeResult = ConservativeResult.intersectWith(
          ConstantRange(APInt::getSignedMinValue(BitWidth).ashr(NS - 1),
                        APInt::getSignedMaxValue(BitWidth).ashr(NS - 1) + 1),
          RangeType);

    if (U->getType()->isPointerTy() && SignHint == HINT_RANGE_UNSIGNED) {
      // Strengthen the range if the underlying IR value is a
      // global/alloca/heap allocation using the size of the object.
      ObjectSizeOpts Opts;
      Opts.RoundToAlign = false;
      Opts.NullIsUnknownSize = true;
      uint64_t ObjSize;
      if ((isa<GlobalVariable>(V) || isa<AllocaInst>(V) ||
           isAllocationFn(V, &TLI)) &&
          getObjectSize(V, ObjSize, DL, &TLI, Opts) && ObjSize > 1) {
        // The highest address the object can start is ObjSize bytes before the
        // end (unsigned max value). If this value is not a multiple of the
        // alignment, the last possible start value is the next lowest multiple
        // of the alignment. Note: The computations below cannot overflow,
        // because if they would there's no possible start address for the
        // object.
        APInt MaxVal = APInt::getMaxValue(BitWidth) - APInt(BitWidth, ObjSize);
        uint64_t Align = U->getValue()->getPointerAlignment(DL).value();
        uint64_t Rem = MaxVal.urem(Align);
        MaxVal -= APInt(BitWidth, Rem);
        APInt MinVal = APInt::getZero(BitWidth);
        if (llvm::isKnownNonZero(V, DL))
          MinVal = Align;
        ConservativeResult = ConservativeResult.intersectWith(
            {MinVal, MaxVal + 1}, RangeType);
      }
    }

    // A range of Phi is a subset of union of all ranges of its input.
    if (PHINode *Phi = dyn_cast<PHINode>(V)) {
      // Make sure that we do not run over cycled Phis.
      if (PendingPhiRanges.insert(Phi).second) {
        ConstantRange RangeFromOps(BitWidth, /*isFullSet=*/false);

        for (const auto &Op : Phi->operands()) {
          auto OpRange = getRangeRef(getSCEV(Op), SignHint, Depth + 1);
          RangeFromOps = RangeFromOps.unionWith(OpRange);
          // No point to continue if we already have a full set.
          if (RangeFromOps.isFullSet())
            break;
        }
        ConservativeResult =
            ConservativeResult.intersectWith(RangeFromOps, RangeType);
        bool Erased = PendingPhiRanges.erase(Phi);
        assert(Erased && "Failed to erase Phi properly?");
        (void)Erased;
      }
    }

    // vscale can't be equal to zero
    if (const auto *II = dyn_cast<IntrinsicInst>(V))
      if (II->getIntrinsicID() == Intrinsic::vscale) {
        ConstantRange Disallowed = APInt::getZero(BitWidth);
        ConservativeResult = ConservativeResult.difference(Disallowed);
      }

    return setRange(U, SignHint, std::move(ConservativeResult));
  }
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }

  return setRange(S, SignHint, std::move(ConservativeResult));
}

// Given a StartRange, Step and MaxBECount for an expression compute a range of
// values that the expression can take. Initially, the expression has a value
// from StartRange and then is changed by Step up to MaxBECount times. Signed
// argument defines if we treat Step as signed or unsigned.
static ConstantRange getRangeForAffineARHelper(APInt Step,
                                               const ConstantRange &StartRange,
                                               const APInt &MaxBECount,
                                               bool Signed) {
  unsigned BitWidth = Step.getBitWidth();
  assert(BitWidth == StartRange.getBitWidth() &&
         BitWidth == MaxBECount.getBitWidth() && "mismatched bit widths");
  // If either Step or MaxBECount is 0, then the expression won't change, and we
  // just need to return the initial range.
  if (Step == 0 || MaxBECount == 0)
    return StartRange;

  // If we don't know anything about the initial value (i.e. StartRange is
  // FullRange), then we don't know anything about the final range either.
  // Return FullRange.
  if (StartRange.isFullSet())
    return ConstantRange::getFull(BitWidth);

  // If Step is signed and negative, then we use its absolute value, but we also
  // note that we're moving in the opposite direction.
  bool Descending = Signed && Step.isNegative();

  if (Signed)
    // This is correct even for INT_SMIN. Let's look at i8 to illustrate this:
    // abs(INT_SMIN) = abs(-128) = abs(0x80) = -0x80 = 0x80 = 128.
    // This equations hold true due to the well-defined wrap-around behavior of
    // APInt.
    Step = Step.abs();

  // Check if Offset is more than full span of BitWidth. If it is, the
  // expression is guaranteed to overflow.
  if (APInt::getMaxValue(StartRange.getBitWidth()).udiv(Step).ult(MaxBECount))
    return ConstantRange::getFull(BitWidth);

  // Offset is by how much the expression can change. Checks above guarantee no
  // overflow here.
  APInt Offset = Step * MaxBECount;

  // Minimum value of the final range will match the minimal value of StartRange
  // if the expression is increasing and will be decreased by Offset otherwise.
  // Maximum value of the final range will match the maximal value of StartRange
  // if the expression is decreasing and will be increased by Offset otherwise.
  APInt StartLower = StartRange.getLower();
  APInt StartUpper = StartRange.getUpper() - 1;
  APInt MovedBoundary = Descending ? (StartLower - std::move(Offset))
                                   : (StartUpper + std::move(Offset));

  // It's possible that the new minimum/maximum value will fall into the initial
  // range (due to wrap around). This means that the expression can take any
  // value in this bitwidth, and we have to return full range.
  if (StartRange.contains(MovedBoundary))
    return ConstantRange::getFull(BitWidth);

  APInt NewLower =
      Descending ? std::move(MovedBoundary) : std::move(StartLower);
  APInt NewUpper =
      Descending ? std::move(StartUpper) : std::move(MovedBoundary);
  NewUpper += 1;

  // No overflow detected, return [StartLower, StartUpper + Offset + 1) range.
  return ConstantRange::getNonEmpty(std::move(NewLower), std::move(NewUpper));
}

ConstantRange ScalarEvolution::getRangeForAffineAR(const SCEV *Start,
                                                   const SCEV *Step,
                                                   const APInt &MaxBECount) {
  assert(getTypeSizeInBits(Start->getType()) ==
             getTypeSizeInBits(Step->getType()) &&
         getTypeSizeInBits(Start->getType()) == MaxBECount.getBitWidth() &&
         "mismatched bit widths");

  // First, consider step signed.
  ConstantRange StartSRange = getSignedRange(Start);
  ConstantRange StepSRange = getSignedRange(Step);

  // If Step can be both positive and negative, we need to find ranges for the
  // maximum absolute step values in both directions and union them.
  ConstantRange SR = getRangeForAffineARHelper(
      StepSRange.getSignedMin(), StartSRange, MaxBECount, /* Signed = */ true);
  SR = SR.unionWith(getRangeForAffineARHelper(StepSRange.getSignedMax(),
                                              StartSRange, MaxBECount,
                                              /* Signed = */ true));

  // Next, consider step unsigned.
  ConstantRange UR = getRangeForAffineARHelper(
      getUnsignedRangeMax(Step), getUnsignedRange(Start), MaxBECount,
      /* Signed = */ false);

  // Finally, intersect signed and unsigned ranges.
  return SR.intersectWith(UR, ConstantRange::Smallest);
}

ConstantRange ScalarEvolution::getRangeForAffineNoSelfWrappingAR(
    const SCEVAddRecExpr *AddRec, const SCEV *MaxBECount, unsigned BitWidth,
    ScalarEvolution::RangeSignHint SignHint) {
  assert(AddRec->isAffine() && "Non-affine AddRecs are not suppored!\n");
  assert(AddRec->hasNoSelfWrap() &&
         "This only works for non-self-wrapping AddRecs!");
  const bool IsSigned = SignHint == HINT_RANGE_SIGNED;
  const SCEV *Step = AddRec->getStepRecurrence(*this);
  // Only deal with constant step to save compile time.
  if (!isa<SCEVConstant>(Step))
    return ConstantRange::getFull(BitWidth);
  // Let's make sure that we can prove that we do not self-wrap during
  // MaxBECount iterations. We need this because MaxBECount is a maximum
  // iteration count estimate, and we might infer nw from some exit for which we
  // do not know max exit count (or any other side reasoning).
  // TODO: Turn into assert at some point.
  if (getTypeSizeInBits(MaxBECount->getType()) >
      getTypeSizeInBits(AddRec->getType()))
    return ConstantRange::getFull(BitWidth);
  MaxBECount = getNoopOrZeroExtend(MaxBECount, AddRec->getType());
  const SCEV *RangeWidth = getMinusOne(AddRec->getType());
  const SCEV *StepAbs = getUMinExpr(Step, getNegativeSCEV(Step));
  const SCEV *MaxItersWithoutWrap = getUDivExpr(RangeWidth, StepAbs);
  if (!isKnownPredicateViaConstantRanges(ICmpInst::ICMP_ULE, MaxBECount,
                                         MaxItersWithoutWrap))
    return ConstantRange::getFull(BitWidth);

  ICmpInst::Predicate LEPred =
      IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
  ICmpInst::Predicate GEPred =
      IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
  const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this);

  // We know that there is no self-wrap. Let's take Start and End values and
  // look at all intermediate values V1, V2, ..., Vn that IndVar takes during
  // the iteration. They either lie inside the range [Min(Start, End),
  // Max(Start, End)] or outside it:
  //
  // Case 1:   RangeMin    ...    Start V1 ... VN End ...           RangeMax;
  // Case 2:   RangeMin Vk ... V1 Start    ...    End Vn ... Vk + 1 RangeMax;
  //
  // No self wrap flag guarantees that the intermediate values cannot be BOTH
  // outside and inside the range [Min(Start, End), Max(Start, End)]. Using that
  // knowledge, let's try to prove that we are dealing with Case 1. It is so if
  // Start <= End and step is positive, or Start >= End and step is negative.
  const SCEV *Start = applyLoopGuards(AddRec->getStart(), AddRec->getLoop());
  ConstantRange StartRange = getRangeRef(Start, SignHint);
  ConstantRange EndRange = getRangeRef(End, SignHint);
  ConstantRange RangeBetween = StartRange.unionWith(EndRange);
  // If they already cover full iteration space, we will know nothing useful
  // even if we prove what we want to prove.
  if (RangeBetween.isFullSet())
    return RangeBetween;
  // Only deal with ranges that do not wrap (i.e. RangeMin < RangeMax).
  bool IsWrappedSet = IsSigned ? RangeBetween.isSignWrappedSet()
                               : RangeBetween.isWrappedSet();
  if (IsWrappedSet)
    return ConstantRange::getFull(BitWidth);

  if (isKnownPositive(Step) &&
      isKnownPredicateViaConstantRanges(LEPred, Start, End))
    return RangeBetween;
  if (isKnownNegative(Step) &&
           isKnownPredicateViaConstantRanges(GEPred, Start, End))
    return RangeBetween;
  return ConstantRange::getFull(BitWidth);
}

ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
                                                    const SCEV *Step,
                                                    const APInt &MaxBECount) {
  //    RangeOf({C?A:B,+,C?P:Q}) == RangeOf(C?{A,+,P}:{B,+,Q})
  // == RangeOf({A,+,P}) union RangeOf({B,+,Q})

  unsigned BitWidth = MaxBECount.getBitWidth();
  assert(getTypeSizeInBits(Start->getType()) == BitWidth &&
         getTypeSizeInBits(Step->getType()) == BitWidth &&
         "mismatched bit widths");

  struct SelectPattern {
    Value *Condition = nullptr;
    APInt TrueValue;
    APInt FalseValue;

    explicit SelectPattern(ScalarEvolution &SE, unsigned BitWidth,
                           const SCEV *S) {
      std::optional<unsigned> CastOp;
      APInt Offset(BitWidth, 0);

      assert(SE.getTypeSizeInBits(S->getType()) == BitWidth &&
             "Should be!");

      // Peel off a constant offset:
      if (auto *SA = dyn_cast<SCEVAddExpr>(S)) {
        // In the future we could consider being smarter here and handle
        // {Start+Step,+,Step} too.
        if (SA->getNumOperands() != 2 || !isa<SCEVConstant>(SA->getOperand(0)))
          return;

        Offset = cast<SCEVConstant>(SA->getOperand(0))->getAPInt();
        S = SA->getOperand(1);
      }

      // Peel off a cast operation
      if (auto *SCast = dyn_cast<SCEVIntegralCastExpr>(S)) {
        CastOp = SCast->getSCEVType();
        S = SCast->getOperand();
      }

      using namespace llvm::PatternMatch;

      auto *SU = dyn_cast<SCEVUnknown>(S);
      const APInt *TrueVal, *FalseVal;
      if (!SU ||
          !match(SU->getValue(), m_Select(m_Value(Condition), m_APInt(TrueVal),
                                          m_APInt(FalseVal)))) {
        Condition = nullptr;
        return;
      }

      TrueValue = *TrueVal;
      FalseValue = *FalseVal;

      // Re-apply the cast we peeled off earlier
      if (CastOp)
        switch (*CastOp) {
        default:
          llvm_unreachable("Unknown SCEV cast type!");

        case scTruncate:
          TrueValue = TrueValue.trunc(BitWidth);
          FalseValue = FalseValue.trunc(BitWidth);
          break;
        case scZeroExtend:
          TrueValue = TrueValue.zext(BitWidth);
          FalseValue = FalseValue.zext(BitWidth);
          break;
        case scSignExtend:
          TrueValue = TrueValue.sext(BitWidth);
          FalseValue = FalseValue.sext(BitWidth);
          break;
        }

      // Re-apply the constant offset we peeled off earlier
      TrueValue += Offset;
      FalseValue += Offset;
    }

    bool isRecognized() { return Condition != nullptr; }
  };

  SelectPattern StartPattern(*this, BitWidth, Start);
  if (!StartPattern.isRecognized())
    return ConstantRange::getFull(BitWidth);

  SelectPattern StepPattern(*this, BitWidth, Step);
  if (!StepPattern.isRecognized())
    return ConstantRange::getFull(BitWidth);

  if (StartPattern.Condition != StepPattern.Condition) {
    // We don't handle this case today; but we could, by considering four
    // possibilities below instead of two. I'm not sure if there are cases where
    // that will help over what getRange already does, though.
    return ConstantRange::getFull(BitWidth);
  }

  // NB! Calling ScalarEvolution::getConstant is fine, but we should not try to
  // construct arbitrary general SCEV expressions here.  This function is called
  // from deep in the call stack, and calling getSCEV (on a sext instruction,
  // say) can end up caching a suboptimal value.

  // FIXME: without the explicit `this` receiver below, MSVC errors out with
  // C2352 and C2512 (otherwise it isn't needed).

  const SCEV *TrueStart = this->getConstant(StartPattern.TrueValue);
  const SCEV *TrueStep = this->getConstant(StepPattern.TrueValue);
  const SCEV *FalseStart = this->getConstant(StartPattern.FalseValue);
  const SCEV *FalseStep = this->getConstant(StepPattern.FalseValue);

  ConstantRange TrueRange =
      this->getRangeForAffineAR(TrueStart, TrueStep, MaxBECount);
  ConstantRange FalseRange =
      this->getRangeForAffineAR(FalseStart, FalseStep, MaxBECount);

  return TrueRange.unionWith(FalseRange);
}

SCEV::NoWrapFlags ScalarEvolution::getNoWrapFlagsFromUB(const Value *V) {
  if (isa<ConstantExpr>(V)) return SCEV::FlagAnyWrap;
  const BinaryOperator *BinOp = cast<BinaryOperator>(V);

  // Return early if there are no flags to propagate to the SCEV.
  SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;
  if (BinOp->hasNoUnsignedWrap())
    Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
  if (BinOp->hasNoSignedWrap())
    Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW);
  if (Flags == SCEV::FlagAnyWrap)
    return SCEV::FlagAnyWrap;

  return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap;
}

const Instruction *
ScalarEvolution::getNonTrivialDefiningScopeBound(const SCEV *S) {
  if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S))
    return &*AddRec->getLoop()->getHeader()->begin();
  if (auto *U = dyn_cast<SCEVUnknown>(S))
    if (auto *I = dyn_cast<Instruction>(U->getValue()))
      return I;
  return nullptr;
}

const Instruction *
ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops,
                                       bool &Precise) {
  Precise = true;
  // Do a bounded search of the def relation of the requested SCEVs.
  SmallSet<const SCEV *, 16> Visited;
  SmallVector<const SCEV *> Worklist;
  auto pushOp = [&](const SCEV *S) {
    if (!Visited.insert(S).second)
      return;
    // Threshold of 30 here is arbitrary.
    if (Visited.size() > 30) {
      Precise = false;
      return;
    }
    Worklist.push_back(S);
  };

  for (const auto *S : Ops)
    pushOp(S);

  const Instruction *Bound = nullptr;
  while (!Worklist.empty()) {
    auto *S = Worklist.pop_back_val();
    if (auto *DefI = getNonTrivialDefiningScopeBound(S)) {
      if (!Bound || DT.dominates(Bound, DefI))
        Bound = DefI;
    } else {
      for (const auto *Op : S->operands())
        pushOp(Op);
    }
  }
  return Bound ? Bound : &*F.getEntryBlock().begin();
}

const Instruction *
ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops) {
  bool Discard;
  return getDefiningScopeBound(Ops, Discard);
}

bool ScalarEvolution::isGuaranteedToTransferExecutionTo(const Instruction *A,
                                                        const Instruction *B) {
  if (A->getParent() == B->getParent() &&
      isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
                                                 B->getIterator()))
    return true;

  auto *BLoop = LI.getLoopFor(B->getParent());
  if (BLoop && BLoop->getHeader() == B->getParent() &&
      BLoop->getLoopPreheader() == A->getParent() &&
      isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
                                                 A->getParent()->end()) &&
      isGuaranteedToTransferExecutionToSuccessor(B->getParent()->begin(),
                                                 B->getIterator()))
    return true;
  return false;
}


bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
  // Only proceed if we can prove that I does not yield poison.
  if (!programUndefinedIfPoison(I))
    return false;

  // At this point we know that if I is executed, then it does not wrap
  // according to at least one of NSW or NUW. If I is not executed, then we do
  // not know if the calculation that I represents would wrap. Multiple
  // instructions can map to the same SCEV. If we apply NSW or NUW from I to
  // the SCEV, we must guarantee no wrapping for that SCEV also when it is
  // derived from other instructions that map to the same SCEV. We cannot make
  // that guarantee for cases where I is not executed. So we need to find a
  // upper bound on the defining scope for the SCEV, and prove that I is
  // executed every time we enter that scope.  When the bounding scope is a
  // loop (the common case), this is equivalent to proving I executes on every
  // iteration of that loop.
  SmallVector<const SCEV *> SCEVOps;
  for (const Use &Op : I->operands()) {
    // I could be an extractvalue from a call to an overflow intrinsic.
    // TODO: We can do better here in some cases.
    if (isSCEVable(Op->getType()))
      SCEVOps.push_back(getSCEV(Op));
  }
  auto *DefI = getDefiningScopeBound(SCEVOps);
  return isGuaranteedToTransferExecutionTo(DefI, I);
}

bool ScalarEvolution::isAddRecNeverPoison(const Instruction *I, const Loop *L) {
  // If we know that \c I can never be poison period, then that's enough.
  if (isSCEVExprNeverPoison(I))
    return true;

  // If the loop only has one exit, then we know that, if the loop is entered,
  // any instruction dominating that exit will be executed. If any such
  // instruction would result in UB, the addrec cannot be poison.
  //
  // This is basically the same reasoning as in isSCEVExprNeverPoison(), but
  // also handles uses outside the loop header (they just need to dominate the
  // single exit).

  auto *ExitingBB = L->getExitingBlock();
  if (!ExitingBB || !loopHasNoAbnormalExits(L))
    return false;

  SmallPtrSet<const Value *, 16> KnownPoison;
  SmallVector<const Instruction *, 8> Worklist;

  // We start by assuming \c I, the post-inc add recurrence, is poison.  Only
  // things that are known to be poison under that assumption go on the
  // Worklist.
  KnownPoison.insert(I);
  Worklist.push_back(I);

  while (!Worklist.empty()) {
    const Instruction *Poison = Worklist.pop_back_val();

    for (const Use &U : Poison->uses()) {
      const Instruction *PoisonUser = cast<Instruction>(U.getUser());
      if (mustTriggerUB(PoisonUser, KnownPoison) &&
          DT.dominates(PoisonUser->getParent(), ExitingBB))
        return true;

      if (propagatesPoison(U) && L->contains(PoisonUser))
        if (KnownPoison.insert(PoisonUser).second)
          Worklist.push_back(PoisonUser);
    }
  }

  return false;
}

ScalarEvolution::LoopProperties
ScalarEvolution::getLoopProperties(const Loop *L) {
  using LoopProperties = ScalarEvolution::LoopProperties;

  auto Itr = LoopPropertiesCache.find(L);
  if (Itr == LoopPropertiesCache.end()) {
    auto HasSideEffects = [](Instruction *I) {
      if (auto *SI = dyn_cast<StoreInst>(I))
        return !SI->isSimple();

      return I->mayThrow() || I->mayWriteToMemory();
    };

    LoopProperties LP = {/* HasNoAbnormalExits */ true,
                         /*HasNoSideEffects*/ true};

    for (auto *BB : L->getBlocks())
      for (auto &I : *BB) {
        if (!isGuaranteedToTransferExecutionToSuccessor(&I))
          LP.HasNoAbnormalExits = false;
        if (HasSideEffects(&I))
          LP.HasNoSideEffects = false;
        if (!LP.HasNoAbnormalExits && !LP.HasNoSideEffects)
          break; // We're already as pessimistic as we can get.
      }

    auto InsertPair = LoopPropertiesCache.insert({L, LP});
    assert(InsertPair.second && "We just checked!");
    Itr = InsertPair.first;
  }

  return Itr->second;
}

bool ScalarEvolution::loopIsFiniteByAssumption(const Loop *L) {
  // A mustprogress loop without side effects must be finite.
  // TODO: The check used here is very conservative.  It's only *specific*
  // side effects which are well defined in infinite loops.
  return isFinite(L) || (isMustProgress(L) && loopHasNoSideEffects(L));
}

const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
  // Worklist item with a Value and a bool indicating whether all operands have
  // been visited already.
  using PointerTy = PointerIntPair<Value *, 1, bool>;
  SmallVector<PointerTy> Stack;

  Stack.emplace_back(V, true);
  Stack.emplace_back(V, false);
  while (!Stack.empty()) {
    auto E = Stack.pop_back_val();
    Value *CurV = E.getPointer();

    if (getExistingSCEV(CurV))
      continue;

    SmallVector<Value *> Ops;
    const SCEV *CreatedSCEV = nullptr;
    // If all operands have been visited already, create the SCEV.
    if (E.getInt()) {
      CreatedSCEV = createSCEV(CurV);
    } else {
      // Otherwise get the operands we need to create SCEV's for before creating
      // the SCEV for CurV. If the SCEV for CurV can be constructed trivially,
      // just use it.
      CreatedSCEV = getOperandsToCreate(CurV, Ops);
    }

    if (CreatedSCEV) {
      insertValueToMap(CurV, CreatedSCEV);
    } else {
      // Queue CurV for SCEV creation, followed by its's operands which need to
      // be constructed first.
      Stack.emplace_back(CurV, true);
      for (Value *Op : Ops)
        Stack.emplace_back(Op, false);
    }
  }

  return getExistingSCEV(V);
}

const SCEV *
ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
  if (!isSCEVable(V->getType()))
    return getUnknown(V);

  if (Instruction *I = dyn_cast<Instruction>(V)) {
    // Don't attempt to analyze instructions in blocks that aren't
    // reachable. Such instructions don't matter, and they aren't required
    // to obey basic rules for definitions dominating uses which this
    // analysis depends on.
    if (!DT.isReachableFromEntry(I->getParent()))
      return getUnknown(PoisonValue::get(V->getType()));
  } else if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
    return getConstant(CI);
  else if (isa<GlobalAlias>(V))
    return getUnknown(V);
  else if (!isa<ConstantExpr>(V))
    return getUnknown(V);

  Operator *U = cast<Operator>(V);
  if (auto BO =
          MatchBinaryOp(U, getDataLayout(), AC, DT, dyn_cast<Instruction>(V))) {
    bool IsConstArg = isa<ConstantInt>(BO->RHS);
    switch (BO->Opcode) {
    case Instruction::Add:
    case Instruction::Mul: {
      // For additions and multiplications, traverse add/mul chains for which we
      // can potentially create a single SCEV, to reduce the number of
      // get{Add,Mul}Expr calls.
      do {
        if (BO->Op) {
          if (BO->Op != V && getExistingSCEV(BO->Op)) {
            Ops.push_back(BO->Op);
            break;
          }
        }
        Ops.push_back(BO->RHS);
        auto NewBO = MatchBinaryOp(BO->LHS, getDataLayout(), AC, DT,
                                   dyn_cast<Instruction>(V));
        if (!NewBO ||
            (BO->Opcode == Instruction::Add &&
             (NewBO->Opcode != Instruction::Add &&
              NewBO->Opcode != Instruction::Sub)) ||
            (BO->Opcode == Instruction::Mul &&
             NewBO->Opcode != Instruction::Mul)) {
          Ops.push_back(BO->LHS);
          break;
        }
        // CreateSCEV calls getNoWrapFlagsFromUB, which under certain conditions
        // requires a SCEV for the LHS.
        if (BO->Op && (BO->IsNSW || BO->IsNUW)) {
          auto *I = dyn_cast<Instruction>(BO->Op);
          if (I && programUndefinedIfPoison(I)) {
            Ops.push_back(BO->LHS);
            break;
          }
        }
        BO = NewBO;
      } while (true);
      return nullptr;
    }
    case Instruction::Sub:
    case Instruction::UDiv:
    case Instruction::URem:
      break;
    case Instruction::AShr:
    case Instruction::Shl:
    case Instruction::Xor:
      if (!IsConstArg)
        return nullptr;
      break;
    case Instruction::And:
    case Instruction::Or:
      if (!IsConstArg && !BO->LHS->getType()->isIntegerTy(1))
        return nullptr;
      break;
    case Instruction::LShr:
      return getUnknown(V);
    default:
      llvm_unreachable("Unhandled binop");
      break;
    }

    Ops.push_back(BO->LHS);
    Ops.push_back(BO->RHS);
    return nullptr;
  }

  switch (U->getOpcode()) {
  case Instruction::Trunc:
  case Instruction::ZExt:
  case Instruction::SExt:
  case Instruction::PtrToInt:
    Ops.push_back(U->getOperand(0));
    return nullptr;

  case Instruction::BitCast:
    if (isSCEVable(U->getType()) && isSCEVable(U->getOperand(0)->getType())) {
      Ops.push_back(U->getOperand(0));
      return nullptr;
    }
    return getUnknown(V);

  case Instruction::SDiv:
  case Instruction::SRem:
    Ops.push_back(U->getOperand(0));
    Ops.push_back(U->getOperand(1));
    return nullptr;

  case Instruction::GetElementPtr:
    assert(cast<GEPOperator>(U)->getSourceElementType()->isSized() &&
           "GEP source element type must be sized");
    for (Value *Index : U->operands())
      Ops.push_back(Index);
    return nullptr;

  case Instruction::IntToPtr:
    return getUnknown(V);

  case Instruction::PHI:
    // Keep constructing SCEVs' for phis recursively for now.
    return nullptr;

  case Instruction::Select: {
    // Check if U is a select that can be simplified to a SCEVUnknown.
    auto CanSimplifyToUnknown = [this, U]() {
      if (U->getType()->isIntegerTy(1) || isa<ConstantInt>(U->getOperand(0)))
        return false;

      auto *ICI = dyn_cast<ICmpInst>(U->getOperand(0));
      if (!ICI)
        return false;
      Value *LHS = ICI->getOperand(0);
      Value *RHS = ICI->getOperand(1);
      if (ICI->getPredicate() == CmpInst::ICMP_EQ ||
          ICI->getPredicate() == CmpInst::ICMP_NE) {
        if (!(isa<ConstantInt>(RHS) && cast<ConstantInt>(RHS)->isZero()))
          return true;
      } else if (getTypeSizeInBits(LHS->getType()) >
                 getTypeSizeInBits(U->getType()))
        return true;
      return false;
    };
    if (CanSimplifyToUnknown())
      return getUnknown(U);

    for (Value *Inc : U->operands())
      Ops.push_back(Inc);
    return nullptr;
    break;
  }
  case Instruction::Call:
  case Instruction::Invoke:
    if (Value *RV = cast<CallBase>(U)->getReturnedArgOperand()) {
      Ops.push_back(RV);
      return nullptr;
    }

    if (auto *II = dyn_cast<IntrinsicInst>(U)) {
      switch (II->getIntrinsicID()) {
      case Intrinsic::abs:
        Ops.push_back(II->getArgOperand(0));
        return nullptr;
      case Intrinsic::umax:
      case Intrinsic::umin:
      case Intrinsic::smax:
      case Intrinsic::smin:
      case Intrinsic::usub_sat:
      case Intrinsic::uadd_sat:
        Ops.push_back(II->getArgOperand(0));
        Ops.push_back(II->getArgOperand(1));
        return nullptr;
      case Intrinsic::start_loop_iterations:
      case Intrinsic::annotation:
      case Intrinsic::ptr_annotation:
        Ops.push_back(II->getArgOperand(0));
        return nullptr;
      default:
        break;
      }
    }
    break;
  }

  return nullptr;
}

const SCEV *ScalarEvolution::createSCEV(Value *V) {
  if (!isSCEVable(V->getType()))
    return getUnknown(V);

  if (Instruction *I = dyn_cast<Instruction>(V)) {
    // Don't attempt to analyze instructions in blocks that aren't
    // reachable. Such instructions don't matter, and they aren't required
    // to obey basic rules for definitions dominating uses which this
    // analysis depends on.
    if (!DT.isReachableFromEntry(I->getParent()))
      return getUnknown(PoisonValue::get(V->getType()));
  } else if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
    return getConstant(CI);
  else if (isa<GlobalAlias>(V))
    return getUnknown(V);
  else if (!isa<ConstantExpr>(V))
    return getUnknown(V);

  const SCEV *LHS;
  const SCEV *RHS;

  Operator *U = cast<Operator>(V);
  if (auto BO =
          MatchBinaryOp(U, getDataLayout(), AC, DT, dyn_cast<Instruction>(V))) {
    switch (BO->Opcode) {
    case Instruction::Add: {
      // The simple thing to do would be to just call getSCEV on both operands
      // and call getAddExpr with the result. However if we're looking at a
      // bunch of things all added together, this can be quite inefficient,
      // because it leads to N-1 getAddExpr calls for N ultimate operands.
      // Instead, gather up all the operands and make a single getAddExpr call.
      // LLVM IR canonical form means we need only traverse the left operands.
      SmallVector<const SCEV *, 4> AddOps;
      do {
        if (BO->Op) {
          if (auto *OpSCEV = getExistingSCEV(BO->Op)) {
            AddOps.push_back(OpSCEV);
            break;
          }

          // If a NUW or NSW flag can be applied to the SCEV for this
          // addition, then compute the SCEV for this addition by itself
          // with a separate call to getAddExpr. We need to do that
          // instead of pushing the operands of the addition onto AddOps,
          // since the flags are only known to apply to this particular
          // addition - they may not apply to other additions that can be
          // formed with operands from AddOps.
          const SCEV *RHS = getSCEV(BO->RHS);
          SCEV::NoWrapFlags Flags = getNoWrapFlagsFromUB(BO->Op);
          if (Flags != SCEV::FlagAnyWrap) {
            const SCEV *LHS = getSCEV(BO->LHS);
            if (BO->Opcode == Instruction::Sub)
              AddOps.push_back(getMinusSCEV(LHS, RHS, Flags));
            else
              AddOps.push_back(getAddExpr(LHS, RHS, Flags));
            break;
          }
        }

        if (BO->Opcode == Instruction::Sub)
          AddOps.push_back(getNegativeSCEV(getSCEV(BO->RHS)));
        else
          AddOps.push_back(getSCEV(BO->RHS));

        auto NewBO = MatchBinaryOp(BO->LHS, getDataLayout(), AC, DT,
                                   dyn_cast<Instruction>(V));
        if (!NewBO || (NewBO->Opcode != Instruction::Add &&
                       NewBO->Opcode != Instruction::Sub)) {
          AddOps.push_back(getSCEV(BO->LHS));
          break;
        }
        BO = NewBO;
      } while (true);

      return getAddExpr(AddOps);
    }

    case Instruction::Mul: {
      SmallVector<const SCEV *, 4> MulOps;
      do {
        if (BO->Op) {
          if (auto *OpSCEV = getExistingSCEV(BO->Op)) {
            MulOps.push_back(OpSCEV);
            break;
          }

          SCEV::NoWrapFlags Flags = getNoWrapFlagsFromUB(BO->Op);
          if (Flags != SCEV::FlagAnyWrap) {
            LHS = getSCEV(BO->LHS);
            RHS = getSCEV(BO->RHS);
            MulOps.push_back(getMulExpr(LHS, RHS, Flags));
            break;
          }
        }

        MulOps.push_back(getSCEV(BO->RHS));
        auto NewBO = MatchBinaryOp(BO->LHS, getDataLayout(), AC, DT,
                                   dyn_cast<Instruction>(V));
        if (!NewBO || NewBO->Opcode != Instruction::Mul) {
          MulOps.push_back(getSCEV(BO->LHS));
          break;
        }
        BO = NewBO;
      } while (true);

      return getMulExpr(MulOps);
    }
    case Instruction::UDiv:
      LHS = getSCEV(BO->LHS);
      RHS = getSCEV(BO->RHS);
      return getUDivExpr(LHS, RHS);
    case Instruction::URem:
      LHS = getSCEV(BO->LHS);
      RHS = getSCEV(BO->RHS);
      return getURemExpr(LHS, RHS);
    case Instruction::Sub: {
      SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;
      if (BO->Op)
        Flags = getNoWrapFlagsFromUB(BO->Op);
      LHS = getSCEV(BO->LHS);
      RHS = getSCEV(BO->RHS);
      return getMinusSCEV(LHS, RHS, Flags);
    }
    case Instruction::And:
      // For an expression like x&255 that merely masks off the high bits,
      // use zext(trunc(x)) as the SCEV expression.
      if (ConstantInt *CI = dyn_cast<ConstantInt>(BO->RHS)) {
        if (CI->isZero())
          return getSCEV(BO->RHS);
        if (CI->isMinusOne())
          return getSCEV(BO->LHS);
        const APInt &A = CI->getValue();

        // Instcombine's ShrinkDemandedConstant may strip bits out of
        // constants, obscuring what would otherwise be a low-bits mask.
        // Use computeKnownBits to compute what ShrinkDemandedConstant
        // knew about to reconstruct a low-bits mask value.
        unsigned LZ = A.countl_zero();
        unsigned TZ = A.countr_zero();
        unsigned BitWidth = A.getBitWidth();
        KnownBits Known(BitWidth);
        computeKnownBits(BO->LHS, Known, getDataLayout(),
                         0, &AC, nullptr, &DT);

        APInt EffectiveMask =
            APInt::getLowBitsSet(BitWidth, BitWidth - LZ - TZ).shl(TZ);
        if ((LZ != 0 || TZ != 0) && !((~A & ~Known.Zero) & EffectiveMask)) {
          const SCEV *MulCount = getConstant(APInt::getOneBitSet(BitWidth, TZ));
          const SCEV *LHS = getSCEV(BO->LHS);
          const SCEV *ShiftedLHS = nullptr;
          if (auto *LHSMul = dyn_cast<SCEVMulExpr>(LHS)) {
            if (auto *OpC = dyn_cast<SCEVConstant>(LHSMul->getOperand(0))) {
              // For an expression like (x * 8) & 8, simplify the multiply.
              unsigned MulZeros = OpC->getAPInt().countr_zero();
              unsigned GCD = std::min(MulZeros, TZ);
              APInt DivAmt = APInt::getOneBitSet(BitWidth, TZ - GCD);
              SmallVector<const SCEV*, 4> MulOps;
              MulOps.push_back(getConstant(OpC->getAPInt().lshr(GCD)));
              append_range(MulOps, LHSMul->operands().drop_front());
              auto *NewMul = getMulExpr(MulOps, LHSMul->getNoWrapFlags());
              ShiftedLHS = getUDivExpr(NewMul, getConstant(DivAmt));
            }
          }
          if (!ShiftedLHS)
            ShiftedLHS = getUDivExpr(LHS, MulCount);
          return getMulExpr(
              getZeroExtendExpr(
                  getTruncateExpr(ShiftedLHS,
                      IntegerType::get(getContext(), BitWidth - LZ - TZ)),
                  BO->LHS->getType()),
              MulCount);
        }
      }
      // Binary `and` is a bit-wise `umin`.
      if (BO->LHS->getType()->isIntegerTy(1)) {
        LHS = getSCEV(BO->LHS);
        RHS = getSCEV(BO->RHS);
        return getUMinExpr(LHS, RHS);
      }
      break;

    case Instruction::Or:
      // Binary `or` is a bit-wise `umax`.
      if (BO->LHS->getType()->isIntegerTy(1)) {
        LHS = getSCEV(BO->LHS);
        RHS = getSCEV(BO->RHS);
        return getUMaxExpr(LHS, RHS);
      }
      break;

    case Instruction::Xor:
      if (ConstantInt *CI = dyn_cast<ConstantInt>(BO->RHS)) {
        // If the RHS of xor is -1, then this is a not operation.
        if (CI->isMinusOne())
          return getNotSCEV(getSCEV(BO->LHS));

        // Model xor(and(x, C), C) as and(~x, C), if C is a low-bits mask.
        // This is a variant of the check for xor with -1, and it handles
        // the case where instcombine has trimmed non-demanded bits out
        // of an xor with -1.
        if (auto *LBO = dyn_cast<BinaryOperator>(BO->LHS))
          if (ConstantInt *LCI = dyn_cast<ConstantInt>(LBO->getOperand(1)))
            if (LBO->getOpcode() == Instruction::And &&
                LCI->getValue() == CI->getValue())
              if (const SCEVZeroExtendExpr *Z =
                      dyn_cast<SCEVZeroExtendExpr>(getSCEV(BO->LHS))) {
                Type *UTy = BO->LHS->getType();
                const SCEV *Z0 = Z->getOperand();
                Type *Z0Ty = Z0->getType();
                unsigned Z0TySize = getTypeSizeInBits(Z0Ty);

                // If C is a low-bits mask, the zero extend is serving to
                // mask off the high bits. Complement the operand and
                // re-apply the zext.
                if (CI->getValue().isMask(Z0TySize))
                  return getZeroExtendExpr(getNotSCEV(Z0), UTy);

                // If C is a single bit, it may be in the sign-bit position
                // before the zero-extend. In this case, represent the xor
                // using an add, which is equivalent, and re-apply the zext.
                APInt Trunc = CI->getValue().trunc(Z0TySize);
                if (Trunc.zext(getTypeSizeInBits(UTy)) == CI->getValue() &&
                    Trunc.isSignMask())
                  return getZeroExtendExpr(getAddExpr(Z0, getConstant(Trunc)),
                                           UTy);
              }
      }
      break;

    case Instruction::Shl:
      // Turn shift left of a constant amount into a multiply.
      if (ConstantInt *SA = dyn_cast<ConstantInt>(BO->RHS)) {
        uint32_t BitWidth = cast<IntegerType>(SA->getType())->getBitWidth();

        // If the shift count is not less than the bitwidth, the result of
        // the shift is undefined. Don't try to analyze it, because the
        // resolution chosen here may differ from the resolution chosen in
        // other parts of the compiler.
        if (SA->getValue().uge(BitWidth))
          break;

        // We can safely preserve the nuw flag in all cases. It's also safe to
        // turn a nuw nsw shl into a nuw nsw mul. However, nsw in isolation
        // requires special handling. It can be preserved as long as we're not
        // left shifting by bitwidth - 1.
        auto Flags = SCEV::FlagAnyWrap;
        if (BO->Op) {
          auto MulFlags = getNoWrapFlagsFromUB(BO->Op);
          if ((MulFlags & SCEV::FlagNSW) &&
              ((MulFlags & SCEV::FlagNUW) || SA->getValue().ult(BitWidth - 1)))
            Flags = (SCEV::NoWrapFlags)(Flags | SCEV::FlagNSW);
          if (MulFlags & SCEV::FlagNUW)
            Flags = (SCEV::NoWrapFlags)(Flags | SCEV::FlagNUW);
        }

        ConstantInt *X = ConstantInt::get(
            getContext(), APInt::getOneBitSet(BitWidth, SA->getZExtValue()));
        return getMulExpr(getSCEV(BO->LHS), getConstant(X), Flags);
      }
      break;

    case Instruction::AShr: {
      // AShr X, C, where C is a constant.
      ConstantInt *CI = dyn_cast<ConstantInt>(BO->RHS);
      if (!CI)
        break;

      Type *OuterTy = BO->LHS->getType();
      uint64_t BitWidth = getTypeSizeInBits(OuterTy);
      // If the shift count is not less than the bitwidth, the result of
      // the shift is undefined. Don't try to analyze it, because the
      // resolution chosen here may differ from the resolution chosen in
      // other parts of the compiler.
      if (CI->getValue().uge(BitWidth))
        break;

      if (CI->isZero())
        return getSCEV(BO->LHS); // shift by zero --> noop

      uint64_t AShrAmt = CI->getZExtValue();
      Type *TruncTy = IntegerType::get(getContext(), BitWidth - AShrAmt);

      Operator *L = dyn_cast<Operator>(BO->LHS);
      if (L && L->getOpcode() == Instruction::Shl) {
        // X = Shl A, n
        // Y = AShr X, m
        // Both n and m are constant.

        const SCEV *ShlOp0SCEV = getSCEV(L->getOperand(0));
        if (L->getOperand(1) == BO->RHS)
          // For a two-shift sext-inreg, i.e. n = m,
          // use sext(trunc(x)) as the SCEV expression.
          return getSignExtendExpr(
              getTruncateExpr(ShlOp0SCEV, TruncTy), OuterTy);

        ConstantInt *ShlAmtCI = dyn_cast<ConstantInt>(L->getOperand(1));
        if (ShlAmtCI && ShlAmtCI->getValue().ult(BitWidth)) {
          uint64_t ShlAmt = ShlAmtCI->getZExtValue();
          if (ShlAmt > AShrAmt) {
            // When n > m, use sext(mul(trunc(x), 2^(n-m)))) as the SCEV
            // expression. We already checked that ShlAmt < BitWidth, so
            // the multiplier, 1 << (ShlAmt - AShrAmt), fits into TruncTy as
            // ShlAmt - AShrAmt < Amt.
            APInt Mul = APInt::getOneBitSet(BitWidth - AShrAmt,
                                            ShlAmt - AShrAmt);
            return getSignExtendExpr(
                getMulExpr(getTruncateExpr(ShlOp0SCEV, TruncTy),
                getConstant(Mul)), OuterTy);
          }
        }
      }
      break;
    }
    }
  }

  switch (U->getOpcode()) {
  case Instruction::Trunc:
    return getTruncateExpr(getSCEV(U->getOperand(0)), U->getType());

  case Instruction::ZExt:
    return getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType());

  case Instruction::SExt:
    if (auto BO = MatchBinaryOp(U->getOperand(0), getDataLayout(), AC, DT,
                                dyn_cast<Instruction>(V))) {
      // The NSW flag of a subtract does not always survive the conversion to
      // A + (-1)*B.  By pushing sign extension onto its operands we are much
      // more likely to preserve NSW and allow later AddRec optimisations.
      //
      // NOTE: This is effectively duplicating this logic from getSignExtend:
      //   sext((A + B + ...)<nsw>) --> (sext(A) + sext(B) + ...)<nsw>
      // but by that point the NSW information has potentially been lost.
      if (BO->Opcode == Instruction::Sub && BO->IsNSW) {
        Type *Ty = U->getType();
        auto *V1 = getSignExtendExpr(getSCEV(BO->LHS), Ty);
        auto *V2 = getSignExtendExpr(getSCEV(BO->RHS), Ty);
        return getMinusSCEV(V1, V2, SCEV::FlagNSW);
      }
    }
    return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType());

  case Instruction::BitCast:
    // BitCasts are no-op casts so we just eliminate the cast.
    if (isSCEVable(U->getType()) && isSCEVable(U->getOperand(0)->getType()))
      return getSCEV(U->getOperand(0));
    break;

  case Instruction::PtrToInt: {
    // Pointer to integer cast is straight-forward, so do model it.
    const SCEV *Op = getSCEV(U->getOperand(0));
    Type *DstIntTy = U->getType();
    // But only if effective SCEV (integer) type is wide enough to represent
    // all possible pointer values.
    const SCEV *IntOp = getPtrToIntExpr(Op, DstIntTy);
    if (isa<SCEVCouldNotCompute>(IntOp))
      return getUnknown(V);
    return IntOp;
  }
  case Instruction::IntToPtr:
    // Just don't deal with inttoptr casts.
    return getUnknown(V);

  case Instruction::SDiv:
    // If both operands are non-negative, this is just an udiv.
    if (isKnownNonNegative(getSCEV(U->getOperand(0))) &&
        isKnownNonNegative(getSCEV(U->getOperand(1))))
      return getUDivExpr(getSCEV(U->getOperand(0)), getSCEV(U->getOperand(1)));
    break;

  case Instruction::SRem:
    // If both operands are non-negative, this is just an urem.
    if (isKnownNonNegative(getSCEV(U->getOperand(0))) &&
        isKnownNonNegative(getSCEV(U->getOperand(1))))
      return getURemExpr(getSCEV(U->getOperand(0)), getSCEV(U->getOperand(1)));
    break;

  case Instruction::GetElementPtr:
    return createNodeForGEP(cast<GEPOperator>(U));

  case Instruction::PHI:
    return createNodeForPHI(cast<PHINode>(U));

  case Instruction::Select:
    return createNodeForSelectOrPHI(U, U->getOperand(0), U->getOperand(1),
                                    U->getOperand(2));

  case Instruction::Call:
  case Instruction::Invoke:
    if (Value *RV = cast<CallBase>(U)->getReturnedArgOperand())
      return getSCEV(RV);

    if (auto *II = dyn_cast<IntrinsicInst>(U)) {
      switch (II->getIntrinsicID()) {
      case Intrinsic::abs:
        return getAbsExpr(
            getSCEV(II->getArgOperand(0)),
            /*IsNSW=*/cast<ConstantInt>(II->getArgOperand(1))->isOne());
      case Intrinsic::umax:
        LHS = getSCEV(II->getArgOperand(0));
        RHS = getSCEV(II->getArgOperand(1));
        return getUMaxExpr(LHS, RHS);
      case Intrinsic::umin:
        LHS = getSCEV(II->getArgOperand(0));
        RHS = getSCEV(II->getArgOperand(1));
        return getUMinExpr(LHS, RHS);
      case Intrinsic::smax:
        LHS = getSCEV(II->getArgOperand(0));
        RHS = getSCEV(II->getArgOperand(1));
        return getSMaxExpr(LHS, RHS);
      case Intrinsic::smin:
        LHS = getSCEV(II->getArgOperand(0));
        RHS = getSCEV(II->getArgOperand(1));
        return getSMinExpr(LHS, RHS);
      case Intrinsic::usub_sat: {
        const SCEV *X = getSCEV(II->getArgOperand(0));
        const SCEV *Y = getSCEV(II->getArgOperand(1));
        const SCEV *ClampedY = getUMinExpr(X, Y);
        return getMinusSCEV(X, ClampedY, SCEV::FlagNUW);
      }
      case Intrinsic::uadd_sat: {
        const SCEV *X = getSCEV(II->getArgOperand(0));
        const SCEV *Y = getSCEV(II->getArgOperand(1));
        const SCEV *ClampedX = getUMinExpr(X, getNotSCEV(Y));
        return getAddExpr(ClampedX, Y, SCEV::FlagNUW);
      }
      case Intrinsic::start_loop_iterations:
      case Intrinsic::annotation:
      case Intrinsic::ptr_annotation:
        // A start_loop_iterations or llvm.annotation or llvm.prt.annotation is
        // just eqivalent to the first operand for SCEV purposes.
        return getSCEV(II->getArgOperand(0));
      case Intrinsic::vscale:
        return getVScale(II->getType());
      default:
        break;
      }
    }
    break;
  }

  return getUnknown(V);
}

//===----------------------------------------------------------------------===//
//                   Iteration Count Computation Code
//

const SCEV *ScalarEvolution::getTripCountFromExitCount(const SCEV *ExitCount) {
  if (isa<SCEVCouldNotCompute>(ExitCount))
    return getCouldNotCompute();

  auto *ExitCountType = ExitCount->getType();
  assert(ExitCountType->isIntegerTy());
  auto *EvalTy = Type::getIntNTy(ExitCountType->getContext(),
                                 1 + ExitCountType->getScalarSizeInBits());
  return getTripCountFromExitCount(ExitCount, EvalTy, nullptr);
}

const SCEV *ScalarEvolution::getTripCountFromExitCount(const SCEV *ExitCount,
                                                       Type *EvalTy,
                                                       const Loop *L) {
  if (isa<SCEVCouldNotCompute>(ExitCount))
    return getCouldNotCompute();

  unsigned ExitCountSize = getTypeSizeInBits(ExitCount->getType());
  unsigned EvalSize = EvalTy->getPrimitiveSizeInBits();

  auto CanAddOneWithoutOverflow = [&]() {
    ConstantRange ExitCountRange =
      getRangeRef(ExitCount, RangeSignHint::HINT_RANGE_UNSIGNED);
    if (!ExitCountRange.contains(APInt::getMaxValue(ExitCountSize)))
      return true;

    return L && isLoopEntryGuardedByCond(L, ICmpInst::ICMP_NE, ExitCount,
                                         getMinusOne(ExitCount->getType()));
  };

  // If we need to zero extend the backedge count, check if we can add one to
  // it prior to zero extending without overflow. Provided this is safe, it
  // allows better simplification of the +1.
  if (EvalSize > ExitCountSize && CanAddOneWithoutOverflow())
    return getZeroExtendExpr(
        getAddExpr(ExitCount, getOne(ExitCount->getType())), EvalTy);

  // Get the total trip count from the count by adding 1.  This may wrap.
  return getAddExpr(getTruncateOrZeroExtend(ExitCount, EvalTy), getOne(EvalTy));
}

static unsigned getConstantTripCount(const SCEVConstant *ExitCount) {
  if (!ExitCount)
    return 0;

  ConstantInt *ExitConst = ExitCount->getValue();

  // Guard against huge trip counts.
  if (ExitConst->getValue().getActiveBits() > 32)
    return 0;

  // In case of integer overflow, this returns 0, which is correct.
  return ((unsigned)ExitConst->getZExtValue()) + 1;
}

unsigned ScalarEvolution::getSmallConstantTripCount(const Loop *L) {
  auto *ExitCount = dyn_cast<SCEVConstant>(getBackedgeTakenCount(L, Exact));
  return getConstantTripCount(ExitCount);
}

unsigned
ScalarEvolution::getSmallConstantTripCount(const Loop *L,
                                           const BasicBlock *ExitingBlock) {
  assert(ExitingBlock && "Must pass a non-null exiting block!");
  assert(L->isLoopExiting(ExitingBlock) &&
         "Exiting block must actually branch out of the loop!");
  const SCEVConstant *ExitCount =
      dyn_cast<SCEVConstant>(getExitCount(L, ExitingBlock));
  return getConstantTripCount(ExitCount);
}

unsigned ScalarEvolution::getSmallConstantMaxTripCount(const Loop *L) {
  const auto *MaxExitCount =
      dyn_cast<SCEVConstant>(getConstantMaxBackedgeTakenCount(L));
  return getConstantTripCount(MaxExitCount);
}

unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L) {
  SmallVector<BasicBlock *, 8> ExitingBlocks;
  L->getExitingBlocks(ExitingBlocks);

  std::optional<unsigned> Res;
  for (auto *ExitingBB : ExitingBlocks) {
    unsigned Multiple = getSmallConstantTripMultiple(L, ExitingBB);
    if (!Res)
      Res = Multiple;
    Res = (unsigned)std::gcd(*Res, Multiple);
  }
  return Res.value_or(1);
}

unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L,
                                                       const SCEV *ExitCount) {
  if (ExitCount == getCouldNotCompute())
    return 1;

  // Get the trip count
  const SCEV *TCExpr = getTripCountFromExitCount(applyLoopGuards(ExitCount, L));

  APInt Multiple = getNonZeroConstantMultiple(TCExpr);
  // If a trip multiple is huge (>=2^32), the trip count is still divisible by
  // the greatest power of 2 divisor less than 2^32.
  return Multiple.getActiveBits() > 32
             ? 1U << std::min((unsigned)31, Multiple.countTrailingZeros())
             : (unsigned)Multiple.zextOrTrunc(32).getZExtValue();
}

/// Returns the largest constant divisor of the trip count of this loop as a
/// normal unsigned value, if possible. This means that the actual trip count is
/// always a multiple of the returned value (don't forget the trip count could
/// very well be zero as well!).
///
/// Returns 1 if the trip count is unknown or not guaranteed to be the
/// multiple of a constant (which is also the case if the trip count is simply
/// constant, use getSmallConstantTripCount for that case), Will also return 1
/// if the trip count is very large (>= 2^32).
///
/// As explained in the comments for getSmallConstantTripCount, this assumes
/// that control exits the loop via ExitingBlock.
unsigned
ScalarEvolution::getSmallConstantTripMultiple(const Loop *L,
                                              const BasicBlock *ExitingBlock) {
  assert(ExitingBlock && "Must pass a non-null exiting block!");
  assert(L->isLoopExiting(ExitingBlock) &&
         "Exiting block must actually branch out of the loop!");
  const SCEV *ExitCount = getExitCount(L, ExitingBlock);
  return getSmallConstantTripMultiple(L, ExitCount);
}

const SCEV *ScalarEvolution::getExitCount(const Loop *L,
                                          const BasicBlock *ExitingBlock,
                                          ExitCountKind Kind) {
  switch (Kind) {
  case Exact:
    return getBackedgeTakenInfo(L).getExact(ExitingBlock, this);
  case SymbolicMaximum:
    return getBackedgeTakenInfo(L).getSymbolicMax(ExitingBlock, this);
  case ConstantMaximum:
    return getBackedgeTakenInfo(L).getConstantMax(ExitingBlock, this);
  };
  llvm_unreachable("Invalid ExitCountKind!");
}

const SCEV *
ScalarEvolution::getPredicatedBackedgeTakenCount(const Loop *L,
                                                 SmallVector<const SCEVPredicate *, 4> &Preds) {
  return getPredicatedBackedgeTakenInfo(L).getExact(L, this, &Preds);
}

const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L,
                                                   ExitCountKind Kind) {
  switch (Kind) {
  case Exact:
    return getBackedgeTakenInfo(L).getExact(L, this);
  case ConstantMaximum:
    return getBackedgeTakenInfo(L).getConstantMax(this);
  case SymbolicMaximum:
    return getBackedgeTakenInfo(L).getSymbolicMax(L, this);
  };
  llvm_unreachable("Invalid ExitCountKind!");
}

bool ScalarEvolution::isBackedgeTakenCountMaxOrZero(const Loop *L) {
  return getBackedgeTakenInfo(L).isConstantMaxOrZero(this);
}

/// Push PHI nodes in the header of the given loop onto the given Worklist.
static void PushLoopPHIs(const Loop *L,
                         SmallVectorImpl<Instruction *> &Worklist,
                         SmallPtrSetImpl<Instruction *> &Visited) {
  BasicBlock *Header = L->getHeader();

  // Push all Loop-header PHIs onto the Worklist stack.
  for (PHINode &PN : Header->phis())
    if (Visited.insert(&PN).second)
      Worklist.push_back(&PN);
}

const ScalarEvolution::BackedgeTakenInfo &
ScalarEvolution::getPredicatedBackedgeTakenInfo(const Loop *L) {
  auto &BTI = getBackedgeTakenInfo(L);
  if (BTI.hasFullInfo())
    return BTI;

  auto Pair = PredicatedBackedgeTakenCounts.insert({L, BackedgeTakenInfo()});

  if (!Pair.second)
    return Pair.first->second;

  BackedgeTakenInfo Result =
      computeBackedgeTakenCount(L, /*AllowPredicates=*/true);

  return PredicatedBackedgeTakenCounts.find(L)->second = std::move(Result);
}

ScalarEvolution::BackedgeTakenInfo &
ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
  // Initially insert an invalid entry for this loop. If the insertion
  // succeeds, proceed to actually compute a backedge-taken count and
  // update the value. The temporary CouldNotCompute value tells SCEV
  // code elsewhere that it shouldn't attempt to request a new
  // backedge-taken count, which could result in infinite recursion.
  std::pair<DenseMap<const Loop *, BackedgeTakenInfo>::iterator, bool> Pair =
      BackedgeTakenCounts.insert({L, BackedgeTakenInfo()});
  if (!Pair.second)
    return Pair.first->second;

  // computeBackedgeTakenCount may allocate memory for its result. Inserting it
  // into the BackedgeTakenCounts map transfers ownership. Otherwise, the result
  // must be cleared in this scope.
  BackedgeTakenInfo Result = computeBackedgeTakenCount(L);

  // Now that we know more about the trip count for this loop, forget any
  // existing SCEV values for PHI nodes in this loop since they are only
  // conservative estimates made without the benefit of trip count
  // information. This invalidation is not necessary for correctness, and is
  // only done to produce more precise results.
  if (Result.hasAnyInfo()) {
    // Invalidate any expression using an addrec in this loop.
    SmallVector<const SCEV *, 8> ToForget;
    auto LoopUsersIt = LoopUsers.find(L);
    if (LoopUsersIt != LoopUsers.end())
      append_range(ToForget, LoopUsersIt->second);
    forgetMemoizedResults(ToForget);

    // Invalidate constant-evolved loop header phis.
    for (PHINode &PN : L->getHeader()->phis())
      ConstantEvolutionLoopExitValue.erase(&PN);
  }

  // Re-lookup the insert position, since the call to
  // computeBackedgeTakenCount above could result in a
  // recusive call to getBackedgeTakenInfo (on a different
  // loop), which would invalidate the iterator computed
  // earlier.
  return BackedgeTakenCounts.find(L)->second = std::move(Result);
}

void ScalarEvolution::forgetAllLoops() {
  // This method is intended to forget all info about loops. It should
  // invalidate caches as if the following happened:
  // - The trip counts of all loops have changed arbitrarily
  // - Every llvm::Value has been updated in place to produce a different
  // result.
  BackedgeTakenCounts.clear();
  PredicatedBackedgeTakenCounts.clear();
  BECountUsers.clear();
  LoopPropertiesCache.clear();
  ConstantEvolutionLoopExitValue.clear();
  ValueExprMap.clear();
  ValuesAtScopes.clear();
  ValuesAtScopesUsers.clear();
  LoopDispositions.clear();
  BlockDispositions.clear();
  UnsignedRanges.clear();
  SignedRanges.clear();
  ExprValueMap.clear();
  HasRecMap.clear();
  ConstantMultipleCache.clear();
  PredicatedSCEVRewrites.clear();
  FoldCache.clear();
  FoldCacheUser.clear();
}
void ScalarEvolution::visitAndClearUsers(
    SmallVectorImpl<Instruction *> &Worklist,
    SmallPtrSetImpl<Instruction *> &Visited,
    SmallVectorImpl<const SCEV *> &ToForget) {
  while (!Worklist.empty()) {
    Instruction *I = Worklist.pop_back_val();
    if (!isSCEVable(I->getType()))
      continue;

    ValueExprMapType::iterator It =
        ValueExprMap.find_as(static_cast<Value *>(I));
    if (It != ValueExprMap.end()) {
      eraseValueFromMap(It->first);
      ToForget.push_back(It->second);
      if (PHINode *PN = dyn_cast<PHINode>(I))
        ConstantEvolutionLoopExitValue.erase(PN);
    }

    PushDefUseChildren(I, Worklist, Visited);
  }
}

void ScalarEvolution::forgetLoop(const Loop *L) {
  SmallVector<const Loop *, 16> LoopWorklist(1, L);
  SmallVector<Instruction *, 32> Worklist;
  SmallPtrSet<Instruction *, 16> Visited;
  SmallVector<const SCEV *, 16> ToForget;

  // Iterate over all the loops and sub-loops to drop SCEV information.
  while (!LoopWorklist.empty()) {
    auto *CurrL = LoopWorklist.pop_back_val();

    // Drop any stored trip count value.
    forgetBackedgeTakenCounts(CurrL, /* Predicated */ false);
    forgetBackedgeTakenCounts(CurrL, /* Predicated */ true);

    // Drop information about predicated SCEV rewrites for this loop.
    for (auto I = PredicatedSCEVRewrites.begin();
         I != PredicatedSCEVRewrites.end();) {
      std::pair<const SCEV *, const Loop *> Entry = I->first;
      if (Entry.second == CurrL)
        PredicatedSCEVRewrites.erase(I++);
      else
        ++I;
    }

    auto LoopUsersItr = LoopUsers.find(CurrL);
    if (LoopUsersItr != LoopUsers.end()) {
      ToForget.insert(ToForget.end(), LoopUsersItr->second.begin(),
                LoopUsersItr->second.end());
    }

    // Drop information about expressions based on loop-header PHIs.
    PushLoopPHIs(CurrL, Worklist, Visited);
    visitAndClearUsers(Worklist, Visited, ToForget);

    LoopPropertiesCache.erase(CurrL);
    // Forget all contained loops too, to avoid dangling entries in the
    // ValuesAtScopes map.
    LoopWorklist.append(CurrL->begin(), CurrL->end());
  }
  forgetMemoizedResults(ToForget);
}

void ScalarEvolution::forgetTopmostLoop(const Loop *L) {
  forgetLoop(L->getOutermostLoop());
}

void ScalarEvolution::forgetValue(Value *V) {
  Instruction *I = dyn_cast<Instruction>(V);
  if (!I) return;

  // Drop information about expressions based on loop-header PHIs.
  SmallVector<Instruction *, 16> Worklist;
  SmallPtrSet<Instruction *, 8> Visited;
  SmallVector<const SCEV *, 8> ToForget;
  Worklist.push_back(I);
  Visited.insert(I);
  visitAndClearUsers(Worklist, Visited, ToForget);

  forgetMemoizedResults(ToForget);
}

void ScalarEvolution::forgetLoopDispositions() { LoopDispositions.clear(); }

void ScalarEvolution::forgetBlockAndLoopDispositions(Value *V) {
  // Unless a specific value is passed to invalidation, completely clear both
  // caches.
  if (!V) {
    BlockDispositions.clear();
    LoopDispositions.clear();
    return;
  }

  if (!isSCEVable(V->getType()))
    return;

  const SCEV *S = getExistingSCEV(V);
  if (!S)
    return;

  // Invalidate the block and loop dispositions cached for S. Dispositions of
  // S's users may change if S's disposition changes (i.e. a user may change to
  // loop-invariant, if S changes to loop invariant), so also invalidate
  // dispositions of S's users recursively.
  SmallVector<const SCEV *, 8> Worklist = {S};
  SmallPtrSet<const SCEV *, 8> Seen = {S};
  while (!Worklist.empty()) {
    const SCEV *Curr = Worklist.pop_back_val();
    bool LoopDispoRemoved = LoopDispositions.erase(Curr);
    bool BlockDispoRemoved = BlockDispositions.erase(Curr);
    if (!LoopDispoRemoved && !BlockDispoRemoved)
      continue;
    auto Users = SCEVUsers.find(Curr);
    if (Users != SCEVUsers.end())
      for (const auto *User : Users->second)
        if (Seen.insert(User).second)
          Worklist.push_back(User);
  }
}

/// Get the exact loop backedge taken count considering all loop exits. A
/// computable result can only be returned for loops with all exiting blocks
/// dominating the latch. howFarToZero assumes that the limit of each loop test
/// is never skipped. This is a valid assumption as long as the loop exits via
/// that test. For precise results, it is the caller's responsibility to specify
/// the relevant loop exiting block using getExact(ExitingBlock, SE).
const SCEV *
ScalarEvolution::BackedgeTakenInfo::getExact(const Loop *L, ScalarEvolution *SE,
                                             SmallVector<const SCEVPredicate *, 4> *Preds) const {
  // If any exits were not computable, the loop is not computable.
  if (!isComplete() || ExitNotTaken.empty())
    return SE->getCouldNotCompute();

  const BasicBlock *Latch = L->getLoopLatch();
  // All exiting blocks we have collected must dominate the only backedge.
  if (!Latch)
    return SE->getCouldNotCompute();

  // 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<const SCEV *, 2> Ops;
  for (const auto &ENT : ExitNotTaken) {
    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!");

    Ops.push_back(BECount);

    if (Preds)
      for (const auto *P : ENT.Predicates)
        Preds->push_back(P);

    assert((Preds || ENT.hasAlwaysTruePredicate()) &&
           "Predicate should be always true!");
  }

  // If an earlier exit exits on the first iteration (exit count zero), then
  // a later poison exit count should not propagate into the result. This are
  // exactly the semantics provided by umin_seq.
  return SE->getUMinFromMismatchedTypes(Ops, /* Sequential */ true);
}

/// Get the exact not taken count for this loop exit.
const SCEV *
ScalarEvolution::BackedgeTakenInfo::getExact(const BasicBlock *ExitingBlock,
                                             ScalarEvolution *SE) const {
  for (const auto &ENT : ExitNotTaken)
    if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePredicate())
      return ENT.ExactNotTaken;

  return SE->getCouldNotCompute();
}

const SCEV *ScalarEvolution::BackedgeTakenInfo::getConstantMax(
    const BasicBlock *ExitingBlock, ScalarEvolution *SE) const {
  for (const auto &ENT : ExitNotTaken)
    if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePredicate())
      return ENT.ConstantMaxNotTaken;

  return SE->getCouldNotCompute();
}

const SCEV *ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(
    const BasicBlock *ExitingBlock, ScalarEvolution *SE) const {
  for (const auto &ENT : ExitNotTaken)
    if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePredicate())
      return ENT.SymbolicMaxNotTaken;

  return SE->getCouldNotCompute();
}

/// getConstantMax - Get the constant max backedge taken count for the loop.
const SCEV *
ScalarEvolution::BackedgeTakenInfo::getConstantMax(ScalarEvolution *SE) const {
  auto PredicateNotAlwaysTrue = [](const ExitNotTakenInfo &ENT) {
    return !ENT.hasAlwaysTruePredicate();
  };

  if (!getConstantMax() || any_of(ExitNotTaken, PredicateNotAlwaysTrue))
    return SE->getCouldNotCompute();

  assert((isa<SCEVCouldNotCompute>(getConstantMax()) ||
          isa<SCEVConstant>(getConstantMax())) &&
         "No point in having a non-constant max backedge taken count!");
  return getConstantMax();
}

const SCEV *
ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(const Loop *L,
                                                   ScalarEvolution *SE) {
  if (!SymbolicMax)
    SymbolicMax = SE->computeSymbolicMaxBackedgeTakenCount(L);
  return SymbolicMax;
}

bool ScalarEvolution::BackedgeTakenInfo::isConstantMaxOrZero(
    ScalarEvolution *SE) const {
  auto PredicateNotAlwaysTrue = [](const ExitNotTakenInfo &ENT) {
    return !ENT.hasAlwaysTruePredicate();
  };
  return MaxOrZero && !any_of(ExitNotTaken, PredicateNotAlwaysTrue);
}

ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E)
    : ExitLimit(E, E, E, false, std::nullopt) {}

ScalarEvolution::ExitLimit::ExitLimit(
    const SCEV *E, const SCEV *ConstantMaxNotTaken,
    const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
    ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *> PredSetList)
    : ExactNotTaken(E), ConstantMaxNotTaken(ConstantMaxNotTaken),
      SymbolicMaxNotTaken(SymbolicMaxNotTaken), MaxOrZero(MaxOrZero) {
  // If we prove the max count is zero, so is the symbolic bound.  This happens
  // in practice due to differences in a) how context sensitive we've chosen
  // to be and b) how we reason about bounds implied by UB.
  if (ConstantMaxNotTaken->isZero()) {
    this->ExactNotTaken = E = ConstantMaxNotTaken;
    this->SymbolicMaxNotTaken = SymbolicMaxNotTaken = ConstantMaxNotTaken;
  }

  assert((isa<SCEVCouldNotCompute>(ExactNotTaken) ||
          !isa<SCEVCouldNotCompute>(ConstantMaxNotTaken)) &&
         "Exact is not allowed to be less precise than Constant Max");
  assert((isa<SCEVCouldNotCompute>(ExactNotTaken) ||
          !isa<SCEVCouldNotCompute>(SymbolicMaxNotTaken)) &&
         "Exact is not allowed to be less precise than Symbolic Max");
  assert((isa<SCEVCouldNotCompute>(SymbolicMaxNotTaken) ||
          !isa<SCEVCouldNotCompute>(ConstantMaxNotTaken)) &&
         "Symbolic Max is not allowed to be less precise than Constant Max");
  assert((isa<SCEVCouldNotCompute>(ConstantMaxNotTaken) ||
          isa<SCEVConstant>(ConstantMaxNotTaken)) &&
         "No point in having a non-constant max backedge taken count!");
  for (const auto *PredSet : PredSetList)
    for (const auto *P : *PredSet)
      addPredicate(P);
  assert((isa<SCEVCouldNotCompute>(E) || !E->getType()->isPointerTy()) &&
         "Backedge count should be int");
  assert((isa<SCEVCouldNotCompute>(ConstantMaxNotTaken) ||
          !ConstantMaxNotTaken->getType()->isPointerTy()) &&
         "Max backedge count should be int");
}

ScalarEvolution::ExitLimit::ExitLimit(
    const SCEV *E, const SCEV *ConstantMaxNotTaken,
    const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
    const SmallPtrSetImpl<const SCEVPredicate *> &PredSet)
    : ExitLimit(E, ConstantMaxNotTaken, SymbolicMaxNotTaken, MaxOrZero,
                { &PredSet }) {}

/// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each
/// computable exit into a persistent ExitNotTakenInfo array.
ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo(
    ArrayRef<ScalarEvolution::BackedgeTakenInfo::EdgeExitInfo> ExitCounts,
    bool IsComplete, const SCEV *ConstantMax, bool MaxOrZero)
    : ConstantMax(ConstantMax), IsComplete(IsComplete), MaxOrZero(MaxOrZero) {
  using EdgeExitInfo = ScalarEvolution::BackedgeTakenInfo::EdgeExitInfo;

  ExitNotTaken.reserve(ExitCounts.size());
  std::transform(ExitCounts.begin(), ExitCounts.end(),
                 std::back_inserter(ExitNotTaken),
                 [&](const EdgeExitInfo &EEI) {
        BasicBlock *ExitBB = EEI.first;
        const ExitLimit &EL = EEI.second;
        return ExitNotTakenInfo(ExitBB, EL.ExactNotTaken,
                                EL.ConstantMaxNotTaken, EL.SymbolicMaxNotTaken,
                                EL.Predicates);
  });
  assert((isa<SCEVCouldNotCompute>(ConstantMax) ||
          isa<SCEVConstant>(ConstantMax)) &&
         "No point in having a non-constant max backedge taken count!");
}

/// Compute the number of times the backedge of the specified loop will execute.
ScalarEvolution::BackedgeTakenInfo
ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
                                           bool AllowPredicates) {
  SmallVector<BasicBlock *, 8> ExitingBlocks;
  L->getExitingBlocks(ExitingBlocks);

  using EdgeExitInfo = ScalarEvolution::BackedgeTakenInfo::EdgeExitInfo;

  SmallVector<EdgeExitInfo, 4> ExitCounts;
  bool CouldComputeBECount = true;
  BasicBlock *Latch = L->getLoopLatch(); // may be NULL.
  const SCEV *MustExitMaxBECount = nullptr;
  const SCEV *MayExitMaxBECount = nullptr;
  bool MustExitMaxOrZero = false;

  // Compute the ExitLimit for each loop exit. Use this to populate ExitCounts
  // and compute maxBECount.
  // Do a union of all the predicates here.
  for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
    BasicBlock *ExitBB = ExitingBlocks[i];

    // We canonicalize untaken exits to br (constant), ignore them so that
    // proving an exit untaken doesn't negatively impact our ability to reason
    // about the loop as whole.
    if (auto *BI = dyn_cast<BranchInst>(ExitBB->getTerminator()))
      if (auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) {
        bool ExitIfTrue = !L->contains(BI->getSuccessor(0));
        if (ExitIfTrue == CI->isZero())
          continue;
      }

    ExitLimit EL = computeExitLimit(L, ExitBB, AllowPredicates);

    assert((AllowPredicates || EL.Predicates.empty()) &&
           "Predicated exit limit when predicates are not allowed!");

    // 1. For each exit that can be computed, add an entry to ExitCounts.
    // CouldComputeBECount is true only if all exits can be computed.
    if (EL.ExactNotTaken != getCouldNotCompute())
      ++NumExitCountsComputed;
    else
      // We couldn't compute an exact value for this exit, so
      // we won't be able to compute an exact value for the loop.
      CouldComputeBECount = false;
    // Remember exit count if either exact or symbolic is known. Because
    // Exact always implies symbolic, only check symbolic.
    if (EL.SymbolicMaxNotTaken != getCouldNotCompute())
      ExitCounts.emplace_back(ExitBB, EL);
    else {
      assert(EL.ExactNotTaken == getCouldNotCompute() &&
             "Exact is known but symbolic isn't?");
      ++NumExitCountsNotComputed;
    }

    // 2. Derive the loop's MaxBECount from each exit's max number of
    // non-exiting iterations. Partition the loop exits into two kinds:
    // LoopMustExits and LoopMayExits.
    //
    // If the exit dominates the loop latch, it is a LoopMustExit otherwise it
    // is a LoopMayExit.  If any computable LoopMustExit is found, then
    // MaxBECount is the minimum EL.ConstantMaxNotTaken of computable
    // LoopMustExits. Otherwise, MaxBECount is conservatively the maximum
    // EL.ConstantMaxNotTaken, where CouldNotCompute is considered greater than
    // any
    // computable EL.ConstantMaxNotTaken.
    if (EL.ConstantMaxNotTaken != getCouldNotCompute() && Latch &&
        DT.dominates(ExitBB, Latch)) {
      if (!MustExitMaxBECount) {
        MustExitMaxBECount = EL.ConstantMaxNotTaken;
        MustExitMaxOrZero = EL.MaxOrZero;
      } else {
        MustExitMaxBECount = getUMinFromMismatchedTypes(MustExitMaxBECount,
                                                        EL.ConstantMaxNotTaken);
      }
    } else if (MayExitMaxBECount != getCouldNotCompute()) {
      if (!MayExitMaxBECount || EL.ConstantMaxNotTaken == getCouldNotCompute())
        MayExitMaxBECount = EL.ConstantMaxNotTaken;
      else {
        MayExitMaxBECount = getUMaxFromMismatchedTypes(MayExitMaxBECount,
                                                       EL.ConstantMaxNotTaken);
      }
    }
  }
  const SCEV *MaxBECount = MustExitMaxBECount ? MustExitMaxBECount :
    (MayExitMaxBECount ? MayExitMaxBECount : getCouldNotCompute());
  // The loop backedge will be taken the maximum or zero times if there's
  // a single exit that must be taken the maximum or zero times.
  bool MaxOrZero = (MustExitMaxOrZero && ExitingBlocks.size() == 1);

  // Remember which SCEVs are used in exit limits for invalidation purposes.
  // We only care about non-constant SCEVs here, so we can ignore
  // EL.ConstantMaxNotTaken
  // and MaxBECount, which must be SCEVConstant.
  for (const auto &Pair : ExitCounts) {
    if (!isa<SCEVConstant>(Pair.second.ExactNotTaken))
      BECountUsers[Pair.second.ExactNotTaken].insert({L, AllowPredicates});
    if (!isa<SCEVConstant>(Pair.second.SymbolicMaxNotTaken))
      BECountUsers[Pair.second.SymbolicMaxNotTaken].insert(
          {L, AllowPredicates});
  }
  return BackedgeTakenInfo(std::move(ExitCounts), CouldComputeBECount,
                           MaxBECount, MaxOrZero);
}

ScalarEvolution::ExitLimit
ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
                                      bool AllowPredicates) {
  assert(L->contains(ExitingBlock) && "Exit count for non-loop block?");
  // If our exiting block does not dominate the latch, then its connection with
  // loop's exit limit may be far from trivial.
  const BasicBlock *Latch = L->getLoopLatch();
  if (!Latch || !DT.dominates(ExitingBlock, Latch))
    return getCouldNotCompute();

  bool IsOnlyExit = (L->getExitingBlock() != nullptr);
  Instruction *Term = ExitingBlock->getTerminator();
  if (BranchInst *BI = dyn_cast<BranchInst>(Term)) {
    assert(BI->isConditional() && "If unconditional, it can't be in loop!");
    bool ExitIfTrue = !L->contains(BI->getSuccessor(0));
    assert(ExitIfTrue == L->contains(BI->getSuccessor(1)) &&
           "It should have one successor in loop and one exit block!");
    // Proceed to the next level to examine the exit condition expression.
    return computeExitLimitFromCond(L, BI->getCondition(), ExitIfTrue,
                                    /*ControlsOnlyExit=*/IsOnlyExit,
                                    AllowPredicates);
  }

  if (SwitchInst *SI = dyn_cast<SwitchInst>(Term)) {
    // For switch, make sure that there is a single exit from the loop.
    BasicBlock *Exit = nullptr;
    for (auto *SBB : successors(ExitingBlock))
      if (!L->contains(SBB)) {
        if (Exit) // Multiple exit successors.
          return getCouldNotCompute();
        Exit = SBB;
      }
    assert(Exit && "Exiting block must have at least one exit");
    return computeExitLimitFromSingleExitSwitch(
        L, SI, Exit,
        /*ControlsOnlyExit=*/IsOnlyExit);
  }

  return getCouldNotCompute();
}

ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromCond(
    const Loop *L, Value *ExitCond, bool ExitIfTrue, bool ControlsOnlyExit,
    bool AllowPredicates) {
  ScalarEvolution::ExitLimitCacheTy Cache(L, ExitIfTrue, AllowPredicates);
  return computeExitLimitFromCondCached(Cache, L, ExitCond, ExitIfTrue,
                                        ControlsOnlyExit, AllowPredicates);
}

std::optional<ScalarEvolution::ExitLimit>
ScalarEvolution::ExitLimitCache::find(const Loop *L, Value *ExitCond,
                                      bool ExitIfTrue, bool ControlsOnlyExit,
                                      bool AllowPredicates) {
  (void)this->L;
  (void)this->ExitIfTrue;
  (void)this->AllowPredicates;

  assert(this->L == L && this->ExitIfTrue == ExitIfTrue &&
         this->AllowPredicates == AllowPredicates &&
         "Variance in assumed invariant key components!");
  auto Itr = TripCountMap.find({ExitCond, ControlsOnlyExit});
  if (Itr == TripCountMap.end())
    return std::nullopt;
  return Itr->second;
}

void ScalarEvolution::ExitLimitCache::insert(const Loop *L, Value *ExitCond,
                                             bool ExitIfTrue,
                                             bool ControlsOnlyExit,
                                             bool AllowPredicates,
                                             const ExitLimit &EL) {
  assert(this->L == L && this->ExitIfTrue == ExitIfTrue &&
         this->AllowPredicates == AllowPredicates &&
         "Variance in assumed invariant key components!");

  auto InsertResult = TripCountMap.insert({{ExitCond, ControlsOnlyExit}, EL});
  assert(InsertResult.second && "Expected successful insertion!");
  (void)InsertResult;
  (void)ExitIfTrue;
}

ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromCondCached(
    ExitLimitCacheTy &Cache, const Loop *L, Value *ExitCond, bool ExitIfTrue,
    bool ControlsOnlyExit, bool AllowPredicates) {

  if (auto MaybeEL = Cache.find(L, ExitCond, ExitIfTrue, ControlsOnlyExit,
                                AllowPredicates))
    return *MaybeEL;

  ExitLimit EL = computeExitLimitFromCondImpl(
      Cache, L, ExitCond, ExitIfTrue, ControlsOnlyExit, AllowPredicates);
  Cache.insert(L, ExitCond, ExitIfTrue, ControlsOnlyExit, AllowPredicates, EL);
  return EL;
}

ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromCondImpl(
    ExitLimitCacheTy &Cache, const Loop *L, Value *ExitCond, bool ExitIfTrue,
    bool ControlsOnlyExit, bool AllowPredicates) {
  // Handle BinOp conditions (And, Or).
  if (auto LimitFromBinOp = computeExitLimitFromCondFromBinOp(
          Cache, L, ExitCond, ExitIfTrue, ControlsOnlyExit, AllowPredicates))
    return *LimitFromBinOp;

  // With an icmp, it may be feasible to compute an exact backedge-taken count.
  // Proceed to the next level to examine the icmp.
  if (ICmpInst *ExitCondICmp = dyn_cast<ICmpInst>(ExitCond)) {
    ExitLimit EL =
        computeExitLimitFromICmp(L, ExitCondICmp, ExitIfTrue, ControlsOnlyExit);
    if (EL.hasFullInfo() || !AllowPredicates)
      return EL;

    // Try again, but use SCEV predicates this time.
    return computeExitLimitFromICmp(L, ExitCondICmp, ExitIfTrue,
                                    ControlsOnlyExit,
                                    /*AllowPredicates=*/true);
  }

  // Check for a constant condition. These are normally stripped out by
  // SimplifyCFG, but ScalarEvolution may be used by a pass which wishes to
  // preserve the CFG and is temporarily leaving constant conditions
  // in place.
  if (ConstantInt *CI = dyn_cast<ConstantInt>(ExitCond)) {
    if (ExitIfTrue == !CI->getZExtValue())
      // The backedge is always taken.
      return getCouldNotCompute();
    // The backedge is never taken.
    return getZero(CI->getType());
  }

  // If we're exiting based on the overflow flag of an x.with.overflow intrinsic
  // with a constant step, we can form an equivalent icmp predicate and figure
  // out how many iterations will be taken before we exit.
  const WithOverflowInst *WO;
  const APInt *C;
  if (match(ExitCond, m_ExtractValue<1>(m_WithOverflowInst(WO))) &&
      match(WO->getRHS(), m_APInt(C))) {
    ConstantRange NWR =
      ConstantRange::makeExactNoWrapRegion(WO->getBinaryOp(), *C,
                                           WO->getNoWrapKind());
    CmpInst::Predicate Pred;
    APInt NewRHSC, Offset;
    NWR.getEquivalentICmp(Pred, NewRHSC, Offset);
    if (!ExitIfTrue)
      Pred = ICmpInst::getInversePredicate(Pred);
    auto *LHS = getSCEV(WO->getLHS());
    if (Offset != 0)
      LHS = getAddExpr(LHS, getConstant(Offset));
    auto EL = computeExitLimitFromICmp(L, Pred, LHS, getConstant(NewRHSC),
                                       ControlsOnlyExit, AllowPredicates);
    if (EL.hasAnyInfo())
      return EL;
  }

  // If it's not an integer or pointer comparison then compute it the hard way.
  return computeExitCountExhaustively(L, ExitCond, ExitIfTrue);
}

std::optional<ScalarEvolution::ExitLimit>
ScalarEvolution::computeExitLimitFromCondFromBinOp(
    ExitLimitCacheTy &Cache, const Loop *L, Value *ExitCond, bool ExitIfTrue,
    bool ControlsOnlyExit, bool AllowPredicates) {
  // Check if the controlling expression for this loop is an And or Or.
  Value *Op0, *Op1;
  bool IsAnd = false;
  if (match(ExitCond, m_LogicalAnd(m_Value(Op0), m_Value(Op1))))
    IsAnd = true;
  else if (match(ExitCond, m_LogicalOr(m_Value(Op0), m_Value(Op1))))
    IsAnd = false;
  else
    return std::nullopt;

  // EitherMayExit is true in these two cases:
  //   br (and Op0 Op1), loop, exit
  //   br (or  Op0 Op1), exit, loop
  bool EitherMayExit = IsAnd ^ ExitIfTrue;
  ExitLimit EL0 = computeExitLimitFromCondCached(
      Cache, L, Op0, ExitIfTrue, ControlsOnlyExit && !EitherMayExit,
      AllowPredicates);
  ExitLimit EL1 = computeExitLimitFromCondCached(
      Cache, L, Op1, ExitIfTrue, ControlsOnlyExit && !EitherMayExit,
      AllowPredicates);

  // Be robust against unsimplified IR for the form "op i1 X, NeutralElement"
  const Constant *NeutralElement = ConstantInt::get(ExitCond->getType(), IsAnd);
  if (isa<ConstantInt>(Op1))
    return Op1 == NeutralElement ? EL0 : EL1;
  if (isa<ConstantInt>(Op0))
    return Op0 == NeutralElement ? EL1 : EL0;

  const SCEV *BECount = getCouldNotCompute();
  const SCEV *ConstantMaxBECount = getCouldNotCompute();
  const SCEV *SymbolicMaxBECount = getCouldNotCompute();
  if (EitherMayExit) {
    bool UseSequentialUMin = !isa<BinaryOperator>(ExitCond);
    // Both conditions must be same for the loop to continue executing.
    // Choose the less conservative count.
    if (EL0.ExactNotTaken != getCouldNotCompute() &&
        EL1.ExactNotTaken != getCouldNotCompute()) {
      BECount = getUMinFromMismatchedTypes(EL0.ExactNotTaken, EL1.ExactNotTaken,
                                           UseSequentialUMin);
    }
    if (EL0.ConstantMaxNotTaken == getCouldNotCompute())
      ConstantMaxBECount = EL1.ConstantMaxNotTaken;
    else if (EL1.ConstantMaxNotTaken == getCouldNotCompute())
      ConstantMaxBECount = EL0.ConstantMaxNotTaken;
    else
      ConstantMaxBECount = getUMinFromMismatchedTypes(EL0.ConstantMaxNotTaken,
                                                      EL1.ConstantMaxNotTaken);
    if (EL0.SymbolicMaxNotTaken == getCouldNotCompute())
      SymbolicMaxBECount = EL1.SymbolicMaxNotTaken;
    else if (EL1.SymbolicMaxNotTaken == getCouldNotCompute())
      SymbolicMaxBECount = EL0.SymbolicMaxNotTaken;
    else
      SymbolicMaxBECount = getUMinFromMismatchedTypes(
          EL0.SymbolicMaxNotTaken, EL1.SymbolicMaxNotTaken, UseSequentialUMin);
  } else {
    // Both conditions must be same at the same time for the loop to exit.
    // For now, be conservative.
    if (EL0.ExactNotTaken == EL1.ExactNotTaken)
      BECount = EL0.ExactNotTaken;
  }

  // There are cases (e.g. PR26207) where computeExitLimitFromCond is able
  // to be more aggressive when computing BECount than when computing
  // ConstantMaxBECount.  In these cases it is possible for EL0.ExactNotTaken
  // and
  // EL1.ExactNotTaken to match, but for EL0.ConstantMaxNotTaken and
  // EL1.ConstantMaxNotTaken to not.
  if (isa<SCEVCouldNotCompute>(ConstantMaxBECount) &&
      !isa<SCEVCouldNotCompute>(BECount))
    ConstantMaxBECount = getConstant(getUnsignedRangeMax(BECount));
  if (isa<SCEVCouldNotCompute>(SymbolicMaxBECount))
    SymbolicMaxBECount =
        isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;
  return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount, false,
                   { &EL0.Predicates, &EL1.Predicates });
}

ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
    const Loop *L, ICmpInst *ExitCond, bool ExitIfTrue, bool ControlsOnlyExit,
    bool AllowPredicates) {
  // If the condition was exit on true, convert the condition to exit on false
  ICmpInst::Predicate Pred;
  if (!ExitIfTrue)
    Pred = ExitCond->getPredicate();
  else
    Pred = ExitCond->getInversePredicate();
  const ICmpInst::Predicate OriginalPred = Pred;

  const SCEV *LHS = getSCEV(ExitCond->getOperand(0));
  const SCEV *RHS = getSCEV(ExitCond->getOperand(1));

  ExitLimit EL = computeExitLimitFromICmp(L, Pred, LHS, RHS, ControlsOnlyExit,
                                          AllowPredicates);
  if (EL.hasAnyInfo())
    return EL;

  auto *ExhaustiveCount =
      computeExitCountExhaustively(L, ExitCond, ExitIfTrue);

  if (!isa<SCEVCouldNotCompute>(ExhaustiveCount))
    return ExhaustiveCount;

  return computeShiftCompareExitLimit(ExitCond->getOperand(0),
                                      ExitCond->getOperand(1), L, OriginalPred);
}
ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
    const Loop *L, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
    bool ControlsOnlyExit, bool AllowPredicates) {

  // Try to evaluate any dependencies out of the loop.
  LHS = getSCEVAtScope(LHS, L);
  RHS = getSCEVAtScope(RHS, L);

  // At this point, we would like to compute how many iterations of the
  // loop the predicate will return true for these inputs.
  if (isLoopInvariant(LHS, L) && !isLoopInvariant(RHS, L)) {
    // If there is a loop-invariant, force it into the RHS.
    std::swap(LHS, RHS);
    Pred = ICmpInst::getSwappedPredicate(Pred);
  }

  bool ControllingFiniteLoop = ControlsOnlyExit && loopHasNoAbnormalExits(L) &&
                               loopIsFiniteByAssumption(L);
  // Simplify the operands before analyzing them.
  (void)SimplifyICmpOperands(Pred, LHS, RHS, /*Depth=*/0);

  // If we have a comparison of a chrec against a constant, try to use value
  // ranges to answer this query.
  if (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS))
    if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(LHS))
      if (AddRec->getLoop() == L) {
        // Form the constant range.
        ConstantRange CompRange =
            ConstantRange::makeExactICmpRegion(Pred, RHSC->getAPInt());

        const SCEV *Ret = AddRec->getNumIterationsInRange(CompRange, *this);
        if (!isa<SCEVCouldNotCompute>(Ret)) return Ret;
      }

  // If this loop must exit based on this condition (or execute undefined
  // behaviour), and we can prove the test sequence produced must repeat
  // the same values on self-wrap of the IV, then we can infer that IV
  // doesn't self wrap because if it did, we'd have an infinite (undefined)
  // loop.
  if (ControllingFiniteLoop && isLoopInvariant(RHS, L)) {
    // TODO: We can peel off any functions which are invertible *in L*.  Loop
    // invariant terms are effectively constants for our purposes here.
    auto *InnerLHS = LHS;
    if (auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(LHS))
      InnerLHS = ZExt->getOperand();
    if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(InnerLHS)) {
      auto *StrideC = dyn_cast<SCEVConstant>(AR->getStepRecurrence(*this));
      if (!AR->hasNoSelfWrap() && AR->getLoop() == L && AR->isAffine() && 
          StrideC && StrideC->getAPInt().isPowerOf2()) {
        auto Flags = AR->getNoWrapFlags();
        Flags = setFlags(Flags, SCEV::FlagNW);
        SmallVector<const SCEV*> Operands{AR->operands()};
        Flags = StrengthenNoWrapFlags(this, scAddRecExpr, Operands, Flags);
        setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), Flags);
      }
    }
  }

  switch (Pred) {
  case ICmpInst::ICMP_NE: {                     // while (X != Y)
    // Convert to: while (X-Y != 0)
    if (LHS->getType()->isPointerTy()) {
      LHS = getLosslessPtrToIntExpr(LHS);
      if (isa<SCEVCouldNotCompute>(LHS))
        return LHS;
    }
    if (RHS->getType()->isPointerTy()) {
      RHS = getLosslessPtrToIntExpr(RHS);
      if (isa<SCEVCouldNotCompute>(RHS))
        return RHS;
    }
    ExitLimit EL = howFarToZero(getMinusSCEV(LHS, RHS), L, ControlsOnlyExit,
                                AllowPredicates);
    if (EL.hasAnyInfo())
      return EL;
    break;
  }
  case ICmpInst::ICMP_EQ: {                     // while (X == Y)
    // Convert to: while (X-Y == 0)
    if (LHS->getType()->isPointerTy()) {
      LHS = getLosslessPtrToIntExpr(LHS);
      if (isa<SCEVCouldNotCompute>(LHS))
        return LHS;
    }
    if (RHS->getType()->isPointerTy()) {
      RHS = getLosslessPtrToIntExpr(RHS);
      if (isa<SCEVCouldNotCompute>(RHS))
        return RHS;
    }
    ExitLimit EL = howFarToNonZero(getMinusSCEV(LHS, RHS), L);
    if (EL.hasAnyInfo()) return EL;
    break;
  }
  case ICmpInst::ICMP_SLE:
  case ICmpInst::ICMP_ULE:
    // Since the loop is finite, an invariant RHS cannot include the boundary
    // value, otherwise it would loop forever.
    if (!EnableFiniteLoopControl || !ControllingFiniteLoop ||
        !isLoopInvariant(RHS, L))
      break;
    RHS = getAddExpr(getOne(RHS->getType()), RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_SLT:
  case ICmpInst::ICMP_ULT: { // while (X < Y)
    bool IsSigned = ICmpInst::isSigned(Pred);
    ExitLimit EL = howManyLessThans(LHS, RHS, L, IsSigned, ControlsOnlyExit,
                                    AllowPredicates);
    if (EL.hasAnyInfo())
      return EL;
    break;
  }
  case ICmpInst::ICMP_SGE:
  case ICmpInst::ICMP_UGE:
    // Since the loop is finite, an invariant RHS cannot include the boundary
    // value, otherwise it would loop forever.
    if (!EnableFiniteLoopControl || !ControllingFiniteLoop ||
        !isLoopInvariant(RHS, L))
      break;
    RHS = getAddExpr(getMinusOne(RHS->getType()), RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_SGT:
  case ICmpInst::ICMP_UGT: { // while (X > Y)
    bool IsSigned = ICmpInst::isSigned(Pred);
    ExitLimit EL = howManyGreaterThans(LHS, RHS, L, IsSigned, ControlsOnlyExit,
                                       AllowPredicates);
    if (EL.hasAnyInfo())
      return EL;
    break;
  }
  default:
    break;
  }

  return getCouldNotCompute();
}

ScalarEvolution::ExitLimit
ScalarEvolution::computeExitLimitFromSingleExitSwitch(const Loop *L,
                                                      SwitchInst *Switch,
                                                      BasicBlock *ExitingBlock,
                                                      bool ControlsOnlyExit) {
  assert(!L->contains(ExitingBlock) && "Not an exiting block!");

  // Give up if the exit is the default dest of a switch.
  if (Switch->getDefaultDest() == ExitingBlock)
    return getCouldNotCompute();

  assert(L->contains(Switch->getDefaultDest()) &&
         "Default case must not exit the loop!");
  const SCEV *LHS = getSCEVAtScope(Switch->getCondition(), L);
  const SCEV *RHS = getConstant(Switch->findCaseDest(ExitingBlock));

  // while (X != Y) --> while (X-Y != 0)
  ExitLimit EL = howFarToZero(getMinusSCEV(LHS, RHS), L, ControlsOnlyExit);
  if (EL.hasAnyInfo())
    return EL;

  return getCouldNotCompute();
}

static ConstantInt *
EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C,
                                ScalarEvolution &SE) {
  const SCEV *InVal = SE.getConstant(C);
  const SCEV *Val = AddRec->evaluateAtIteration(InVal, SE);
  assert(isa<SCEVConstant>(Val) &&
         "Evaluation of SCEV at constant didn't fold correctly?");
  return cast<SCEVConstant>(Val)->getValue();
}

ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
    Value *LHS, Value *RHSV, const Loop *L, ICmpInst::Predicate Pred) {
  ConstantInt *RHS = dyn_cast<ConstantInt>(RHSV);
  if (!RHS)
    return getCouldNotCompute();

  const BasicBlock *Latch = L->getLoopLatch();
  if (!Latch)
    return getCouldNotCompute();

  const BasicBlock *Predecessor = L->getLoopPredecessor();
  if (!Predecessor)
    return getCouldNotCompute();

  // Return true if V is of the form "LHS `shift_op` <positive constant>".
  // Return LHS in OutLHS and shift_opt in OutOpCode.
  auto MatchPositiveShift =
      [](Value *V, Value *&OutLHS, Instruction::BinaryOps &OutOpCode) {

    using namespace PatternMatch;

    ConstantInt *ShiftAmt;
    if (match(V, m_LShr(m_Value(OutLHS), m_ConstantInt(ShiftAmt))))
      OutOpCode = Instruction::LShr;
    else if (match(V, m_AShr(m_Value(OutLHS), m_ConstantInt(ShiftAmt))))
      OutOpCode = Instruction::AShr;
    else if (match(V, m_Shl(m_Value(OutLHS), m_ConstantInt(ShiftAmt))))
      OutOpCode = Instruction::Shl;
    else
      return false;

    return ShiftAmt->getValue().isStrictlyPositive();
  };

  // Recognize a "shift recurrence" either of the form %iv or of %iv.shifted in
  //
  // loop:
  //   %iv = phi i32 [ %iv.shifted, %loop ], [ %val, %preheader ]
  //   %iv.shifted = lshr i32 %iv, <positive constant>
  //
  // Return true on a successful match.  Return the corresponding PHI node (%iv
  // above) in PNOut and the opcode of the shift operation in OpCodeOut.
  auto MatchShiftRecurrence =
      [&](Value *V, PHINode *&PNOut, Instruction::BinaryOps &OpCodeOut) {
    std::optional<Instruction::BinaryOps> PostShiftOpCode;

    {
      Instruction::BinaryOps OpC;
      Value *V;

      // If we encounter a shift instruction, "peel off" the shift operation,
      // and remember that we did so.  Later when we inspect %iv's backedge
      // value, we will make sure that the backedge value uses the same
      // operation.
      //
      // Note: the peeled shift operation does not have to be the same
      // instruction as the one feeding into the PHI's backedge value.  We only
      // really care about it being the same *kind* of shift instruction --
      // that's all that is required for our later inferences to hold.
      if (MatchPositiveShift(LHS, V, OpC)) {
        PostShiftOpCode = OpC;
        LHS = V;
      }
    }

    PNOut = dyn_cast<PHINode>(LHS);
    if (!PNOut || PNOut->getParent() != L->getHeader())
      return false;

    Value *BEValue = PNOut->getIncomingValueForBlock(Latch);
    Value *OpLHS;

    return
        // The backedge value for the PHI node must be a shift by a positive
        // amount
        MatchPositiveShift(BEValue, OpLHS, OpCodeOut) &&

        // of the PHI node itself
        OpLHS == PNOut &&

        // and the kind of shift should be match the kind of shift we peeled
        // off, if any.
        (!PostShiftOpCode || *PostShiftOpCode == OpCodeOut);
  };

  PHINode *PN;
  Instruction::BinaryOps OpCode;
  if (!MatchShiftRecurrence(LHS, PN, OpCode))
    return getCouldNotCompute();

  const DataLayout &DL = getDataLayout();

  // The key rationale for this optimization is that for some kinds of shift
  // recurrences, the value of the recurrence "stabilizes" to either 0 or -1
  // within a finite number of iterations.  If the condition guarding the
  // backedge (in the sense that the backedge is taken if the condition is true)
  // is false for the value the shift recurrence stabilizes to, then we know
  // that the backedge is taken only a finite number of times.

  ConstantInt *StableValue = nullptr;
  switch (OpCode) {
  default:
    llvm_unreachable("Impossible case!");

  case Instruction::AShr: {
    // {K,ashr,<positive-constant>} stabilizes to signum(K) in at most
    // bitwidth(K) iterations.
    Value *FirstValue = PN->getIncomingValueForBlock(Predecessor);
    KnownBits Known = computeKnownBits(FirstValue, DL, 0, &AC,
                                       Predecessor->getTerminator(), &DT);
    auto *Ty = cast<IntegerType>(RHS->getType());
    if (Known.isNonNegative())
      StableValue = ConstantInt::get(Ty, 0);
    else if (Known.isNegative())
      StableValue = ConstantInt::get(Ty, -1, true);
    else
      return getCouldNotCompute();

    break;
  }
  case Instruction::LShr:
  case Instruction::Shl:
    // Both {K,lshr,<positive-constant>} and {K,shl,<positive-constant>}
    // stabilize to 0 in at most bitwidth(K) iterations.
    StableValue = ConstantInt::get(cast<IntegerType>(RHS->getType()), 0);
    break;
  }

  auto *Result =
      ConstantFoldCompareInstOperands(Pred, StableValue, RHS, DL, &TLI);
  assert(Result->getType()->isIntegerTy(1) &&
         "Otherwise cannot be an operand to a branch instruction");

  if (Result->isZeroValue()) {
    unsigned BitWidth = getTypeSizeInBits(RHS->getType());
    const SCEV *UpperBound =
        getConstant(getEffectiveSCEVType(RHS->getType()), BitWidth);
    return ExitLimit(getCouldNotCompute(), UpperBound, UpperBound, false);
  }

  return getCouldNotCompute();
}

/// Return true if we can constant fold an instruction of the specified type,
/// assuming that all operands were constants.
static bool CanConstantFold(const Instruction *I) {
  if (isa<BinaryOperator>(I) || isa<CmpInst>(I) ||
      isa<SelectInst>(I) || isa<CastInst>(I) || isa<GetElementPtrInst>(I) ||
      isa<LoadInst>(I) || isa<ExtractValueInst>(I))
    return true;

  if (const CallInst *CI = dyn_cast<CallInst>(I))
    if (const Function *F = CI->getCalledFunction())
      return canConstantFoldCallTo(CI, F);
  return false;
}

/// Determine whether this instruction can constant evolve within this loop
/// assuming its operands can all constant evolve.
static bool canConstantEvolve(Instruction *I, const Loop *L) {
  // An instruction outside of the loop can't be derived from a loop PHI.
  if (!L->contains(I)) return false;

  if (isa<PHINode>(I)) {
    // We don't currently keep track of the control flow needed to evaluate
    // PHIs, so we cannot handle PHIs inside of loops.
    return L->getHeader() == I->getParent();
  }

  // If we won't be able to constant fold this expression even if the operands
  // are constants, bail early.
  return CanConstantFold(I);
}

/// getConstantEvolvingPHIOperands - Implement getConstantEvolvingPHI by
/// recursing through each instruction operand until reaching a loop header phi.
static PHINode *
getConstantEvolvingPHIOperands(Instruction *UseInst, const Loop *L,
                               DenseMap<Instruction *, PHINode *> &PHIMap,
                               unsigned Depth) {
  if (Depth > MaxConstantEvolvingDepth)
    return nullptr;

  // Otherwise, we can evaluate this instruction if all of its operands are
  // constant or derived from a PHI node themselves.
  PHINode *PHI = nullptr;
  for (Value *Op : UseInst->operands()) {
    if (isa<Constant>(Op)) continue;

    Instruction *OpInst = dyn_cast<Instruction>(Op);
    if (!OpInst || !canConstantEvolve(OpInst, L)) return nullptr;

    PHINode *P = dyn_cast<PHINode>(OpInst);
    if (!P)
      // If this operand is already visited, reuse the prior result.
      // We may have P != PHI if this is the deepest point at which the
      // inconsistent paths meet.
      P = PHIMap.lookup(OpInst);
    if (!P) {
      // Recurse and memoize the results, whether a phi is found or not.
      // This recursive call invalidates pointers into PHIMap.
      P = getConstantEvolvingPHIOperands(OpInst, L, PHIMap, Depth + 1);
      PHIMap[OpInst] = P;
    }
    if (!P)
      return nullptr;  // Not evolving from PHI
    if (PHI && PHI != P)
      return nullptr;  // Evolving from multiple different PHIs.
    PHI = P;
  }
  // This is a expression evolving from a constant PHI!
  return PHI;
}

/// getConstantEvolvingPHI - Given an LLVM value and a loop, return a PHI node
/// in the loop that V is derived from.  We allow arbitrary operations along the
/// way, but the operands of an operation must either be constants or a value
/// derived from a constant PHI.  If this expression does not fit with these
/// constraints, return null.
static PHINode *getConstantEvolvingPHI(Value *V, const Loop *L) {
  Instruction *I = dyn_cast<Instruction>(V);
  if (!I || !canConstantEvolve(I, L)) return nullptr;

  if (PHINode *PN = dyn_cast<PHINode>(I))
    return PN;

  // Record non-constant instructions contained by the loop.
  DenseMap<Instruction *, PHINode *> PHIMap;
  return getConstantEvolvingPHIOperands(I, L, PHIMap, 0);
}

/// EvaluateExpression - Given an expression that passes the
/// getConstantEvolvingPHI predicate, evaluate its value assuming the PHI node
/// in the loop has the value PHIVal.  If we can't fold this expression for some
/// reason, return null.
static Constant *EvaluateExpression(Value *V, const Loop *L,
                                    DenseMap<Instruction *, Constant *> &Vals,
                                    const DataLayout &DL,
                                    const TargetLibraryInfo *TLI) {
  // Convenient constant check, but redundant for recursive calls.
  if (Constant *C = dyn_cast<Constant>(V)) return C;
  Instruction *I = dyn_cast<Instruction>(V);
  if (!I) return nullptr;

  if (Constant *C = Vals.lookup(I)) return C;

  // An instruction inside the loop depends on a value outside the loop that we
  // weren't given a mapping for, or a value such as a call inside the loop.
  if (!canConstantEvolve(I, L)) return nullptr;

  // An unmapped PHI can be due to a branch or another loop inside this loop,
  // or due to this not being the initial iteration through a loop where we
  // couldn't compute the evolution of this particular PHI last time.
  if (isa<PHINode>(I)) return nullptr;

  std::vector<Constant*> Operands(I->getNumOperands());

  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    Instruction *Operand = dyn_cast<Instruction>(I->getOperand(i));
    if (!Operand) {
      Operands[i] = dyn_cast<Constant>(I->getOperand(i));
      if (!Operands[i]) return nullptr;
      continue;
    }
    Constant *C = EvaluateExpression(Operand, L, Vals, DL, TLI);
    Vals[Operand] = C;
    if (!C) return nullptr;
    Operands[i] = C;
  }

  return ConstantFoldInstOperands(I, Operands, DL, TLI);
}


// If every incoming value to PN except the one for BB is a specific Constant,
// return that, else return nullptr.
static Constant *getOtherIncomingValue(PHINode *PN, BasicBlock *BB) {
  Constant *IncomingVal = nullptr;

  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
    if (PN->getIncomingBlock(i) == BB)
      continue;

    auto *CurrentVal = dyn_cast<Constant>(PN->getIncomingValue(i));
    if (!CurrentVal)
      return nullptr;

    if (IncomingVal != CurrentVal) {
      if (IncomingVal)
        return nullptr;
      IncomingVal = CurrentVal;
    }
  }

  return IncomingVal;
}

/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
/// in the header of its containing loop, we know the loop executes a
/// constant number of times, and the PHI node is just a recurrence
/// involving constants, fold it.
Constant *
ScalarEvolution::getConstantEvolutionLoopExitValue(PHINode *PN,
                                                   const APInt &BEs,
                                                   const Loop *L) {
  auto I = ConstantEvolutionLoopExitValue.find(PN);
  if (I != ConstantEvolutionLoopExitValue.end())
    return I->second;

  if (BEs.ugt(MaxBruteForceIterations))
    return ConstantEvolutionLoopExitValue[PN] = nullptr;  // Not going to evaluate it.

  Constant *&RetVal = ConstantEvolutionLoopExitValue[PN];

  DenseMap<Instruction *, Constant *> CurrentIterVals;
  BasicBlock *Header = L->getHeader();
  assert(PN->getParent() == Header && "Can't evaluate PHI not in loop header!");

  BasicBlock *Latch = L->getLoopLatch();
  if (!Latch)
    return nullptr;

  for (PHINode &PHI : Header->phis()) {
    if (auto *StartCST = getOtherIncomingValue(&PHI, Latch))
      CurrentIterVals[&PHI] = StartCST;
  }
  if (!CurrentIterVals.count(PN))
    return RetVal = nullptr;

  Value *BEValue = PN->getIncomingValueForBlock(Latch);

  // Execute the loop symbolically to determine the exit value.
  assert(BEs.getActiveBits() < CHAR_BIT * sizeof(unsigned) &&
         "BEs is <= MaxBruteForceIterations which is an 'unsigned'!");

  unsigned NumIterations = BEs.getZExtValue(); // must be in range
  unsigned IterationNum = 0;
  const DataLayout &DL = getDataLayout();
  for (; ; ++IterationNum) {
    if (IterationNum == NumIterations)
      return RetVal = CurrentIterVals[PN];  // Got exit value!

    // Compute the value of the PHIs for the next iteration.
    // EvaluateExpression adds non-phi values to the CurrentIterVals map.
    DenseMap<Instruction *, Constant *> NextIterVals;
    Constant *NextPHI =
        EvaluateExpression(BEValue, L, CurrentIterVals, DL, &TLI);
    if (!NextPHI)
      return nullptr;        // Couldn't evaluate!
    NextIterVals[PN] = NextPHI;

    bool StoppedEvolving = NextPHI == CurrentIterVals[PN];

    // Also evaluate the other PHI nodes.  However, we don't get to stop if we
    // cease to be able to evaluate one of them or if they stop evolving,
    // because that doesn't necessarily prevent us from computing PN.
    SmallVector<std::pair<PHINode *, Constant *>, 8> PHIsToCompute;
    for (const auto &I : CurrentIterVals) {
      PHINode *PHI = dyn_cast<PHINode>(I.first);
      if (!PHI || PHI == PN || PHI->getParent() != Header) continue;
      PHIsToCompute.emplace_back(PHI, I.second);
    }
    // We use two distinct loops because EvaluateExpression may invalidate any
    // iterators into CurrentIterVals.
    for (const auto &I : PHIsToCompute) {
      PHINode *PHI = I.first;
      Constant *&NextPHI = NextIterVals[PHI];
      if (!NextPHI) {   // Not already computed.
        Value *BEValue = PHI->getIncomingValueForBlock(Latch);
        NextPHI = EvaluateExpression(BEValue, L, CurrentIterVals, DL, &TLI);
      }
      if (NextPHI != I.second)
        StoppedEvolving = false;
    }

    // If all entries in CurrentIterVals == NextIterVals then we can stop
    // iterating, the loop can't continue to change.
    if (StoppedEvolving)
      return RetVal = CurrentIterVals[PN];

    CurrentIterVals.swap(NextIterVals);
  }
}

const SCEV *ScalarEvolution::computeExitCountExhaustively(const Loop *L,
                                                          Value *Cond,
                                                          bool ExitWhen) {
  PHINode *PN = getConstantEvolvingPHI(Cond, L);
  if (!PN) return getCouldNotCompute();

  // If the loop is canonicalized, the PHI will have exactly two entries.
  // That's the only form we support here.
  if (PN->getNumIncomingValues() != 2) return getCouldNotCompute();

  DenseMap<Instruction *, Constant *> CurrentIterVals;
  BasicBlock *Header = L->getHeader();
  assert(PN->getParent() == Header && "Can't evaluate PHI not in loop header!");

  BasicBlock *Latch = L->getLoopLatch();
  assert(Latch && "Should follow from NumIncomingValues == 2!");

  for (PHINode &PHI : Header->phis()) {
    if (auto *StartCST = getOtherIncomingValue(&PHI, Latch))
      CurrentIterVals[&PHI] = StartCST;
  }
  if (!CurrentIterVals.count(PN))
    return getCouldNotCompute();

  // Okay, we find a PHI node that defines the trip count of this loop.  Execute
  // the loop symbolically to determine when the condition gets a value of
  // "ExitWhen".
  unsigned MaxIterations = MaxBruteForceIterations;   // Limit analysis.
  const DataLayout &DL = getDataLayout();
  for (unsigned IterationNum = 0; IterationNum != MaxIterations;++IterationNum){
    auto *CondVal = dyn_cast_or_null<ConstantInt>(
        EvaluateExpression(Cond, L, CurrentIterVals, DL, &TLI));

    // Couldn't symbolically evaluate.
    if (!CondVal) return getCouldNotCompute();

    if (CondVal->getValue() == uint64_t(ExitWhen)) {
      ++NumBruteForceTripCountsComputed;
      return getConstant(Type::getInt32Ty(getContext()), IterationNum);
    }

    // Update all the PHI nodes for the next iteration.
    DenseMap<Instruction *, Constant *> NextIterVals;

    // Create a list of which PHIs we need to compute. We want to do this before
    // calling EvaluateExpression on them because that may invalidate iterators
    // into CurrentIterVals.
    SmallVector<PHINode *, 8> PHIsToCompute;
    for (const auto &I : CurrentIterVals) {
      PHINode *PHI = dyn_cast<PHINode>(I.first);
      if (!PHI || PHI->getParent() != Header) continue;
      PHIsToCompute.push_back(PHI);
    }
    for (PHINode *PHI : PHIsToCompute) {
      Constant *&NextPHI = NextIterVals[PHI];
      if (NextPHI) continue;    // Already computed!

      Value *BEValue = PHI->getIncomingValueForBlock(Latch);
      NextPHI = EvaluateExpression(BEValue, L, CurrentIterVals, DL, &TLI);
    }
    CurrentIterVals.swap(NextIterVals);
  }

  // Too many iterations were needed to evaluate.
  return getCouldNotCompute();
}

const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
  SmallVector<std::pair<const Loop *, const SCEV *>, 2> &Values =
      ValuesAtScopes[V];
  // Check to see if we've folded this expression at this loop before.
  for (auto &LS : Values)
    if (LS.first == L)
      return LS.second ? LS.second : V;

  Values.emplace_back(L, nullptr);

  // Otherwise compute it.
  const SCEV *C = computeSCEVAtScope(V, L);
  for (auto &LS : reverse(ValuesAtScopes[V]))
    if (LS.first == L) {
      LS.second = C;
      if (!isa<SCEVConstant>(C))
        ValuesAtScopesUsers[C].push_back({L, V});
      break;
    }
  return C;
}

/// This builds up a Constant using the ConstantExpr interface.  That way, we
/// will return Constants for objects which aren't represented by a
/// SCEVConstant, because SCEVConstant is restricted to ConstantInt.
/// Returns NULL if the SCEV isn't representable as a Constant.
static Constant *BuildConstantFromSCEV(const SCEV *V) {
  switch (V->getSCEVType()) {
  case scCouldNotCompute:
  case scAddRecExpr:
  case scVScale:
    return nullptr;
  case scConstant:
    return cast<SCEVConstant>(V)->getValue();
  case scUnknown:
    return dyn_cast<Constant>(cast<SCEVUnknown>(V)->getValue());
  case scSignExtend: {
    const SCEVSignExtendExpr *SS = cast<SCEVSignExtendExpr>(V);
    if (Constant *CastOp = BuildConstantFromSCEV(SS->getOperand()))
      return ConstantExpr::getSExt(CastOp, SS->getType());
    return nullptr;
  }
  case scZeroExtend: {
    const SCEVZeroExtendExpr *SZ = cast<SCEVZeroExtendExpr>(V);
    if (Constant *CastOp = BuildConstantFromSCEV(SZ->getOperand()))
      return ConstantExpr::getZExt(CastOp, SZ->getType());
    return nullptr;
  }
  case scPtrToInt: {
    const SCEVPtrToIntExpr *P2I = cast<SCEVPtrToIntExpr>(V);
    if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
      return ConstantExpr::getPtrToInt(CastOp, P2I->getType());

    return nullptr;
  }
  case scTruncate: {
    const SCEVTruncateExpr *ST = cast<SCEVTruncateExpr>(V);
    if (Constant *CastOp = BuildConstantFromSCEV(ST->getOperand()))
      return ConstantExpr::getTrunc(CastOp, ST->getType());
    return nullptr;
  }
  case scAddExpr: {
    const SCEVAddExpr *SA = cast<SCEVAddExpr>(V);
    Constant *C = nullptr;
    for (const SCEV *Op : SA->operands()) {
      Constant *OpC = BuildConstantFromSCEV(Op);
      if (!OpC)
        return nullptr;
      if (!C) {
        C = OpC;
        continue;
      }
      assert(!C->getType()->isPointerTy() &&
             "Can only have one pointer, and it must be last");
      if (auto *PT = dyn_cast<PointerType>(OpC->getType())) {
        // The offsets have been converted to bytes.  We can add bytes to an
        // i8* by GEP with the byte count in the first index.
        Type *DestPtrTy =
            Type::getInt8PtrTy(PT->getContext(), PT->getAddressSpace());
        OpC = ConstantExpr::getBitCast(OpC, DestPtrTy);
        C = ConstantExpr::getGetElementPtr(Type::getInt8Ty(C->getContext()),
                                           OpC, C);
      } else {
        C = ConstantExpr::getAdd(C, OpC);
      }
    }
    return C;
  }
  case scMulExpr: {
    const SCEVMulExpr *SM = cast<SCEVMulExpr>(V);
    Constant *C = nullptr;
    for (const SCEV *Op : SM->operands()) {
      assert(!Op->getType()->isPointerTy() && "Can't multiply pointers");
      Constant *OpC = BuildConstantFromSCEV(Op);
      if (!OpC)
        return nullptr;
      C = C ? ConstantExpr::getMul(C, OpC) : OpC;
    }
    return C;
  }
  case scUDivExpr:
  case scSMaxExpr:
  case scUMaxExpr:
  case scSMinExpr:
  case scUMinExpr:
  case scSequentialUMinExpr:
    return nullptr; // TODO: smax, umax, smin, umax, umin_seq.
  }
  llvm_unreachable("Unknown SCEV kind!");
}

const SCEV *
ScalarEvolution::getWithOperands(const SCEV *S,
                                 SmallVectorImpl<const SCEV *> &NewOps) {
  switch (S->getSCEVType()) {
  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
  case scPtrToInt:
    return getCastExpr(S->getSCEVType(), NewOps[0], S->getType());
  case scAddRecExpr: {
    auto *AddRec = cast<SCEVAddRecExpr>(S);
    return getAddRecExpr(NewOps, AddRec->getLoop(), AddRec->getNoWrapFlags());
  }
  case scAddExpr:
    return getAddExpr(NewOps, cast<SCEVAddExpr>(S)->getNoWrapFlags());
  case scMulExpr:
    return getMulExpr(NewOps, cast<SCEVMulExpr>(S)->getNoWrapFlags());
  case scUDivExpr:
    return getUDivExpr(NewOps[0], NewOps[1]);
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
    return getMinMaxExpr(S->getSCEVType(), NewOps);
  case scSequentialUMinExpr:
    return getSequentialMinMaxExpr(S->getSCEVType(), NewOps);
  case scConstant:
  case scVScale:
  case scUnknown:
    return S;
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
  switch (V->getSCEVType()) {
  case scConstant:
  case scVScale:
    return V;
  case scAddRecExpr: {
    // If this is a loop recurrence for a loop that does not contain L, then we
    // are dealing with the final value computed by the loop.
    const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(V);
    // First, attempt to evaluate each operand.
    // Avoid performing the look-up in the common case where the specified
    // expression has no loop-variant portions.
    for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) {
      const SCEV *OpAtScope = getSCEVAtScope(AddRec->getOperand(i), L);
      if (OpAtScope == AddRec->getOperand(i))
        continue;

      // Okay, at least one of these operands is loop variant but might be
      // foldable.  Build a new instance of the folded commutative expression.
      SmallVector<const SCEV *, 8> NewOps;
      NewOps.reserve(AddRec->getNumOperands());
      append_range(NewOps, AddRec->operands().take_front(i));
      NewOps.push_back(OpAtScope);
      for (++i; i != e; ++i)
        NewOps.push_back(getSCEVAtScope(AddRec->getOperand(i), L));

      const SCEV *FoldedRec = getAddRecExpr(
          NewOps, AddRec->getLoop(), AddRec->getNoWrapFlags(SCEV::FlagNW));
      AddRec = dyn_cast<SCEVAddRecExpr>(FoldedRec);
      // The addrec may be folded to a nonrecurrence, for example, if the
      // induction variable is multiplied by zero after constant folding. Go
      // ahead and return the folded value.
      if (!AddRec)
        return FoldedRec;
      break;
    }

    // If the scope is outside the addrec's loop, evaluate it by using the
    // loop exit value of the addrec.
    if (!AddRec->getLoop()->contains(L)) {
      // To evaluate this recurrence, we need to know how many times the AddRec
      // loop iterates.  Compute this now.
      const SCEV *BackedgeTakenCount = getBackedgeTakenCount(AddRec->getLoop());
      if (BackedgeTakenCount == getCouldNotCompute())
        return AddRec;

      // Then, evaluate the AddRec.
      return AddRec->evaluateAtIteration(BackedgeTakenCount, *this);
    }

    return AddRec;
  }
  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
  case scPtrToInt:
  case scAddExpr:
  case scMulExpr:
  case scUDivExpr:
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scSequentialUMinExpr: {
    ArrayRef<const SCEV *> Ops = V->operands();
    // Avoid performing the look-up in the common case where the specified
    // expression has no loop-variant portions.
    for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
      const SCEV *OpAtScope = getSCEVAtScope(Ops[i], L);
      if (OpAtScope != Ops[i]) {
        // Okay, at least one of these operands is loop variant but might be
        // foldable.  Build a new instance of the folded commutative expression.
        SmallVector<const SCEV *, 8> NewOps;
        NewOps.reserve(Ops.size());
        append_range(NewOps, Ops.take_front(i));
        NewOps.push_back(OpAtScope);

        for (++i; i != e; ++i) {
          OpAtScope = getSCEVAtScope(Ops[i], L);
          NewOps.push_back(OpAtScope);
        }

        return getWithOperands(V, NewOps);
      }
    }
    // If we got here, all operands are loop invariant.
    return V;
  }
  case scUnknown: {
    // If this instruction is evolved from a constant-evolving PHI, compute the
    // exit value from the loop without using SCEVs.
    const SCEVUnknown *SU = cast<SCEVUnknown>(V);
    Instruction *I = dyn_cast<Instruction>(SU->getValue());
    if (!I)
      return V; // This is some other type of SCEVUnknown, just return it.

    if (PHINode *PN = dyn_cast<PHINode>(I)) {
      const Loop *CurrLoop = this->LI[I->getParent()];
      // Looking for loop exit value.
      if (CurrLoop && CurrLoop->getParentLoop() == L &&
          PN->getParent() == CurrLoop->getHeader()) {
        // Okay, there is no closed form solution for the PHI node.  Check
        // to see if the loop that contains it has a known backedge-taken
        // count.  If so, we may be able to force computation of the exit
        // value.
        const SCEV *BackedgeTakenCount = getBackedgeTakenCount(CurrLoop);
        // This trivial case can show up in some degenerate cases where
        // the incoming IR has not yet been fully simplified.
        if (BackedgeTakenCount->isZero()) {
          Value *InitValue = nullptr;
          bool MultipleInitValues = false;
          for (unsigned i = 0; i < PN->getNumIncomingValues(); i++) {
            if (!CurrLoop->contains(PN->getIncomingBlock(i))) {
              if (!InitValue)
                InitValue = PN->getIncomingValue(i);
              else if (InitValue != PN->getIncomingValue(i)) {
                MultipleInitValues = true;
                break;
              }
            }
          }
          if (!MultipleInitValues && InitValue)
            return getSCEV(InitValue);
        }
        // Do we have a loop invariant value flowing around the backedge
        // for a loop which must execute the backedge?
        if (!isa<SCEVCouldNotCompute>(BackedgeTakenCount) &&
            isKnownPositive(BackedgeTakenCount) &&
            PN->getNumIncomingValues() == 2) {

          unsigned InLoopPred =
              CurrLoop->contains(PN->getIncomingBlock(0)) ? 0 : 1;
          Value *BackedgeVal = PN->getIncomingValue(InLoopPred);
          if (CurrLoop->isLoopInvariant(BackedgeVal))
            return getSCEV(BackedgeVal);
        }
        if (auto *BTCC = dyn_cast<SCEVConstant>(BackedgeTakenCount)) {
          // Okay, we know how many times the containing loop executes.  If
          // this is a constant evolving PHI node, get the final value at
          // the specified iteration number.
          Constant *RV =
              getConstantEvolutionLoopExitValue(PN, BTCC->getAPInt(), CurrLoop);
          if (RV)
            return getSCEV(RV);
        }
      }
    }

    // Okay, this is an expression that we cannot symbolically evaluate
    // into a SCEV.  Check to see if it's possible to symbolically evaluate
    // the arguments into constants, and if so, try to constant propagate the
    // result.  This is particularly useful for computing loop exit values.
    if (!CanConstantFold(I))
      return V; // This is some other type of SCEVUnknown, just return it.

    SmallVector<Constant *, 4> Operands;
    Operands.reserve(I->getNumOperands());
    bool MadeImprovement = false;
    for (Value *Op : I->operands()) {
      if (Constant *C = dyn_cast<Constant>(Op)) {
        Operands.push_back(C);
        continue;
      }

      // If any of the operands is non-constant and if they are
      // non-integer and non-pointer, don't even try to analyze them
      // with scev techniques.
      if (!isSCEVable(Op->getType()))
        return V;

      const SCEV *OrigV = getSCEV(Op);
      const SCEV *OpV = getSCEVAtScope(OrigV, L);
      MadeImprovement |= OrigV != OpV;

      Constant *C = BuildConstantFromSCEV(OpV);
      if (!C)
        return V;
      if (C->getType() != Op->getType())
        C = ConstantExpr::getCast(
            CastInst::getCastOpcode(C, false, Op->getType(), false), C,
            Op->getType());
      Operands.push_back(C);
    }

    // Check to see if getSCEVAtScope actually made an improvement.
    if (!MadeImprovement)
      return V; // This is some other type of SCEVUnknown, just return it.

    Constant *C = nullptr;
    const DataLayout &DL = getDataLayout();
    C = ConstantFoldInstOperands(I, Operands, DL, &TLI);
    if (!C)
      return V;
    return getSCEV(C);
  }
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV type!");
}

const SCEV *ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) {
  return getSCEVAtScope(getSCEV(V), L);
}

const SCEV *ScalarEvolution::stripInjectiveFunctions(const SCEV *S) const {
  if (const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S))
    return stripInjectiveFunctions(ZExt->getOperand());
  if (const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S))
    return stripInjectiveFunctions(SExt->getOperand());
  return S;
}

/// Finds the minimum unsigned root of the following equation:
///
///     A * X = B (mod N)
///
/// where N = 2^BW and BW is the common bit width of A and B. The signedness of
/// A and B isn't important.
///
/// If the equation does not have a solution, SCEVCouldNotCompute is returned.
static const SCEV *SolveLinEquationWithOverflow(const APInt &A, const SCEV *B,
                                               ScalarEvolution &SE) {
  uint32_t BW = A.getBitWidth();
  assert(BW == SE.getTypeSizeInBits(B->getType()));
  assert(A != 0 && "A must be non-zero.");

  // 1. D = gcd(A, N)
  //
  // The gcd of A and N may have only one prime factor: 2. The number of
  // trailing zeros in A is its multiplicity
  uint32_t Mult2 = A.countr_zero();
  // D = 2^Mult2

  // 2. Check if B is divisible by D.
  //
  // B is divisible by D if and only if the multiplicity of prime factor 2 for B
  // is not less than multiplicity of this prime factor for D.
  if (SE.getMinTrailingZeros(B) < Mult2)
    return SE.getCouldNotCompute();

  // 3. Compute I: the multiplicative inverse of (A / D) in arithmetic
  // modulo (N / D).
  //
  // If D == 1, (N / D) == N == 2^BW, so we need one extra bit to represent
  // (N / D) in general. The inverse itself always fits into BW bits, though,
  // so we immediately truncate it.
  APInt AD = A.lshr(Mult2).zext(BW + 1);  // AD = A / D
  APInt Mod(BW + 1, 0);
  Mod.setBit(BW - Mult2);  // Mod = N / D
  APInt I = AD.multiplicativeInverse(Mod).trunc(BW);

  // 4. Compute the minimum unsigned root of the equation:
  // I * (B / D) mod (N / D)
  // To simplify the computation, we factor out the divide by D:
  // (I * B mod N) / D
  const SCEV *D = SE.getConstant(APInt::getOneBitSet(BW, Mult2));
  return SE.getUDivExactExpr(SE.getMulExpr(B, SE.getConstant(I)), D);
}

/// For a given quadratic addrec, generate coefficients of the corresponding
/// quadratic equation, multiplied by a common value to ensure that they are
/// integers.
/// The returned value is a tuple { A, B, C, M, BitWidth }, where
/// Ax^2 + Bx + C is the quadratic function, M is the value that A, B and C
/// were multiplied by, and BitWidth is the bit width of the original addrec
/// coefficients.
/// This function returns std::nullopt if the addrec coefficients are not
/// compile- time constants.
static std::optional<std::tuple<APInt, APInt, APInt, APInt, unsigned>>
GetQuadraticEquation(const SCEVAddRecExpr *AddRec) {
  assert(AddRec->getNumOperands() == 3 && "This is not a quadratic chrec!");
  const SCEVConstant *LC = dyn_cast<SCEVConstant>(AddRec->getOperand(0));
  const SCEVConstant *MC = dyn_cast<SCEVConstant>(AddRec->getOperand(1));
  const SCEVConstant *NC = dyn_cast<SCEVConstant>(AddRec->getOperand(2));
  LLVM_DEBUG(dbgs() << __func__ << ": analyzing quadratic addrec: "
                    << *AddRec << '\n');

  // We currently can only solve this if the coefficients are constants.
  if (!LC || !MC || !NC) {
    LLVM_DEBUG(dbgs() << __func__ << ": coefficients are not constant\n");
    return std::nullopt;
  }

  APInt L = LC->getAPInt();
  APInt M = MC->getAPInt();
  APInt N = NC->getAPInt();
  assert(!N.isZero() && "This is not a quadratic addrec");

  unsigned BitWidth = LC->getAPInt().getBitWidth();
  unsigned NewWidth = BitWidth + 1;
  LLVM_DEBUG(dbgs() << __func__ << ": addrec coeff bw: "
                    << BitWidth << '\n');
  // The sign-extension (as opposed to a zero-extension) here matches the
  // extension used in SolveQuadraticEquationWrap (with the same motivation).
  N = N.sext(NewWidth);
  M = M.sext(NewWidth);
  L = L.sext(NewWidth);

  // The increments are M, M+N, M+2N, ..., so the accumulated values are
  //   L+M, (L+M)+(M+N), (L+M)+(M+N)+(M+2N), ..., that is,
  //   L+M, L+2M+N, L+3M+3N, ...
  // After n iterations the accumulated value Acc is L + nM + n(n-1)/2 N.
  //
  // The equation Acc = 0 is then
  //   L + nM + n(n-1)/2 N = 0,  or  2L + 2M n + n(n-1) N = 0.
  // In a quadratic form it becomes:
  //   N n^2 + (2M-N) n + 2L = 0.

  APInt A = N;
  APInt B = 2 * M - A;
  APInt C = 2 * L;
  APInt T = APInt(NewWidth, 2);
  LLVM_DEBUG(dbgs() << __func__ << ": equation " << A << "x^2 + " << B
                    << "x + " << C << ", coeff bw: " << NewWidth
                    << ", multiplied by " << T << '\n');
  return std::make_tuple(A, B, C, T, BitWidth);
}

/// Helper function to compare optional APInts:
/// (a) if X and Y both exist, return min(X, Y),
/// (b) if neither X nor Y exist, return std::nullopt,
/// (c) if exactly one of X and Y exists, return that value.
static std::optional<APInt> MinOptional(std::optional<APInt> X,
                                        std::optional<APInt> Y) {
  if (X && Y) {
    unsigned W = std::max(X->getBitWidth(), Y->getBitWidth());
    APInt XW = X->sext(W);
    APInt YW = Y->sext(W);
    return XW.slt(YW) ? *X : *Y;
  }
  if (!X && !Y)
    return std::nullopt;
  return X ? *X : *Y;
}

/// Helper function to truncate an optional APInt to a given BitWidth.
/// When solving addrec-related equations, it is preferable to return a value
/// that has the same bit width as the original addrec's coefficients. If the
/// solution fits in the original bit width, truncate it (except for i1).
/// Returning a value of a different bit width may inhibit some optimizations.
///
/// In general, a solution to a quadratic equation generated from an addrec
/// may require BW+1 bits, where BW is the bit width of the addrec's
/// coefficients. The reason is that the coefficients of the quadratic
/// equation are BW+1 bits wide (to avoid truncation when converting from
/// the addrec to the equation).
static std::optional<APInt> TruncIfPossible(std::optional<APInt> X,
                                            unsigned BitWidth) {
  if (!X)
    return std::nullopt;
  unsigned W = X->getBitWidth();
  if (BitWidth > 1 && BitWidth < W && X->isIntN(BitWidth))
    return X->trunc(BitWidth);
  return X;
}

/// Let c(n) be the value of the quadratic chrec {L,+,M,+,N} after n
/// iterations. The values L, M, N are assumed to be signed, and they
/// should all have the same bit widths.
/// Find the least n >= 0 such that c(n) = 0 in the arithmetic modulo 2^BW,
/// where BW is the bit width of the addrec's coefficients.
/// If the calculated value is a BW-bit integer (for BW > 1), it will be
/// returned as such, otherwise the bit width of the returned value may
/// be greater than BW.
///
/// This function returns std::nullopt if
/// (a) the addrec coefficients are not constant, or
/// (b) SolveQuadraticEquationWrap was unable to find a solution. For cases
///     like x^2 = 5, no integer solutions exist, in other cases an integer
///     solution may exist, but SolveQuadraticEquationWrap may fail to find it.
static std::optional<APInt>
SolveQuadraticAddRecExact(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) {
  APInt A, B, C, M;
  unsigned BitWidth;
  auto T = GetQuadraticEquation(AddRec);
  if (!T)
    return std::nullopt;

  std::tie(A, B, C, M, BitWidth) = *T;
  LLVM_DEBUG(dbgs() << __func__ << ": solving for unsigned overflow\n");
  std::optional<APInt> X =
      APIntOps::SolveQuadraticEquationWrap(A, B, C, BitWidth + 1);
  if (!X)
    return std::nullopt;

  ConstantInt *CX = ConstantInt::get(SE.getContext(), *X);
  ConstantInt *V = EvaluateConstantChrecAtConstant(AddRec, CX, SE);
  if (!V->isZero())
    return std::nullopt;

  return TruncIfPossible(X, BitWidth);
}

/// Let c(n) be the value of the quadratic chrec {0,+,M,+,N} after n
/// iterations. The values M, N are assumed to be signed, and they
/// should all have the same bit widths.
/// Find the least n such that c(n) does not belong to the given range,
/// while c(n-1) does.
///
/// This function returns std::nullopt if
/// (a) the addrec coefficients are not constant, or
/// (b) SolveQuadraticEquationWrap was unable to find a solution for the
///     bounds of the range.
static std::optional<APInt>
SolveQuadraticAddRecRange(const SCEVAddRecExpr *AddRec,
                          const ConstantRange &Range, ScalarEvolution &SE) {
  assert(AddRec->getOperand(0)->isZero() &&
         "Starting value of addrec should be 0");
  LLVM_DEBUG(dbgs() << __func__ << ": solving boundary crossing for range "
                    << Range << ", addrec " << *AddRec << '\n');
  // This case is handled in getNumIterationsInRange. Here we can assume that
  // we start in the range.
  assert(Range.contains(APInt(SE.getTypeSizeInBits(AddRec->getType()), 0)) &&
         "Addrec's initial value should be in range");

  APInt A, B, C, M;
  unsigned BitWidth;
  auto T = GetQuadraticEquation(AddRec);
  if (!T)
    return std::nullopt;

  // Be careful about the return value: there can be two reasons for not
  // returning an actual number. First, if no solutions to the equations
  // were found, and second, if the solutions don't leave the given range.
  // The first case means that the actual solution is "unknown", the second
  // means that it's known, but not valid. If the solution is unknown, we
  // cannot make any conclusions.
  // Return a pair: the optional solution and a flag indicating if the
  // solution was found.
  auto SolveForBoundary =
      [&](APInt Bound) -> std::pair<std::optional<APInt>, bool> {
    // Solve for signed overflow and unsigned overflow, pick the lower
    // solution.
    LLVM_DEBUG(dbgs() << "SolveQuadraticAddRecRange: checking boundary "
                      << Bound << " (before multiplying by " << M << ")\n");
    Bound *= M; // The quadratic equation multiplier.

    std::optional<APInt> SO;
    if (BitWidth > 1) {
      LLVM_DEBUG(dbgs() << "SolveQuadraticAddRecRange: solving for "
                           "signed overflow\n");
      SO = APIntOps::SolveQuadraticEquationWrap(A, B, -Bound, BitWidth);
    }
    LLVM_DEBUG(dbgs() << "SolveQuadraticAddRecRange: solving for "
                         "unsigned overflow\n");
    std::optional<APInt> UO =
        APIntOps::SolveQuadraticEquationWrap(A, B, -Bound, BitWidth + 1);

    auto LeavesRange = [&] (const APInt &X) {
      ConstantInt *C0 = ConstantInt::get(SE.getContext(), X);
      ConstantInt *V0 = EvaluateConstantChrecAtConstant(AddRec, C0, SE);
      if (Range.contains(V0->getValue()))
        return false;
      // X should be at least 1, so X-1 is non-negative.
      ConstantInt *C1 = ConstantInt::get(SE.getContext(), X-1);
      ConstantInt *V1 = EvaluateConstantChrecAtConstant(AddRec, C1, SE);
      if (Range.contains(V1->getValue()))
        return true;
      return false;
    };

    // If SolveQuadraticEquationWrap returns std::nullopt, it means that there
    // can be a solution, but the function failed to find it. We cannot treat it
    // as "no solution".
    if (!SO || !UO)
      return {std::nullopt, false};

    // Check the smaller value first to see if it leaves the range.
    // At this point, both SO and UO must have values.
    std::optional<APInt> Min = MinOptional(SO, UO);
    if (LeavesRange(*Min))
      return { Min, true };
    std::optional<APInt> Max = Min == SO ? UO : SO;
    if (LeavesRange(*Max))
      return { Max, true };

    // Solutions were found, but were eliminated, hence the "true".
    return {std::nullopt, true};
  };

  std::tie(A, B, C, M, BitWidth) = *T;
  // Lower bound is inclusive, subtract 1 to represent the exiting value.
  APInt Lower = Range.getLower().sext(A.getBitWidth()) - 1;
  APInt Upper = Range.getUpper().sext(A.getBitWidth());
  auto SL = SolveForBoundary(Lower);
  auto SU = SolveForBoundary(Upper);
  // If any of the solutions was unknown, no meaninigful conclusions can
  // be made.
  if (!SL.second || !SU.second)
    return std::nullopt;

  // Claim: The correct solution is not some value between Min and Max.
  //
  // Justification: Assuming that Min and Max are different values, one of
  // them is when the first signed overflow happens, the other is when the
  // first unsigned overflow happens. Crossing the range boundary is only
  // possible via an overflow (treating 0 as a special case of it, modeling
  // an overflow as crossing k*2^W for some k).
  //
  // The interesting case here is when Min was eliminated as an invalid
  // solution, but Max was not. The argument is that if there was another
  // overflow between Min and Max, it would also have been eliminated if
  // it was considered.
  //
  // For a given boundary, it is possible to have two overflows of the same
  // type (signed/unsigned) without having the other type in between: this
  // can happen when the vertex of the parabola is between the iterations
  // corresponding to the overflows. This is only possible when the two
  // overflows cross k*2^W for the same k. In such case, if the second one
  // left the range (and was the first one to do so), the first overflow
  // would have to enter the range, which would mean that either we had left
  // the range before or that we started outside of it. Both of these cases
  // are contradictions.
  //
  // Claim: In the case where SolveForBoundary returns std::nullopt, the correct
  // solution is not some value between the Max for this boundary and the
  // Min of the other boundary.
  //
  // Justification: Assume that we had such Max_A and Min_B corresponding
  // to range boundaries A and B and such that Max_A < Min_B. If there was
  // a solution between Max_A and Min_B, it would have to be caused by an
  // overflow corresponding to either A or B. It cannot correspond to B,
  // since Min_B is the first occurrence of such an overflow. If it
  // corresponded to A, it would have to be either a signed or an unsigned
  // overflow that is larger than both eliminated overflows for A. But
  // between the eliminated overflows and this overflow, the values would
  // cover the entire value space, thus crossing the other boundary, which
  // is a contradiction.

  return TruncIfPossible(MinOptional(SL.first, SU.first), BitWidth);
}

ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
                                                         const Loop *L,
                                                         bool ControlsOnlyExit,
                                                         bool AllowPredicates) {

  // This is only used for loops with a "x != y" exit test. The exit condition
  // is now expressed as a single expression, V = x-y. So the exit test is
  // effectively V != 0.  We know and take advantage of the fact that this
  // expression only being used in a comparison by zero context.

  SmallPtrSet<const SCEVPredicate *, 4> Predicates;
  // If the value is a constant
  if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
    // If the value is already zero, the branch will execute zero times.
    if (C->getValue()->isZero()) return C;
    return getCouldNotCompute();  // Otherwise it will loop infinitely.
  }

  const SCEVAddRecExpr *AddRec =
      dyn_cast<SCEVAddRecExpr>(stripInjectiveFunctions(V));

  if (!AddRec && AllowPredicates)
    // Try to make this an AddRec using runtime tests, in the first X
    // iterations of this loop, where X is the SCEV expression found by the
    // algorithm below.
    AddRec = convertSCEVToAddRecWithPredicates(V, L, Predicates);

  if (!AddRec || AddRec->getLoop() != L)
    return getCouldNotCompute();

  // If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of
  // the quadratic equation to solve it.
  if (AddRec->isQuadratic() && AddRec->getType()->isIntegerTy()) {
    // We can only use this value if the chrec ends up with an exact zero
    // value at this index.  When solving for "X*X != 5", for example, we
    // should not accept a root of 2.
    if (auto S = SolveQuadraticAddRecExact(AddRec, *this)) {
      const auto *R = cast<SCEVConstant>(getConstant(*S));
      return ExitLimit(R, R, R, false, Predicates);
    }
    return getCouldNotCompute();
  }

  // Otherwise we can only handle this if it is affine.
  if (!AddRec->isAffine())
    return getCouldNotCompute();

  // If this is an affine expression, the execution count of this branch is
  // the minimum unsigned root of the following equation:
  //
  //     Start + Step*N = 0 (mod 2^BW)
  //
  // equivalent to:
  //
  //             Step*N = -Start (mod 2^BW)
  //
  // where BW is the common bit width of Start and Step.

  // Get the initial value for the loop.
  const SCEV *Start = getSCEVAtScope(AddRec->getStart(), L->getParentLoop());
  const SCEV *Step = getSCEVAtScope(AddRec->getOperand(1), L->getParentLoop());

  // For now we handle only constant steps.
  //
  // TODO: Handle a nonconstant Step given AddRec<NUW>. If the
  // AddRec is NUW, then (in an unsigned sense) it cannot be counting up to wrap
  // to 0, it must be counting down to equal 0. Consequently, N = Start / -Step.
  // We have not yet seen any such cases.
  const SCEVConstant *StepC = dyn_cast<SCEVConstant>(Step);
  if (!StepC || StepC->getValue()->isZero())
    return getCouldNotCompute();

  // For positive steps (counting up until unsigned overflow):
  //   N = -Start/Step (as unsigned)
  // For negative steps (counting down to zero):
  //   N = Start/-Step
  // First compute the unsigned distance from zero in the direction of Step.
  bool CountDown = StepC->getAPInt().isNegative();
  const SCEV *Distance = CountDown ? Start : getNegativeSCEV(Start);

  // Handle unitary steps, which cannot wraparound.
  // 1*N = -Start; -1*N = Start (mod 2^BW), so:
  //   N = Distance (as unsigned)
  if (StepC->getValue()->isOne() || StepC->getValue()->isMinusOne()) {
    APInt MaxBECount = getUnsignedRangeMax(applyLoopGuards(Distance, L));
    MaxBECount = APIntOps::umin(MaxBECount, getUnsignedRangeMax(Distance));

    // When a loop like "for (int i = 0; i != n; ++i) { /* body */ }" is rotated,
    // we end up with a loop whose backedge-taken count is n - 1.  Detect this
    // case, and see if we can improve the bound.
    //
    // Explicitly handling this here is necessary because getUnsignedRange
    // isn't context-sensitive; it doesn't know that we only care about the
    // range inside the loop.
    const SCEV *Zero = getZero(Distance->getType());
    const SCEV *One = getOne(Distance->getType());
    const SCEV *DistancePlusOne = getAddExpr(Distance, One);
    if (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_NE, DistancePlusOne, Zero)) {
      // If Distance + 1 doesn't overflow, we can compute the maximum distance
      // as "unsigned_max(Distance + 1) - 1".
      ConstantRange CR = getUnsignedRange(DistancePlusOne);
      MaxBECount = APIntOps::umin(MaxBECount, CR.getUnsignedMax() - 1);
    }
    return ExitLimit(Distance, getConstant(MaxBECount), Distance, false,
                     Predicates);
  }

  // If the condition controls loop exit (the loop exits only if the expression
  // is true) and the addition is no-wrap we can use unsigned divide to
  // compute the backedge count.  In this case, the step may not divide the
  // distance, but we don't care because if the condition is "missed" the loop
  // will have undefined behavior due to wrapping.
  if (ControlsOnlyExit && AddRec->hasNoSelfWrap() &&
      loopHasNoAbnormalExits(AddRec->getLoop())) {
    const SCEV *Exact =
        getUDivExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step);
    const SCEV *ConstantMax = getCouldNotCompute();
    if (Exact != getCouldNotCompute()) {
      APInt MaxInt = getUnsignedRangeMax(applyLoopGuards(Exact, L));
      ConstantMax =
          getConstant(APIntOps::umin(MaxInt, getUnsignedRangeMax(Exact)));
    }
    const SCEV *SymbolicMax =
        isa<SCEVCouldNotCompute>(Exact) ? ConstantMax : Exact;
    return ExitLimit(Exact, ConstantMax, SymbolicMax, false, Predicates);
  }

  // Solve the general equation.
  const SCEV *E = SolveLinEquationWithOverflow(StepC->getAPInt(),
                                               getNegativeSCEV(Start), *this);

  const SCEV *M = E;
  if (E != getCouldNotCompute()) {
    APInt MaxWithGuards = getUnsignedRangeMax(applyLoopGuards(E, L));
    M = getConstant(APIntOps::umin(MaxWithGuards, getUnsignedRangeMax(E)));
  }
  auto *S = isa<SCEVCouldNotCompute>(E) ? M : E;
  return ExitLimit(E, M, S, false, Predicates);
}

ScalarEvolution::ExitLimit
ScalarEvolution::howFarToNonZero(const SCEV *V, const Loop *L) {
  // Loops that look like: while (X == 0) are very strange indeed.  We don't
  // handle them yet except for the trivial case.  This could be expanded in the
  // future as needed.

  // If the value is a constant, check to see if it is known to be non-zero
  // already.  If so, the backedge will execute zero times.
  if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
    if (!C->getValue()->isZero())
      return getZero(C->getType());
    return getCouldNotCompute();  // Otherwise it will loop infinitely.
  }

  // We could implement others, but I really doubt anyone writes loops like
  // this, and if they did, they would already be constant folded.
  return getCouldNotCompute();
}

std::pair<const BasicBlock *, const BasicBlock *>
ScalarEvolution::getPredecessorWithUniqueSuccessorForBB(const BasicBlock *BB)
    const {
  // If the block has a unique predecessor, then there is no path from the
  // predecessor to the block that does not go through the direct edge
  // from the predecessor to the block.
  if (const BasicBlock *Pred = BB->getSinglePredecessor())
    return {Pred, BB};

  // A loop's header is defined to be a block that dominates the loop.
  // If the header has a unique predecessor outside the loop, it must be
  // a block that has exactly one successor that can reach the loop.
  if (const Loop *L = LI.getLoopFor(BB))
    return {L->getLoopPredecessor(), L->getHeader()};

  return {nullptr, nullptr};
}

/// SCEV structural equivalence is usually sufficient for testing whether two
/// expressions are equal, however for the purposes of looking for a condition
/// guarding a loop, it can be useful to be a little more general, since a
/// front-end may have replicated the controlling expression.
static bool HasSameValue(const SCEV *A, const SCEV *B) {
  // Quick check to see if they are the same SCEV.
  if (A == B) return true;

  auto ComputesEqualValues = [](const Instruction *A, const Instruction *B) {
    // Not all instructions that are "identical" compute the same value.  For
    // instance, two distinct alloca instructions allocating the same type are
    // identical and do not read memory; but compute distinct values.
    return A->isIdenticalTo(B) && (isa<BinaryOperator>(A) || isa<GetElementPtrInst>(A));
  };

  // Otherwise, if they're both SCEVUnknown, it's possible that they hold
  // two different instructions with the same value. Check for this case.
  if (const SCEVUnknown *AU = dyn_cast<SCEVUnknown>(A))
    if (const SCEVUnknown *BU = dyn_cast<SCEVUnknown>(B))
      if (const Instruction *AI = dyn_cast<Instruction>(AU->getValue()))
        if (const Instruction *BI = dyn_cast<Instruction>(BU->getValue()))
          if (ComputesEqualValues(AI, BI))
            return true;

  // Otherwise assume they may have a different value.
  return false;
}

bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred,
                                           const SCEV *&LHS, const SCEV *&RHS,
                                           unsigned Depth) {
  bool Changed = false;
  // Simplifies ICMP to trivial true or false by turning it into '0 == 0' or
  // '0 != 0'.
  auto TrivialCase = [&](bool TriviallyTrue) {
    LHS = RHS = getConstant(ConstantInt::getFalse(getContext()));
    Pred = TriviallyTrue ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
    return true;
  };
  // If we hit the max recursion limit bail out.
  if (Depth >= 3)
    return false;

  // Canonicalize a constant to the right side.
  if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
    // Check for both operands constant.
    if (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
      if (ConstantExpr::getICmp(Pred,
                                LHSC->getValue(),
                                RHSC->getValue())->isNullValue())
        return TrivialCase(false);
      return TrivialCase(true);
    }
    // Otherwise swap the operands to put the constant on the right.
    std::swap(LHS, RHS);
    Pred = ICmpInst::getSwappedPredicate(Pred);
    Changed = true;
  }

  // If we're comparing an addrec with a value which is loop-invariant in the
  // addrec's loop, put the addrec on the left. Also make a dominance check,
  // as both operands could be addrecs loop-invariant in each other's loop.
  if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(RHS)) {
    const Loop *L = AR->getLoop();
    if (isLoopInvariant(LHS, L) && properlyDominates(LHS, L->getHeader())) {
      std::swap(LHS, RHS);
      Pred = ICmpInst::getSwappedPredicate(Pred);
      Changed = true;
    }
  }

  // If there's a constant operand, canonicalize comparisons with boundary
  // cases, and canonicalize *-or-equal comparisons to regular comparisons.
  if (const SCEVConstant *RC = dyn_cast<SCEVConstant>(RHS)) {
    const APInt &RA = RC->getAPInt();

    bool SimplifiedByConstantRange = false;

    if (!ICmpInst::isEquality(Pred)) {
      ConstantRange ExactCR = ConstantRange::makeExactICmpRegion(Pred, RA);
      if (ExactCR.isFullSet())
        return TrivialCase(true);
      if (ExactCR.isEmptySet())
        return TrivialCase(false);

      APInt NewRHS;
      CmpInst::Predicate NewPred;
      if (ExactCR.getEquivalentICmp(NewPred, NewRHS) &&
          ICmpInst::isEquality(NewPred)) {
        // We were able to convert an inequality to an equality.
        Pred = NewPred;
        RHS = getConstant(NewRHS);
        Changed = SimplifiedByConstantRange = true;
      }
    }

    if (!SimplifiedByConstantRange) {
      switch (Pred) {
      default:
        break;
      case ICmpInst::ICMP_EQ:
      case ICmpInst::ICMP_NE:
        // Fold ((-1) * %a) + %b == 0 (equivalent to %b-%a == 0) into %a == %b.
        if (!RA)
          if (const SCEVAddExpr *AE = dyn_cast<SCEVAddExpr>(LHS))
            if (const SCEVMulExpr *ME =
                    dyn_cast<SCEVMulExpr>(AE->getOperand(0)))
              if (AE->getNumOperands() == 2 && ME->getNumOperands() == 2 &&
                  ME->getOperand(0)->isAllOnesValue()) {
                RHS = AE->getOperand(1);
                LHS = ME->getOperand(1);
                Changed = true;
              }
        break;


        // The "Should have been caught earlier!" messages refer to the fact
        // that the ExactCR.isFullSet() or ExactCR.isEmptySet() check above
        // should have fired on the corresponding cases, and canonicalized the
        // check to trivial case.

      case ICmpInst::ICMP_UGE:
        assert(!RA.isMinValue() && "Should have been caught earlier!");
        Pred = ICmpInst::ICMP_UGT;
        RHS = getConstant(RA - 1);
        Changed = true;
        break;
      case ICmpInst::ICMP_ULE:
        assert(!RA.isMaxValue() && "Should have been caught earlier!");
        Pred = ICmpInst::ICMP_ULT;
        RHS = getConstant(RA + 1);
        Changed = true;
        break;
      case ICmpInst::ICMP_SGE:
        assert(!RA.isMinSignedValue() && "Should have been caught earlier!");
        Pred = ICmpInst::ICMP_SGT;
        RHS = getConstant(RA - 1);
        Changed = true;
        break;
      case ICmpInst::ICMP_SLE:
        assert(!RA.isMaxSignedValue() && "Should have been caught earlier!");
        Pred = ICmpInst::ICMP_SLT;
        RHS = getConstant(RA + 1);
        Changed = true;
        break;
      }
    }
  }

  // Check for obvious equality.
  if (HasSameValue(LHS, RHS)) {
    if (ICmpInst::isTrueWhenEqual(Pred))
      return TrivialCase(true);
    if (ICmpInst::isFalseWhenEqual(Pred))
      return TrivialCase(false);
  }

  // If possible, canonicalize GE/LE comparisons to GT/LT comparisons, by
  // adding or subtracting 1 from one of the operands.
  switch (Pred) {
  case ICmpInst::ICMP_SLE:
    if (!getSignedRangeMax(RHS).isMaxSignedValue()) {
      RHS = getAddExpr(getConstant(RHS->getType(), 1, true), RHS,
                       SCEV::FlagNSW);
      Pred = ICmpInst::ICMP_SLT;
      Changed = true;
    } else if (!getSignedRangeMin(LHS).isMinSignedValue()) {
      LHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), LHS,
                       SCEV::FlagNSW);
      Pred = ICmpInst::ICMP_SLT;
      Changed = true;
    }
    break;
  case ICmpInst::ICMP_SGE:
    if (!getSignedRangeMin(RHS).isMinSignedValue()) {
      RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS,
                       SCEV::FlagNSW);
      Pred = ICmpInst::ICMP_SGT;
      Changed = true;
    } else if (!getSignedRangeMax(LHS).isMaxSignedValue()) {
      LHS = getAddExpr(getConstant(RHS->getType(), 1, true), LHS,
                       SCEV::FlagNSW);
      Pred = ICmpInst::ICMP_SGT;
      Changed = true;
    }
    break;
  case ICmpInst::ICMP_ULE:
    if (!getUnsignedRangeMax(RHS).isMaxValue()) {
      RHS = getAddExpr(getConstant(RHS->getType(), 1, true), RHS,
                       SCEV::FlagNUW);
      Pred = ICmpInst::ICMP_ULT;
      Changed = true;
    } else if (!getUnsignedRangeMin(LHS).isMinValue()) {
      LHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), LHS);
      Pred = ICmpInst::ICMP_ULT;
      Changed = true;
    }
    break;
  case ICmpInst::ICMP_UGE:
    if (!getUnsignedRangeMin(RHS).isMinValue()) {
      RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS);
      Pred = ICmpInst::ICMP_UGT;
      Changed = true;
    } else if (!getUnsignedRangeMax(LHS).isMaxValue()) {
      LHS = getAddExpr(getConstant(RHS->getType(), 1, true), LHS,
                       SCEV::FlagNUW);
      Pred = ICmpInst::ICMP_UGT;
      Changed = true;
    }
    break;
  default:
    break;
  }

  // TODO: More simplifications are possible here.

  // Recursively simplify until we either hit a recursion limit or nothing
  // changes.
  if (Changed)
    return SimplifyICmpOperands(Pred, LHS, RHS, Depth + 1);

  return Changed;
}

bool ScalarEvolution::isKnownNegative(const SCEV *S) {
  return getSignedRangeMax(S).isNegative();
}

bool ScalarEvolution::isKnownPositive(const SCEV *S) {
  return getSignedRangeMin(S).isStrictlyPositive();
}

bool ScalarEvolution::isKnownNonNegative(const SCEV *S) {
  return !getSignedRangeMin(S).isNegative();
}

bool ScalarEvolution::isKnownNonPositive(const SCEV *S) {
  return !getSignedRangeMax(S).isStrictlyPositive();
}

bool ScalarEvolution::isKnownNonZero(const SCEV *S) {
  return getUnsignedRangeMin(S) != 0;
}

std::pair<const SCEV *, const SCEV *>
ScalarEvolution::SplitIntoInitAndPostInc(const Loop *L, const SCEV *S) {
  // Compute SCEV on entry of loop L.
  const SCEV *Start = SCEVInitRewriter::rewrite(S, L, *this);
  if (Start == getCouldNotCompute())
    return { Start, Start };
  // Compute post increment SCEV for loop L.
  const SCEV *PostInc = SCEVPostIncRewriter::rewrite(S, L, *this);
  assert(PostInc != getCouldNotCompute() && "Unexpected could not compute");
  return { Start, PostInc };
}

bool ScalarEvolution::isKnownViaInduction(ICmpInst::Predicate Pred,
                                          const SCEV *LHS, const SCEV *RHS) {
  // First collect all loops.
  SmallPtrSet<const Loop *, 8> LoopsUsed;
  getUsedLoops(LHS, LoopsUsed);
  getUsedLoops(RHS, LoopsUsed);

  if (LoopsUsed.empty())
    return false;

  // Domination relationship must be a linear order on collected loops.
#ifndef NDEBUG
  for (const auto *L1 : LoopsUsed)
    for (const auto *L2 : LoopsUsed)
      assert((DT.dominates(L1->getHeader(), L2->getHeader()) ||
              DT.dominates(L2->getHeader(), L1->getHeader())) &&
             "Domination relationship is not a linear order");
#endif

  const Loop *MDL =
      *std::max_element(LoopsUsed.begin(), LoopsUsed.end(),
                        [&](const Loop *L1, const Loop *L2) {
         return DT.properlyDominates(L1->getHeader(), L2->getHeader());
       });

  // Get init and post increment value for LHS.
  auto SplitLHS = SplitIntoInitAndPostInc(MDL, LHS);
  // if LHS contains unknown non-invariant SCEV then bail out.
  if (SplitLHS.first == getCouldNotCompute())
    return false;
  assert (SplitLHS.second != getCouldNotCompute() && "Unexpected CNC");
  // Get init and post increment value for RHS.
  auto SplitRHS = SplitIntoInitAndPostInc(MDL, RHS);
  // if RHS contains unknown non-invariant SCEV then bail out.
  if (SplitRHS.first == getCouldNotCompute())
    return false;
  assert (SplitRHS.second != getCouldNotCompute() && "Unexpected CNC");
  // It is possible that init SCEV contains an invariant load but it does
  // not dominate MDL and is not available at MDL loop entry, so we should
  // check it here.
  if (!isAvailableAtLoopEntry(SplitLHS.first, MDL) ||
      !isAvailableAtLoopEntry(SplitRHS.first, MDL))
    return false;

  // It seems backedge guard check is faster than entry one so in some cases
  // it can speed up whole estimation by short circuit
  return isLoopBackedgeGuardedByCond(MDL, Pred, SplitLHS.second,
                                     SplitRHS.second) &&
         isLoopEntryGuardedByCond(MDL, Pred, SplitLHS.first, SplitRHS.first);
}

bool ScalarEvolution::isKnownPredicate(ICmpInst::Predicate Pred,
                                       const SCEV *LHS, const SCEV *RHS) {
  // Canonicalize the inputs first.
  (void)SimplifyICmpOperands(Pred, LHS, RHS);

  if (isKnownViaInduction(Pred, LHS, RHS))
    return true;

  if (isKnownPredicateViaSplitting(Pred, LHS, RHS))
    return true;

  // Otherwise see what can be done with some simple reasoning.
  return isKnownViaNonRecursiveReasoning(Pred, LHS, RHS);
}

std::optional<bool> ScalarEvolution::evaluatePredicate(ICmpInst::Predicate Pred,
                                                       const SCEV *LHS,
                                                       const SCEV *RHS) {
  if (isKnownPredicate(Pred, LHS, RHS))
    return true;
  if (isKnownPredicate(ICmpInst::getInversePredicate(Pred), LHS, RHS))
    return false;
  return std::nullopt;
}

bool ScalarEvolution::isKnownPredicateAt(ICmpInst::Predicate Pred,
                                         const SCEV *LHS, const SCEV *RHS,
                                         const Instruction *CtxI) {
  // TODO: Analyze guards and assumes from Context's block.
  return isKnownPredicate(Pred, LHS, RHS) ||
         isBasicBlockEntryGuardedByCond(CtxI->getParent(), Pred, LHS, RHS);
}

std::optional<bool>
ScalarEvolution::evaluatePredicateAt(ICmpInst::Predicate Pred, const SCEV *LHS,
                                     const SCEV *RHS, const Instruction *CtxI) {
  std::optional<bool> KnownWithoutContext = evaluatePredicate(Pred, LHS, RHS);
  if (KnownWithoutContext)
    return KnownWithoutContext;

  if (isBasicBlockEntryGuardedByCond(CtxI->getParent(), Pred, LHS, RHS))
    return true;
  if (isBasicBlockEntryGuardedByCond(CtxI->getParent(),
                                          ICmpInst::getInversePredicate(Pred),
                                          LHS, RHS))
    return false;
  return std::nullopt;
}

bool ScalarEvolution::isKnownOnEveryIteration(ICmpInst::Predicate Pred,
                                              const SCEVAddRecExpr *LHS,
                                              const SCEV *RHS) {
  const Loop *L = LHS->getLoop();
  return isLoopEntryGuardedByCond(L, Pred, LHS->getStart(), RHS) &&
         isLoopBackedgeGuardedByCond(L, Pred, LHS->getPostIncExpr(*this), RHS);
}

std::optional<ScalarEvolution::MonotonicPredicateType>
ScalarEvolution::getMonotonicPredicateType(const SCEVAddRecExpr *LHS,
                                           ICmpInst::Predicate Pred) {
  auto Result = getMonotonicPredicateTypeImpl(LHS, Pred);

#ifndef NDEBUG
  // Verify an invariant: inverting the predicate should turn a monotonically
  // increasing change to a monotonically decreasing one, and vice versa.
  if (Result) {
    auto ResultSwapped =
        getMonotonicPredicateTypeImpl(LHS, ICmpInst::getSwappedPredicate(Pred));

    assert(*ResultSwapped != *Result &&
           "monotonicity should flip as we flip the predicate");
  }
#endif

  return Result;
}

std::optional<ScalarEvolution::MonotonicPredicateType>
ScalarEvolution::getMonotonicPredicateTypeImpl(const SCEVAddRecExpr *LHS,
                                               ICmpInst::Predicate Pred) {
  // A zero step value for LHS means the induction variable is essentially a
  // loop invariant value. We don't really depend on the predicate actually
  // flipping from false to true (for increasing predicates, and the other way
  // around for decreasing predicates), all we care about is that *if* the
  // predicate changes then it only changes from false to true.
  //
  // A zero step value in itself is not very useful, but there may be places
  // where SCEV can prove X >= 0 but not prove X > 0, so it is helpful to be
  // as general as possible.

  // Only handle LE/LT/GE/GT predicates.
  if (!ICmpInst::isRelational(Pred))
    return std::nullopt;

  bool IsGreater = ICmpInst::isGE(Pred) || ICmpInst::isGT(Pred);
  assert((IsGreater || ICmpInst::isLE(Pred) || ICmpInst::isLT(Pred)) &&
         "Should be greater or less!");

  // Check that AR does not wrap.
  if (ICmpInst::isUnsigned(Pred)) {
    if (!LHS->hasNoUnsignedWrap())
      return std::nullopt;
    return IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;
  }
  assert(ICmpInst::isSigned(Pred) &&
         "Relational predicate is either signed or unsigned!");
  if (!LHS->hasNoSignedWrap())
    return std::nullopt;

  const SCEV *Step = LHS->getStepRecurrence(*this);

  if (isKnownNonNegative(Step))
    return IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;

  if (isKnownNonPositive(Step))
    return !IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;

  return std::nullopt;
}

std::optional<ScalarEvolution::LoopInvariantPredicate>
ScalarEvolution::getLoopInvariantPredicate(ICmpInst::Predicate Pred,
                                           const SCEV *LHS, const SCEV *RHS,
                                           const Loop *L,
                                           const Instruction *CtxI) {
  // If there is a loop-invariant, force it into the RHS, otherwise bail out.
  if (!isLoopInvariant(RHS, L)) {
    if (!isLoopInvariant(LHS, L))
      return std::nullopt;

    std::swap(LHS, RHS);
    Pred = ICmpInst::getSwappedPredicate(Pred);
  }

  const SCEVAddRecExpr *ArLHS = dyn_cast<SCEVAddRecExpr>(LHS);
  if (!ArLHS || ArLHS->getLoop() != L)
    return std::nullopt;

  auto MonotonicType = getMonotonicPredicateType(ArLHS, Pred);
  if (!MonotonicType)
    return std::nullopt;
  // If the predicate "ArLHS `Pred` RHS" monotonically increases from false to
  // true as the loop iterates, and the backedge is control dependent on
  // "ArLHS `Pred` RHS" == true then we can reason as follows:
  //
  //   * if the predicate was false in the first iteration then the predicate
  //     is never evaluated again, since the loop exits without taking the
  //     backedge.
  //   * if the predicate was true in the first iteration then it will
  //     continue to be true for all future iterations since it is
  //     monotonically increasing.
  //
  // For both the above possibilities, we can replace the loop varying
  // predicate with its value on the first iteration of the loop (which is
  // loop invariant).
  //
  // A similar reasoning applies for a monotonically decreasing predicate, by
  // replacing true with false and false with true in the above two bullets.
  bool Increasing = *MonotonicType == ScalarEvolution::MonotonicallyIncreasing;
  auto P = Increasing ? Pred : ICmpInst::getInversePredicate(Pred);

  if (isLoopBackedgeGuardedByCond(L, P, LHS, RHS))
    return ScalarEvolution::LoopInvariantPredicate(Pred, ArLHS->getStart(),
                                                   RHS);

  if (!CtxI)
    return std::nullopt;
  // Try to prove via context.
  // TODO: Support other cases.
  switch (Pred) {
  default:
    break;
  case ICmpInst::ICMP_ULE:
  case ICmpInst::ICMP_ULT: {
    assert(ArLHS->hasNoUnsignedWrap() && "Is a requirement of monotonicity!");
    // Given preconditions
    // (1) ArLHS does not cross the border of positive and negative parts of
    //     range because of:
    //     - Positive step; (TODO: lift this limitation)
    //     - nuw - does not cross zero boundary;
    //     - nsw - does not cross SINT_MAX boundary;
    // (2) ArLHS <s RHS
    // (3) RHS >=s 0
    // we can replace the loop variant ArLHS <u RHS condition with loop
    // invariant Start(ArLHS) <u RHS.
    //
    // Because of (1) there are two options:
    // - ArLHS is always negative. It means that ArLHS <u RHS is always false;
    // - ArLHS is always non-negative. Because of (3) RHS is also non-negative.
    //   It means that ArLHS <s RHS <=> ArLHS <u RHS.
    //   Because of (2) ArLHS <u RHS is trivially true.
    // All together it means that ArLHS <u RHS <=> Start(ArLHS) >=s 0.
    // We can strengthen this to Start(ArLHS) <u RHS.
    auto SignFlippedPred = ICmpInst::getFlippedSignednessPredicate(Pred);
    if (ArLHS->hasNoSignedWrap() && ArLHS->isAffine() &&
        isKnownPositive(ArLHS->getStepRecurrence(*this)) &&
        isKnownNonNegative(RHS) &&
        isKnownPredicateAt(SignFlippedPred, ArLHS, RHS, CtxI))
      return ScalarEvolution::LoopInvariantPredicate(Pred, ArLHS->getStart(),
                                                     RHS);
  }
  }

  return std::nullopt;
}

std::optional<ScalarEvolution::LoopInvariantPredicate>
ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(
    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const Loop *L,
    const Instruction *CtxI, const SCEV *MaxIter) {
  if (auto LIP = getLoopInvariantExitCondDuringFirstIterationsImpl(
          Pred, LHS, RHS, L, CtxI, MaxIter))
    return LIP;
  if (auto *UMin = dyn_cast<SCEVUMinExpr>(MaxIter))
    // Number of iterations expressed as UMIN isn't always great for expressing
    // the value on the last iteration. If the straightforward approach didn't
    // work, try the following trick: if the a predicate is invariant for X, it
    // is also invariant for umin(X, ...). So try to find something that works
    // among subexpressions of MaxIter expressed as umin.
    for (auto *Op : UMin->operands())
      if (auto LIP = getLoopInvariantExitCondDuringFirstIterationsImpl(
              Pred, LHS, RHS, L, CtxI, Op))
        return LIP;
  return std::nullopt;
}

std::optional<ScalarEvolution::LoopInvariantPredicate>
ScalarEvolution::getLoopInvariantExitCondDuringFirstIterationsImpl(
    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const Loop *L,
    const Instruction *CtxI, const SCEV *MaxIter) {
  // Try to prove the following set of facts:
  // - The predicate is monotonic in the iteration space.
  // - If the check does not fail on the 1st iteration:
  //   - No overflow will happen during first MaxIter iterations;
  //   - It will not fail on the MaxIter'th iteration.
  // If the check does fail on the 1st iteration, we leave the loop and no
  // other checks matter.

  // If there is a loop-invariant, force it into the RHS, otherwise bail out.
  if (!isLoopInvariant(RHS, L)) {
    if (!isLoopInvariant(LHS, L))
      return std::nullopt;

    std::swap(LHS, RHS);
    Pred = ICmpInst::getSwappedPredicate(Pred);
  }

  auto *AR = dyn_cast<SCEVAddRecExpr>(LHS);
  if (!AR || AR->getLoop() != L)
    return std::nullopt;

  // The predicate must be relational (i.e. <, <=, >=, >).
  if (!ICmpInst::isRelational(Pred))
    return std::nullopt;

  // TODO: Support steps other than +/- 1.
  const SCEV *Step = AR->getStepRecurrence(*this);
  auto *One = getOne(Step->getType());
  auto *MinusOne = getNegativeSCEV(One);
  if (Step != One && Step != MinusOne)
    return std::nullopt;

  // Type mismatch here means that MaxIter is potentially larger than max
  // unsigned value in start type, which mean we cannot prove no wrap for the
  // indvar.
  if (AR->getType() != MaxIter->getType())
    return std::nullopt;

  // Value of IV on suggested last iteration.
  const SCEV *Last = AR->evaluateAtIteration(MaxIter, *this);
  // Does it still meet the requirement?
  if (!isLoopBackedgeGuardedByCond(L, Pred, Last, RHS))
    return std::nullopt;
  // Because step is +/- 1 and MaxIter has same type as Start (i.e. it does
  // not exceed max unsigned value of this type), this effectively proves
  // that there is no wrap during the iteration. To prove that there is no
  // signed/unsigned wrap, we need to check that
  // Start <= Last for step = 1 or Start >= Last for step = -1.
  ICmpInst::Predicate NoOverflowPred =
      CmpInst::isSigned(Pred) ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
  if (Step == MinusOne)
    NoOverflowPred = CmpInst::getSwappedPredicate(NoOverflowPred);
  const SCEV *Start = AR->getStart();
  if (!isKnownPredicateAt(NoOverflowPred, Start, Last, CtxI))
    return std::nullopt;

  // Everything is fine.
  return ScalarEvolution::LoopInvariantPredicate(Pred, Start, RHS);
}

bool ScalarEvolution::isKnownPredicateViaConstantRanges(
    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS) {
  if (HasSameValue(LHS, RHS))
    return ICmpInst::isTrueWhenEqual(Pred);

  // This code is split out from isKnownPredicate because it is called from
  // within isLoopEntryGuardedByCond.

  auto CheckRanges = [&](const ConstantRange &RangeLHS,
                         const ConstantRange &RangeRHS) {
    return RangeLHS.icmp(Pred, RangeRHS);
  };

  // The check at the top of the function catches the case where the values are
  // known to be equal.
  if (Pred == CmpInst::ICMP_EQ)
    return false;

  if (Pred == CmpInst::ICMP_NE) {
    auto SL = getSignedRange(LHS);
    auto SR = getSignedRange(RHS);
    if (CheckRanges(SL, SR))
      return true;
    auto UL = getUnsignedRange(LHS);
    auto UR = getUnsignedRange(RHS);
    if (CheckRanges(UL, UR))
      return true;
    auto *Diff = getMinusSCEV(LHS, RHS);
    return !isa<SCEVCouldNotCompute>(Diff) && isKnownNonZero(Diff);
  }

  if (CmpInst::isSigned(Pred)) {
    auto SL = getSignedRange(LHS);
    auto SR = getSignedRange(RHS);
    return CheckRanges(SL, SR);
  }

  auto UL = getUnsignedRange(LHS);
  auto UR = getUnsignedRange(RHS);
  return CheckRanges(UL, UR);
}

bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
                                                    const SCEV *LHS,
                                                    const SCEV *RHS) {
  // Match X to (A + C1)<ExpectedFlags> and Y to (A + C2)<ExpectedFlags>, where
  // C1 and C2 are constant integers. If either X or Y are not add expressions,
  // consider them as X + 0 and Y + 0 respectively. C1 and C2 are returned via
  // OutC1 and OutC2.
  auto MatchBinaryAddToConst = [this](const SCEV *X, const SCEV *Y,
                                      APInt &OutC1, APInt &OutC2,
                                      SCEV::NoWrapFlags ExpectedFlags) {
    const SCEV *XNonConstOp, *XConstOp;
    const SCEV *YNonConstOp, *YConstOp;
    SCEV::NoWrapFlags XFlagsPresent;
    SCEV::NoWrapFlags YFlagsPresent;

    if (!splitBinaryAdd(X, XConstOp, XNonConstOp, XFlagsPresent)) {
      XConstOp = getZero(X->getType());
      XNonConstOp = X;
      XFlagsPresent = ExpectedFlags;
    }
    if (!isa<SCEVConstant>(XConstOp) ||
        (XFlagsPresent & ExpectedFlags) != ExpectedFlags)
      return false;

    if (!splitBinaryAdd(Y, YConstOp, YNonConstOp, YFlagsPresent)) {
      YConstOp = getZero(Y->getType());
      YNonConstOp = Y;
      YFlagsPresent = ExpectedFlags;
    }

    if (!isa<SCEVConstant>(YConstOp) ||
        (YFlagsPresent & ExpectedFlags) != ExpectedFlags)
      return false;

    if (YNonConstOp != XNonConstOp)
      return false;

    OutC1 = cast<SCEVConstant>(XConstOp)->getAPInt();
    OutC2 = cast<SCEVConstant>(YConstOp)->getAPInt();

    return true;
  };

  APInt C1;
  APInt C2;

  switch (Pred) {
  default:
    break;

  case ICmpInst::ICMP_SGE:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_SLE:
    // (X + C1)<nsw> s<= (X + C2)<nsw> if C1 s<= C2.
    if (MatchBinaryAddToConst(LHS, RHS, C1, C2, SCEV::FlagNSW) && C1.sle(C2))
      return true;

    break;

  case ICmpInst::ICMP_SGT:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_SLT:
    // (X + C1)<nsw> s< (X + C2)<nsw> if C1 s< C2.
    if (MatchBinaryAddToConst(LHS, RHS, C1, C2, SCEV::FlagNSW) && C1.slt(C2))
      return true;

    break;

  case ICmpInst::ICMP_UGE:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_ULE:
    // (X + C1)<nuw> u<= (X + C2)<nuw> for C1 u<= C2.
    if (MatchBinaryAddToConst(RHS, LHS, C2, C1, SCEV::FlagNUW) && C1.ule(C2))
      return true;

    break;

  case ICmpInst::ICMP_UGT:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_ULT:
    // (X + C1)<nuw> u< (X + C2)<nuw> if C1 u< C2.
    if (MatchBinaryAddToConst(RHS, LHS, C2, C1, SCEV::FlagNUW) && C1.ult(C2))
      return true;
    break;
  }

  return false;
}

bool ScalarEvolution::isKnownPredicateViaSplitting(ICmpInst::Predicate Pred,
                                                   const SCEV *LHS,
                                                   const SCEV *RHS) {
  if (Pred != ICmpInst::ICMP_ULT || ProvingSplitPredicate)
    return false;

  // Allowing arbitrary number of activations of isKnownPredicateViaSplitting on
  // the stack can result in exponential time complexity.
  SaveAndRestore Restore(ProvingSplitPredicate, true);

  // If L >= 0 then I `ult` L <=> I >= 0 && I `slt` L
  //
  // To prove L >= 0 we use isKnownNonNegative whereas to prove I >= 0 we use
  // isKnownPredicate.  isKnownPredicate is more powerful, but also more
  // expensive; and using isKnownNonNegative(RHS) is sufficient for most of the
  // interesting cases seen in practice.  We can consider "upgrading" L >= 0 to
  // use isKnownPredicate later if needed.
  return isKnownNonNegative(RHS) &&
         isKnownPredicate(CmpInst::ICMP_SGE, LHS, getZero(LHS->getType())) &&
         isKnownPredicate(CmpInst::ICMP_SLT, LHS, RHS);
}

bool ScalarEvolution::isImpliedViaGuard(const BasicBlock *BB,
                                        ICmpInst::Predicate Pred,
                                        const SCEV *LHS, const SCEV *RHS) {
  // No need to even try if we know the module has no guards.
  if (!HasGuards)
    return false;

  return any_of(*BB, [&](const Instruction &I) {
    using namespace llvm::PatternMatch;

    Value *Condition;
    return match(&I, m_Intrinsic<Intrinsic::experimental_guard>(
                         m_Value(Condition))) &&
           isImpliedCond(Pred, LHS, RHS, Condition, false);
  });
}

/// isLoopBackedgeGuardedByCond - Test whether the backedge of the loop is
/// protected by a conditional between LHS and RHS.  This is used to
/// to eliminate casts.
bool
ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
                                             ICmpInst::Predicate Pred,
                                             const SCEV *LHS, const SCEV *RHS) {
  // Interpret a null as meaning no loop, where there is obviously no guard
  // (interprocedural conditions notwithstanding). Do not bother about
  // unreachable loops.
  if (!L || !DT.isReachableFromEntry(L->getHeader()))
    return true;

  if (VerifyIR)
    assert(!verifyFunction(*L->getHeader()->getParent(), &dbgs()) &&
           "This cannot be done on broken IR!");


  if (isKnownViaNonRecursiveReasoning(Pred, LHS, RHS))
    return true;

  BasicBlock *Latch = L->getLoopLatch();
  if (!Latch)
    return false;

  BranchInst *LoopContinuePredicate =
    dyn_cast<BranchInst>(Latch->getTerminator());
  if (LoopContinuePredicate && LoopContinuePredicate->isConditional() &&
      isImpliedCond(Pred, LHS, RHS,
                    LoopContinuePredicate->getCondition(),
                    LoopContinuePredicate->getSuccessor(0) != L->getHeader()))
    return true;

  // We don't want more than one activation of the following loops on the stack
  // -- that can lead to O(n!) time complexity.
  if (WalkingBEDominatingConds)
    return false;

  SaveAndRestore ClearOnExit(WalkingBEDominatingConds, true);

  // See if we can exploit a trip count to prove the predicate.
  const auto &BETakenInfo = getBackedgeTakenInfo(L);
  const SCEV *LatchBECount = BETakenInfo.getExact(Latch, this);
  if (LatchBECount != getCouldNotCompute()) {
    // We know that Latch branches back to the loop header exactly
    // LatchBECount times.  This means the backdege condition at Latch is
    // equivalent to  "{0,+,1} u< LatchBECount".
    Type *Ty = LatchBECount->getType();
    auto NoWrapFlags = SCEV::NoWrapFlags(SCEV::FlagNUW | SCEV::FlagNW);
    const SCEV *LoopCounter =
      getAddRecExpr(getZero(Ty), getOne(Ty), L, NoWrapFlags);
    if (isImpliedCond(Pred, LHS, RHS, ICmpInst::ICMP_ULT, LoopCounter,
                      LatchBECount))
      return true;
  }

  // Check conditions due to any @llvm.assume intrinsics.
  for (auto &AssumeVH : AC.assumptions()) {
    if (!AssumeVH)
      continue;
    auto *CI = cast<CallInst>(AssumeVH);
    if (!DT.dominates(CI, Latch->getTerminator()))
      continue;

    if (isImpliedCond(Pred, LHS, RHS, CI->getArgOperand(0), false))
      return true;
  }

  if (isImpliedViaGuard(Latch, Pred, LHS, RHS))
    return true;

  for (DomTreeNode *DTN = DT[Latch], *HeaderDTN = DT[L->getHeader()];
       DTN != HeaderDTN; DTN = DTN->getIDom()) {
    assert(DTN && "should reach the loop header before reaching the root!");

    BasicBlock *BB = DTN->getBlock();
    if (isImpliedViaGuard(BB, Pred, LHS, RHS))
      return true;

    BasicBlock *PBB = BB->getSinglePredecessor();
    if (!PBB)
      continue;

    BranchInst *ContinuePredicate = dyn_cast<BranchInst>(PBB->getTerminator());
    if (!ContinuePredicate || !ContinuePredicate->isConditional())
      continue;

    Value *Condition = ContinuePredicate->getCondition();

    // If we have an edge `E` within the loop body that dominates the only
    // latch, the condition guarding `E` also guards the backedge.  This
    // reasoning works only for loops with a single latch.

    BasicBlockEdge DominatingEdge(PBB, BB);
    if (DominatingEdge.isSingleEdge()) {
      // We're constructively (and conservatively) enumerating edges within the
      // loop body that dominate the latch.  The dominator tree better agree
      // with us on this:
      assert(DT.dominates(DominatingEdge, Latch) && "should be!");

      if (isImpliedCond(Pred, LHS, RHS, Condition,
                        BB != ContinuePredicate->getSuccessor(0)))
        return true;
    }
  }

  return false;
}

bool ScalarEvolution::isBasicBlockEntryGuardedByCond(const BasicBlock *BB,
                                                     ICmpInst::Predicate Pred,
                                                     const SCEV *LHS,
                                                     const SCEV *RHS) {
  // Do not bother proving facts for unreachable code.
  if (!DT.isReachableFromEntry(BB))
    return true;
  if (VerifyIR)
    assert(!verifyFunction(*BB->getParent(), &dbgs()) &&
           "This cannot be done on broken IR!");

  // If we cannot prove strict comparison (e.g. a > b), maybe we can prove
  // the facts (a >= b && a != b) separately. A typical situation is when the
  // non-strict comparison is known from ranges and non-equality is known from
  // dominating predicates. If we are proving strict comparison, we always try
  // to prove non-equality and non-strict comparison separately.
  auto NonStrictPredicate = ICmpInst::getNonStrictPredicate(Pred);
  const bool ProvingStrictComparison = (Pred != NonStrictPredicate);
  bool ProvedNonStrictComparison = false;
  bool ProvedNonEquality = false;

  auto SplitAndProve =
    [&](std::function<bool(ICmpInst::Predicate)> Fn) -> bool {
    if (!ProvedNonStrictComparison)
      ProvedNonStrictComparison = Fn(NonStrictPredicate);
    if (!ProvedNonEquality)
      ProvedNonEquality = Fn(ICmpInst::ICMP_NE);
    if (ProvedNonStrictComparison && ProvedNonEquality)
      return true;
    return false;
  };

  if (ProvingStrictComparison) {
    auto ProofFn = [&](ICmpInst::Predicate P) {
      return isKnownViaNonRecursiveReasoning(P, LHS, RHS);
    };
    if (SplitAndProve(ProofFn))
      return true;
  }

  // Try to prove (Pred, LHS, RHS) using isImpliedCond.
  auto ProveViaCond = [&](const Value *Condition, bool Inverse) {
    const Instruction *CtxI = &BB->front();
    if (isImpliedCond(Pred, LHS, RHS, Condition, Inverse, CtxI))
      return true;
    if (ProvingStrictComparison) {
      auto ProofFn = [&](ICmpInst::Predicate P) {
        return isImpliedCond(P, LHS, RHS, Condition, Inverse, CtxI);
      };
      if (SplitAndProve(ProofFn))
        return true;
    }
    return false;
  };

  // Starting at the block's predecessor, climb up the predecessor chain, as long
  // as there are predecessors that can be found that have unique successors
  // leading to the original block.
  const Loop *ContainingLoop = LI.getLoopFor(BB);
  const BasicBlock *PredBB;
  if (ContainingLoop && ContainingLoop->getHeader() == BB)
    PredBB = ContainingLoop->getLoopPredecessor();
  else
    PredBB = BB->getSinglePredecessor();
  for (std::pair<const BasicBlock *, const BasicBlock *> Pair(PredBB, BB);
       Pair.first; Pair = getPredecessorWithUniqueSuccessorForBB(Pair.first)) {
    const BranchInst *BlockEntryPredicate =
        dyn_cast<BranchInst>(Pair.first->getTerminator());
    if (!BlockEntryPredicate || BlockEntryPredicate->isUnconditional())
      continue;

    if (ProveViaCond(BlockEntryPredicate->getCondition(),
                     BlockEntryPredicate->getSuccessor(0) != Pair.second))
      return true;
  }

  // Check conditions due to any @llvm.assume intrinsics.
  for (auto &AssumeVH : AC.assumptions()) {
    if (!AssumeVH)
      continue;
    auto *CI = cast<CallInst>(AssumeVH);
    if (!DT.dominates(CI, BB))
      continue;

    if (ProveViaCond(CI->getArgOperand(0), false))
      return true;
  }

  // Check conditions due to any @llvm.experimental.guard intrinsics.
  auto *GuardDecl = F.getParent()->getFunction(
      Intrinsic::getName(Intrinsic::experimental_guard));
  if (GuardDecl)
    for (const auto *GU : GuardDecl->users())
      if (const auto *Guard = dyn_cast<IntrinsicInst>(GU))
        if (Guard->getFunction() == BB->getParent() && DT.dominates(Guard, BB))
          if (ProveViaCond(Guard->getArgOperand(0), false))
            return true;
  return false;
}

bool ScalarEvolution::isLoopEntryGuardedByCond(const Loop *L,
                                               ICmpInst::Predicate Pred,
                                               const SCEV *LHS,
                                               const SCEV *RHS) {
  // Interpret a null as meaning no loop, where there is obviously no guard
  // (interprocedural conditions notwithstanding).
  if (!L)
    return false;

  // Both LHS and RHS must be available at loop entry.
  assert(isAvailableAtLoopEntry(LHS, L) &&
         "LHS is not available at Loop Entry");
  assert(isAvailableAtLoopEntry(RHS, L) &&
         "RHS is not available at Loop Entry");

  if (isKnownViaNonRecursiveReasoning(Pred, LHS, RHS))
    return true;

  return isBasicBlockEntryGuardedByCond(L->getHeader(), Pred, LHS, RHS);
}

bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
                                    const SCEV *RHS,
                                    const Value *FoundCondValue, bool Inverse,
                                    const Instruction *CtxI) {
  // False conditions implies anything. Do not bother analyzing it further.
  if (FoundCondValue ==
      ConstantInt::getBool(FoundCondValue->getContext(), Inverse))
    return true;

  if (!PendingLoopPredicates.insert(FoundCondValue).second)
    return false;

  auto ClearOnExit =
      make_scope_exit([&]() { PendingLoopPredicates.erase(FoundCondValue); });

  // Recursively handle And and Or conditions.
  const Value *Op0, *Op1;
  if (match(FoundCondValue, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
    if (!Inverse)
      return isImpliedCond(Pred, LHS, RHS, Op0, Inverse, CtxI) ||
             isImpliedCond(Pred, LHS, RHS, Op1, Inverse, CtxI);
  } else if (match(FoundCondValue, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) {
    if (Inverse)
      return isImpliedCond(Pred, LHS, RHS, Op0, Inverse, CtxI) ||
             isImpliedCond(Pred, LHS, RHS, Op1, Inverse, CtxI);
  }

  const ICmpInst *ICI = dyn_cast<ICmpInst>(FoundCondValue);
  if (!ICI) return false;

  // Now that we found a conditional branch that dominates the loop or controls
  // the loop latch. Check to see if it is the comparison we are looking for.
  ICmpInst::Predicate FoundPred;
  if (Inverse)
    FoundPred = ICI->getInversePredicate();
  else
    FoundPred = ICI->getPredicate();

  const SCEV *FoundLHS = getSCEV(ICI->getOperand(0));
  const SCEV *FoundRHS = getSCEV(ICI->getOperand(1));

  return isImpliedCond(Pred, LHS, RHS, FoundPred, FoundLHS, FoundRHS, CtxI);
}

bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
                                    const SCEV *RHS,
                                    ICmpInst::Predicate FoundPred,
                                    const SCEV *FoundLHS, const SCEV *FoundRHS,
                                    const Instruction *CtxI) {
  // Balance the types.
  if (getTypeSizeInBits(LHS->getType()) <
      getTypeSizeInBits(FoundLHS->getType())) {
    // For unsigned and equality predicates, try to prove that both found
    // operands fit into narrow unsigned range. If so, try to prove facts in
    // narrow types.
    if (!CmpInst::isSigned(FoundPred) && !FoundLHS->getType()->isPointerTy() &&
        !FoundRHS->getType()->isPointerTy()) {
      auto *NarrowType = LHS->getType();
      auto *WideType = FoundLHS->getType();
      auto BitWidth = getTypeSizeInBits(NarrowType);
      const SCEV *MaxValue = getZeroExtendExpr(
          getConstant(APInt::getMaxValue(BitWidth)), WideType);
      if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, FoundLHS,
                                          MaxValue) &&
          isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, FoundRHS,
                                          MaxValue)) {
        const SCEV *TruncFoundLHS = getTruncateExpr(FoundLHS, NarrowType);
        const SCEV *TruncFoundRHS = getTruncateExpr(FoundRHS, NarrowType);
        if (isImpliedCondBalancedTypes(Pred, LHS, RHS, FoundPred, TruncFoundLHS,
                                       TruncFoundRHS, CtxI))
          return true;
      }
    }

    if (LHS->getType()->isPointerTy() || RHS->getType()->isPointerTy())
      return false;
    if (CmpInst::isSigned(Pred)) {
      LHS = getSignExtendExpr(LHS, FoundLHS->getType());
      RHS = getSignExtendExpr(RHS, FoundLHS->getType());
    } else {
      LHS = getZeroExtendExpr(LHS, FoundLHS->getType());
      RHS = getZeroExtendExpr(RHS, FoundLHS->getType());
    }
  } else if (getTypeSizeInBits(LHS->getType()) >
      getTypeSizeInBits(FoundLHS->getType())) {
    if (FoundLHS->getType()->isPointerTy() || FoundRHS->getType()->isPointerTy())
      return false;
    if (CmpInst::isSigned(FoundPred)) {
      FoundLHS = getSignExtendExpr(FoundLHS, LHS->getType());
      FoundRHS = getSignExtendExpr(FoundRHS, LHS->getType());
    } else {
      FoundLHS = getZeroExtendExpr(FoundLHS, LHS->getType());
      FoundRHS = getZeroExtendExpr(FoundRHS, LHS->getType());
    }
  }
  return isImpliedCondBalancedTypes(Pred, LHS, RHS, FoundPred, FoundLHS,
                                    FoundRHS, CtxI);
}

bool ScalarEvolution::isImpliedCondBalancedTypes(
    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
    ICmpInst::Predicate FoundPred, const SCEV *FoundLHS, const SCEV *FoundRHS,
    const Instruction *CtxI) {
  assert(getTypeSizeInBits(LHS->getType()) ==
             getTypeSizeInBits(FoundLHS->getType()) &&
         "Types should be balanced!");
  // Canonicalize the query to match the way instcombine will have
  // canonicalized the comparison.
  if (SimplifyICmpOperands(Pred, LHS, RHS))
    if (LHS == RHS)
      return CmpInst::isTrueWhenEqual(Pred);
  if (SimplifyICmpOperands(FoundPred, FoundLHS, FoundRHS))
    if (FoundLHS == FoundRHS)
      return CmpInst::isFalseWhenEqual(FoundPred);

  // Check to see if we can make the LHS or RHS match.
  if (LHS == FoundRHS || RHS == FoundLHS) {
    if (isa<SCEVConstant>(RHS)) {
      std::swap(FoundLHS, FoundRHS);
      FoundPred = ICmpInst::getSwappedPredicate(FoundPred);
    } else {
      std::swap(LHS, RHS);
      Pred = ICmpInst::getSwappedPredicate(Pred);
    }
  }

  // Check whether the found predicate is the same as the desired predicate.
  if (FoundPred == Pred)
    return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI);

  // Check whether swapping the found predicate makes it the same as the
  // desired predicate.
  if (ICmpInst::getSwappedPredicate(FoundPred) == Pred) {
    // We can write the implication
    // 0.  LHS Pred      RHS  <-   FoundLHS SwapPred  FoundRHS
    // using one of the following ways:
    // 1.  LHS Pred      RHS  <-   FoundRHS Pred      FoundLHS
    // 2.  RHS SwapPred  LHS  <-   FoundLHS SwapPred  FoundRHS
    // 3.  LHS Pred      RHS  <-  ~FoundLHS Pred     ~FoundRHS
    // 4. ~LHS SwapPred ~RHS  <-   FoundLHS SwapPred  FoundRHS
    // Forms 1. and 2. require swapping the operands of one condition. Don't
    // do this if it would break canonical constant/addrec ordering.
    if (!isa<SCEVConstant>(RHS) && !isa<SCEVAddRecExpr>(LHS))
      return isImpliedCondOperands(FoundPred, RHS, LHS, FoundLHS, FoundRHS,
                                   CtxI);
    if (!isa<SCEVConstant>(FoundRHS) && !isa<SCEVAddRecExpr>(FoundLHS))
      return isImpliedCondOperands(Pred, LHS, RHS, FoundRHS, FoundLHS, CtxI);

    // There's no clear preference between forms 3. and 4., try both.  Avoid
    // forming getNotSCEV of pointer values as the resulting subtract is
    // not legal.
    if (!LHS->getType()->isPointerTy() && !RHS->getType()->isPointerTy() &&
        isImpliedCondOperands(FoundPred, getNotSCEV(LHS), getNotSCEV(RHS),
                              FoundLHS, FoundRHS, CtxI))
      return true;

    if (!FoundLHS->getType()->isPointerTy() &&
        !FoundRHS->getType()->isPointerTy() &&
        isImpliedCondOperands(Pred, LHS, RHS, getNotSCEV(FoundLHS),
                              getNotSCEV(FoundRHS), CtxI))
      return true;

    return false;
  }

  auto IsSignFlippedPredicate = [](CmpInst::Predicate P1,
                                   CmpInst::Predicate P2) {
    assert(P1 != P2 && "Handled earlier!");
    return CmpInst::isRelational(P2) &&
           P1 == CmpInst::getFlippedSignednessPredicate(P2);
  };
  if (IsSignFlippedPredicate(Pred, FoundPred)) {
    // Unsigned comparison is the same as signed comparison when both the
    // operands are non-negative or negative.
    if ((isKnownNonNegative(FoundLHS) && isKnownNonNegative(FoundRHS)) ||
        (isKnownNegative(FoundLHS) && isKnownNegative(FoundRHS)))
      return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI);
    // Create local copies that we can freely swap and canonicalize our
    // conditions to "le/lt".
    ICmpInst::Predicate CanonicalPred = Pred, CanonicalFoundPred = FoundPred;
    const SCEV *CanonicalLHS = LHS, *CanonicalRHS = RHS,
               *CanonicalFoundLHS = FoundLHS, *CanonicalFoundRHS = FoundRHS;
    if (ICmpInst::isGT(CanonicalPred) || ICmpInst::isGE(CanonicalPred)) {
      CanonicalPred = ICmpInst::getSwappedPredicate(CanonicalPred);
      CanonicalFoundPred = ICmpInst::getSwappedPredicate(CanonicalFoundPred);
      std::swap(CanonicalLHS, CanonicalRHS);
      std::swap(CanonicalFoundLHS, CanonicalFoundRHS);
    }
    assert((ICmpInst::isLT(CanonicalPred) || ICmpInst::isLE(CanonicalPred)) &&
           "Must be!");
    assert((ICmpInst::isLT(CanonicalFoundPred) ||
            ICmpInst::isLE(CanonicalFoundPred)) &&
           "Must be!");
    if (ICmpInst::isSigned(CanonicalPred) && isKnownNonNegative(CanonicalRHS))
      // Use implication:
      // x <u y && y >=s 0 --> x <s y.
      // If we can prove the left part, the right part is also proven.
      return isImpliedCondOperands(CanonicalFoundPred, CanonicalLHS,
                                   CanonicalRHS, CanonicalFoundLHS,
                                   CanonicalFoundRHS);
    if (ICmpInst::isUnsigned(CanonicalPred) && isKnownNegative(CanonicalRHS))
      // Use implication:
      // x <s y && y <s 0 --> x <u y.
      // If we can prove the left part, the right part is also proven.
      return isImpliedCondOperands(CanonicalFoundPred, CanonicalLHS,
                                   CanonicalRHS, CanonicalFoundLHS,
                                   CanonicalFoundRHS);
  }

  // Check if we can make progress by sharpening ranges.
  if (FoundPred == ICmpInst::ICMP_NE &&
      (isa<SCEVConstant>(FoundLHS) || isa<SCEVConstant>(FoundRHS))) {

    const SCEVConstant *C = nullptr;
    const SCEV *V = nullptr;

    if (isa<SCEVConstant>(FoundLHS)) {
      C = cast<SCEVConstant>(FoundLHS);
      V = FoundRHS;
    } else {
      C = cast<SCEVConstant>(FoundRHS);
      V = FoundLHS;
    }

    // The guarding predicate tells us that C != V. If the known range
    // of V is [C, t), we can sharpen the range to [C + 1, t).  The
    // range we consider has to correspond to same signedness as the
    // predicate we're interested in folding.

    APInt Min = ICmpInst::isSigned(Pred) ?
        getSignedRangeMin(V) : getUnsignedRangeMin(V);

    if (Min == C->getAPInt()) {
      // Given (V >= Min && V != Min) we conclude V >= (Min + 1).
      // This is true even if (Min + 1) wraps around -- in case of
      // wraparound, (Min + 1) < Min, so (V >= Min => V >= (Min + 1)).

      APInt SharperMin = Min + 1;

      switch (Pred) {
        case ICmpInst::ICMP_SGE:
        case ICmpInst::ICMP_UGE:
          // We know V `Pred` SharperMin.  If this implies LHS `Pred`
          // RHS, we're done.
          if (isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(SharperMin),
                                    CtxI))
            return true;
          [[fallthrough]];

        case ICmpInst::ICMP_SGT:
        case ICmpInst::ICMP_UGT:
          // We know from the range information that (V `Pred` Min ||
          // V == Min).  We know from the guarding condition that !(V
          // == Min).  This gives us
          //
          //       V `Pred` Min || V == Min && !(V == Min)
          //   =>  V `Pred` Min
          //
          // If V `Pred` Min implies LHS `Pred` RHS, we're done.

          if (isImpliedCondOperands(Pred, LHS, RHS, V, getConstant(Min), CtxI))
            return true;
          break;

        // `LHS < RHS` and `LHS <= RHS` are handled in the same way as `RHS > LHS` and `RHS >= LHS` respectively.
        case ICmpInst::ICMP_SLE:
        case ICmpInst::ICMP_ULE:
          if (isImpliedCondOperands(CmpInst::getSwappedPredicate(Pred), RHS,
                                    LHS, V, getConstant(SharperMin), CtxI))
            return true;
          [[fallthrough]];

        case ICmpInst::ICMP_SLT:
        case ICmpInst::ICMP_ULT:
          if (isImpliedCondOperands(CmpInst::getSwappedPredicate(Pred), RHS,
                                    LHS, V, getConstant(Min), CtxI))
            return true;
          break;

        default:
          // No change
          break;
      }
    }
  }

  // Check whether the actual condition is beyond sufficient.
  if (FoundPred == ICmpInst::ICMP_EQ)
    if (ICmpInst::isTrueWhenEqual(Pred))
      if (isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI))
        return true;
  if (Pred == ICmpInst::ICMP_NE)
    if (!ICmpInst::isTrueWhenEqual(FoundPred))
      if (isImpliedCondOperands(FoundPred, LHS, RHS, FoundLHS, FoundRHS, CtxI))
        return true;

  // Otherwise assume the worst.
  return false;
}

bool ScalarEvolution::splitBinaryAdd(const SCEV *Expr,
                                     const SCEV *&L, const SCEV *&R,
                                     SCEV::NoWrapFlags &Flags) {
  const auto *AE = dyn_cast<SCEVAddExpr>(Expr);
  if (!AE || AE->getNumOperands() != 2)
    return false;

  L = AE->getOperand(0);
  R = AE->getOperand(1);
  Flags = AE->getNoWrapFlags();
  return true;
}

std::optional<APInt>
ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) {
  // We avoid subtracting expressions here because this function is usually
  // fairly deep in the call stack (i.e. is called many times).

  // X - X = 0.
  if (More == Less)
    return APInt(getTypeSizeInBits(More->getType()), 0);

  if (isa<SCEVAddRecExpr>(Less) && isa<SCEVAddRecExpr>(More)) {
    const auto *LAR = cast<SCEVAddRecExpr>(Less);
    const auto *MAR = cast<SCEVAddRecExpr>(More);

    if (LAR->getLoop() != MAR->getLoop())
      return std::nullopt;

    // We look at affine expressions only; not for correctness but to keep
    // getStepRecurrence cheap.
    if (!LAR->isAffine() || !MAR->isAffine())
      return std::nullopt;

    if (LAR->getStepRecurrence(*this) != MAR->getStepRecurrence(*this))
      return std::nullopt;

    Less = LAR->getStart();
    More = MAR->getStart();

    // fall through
  }

  if (isa<SCEVConstant>(Less) && isa<SCEVConstant>(More)) {
    const auto &M = cast<SCEVConstant>(More)->getAPInt();
    const auto &L = cast<SCEVConstant>(Less)->getAPInt();
    return M - L;
  }

  SCEV::NoWrapFlags Flags;
  const SCEV *LLess = nullptr, *RLess = nullptr;
  const SCEV *LMore = nullptr, *RMore = nullptr;
  const SCEVConstant *C1 = nullptr, *C2 = nullptr;
  // Compare (X + C1) vs X.
  if (splitBinaryAdd(Less, LLess, RLess, Flags))
    if ((C1 = dyn_cast<SCEVConstant>(LLess)))
      if (RLess == More)
        return -(C1->getAPInt());

  // Compare X vs (X + C2).
  if (splitBinaryAdd(More, LMore, RMore, Flags))
    if ((C2 = dyn_cast<SCEVConstant>(LMore)))
      if (RMore == Less)
        return C2->getAPInt();

  // Compare (X + C1) vs (X + C2).
  if (C1 && C2 && RLess == RMore)
    return C2->getAPInt() - C1->getAPInt();

  return std::nullopt;
}

bool ScalarEvolution::isImpliedCondOperandsViaAddRecStart(
    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
    const SCEV *FoundLHS, const SCEV *FoundRHS, const Instruction *CtxI) {
  // Try to recognize the following pattern:
  //
  //   FoundRHS = ...
  // ...
  // loop:
  //   FoundLHS = {Start,+,W}
  // context_bb: // Basic block from the same loop
  //   known(Pred, FoundLHS, FoundRHS)
  //
  // If some predicate is known in the context of a loop, it is also known on
  // each iteration of this loop, including the first iteration. Therefore, in
  // this case, `FoundLHS Pred FoundRHS` implies `Start Pred FoundRHS`. Try to
  // prove the original pred using this fact.
  if (!CtxI)
    return false;
  const BasicBlock *ContextBB = CtxI->getParent();
  // Make sure AR varies in the context block.
  if (auto *AR = dyn_cast<SCEVAddRecExpr>(FoundLHS)) {
    const Loop *L = AR->getLoop();
    // Make sure that context belongs to the loop and executes on 1st iteration
    // (if it ever executes at all).
    if (!L->contains(ContextBB) || !DT.dominates(ContextBB, L->getLoopLatch()))
      return false;
    if (!isAvailableAtLoopEntry(FoundRHS, AR->getLoop()))
      return false;
    return isImpliedCondOperands(Pred, LHS, RHS, AR->getStart(), FoundRHS);
  }

  if (auto *AR = dyn_cast<SCEVAddRecExpr>(FoundRHS)) {
    const Loop *L = AR->getLoop();
    // Make sure that context belongs to the loop and executes on 1st iteration
    // (if it ever executes at all).
    if (!L->contains(ContextBB) || !DT.dominates(ContextBB, L->getLoopLatch()))
      return false;
    if (!isAvailableAtLoopEntry(FoundLHS, AR->getLoop()))
      return false;
    return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, AR->getStart());
  }

  return false;
}

bool ScalarEvolution::isImpliedCondOperandsViaNoOverflow(
    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
    const SCEV *FoundLHS, const SCEV *FoundRHS) {
  if (Pred != CmpInst::ICMP_SLT && Pred != CmpInst::ICMP_ULT)
    return false;

  const auto *AddRecLHS = dyn_cast<SCEVAddRecExpr>(LHS);
  if (!AddRecLHS)
    return false;

  const auto *AddRecFoundLHS = dyn_cast<SCEVAddRecExpr>(FoundLHS);
  if (!AddRecFoundLHS)
    return false;

  // We'd like to let SCEV reason about control dependencies, so we constrain
  // both the inequalities to be about add recurrences on the same loop.  This
  // way we can use isLoopEntryGuardedByCond later.

  const Loop *L = AddRecFoundLHS->getLoop();
  if (L != AddRecLHS->getLoop())
    return false;

  //  FoundLHS u< FoundRHS u< -C =>  (FoundLHS + C) u< (FoundRHS + C) ... (1)
  //
  //  FoundLHS s< FoundRHS s< INT_MIN - C => (FoundLHS + C) s< (FoundRHS + C)
  //                                                                  ... (2)
  //
  // Informal proof for (2), assuming (1) [*]:
  //
  // We'll also assume (A s< B) <=> ((A + INT_MIN) u< (B + INT_MIN)) ... (3)[**]
  //
  // Then
  //
  //       FoundLHS s< FoundRHS s< INT_MIN - C
  // <=>  (FoundLHS + INT_MIN) u< (FoundRHS + INT_MIN) u< -C   [ using (3) ]
  // <=>  (FoundLHS + INT_MIN + C) u< (FoundRHS + INT_MIN + C) [ using (1) ]
  // <=>  (FoundLHS + INT_MIN + C + INT_MIN) s<
  //                        (FoundRHS + INT_MIN + C + INT_MIN) [ using (3) ]
  // <=>  FoundLHS + C s< FoundRHS + C
  //
  // [*]: (1) can be proved by ruling out overflow.
  //
  // [**]: This can be proved by analyzing all the four possibilities:
  //    (A s< 0, B s< 0), (A s< 0, B s>= 0), (A s>= 0, B s< 0) and
  //    (A s>= 0, B s>= 0).
  //
  // Note:
  // Despite (2), "FoundRHS s< INT_MIN - C" does not mean that "FoundRHS + C"
  // will not sign underflow.  For instance, say FoundLHS = (i8 -128), FoundRHS
  // = (i8 -127) and C = (i8 -100).  Then INT_MIN - C = (i8 -28), and FoundRHS
  // s< (INT_MIN - C).  Lack of sign overflow / underflow in "FoundRHS + C" is
  // neither necessary nor sufficient to prove "(FoundLHS + C) s< (FoundRHS +
  // C)".

  std::optional<APInt> LDiff = computeConstantDifference(LHS, FoundLHS);
  std::optional<APInt> RDiff = computeConstantDifference(RHS, FoundRHS);
  if (!LDiff || !RDiff || *LDiff != *RDiff)
    return false;

  if (LDiff->isMinValue())
    return true;

  APInt FoundRHSLimit;

  if (Pred == CmpInst::ICMP_ULT) {
    FoundRHSLimit = -(*RDiff);
  } else {
    assert(Pred == CmpInst::ICMP_SLT && "Checked above!");
    FoundRHSLimit = APInt::getSignedMinValue(getTypeSizeInBits(RHS->getType())) - *RDiff;
  }

  // Try to prove (1) or (2), as needed.
  return isAvailableAtLoopEntry(FoundRHS, L) &&
         isLoopEntryGuardedByCond(L, Pred, FoundRHS,
                                  getConstant(FoundRHSLimit));
}

bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
                                        const SCEV *LHS, const SCEV *RHS,
                                        const SCEV *FoundLHS,
                                        const SCEV *FoundRHS, unsigned Depth) {
  const PHINode *LPhi = nullptr, *RPhi = nullptr;

  auto ClearOnExit = make_scope_exit([&]() {
    if (LPhi) {
      bool Erased = PendingMerges.erase(LPhi);
      assert(Erased && "Failed to erase LPhi!");
      (void)Erased;
    }
    if (RPhi) {
      bool Erased = PendingMerges.erase(RPhi);
      assert(Erased && "Failed to erase RPhi!");
      (void)Erased;
    }
  });

  // Find respective Phis and check that they are not being pending.
  if (const SCEVUnknown *LU = dyn_cast<SCEVUnknown>(LHS))
    if (auto *Phi = dyn_cast<PHINode>(LU->getValue())) {
      if (!PendingMerges.insert(Phi).second)
        return false;
      LPhi = Phi;
    }
  if (const SCEVUnknown *RU = dyn_cast<SCEVUnknown>(RHS))
    if (auto *Phi = dyn_cast<PHINode>(RU->getValue())) {
      // If we detect a loop of Phi nodes being processed by this method, for
      // example:
      //
      //   %a = phi i32 [ %some1, %preheader ], [ %b, %latch ]
      //   %b = phi i32 [ %some2, %preheader ], [ %a, %latch ]
      //
      // we don't want to deal with a case that complex, so return conservative
      // answer false.
      if (!PendingMerges.insert(Phi).second)
        return false;
      RPhi = Phi;
    }

  // If none of LHS, RHS is a Phi, nothing to do here.
  if (!LPhi && !RPhi)
    return false;

  // If there is a SCEVUnknown Phi we are interested in, make it left.
  if (!LPhi) {
    std::swap(LHS, RHS);
    std::swap(FoundLHS, FoundRHS);
    std::swap(LPhi, RPhi);
    Pred = ICmpInst::getSwappedPredicate(Pred);
  }

  assert(LPhi && "LPhi should definitely be a SCEVUnknown Phi!");
  const BasicBlock *LBB = LPhi->getParent();
  const SCEVAddRecExpr *RAR = dyn_cast<SCEVAddRecExpr>(RHS);

  auto ProvedEasily = [&](const SCEV *S1, const SCEV *S2) {
    return isKnownViaNonRecursiveReasoning(Pred, S1, S2) ||
           isImpliedCondOperandsViaRanges(Pred, S1, S2, FoundLHS, FoundRHS) ||
           isImpliedViaOperations(Pred, S1, S2, FoundLHS, FoundRHS, Depth);
  };

  if (RPhi && RPhi->getParent() == LBB) {
    // Case one: RHS is also a SCEVUnknown Phi from the same basic block.
    // If we compare two Phis from the same block, and for each entry block
    // the predicate is true for incoming values from this block, then the
    // predicate is also true for the Phis.
    for (const BasicBlock *IncBB : predecessors(LBB)) {
      const SCEV *L = getSCEV(LPhi->getIncomingValueForBlock(IncBB));
      const SCEV *R = getSCEV(RPhi->getIncomingValueForBlock(IncBB));
      if (!ProvedEasily(L, R))
        return false;
    }
  } else if (RAR && RAR->getLoop()->getHeader() == LBB) {
    // Case two: RHS is also a Phi from the same basic block, and it is an
    // AddRec. It means that there is a loop which has both AddRec and Unknown
    // PHIs, for it we can compare incoming values of AddRec from above the loop
    // and latch with their respective incoming values of LPhi.
    // TODO: Generalize to handle loops with many inputs in a header.
    if (LPhi->getNumIncomingValues() != 2) return false;

    auto *RLoop = RAR->getLoop();
    auto *Predecessor = RLoop->getLoopPredecessor();
    assert(Predecessor && "Loop with AddRec with no predecessor?");
    const SCEV *L1 = getSCEV(LPhi->getIncomingValueForBlock(Predecessor));
    if (!ProvedEasily(L1, RAR->getStart()))
      return false;
    auto *Latch = RLoop->getLoopLatch();
    assert(Latch && "Loop with AddRec with no latch?");
    const SCEV *L2 = getSCEV(LPhi->getIncomingValueForBlock(Latch));
    if (!ProvedEasily(L2, RAR->getPostIncExpr(*this)))
      return false;
  } else {
    // In all other cases go over inputs of LHS and compare each of them to RHS,
    // the predicate is true for (LHS, RHS) if it is true for all such pairs.
    // At this point RHS is either a non-Phi, or it is a Phi from some block
    // different from LBB.
    for (const BasicBlock *IncBB : predecessors(LBB)) {
      // Check that RHS is available in this block.
      if (!dominates(RHS, IncBB))
        return false;
      const SCEV *L = getSCEV(LPhi->getIncomingValueForBlock(IncBB));
      // Make sure L does not refer to a value from a potentially previous
      // iteration of a loop.
      if (!properlyDominates(L, LBB))
        return false;
      if (!ProvedEasily(L, RHS))
        return false;
    }
  }
  return true;
}

bool ScalarEvolution::isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred,
                                                    const SCEV *LHS,
                                                    const SCEV *RHS,
                                                    const SCEV *FoundLHS,
                                                    const SCEV *FoundRHS) {
  // We want to imply LHS < RHS from LHS < (RHS >> shiftvalue).  First, make
  // sure that we are dealing with same LHS.
  if (RHS == FoundRHS) {
    std::swap(LHS, RHS);
    std::swap(FoundLHS, FoundRHS);
    Pred = ICmpInst::getSwappedPredicate(Pred);
  }
  if (LHS != FoundLHS)
    return false;

  auto *SUFoundRHS = dyn_cast<SCEVUnknown>(FoundRHS);
  if (!SUFoundRHS)
    return false;

  Value *Shiftee, *ShiftValue;

  using namespace PatternMatch;
  if (match(SUFoundRHS->getValue(),
            m_LShr(m_Value(Shiftee), m_Value(ShiftValue)))) {
    auto *ShifteeS = getSCEV(Shiftee);
    // Prove one of the following:
    // LHS <u (shiftee >> shiftvalue) && shiftee <=u RHS ---> LHS <u RHS
    // LHS <=u (shiftee >> shiftvalue) && shiftee <=u RHS ---> LHS <=u RHS
    // LHS <s (shiftee >> shiftvalue) && shiftee <=s RHS && shiftee >=s 0
    //   ---> LHS <s RHS
    // LHS <=s (shiftee >> shiftvalue) && shiftee <=s RHS && shiftee >=s 0
    //   ---> LHS <=s RHS
    if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE)
      return isKnownPredicate(ICmpInst::ICMP_ULE, ShifteeS, RHS);
    if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE)
      if (isKnownNonNegative(ShifteeS))
        return isKnownPredicate(ICmpInst::ICMP_SLE, ShifteeS, RHS);
  }

  return false;
}

bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred,
                                            const SCEV *LHS, const SCEV *RHS,
                                            const SCEV *FoundLHS,
                                            const SCEV *FoundRHS,
                                            const Instruction *CtxI) {
  if (isImpliedCondOperandsViaRanges(Pred, LHS, RHS, FoundLHS, FoundRHS))
    return true;

  if (isImpliedCondOperandsViaNoOverflow(Pred, LHS, RHS, FoundLHS, FoundRHS))
    return true;

  if (isImpliedCondOperandsViaShift(Pred, LHS, RHS, FoundLHS, FoundRHS))
    return true;

  if (isImpliedCondOperandsViaAddRecStart(Pred, LHS, RHS, FoundLHS, FoundRHS,
                                          CtxI))
    return true;

  return isImpliedCondOperandsHelper(Pred, LHS, RHS,
                                     FoundLHS, FoundRHS);
}

/// Is MaybeMinMaxExpr an (U|S)(Min|Max) of Candidate and some other values?
template <typename MinMaxExprType>
static bool IsMinMaxConsistingOf(const SCEV *MaybeMinMaxExpr,
                                 const SCEV *Candidate) {
  const MinMaxExprType *MinMaxExpr = dyn_cast<MinMaxExprType>(MaybeMinMaxExpr);
  if (!MinMaxExpr)
    return false;

  return is_contained(MinMaxExpr->operands(), Candidate);
}

static bool IsKnownPredicateViaAddRecStart(ScalarEvolution &SE,
                                           ICmpInst::Predicate Pred,
                                           const SCEV *LHS, const SCEV *RHS) {
  // If both sides are affine addrecs for the same loop, with equal
  // steps, and we know the recurrences don't wrap, then we only
  // need to check the predicate on the starting values.

  if (!ICmpInst::isRelational(Pred))
    return false;

  const SCEVAddRecExpr *LAR = dyn_cast<SCEVAddRecExpr>(LHS);
  if (!LAR)
    return false;
  const SCEVAddRecExpr *RAR = dyn_cast<SCEVAddRecExpr>(RHS);
  if (!RAR)
    return false;
  if (LAR->getLoop() != RAR->getLoop())
    return false;
  if (!LAR->isAffine() || !RAR->isAffine())
    return false;

  if (LAR->getStepRecurrence(SE) != RAR->getStepRecurrence(SE))
    return false;

  SCEV::NoWrapFlags NW = ICmpInst::isSigned(Pred) ?
                         SCEV::FlagNSW : SCEV::FlagNUW;
  if (!LAR->getNoWrapFlags(NW) || !RAR->getNoWrapFlags(NW))
    return false;

  return SE.isKnownPredicate(Pred, LAR->getStart(), RAR->getStart());
}

/// Is LHS `Pred` RHS true on the virtue of LHS or RHS being a Min or Max
/// expression?
static bool IsKnownPredicateViaMinOrMax(ScalarEvolution &SE,
                                        ICmpInst::Predicate Pred,
                                        const SCEV *LHS, const SCEV *RHS) {
  switch (Pred) {
  default:
    return false;

  case ICmpInst::ICMP_SGE:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_SLE:
    return
        // min(A, ...) <= A
        IsMinMaxConsistingOf<SCEVSMinExpr>(LHS, RHS) ||
        // A <= max(A, ...)
        IsMinMaxConsistingOf<SCEVSMaxExpr>(RHS, LHS);

  case ICmpInst::ICMP_UGE:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_ULE:
    return
        // min(A, ...) <= A
        // FIXME: what about umin_seq?
        IsMinMaxConsistingOf<SCEVUMinExpr>(LHS, RHS) ||
        // A <= max(A, ...)
        IsMinMaxConsistingOf<SCEVUMaxExpr>(RHS, LHS);
  }

  llvm_unreachable("covered switch fell through?!");
}

bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
                                             const SCEV *LHS, const SCEV *RHS,
                                             const SCEV *FoundLHS,
                                             const SCEV *FoundRHS,
                                             unsigned Depth) {
  assert(getTypeSizeInBits(LHS->getType()) ==
             getTypeSizeInBits(RHS->getType()) &&
         "LHS and RHS have different sizes?");
  assert(getTypeSizeInBits(FoundLHS->getType()) ==
             getTypeSizeInBits(FoundRHS->getType()) &&
         "FoundLHS and FoundRHS have different sizes?");
  // We want to avoid hurting the compile time with analysis of too big trees.
  if (Depth > MaxSCEVOperationsImplicationDepth)
    return false;

  // We only want to work with GT comparison so far.
  if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_SLT) {
    Pred = CmpInst::getSwappedPredicate(Pred);
    std::swap(LHS, RHS);
    std::swap(FoundLHS, FoundRHS);
  }

  // For unsigned, try to reduce it to corresponding signed comparison.
  if (Pred == ICmpInst::ICMP_UGT)
    // We can replace unsigned predicate with its signed counterpart if all
    // involved values are non-negative.
    // TODO: We could have better support for unsigned.
    if (isKnownNonNegative(FoundLHS) && isKnownNonNegative(FoundRHS)) {
      // Knowing that both FoundLHS and FoundRHS are non-negative, and knowing
      // FoundLHS >u FoundRHS, we also know that FoundLHS >s FoundRHS. Let us
      // use this fact to prove that LHS and RHS are non-negative.
      const SCEV *MinusOne = getMinusOne(LHS->getType());
      if (isImpliedCondOperands(ICmpInst::ICMP_SGT, LHS, MinusOne, FoundLHS,
                                FoundRHS) &&
          isImpliedCondOperands(ICmpInst::ICMP_SGT, RHS, MinusOne, FoundLHS,
                                FoundRHS))
        Pred = ICmpInst::ICMP_SGT;
    }

  if (Pred != ICmpInst::ICMP_SGT)
    return false;

  auto GetOpFromSExt = [&](const SCEV *S) {
    if (auto *Ext = dyn_cast<SCEVSignExtendExpr>(S))
      return Ext->getOperand();
    // TODO: If S is a SCEVConstant then you can cheaply "strip" the sext off
    // the constant in some cases.
    return S;
  };

  // Acquire values from extensions.
  auto *OrigLHS = LHS;
  auto *OrigFoundLHS = FoundLHS;
  LHS = GetOpFromSExt(LHS);
  FoundLHS = GetOpFromSExt(FoundLHS);

  // Is the SGT predicate can be proved trivially or using the found context.
  auto IsSGTViaContext = [&](const SCEV *S1, const SCEV *S2) {
    return isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_SGT, S1, S2) ||
           isImpliedViaOperations(ICmpInst::ICMP_SGT, S1, S2, OrigFoundLHS,
                                  FoundRHS, Depth + 1);
  };

  if (auto *LHSAddExpr = dyn_cast<SCEVAddExpr>(LHS)) {
    // We want to avoid creation of any new non-constant SCEV. Since we are
    // going to compare the operands to RHS, we should be certain that we don't
    // need any size extensions for this. So let's decline all cases when the
    // sizes of types of LHS and RHS do not match.
    // TODO: Maybe try to get RHS from sext to catch more cases?
    if (getTypeSizeInBits(LHS->getType()) != getTypeSizeInBits(RHS->getType()))
      return false;

    // Should not overflow.
    if (!LHSAddExpr->hasNoSignedWrap())
      return false;

    auto *LL = LHSAddExpr->getOperand(0);
    auto *LR = LHSAddExpr->getOperand(1);
    auto *MinusOne = getMinusOne(RHS->getType());

    // Checks that S1 >= 0 && S2 > RHS, trivially or using the found context.
    auto IsSumGreaterThanRHS = [&](const SCEV *S1, const SCEV *S2) {
      return IsSGTViaContext(S1, MinusOne) && IsSGTViaContext(S2, RHS);
    };
    // Try to prove the following rule:
    // (LHS = LL + LR) && (LL >= 0) && (LR > RHS) => (LHS > RHS).
    // (LHS = LL + LR) && (LR >= 0) && (LL > RHS) => (LHS > RHS).
    if (IsSumGreaterThanRHS(LL, LR) || IsSumGreaterThanRHS(LR, LL))
      return true;
  } else if (auto *LHSUnknownExpr = dyn_cast<SCEVUnknown>(LHS)) {
    Value *LL, *LR;
    // FIXME: Once we have SDiv implemented, we can get rid of this matching.

    using namespace llvm::PatternMatch;

    if (match(LHSUnknownExpr->getValue(), m_SDiv(m_Value(LL), m_Value(LR)))) {
      // Rules for division.
      // We are going to perform some comparisons with Denominator and its
      // derivative expressions. In general case, creating a SCEV for it may
      // lead to a complex analysis of the entire graph, and in particular it
      // can request trip count recalculation for the same loop. This would
      // cache as SCEVCouldNotCompute to avoid the infinite recursion. To avoid
      // this, we only want to create SCEVs that are constants in this section.
      // So we bail if Denominator is not a constant.
      if (!isa<ConstantInt>(LR))
        return false;

      auto *Denominator = cast<SCEVConstant>(getSCEV(LR));

      // We want to make sure that LHS = FoundLHS / Denominator. If it is so,
      // then a SCEV for the numerator already exists and matches with FoundLHS.
      auto *Numerator = getExistingSCEV(LL);
      if (!Numerator || Numerator->getType() != FoundLHS->getType())
        return false;

      // Make sure that the numerator matches with FoundLHS and the denominator
      // is positive.
      if (!HasSameValue(Numerator, FoundLHS) || !isKnownPositive(Denominator))
        return false;

      auto *DTy = Denominator->getType();
      auto *FRHSTy = FoundRHS->getType();
      if (DTy->isPointerTy() != FRHSTy->isPointerTy())
        // One of types is a pointer and another one is not. We cannot extend
        // them properly to a wider type, so let us just reject this case.
        // TODO: Usage of getEffectiveSCEVType for DTy, FRHSTy etc should help
        // to avoid this check.
        return false;

      // Given that:
      // FoundLHS > FoundRHS, LHS = FoundLHS / Denominator, Denominator > 0.
      auto *WTy = getWiderType(DTy, FRHSTy);
      auto *DenominatorExt = getNoopOrSignExtend(Denominator, WTy);
      auto *FoundRHSExt = getNoopOrSignExtend(FoundRHS, WTy);

      // Try to prove the following rule:
      // (FoundRHS > Denominator - 2) && (RHS <= 0) => (LHS > RHS).
      // For example, given that FoundLHS > 2. It means that FoundLHS is at
      // least 3. If we divide it by Denominator < 4, we will have at least 1.
      auto *DenomMinusTwo = getMinusSCEV(DenominatorExt, getConstant(WTy, 2));
      if (isKnownNonPositive(RHS) &&
          IsSGTViaContext(FoundRHSExt, DenomMinusTwo))
        return true;

      // Try to prove the following rule:
      // (FoundRHS > -1 - Denominator) && (RHS < 0) => (LHS > RHS).
      // For example, given that FoundLHS > -3. Then FoundLHS is at least -2.
      // If we divide it by Denominator > 2, then:
      // 1. If FoundLHS is negative, then the result is 0.
      // 2. If FoundLHS is non-negative, then the result is non-negative.
      // Anyways, the result is non-negative.
      auto *MinusOne = getMinusOne(WTy);
      auto *NegDenomMinusOne = getMinusSCEV(MinusOne, DenominatorExt);
      if (isKnownNegative(RHS) &&
          IsSGTViaContext(FoundRHSExt, NegDenomMinusOne))
        return true;
    }
  }

  // If our expression contained SCEVUnknown Phis, and we split it down and now
  // need to prove something for them, try to prove the predicate for every
  // possible incoming values of those Phis.
  if (isImpliedViaMerge(Pred, OrigLHS, RHS, OrigFoundLHS, FoundRHS, Depth + 1))
    return true;

  return false;
}

static bool isKnownPredicateExtendIdiom(ICmpInst::Predicate Pred,
                                        const SCEV *LHS, const SCEV *RHS) {
  // zext x u<= sext x, sext x s<= zext x
  switch (Pred) {
  case ICmpInst::ICMP_SGE:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_SLE: {
    // If operand >=s 0 then ZExt == SExt.  If operand <s 0 then SExt <s ZExt.
    const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(LHS);
    const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(RHS);
    if (SExt && ZExt && SExt->getOperand() == ZExt->getOperand())
      return true;
    break;
  }
  case ICmpInst::ICMP_UGE:
    std::swap(LHS, RHS);
    [[fallthrough]];
  case ICmpInst::ICMP_ULE: {
    // If operand >=s 0 then ZExt == SExt.  If operand <s 0 then ZExt <u SExt.
    const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(LHS);
    const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(RHS);
    if (SExt && ZExt && SExt->getOperand() == ZExt->getOperand())
      return true;
    break;
  }
  default:
    break;
  };
  return false;
}

bool
ScalarEvolution::isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred,
                                           const SCEV *LHS, const SCEV *RHS) {
  return isKnownPredicateExtendIdiom(Pred, LHS, RHS) ||
         isKnownPredicateViaConstantRanges(Pred, LHS, RHS) ||
         IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
         IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS) ||
         isKnownPredicateViaNoOverflow(Pred, LHS, RHS);
}

bool
ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
                                             const SCEV *LHS, const SCEV *RHS,
                                             const SCEV *FoundLHS,
                                             const SCEV *FoundRHS) {
  switch (Pred) {
  default: llvm_unreachable("Unexpected ICmpInst::Predicate value!");
  case ICmpInst::ICMP_EQ:
  case ICmpInst::ICMP_NE:
    if (HasSameValue(LHS, FoundLHS) && HasSameValue(RHS, FoundRHS))
      return true;
    break;
  case ICmpInst::ICMP_SLT:
  case ICmpInst::ICMP_SLE:
    if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_SLE, LHS, FoundLHS) &&
        isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_SGE, RHS, FoundRHS))
      return true;
    break;
  case ICmpInst::ICMP_SGT:
  case ICmpInst::ICMP_SGE:
    if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_SGE, LHS, FoundLHS) &&
        isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_SLE, RHS, FoundRHS))
      return true;
    break;
  case ICmpInst::ICMP_ULT:
  case ICmpInst::ICMP_ULE:
    if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, LHS, FoundLHS) &&
        isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_UGE, RHS, FoundRHS))
      return true;
    break;
  case ICmpInst::ICMP_UGT:
  case ICmpInst::ICMP_UGE:
    if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_UGE, LHS, FoundLHS) &&
        isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, RHS, FoundRHS))
      return true;
    break;
  }

  // Maybe it can be proved via operations?
  if (isImpliedViaOperations(Pred, LHS, RHS, FoundLHS, FoundRHS))
    return true;

  return false;
}

bool ScalarEvolution::isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
                                                     const SCEV *LHS,
                                                     const SCEV *RHS,
                                                     const SCEV *FoundLHS,
                                                     const SCEV *FoundRHS) {
  if (!isa<SCEVConstant>(RHS) || !isa<SCEVConstant>(FoundRHS))
    // The restriction on `FoundRHS` be lifted easily -- it exists only to
    // reduce the compile time impact of this optimization.
    return false;

  std::optional<APInt> Addend = computeConstantDifference(LHS, FoundLHS);
  if (!Addend)
    return false;

  const APInt &ConstFoundRHS = cast<SCEVConstant>(FoundRHS)->getAPInt();

  // `FoundLHSRange` is the range we know `FoundLHS` to be in by virtue of the
  // antecedent "`FoundLHS` `Pred` `FoundRHS`".
  ConstantRange FoundLHSRange =
      ConstantRange::makeExactICmpRegion(Pred, ConstFoundRHS);

  // Since `LHS` is `FoundLHS` + `Addend`, we can compute a range for `LHS`:
  ConstantRange LHSRange = FoundLHSRange.add(ConstantRange(*Addend));

  // We can also compute the range of values for `LHS` that satisfy the
  // consequent, "`LHS` `Pred` `RHS`":
  const APInt &ConstRHS = cast<SCEVConstant>(RHS)->getAPInt();
  // The antecedent implies the consequent if every value of `LHS` that
  // satisfies the antecedent also satisfies the consequent.
  return LHSRange.icmp(Pred, ConstRHS);
}

bool ScalarEvolution::canIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride,
                                        bool IsSigned) {
  assert(isKnownPositive(Stride) && "Positive stride expected!");

  unsigned BitWidth = getTypeSizeInBits(RHS->getType());
  const SCEV *One = getOne(Stride->getType());

  if (IsSigned) {
    APInt MaxRHS = getSignedRangeMax(RHS);
    APInt MaxValue = APInt::getSignedMaxValue(BitWidth);
    APInt MaxStrideMinusOne = getSignedRangeMax(getMinusSCEV(Stride, One));

    // SMaxRHS + SMaxStrideMinusOne > SMaxValue => overflow!
    return (std::move(MaxValue) - MaxStrideMinusOne).slt(MaxRHS);
  }

  APInt MaxRHS = getUnsignedRangeMax(RHS);
  APInt MaxValue = APInt::getMaxValue(BitWidth);
  APInt MaxStrideMinusOne = getUnsignedRangeMax(getMinusSCEV(Stride, One));

  // UMaxRHS + UMaxStrideMinusOne > UMaxValue => overflow!
  return (std::move(MaxValue) - MaxStrideMinusOne).ult(MaxRHS);
}

bool ScalarEvolution::canIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride,
                                        bool IsSigned) {
  
  unsigned BitWidth = getTypeSizeInBits(RHS->getType());
  const SCEV *One = getOne(Stride->getType());

  if (IsSigned) {
    APInt MinRHS = getSignedRangeMin(RHS);
    APInt MinValue = APInt::getSignedMinValue(BitWidth);
    APInt MaxStrideMinusOne = getSignedRangeMax(getMinusSCEV(Stride, One));

    // SMinRHS - SMaxStrideMinusOne < SMinValue => overflow!
    return (std::move(MinValue) + MaxStrideMinusOne).sgt(MinRHS);
  }

  APInt MinRHS = getUnsignedRangeMin(RHS);
  APInt MinValue = APInt::getMinValue(BitWidth);
  APInt MaxStrideMinusOne = getUnsignedRangeMax(getMinusSCEV(Stride, One));

  // UMinRHS - UMaxStrideMinusOne < UMinValue => overflow!
  return (std::move(MinValue) + MaxStrideMinusOne).ugt(MinRHS);
}

const SCEV *ScalarEvolution::getUDivCeilSCEV(const SCEV *N, const SCEV *D) {
  // umin(N, 1) + floor((N - umin(N, 1)) / D)
  // This is equivalent to "1 + floor((N - 1) / D)" for N != 0. The umin
  // expression fixes the case of N=0.
  const SCEV *MinNOne = getUMinExpr(N, getOne(N->getType()));
  const SCEV *NMinusOne = getMinusSCEV(N, MinNOne);
  return getAddExpr(MinNOne, getUDivExpr(NMinusOne, D));
}

const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start,
                                                    const SCEV *Stride,
                                                    const SCEV *End,
                                                    unsigned BitWidth,
                                                    bool IsSigned) {
  // The logic in this function assumes we can represent a positive stride.
  // If we can't, the backedge-taken count must be zero.
  if (IsSigned && BitWidth == 1)
    return getZero(Stride->getType());

  // This code below only been closely audited for negative strides in the
  // unsigned comparison case, it may be correct for signed comparison, but
  // that needs to be established.
  if (IsSigned && isKnownNegative(Stride))
    return getCouldNotCompute();

  // Calculate the maximum backedge count based on the range of values
  // permitted by Start, End, and Stride.
  APInt MinStart =
      IsSigned ? getSignedRangeMin(Start) : getUnsignedRangeMin(Start);

  APInt MinStride =
      IsSigned ? getSignedRangeMin(Stride) : getUnsignedRangeMin(Stride);

  // We assume either the stride is positive, or the backedge-taken count
  // is zero. So force StrideForMaxBECount to be at least one.
  APInt One(BitWidth, 1);
  APInt StrideForMaxBECount = IsSigned ? APIntOps::smax(One, MinStride)
                                       : APIntOps::umax(One, MinStride);

  APInt MaxValue = IsSigned ? APInt::getSignedMaxValue(BitWidth)
                            : APInt::getMaxValue(BitWidth);
  APInt Limit = MaxValue - (StrideForMaxBECount - 1);

  // Although End can be a MAX expression we estimate MaxEnd considering only
  // the case End = RHS of the loop termination condition. This is safe because
  // in the other case (End - Start) is zero, leading to a zero maximum backedge
  // taken count.
  APInt MaxEnd = IsSigned ? APIntOps::smin(getSignedRangeMax(End), Limit)
                          : APIntOps::umin(getUnsignedRangeMax(End), Limit);

  // MaxBECount = ceil((max(MaxEnd, MinStart) - MinStart) / Stride)
  MaxEnd = IsSigned ? APIntOps::smax(MaxEnd, MinStart)
                    : APIntOps::umax(MaxEnd, MinStart);

  return getUDivCeilSCEV(getConstant(MaxEnd - MinStart) /* Delta */,
                         getConstant(StrideForMaxBECount) /* Step */);
}

ScalarEvolution::ExitLimit
ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
                                  const Loop *L, bool IsSigned,
                                  bool ControlsOnlyExit, bool AllowPredicates) {
  SmallPtrSet<const SCEVPredicate *, 4> Predicates;

  const SCEVAddRecExpr *IV = dyn_cast<SCEVAddRecExpr>(LHS);
  bool PredicatedIV = false;

  auto canAssumeNoSelfWrap = [&](const SCEVAddRecExpr *AR) {
    // Can we prove this loop *must* be UB if overflow of IV occurs?
    // Reasoning goes as follows:
    // * Suppose the IV did self wrap.
    // * If Stride evenly divides the iteration space, then once wrap
    //   occurs, the loop must revisit the same values.
    // * We know that RHS is invariant, and that none of those values
    //   caused this exit to be taken previously.  Thus, this exit is
    //   dynamically dead.
    // * If this is the sole exit, then a dead exit implies the loop
    //   must be infinite if there are no abnormal exits.
    // * If the loop were infinite, then it must either not be mustprogress
    //   or have side effects. Otherwise, it must be UB.
    // * It can't (by assumption), be UB so we have contradicted our
    //   premise and can conclude the IV did not in fact self-wrap.
    if (!isLoopInvariant(RHS, L))
      return false;

    auto *StrideC = dyn_cast<SCEVConstant>(AR->getStepRecurrence(*this));
    if (!StrideC || !StrideC->getAPInt().isPowerOf2())
      return false;

    if (!ControlsOnlyExit || !loopHasNoAbnormalExits(L))
      return false;

    return loopIsFiniteByAssumption(L);
  };

  if (!IV) {
    if (auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(LHS)) {
      const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(ZExt->getOperand());
      if (AR && AR->getLoop() == L && AR->isAffine()) {
        auto canProveNUW = [&]() {
          if (!isLoopInvariant(RHS, L))
            return false;

          if (!isKnownNonZero(AR->getStepRecurrence(*this)))
            // We need the sequence defined by AR to strictly increase in the
            // unsigned integer domain for the logic below to hold.
            return false;

          const unsigned InnerBitWidth = getTypeSizeInBits(AR->getType());
          const unsigned OuterBitWidth = getTypeSizeInBits(RHS->getType());
          // If RHS <=u Limit, then there must exist a value V in the sequence
          // defined by AR (e.g. {Start,+,Step}) such that V >u RHS, and
          // V <=u UINT_MAX.  Thus, we must exit the loop before unsigned
          // overflow occurs.  This limit also implies that a signed comparison
          // (in the wide bitwidth) is equivalent to an unsigned comparison as
          // the high bits on both sides must be zero.
          APInt StrideMax = getUnsignedRangeMax(AR->getStepRecurrence(*this));
          APInt Limit = APInt::getMaxValue(InnerBitWidth) - (StrideMax - 1);
          Limit = Limit.zext(OuterBitWidth);
          return getUnsignedRangeMax(applyLoopGuards(RHS, L)).ule(Limit);
        };
        auto Flags = AR->getNoWrapFlags();
        if (!hasFlags(Flags, SCEV::FlagNUW) && canProveNUW())
          Flags = setFlags(Flags, SCEV::FlagNUW);

        setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), Flags);
        if (AR->hasNoUnsignedWrap()) {
          // Emulate what getZeroExtendExpr would have done during construction
          // if we'd been able to infer the fact just above at that time.
          const SCEV *Step = AR->getStepRecurrence(*this);
          Type *Ty = ZExt->getType();
          auto *S = getAddRecExpr(
            getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, 0),
            getZeroExtendExpr(Step, Ty, 0), L, AR->getNoWrapFlags());
          IV = dyn_cast<SCEVAddRecExpr>(S);
        }
      }
    }
  }


  if (!IV && AllowPredicates) {
    // Try to make this an AddRec using runtime tests, in the first X
    // iterations of this loop, where X is the SCEV expression found by the
    // algorithm below.
    IV = convertSCEVToAddRecWithPredicates(LHS, L, Predicates);
    PredicatedIV = true;
  }

  // Avoid weird loops
  if (!IV || IV->getLoop() != L || !IV->isAffine())
    return getCouldNotCompute();

  // A precondition of this method is that the condition being analyzed
  // reaches an exiting branch which dominates the latch.  Given that, we can
  // assume that an increment which violates the nowrap specification and
  // produces poison must cause undefined behavior when the resulting poison
  // value is branched upon and thus we can conclude that the backedge is
  // taken no more often than would be required to produce that poison value.
  // Note that a well defined loop can exit on the iteration which violates
  // the nowrap specification if there is another exit (either explicit or
  // implicit/exceptional) which causes the loop to execute before the
  // exiting instruction we're analyzing would trigger UB.
  auto WrapType = IsSigned ? SCEV::FlagNSW : SCEV::FlagNUW;
  bool NoWrap = ControlsOnlyExit && IV->getNoWrapFlags(WrapType);
  ICmpInst::Predicate Cond = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;

  const SCEV *Stride = IV->getStepRecurrence(*this);

  bool PositiveStride = isKnownPositive(Stride);

  // Avoid negative or zero stride values.
  if (!PositiveStride) {
    // We can compute the correct backedge taken count for loops with unknown
    // strides if we can prove that the loop is not an infinite loop with side
    // effects. Here's the loop structure we are trying to handle -
    //
    // i = start
    // do {
    //   A[i] = i;
    //   i += s;
    // } while (i < end);
    //
    // The backedge taken count for such loops is evaluated as -
    // (max(end, start + stride) - start - 1) /u stride
    //
    // The additional preconditions that we need to check to prove correctness
    // of the above formula is as follows -
    //
    // a) IV is either nuw or nsw depending upon signedness (indicated by the
    //    NoWrap flag).
    // b) the loop is guaranteed to be finite (e.g. is mustprogress and has
    //    no side effects within the loop)
    // c) loop has a single static exit (with no abnormal exits)
    //
    // Precondition a) implies that if the stride is negative, this is a single
    // trip loop. The backedge taken count formula reduces to zero in this case.
    //
    // Precondition b) and c) combine to imply that if rhs is invariant in L,
    // then a zero stride means the backedge can't be taken without executing
    // undefined behavior.
    //
    // The positive stride case is the same as isKnownPositive(Stride) returning
    // true (original behavior of the function).
    //
    if (PredicatedIV || !NoWrap || !loopIsFiniteByAssumption(L) ||
        !loopHasNoAbnormalExits(L))
      return getCouldNotCompute();

    if (!isKnownNonZero(Stride)) {
      // If we have a step of zero, and RHS isn't invariant in L, we don't know
      // if it might eventually be greater than start and if so, on which
      // iteration.  We can't even produce a useful upper bound.
      if (!isLoopInvariant(RHS, L))
        return getCouldNotCompute();

      // We allow a potentially zero stride, but we need to divide by stride
      // below.  Since the loop can't be infinite and this check must control
      // the sole exit, we can infer the exit must be taken on the first
      // iteration (e.g. backedge count = 0) if the stride is zero.  Given that,
      // we know the numerator in the divides below must be zero, so we can
      // pick an arbitrary non-zero value for the denominator (e.g. stride)
      // and produce the right result.
      // FIXME: Handle the case where Stride is poison?
      auto wouldZeroStrideBeUB = [&]() {
        // Proof by contradiction.  Suppose the stride were zero.  If we can
        // prove that the backedge *is* taken on the first iteration, then since
        // we know this condition controls the sole exit, we must have an
        // infinite loop.  We can't have a (well defined) infinite loop per
        // check just above.
        // Note: The (Start - Stride) term is used to get the start' term from
        // (start' + stride,+,stride). Remember that we only care about the
        // result of this expression when stride == 0 at runtime.
        auto *StartIfZero = getMinusSCEV(IV->getStart(), Stride);
        return isLoopEntryGuardedByCond(L, Cond, StartIfZero, RHS);
      };
      if (!wouldZeroStrideBeUB()) {
        Stride = getUMaxExpr(Stride, getOne(Stride->getType()));
      }
    }
  } else if (!Stride->isOne() && !NoWrap) {
    auto isUBOnWrap = [&]() {
      // From no-self-wrap, we need to then prove no-(un)signed-wrap.  This
      // follows trivially from the fact that every (un)signed-wrapped, but
      // not self-wrapped value must be LT than the last value before
      // (un)signed wrap.  Since we know that last value didn't exit, nor
      // will any smaller one.
      return canAssumeNoSelfWrap(IV);
    };

    // Avoid proven overflow cases: this will ensure that the backedge taken
    // count will not generate any unsigned overflow. Relaxed no-overflow
    // conditions exploit NoWrapFlags, allowing to optimize in presence of
    // undefined behaviors like the case of C language.
    if (canIVOverflowOnLT(RHS, Stride, IsSigned) && !isUBOnWrap())
      return getCouldNotCompute();
  }

  // On all paths just preceeding, we established the following invariant:
  //   IV can be assumed not to overflow up to and including the exiting
  //   iteration.  We proved this in one of two ways:
  //   1) We can show overflow doesn't occur before the exiting iteration
  //      1a) canIVOverflowOnLT, and b) step of one
  //   2) We can show that if overflow occurs, the loop must execute UB
  //      before any possible exit.
  // Note that we have not yet proved RHS invariant (in general).

  const SCEV *Start = IV->getStart();

  // Preserve pointer-typed Start/RHS to pass to isLoopEntryGuardedByCond.
  // If we convert to integers, isLoopEntryGuardedByCond will miss some cases.
  // Use integer-typed versions for actual computation; we can't subtract
  // pointers in general.
  const SCEV *OrigStart = Start;
  const SCEV *OrigRHS = RHS;
  if (Start->getType()->isPointerTy()) {
    Start = getLosslessPtrToIntExpr(Start);
    if (isa<SCEVCouldNotCompute>(Start))
      return Start;
  }
  if (RHS->getType()->isPointerTy()) {
    RHS = getLosslessPtrToIntExpr(RHS);
    if (isa<SCEVCouldNotCompute>(RHS))
      return RHS;
  }

  // When the RHS is not invariant, we do not know the end bound of the loop and
  // cannot calculate the ExactBECount needed by ExitLimit. However, we can
  // calculate the MaxBECount, given the start, stride and max value for the end
  // bound of the loop (RHS), and the fact that IV does not overflow (which is
  // checked above).
  if (!isLoopInvariant(RHS, L)) {
    const SCEV *MaxBECount = computeMaxBECountForLT(
        Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned);
    return ExitLimit(getCouldNotCompute() /* ExactNotTaken */, MaxBECount,
                     MaxBECount, false /*MaxOrZero*/, Predicates);
  }

  // We use the expression (max(End,Start)-Start)/Stride to describe the
  // backedge count, as if the backedge is taken at least once max(End,Start)
  // is End and so the result is as above, and if not max(End,Start) is Start
  // so we get a backedge count of zero.
  const SCEV *BECount = nullptr;
  auto *OrigStartMinusStride = getMinusSCEV(OrigStart, Stride);
  assert(isAvailableAtLoopEntry(OrigStartMinusStride, L) && "Must be!");
  assert(isAvailableAtLoopEntry(OrigStart, L) && "Must be!");
  assert(isAvailableAtLoopEntry(OrigRHS, L) && "Must be!");
  // Can we prove (max(RHS,Start) > Start - Stride?
  if (isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigStart) &&
      isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigRHS)) {
    // In this case, we can use a refined formula for computing backedge taken
    // count.  The general formula remains:
    //   "End-Start /uceiling Stride" where "End = max(RHS,Start)"
    // We want to use the alternate formula:
    //   "((End - 1) - (Start - Stride)) /u Stride"
    // Let's do a quick case analysis to show these are equivalent under
    // our precondition that max(RHS,Start) > Start - Stride.
    // * For RHS <= Start, the backedge-taken count must be zero.
    //   "((End - 1) - (Start - Stride)) /u Stride" reduces to
    //   "((Start - 1) - (Start - Stride)) /u Stride" which simplies to
    //   "Stride - 1 /u Stride" which is indeed zero for all non-zero values
    //     of Stride.  For 0 stride, we've use umin(1,Stride) above, reducing
    //     this to the stride of 1 case.
    // * For RHS >= Start, the backedge count must be "RHS-Start /uceil Stride".
    //   "((End - 1) - (Start - Stride)) /u Stride" reduces to
    //   "((RHS - 1) - (Start - Stride)) /u Stride" reassociates to
    //   "((RHS - (Start - Stride) - 1) /u Stride".
    //   Our preconditions trivially imply no overflow in that form.
    const SCEV *MinusOne = getMinusOne(Stride->getType());
    const SCEV *Numerator =
        getMinusSCEV(getAddExpr(RHS, MinusOne), getMinusSCEV(Start, Stride));
    BECount = getUDivExpr(Numerator, Stride);
  }

  const SCEV *BECountIfBackedgeTaken = nullptr;
  if (!BECount) {
    auto canProveRHSGreaterThanEqualStart = [&]() {
      auto CondGE = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
      if (isLoopEntryGuardedByCond(L, CondGE, OrigRHS, OrigStart))
        return true;

      // (RHS > Start - 1) implies RHS >= Start.
      // * "RHS >= Start" is trivially equivalent to "RHS > Start - 1" if
      //   "Start - 1" doesn't overflow.
      // * For signed comparison, if Start - 1 does overflow, it's equal
      //   to INT_MAX, and "RHS >s INT_MAX" is trivially false.
      // * For unsigned comparison, if Start - 1 does overflow, it's equal
      //   to UINT_MAX, and "RHS >u UINT_MAX" is trivially false.
      //
      // FIXME: Should isLoopEntryGuardedByCond do this for us?
      auto CondGT = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
      auto *StartMinusOne = getAddExpr(OrigStart,
                                       getMinusOne(OrigStart->getType()));
      return isLoopEntryGuardedByCond(L, CondGT, OrigRHS, StartMinusOne);
    };

    // If we know that RHS >= Start in the context of loop, then we know that
    // max(RHS, Start) = RHS at this point.
    const SCEV *End;
    if (canProveRHSGreaterThanEqualStart()) {
      End = RHS;
    } else {
      // If RHS < Start, the backedge will be taken zero times.  So in
      // general, we can write the backedge-taken count as:
      //
      //     RHS >= Start ? ceil(RHS - Start) / Stride : 0
      //
      // We convert it to the following to make it more convenient for SCEV:
      //
      //     ceil(max(RHS, Start) - Start) / Stride
      End = IsSigned ? getSMaxExpr(RHS, Start) : getUMaxExpr(RHS, Start);

      // See what would happen if we assume the backedge is taken. This is
      // used to compute MaxBECount.
      BECountIfBackedgeTaken = getUDivCeilSCEV(getMinusSCEV(RHS, Start), Stride);
    }

    // At this point, we know:
    //
    // 1. If IsSigned, Start <=s End; otherwise, Start <=u End
    // 2. The index variable doesn't overflow.
    //
    // Therefore, we know N exists such that
    // (Start + Stride * N) >= End, and computing "(Start + Stride * N)"
    // doesn't overflow.
    //
    // Using this information, try to prove whether the addition in
    // "(Start - End) + (Stride - 1)" has unsigned overflow.
    const SCEV *One = getOne(Stride->getType());
    bool MayAddOverflow = [&] {
      if (auto *StrideC = dyn_cast<SCEVConstant>(Stride)) {
        if (StrideC->getAPInt().isPowerOf2()) {
          // Suppose Stride is a power of two, and Start/End are unsigned
          // integers.  Let UMAX be the largest representable unsigned
          // integer.
          //
          // By the preconditions of this function, we know
          // "(Start + Stride * N) >= End", and this doesn't overflow.
          // As a formula:
          //
          //   End <= (Start + Stride * N) <= UMAX
          //
          // Subtracting Start from all the terms:
          //
          //   End - Start <= Stride * N <= UMAX - Start
          //
          // Since Start is unsigned, UMAX - Start <= UMAX.  Therefore:
          //
          //   End - Start <= Stride * N <= UMAX
          //
          // Stride * N is a multiple of Stride. Therefore,
          //
          //   End - Start <= Stride * N <= UMAX - (UMAX mod Stride)
          //
          // Since Stride is a power of two, UMAX + 1 is divisible by Stride.
          // Therefore, UMAX mod Stride == Stride - 1.  So we can write:
          //
          //   End - Start <= Stride * N <= UMAX - Stride - 1
          //
          // Dropping the middle term:
          //
          //   End - Start <= UMAX - Stride - 1
          //
          // Adding Stride - 1 to both sides:
          //
          //   (End - Start) + (Stride - 1) <= UMAX
          //
          // In other words, the addition doesn't have unsigned overflow.
          //
          // A similar proof works if we treat Start/End as signed values.
          // Just rewrite steps before "End - Start <= Stride * N <= UMAX" to
          // use signed max instead of unsigned max. Note that we're trying
          // to prove a lack of unsigned overflow in either case.
          return false;
        }
      }
      if (Start == Stride || Start == getMinusSCEV(Stride, One)) {
        // If Start is equal to Stride, (End - Start) + (Stride - 1) == End - 1.
        // If !IsSigned, 0 <u Stride == Start <=u End; so 0 <u End - 1 <u End.
        // If IsSigned, 0 <s Stride == Start <=s End; so 0 <s End - 1 <s End.
        //
        // If Start is equal to Stride - 1, (End - Start) + Stride - 1 == End.
        return false;
      }
      return true;
    }();

    const SCEV *Delta = getMinusSCEV(End, Start);
    if (!MayAddOverflow) {
      // floor((D + (S - 1)) / S)
      // We prefer this formulation if it's legal because it's fewer operations.
      BECount =
          getUDivExpr(getAddExpr(Delta, getMinusSCEV(Stride, One)), Stride);
    } else {
      BECount = getUDivCeilSCEV(Delta, Stride);
    }
  }

  const SCEV *ConstantMaxBECount;
  bool MaxOrZero = false;
  if (isa<SCEVConstant>(BECount)) {
    ConstantMaxBECount = BECount;
  } else if (BECountIfBackedgeTaken &&
             isa<SCEVConstant>(BECountIfBackedgeTaken)) {
    // If we know exactly how many times the backedge will be taken if it's
    // taken at least once, then the backedge count will either be that or
    // zero.
    ConstantMaxBECount = BECountIfBackedgeTaken;
    MaxOrZero = true;
  } else {
    ConstantMaxBECount = computeMaxBECountForLT(
        Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned);
  }

  if (isa<SCEVCouldNotCompute>(ConstantMaxBECount) &&
      !isa<SCEVCouldNotCompute>(BECount))
    ConstantMaxBECount = getConstant(getUnsignedRangeMax(BECount));

  const SCEV *SymbolicMaxBECount =
      isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;
  return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount, MaxOrZero,
                   Predicates);
}

ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
    const SCEV *LHS, const SCEV *RHS, const Loop *L, bool IsSigned,
    bool ControlsOnlyExit, bool AllowPredicates) {
  SmallPtrSet<const SCEVPredicate *, 4> Predicates;
  // We handle only IV > Invariant
  if (!isLoopInvariant(RHS, L))
    return getCouldNotCompute();

  const SCEVAddRecExpr *IV = dyn_cast<SCEVAddRecExpr>(LHS);
  if (!IV && AllowPredicates)
    // Try to make this an AddRec using runtime tests, in the first X
    // iterations of this loop, where X is the SCEV expression found by the
    // algorithm below.
    IV = convertSCEVToAddRecWithPredicates(LHS, L, Predicates);

  // Avoid weird loops
  if (!IV || IV->getLoop() != L || !IV->isAffine())
    return getCouldNotCompute();

  auto WrapType = IsSigned ? SCEV::FlagNSW : SCEV::FlagNUW;
  bool NoWrap = ControlsOnlyExit && IV->getNoWrapFlags(WrapType);
  ICmpInst::Predicate Cond = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;

  const SCEV *Stride = getNegativeSCEV(IV->getStepRecurrence(*this));

  // Avoid negative or zero stride values
  if (!isKnownPositive(Stride))
    return getCouldNotCompute();

  // Avoid proven overflow cases: this will ensure that the backedge taken count
  // will not generate any unsigned overflow. Relaxed no-overflow conditions
  // exploit NoWrapFlags, allowing to optimize in presence of undefined
  // behaviors like the case of C language.
  if (!Stride->isOne() && !NoWrap)
    if (canIVOverflowOnGT(RHS, Stride, IsSigned))
      return getCouldNotCompute();

  const SCEV *Start = IV->getStart();
  const SCEV *End = RHS;
  if (!isLoopEntryGuardedByCond(L, Cond, getAddExpr(Start, Stride), RHS)) {
    // If we know that Start >= RHS in the context of loop, then we know that
    // min(RHS, Start) = RHS at this point.
    if (isLoopEntryGuardedByCond(
            L, IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE, Start, RHS))
      End = RHS;
    else
      End = IsSigned ? getSMinExpr(RHS, Start) : getUMinExpr(RHS, Start);
  }

  if (Start->getType()->isPointerTy()) {
    Start = getLosslessPtrToIntExpr(Start);
    if (isa<SCEVCouldNotCompute>(Start))
      return Start;
  }
  if (End->getType()->isPointerTy()) {
    End = getLosslessPtrToIntExpr(End);
    if (isa<SCEVCouldNotCompute>(End))
      return End;
  }

  // Compute ((Start - End) + (Stride - 1)) / Stride.
  // FIXME: This can overflow. Holding off on fixing this for now;
  // howManyGreaterThans will hopefully be gone soon.
  const SCEV *One = getOne(Stride->getType());
  const SCEV *BECount = getUDivExpr(
      getAddExpr(getMinusSCEV(Start, End), getMinusSCEV(Stride, One)), Stride);

  APInt MaxStart = IsSigned ? getSignedRangeMax(Start)
                            : getUnsignedRangeMax(Start);

  APInt MinStride = IsSigned ? getSignedRangeMin(Stride)
                             : getUnsignedRangeMin(Stride);

  unsigned BitWidth = getTypeSizeInBits(LHS->getType());
  APInt Limit = IsSigned ? APInt::getSignedMinValue(BitWidth) + (MinStride - 1)
                         : APInt::getMinValue(BitWidth) + (MinStride - 1);

  // Although End can be a MIN expression we estimate MinEnd considering only
  // the case End = RHS. This is safe because in the other case (Start - End)
  // is zero, leading to a zero maximum backedge taken count.
  APInt MinEnd =
    IsSigned ? APIntOps::smax(getSignedRangeMin(RHS), Limit)
             : APIntOps::umax(getUnsignedRangeMin(RHS), Limit);

  const SCEV *ConstantMaxBECount =
      isa<SCEVConstant>(BECount)
          ? BECount
          : getUDivCeilSCEV(getConstant(MaxStart - MinEnd),
                            getConstant(MinStride));

  if (isa<SCEVCouldNotCompute>(ConstantMaxBECount))
    ConstantMaxBECount = BECount;
  const SCEV *SymbolicMaxBECount =
      isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;

  return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount, false,
                   Predicates);
}

const SCEV *SCEVAddRecExpr::getNumIterationsInRange(const ConstantRange &Range,
                                                    ScalarEvolution &SE) const {
  if (Range.isFullSet())  // Infinite loop.
    return SE.getCouldNotCompute();

  // If the start is a non-zero constant, shift the range to simplify things.
  if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(getStart()))
    if (!SC->getValue()->isZero()) {
      SmallVector<const SCEV *, 4> Operands(operands());
      Operands[0] = SE.getZero(SC->getType());
      const SCEV *Shifted = SE.getAddRecExpr(Operands, getLoop(),
                                             getNoWrapFlags(FlagNW));
      if (const auto *ShiftedAddRec = dyn_cast<SCEVAddRecExpr>(Shifted))
        return ShiftedAddRec->getNumIterationsInRange(
            Range.subtract(SC->getAPInt()), SE);
      // This is strange and shouldn't happen.
      return SE.getCouldNotCompute();
    }

  // The only time we can solve this is when we have all constant indices.
  // Otherwise, we cannot determine the overflow conditions.
  if (any_of(operands(), [](const SCEV *Op) { return !isa<SCEVConstant>(Op); }))
    return SE.getCouldNotCompute();

  // Okay at this point we know that all elements of the chrec are constants and
  // that the start element is zero.

  // First check to see if the range contains zero.  If not, the first
  // iteration exits.
  unsigned BitWidth = SE.getTypeSizeInBits(getType());
  if (!Range.contains(APInt(BitWidth, 0)))
    return SE.getZero(getType());

  if (isAffine()) {
    // If this is an affine expression then we have this situation:
    //   Solve {0,+,A} in Range  ===  Ax in Range

    // We know that zero is in the range.  If A is positive then we know that
    // the upper value of the range must be the first possible exit value.
    // If A is negative then the lower of the range is the last possible loop
    // value.  Also note that we already checked for a full range.
    APInt A = cast<SCEVConstant>(getOperand(1))->getAPInt();
    APInt End = A.sge(1) ? (Range.getUpper() - 1) : Range.getLower();

    // The exit value should be (End+A)/A.
    APInt ExitVal = (End + A).udiv(A);
    ConstantInt *ExitValue = ConstantInt::get(SE.getContext(), ExitVal);

    // Evaluate at the exit value.  If we really did fall out of the valid
    // range, then we computed our trip count, otherwise wrap around or other
    // things must have happened.
    ConstantInt *Val = EvaluateConstantChrecAtConstant(this, ExitValue, SE);
    if (Range.contains(Val->getValue()))
      return SE.getCouldNotCompute();  // Something strange happened

    // Ensure that the previous value is in the range.
    assert(Range.contains(
           EvaluateConstantChrecAtConstant(this,
           ConstantInt::get(SE.getContext(), ExitVal - 1), SE)->getValue()) &&
           "Linear scev computation is off in a bad way!");
    return SE.getConstant(ExitValue);
  }

  if (isQuadratic()) {
    if (auto S = SolveQuadraticAddRecRange(this, Range, SE))
      return SE.getConstant(*S);
  }

  return SE.getCouldNotCompute();
}

const SCEVAddRecExpr *
SCEVAddRecExpr::getPostIncExpr(ScalarEvolution &SE) const {
  assert(getNumOperands() > 1 && "AddRec with zero step?");
  // There is a temptation to just call getAddExpr(this, getStepRecurrence(SE)),
  // but in this case we cannot guarantee that the value returned will be an
  // AddRec because SCEV does not have a fixed point where it stops
  // simplification: it is legal to return ({rec1} + {rec2}). For example, it
  // may happen if we reach arithmetic depth limit while simplifying. So we
  // construct the returned value explicitly.
  SmallVector<const SCEV *, 3> Ops;
  // If this is {A,+,B,+,C,...,+,N}, then its step is {B,+,C,+,...,+,N}, and
  // (this + Step) is {A+B,+,B+C,+...,+,N}.
  for (unsigned i = 0, e = getNumOperands() - 1; i < e; ++i)
    Ops.push_back(SE.getAddExpr(getOperand(i), getOperand(i + 1)));
  // We know that the last operand is not a constant zero (otherwise it would
  // have been popped out earlier). This guarantees us that if the result has
  // the same last operand, then it will also not be popped out, meaning that
  // the returned value will be an AddRec.
  const SCEV *Last = getOperand(getNumOperands() - 1);
  assert(!Last->isZero() && "Recurrency with zero step?");
  Ops.push_back(Last);
  return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, getLoop(),
                                               SCEV::FlagAnyWrap));
}

// Return true when S contains at least an undef value.
bool ScalarEvolution::containsUndefs(const SCEV *S) const {
  return SCEVExprContains(S, [](const SCEV *S) {
    if (const auto *SU = dyn_cast<SCEVUnknown>(S))
      return isa<UndefValue>(SU->getValue());
    return false;
  });
}

// Return true when S contains a value that is a nullptr.
bool ScalarEvolution::containsErasedValue(const SCEV *S) const {
  return SCEVExprContains(S, [](const SCEV *S) {
    if (const auto *SU = dyn_cast<SCEVUnknown>(S))
      return SU->getValue() == nullptr;
    return false;
  });
}

/// Return the size of an element read or written by Inst.
const SCEV *ScalarEvolution::getElementSize(Instruction *Inst) {
  Type *Ty;
  if (StoreInst *Store = dyn_cast<StoreInst>(Inst))
    Ty = Store->getValueOperand()->getType();
  else if (LoadInst *Load = dyn_cast<LoadInst>(Inst))
    Ty = Load->getType();
  else
    return nullptr;

  Type *ETy = getEffectiveSCEVType(PointerType::getUnqual(Ty));
  return getSizeOfExpr(ETy, Ty);
}

//===----------------------------------------------------------------------===//
//                   SCEVCallbackVH Class Implementation
//===----------------------------------------------------------------------===//

void ScalarEvolution::SCEVCallbackVH::deleted() {
  assert(SE && "SCEVCallbackVH called with a null ScalarEvolution!");
  if (PHINode *PN = dyn_cast<PHINode>(getValPtr()))
    SE->ConstantEvolutionLoopExitValue.erase(PN);
  SE->eraseValueFromMap(getValPtr());
  // this now dangles!
}

void ScalarEvolution::SCEVCallbackVH::allUsesReplacedWith(Value *V) {
  assert(SE && "SCEVCallbackVH called with a null ScalarEvolution!");

  // Forget all the expressions associated with users of the old value,
  // so that future queries will recompute the expressions using the new
  // value.
  Value *Old = getValPtr();
  SmallVector<User *, 16> Worklist(Old->users());
  SmallPtrSet<User *, 8> Visited;
  while (!Worklist.empty()) {
    User *U = Worklist.pop_back_val();
    // Deleting the Old value will cause this to dangle. Postpone
    // that until everything else is done.
    if (U == Old)
      continue;
    if (!Visited.insert(U).second)
      continue;
    if (PHINode *PN = dyn_cast<PHINode>(U))
      SE->ConstantEvolutionLoopExitValue.erase(PN);
    SE->eraseValueFromMap(U);
    llvm::append_range(Worklist, U->users());
  }
  // Delete the Old value.
  if (PHINode *PN = dyn_cast<PHINode>(Old))
    SE->ConstantEvolutionLoopExitValue.erase(PN);
  SE->eraseValueFromMap(Old);
  // this now dangles!
}

ScalarEvolution::SCEVCallbackVH::SCEVCallbackVH(Value *V, ScalarEvolution *se)
  : CallbackVH(V), SE(se) {}

//===----------------------------------------------------------------------===//
//                   ScalarEvolution Class Implementation
//===----------------------------------------------------------------------===//

ScalarEvolution::ScalarEvolution(Function &F, TargetLibraryInfo &TLI,
                                 AssumptionCache &AC, DominatorTree &DT,
                                 LoopInfo &LI)
    : F(F), TLI(TLI), AC(AC), DT(DT), LI(LI),
      CouldNotCompute(new SCEVCouldNotCompute()), ValuesAtScopes(64),
      LoopDispositions(64), BlockDispositions(64) {
  // To use guards for proving predicates, we need to scan every instruction in
  // relevant basic blocks, and not just terminators.  Doing this is a waste of
  // time if the IR does not actually contain any calls to
  // @llvm.experimental.guard, so do a quick check and remember this beforehand.
  //
  // This pessimizes the case where a pass that preserves ScalarEvolution wants
  // to _add_ guards to the module when there weren't any before, and wants
  // ScalarEvolution to optimize based on those guards.  For now we prefer to be
  // efficient in lieu of being smart in that rather obscure case.

  auto *GuardDecl = F.getParent()->getFunction(
      Intrinsic::getName(Intrinsic::experimental_guard));
  HasGuards = GuardDecl && !GuardDecl->use_empty();
}

ScalarEvolution::ScalarEvolution(ScalarEvolution &&Arg)
    : F(Arg.F), HasGuards(Arg.HasGuards), TLI(Arg.TLI), AC(Arg.AC), DT(Arg.DT),
      LI(Arg.LI), CouldNotCompute(std::move(Arg.CouldNotCompute)),
      ValueExprMap(std::move(Arg.ValueExprMap)),
      PendingLoopPredicates(std::move(Arg.PendingLoopPredicates)),
      PendingPhiRanges(std::move(Arg.PendingPhiRanges)),
      PendingMerges(std::move(Arg.PendingMerges)),
      ConstantMultipleCache(std::move(Arg.ConstantMultipleCache)),
      BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)),
      PredicatedBackedgeTakenCounts(
          std::move(Arg.PredicatedBackedgeTakenCounts)),
      BECountUsers(std::move(Arg.BECountUsers)),
      ConstantEvolutionLoopExitValue(
          std::move(Arg.ConstantEvolutionLoopExitValue)),
      ValuesAtScopes(std::move(Arg.ValuesAtScopes)),
      ValuesAtScopesUsers(std::move(Arg.ValuesAtScopesUsers)),
      LoopDispositions(std::move(Arg.LoopDispositions)),
      LoopPropertiesCache(std::move(Arg.LoopPropertiesCache)),
      BlockDispositions(std::move(Arg.BlockDispositions)),
      SCEVUsers(std::move(Arg.SCEVUsers)),
      UnsignedRanges(std::move(Arg.UnsignedRanges)),
      SignedRanges(std::move(Arg.SignedRanges)),
      UniqueSCEVs(std::move(Arg.UniqueSCEVs)),
      UniquePreds(std::move(Arg.UniquePreds)),
      SCEVAllocator(std::move(Arg.SCEVAllocator)),
      LoopUsers(std::move(Arg.LoopUsers)),
      PredicatedSCEVRewrites(std::move(Arg.PredicatedSCEVRewrites)),
      FirstUnknown(Arg.FirstUnknown) {
  Arg.FirstUnknown = nullptr;
}

ScalarEvolution::~ScalarEvolution() {
  // Iterate through all the SCEVUnknown instances and call their
  // destructors, so that they release their references to their values.
  for (SCEVUnknown *U = FirstUnknown; U;) {
    SCEVUnknown *Tmp = U;
    U = U->Next;
    Tmp->~SCEVUnknown();
  }
  FirstUnknown = nullptr;

  ExprValueMap.clear();
  ValueExprMap.clear();
  HasRecMap.clear();
  BackedgeTakenCounts.clear();
  PredicatedBackedgeTakenCounts.clear();

  assert(PendingLoopPredicates.empty() && "isImpliedCond garbage");
  assert(PendingPhiRanges.empty() && "getRangeRef garbage");
  assert(PendingMerges.empty() && "isImpliedViaMerge garbage");
  assert(!WalkingBEDominatingConds && "isLoopBackedgeGuardedByCond garbage!");
  assert(!ProvingSplitPredicate && "ProvingSplitPredicate garbage!");
}

bool ScalarEvolution::hasLoopInvariantBackedgeTakenCount(const Loop *L) {
  return !isa<SCEVCouldNotCompute>(getBackedgeTakenCount(L));
}

static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
                          const Loop *L) {
  // Print all inner loops first
  for (Loop *I : *L)
    PrintLoopInfo(OS, SE, I);

  OS << "Loop ";
  L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
  OS << ": ";

  SmallVector<BasicBlock *, 8> ExitingBlocks;
  L->getExitingBlocks(ExitingBlocks);
  if (ExitingBlocks.size() != 1)
    OS << "<multiple exits> ";

  if (SE->hasLoopInvariantBackedgeTakenCount(L))
    OS << "backedge-taken count is " << *SE->getBackedgeTakenCount(L) << "\n";
  else
    OS << "Unpredictable backedge-taken count.\n";

  if (ExitingBlocks.size() > 1)
    for (BasicBlock *ExitingBlock : ExitingBlocks) {
      OS << "  exit count for " << ExitingBlock->getName() << ": "
         << *SE->getExitCount(L, ExitingBlock) << "\n";
    }

  OS << "Loop ";
  L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
  OS << ": ";

  auto *ConstantBTC = SE->getConstantMaxBackedgeTakenCount(L);
  if (!isa<SCEVCouldNotCompute>(ConstantBTC)) {
    OS << "constant max backedge-taken count is " << *ConstantBTC;
    if (SE->isBackedgeTakenCountMaxOrZero(L))
      OS << ", actual taken count either this or zero.";
  } else {
    OS << "Unpredictable constant max backedge-taken count. ";
  }

  OS << "\n"
        "Loop ";
  L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
  OS << ": ";

  auto *SymbolicBTC = SE->getSymbolicMaxBackedgeTakenCount(L);
  if (!isa<SCEVCouldNotCompute>(SymbolicBTC)) {
    OS << "symbolic max backedge-taken count is " << *SymbolicBTC;
    if (SE->isBackedgeTakenCountMaxOrZero(L))
      OS << ", actual taken count either this or zero.";
  } else {
    OS << "Unpredictable symbolic max backedge-taken count. ";
  }

  OS << "\n";
  if (ExitingBlocks.size() > 1)
    for (BasicBlock *ExitingBlock : ExitingBlocks) {
      OS << "  symbolic max exit count for " << ExitingBlock->getName() << ": "
         << *SE->getExitCount(L, ExitingBlock, ScalarEvolution::SymbolicMaximum)
         << "\n";
    }

  OS << "Loop ";
  L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
  OS << ": ";

  SmallVector<const SCEVPredicate *, 4> Preds;
  auto PBT = SE->getPredicatedBackedgeTakenCount(L, Preds);
  if (!isa<SCEVCouldNotCompute>(PBT)) {
    OS << "Predicated backedge-taken count is " << *PBT << "\n";
    OS << " Predicates:\n";
    for (const auto *P : Preds)
      P->print(OS, 4);
  } else {
    OS << "Unpredictable predicated backedge-taken count. ";
  }
  OS << "\n";

  if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
    OS << "Loop ";
    L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
    OS << ": ";
    OS << "Trip multiple is " << SE->getSmallConstantTripMultiple(L) << "\n";
  }
}

namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, ScalarEvolution::LoopDisposition LD) {
  switch (LD) {
  case ScalarEvolution::LoopVariant:
    OS << "Variant";
    break;
  case ScalarEvolution::LoopInvariant:
    OS << "Invariant";
    break;
  case ScalarEvolution::LoopComputable:
    OS << "Computable";
    break;
  }
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, ScalarEvolution::BlockDisposition BD) {
  switch (BD) {
  case ScalarEvolution::DoesNotDominateBlock:
    OS << "DoesNotDominate";
    break;
  case ScalarEvolution::DominatesBlock:
    OS << "Dominates";
    break;
  case ScalarEvolution::ProperlyDominatesBlock:
    OS << "ProperlyDominates";
    break;
  }
  return OS;
}
}

void ScalarEvolution::print(raw_ostream &OS) const {
  // ScalarEvolution's implementation of the print method is to print
  // out SCEV values of all instructions that are interesting. Doing
  // this potentially causes it to create new SCEV objects though,
  // which technically conflicts with the const qualifier. This isn't
  // observable from outside the class though, so casting away the
  // const isn't dangerous.
  ScalarEvolution &SE = *const_cast<ScalarEvolution *>(this);

  if (ClassifyExpressions) {
    OS << "Classifying expressions for: ";
    F.printAsOperand(OS, /*PrintType=*/false);
    OS << "\n";
    for (Instruction &I : instructions(F))
      if (isSCEVable(I.getType()) && !isa<CmpInst>(I)) {
        OS << I << '\n';
        OS << "  -->  ";
        const SCEV *SV = SE.getSCEV(&I);
        SV->print(OS);
        if (!isa<SCEVCouldNotCompute>(SV)) {
          OS << " U: ";
          SE.getUnsignedRange(SV).print(OS);
          OS << " S: ";
          SE.getSignedRange(SV).print(OS);
        }

        const Loop *L = LI.getLoopFor(I.getParent());

        const SCEV *AtUse = SE.getSCEVAtScope(SV, L);
        if (AtUse != SV) {
          OS << "  -->  ";
          AtUse->print(OS);
          if (!isa<SCEVCouldNotCompute>(AtUse)) {
            OS << " U: ";
            SE.getUnsignedRange(AtUse).print(OS);
            OS << " S: ";
            SE.getSignedRange(AtUse).print(OS);
          }
        }

        if (L) {
          OS << "\t\t" "Exits: ";
          const SCEV *ExitValue = SE.getSCEVAtScope(SV, L->getParentLoop());
          if (!SE.isLoopInvariant(ExitValue, L)) {
            OS << "<<Unknown>>";
          } else {
            OS << *ExitValue;
          }

          bool First = true;
          for (const auto *Iter = L; Iter; Iter = Iter->getParentLoop()) {
            if (First) {
              OS << "\t\t" "LoopDispositions: { ";
              First = false;
            } else {
              OS << ", ";
            }

            Iter->getHeader()->printAsOperand(OS, /*PrintType=*/false);
            OS << ": " << SE.getLoopDisposition(SV, Iter);
          }

          for (const auto *InnerL : depth_first(L)) {
            if (InnerL == L)
              continue;
            if (First) {
              OS << "\t\t" "LoopDispositions: { ";
              First = false;
            } else {
              OS << ", ";
            }

            InnerL->getHeader()->printAsOperand(OS, /*PrintType=*/false);
            OS << ": " << SE.getLoopDisposition(SV, InnerL);
          }

          OS << " }";
        }

        OS << "\n";
      }
  }

  OS << "Determining loop execution counts for: ";
  F.printAsOperand(OS, /*PrintType=*/false);
  OS << "\n";
  for (Loop *I : LI)
    PrintLoopInfo(OS, &SE, I);
}

ScalarEvolution::LoopDisposition
ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) {
  auto &Values = LoopDispositions[S];
  for (auto &V : Values) {
    if (V.getPointer() == L)
      return V.getInt();
  }
  Values.emplace_back(L, LoopVariant);
  LoopDisposition D = computeLoopDisposition(S, L);
  auto &Values2 = LoopDispositions[S];
  for (auto &V : llvm::reverse(Values2)) {
    if (V.getPointer() == L) {
      V.setInt(D);
      break;
    }
  }
  return D;
}

ScalarEvolution::LoopDisposition
ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
  switch (S->getSCEVType()) {
  case scConstant:
  case scVScale:
    return LoopInvariant;
  case scAddRecExpr: {
    const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);

    // If L is the addrec's loop, it's computable.
    if (AR->getLoop() == L)
      return LoopComputable;

    // Add recurrences are never invariant in the function-body (null loop).
    if (!L)
      return LoopVariant;

    // Everything that is not defined at loop entry is variant.
    if (DT.dominates(L->getHeader(), AR->getLoop()->getHeader()))
      return LoopVariant;
    assert(!L->contains(AR->getLoop()) && "Containing loop's header does not"
           " dominate the contained loop's header?");

    // This recurrence is invariant w.r.t. L if AR's loop contains L.
    if (AR->getLoop()->contains(L))
      return LoopInvariant;

    // This recurrence is variant w.r.t. L if any of its operands
    // are variant.
    for (const auto *Op : AR->operands())
      if (!isLoopInvariant(Op, L))
        return LoopVariant;

    // Otherwise it's loop-invariant.
    return LoopInvariant;
  }
  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
  case scPtrToInt:
  case scAddExpr:
  case scMulExpr:
  case scUDivExpr:
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scSequentialUMinExpr: {
    bool HasVarying = false;
    for (const auto *Op : S->operands()) {
      LoopDisposition D = getLoopDisposition(Op, L);
      if (D == LoopVariant)
        return LoopVariant;
      if (D == LoopComputable)
        HasVarying = true;
    }
    return HasVarying ? LoopComputable : LoopInvariant;
  }
  case scUnknown:
    // All non-instruction values are loop invariant.  All instructions are loop
    // invariant if they are not contained in the specified loop.
    // Instructions are never considered invariant in the function body
    // (null loop) because they are defined within the "loop".
    if (auto *I = dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue()))
      return (L && !L->contains(I)) ? LoopInvariant : LoopVariant;
    return LoopInvariant;
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
  return getLoopDisposition(S, L) == LoopInvariant;
}

bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) {
  return getLoopDisposition(S, L) == LoopComputable;
}

ScalarEvolution::BlockDisposition
ScalarEvolution::getBlockDisposition(const SCEV *S, const BasicBlock *BB) {
  auto &Values = BlockDispositions[S];
  for (auto &V : Values) {
    if (V.getPointer() == BB)
      return V.getInt();
  }
  Values.emplace_back(BB, DoesNotDominateBlock);
  BlockDisposition D = computeBlockDisposition(S, BB);
  auto &Values2 = BlockDispositions[S];
  for (auto &V : llvm::reverse(Values2)) {
    if (V.getPointer() == BB) {
      V.setInt(D);
      break;
    }
  }
  return D;
}

ScalarEvolution::BlockDisposition
ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
  switch (S->getSCEVType()) {
  case scConstant:
  case scVScale:
    return ProperlyDominatesBlock;
  case scAddRecExpr: {
    // This uses a "dominates" query instead of "properly dominates" query
    // to test for proper dominance too, because the instruction which
    // produces the addrec's value is a PHI, and a PHI effectively properly
    // dominates its entire containing block.
    const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
    if (!DT.dominates(AR->getLoop()->getHeader(), BB))
      return DoesNotDominateBlock;

    // Fall through into SCEVNAryExpr handling.
    [[fallthrough]];
  }
  case scTruncate:
  case scZeroExtend:
  case scSignExtend:
  case scPtrToInt:
  case scAddExpr:
  case scMulExpr:
  case scUDivExpr:
  case scUMaxExpr:
  case scSMaxExpr:
  case scUMinExpr:
  case scSMinExpr:
  case scSequentialUMinExpr: {
    bool Proper = true;
    for (const SCEV *NAryOp : S->operands()) {
      BlockDisposition D = getBlockDisposition(NAryOp, BB);
      if (D == DoesNotDominateBlock)
        return DoesNotDominateBlock;
      if (D == DominatesBlock)
        Proper = false;
    }
    return Proper ? ProperlyDominatesBlock : DominatesBlock;
  }
  case scUnknown:
    if (Instruction *I =
          dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue())) {
      if (I->getParent() == BB)
        return DominatesBlock;
      if (DT.properlyDominates(I->getParent(), BB))
        return ProperlyDominatesBlock;
      return DoesNotDominateBlock;
    }
    return ProperlyDominatesBlock;
  case scCouldNotCompute:
    llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
  }
  llvm_unreachable("Unknown SCEV kind!");
}

bool ScalarEvolution::dominates(const SCEV *S, const BasicBlock *BB) {
  return getBlockDisposition(S, BB) >= DominatesBlock;
}

bool ScalarEvolution::properlyDominates(const SCEV *S, const BasicBlock *BB) {
  return getBlockDisposition(S, BB) == ProperlyDominatesBlock;
}

bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const {
  return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; });
}

void ScalarEvolution::forgetBackedgeTakenCounts(const Loop *L,
                                                bool Predicated) {
  auto &BECounts =
      Predicated ? PredicatedBackedgeTakenCounts : BackedgeTakenCounts;
  auto It = BECounts.find(L);
  if (It != BECounts.end()) {
    for (const ExitNotTakenInfo &ENT : It->second.ExitNotTaken) {
      for (const SCEV *S : {ENT.ExactNotTaken, ENT.SymbolicMaxNotTaken}) {
        if (!isa<SCEVConstant>(S)) {
          auto UserIt = BECountUsers.find(S);
          assert(UserIt != BECountUsers.end());
          UserIt->second.erase({L, Predicated});
        }
      }
    }
    BECounts.erase(It);
  }
}

void ScalarEvolution::forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs) {
  SmallPtrSet<const SCEV *, 8> ToForget(SCEVs.begin(), SCEVs.end());
  SmallVector<const SCEV *, 8> Worklist(ToForget.begin(), ToForget.end());

  while (!Worklist.empty()) {
    const SCEV *Curr = Worklist.pop_back_val();
    auto Users = SCEVUsers.find(Curr);
    if (Users != SCEVUsers.end())
      for (const auto *User : Users->second)
        if (ToForget.insert(User).second)
          Worklist.push_back(User);
  }

  for (const auto *S : ToForget)
    forgetMemoizedResultsImpl(S);

  for (auto I = PredicatedSCEVRewrites.begin();
       I != PredicatedSCEVRewrites.end();) {
    std::pair<const SCEV *, const Loop *> Entry = I->first;
    if (ToForget.count(Entry.first))
      PredicatedSCEVRewrites.erase(I++);
    else
      ++I;
  }
}

void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
  LoopDispositions.erase(S);
  BlockDispositions.erase(S);
  UnsignedRanges.erase(S);
  SignedRanges.erase(S);
  HasRecMap.erase(S);
  ConstantMultipleCache.erase(S);

  if (auto *AR = dyn_cast<SCEVAddRecExpr>(S)) {
    UnsignedWrapViaInductionTried.erase(AR);
    SignedWrapViaInductionTried.erase(AR);
  }

  auto ExprIt = ExprValueMap.find(S);
  if (ExprIt != ExprValueMap.end()) {
    for (Value *V : ExprIt->second) {
      auto ValueIt = ValueExprMap.find_as(V);
      if (ValueIt != ValueExprMap.end())
        ValueExprMap.erase(ValueIt);
    }
    ExprValueMap.erase(ExprIt);
  }

  auto ScopeIt = ValuesAtScopes.find(S);
  if (ScopeIt != ValuesAtScopes.end()) {
    for (const auto &Pair : ScopeIt->second)
      if (!isa_and_nonnull<SCEVConstant>(Pair.second))
        erase_value(ValuesAtScopesUsers[Pair.second],
                    std::make_pair(Pair.first, S));
    ValuesAtScopes.erase(ScopeIt);
  }

  auto ScopeUserIt = ValuesAtScopesUsers.find(S);
  if (ScopeUserIt != ValuesAtScopesUsers.end()) {
    for (const auto &Pair : ScopeUserIt->second)
      erase_value(ValuesAtScopes[Pair.second], std::make_pair(Pair.first, S));
    ValuesAtScopesUsers.erase(ScopeUserIt);
  }

  auto BEUsersIt = BECountUsers.find(S);
  if (BEUsersIt != BECountUsers.end()) {
    // Work on a copy, as forgetBackedgeTakenCounts() will modify the original.
    auto Copy = BEUsersIt->second;
    for (const auto &Pair : Copy)
      forgetBackedgeTakenCounts(Pair.getPointer(), Pair.getInt());
    BECountUsers.erase(BEUsersIt);
  }

  auto FoldUser = FoldCacheUser.find(S);
  if (FoldUser != FoldCacheUser.end())
    for (auto &KV : FoldUser->second)
      FoldCache.erase(KV);
  FoldCacheUser.erase(S);
}

void
ScalarEvolution::getUsedLoops(const SCEV *S,
                              SmallPtrSetImpl<const Loop *> &LoopsUsed) {
  struct FindUsedLoops {
    FindUsedLoops(SmallPtrSetImpl<const Loop *> &LoopsUsed)
        : LoopsUsed(LoopsUsed) {}
    SmallPtrSetImpl<const Loop *> &LoopsUsed;
    bool follow(const SCEV *S) {
      if (auto *AR = dyn_cast<SCEVAddRecExpr>(S))
        LoopsUsed.insert(AR->getLoop());
      return true;
    }

    bool isDone() const { return false; }
  };

  FindUsedLoops F(LoopsUsed);
  SCEVTraversal<FindUsedLoops>(F).visitAll(S);
}

void ScalarEvolution::getReachableBlocks(
    SmallPtrSetImpl<BasicBlock *> &Reachable, Function &F) {
  SmallVector<BasicBlock *> Worklist;
  Worklist.push_back(&F.getEntryBlock());
  while (!Worklist.empty()) {
    BasicBlock *BB = Worklist.pop_back_val();
    if (!Reachable.insert(BB).second)
      continue;

    Value *Cond;
    BasicBlock *TrueBB, *FalseBB;
    if (match(BB->getTerminator(), m_Br(m_Value(Cond), m_BasicBlock(TrueBB),
                                        m_BasicBlock(FalseBB)))) {
      if (auto *C = dyn_cast<ConstantInt>(Cond)) {
        Worklist.push_back(C->isOne() ? TrueBB : FalseBB);
        continue;
      }

      if (auto *Cmp = dyn_cast<ICmpInst>(Cond)) {
        const SCEV *L = getSCEV(Cmp->getOperand(0));
        const SCEV *R = getSCEV(Cmp->getOperand(1));
        if (isKnownPredicateViaConstantRanges(Cmp->getPredicate(), L, R)) {
          Worklist.push_back(TrueBB);
          continue;
        }
        if (isKnownPredicateViaConstantRanges(Cmp->getInversePredicate(), L,
                                              R)) {
          Worklist.push_back(FalseBB);
          continue;
        }
      }
    }

    append_range(Worklist, successors(BB));
  }
}

void ScalarEvolution::verify() const {
  ScalarEvolution &SE = *const_cast<ScalarEvolution *>(this);
  ScalarEvolution SE2(F, TLI, AC, DT, LI);

  SmallVector<Loop *, 8> LoopStack(LI.begin(), LI.end());

  // Map's SCEV expressions from one ScalarEvolution "universe" to another.
  struct SCEVMapper : public SCEVRewriteVisitor<SCEVMapper> {
    SCEVMapper(ScalarEvolution &SE) : SCEVRewriteVisitor<SCEVMapper>(SE) {}

    const SCEV *visitConstant(const SCEVConstant *Constant) {
      return SE.getConstant(Constant->getAPInt());
    }

    const SCEV *visitUnknown(const SCEVUnknown *Expr) {
      return SE.getUnknown(Expr->getValue());
    }

    const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) {
      return SE.getCouldNotCompute();
    }
  };

  SCEVMapper SCM(SE2);
  SmallPtrSet<BasicBlock *, 16> ReachableBlocks;
  SE2.getReachableBlocks(ReachableBlocks, F);

  auto GetDelta = [&](const SCEV *Old, const SCEV *New) -> const SCEV * {
    if (containsUndefs(Old) || containsUndefs(New)) {
      // SCEV treats "undef" as an unknown but consistent value (i.e. it does
      // not propagate undef aggressively).  This means we can (and do) fail
      // verification in cases where a transform makes a value go from "undef"
      // to "undef+1" (say).  The transform is fine, since in both cases the
      // result is "undef", but SCEV thinks the value increased by 1.
      return nullptr;
    }

    // Unless VerifySCEVStrict is set, we only compare constant deltas.
    const SCEV *Delta = SE2.getMinusSCEV(Old, New);
    if (!VerifySCEVStrict && !isa<SCEVConstant>(Delta))
      return nullptr;

    return Delta;
  };

  while (!LoopStack.empty()) {
    auto *L = LoopStack.pop_back_val();
    llvm::append_range(LoopStack, *L);

    // Only verify BECounts in reachable loops. For an unreachable loop,
    // any BECount is legal.
    if (!ReachableBlocks.contains(L->getHeader()))
      continue;

    // Only verify cached BECounts. Computing new BECounts may change the
    // results of subsequent SCEV uses.
    auto It = BackedgeTakenCounts.find(L);
    if (It == BackedgeTakenCounts.end())
      continue;

    auto *CurBECount =
        SCM.visit(It->second.getExact(L, const_cast<ScalarEvolution *>(this)));
    auto *NewBECount = SE2.getBackedgeTakenCount(L);

    if (CurBECount == SE2.getCouldNotCompute() ||
        NewBECount == SE2.getCouldNotCompute()) {
      // NB! This situation is legal, but is very suspicious -- whatever pass
      // change the loop to make a trip count go from could not compute to
      // computable or vice-versa *should have* invalidated SCEV.  However, we
      // choose not to assert here (for now) since we don't want false
      // positives.
      continue;
    }

    if (SE.getTypeSizeInBits(CurBECount->getType()) >
        SE.getTypeSizeInBits(NewBECount->getType()))
      NewBECount = SE2.getZeroExtendExpr(NewBECount, CurBECount->getType());
    else if (SE.getTypeSizeInBits(CurBECount->getType()) <
             SE.getTypeSizeInBits(NewBECount->getType()))
      CurBECount = SE2.getZeroExtendExpr(CurBECount, NewBECount->getType());

    const SCEV *Delta = GetDelta(CurBECount, NewBECount);
    if (Delta && !Delta->isZero()) {
      dbgs() << "Trip Count for " << *L << " Changed!\n";
      dbgs() << "Old: " << *CurBECount << "\n";
      dbgs() << "New: " << *NewBECount << "\n";
      dbgs() << "Delta: " << *Delta << "\n";
      std::abort();
    }
  }

  // Collect all valid loops currently in LoopInfo.
  SmallPtrSet<Loop *, 32> ValidLoops;
  SmallVector<Loop *, 32> Worklist(LI.begin(), LI.end());
  while (!Worklist.empty()) {
    Loop *L = Worklist.pop_back_val();
    if (ValidLoops.insert(L).second)
      Worklist.append(L->begin(), L->end());
  }
  for (const auto &KV : ValueExprMap) {
#ifndef NDEBUG
    // Check for SCEV expressions referencing invalid/deleted loops.
    if (auto *AR = dyn_cast<SCEVAddRecExpr>(KV.second)) {
      assert(ValidLoops.contains(AR->getLoop()) &&
             "AddRec references invalid loop");
    }
#endif

    // Check that the value is also part of the reverse map.
    auto It = ExprValueMap.find(KV.second);
    if (It == ExprValueMap.end() || !It->second.contains(KV.first)) {
      dbgs() << "Value " << *KV.first
             << " is in ValueExprMap but not in ExprValueMap\n";
      std::abort();
    }

    if (auto *I = dyn_cast<Instruction>(&*KV.first)) {
      if (!ReachableBlocks.contains(I->getParent()))
        continue;
      const SCEV *OldSCEV = SCM.visit(KV.second);
      const SCEV *NewSCEV = SE2.getSCEV(I);
      const SCEV *Delta = GetDelta(OldSCEV, NewSCEV);
      if (Delta && !Delta->isZero()) {
        dbgs() << "SCEV for value " << *I << " changed!\n"
               << "Old: " << *OldSCEV << "\n"
               << "New: " << *NewSCEV << "\n"
               << "Delta: " << *Delta << "\n";
        std::abort();
      }
    }
  }

  for (const auto &KV : ExprValueMap) {
    for (Value *V : KV.second) {
      auto It = ValueExprMap.find_as(V);
      if (It == ValueExprMap.end()) {
        dbgs() << "Value " << *V
               << " is in ExprValueMap but not in ValueExprMap\n";
        std::abort();
      }
      if (It->second != KV.first) {
        dbgs() << "Value " << *V << " mapped to " << *It->second
               << " rather than " << *KV.first << "\n";
        std::abort();
      }
    }
  }

  // Verify integrity of SCEV users.
  for (const auto &S : UniqueSCEVs) {
    for (const auto *Op : S.operands()) {
      // We do not store dependencies of constants.
      if (isa<SCEVConstant>(Op))
        continue;
      auto It = SCEVUsers.find(Op);
      if (It != SCEVUsers.end() && It->second.count(&S))
        continue;
      dbgs() << "Use of operand  " << *Op << " by user " << S
             << " is not being tracked!\n";
      std::abort();
    }
  }

  // Verify integrity of ValuesAtScopes users.
  for (const auto &ValueAndVec : ValuesAtScopes) {
    const SCEV *Value = ValueAndVec.first;
    for (const auto &LoopAndValueAtScope : ValueAndVec.second) {
      const Loop *L = LoopAndValueAtScope.first;
      const SCEV *ValueAtScope = LoopAndValueAtScope.second;
      if (!isa<SCEVConstant>(ValueAtScope)) {
        auto It = ValuesAtScopesUsers.find(ValueAtScope);
        if (It != ValuesAtScopesUsers.end() &&
            is_contained(It->second, std::make_pair(L, Value)))
          continue;
        dbgs() << "Value: " << *Value << ", Loop: " << *L << ", ValueAtScope: "
               << *ValueAtScope << " missing in ValuesAtScopesUsers\n";
        std::abort();
      }
    }
  }

  for (const auto &ValueAtScopeAndVec : ValuesAtScopesUsers) {
    const SCEV *ValueAtScope = ValueAtScopeAndVec.first;
    for (const auto &LoopAndValue : ValueAtScopeAndVec.second) {
      const Loop *L = LoopAndValue.first;
      const SCEV *Value = LoopAndValue.second;
      assert(!isa<SCEVConstant>(Value));
      auto It = ValuesAtScopes.find(Value);
      if (It != ValuesAtScopes.end() &&
          is_contained(It->second, std::make_pair(L, ValueAtScope)))
        continue;
      dbgs() << "Value: " << *Value << ", Loop: " << *L << ", ValueAtScope: "
             << *ValueAtScope << " missing in ValuesAtScopes\n";
      std::abort();
    }
  }

  // Verify integrity of BECountUsers.
  auto VerifyBECountUsers = [&](bool Predicated) {
    auto &BECounts =
        Predicated ? PredicatedBackedgeTakenCounts : BackedgeTakenCounts;
    for (const auto &LoopAndBEInfo : BECounts) {
      for (const ExitNotTakenInfo &ENT : LoopAndBEInfo.second.ExitNotTaken) {
        for (const SCEV *S : {ENT.ExactNotTaken, ENT.SymbolicMaxNotTaken}) {
          if (!isa<SCEVConstant>(S)) {
            auto UserIt = BECountUsers.find(S);
            if (UserIt != BECountUsers.end() &&
                UserIt->second.contains({ LoopAndBEInfo.first, Predicated }))
              continue;
            dbgs() << "Value " << *S << " for loop " << *LoopAndBEInfo.first
                   << " missing from BECountUsers\n";
            std::abort();
          }
        }
      }
    }
  };
  VerifyBECountUsers(/* Predicated */ false);
  VerifyBECountUsers(/* Predicated */ true);

  // Verify intergity of loop disposition cache.
  for (auto &[S, Values] : LoopDispositions) {
    for (auto [Loop, CachedDisposition] : Values) {
      const auto RecomputedDisposition = SE2.getLoopDisposition(S, Loop);
      if (CachedDisposition != RecomputedDisposition) {
        dbgs() << "Cached disposition of " << *S << " for loop " << *Loop
               << " is incorrect: cached " << CachedDisposition << ", actual "
               << RecomputedDisposition << "\n";
        std::abort();
      }
    }
  }

  // Verify integrity of the block disposition cache.
  for (auto &[S, Values] : BlockDispositions) {
    for (auto [BB, CachedDisposition] : Values) {
      const auto RecomputedDisposition = SE2.getBlockDisposition(S, BB);
      if (CachedDisposition != RecomputedDisposition) {
        dbgs() << "Cached disposition of " << *S << " for block %"
               << BB->getName() << " is incorrect: cached " << CachedDisposition
               << ", actual " << RecomputedDisposition << "\n";
        std::abort();
      }
    }
  }

  // Verify FoldCache/FoldCacheUser caches.
  for (auto [FoldID, Expr] : FoldCache) {
    auto I = FoldCacheUser.find(Expr);
    if (I == FoldCacheUser.end()) {
      dbgs() << "Missing entry in FoldCacheUser for cached expression " << *Expr
             << "!\n";
      std::abort();
    }
    if (!is_contained(I->second, FoldID)) {
      dbgs() << "Missing FoldID in cached users of " << *Expr << "!\n";
      std::abort();
    }
  }
  for (auto [Expr, IDs] : FoldCacheUser) {
    for (auto &FoldID : IDs) {
      auto I = FoldCache.find(FoldID);
      if (I == FoldCache.end()) {
        dbgs() << "Missing entry in FoldCache for expression " << *Expr
               << "!\n";
        std::abort();
      }
      if (I->second != Expr) {
        dbgs() << "Entry in FoldCache doesn't match FoldCacheUser: "
               << *I->second << " != " << *Expr << "!\n";
        std::abort();
      }
    }
  }

  // Verify that ConstantMultipleCache computations are correct. We check that
  // cached multiples and recomputed multiples are multiples of each other to
  // verify correctness. It is possible that a recomputed multiple is different
  // from the cached multiple due to strengthened no wrap flags or changes in
  // KnownBits computations.
  for (auto [S, Multiple] : ConstantMultipleCache) {
    APInt RecomputedMultiple = SE2.getConstantMultiple(S);
    if ((Multiple != 0 && RecomputedMultiple != 0 &&
         Multiple.urem(RecomputedMultiple) != 0 &&
         RecomputedMultiple.urem(Multiple) != 0)) {
      dbgs() << "Incorrect cached computation in ConstantMultipleCache for "
             << *S << " : Computed " << RecomputedMultiple
             << " but cache contains " << Multiple << "!\n";
      std::abort();
    }
  }
}

bool ScalarEvolution::invalidate(
    Function &F, const PreservedAnalyses &PA,
    FunctionAnalysisManager::Invalidator &Inv) {
  // Invalidate the ScalarEvolution object whenever it isn't preserved or one
  // of its dependencies is invalidated.
  auto PAC = PA.getChecker<ScalarEvolutionAnalysis>();
  return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) ||
         Inv.invalidate<AssumptionAnalysis>(F, PA) ||
         Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
         Inv.invalidate<LoopAnalysis>(F, PA);
}

AnalysisKey ScalarEvolutionAnalysis::Key;

ScalarEvolution ScalarEvolutionAnalysis::run(Function &F,
                                             FunctionAnalysisManager &AM) {
  auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
  auto &AC = AM.getResult<AssumptionAnalysis>(F);
  auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
  auto &LI = AM.getResult<LoopAnalysis>(F);
  return ScalarEvolution(F, TLI, AC, DT, LI);
}

PreservedAnalyses
ScalarEvolutionVerifierPass::run(Function &F, FunctionAnalysisManager &AM) {
  AM.getResult<ScalarEvolutionAnalysis>(F).verify();
  return PreservedAnalyses::all();
}

PreservedAnalyses
ScalarEvolutionPrinterPass::run(Function &F, FunctionAnalysisManager &AM) {
  // For compatibility with opt's -analyze feature under legacy pass manager
  // which was not ported to NPM. This keeps tests using
  // update_analyze_test_checks.py working.
  OS << "Printing analysis 'Scalar Evolution Analysis' for function '"
     << F.getName() << "':\n";
  AM.getResult<ScalarEvolutionAnalysis>(F).print(OS);
  return PreservedAnalyses::all();
}

INITIALIZE_PASS_BEGIN(ScalarEvolutionWrapperPass, "scalar-evolution",
                      "Scalar Evolution Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(ScalarEvolutionWrapperPass, "scalar-evolution",
                    "Scalar Evolution Analysis", false, true)

char ScalarEvolutionWrapperPass::ID = 0;

ScalarEvolutionWrapperPass::ScalarEvolutionWrapperPass() : FunctionPass(ID) {
  initializeScalarEvolutionWrapperPassPass(*PassRegistry::getPassRegistry());
}

bool ScalarEvolutionWrapperPass::runOnFunction(Function &F) {
  SE.reset(new ScalarEvolution(
      F, getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F),
      getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F),
      getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
      getAnalysis<LoopInfoWrapperPass>().getLoopInfo()));
  return false;
}

void ScalarEvolutionWrapperPass::releaseMemory() { SE.reset(); }

void ScalarEvolutionWrapperPass::print(raw_ostream &OS, const Module *) const {
  SE->print(OS);
}

void ScalarEvolutionWrapperPass::verifyAnalysis() const {
  if (!VerifySCEV)
    return;

  SE->verify();
}

void ScalarEvolutionWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequiredTransitive<AssumptionCacheTracker>();
  AU.addRequiredTransitive<LoopInfoWrapperPass>();
  AU.addRequiredTransitive<DominatorTreeWrapperPass>();
  AU.addRequiredTransitive<TargetLibraryInfoWrapperPass>();
}

const SCEVPredicate *ScalarEvolution::getEqualPredicate(const SCEV *LHS,
                                                        const SCEV *RHS) {
  return getComparePredicate(ICmpInst::ICMP_EQ, LHS, RHS);
}

const SCEVPredicate *
ScalarEvolution::getComparePredicate(const ICmpInst::Predicate Pred,
                                     const SCEV *LHS, const SCEV *RHS) {
  FoldingSetNodeID ID;
  assert(LHS->getType() == RHS->getType() &&
         "Type mismatch between LHS and RHS");
  // Unique this node based on the arguments
  ID.AddInteger(SCEVPredicate::P_Compare);
  ID.AddInteger(Pred);
  ID.AddPointer(LHS);
  ID.AddPointer(RHS);
  void *IP = nullptr;
  if (const auto *S = UniquePreds.FindNodeOrInsertPos(ID, IP))
    return S;
  SCEVComparePredicate *Eq = new (SCEVAllocator)
    SCEVComparePredicate(ID.Intern(SCEVAllocator), Pred, LHS, RHS);
  UniquePreds.InsertNode(Eq, IP);
  return Eq;
}

const SCEVPredicate *ScalarEvolution::getWrapPredicate(
    const SCEVAddRecExpr *AR,
    SCEVWrapPredicate::IncrementWrapFlags AddedFlags) {
  FoldingSetNodeID ID;
  // Unique this node based on the arguments
  ID.AddInteger(SCEVPredicate::P_Wrap);
  ID.AddPointer(AR);
  ID.AddInteger(AddedFlags);
  void *IP = nullptr;
  if (const auto *S = UniquePreds.FindNodeOrInsertPos(ID, IP))
    return S;
  auto *OF = new (SCEVAllocator)
      SCEVWrapPredicate(ID.Intern(SCEVAllocator), AR, AddedFlags);
  UniquePreds.InsertNode(OF, IP);
  return OF;
}

namespace {

class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
public:

  /// Rewrites \p S in the context of a loop L and the SCEV predication
  /// infrastructure.
  ///
  /// If \p Pred is non-null, the SCEV expression is rewritten to respect the
  /// equivalences present in \p Pred.
  ///
  /// If \p NewPreds is non-null, rewrite is free to add further predicates to
  /// \p NewPreds such that the result will be an AddRecExpr.
  static const SCEV *rewrite(const SCEV *S, const Loop *L, ScalarEvolution &SE,
                             SmallPtrSetImpl<const SCEVPredicate *> *NewPreds,
                             const SCEVPredicate *Pred) {
    SCEVPredicateRewriter Rewriter(L, SE, NewPreds, Pred);
    return Rewriter.visit(S);
  }

  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
    if (Pred) {
      if (auto *U = dyn_cast<SCEVUnionPredicate>(Pred)) {
        for (const auto *Pred : U->getPredicates())
          if (const auto *IPred = dyn_cast<SCEVComparePredicate>(Pred))
            if (IPred->getLHS() == Expr &&
                IPred->getPredicate() == ICmpInst::ICMP_EQ)
              return IPred->getRHS();
      } else if (const auto *IPred = dyn_cast<SCEVComparePredicate>(Pred)) {
        if (IPred->getLHS() == Expr &&
            IPred->getPredicate() == ICmpInst::ICMP_EQ)
          return IPred->getRHS();
      }
    }
    return convertToAddRecWithPreds(Expr);
  }

  const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
    const SCEV *Operand = visit(Expr->getOperand());
    const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Operand);
    if (AR && AR->getLoop() == L && AR->isAffine()) {
      // This couldn't be folded because the operand didn't have the nuw
      // flag. Add the nusw flag as an assumption that we could make.
      const SCEV *Step = AR->getStepRecurrence(SE);
      Type *Ty = Expr->getType();
      if (addOverflowAssumption(AR, SCEVWrapPredicate::IncrementNUSW))
        return SE.getAddRecExpr(SE.getZeroExtendExpr(AR->getStart(), Ty),
                                SE.getSignExtendExpr(Step, Ty), L,
                                AR->getNoWrapFlags());
    }
    return SE.getZeroExtendExpr(Operand, Expr->getType());
  }

  const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
    const SCEV *Operand = visit(Expr->getOperand());
    const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Operand);
    if (AR && AR->getLoop() == L && AR->isAffine()) {
      // This couldn't be folded because the operand didn't have the nsw
      // flag. Add the nssw flag as an assumption that we could make.
      const SCEV *Step = AR->getStepRecurrence(SE);
      Type *Ty = Expr->getType();
      if (addOverflowAssumption(AR, SCEVWrapPredicate::IncrementNSSW))
        return SE.getAddRecExpr(SE.getSignExtendExpr(AR->getStart(), Ty),
                                SE.getSignExtendExpr(Step, Ty), L,
                                AR->getNoWrapFlags());
    }
    return SE.getSignExtendExpr(Operand, Expr->getType());
  }

private:
  explicit SCEVPredicateRewriter(const Loop *L, ScalarEvolution &SE,
                        SmallPtrSetImpl<const SCEVPredicate *> *NewPreds,
                        const SCEVPredicate *Pred)
      : SCEVRewriteVisitor(SE), NewPreds(NewPreds), Pred(Pred), L(L) {}

  bool addOverflowAssumption(const SCEVPredicate *P) {
    if (!NewPreds) {
      // Check if we've already made this assumption.
      return Pred && Pred->implies(P);
    }
    NewPreds->insert(P);
    return true;
  }

  bool addOverflowAssumption(const SCEVAddRecExpr *AR,
                             SCEVWrapPredicate::IncrementWrapFlags AddedFlags) {
    auto *A = SE.getWrapPredicate(AR, AddedFlags);
    return addOverflowAssumption(A);
  }

  // If \p Expr represents a PHINode, we try to see if it can be represented
  // as an AddRec, possibly under a predicate (PHISCEVPred). If it is possible
  // to add this predicate as a runtime overflow check, we return the AddRec.
  // If \p Expr does not meet these conditions (is not a PHI node, or we
  // couldn't create an AddRec for it, or couldn't add the predicate), we just
  // return \p Expr.
  const SCEV *convertToAddRecWithPreds(const SCEVUnknown *Expr) {
    if (!isa<PHINode>(Expr->getValue()))
      return Expr;
    std::optional<
        std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
        PredicatedRewrite = SE.createAddRecFromPHIWithCasts(Expr);
    if (!PredicatedRewrite)
      return Expr;
    for (const auto *P : PredicatedRewrite->second){
      // Wrap predicates from outer loops are not supported.
      if (auto *WP = dyn_cast<const SCEVWrapPredicate>(P)) {
        if (L != WP->getExpr()->getLoop())
          return Expr;
      }
      if (!addOverflowAssumption(P))
        return Expr;
    }
    return PredicatedRewrite->first;
  }

  SmallPtrSetImpl<const SCEVPredicate *> *NewPreds;
  const SCEVPredicate *Pred;
  const Loop *L;
};

} // end anonymous namespace

const SCEV *
ScalarEvolution::rewriteUsingPredicate(const SCEV *S, const Loop *L,
                                       const SCEVPredicate &Preds) {
  return SCEVPredicateRewriter::rewrite(S, L, *this, nullptr, &Preds);
}

const SCEVAddRecExpr *ScalarEvolution::convertSCEVToAddRecWithPredicates(
    const SCEV *S, const Loop *L,
    SmallPtrSetImpl<const SCEVPredicate *> &Preds) {
  SmallPtrSet<const SCEVPredicate *, 4> TransformPreds;
  S = SCEVPredicateRewriter::rewrite(S, L, *this, &TransformPreds, nullptr);
  auto *AddRec = dyn_cast<SCEVAddRecExpr>(S);

  if (!AddRec)
    return nullptr;

  // Since the transformation was successful, we can now transfer the SCEV
  // predicates.
  for (const auto *P : TransformPreds)
    Preds.insert(P);

  return AddRec;
}

/// SCEV predicates
SCEVPredicate::SCEVPredicate(const FoldingSetNodeIDRef ID,
                             SCEVPredicateKind Kind)
    : FastID(ID), Kind(Kind) {}

SCEVComparePredicate::SCEVComparePredicate(const FoldingSetNodeIDRef ID,
                                   const ICmpInst::Predicate Pred,
                                   const SCEV *LHS, const SCEV *RHS)
  : SCEVPredicate(ID, P_Compare), Pred(Pred), LHS(LHS), RHS(RHS) {
  assert(LHS->getType() == RHS->getType() && "LHS and RHS types don't match");
  assert(LHS != RHS && "LHS and RHS are the same SCEV");
}

bool SCEVComparePredicate::implies(const SCEVPredicate *N) const {
  const auto *Op = dyn_cast<SCEVComparePredicate>(N);

  if (!Op)
    return false;

  if (Pred != ICmpInst::ICMP_EQ)
    return false;

  return Op->LHS == LHS && Op->RHS == RHS;
}

bool SCEVComparePredicate::isAlwaysTrue() const { return false; }

void SCEVComparePredicate::print(raw_ostream &OS, unsigned Depth) const {
  if (Pred == ICmpInst::ICMP_EQ)
    OS.indent(Depth) << "Equal predicate: " << *LHS << " == " << *RHS << "\n";
  else
    OS.indent(Depth) << "Compare predicate: " << *LHS << " " << Pred << ") "
                     << *RHS << "\n";

}

SCEVWrapPredicate::SCEVWrapPredicate(const FoldingSetNodeIDRef ID,
                                     const SCEVAddRecExpr *AR,
                                     IncrementWrapFlags Flags)
    : SCEVPredicate(ID, P_Wrap), AR(AR), Flags(Flags) {}

const SCEVAddRecExpr *SCEVWrapPredicate::getExpr() const { return AR; }

bool SCEVWrapPredicate::implies(const SCEVPredicate *N) const {
  const auto *Op = dyn_cast<SCEVWrapPredicate>(N);

  return Op && Op->AR == AR && setFlags(Flags, Op->Flags) == Flags;
}

bool SCEVWrapPredicate::isAlwaysTrue() const {
  SCEV::NoWrapFlags ScevFlags = AR->getNoWrapFlags();
  IncrementWrapFlags IFlags = Flags;

  if (ScalarEvolution::setFlags(ScevFlags, SCEV::FlagNSW) == ScevFlags)
    IFlags = clearFlags(IFlags, IncrementNSSW);

  return IFlags == IncrementAnyWrap;
}

void SCEVWrapPredicate::print(raw_ostream &OS, unsigned Depth) const {
  OS.indent(Depth) << *getExpr() << " Added Flags: ";
  if (SCEVWrapPredicate::IncrementNUSW & getFlags())
    OS << "<nusw>";
  if (SCEVWrapPredicate::IncrementNSSW & getFlags())
    OS << "<nssw>";
  OS << "\n";
}

SCEVWrapPredicate::IncrementWrapFlags
SCEVWrapPredicate::getImpliedFlags(const SCEVAddRecExpr *AR,
                                   ScalarEvolution &SE) {
  IncrementWrapFlags ImpliedFlags = IncrementAnyWrap;
  SCEV::NoWrapFlags StaticFlags = AR->getNoWrapFlags();

  // We can safely transfer the NSW flag as NSSW.
  if (ScalarEvolution::setFlags(StaticFlags, SCEV::FlagNSW) == StaticFlags)
    ImpliedFlags = IncrementNSSW;

  if (ScalarEvolution::setFlags(StaticFlags, SCEV::FlagNUW) == StaticFlags) {
    // If the increment is positive, the SCEV NUW flag will also imply the
    // WrapPredicate NUSW flag.
    if (const auto *Step = dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE)))
      if (Step->getValue()->getValue().isNonNegative())
        ImpliedFlags = setFlags(ImpliedFlags, IncrementNUSW);
  }

  return ImpliedFlags;
}

/// Union predicates don't get cached so create a dummy set ID for it.
SCEVUnionPredicate::SCEVUnionPredicate(ArrayRef<const SCEVPredicate *> Preds)
  : SCEVPredicate(FoldingSetNodeIDRef(nullptr, 0), P_Union) {
  for (const auto *P : Preds)
    add(P);
}

bool SCEVUnionPredicate::isAlwaysTrue() const {
  return all_of(Preds,
                [](const SCEVPredicate *I) { return I->isAlwaysTrue(); });
}

bool SCEVUnionPredicate::implies(const SCEVPredicate *N) const {
  if (const auto *Set = dyn_cast<SCEVUnionPredicate>(N))
    return all_of(Set->Preds,
                  [this](const SCEVPredicate *I) { return this->implies(I); });

  return any_of(Preds,
                [N](const SCEVPredicate *I) { return I->implies(N); });
}

void SCEVUnionPredicate::print(raw_ostream &OS, unsigned Depth) const {
  for (const auto *Pred : Preds)
    Pred->print(OS, Depth);
}

void SCEVUnionPredicate::add(const SCEVPredicate *N) {
  if (const auto *Set = dyn_cast<SCEVUnionPredicate>(N)) {
    for (const auto *Pred : Set->Preds)
      add(Pred);
    return;
  }

  Preds.push_back(N);
}

PredicatedScalarEvolution::PredicatedScalarEvolution(ScalarEvolution &SE,
                                                     Loop &L)
    : SE(SE), L(L) {
  SmallVector<const SCEVPredicate*, 4> Empty;
  Preds = std::make_unique<SCEVUnionPredicate>(Empty);
}

void ScalarEvolution::registerUser(const SCEV *User,
                                   ArrayRef<const SCEV *> Ops) {
  for (const auto *Op : Ops)
    // We do not expect that forgetting cached data for SCEVConstants will ever
    // open any prospects for sharpening or introduce any correctness issues,
    // so we don't bother storing their dependencies.
    if (!isa<SCEVConstant>(Op))
      SCEVUsers[Op].insert(User);
}

const SCEV *PredicatedScalarEvolution::getSCEV(Value *V) {
  const SCEV *Expr = SE.getSCEV(V);
  RewriteEntry &Entry = RewriteMap[Expr];

  // If we already have an entry and the version matches, return it.
  if (Entry.second && Generation == Entry.first)
    return Entry.second;

  // We found an entry but it's stale. Rewrite the stale entry
  // according to the current predicate.
  if (Entry.second)
    Expr = Entry.second;

  const SCEV *NewSCEV = SE.rewriteUsingPredicate(Expr, &L, *Preds);
  Entry = {Generation, NewSCEV};

  return NewSCEV;
}

const SCEV *PredicatedScalarEvolution::getBackedgeTakenCount() {
  if (!BackedgeCount) {
    SmallVector<const SCEVPredicate *, 4> Preds;
    BackedgeCount = SE.getPredicatedBackedgeTakenCount(&L, Preds);
    for (const auto *P : Preds)
      addPredicate(*P);
  }
  return BackedgeCount;
}

void PredicatedScalarEvolution::addPredicate(const SCEVPredicate &Pred) {
  if (Preds->implies(&Pred))
    return;

  auto &OldPreds = Preds->getPredicates();
  SmallVector<const SCEVPredicate*, 4> NewPreds(OldPreds.begin(), OldPreds.end());
  NewPreds.push_back(&Pred);
  Preds = std::make_unique<SCEVUnionPredicate>(NewPreds);
  updateGeneration();
}

const SCEVPredicate &PredicatedScalarEvolution::getPredicate() const {
  return *Preds;
}

void PredicatedScalarEvolution::updateGeneration() {
  // If the generation number wrapped recompute everything.
  if (++Generation == 0) {
    for (auto &II : RewriteMap) {
      const SCEV *Rewritten = II.second.second;
      II.second = {Generation, SE.rewriteUsingPredicate(Rewritten, &L, *Preds)};
    }
  }
}

void PredicatedScalarEvolution::setNoOverflow(
    Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags) {
  const SCEV *Expr = getSCEV(V);
  const auto *AR = cast<SCEVAddRecExpr>(Expr);

  auto ImpliedFlags = SCEVWrapPredicate::getImpliedFlags(AR, SE);

  // Clear the statically implied flags.
  Flags = SCEVWrapPredicate::clearFlags(Flags, ImpliedFlags);
  addPredicate(*SE.getWrapPredicate(AR, Flags));

  auto II = FlagsMap.insert({V, Flags});
  if (!II.second)
    II.first->second = SCEVWrapPredicate::setFlags(Flags, II.first->second);
}

bool PredicatedScalarEvolution::hasNoOverflow(
    Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags) {
  const SCEV *Expr = getSCEV(V);
  const auto *AR = cast<SCEVAddRecExpr>(Expr);

  Flags = SCEVWrapPredicate::clearFlags(
      Flags, SCEVWrapPredicate::getImpliedFlags(AR, SE));

  auto II = FlagsMap.find(V);

  if (II != FlagsMap.end())
    Flags = SCEVWrapPredicate::clearFlags(Flags, II->second);

  return Flags == SCEVWrapPredicate::IncrementAnyWrap;
}

const SCEVAddRecExpr *PredicatedScalarEvolution::getAsAddRec(Value *V) {
  const SCEV *Expr = this->getSCEV(V);
  SmallPtrSet<const SCEVPredicate *, 4> NewPreds;
  auto *New = SE.convertSCEVToAddRecWithPredicates(Expr, &L, NewPreds);

  if (!New)
    return nullptr;

  for (const auto *P : NewPreds)
    addPredicate(*P);

  RewriteMap[SE.getSCEV(V)] = {Generation, New};
  return New;
}

PredicatedScalarEvolution::PredicatedScalarEvolution(
    const PredicatedScalarEvolution &Init)
  : RewriteMap(Init.RewriteMap), SE(Init.SE), L(Init.L),
    Preds(std::make_unique<SCEVUnionPredicate>(Init.Preds->getPredicates())),
    Generation(Init.Generation), BackedgeCount(Init.BackedgeCount) {
  for (auto I : Init.FlagsMap)
    FlagsMap.insert(I);
}

void PredicatedScalarEvolution::print(raw_ostream &OS, unsigned Depth) const {
  // For each block.
  for (auto *BB : L.getBlocks())
    for (auto &I : *BB) {
      if (!SE.isSCEVable(I.getType()))
        continue;

      auto *Expr = SE.getSCEV(&I);
      auto II = RewriteMap.find(Expr);

      if (II == RewriteMap.end())
        continue;

      // Don't print things that are not interesting.
      if (II->second.second == Expr)
        continue;

      OS.indent(Depth) << "[PSE]" << I << ":\n";
      OS.indent(Depth + 2) << *Expr << "\n";
      OS.indent(Depth + 2) << "--> " << *II->second.second << "\n";
    }
}

// Match the mathematical pattern A - (A / B) * B, where A and B can be
// arbitrary expressions. Also match zext (trunc A to iB) to iY, which is used
// for URem with constant power-of-2 second operands.
// It's not always easy, as A and B can be folded (imagine A is X / 2, and B is
// 4, A / B becomes X / 8).
bool ScalarEvolution::matchURem(const SCEV *Expr, const SCEV *&LHS,
                                const SCEV *&RHS) {
  // Try to match 'zext (trunc A to iB) to iY', which is used
  // for URem with constant power-of-2 second operands. Make sure the size of
  // the operand A matches the size of the whole expressions.
  if (const auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(Expr))
    if (const auto *Trunc = dyn_cast<SCEVTruncateExpr>(ZExt->getOperand(0))) {
      LHS = Trunc->getOperand();
      // Bail out if the type of the LHS is larger than the type of the
      // expression for now.
      if (getTypeSizeInBits(LHS->getType()) >
          getTypeSizeInBits(Expr->getType()))
        return false;
      if (LHS->getType() != Expr->getType())
        LHS = getZeroExtendExpr(LHS, Expr->getType());
      RHS = getConstant(APInt(getTypeSizeInBits(Expr->getType()), 1)
                        << getTypeSizeInBits(Trunc->getType()));
      return true;
    }
  const auto *Add = dyn_cast<SCEVAddExpr>(Expr);
  if (Add == nullptr || Add->getNumOperands() != 2)
    return false;

  const SCEV *A = Add->getOperand(1);
  const auto *Mul = dyn_cast<SCEVMulExpr>(Add->getOperand(0));

  if (Mul == nullptr)
    return false;

  const auto MatchURemWithDivisor = [&](const SCEV *B) {
    // (SomeExpr + (-(SomeExpr / B) * B)).
    if (Expr == getURemExpr(A, B)) {
      LHS = A;
      RHS = B;
      return true;
    }
    return false;
  };

  // (SomeExpr + (-1 * (SomeExpr / B) * B)).
  if (Mul->getNumOperands() == 3 && isa<SCEVConstant>(Mul->getOperand(0)))
    return MatchURemWithDivisor(Mul->getOperand(1)) ||
           MatchURemWithDivisor(Mul->getOperand(2));

  // (SomeExpr + ((-SomeExpr / B) * B)) or (SomeExpr + ((SomeExpr / B) * -B)).
  if (Mul->getNumOperands() == 2)
    return MatchURemWithDivisor(Mul->getOperand(1)) ||
           MatchURemWithDivisor(Mul->getOperand(0)) ||
           MatchURemWithDivisor(getNegativeSCEV(Mul->getOperand(1))) ||
           MatchURemWithDivisor(getNegativeSCEV(Mul->getOperand(0)));
  return false;
}

const SCEV *
ScalarEvolution::computeSymbolicMaxBackedgeTakenCount(const Loop *L) {
  SmallVector<BasicBlock*, 16> ExitingBlocks;
  L->getExitingBlocks(ExitingBlocks);

  // Form an expression for the maximum exit count possible for this loop. We
  // merge the max and exact information to approximate a version of
  // getConstantMaxBackedgeTakenCount which isn't restricted to just constants.
  SmallVector<const SCEV*, 4> ExitCounts;
  for (BasicBlock *ExitingBB : ExitingBlocks) {
    const SCEV *ExitCount =
        getExitCount(L, ExitingBB, ScalarEvolution::SymbolicMaximum);
    if (!isa<SCEVCouldNotCompute>(ExitCount)) {
      assert(DT.dominates(ExitingBB, L->getLoopLatch()) &&
             "We should only have known counts for exiting blocks that "
             "dominate latch!");
      ExitCounts.push_back(ExitCount);
    }
  }
  if (ExitCounts.empty())
    return getCouldNotCompute();
  return getUMinFromMismatchedTypes(ExitCounts, /*Sequential*/ true);
}

/// A rewriter to replace SCEV expressions in Map with the corresponding entry
/// in the map. It skips AddRecExpr because we cannot guarantee that the
/// replacement is loop invariant in the loop of the AddRec.
class SCEVLoopGuardRewriter : public SCEVRewriteVisitor<SCEVLoopGuardRewriter> {
  const DenseMap<const SCEV *, const SCEV *> &Map;

public:
  SCEVLoopGuardRewriter(ScalarEvolution &SE,
                        DenseMap<const SCEV *, const SCEV *> &M)
      : SCEVRewriteVisitor(SE), Map(M) {}

  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { return Expr; }

  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
    auto I = Map.find(Expr);
    if (I == Map.end())
      return Expr;
    return I->second;
  }

  const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
    auto I = Map.find(Expr);
    if (I == Map.end()) {
      // If we didn't find the extact ZExt expr in the map, check if there's an
      // entry for a smaller ZExt we can use instead.
      Type *Ty = Expr->getType();
      const SCEV *Op = Expr->getOperand(0);
      unsigned Bitwidth = Ty->getScalarSizeInBits() / 2;
      while (Bitwidth % 8 == 0 && Bitwidth >= 8 &&
             Bitwidth > Op->getType()->getScalarSizeInBits()) {
        Type *NarrowTy = IntegerType::get(SE.getContext(), Bitwidth);
        auto *NarrowExt = SE.getZeroExtendExpr(Op, NarrowTy);
        auto I = Map.find(NarrowExt);
        if (I != Map.end())
          return SE.getZeroExtendExpr(I->second, Ty);
        Bitwidth = Bitwidth / 2;
      }

      return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitZeroExtendExpr(
          Expr);
    }
    return I->second;
  }

  const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
    auto I = Map.find(Expr);
    if (I == Map.end())
      return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSignExtendExpr(
          Expr);
    return I->second;
  }

  const SCEV *visitUMinExpr(const SCEVUMinExpr *Expr) {
    auto I = Map.find(Expr);
    if (I == Map.end())
      return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitUMinExpr(Expr);
    return I->second;
  }

  const SCEV *visitSMinExpr(const SCEVSMinExpr *Expr) {
    auto I = Map.find(Expr);
    if (I == Map.end())
      return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSMinExpr(Expr);
    return I->second;
  }
};

const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
  SmallVector<const SCEV *> ExprsToRewrite;
  auto CollectCondition = [&](ICmpInst::Predicate Predicate, const SCEV *LHS,
                              const SCEV *RHS,
                              DenseMap<const SCEV *, const SCEV *>
                                  &RewriteMap) {
    // WARNING: It is generally unsound to apply any wrap flags to the proposed
    // replacement SCEV which isn't directly implied by the structure of that
    // SCEV.  In particular, using contextual facts to imply flags is *NOT*
    // legal.  See the scoping rules for flags in the header to understand why.

    // If LHS is a constant, apply information to the other expression.
    if (isa<SCEVConstant>(LHS)) {
      std::swap(LHS, RHS);
      Predicate = CmpInst::getSwappedPredicate(Predicate);
    }

    // Check for a condition of the form (-C1 + X < C2).  InstCombine will
    // create this form when combining two checks of the form (X u< C2 + C1) and
    // (X >=u C1).
    auto MatchRangeCheckIdiom = [this, Predicate, LHS, RHS, &RewriteMap,
                                 &ExprsToRewrite]() {
      auto *AddExpr = dyn_cast<SCEVAddExpr>(LHS);
      if (!AddExpr || AddExpr->getNumOperands() != 2)
        return false;

      auto *C1 = dyn_cast<SCEVConstant>(AddExpr->getOperand(0));
      auto *LHSUnknown = dyn_cast<SCEVUnknown>(AddExpr->getOperand(1));
      auto *C2 = dyn_cast<SCEVConstant>(RHS);
      if (!C1 || !C2 || !LHSUnknown)
        return false;

      auto ExactRegion =
          ConstantRange::makeExactICmpRegion(Predicate, C2->getAPInt())
              .sub(C1->getAPInt());

      // Bail out, unless we have a non-wrapping, monotonic range.
      if (ExactRegion.isWrappedSet() || ExactRegion.isFullSet())
        return false;
      auto I = RewriteMap.find(LHSUnknown);
      const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : LHSUnknown;
      RewriteMap[LHSUnknown] = getUMaxExpr(
          getConstant(ExactRegion.getUnsignedMin()),
          getUMinExpr(RewrittenLHS, getConstant(ExactRegion.getUnsignedMax())));
      ExprsToRewrite.push_back(LHSUnknown);
      return true;
    };
    if (MatchRangeCheckIdiom())
      return;

    // Return true if \p Expr is a MinMax SCEV expression with a non-negative
    // constant operand. If so, return in \p SCTy the SCEV type and in \p RHS
    // the non-constant operand and in \p LHS the constant operand.
    auto IsMinMaxSCEVWithNonNegativeConstant =
        [&](const SCEV *Expr, SCEVTypes &SCTy, const SCEV *&LHS,
            const SCEV *&RHS) {
          if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr)) {
            if (MinMax->getNumOperands() != 2)
              return false;
            if (auto *C = dyn_cast<SCEVConstant>(MinMax->getOperand(0))) {
              if (C->getAPInt().isNegative())
                return false;
              SCTy = MinMax->getSCEVType();
              LHS = MinMax->getOperand(0);
              RHS = MinMax->getOperand(1);
              return true;
            }
          }
          return false;
        };

    // Checks whether Expr is a non-negative constant, and Divisor is a positive
    // constant, and returns their APInt in ExprVal and in DivisorVal.
    auto GetNonNegExprAndPosDivisor = [&](const SCEV *Expr, const SCEV *Divisor,
                                          APInt &ExprVal, APInt &DivisorVal) {
      auto *ConstExpr = dyn_cast<SCEVConstant>(Expr);
      auto *ConstDivisor = dyn_cast<SCEVConstant>(Divisor);
      if (!ConstExpr || !ConstDivisor)
        return false;
      ExprVal = ConstExpr->getAPInt();
      DivisorVal = ConstDivisor->getAPInt();
      return ExprVal.isNonNegative() && !DivisorVal.isNonPositive();
    };

    // Return a new SCEV that modifies \p Expr to the closest number divides by
    // \p Divisor and greater or equal than Expr.
    // For now, only handle constant Expr and Divisor.
    auto GetNextSCEVDividesByDivisor = [&](const SCEV *Expr,
                                           const SCEV *Divisor) {
      APInt ExprVal;
      APInt DivisorVal;
      if (!GetNonNegExprAndPosDivisor(Expr, Divisor, ExprVal, DivisorVal))
        return Expr;
      APInt Rem = ExprVal.urem(DivisorVal);
      if (!Rem.isZero())
        // return the SCEV: Expr + Divisor - Expr % Divisor
        return getConstant(ExprVal + DivisorVal - Rem);
      return Expr;
    };

    // Return a new SCEV that modifies \p Expr to the closest number divides by
    // \p Divisor and less or equal than Expr.
    // For now, only handle constant Expr and Divisor.
    auto GetPreviousSCEVDividesByDivisor = [&](const SCEV *Expr,
                                               const SCEV *Divisor) {
      APInt ExprVal;
      APInt DivisorVal;
      if (!GetNonNegExprAndPosDivisor(Expr, Divisor, ExprVal, DivisorVal))
        return Expr;
      APInt Rem = ExprVal.urem(DivisorVal);
      // return the SCEV: Expr - Expr % Divisor
      return getConstant(ExprVal - Rem);
    };

    // Apply divisibilty by \p Divisor on MinMaxExpr with constant values,
    // recursively. This is done by aligning up/down the constant value to the
    // Divisor.
    std::function<const SCEV *(const SCEV *, const SCEV *)>
        ApplyDivisibiltyOnMinMaxExpr = [&](const SCEV *MinMaxExpr,
                                           const SCEV *Divisor) {
          const SCEV *MinMaxLHS = nullptr, *MinMaxRHS = nullptr;
          SCEVTypes SCTy;
          if (!IsMinMaxSCEVWithNonNegativeConstant(MinMaxExpr, SCTy, MinMaxLHS,
                                                   MinMaxRHS))
            return MinMaxExpr;
          auto IsMin =
              isa<SCEVSMinExpr>(MinMaxExpr) || isa<SCEVUMinExpr>(MinMaxExpr);
          assert(isKnownNonNegative(MinMaxLHS) &&
                 "Expected non-negative operand!");
          auto *DivisibleExpr =
              IsMin ? GetPreviousSCEVDividesByDivisor(MinMaxLHS, Divisor)
                    : GetNextSCEVDividesByDivisor(MinMaxLHS, Divisor);
          SmallVector<const SCEV *> Ops = {
              ApplyDivisibiltyOnMinMaxExpr(MinMaxRHS, Divisor), DivisibleExpr};
          return getMinMaxExpr(SCTy, Ops);
        };

    // If we have LHS == 0, check if LHS is computing a property of some unknown
    // SCEV %v which we can rewrite %v to express explicitly.
    const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS);
    if (Predicate == CmpInst::ICMP_EQ && RHSC &&
        RHSC->getValue()->isNullValue()) {
      // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to
      // explicitly express that.
      const SCEV *URemLHS = nullptr;
      const SCEV *URemRHS = nullptr;
      if (matchURem(LHS, URemLHS, URemRHS)) {
        if (const SCEVUnknown *LHSUnknown = dyn_cast<SCEVUnknown>(URemLHS)) {
          auto I = RewriteMap.find(LHSUnknown);
          const SCEV *RewrittenLHS =
              I != RewriteMap.end() ? I->second : LHSUnknown;
          RewrittenLHS = ApplyDivisibiltyOnMinMaxExpr(RewrittenLHS, URemRHS);
          const auto *Multiple =
              getMulExpr(getUDivExpr(RewrittenLHS, URemRHS), URemRHS);
          RewriteMap[LHSUnknown] = Multiple;
          ExprsToRewrite.push_back(LHSUnknown);
          return;
        }
      }
    }

    // Do not apply information for constants or if RHS contains an AddRec.
    if (isa<SCEVConstant>(LHS) || containsAddRecurrence(RHS))
      return;

    // If RHS is SCEVUnknown, make sure the information is applied to it.
    if (!isa<SCEVUnknown>(LHS) && isa<SCEVUnknown>(RHS)) {
      std::swap(LHS, RHS);
      Predicate = CmpInst::getSwappedPredicate(Predicate);
    }

    // Puts rewrite rule \p From -> \p To into the rewrite map. Also if \p From
    // and \p FromRewritten are the same (i.e. there has been no rewrite
    // registered for \p From), then puts this value in the list of rewritten
    // expressions.
    auto AddRewrite = [&](const SCEV *From, const SCEV *FromRewritten,
                          const SCEV *To) {
      if (From == FromRewritten)
        ExprsToRewrite.push_back(From);
      RewriteMap[From] = To;
    };

    // Checks whether \p S has already been rewritten. In that case returns the
    // existing rewrite because we want to chain further rewrites onto the
    // already rewritten value. Otherwise returns \p S.
    auto GetMaybeRewritten = [&](const SCEV *S) {
      auto I = RewriteMap.find(S);
      return I != RewriteMap.end() ? I->second : S;
    };

    // Check for the SCEV expression (A /u B) * B while B is a constant, inside
    // \p Expr. The check is done recuresively on \p Expr, which is assumed to
    // be a composition of Min/Max SCEVs. Return whether the SCEV expression (A
    // /u B) * B was found, and return the divisor B in \p DividesBy. For
    // example, if Expr = umin (umax ((A /u 8) * 8, 16), 64), return true since
    // (A /u 8) * 8 matched the pattern, and return the constant SCEV 8 in \p
    // DividesBy.
    std::function<bool(const SCEV *, const SCEV *&)> HasDivisibiltyInfo =
        [&](const SCEV *Expr, const SCEV *&DividesBy) {
          if (auto *Mul = dyn_cast<SCEVMulExpr>(Expr)) {
            if (Mul->getNumOperands() != 2)
              return false;
            auto *MulLHS = Mul->getOperand(0);
            auto *MulRHS = Mul->getOperand(1);
            if (isa<SCEVConstant>(MulLHS))
              std::swap(MulLHS, MulRHS);
            if (auto *Div = dyn_cast<SCEVUDivExpr>(MulLHS))
              if (Div->getOperand(1) == MulRHS) {
                DividesBy = MulRHS;
                return true;
              }
          }
          if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr))
            return HasDivisibiltyInfo(MinMax->getOperand(0), DividesBy) ||
                   HasDivisibiltyInfo(MinMax->getOperand(1), DividesBy);
          return false;
        };

    // Return true if Expr known to divide by \p DividesBy.
    std::function<bool(const SCEV *, const SCEV *&)> IsKnownToDivideBy =
        [&](const SCEV *Expr, const SCEV *DividesBy) {
          if (getURemExpr(Expr, DividesBy)->isZero())
            return true;
          if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr))
            return IsKnownToDivideBy(MinMax->getOperand(0), DividesBy) &&
                   IsKnownToDivideBy(MinMax->getOperand(1), DividesBy);
          return false;
        };

    const SCEV *RewrittenLHS = GetMaybeRewritten(LHS);
    const SCEV *DividesBy = nullptr;
    if (HasDivisibiltyInfo(RewrittenLHS, DividesBy))
      // Check that the whole expression is divided by DividesBy
      DividesBy =
          IsKnownToDivideBy(RewrittenLHS, DividesBy) ? DividesBy : nullptr;

    // Collect rewrites for LHS and its transitive operands based on the
    // condition.
    // For min/max expressions, also apply the guard to its operands:
    //  'min(a, b) >= c'   ->   '(a >= c) and (b >= c)',
    //  'min(a, b) >  c'   ->   '(a >  c) and (b >  c)',
    //  'max(a, b) <= c'   ->   '(a <= c) and (b <= c)',
    //  'max(a, b) <  c'   ->   '(a <  c) and (b <  c)'.

    // We cannot express strict predicates in SCEV, so instead we replace them
    // with non-strict ones against plus or minus one of RHS depending on the
    // predicate.
    const SCEV *One = getOne(RHS->getType());
    switch (Predicate) {
      case CmpInst::ICMP_ULT:
        if (RHS->getType()->isPointerTy())
          return;
        RHS = getUMaxExpr(RHS, One);
        [[fallthrough]];
      case CmpInst::ICMP_SLT: {
        RHS = getMinusSCEV(RHS, One);
        RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
        break;
      }
      case CmpInst::ICMP_UGT:
      case CmpInst::ICMP_SGT:
        RHS = getAddExpr(RHS, One);
        RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
        break;
      case CmpInst::ICMP_ULE:
      case CmpInst::ICMP_SLE:
        RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
        break;
      case CmpInst::ICMP_UGE:
      case CmpInst::ICMP_SGE:
        RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
        break;
      default:
        break;
    }

    SmallVector<const SCEV *, 16> Worklist(1, LHS);
    SmallPtrSet<const SCEV *, 16> Visited;

    auto EnqueueOperands = [&Worklist](const SCEVNAryExpr *S) {
      append_range(Worklist, S->operands());
    };

    while (!Worklist.empty()) {
      const SCEV *From = Worklist.pop_back_val();
      if (isa<SCEVConstant>(From))
        continue;
      if (!Visited.insert(From).second)
        continue;
      const SCEV *FromRewritten = GetMaybeRewritten(From);
      const SCEV *To = nullptr;

      switch (Predicate) {
      case CmpInst::ICMP_ULT:
      case CmpInst::ICMP_ULE:
        To = getUMinExpr(FromRewritten, RHS);
        if (auto *UMax = dyn_cast<SCEVUMaxExpr>(FromRewritten))
          EnqueueOperands(UMax);
        break;
      case CmpInst::ICMP_SLT:
      case CmpInst::ICMP_SLE:
        To = getSMinExpr(FromRewritten, RHS);
        if (auto *SMax = dyn_cast<SCEVSMaxExpr>(FromRewritten))
          EnqueueOperands(SMax);
        break;
      case CmpInst::ICMP_UGT:
      case CmpInst::ICMP_UGE:
        To = getUMaxExpr(FromRewritten, RHS);
        if (auto *UMin = dyn_cast<SCEVUMinExpr>(FromRewritten))
          EnqueueOperands(UMin);
        break;
      case CmpInst::ICMP_SGT:
      case CmpInst::ICMP_SGE:
        To = getSMaxExpr(FromRewritten, RHS);
        if (auto *SMin = dyn_cast<SCEVSMinExpr>(FromRewritten))
          EnqueueOperands(SMin);
        break;
      case CmpInst::ICMP_EQ:
        if (isa<SCEVConstant>(RHS))
          To = RHS;
        break;
      case CmpInst::ICMP_NE:
        if (isa<SCEVConstant>(RHS) &&
            cast<SCEVConstant>(RHS)->getValue()->isNullValue()) {
          const SCEV *OneAlignedUp =
              DividesBy ? GetNextSCEVDividesByDivisor(One, DividesBy) : One;
          To = getUMaxExpr(FromRewritten, OneAlignedUp);
        }
        break;
      default:
        break;
      }

      if (To)
        AddRewrite(From, FromRewritten, To);
    }
  };

  BasicBlock *Header = L->getHeader();
  SmallVector<PointerIntPair<Value *, 1, bool>> Terms;
  // First, collect information from assumptions dominating the loop.
  for (auto &AssumeVH : AC.assumptions()) {
    if (!AssumeVH)
      continue;
    auto *AssumeI = cast<CallInst>(AssumeVH);
    if (!DT.dominates(AssumeI, Header))
      continue;
    Terms.emplace_back(AssumeI->getOperand(0), true);
  }

  // Second, collect information from llvm.experimental.guards dominating the loop.
  auto *GuardDecl = F.getParent()->getFunction(
      Intrinsic::getName(Intrinsic::experimental_guard));
  if (GuardDecl)
    for (const auto *GU : GuardDecl->users())
      if (const auto *Guard = dyn_cast<IntrinsicInst>(GU))
        if (Guard->getFunction() == Header->getParent() && DT.dominates(Guard, Header))
          Terms.emplace_back(Guard->getArgOperand(0), true);

  // Third, collect conditions from dominating branches. Starting at the loop
  // predecessor, climb up the predecessor chain, as long as there are
  // predecessors that can be found that have unique successors leading to the
  // original header.
  // TODO: share this logic with isLoopEntryGuardedByCond.
  for (std::pair<const BasicBlock *, const BasicBlock *> Pair(
           L->getLoopPredecessor(), Header);
       Pair.first; Pair = getPredecessorWithUniqueSuccessorForBB(Pair.first)) {

    const BranchInst *LoopEntryPredicate =
        dyn_cast<BranchInst>(Pair.first->getTerminator());
    if (!LoopEntryPredicate || LoopEntryPredicate->isUnconditional())
      continue;

    Terms.emplace_back(LoopEntryPredicate->getCondition(),
                       LoopEntryPredicate->getSuccessor(0) == Pair.second);
  }

  // Now apply the information from the collected conditions to RewriteMap.
  // Conditions are processed in reverse order, so the earliest conditions is
  // processed first. This ensures the SCEVs with the shortest dependency chains
  // are constructed first.
  DenseMap<const SCEV *, const SCEV *> RewriteMap;
  for (auto [Term, EnterIfTrue] : reverse(Terms)) {
    SmallVector<Value *, 8> Worklist;
    SmallPtrSet<Value *, 8> Visited;
    Worklist.push_back(Term);
    while (!Worklist.empty()) {
      Value *Cond = Worklist.pop_back_val();
      if (!Visited.insert(Cond).second)
        continue;

      if (auto *Cmp = dyn_cast<ICmpInst>(Cond)) {
        auto Predicate =
            EnterIfTrue ? Cmp->getPredicate() : Cmp->getInversePredicate();
        const auto *LHS = getSCEV(Cmp->getOperand(0));
        const auto *RHS = getSCEV(Cmp->getOperand(1));
        CollectCondition(Predicate, LHS, RHS, RewriteMap);
        continue;
      }

      Value *L, *R;
      if (EnterIfTrue ? match(Cond, m_LogicalAnd(m_Value(L), m_Value(R)))
                      : match(Cond, m_LogicalOr(m_Value(L), m_Value(R)))) {
        Worklist.push_back(L);
        Worklist.push_back(R);
      }
    }
  }

  if (RewriteMap.empty())
    return Expr;

  // Now that all rewrite information is collect, rewrite the collected
  // expressions with the information in the map. This applies information to
  // sub-expressions.
  if (ExprsToRewrite.size() > 1) {
    for (const SCEV *Expr : ExprsToRewrite) {
      const SCEV *RewriteTo = RewriteMap[Expr];
      RewriteMap.erase(Expr);
      SCEVLoopGuardRewriter Rewriter(*this, RewriteMap);
      RewriteMap.insert({Expr, Rewriter.visit(RewriteTo)});
    }
  }

  SCEVLoopGuardRewriter Rewriter(*this, RewriteMap);
  return Rewriter.visit(Expr);
}
