//===- LoopAccessAnalysis.cpp - Loop Access Analysis Implementation --------==//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The implementation for the loop memory dependence that was originally
// developed for the loop vectorizer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/ScalarEvolutionPatternMatch.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <utility>
#include <variant>
#include <vector>

using namespace llvm;
using namespace llvm::SCEVPatternMatch;

#define DEBUG_TYPE "loop-accesses"

static cl::opt<ElementCount, true>
    VectorizationFactor("force-vector-width", cl::Hidden,
                        cl::desc("Sets the SIMD width. Zero is autoselect."),
                        cl::location(VectorizerParams::VectorizationFactor));
ElementCount VectorizerParams::VectorizationFactor;

static cl::opt<unsigned, true>
VectorizationInterleave("force-vector-interleave", cl::Hidden,
                        cl::desc("Sets the vectorization interleave count. "
                                 "Zero is autoselect."),
                        cl::location(
                            VectorizerParams::VectorizationInterleave));
unsigned VectorizerParams::VectorizationInterleave;

static cl::opt<unsigned, true> RuntimeMemoryCheckThreshold(
    "runtime-memory-check-threshold", cl::Hidden,
    cl::desc("When performing memory disambiguation checks at runtime do not "
             "generate more than this number of comparisons (default = 8)."),
    cl::location(VectorizerParams::RuntimeMemoryCheckThreshold), cl::init(8));
unsigned VectorizerParams::RuntimeMemoryCheckThreshold;

static cl::opt<unsigned, true> VectorizeMemoryCheckThreshold(
    "vectorize-memory-check-threshold", cl::Hidden,
    cl::desc("The maximum allowed number of runtime memory checks"),
    cl::location(VectorizerParams::VectorizeMemoryCheckThreshold),
    cl::init(128));
unsigned VectorizerParams::VectorizeMemoryCheckThreshold;

/// The maximum iterations used to merge memory checks
static cl::opt<unsigned> MemoryCheckMergeThreshold(
    "memory-check-merge-threshold", cl::Hidden,
    cl::desc("Maximum number of comparisons done when trying to merge "
             "runtime memory checks. (default = 100)"),
    cl::init(100));

enum class StencilMergePolicy { Off, Auto, Force };

static cl::opt<StencilMergePolicy> StencilMerge(
    "stencil-runtime-check-merge", cl::Hidden,
    cl::desc("Control stencil-pattern merging of runtime memory checks"),
    cl::init(StencilMergePolicy::Off),
    cl::values(
        clEnumValN(StencilMergePolicy::Off, "off",
                   "Disable stencil merge (default)"),
        clEnumValN(StencilMergePolicy::Auto, "auto",
                   "Enable stencil merge when runtime check count exceeds "
                   "-vectorize-memory-check-threshold"),
        clEnumValN(StencilMergePolicy::Force, "force",
                   "Always attempt stencil merge regardless of check "
                   "count")));

static cl::opt<unsigned> StencilMergeMaxGroups(
    "stencil-merge-max-groups", cl::Hidden,
    cl::desc(
        "Skip stencil group merging when the number of runtime checking groups "
        "exceeds this limit, to bound compile time (default =4096)."),
    cl::init(4096));

/// Maximum SIMD width.
const unsigned VectorizerParams::MaxVectorWidth = 64;

/// We collect dependences up to this threshold.
static cl::opt<unsigned>
    MaxDependences("max-dependences", cl::Hidden,
                   cl::desc("Maximum number of dependences collected by "
                            "loop-access analysis (default = 100)"),
                   cl::init(100));

/// This enables versioning on the strides of symbolically striding memory
/// accesses in code like the following.
///   for (i = 0; i < N; ++i)
///     A[i * Stride1] += B[i * Stride2] ...
///
/// Will be roughly translated to
///    if (Stride1 == 1 && Stride2 == 1) {
///      for (i = 0; i < N; i+=4)
///       A[i:i+3] += ...
///    } else
///      ...
static cl::opt<bool> EnableMemAccessVersioning(
    "enable-mem-access-versioning", cl::init(true), cl::Hidden,
    cl::desc("Enable symbolic stride memory access versioning"));

/// Enable store-to-load forwarding conflict detection. This option can
/// be disabled for correctness testing.
static cl::opt<bool> EnableForwardingConflictDetection(
    "store-to-load-forwarding-conflict-detection", cl::Hidden,
    cl::desc("Enable conflict detection in loop-access analysis"),
    cl::init(true));

static cl::opt<unsigned> MaxForkedSCEVDepth(
    "max-forked-scev-depth", cl::Hidden,
    cl::desc("Maximum recursion depth when finding forked SCEVs (default = 5)"),
    cl::init(5));

static cl::opt<bool> SpeculateUnitStride(
    "laa-speculate-unit-stride", cl::Hidden,
    cl::desc("Speculate that non-constant strides are unit in LAA"),
    cl::init(true));

static cl::opt<bool, true> HoistRuntimeChecks(
    "hoist-runtime-checks", cl::Hidden,
    cl::desc(
        "Hoist inner loop runtime memory checks to outer loop if possible"),
    cl::location(VectorizerParams::HoistRuntimeChecks), cl::init(true));
bool VectorizerParams::HoistRuntimeChecks;

bool VectorizerParams::isInterleaveForced() {
  return ::VectorizationInterleave.getNumOccurrences() > 0;
}

const SCEV *llvm::replaceSymbolicStrideSCEV(
    PredicatedScalarEvolution &PSE, const Loop *Lp,
    const SymbolicStrideMap &PtrToStride, Value *Ptr,
    SmallVectorImpl<const SCEVPredicate *> *Predicates) {
  const SCEV *OrigSCEV = PSE.getSCEV(Ptr);

  // If there is an entry in the map return the SCEV of the pointer with the
  // symbolic stride replaced by one.
  const SCEVUnknown *StrideSCEV = PtrToStride.lookup(Ptr);
  if (!StrideSCEV)
    // For a non-symbolic stride, just return the original expression.
    return OrigSCEV;

  ScalarEvolution *SE = PSE.getSE();
  const SCEV *CT = SE->getOne(StrideSCEV->getType());
  const SCEV *Expr;
  const SCEVPredicate *EqPred = SE->getEqualPredicate(StrideSCEV, CT);
  if (Predicates) {
    Predicates->push_back(EqPred);
    Expr = SE->rewriteUsingPredicate(OrigSCEV, Lp,
                                     SCEVUnionPredicate(*Predicates, *SE));
  } else {
    PSE.addPredicate(*EqPred);
    Expr = PSE.getSCEV(Ptr);
  }
  LLVM_DEBUG(dbgs() << "LAA: Replacing SCEV: " << *OrigSCEV << " by: " << *Expr
                    << "\n");
  return Expr;
}

RuntimeCheckingPtrGroup::RuntimeCheckingPtrGroup(
    unsigned Index, const RuntimePointerChecking &RtCheck)
    : High(RtCheck.Pointers[Index].End), Low(RtCheck.Pointers[Index].Start),
      AddressSpace(RtCheck.Pointers[Index]
                       .PointerValue->getType()
                       ->getPointerAddressSpace()),
      NeedsFreeze(RtCheck.Pointers[Index].NeedsFreeze) {
  Members.push_back(Index);
}

/// Returns \p A + \p B, if it is guaranteed not to unsigned wrap. Otherwise
/// return nullptr. \p A and \p B must have the same type.
static const SCEV *addSCEVNoOverflow(const SCEV *A, const SCEV *B,
                                     ScalarEvolution &SE) {
  if (!SE.willNotOverflow(Instruction::Add, /*IsSigned=*/false, A, B))
    return nullptr;
  return SE.getAddExpr(A, B);
}

/// Returns \p A * \p B, if it is guaranteed not to unsigned wrap. Otherwise
/// return nullptr. \p A and \p B must have the same type.
static const SCEV *mulSCEVNoOverflow(const SCEV *A, const SCEV *B,
                                     ScalarEvolution &SE) {
  if (!SE.willNotOverflow(Instruction::Mul, /*IsSigned=*/false, A, B))
    return nullptr;
  return SE.getMulExpr(A, B);
}

/// Return true, if evaluating \p AR at \p MaxBTC cannot wrap, because \p AR at
/// \p MaxBTC is guaranteed inbounds of the accessed object.
static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(
    const SCEVAddRecExpr *AR, const SCEV *MaxBTC, const SCEV *EltSize,
    ScalarEvolution &SE, const DataLayout &DL, DominatorTree *DT,
    AssumptionCache *AC, ScalarEvolution::LoopGuards &LoopGuards) {
  auto *PointerBase = SE.getPointerBase(AR->getStart());
  auto *StartPtr = dyn_cast<SCEVUnknown>(PointerBase);
  if (!StartPtr)
    return false;
  const Loop *L = AR->getLoop();
  bool CheckForNonNull;
  Value *StartPtrV = StartPtr->getValue();
  // We can ignore frees, as the fact that an object of a certain size existed
  // at the location *at some point* is sufficient to derive the nowrap fact.
  uint64_t DerefBytes = StartPtrV->getPointerDereferenceableBytes(
      DL, CheckForNonNull, /*CanBeFreed=*/nullptr);

  // If the deref size is only known when the pointer is non-null, ignore it
  // here and fall back to a dereferenceable assumption below.
  if (DerefBytes && CheckForNonNull)
    DerefBytes = 0;

  const SCEV *Step = AR->getStepRecurrence(SE);
  Type *WiderTy = SE.getWiderType(MaxBTC->getType(), Step->getType());
  const SCEV *DerefBytesSCEV = SE.getConstant(WiderTy, DerefBytes);

  // Check if we have a suitable dereferencable assumption we can use.
  Instruction *CtxI = &*L->getHeader()->getFirstNonPHIIt();
  if (BasicBlock *LoopPred = L->getLoopPredecessor()) {
    if (isa<UncondBrInst, CondBrInst>(LoopPred->getTerminator()))
      CtxI = LoopPred->getTerminator();
  }
  getKnowledgeForValue(
      StartPtrV, Attribute::Dereferenceable, *AC,
      [&](RetainedKnowledge RK, Instruction *Assume, auto) {
        if (!isValidAssumeForContext(Assume, CtxI, DT))
          return false;
        const SCEV *DerefRKSCEV = SE.getSCEV(RK.IRArgValue);
        Type *CommonTy =
            SE.getWiderType(DerefBytesSCEV->getType(), DerefRKSCEV->getType());
        DerefBytesSCEV = SE.getNoopOrZeroExtend(DerefBytesSCEV, CommonTy);
        DerefRKSCEV = SE.getNoopOrZeroExtend(DerefRKSCEV, CommonTy);
        DerefBytesSCEV = SE.getUMaxExpr(DerefBytesSCEV, DerefRKSCEV);
        // Continue with other assumptions.
        return false;
      });

  if (DerefBytesSCEV->isZero())
    return false;

  bool IsKnownNonNegative = SE.isKnownNonNegative(Step);
  if (!IsKnownNonNegative && !SE.isKnownNegative(Step))
    return false;

  WiderTy = SE.getWiderType(WiderTy, DerefBytesSCEV->getType());
  Step = SE.getNoopOrSignExtend(Step, WiderTy);
  MaxBTC = SE.getNoopOrZeroExtend(MaxBTC, WiderTy);

  // For the computations below, make sure they don't unsigned wrap.
  // FIXME: for a negative step the lowest accessed address is not
  // AR->getStart() but AR->evaluateAtIteration(MaxBTC, SE); the check below
  // therefore compares StartPtr against the highest accessed address instead
  // of the lowest.
  if (!SE.isKnownPredicate(CmpInst::ICMP_UGE, AR->getStart(), StartPtr))
    return false;
  const SCEV *StartOffset = SE.getNoopOrZeroExtend(
      SE.getMinusSCEV(AR->getStart(), StartPtr), WiderTy);

  MaxBTC = SE.applyLoopGuards(MaxBTC, LoopGuards);

  const SCEV *AbsStep = SE.getAbsExpr(Step, /*IsNSW=*/false);
  // Total distance (in bytes) between the first and the last
  // accessed pointer.
  const SCEV *DistToLastIter = mulSCEVNoOverflow(MaxBTC, AbsStep, SE);
  if (!DistToLastIter) {
    // Re-try with constant max backedge-taken count if using the symbolic one
    // failed.
    MaxBTC = SE.getConstantMaxBackedgeTakenCount(AR->getLoop());
    if (isa<SCEVCouldNotCompute>(MaxBTC))
      return false;
    MaxBTC = SE.getNoopOrZeroExtend(MaxBTC, WiderTy);
    DistToLastIter = mulSCEVNoOverflow(MaxBTC, AbsStep, SE);
    if (!DistToLastIter)
      return false;
  }

  // Total length in bytes of the accessed range (from the first accessed
  // byte through the end of the last access).
  const SCEV *AccessedBytes = addSCEVNoOverflow(
      DistToLastIter, SE.getNoopOrZeroExtend(EltSize, WiderTy), SE);
  if (!AccessedBytes)
    return false;

  // Compute MaxOffset per direction: exclusive upper offset of the
  // accessed range.
  const SCEV *MaxOffset;
  if (IsKnownNonNegative) {
    MaxOffset = addSCEVNoOverflow(StartOffset, AccessedBytes, SE);
    if (!MaxOffset)
      return false;
    DerefBytesSCEV = SE.applyLoopGuards(DerefBytesSCEV, LoopGuards);
  } else {
    // FIXME: two independent off-by-EltSize bugs on this branch:
    //  1. StartOffset here is actually the HIGHEST offset, because it is
    //     computed from AR->getStart() rather than
    //     AR->evaluateAtIteration(MaxBTC, SE) (see FIXME above).
    //  2. The lower check is over-strict by EltSize and the upper is
    //     under-counted by EltSize.
    assert(SE.isKnownNegative(Step) && "must be known negative");
    if (!SE.isKnownPredicate(CmpInst::ICMP_SGE, StartOffset, AccessedBytes))
      return false;
    MaxOffset = StartOffset;
  }
  // MaxOffset must not exceed the deref-region end.
  return SE.isKnownPredicate(CmpInst::ICMP_ULE, MaxOffset, DerefBytesSCEV);
}

/// Return true if \p S is known to be monotonically non-decreasing
/// (in the unsigned sense, without unsigned wrap) across iterations of \p L.
static bool isKnownNonDecreasingInLoop(const SCEV *S, const Loop *L,
                                       ScalarEvolution &SE) {
  if (SE.isLoopInvariant(S, L))
    return true;

  switch (S->getSCEVType()) {
  case scUDivExpr: {
    // Non-decreasing in the numerator when the divisor is loop-invariant.
    const auto *UDiv = cast<SCEVUDivExpr>(S);
    return SE.isLoopInvariant(UDiv->getRHS(), L) &&
           isKnownNonDecreasingInLoop(UDiv->getLHS(), L, SE);
  }
  case scAddRecExpr: {
    auto *AR = cast<SCEVAddRecExpr>(S);
    assert(AR->getLoop() == L &&
           "trying to check for AddRec in different loop");
    return SE.getMonotonicPredicateType(AR, ICmpInst::ICMP_UGE) ==
           ScalarEvolution::MonotonicPredicateType::MonotonicallyIncreasing;
  }
  case scAddExpr:
  case scMulExpr: {
    const auto *NAry = cast<SCEVNAryExpr>(S);
    if (!NAry->hasNoUnsignedWrap())
      return false;
    // With NUW, the exact sum or product fits in the type, so it is
    // non-decreasing if every operandis.
    return all_of(NAry->operands(), [&](const SCEV *Op) {
      return isKnownNonDecreasingInLoop(Op, L, SE);
    });
  }
  default:
    return false;
  }
}

/// Try to bound a loop-variant pointer that is not an affine AddRec.
///
/// If the offset is provably monotonically non-decreasing the accessed range is
/// bounded by the offset's value at the first iteration (via
/// SplitIntoInitAndPostInc) and last iteration (via getSCEVAtScope). The
/// returned range is half-open: \p EltSizeSCEV is added to the address of the
/// last accessed element to form the end.
///
/// Returns {nullptr, nullptr} if no such bound can be formed.
static std::pair<const SCEV *, const SCEV *>
getNonAffineMonotonicBounds(const Loop *Lp, const SCEV *PtrExpr,
                            const SCEV *EltSizeSCEV, ScalarEvolution *SE) {
  const auto *PtrAdd = dyn_cast<SCEVAddExpr>(PtrExpr);
  if (!PtrAdd || !PtrAdd->hasNoUnsignedWrap())
    return {nullptr, nullptr};

  const SCEV *Base = *find_if(PtrAdd->operands(), [](const auto &Op) {
    return Op->getType()->isPointerTy();
  });
  if (isa<SCEVCouldNotCompute>(Base) || !SE->isLoopInvariant(Base, Lp))
    return {nullptr, nullptr};

  const SCEV *Offset = SE->getMinusSCEV(PtrExpr, Base);
  if (isa<SCEVCouldNotCompute>(Offset) ||
      !isKnownNonDecreasingInLoop(Offset, Lp, *SE))
    return {nullptr, nullptr};

  const SCEV *OffStart = SE->SplitIntoInitAndPostInc(Lp, Offset).first;
  const SCEV *OffEnd = SE->getSCEVAtScope(Offset, Lp->getParentLoop());
  if (isa<SCEVCouldNotCompute>(OffStart) || isa<SCEVCouldNotCompute>(OffEnd) ||
      !SE->isLoopInvariant(OffStart, Lp) || !SE->isLoopInvariant(OffEnd, Lp))
    return {nullptr, nullptr};

  return {SE->getAddExpr(Base, OffStart),
          SE->getAddExpr(Base, OffEnd, EltSizeSCEV)};
}

std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
    const Loop *Lp, const SCEV *PtrExpr, Type *AccessTy, const SCEV *BTC,
    const SCEV *MaxBTC, ScalarEvolution *SE,
    DenseMap<std::pair<const SCEV *, const SCEV *>,
             std::pair<const SCEV *, const SCEV *>> *PointerBounds,
    DominatorTree *DT, AssumptionCache *AC,
    ScalarEvolution::LoopGuards &LoopGuards) {
  auto &DL = Lp->getHeader()->getDataLayout();
  Type *IdxTy = DL.getIndexType(PtrExpr->getType());
  const SCEV *EltSizeSCEV = SE->getStoreSizeOfExpr(IdxTy, AccessTy);

  // Delegate to the SCEV-based overload, passing through the cache.
  return getStartAndEndForAccess(Lp, PtrExpr, EltSizeSCEV, BTC, MaxBTC, SE,
                                 PointerBounds, DT, AC, LoopGuards);
}

std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
    const Loop *Lp, const SCEV *PtrExpr, const SCEV *EltSizeSCEV,
    const SCEV *BTC, const SCEV *MaxBTC, ScalarEvolution *SE,
    DenseMap<std::pair<const SCEV *, const SCEV *>,
             std::pair<const SCEV *, const SCEV *>> *PointerBounds,
    DominatorTree *DT, AssumptionCache *AC,
    ScalarEvolution::LoopGuards &LoopGuards) {
  std::pair<const SCEV *, const SCEV *> *PtrBoundsPair;
  if (PointerBounds) {
    auto [Iter, Ins] = PointerBounds->insert(
        {{PtrExpr, EltSizeSCEV},
         {SE->getCouldNotCompute(), SE->getCouldNotCompute()}});
    if (!Ins)
      return Iter->second;
    PtrBoundsPair = &Iter->second;
  }

  // ScStart is the lowest accessed address; ScEnd is the highest one plus the
  // size of the accessed element.
  const SCEV *ScStart;
  const SCEV *ScEnd;

  auto &DL = Lp->getHeader()->getDataLayout();
  if (SE->isLoopInvariant(PtrExpr, Lp)) {
    ScStart = PtrExpr;
    ScEnd = SE->getAddExpr(PtrExpr, EltSizeSCEV);
  } else if (auto *AR = dyn_cast<SCEVAddRecExpr>(PtrExpr)) {
    assert(AR->getLoop() == Lp && "LoopGuards must be the guards of Lp");
    const SCEV *Step = AR->getStepRecurrence(*SE);
    // The address of the last accessed element, if it can be computed
    // precisely.
    const SCEV *LastAddr = nullptr;
    if (!isa<SCEVCouldNotCompute>(BTC)) {
      // Evaluating AR at an exact BTC is safe: LAA separately checks that
      // accesses cannot wrap in the loop. If evaluating AR at BTC wraps, then
      // the loop either triggers UB when executing a memory access with a
      // poison pointer or the wrapping/poisoned pointer is not used.
      LastAddr = AR->evaluateAtIteration(BTC, *SE);
    } else if (evaluatePtrAddRecAtMaxBTCWillNotWrap(
                   AR, MaxBTC, EltSizeSCEV, *SE, DL, DT, AC, LoopGuards)) {
      LastAddr = AR->evaluateAtIteration(MaxBTC, *SE);
    }
    const SCEV *Start = AR->getStart();
    Type *PtrTy = AR->getType();
    if (SE->isKnownNegative(Step)) {
      ScStart =
          LastAddr
              ? LastAddr
              : SE->getSCEV(ConstantExpr::getIntToPtr(
                    Constant::getNullValue(DL.getIndexType(PtrTy)), PtrTy));
      ScEnd = SE->getAddExpr(Start, EltSizeSCEV);
    } else if (SE->isKnownNonNegative(Step)) {
      ScStart = Start;
      // The highest address for the type saturates; adding EltSize to it would
      // wrap to the start of the address space.
      if (LastAddr)
        ScEnd = SE->getAddExpr(LastAddr, EltSizeSCEV);
      else
        ScEnd = SE->getSCEV(ConstantExpr::getIntToPtr(
            Constant::getAllOnesValue(DL.getIndexType(PtrTy)), PtrTy));
    } else {
      if (!LastAddr)
        return {SE->getCouldNotCompute(), SE->getCouldNotCompute()};
      // Fallback case: the step is not constant, but we can still
      // get the upper and lower bounds of the interval by using min/max
      // expressions.
      ScStart = SE->getUMinExpr(Start, LastAddr);
      ScEnd = SE->getAddExpr(SE->getUMaxExpr(Start, LastAddr), EltSizeSCEV);
    }
  } else {
    // The pointer is loop-variant but not an affine AddRec. Try to form a
    // tight bound for a monotonic offset (see getNonAffineMonotonicBounds).
    std::tie(ScStart, ScEnd) =
        getNonAffineMonotonicBounds(Lp, PtrExpr, EltSizeSCEV, SE);
    if (!ScStart)
      return {SE->getCouldNotCompute(), SE->getCouldNotCompute()};
  }

  assert(SE->isLoopInvariant(ScStart, Lp) && "ScStart needs to be invariant");
  assert(SE->isLoopInvariant(ScEnd, Lp) && "ScEnd needs to be invariant");

  std::pair<const SCEV *, const SCEV *> Res = {ScStart, ScEnd};
  if (PointerBounds)
    *PtrBoundsPair = Res;
  return Res;
}

/// Calculate Start and End points of memory access using
/// getStartAndEndForAccess.
bool RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
                                    Type *AccessTy, bool WritePtr,
                                    unsigned DepSetId, unsigned ASId,
                                    PredicatedScalarEvolution &PSE,
                                    bool NeedsFreeze, bool IsForked) {
  const SCEV *SymbolicMaxBTC = PSE.getSymbolicMaxBackedgeTakenCount();
  const SCEV *BTC = PSE.getBackedgeTakenCount();
  const auto &[ScStart, ScEnd] = getStartAndEndForAccess(
      Lp, PtrExpr, AccessTy, BTC, SymbolicMaxBTC, PSE.getSE(),
      &DC.getPointerBounds(), DC.getDT(), DC.getAC(), LoopGuards);
  if (isa<SCEVCouldNotCompute>(ScStart) || isa<SCEVCouldNotCompute>(ScEnd))
    return false;
  Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, PtrExpr,
                        NeedsFreeze, IsForked);
  return true;
}

bool RuntimePointerChecking::tryToCreateDiffCheck(
    const RuntimeCheckingPtrGroup &CGI, const RuntimeCheckingPtrGroup &CGJ) {
  // If either group contains multiple different pointers, bail out.
  // TODO: Support multiple pointers by using the minimum or maximum pointer,
  // depending on src & sink.
  if (CGI.Members.size() != 1 || CGJ.Members.size() != 1)
    return false;

  const PointerInfo *Src = &Pointers[CGI.Members[0]];
  const PointerInfo *Sink = &Pointers[CGJ.Members[0]];

  // If either pointer is read and written, multiple checks may be needed. Bail
  // out.
  if (!DC.getOrderForAccess(Src->PointerValue, !Src->IsWritePtr).empty() ||
      !DC.getOrderForAccess(Sink->PointerValue, !Sink->IsWritePtr).empty())
    return false;

  ArrayRef<unsigned> AccSrc =
      DC.getOrderForAccess(Src->PointerValue, Src->IsWritePtr);
  ArrayRef<unsigned> AccSink =
      DC.getOrderForAccess(Sink->PointerValue, Sink->IsWritePtr);
  // If either pointer is accessed multiple times, there may not be a clear
  // src/sink relation. Bail out for now.
  if (AccSrc.size() != 1 || AccSink.size() != 1)
    return false;

  // If the sink is accessed before src, swap src/sink.
  if (AccSink[0] < AccSrc[0])
    std::swap(Src, Sink);

  const SCEVConstant *Step;
  const SCEV *SrcStart;
  const SCEV *SinkStart;
  const Loop *InnerLoop = DC.getInnermostLoop();
  if (!match(Src->Expr,
             m_scev_AffineAddRec(m_SCEV(SrcStart), m_SCEVConstant(Step),
                                 m_SpecificLoop(InnerLoop))) ||
      !match(Sink->Expr,
             m_scev_AffineAddRec(m_SCEV(SinkStart), m_scev_Specific(Step),
                                 m_SpecificLoop(InnerLoop))))
    return false;

  SmallVector<Instruction *, 4> SrcInsts =
      DC.getInstructionsForAccess(Src->PointerValue, Src->IsWritePtr);
  SmallVector<Instruction *, 4> SinkInsts =
      DC.getInstructionsForAccess(Sink->PointerValue, Sink->IsWritePtr);
  Type *SrcTy = getLoadStoreType(SrcInsts[0]);
  Type *DstTy = getLoadStoreType(SinkInsts[0]);
  if (isa<ScalableVectorType>(SrcTy) || isa<ScalableVectorType>(DstTy))
    return false;

  const DataLayout &DL = InnerLoop->getHeader()->getDataLayout();
  unsigned AllocSize =
      std::max(DL.getTypeAllocSize(SrcTy), DL.getTypeAllocSize(DstTy));

  // Only matching constant steps matching the AllocSize are supported at the
  // moment. This simplifies the difference computation. Can be extended in the
  // future.
  if (Step->getAPInt().abs() != AllocSize)
    return false;

  // When counting down, the dependence distance needs to be swapped.
  if (Step->getValue()->isNegative())
    std::swap(SinkStart, SrcStart);

  const SCEV *SinkStartInt = SE->getPtrToAddrExpr(SinkStart);
  const SCEV *SrcStartInt = SE->getPtrToAddrExpr(SrcStart);
  if (isa<SCEVCouldNotCompute>(SinkStartInt) ||
      isa<SCEVCouldNotCompute>(SrcStartInt))
    return false;

  // If the start values for both Src and Sink also vary according to an outer
  // loop, then it's probably better to avoid creating diff checks because
  // they may not be hoisted. We should instead let llvm::addRuntimeChecks
  // do the expanded full range overlap checks, which can be hoisted.
  if (HoistRuntimeChecks && InnerLoop->getParentLoop() &&
      isa<SCEVAddRecExpr>(SinkStartInt) && isa<SCEVAddRecExpr>(SrcStartInt)) {
    auto *SrcStartAR = cast<SCEVAddRecExpr>(SrcStartInt);
    auto *SinkStartAR = cast<SCEVAddRecExpr>(SinkStartInt);
    const Loop *StartARLoop = SrcStartAR->getLoop();
    if (StartARLoop == SinkStartAR->getLoop() &&
        StartARLoop == InnerLoop->getParentLoop() &&
        // If the diff check would already be loop invariant (due to the
        // recurrences being the same), then we prefer to keep the diff checks
        // because they are cheaper.
        SrcStartAR->getStepRecurrence(*SE) !=
            SinkStartAR->getStepRecurrence(*SE)) {
      LLVM_DEBUG(dbgs() << "LAA: Not creating diff runtime check, since these "
                           "cannot be hoisted out of the outer loop\n");
      return false;
    }
  }

  LLVM_DEBUG(dbgs() << "LAA: Creating diff runtime check for:\n"
                    << "SrcStart: " << *SrcStartInt << '\n'
                    << "SinkStartInt: " << *SinkStartInt << '\n');
  DiffChecks.emplace_back(SrcStartInt, SinkStartInt, AllocSize,
                          Src->NeedsFreeze || Sink->NeedsFreeze);
  return true;
}

SmallVector<RuntimePointerCheck, 4> RuntimePointerChecking::generateChecks() {
  SmallVector<RuntimePointerCheck, 4> Checks;

  for (unsigned I = 0; I < CheckingGroups.size(); ++I) {
    for (unsigned J = I + 1; J < CheckingGroups.size(); ++J) {
      const RuntimeCheckingPtrGroup &CGI = CheckingGroups[I];
      const RuntimeCheckingPtrGroup &CGJ = CheckingGroups[J];

      if (needsChecking(CGI, CGJ)) {
        CanUseDiffCheck = CanUseDiffCheck && tryToCreateDiffCheck(CGI, CGJ);
        Checks.emplace_back(&CGI, &CGJ);
      }
    }
  }
  return Checks;
}

void RuntimePointerChecking::generateChecks(
    MemoryDepChecker::DepCandidates &DepCands) {
  assert(Checks.empty() && "Checks is not empty");
  groupChecks(DepCands);
  mergeStencilGroups();
  Checks = generateChecks();
}

bool RuntimePointerChecking::needsChecking(
    const RuntimeCheckingPtrGroup &M, const RuntimeCheckingPtrGroup &N) const {
  for (const auto &I : M.Members)
    for (const auto &J : N.Members)
      if (needsChecking(I, J))
        return true;
  return false;
}

/// Compare \p I and \p J and return the minimum.
/// Return nullptr in case we couldn't find an answer.
static const SCEV *getMinFromExprs(const SCEV *I, const SCEV *J,
                                   ScalarEvolution *SE) {
  std::optional<APInt> Diff = SE->computeConstantDifference(J, I);
  if (!Diff)
    return nullptr;
  return Diff->isNegative() ? J : I;
}

bool RuntimeCheckingPtrGroup::addPointer(
    unsigned Index, const RuntimePointerChecking &RtCheck) {
  return addPointer(
      Index, RtCheck.Pointers[Index].Start, RtCheck.Pointers[Index].End,
      RtCheck.Pointers[Index].PointerValue->getType()->getPointerAddressSpace(),
      RtCheck.Pointers[Index].NeedsFreeze, *RtCheck.SE);
}

bool RuntimeCheckingPtrGroup::addPointer(unsigned Index, const SCEV *Start,
                                         const SCEV *End, unsigned AS,
                                         bool NeedsFreeze,
                                         ScalarEvolution &SE) {
  assert(AddressSpace == AS &&
         "all pointers in a checking group must be in the same address space");

  // Compare the starts and ends with the known minimum and maximum
  // of this set. We need to know how we compare against the min/max
  // of the set in order to be able to emit memchecks.
  const SCEV *Min0 = getMinFromExprs(Start, Low, &SE);
  if (!Min0)
    return false;

  const SCEV *Min1 = getMinFromExprs(End, High, &SE);
  if (!Min1)
    return false;

  // Update the low bound  expression if we've found a new min value.
  if (Min0 == Start)
    Low = Start;

  // Update the high bound expression if we've found a new max value.
  if (Min1 != End)
    High = End;

  Members.push_back(Index);
  this->NeedsFreeze |= NeedsFreeze;
  return true;
}

void RuntimePointerChecking::groupChecks(
    MemoryDepChecker::DepCandidates &DepCands) {
  // We build the groups from dependency candidates equivalence classes
  // because:
  //    - We know that pointers in the same equivalence class share
  //      the same underlying object and therefore there is a chance
  //      that we can compare pointers
  //    - We wouldn't be able to merge two pointers for which we need
  //      to emit a memcheck. The classes in DepCands are already
  //      conveniently built such that no two pointers in the same
  //      class need checking against each other.

  // We use the following (greedy) algorithm to construct the groups
  // For every pointer in the equivalence class:
  //   For each existing group:
  //   - if the difference between this pointer and the min/max bounds
  //     of the group is a constant, then make the pointer part of the
  //     group and update the min/max bounds of that group as required.

  CheckingGroups.clear();

  // If we need to check two pointers to the same underlying object
  // with a non-constant difference, we shouldn't perform any pointer
  // grouping with those pointers. This is because we can easily get
  // into cases where the resulting check would return false, even when
  // the accesses are safe.
  //
  // The following example shows this:
  // for (i = 0; i < 1000; ++i)
  //   a[5000 + i * m] = a[i] + a[i + 9000]
  //
  // Here grouping gives a check of (5000, 5000 + 1000 * m) against
  // (0, 10000) which is always false. However, if m is 1, there is no
  // dependence. Not grouping the checks for a[i] and a[i + 9000] allows
  // us to perform an accurate check in this case.
  //
  // In the above case, we have a non-constant distance and an Unknown
  // dependence between accesses to the same underlying object, and could retry
  // with runtime checks without dependency information being available. In this
  // case we will use the fallback path and create separate checking groups for
  // accesses not present in DepCands.

  unsigned TotalComparisons = 0;

  DenseMap<MemoryDepChecker::MemAccessInfo, SmallVector<unsigned>> PositionMap;
  for (unsigned Index = 0; Index < Pointers.size(); ++Index)
    PositionMap[{Pointers[Index].PointerValue, Pointers[Index].IsWritePtr}]
        .push_back(Index);

  // We need to keep track of what pointers we've already seen so we
  // don't process them twice.
  SmallSet<unsigned, 2> Seen;

  // Go through all equivalence classes, get the "pointer check groups"
  // and add them to the overall solution. We use the order in which accesses
  // appear in 'Pointers' to enforce determinism.
  for (unsigned I = 0; I < Pointers.size(); ++I) {
    // We've seen this pointer before, and therefore already processed
    // its equivalence class.
    if (Seen.contains(I))
      continue;

    MemoryDepChecker::MemAccessInfo Access(Pointers[I].PointerValue,
                                           Pointers[I].IsWritePtr);

    // If there is no entry in the dependency partition, there are no potential
    // accesses to merge; simply add a new pointer checking group.
    if (!DepCands.contains(Access)) {
      CheckingGroups.push_back(RuntimeCheckingPtrGroup(I, *this));
      continue;
    }

    SmallVector<RuntimeCheckingPtrGroup, 2> Groups;

    // Because DepCands is constructed by visiting accesses in the order in
    // which they appear in alias sets (which is deterministic) and the
    // iteration order within an equivalence class member is only dependent on
    // the order in which unions and insertions are performed on the
    // equivalence class, the iteration order is deterministic.
    for (auto M : DepCands.members(Access)) {
      for (unsigned Pointer : PositionMap.lookup(M)) {
        assert(!Seen.contains(Pointer) && "pointer already processed");
        Seen.insert(Pointer);
        bool Merged = false;

        // Go through all the existing sets and see if we can find one
        // which can include this pointer.
        for (RuntimeCheckingPtrGroup &Group : Groups) {
          // Don't perform more than a certain amount of comparisons.
          // This should limit the cost of grouping the pointers to something
          // reasonable.  If we do end up hitting this threshold, the algorithm
          // will create separate groups for all remaining pointers.
          if (TotalComparisons > MemoryCheckMergeThreshold)
            break;

          TotalComparisons++;

          if (Group.addPointer(Pointer, *this)) {
            Merged = true;
            break;
          }
        }

        if (!Merged)
          // We couldn't add this pointer to any existing set or the threshold
          // for the number of comparisons has been reached. Create a new group
          // to hold the current pointer.
          Groups.emplace_back(Pointer, *this);
      }
    }

    // We've computed the grouped checks for this partition.
    // Save the results and continue with the next one.
    llvm::append_range(CheckingGroups, Groups);
  }
}

/// Result of decomposing a SCEV expression into stencil offset form:
///   Offset = Constant + sum(Coefficients[stride] * stride)
/// where each stride is a loop-invariant SCEV expression.
struct StencilDecomposition {
  int64_t Constant = 0;
  /// Map from loop-invariant stride SCEV to its integer coefficient.
  SmallMapVector<const SCEV *, int64_t, 4> Coefficients;
};

/// Recursion cap for addScaledStencilTerm. Depth counts how deep a term
/// sits inside the offset expression. For example, the offset
///   8 + (64 * (s1 + s2 + (4 * s3)))
/// is visited like this:
///   depth 0: the whole add
///   depth 1: its operands 8 and (64 * (s1 + s2 + (4 * s3)))
///   depth 2: (s1 + s2 + (4 * s3)), the operand of the multiply
///   depth 3: s1, s2 and (4 * s3), the operands of that add
/// At depth 3 addScaledStencilTerm stops going deeper. s1 and s2 are plain
/// strides anyway. (4 * s3) is not split into 4 times s3: it becomes one
/// stride key as it is, with coefficient 64. The result is Constant = 8
/// and coefficients {s1: 64, s2: 64, (4 * s3): 64}.
/// Three levels cover the stencil offsets we care about: a top-level add,
/// a constant times a sum inside it, and the strides in that sum. A deeper
/// term is kept whole as one stride key. The merge does not care what is
/// inside a key. It only needs a loop-invariant value with a
/// positive-stride predicate, and a whole term has both. The only cost is
/// precision, when another member uses a part of that term, here s3 alone,
/// as a key of its own. isNeverAbove sees two unrelated keys, so a member
/// that is in fact always lower or higher may stay a candidate.
constexpr unsigned MaxStencilDecomposeDepth = 3;

/// Add one term of a stencil offset to \p D. \p Mult is the factor in
/// front of the term; the top-level call passes 1.
/// Example: the offset 8 + (-64 * (s1 + s2)) + (-32 * s1), Mult = 1. It is
/// an add, so each operand is visited in turn with the same Mult = 1:
///   8                  a constant: D.Constant += 1 * 8
///   (-64 * (s1 + s2))  a constant times X: visit X = (s1 + s2) with
///                      Mult = 1 * -64. X is an add, so each operand is
///                      visited with Mult = -64:
///     s1                 a stride: D.Coefficients[s1] += -64
///     s2                 a stride: D.Coefficients[s2] += -64
///   (-32 * s1)         a constant times X: visit X = s1 with Mult = -32:
///     s1                 a stride: D.Coefficients[s1] += -32
/// Result: Constant = 8, Coefficients {s1: -96, s2: -64}. The -64 and the
/// -32 for s1 come from two different terms and add up in the map.
/// So, by the kind of term:
///   constant K       D.Constant += Mult * K
///   (K * X)          visit X with Mult * K
///   (a + b + ...)    visit a, b, ... each with this same Mult
///   anything else    a stride key: D.Coefficients[Term] += Mult
/// The two recursive cases only fire while Depth is below
/// MaxStencilDecomposeDepth. At the cap, (K * X) and (a + b + ...) are
/// stride keys like anything else; that is not a bailout.
/// Returns false when a constant does not fit in int64_t or an update
/// overflows. The caller then drops the whole decomposition.
static bool addScaledStencilTerm(const SCEV *Term, int64_t Mult, unsigned Depth,
                                 StencilDecomposition &D) {
  const SCEVConstant *C;
  // A constant folds into the running constant at any depth.
  if (match(Term, m_SCEVConstant(C))) {
    std::optional<int64_t> V = C->getAPInt().trySExtValue();
    int64_t Scaled;
    return V && !MulOverflow(Mult, *V, Scaled) &&
           !AddOverflow(D.Constant, Scaled, D.Constant);
  }

  if (Depth < MaxStencilDecomposeDepth) {
    const SCEV *Inner;
    if (match(Term, m_scev_Mul(m_SCEVConstant(C), m_SCEV(Inner)))) {
      std::optional<int64_t> V = C->getAPInt().trySExtValue();
      int64_t NewMult;
      return V && !MulOverflow(Mult, *V, NewMult) &&
             addScaledStencilTerm(Inner, NewMult, Depth + 1, D);
    }
    if (auto *Add = dyn_cast<SCEVAddExpr>(Term))
      return all_of(Add->operands(), [&](const SCEV *Op) {
        return addScaledStencilTerm(Op, Mult, Depth + 1, D);
      });
  }

  // Anything else is one stride key.
  int64_t &Coeff = D.Coefficients[Term];
  return !AddOverflow(Coeff, Mult, Coeff);
}

/// Try to decompose \p Expr into a stencil offset function of loop-invariant
/// strides: C + a1*s1 + a2*s2 + ...
/// \p Expr is the difference of two access "Start" SCEVs (Start_member -
/// Start_base). A "Start" is the low bound of a memory access range as computed
/// by getStartAndEndForAccess: the address of the first byte the access can
/// touch. The result describes where one member's range sits relative to the
/// base member's range.
/// Constant factors are distributed over sums. SCEV can keep a factored form:
/// -64*s1 + -64*s2 is stored as (-64 * (s1 + s2)). Distributing the -64 gives
/// the coefficients {s1: -64, s2: -64}, so every member of a group is keyed
/// on the same base strides.
/// Relies on SCEV's canonical form: AddExpr operands are flattened (N-ary),
/// MulExpr has the constant operand first when present.
/// Returns std::nullopt if a constant, multiplier, or coefficient update does
/// not fit in int64_t.
static std::optional<StencilDecomposition>
decomposeStencilOffset(const SCEV *Expr, ScalarEvolution &SE, const Loop &L) {
  // A "Start" is always loop-invariant (getStartAndEndForAccess asserts it), so
  // the difference Expr passed in by the caller is loop-invariant too, and so
  // is every term addScaledStencilTerm visits.
  assert(SE.isLoopInvariant(Expr, &L) && "expected a loop-invariant offset");

  StencilDecomposition D;
  if (!addScaledStencilTerm(Expr, /*Mult=*/1, /*Depth=*/0, D))
    return std::nullopt;
  return D;
}

/// Find a common upper limit M for the positive strides in D. If every stride
/// is between 1 and M, the decomposed offset fits in the signed index type.
/// This lets isNeverAbove compare offsets as ordinary signed integers.
///
/// Subtract abs(Constant) from SignedMax, then divide the remaining budget by
/// the sum of absolute coefficients:
///   M = (SignedMax - abs(Constant)) / sum(abs(Coefficient)).
/// For example, both 8 + 4*s and 8 - 4*s get M = (SignedMax - 8) / 4.
///
/// Return nullopt if abs(Constant) exceeds SignedMax or no positive stride
/// fits. Otherwise, if all coefficients are zero, no stride limit is needed;
/// return SignedMax.
static std::optional<APInt>
getStencilStrideUpperLimit(const StencilDecomposition &D, unsigned BitWidth) {
  uint64_t SignedMax = maxIntN(BitWidth);
  uint64_t AbsConstant = AbsoluteValue(D.Constant);
  if (AbsConstant > SignedMax)
    return std::nullopt;
  uint64_t Budget = SignedMax - AbsConstant;
  uint64_t CoeffSum = 0;
  for (const auto &[Stride, Coeff] : D.Coefficients) {
    uint64_t AbsCoeff = AbsoluteValue(Coeff);
    if (AbsCoeff > Budget - CoeffSum)
      return std::nullopt;
    CoeffSum += AbsCoeff;
  }
  return APInt(BitWidth, CoeffSum ? Budget / CoeffSum : SignedMax);
}

namespace {
/// The runtime checks the merge needs on each stride.
/// Example:
///   s1: {NeedsPositive = true, Max = 1000} means the checks 1 <= s1 <= 1000
///   s2: {Max = 50} means the check s2 <= 50
/// The lower limit is always 1, so a flag is enough for it.
/// Several members can each ask for an upper limit on the same stride, but only
/// the smallest one is kept.
class StrideLimits {
  struct Limit {
    bool NeedsPositive = false;
    std::optional<APInt> Max;
  };
  SmallMapVector<const SCEV *, Limit, 4> Limits;

public:
  void requireLowerLimit(const SCEV *Stride) {
    Limits[Stride].NeedsPositive = true;
  }

  void requireUpperLimit(const SCEV *Stride, const APInt &Max) {
    std::optional<APInt> &Current = Limits[Stride].Max;
    if (!Current || Max.ult(*Current))
      Current = Max;
  }

  /// Add every new or more strict check in \p Other to this set.
  void addFrom(const StrideLimits &Other) {
    for (const auto &[Stride, L] : Other.Limits) {
      if (L.NeedsPositive)
        requireLowerLimit(Stride);
      if (L.Max)
        requireUpperLimit(Stride, *L.Max);
    }
  }

  /// Count the strides that have no check in \p Committed yet.
  unsigned countNew(const StrideLimits &Committed) const {
    return count_if(Limits, [&](const auto &Entry) {
      return !Committed.Limits.contains(Entry.first);
    });
  }

  /// Add the checks to \p PSE as SCEV predicates.
  void addPredicates(PredicatedScalarEvolution &PSE) const {
    ScalarEvolution &SE = *PSE.getSE();
    for (const auto &[Stride, L] : Limits) {
      if (L.NeedsPositive) {
        const SCEV *Zero = SE.getZero(Stride->getType());
        PSE.addPredicate(
            *SE.getComparePredicate(ICmpInst::ICMP_SGT, Stride, Zero));
        LLVM_DEBUG(dbgs() << "LAA:   Adding positive-stride predicate for "
                          << *Stride << "\n");
      }
      if (L.Max) {
        PSE.addPredicate(*SE.getComparePredicate(ICmpInst::ICMP_SLE, Stride,
                                                 SE.getConstant(*L.Max)));
        LLVM_DEBUG(dbgs() << "LAA:   Adding stride upper-limit predicate "
                          << *Stride << " <= " << *L.Max << "\n");
      }
    }
  }
};
} // namespace

/// Add to \p Limits the checks each stride s of \p D needs:
///   1 <= s     isNeverAbove assumes every stride is 1 or more.
///   s <= Max   Max is from getStencilStrideUpperLimit.
/// A check is skipped when SCEV already proves it.
/// Returns false if getStencilStrideUpperLimit finds no Max, or if SCEV proves
/// that a check always fails. Example: s = smin(x, -1) can never pass 1 <= s,
/// so a merge would send every run to the scalar loop.
static bool collectStrideLimits(const StencilDecomposition &D,
                                unsigned BitWidth, ScalarEvolution &SE,
                                StrideLimits &Limits) {
  std::optional<APInt> UpperLimit = getStencilStrideUpperLimit(D, BitWidth);
  if (!UpperLimit)
    return false;

  const SCEV *Max = SE.getConstant(*UpperLimit);
  for (const auto &[Stride, Coeff] : D.Coefficients) {
    if (SE.isKnownNonPositive(Stride) ||
        SE.isKnownPredicate(ICmpInst::ICMP_SGT, Stride, Max))
      return false;
    if (!SE.isKnownPositive(Stride))
      Limits.requireLowerLimit(Stride);
    if (!SE.isKnownPredicate(ICmpInst::ICMP_SLE, Stride, Max))
      Limits.requireUpperLimit(Stride, *UpperLimit);
  }
  return true;
}

/// Return true if offset A is never higher than offset B.
/// A and B are these sums:
///   A = A.Constant + CoefA_1 * stride_1 + CoefA_2 * stride_2 + ...
///   B = B.Constant + CoefB_1 * stride_1 + CoefB_2 * stride_2 + ...
/// A stride missing from a member's map has coefficient 0. Every stride
/// is 1 or more: the caller proves or predicates each stride to be positive
/// and that the whole expression does not overflow.
/// Example:
///   A: 0   - 80*s1
///   B: -40 - 40*s1
/// At s1 = 1 both are -80. For bigger s1, A goes down faster. So A is
/// never above B.
/// The rule checks two things:
/// 1. CoefA_i <= CoefB_i for every stride. So when a stride grows, B - A
///    grows too, or stays the same.
/// 2. B - A >= 0 when every stride is 1. That is ACorner <= BCorner, with
///    ACorner = A.Constant + the sum of all CoefA_i, same for BCorner.
/// B - A starts at or above zero and never goes down, so B - A >= 0 for
/// all stride values.
/// Offsets are signed and addresses are unsigned, but both members read
/// one object, and an object does not wrap around the address space, so
/// the smaller offset is the smaller address.
/// Returns false when ACorner or BCorner overflows int64_t. The caller
/// then keeps the member, which is the safe side.
static bool isNeverAbove(const StencilDecomposition &A,
                         const StencilDecomposition &B) {
  int64_t ACorner = A.Constant, BCorner = B.Constant;
  for (const auto &[Stride, ACoeff] : A.Coefficients) {
    if (ACoeff > B.Coefficients.lookup(Stride))
      return false;
    if (AddOverflow(ACorner, ACoeff, ACorner))
      return false;
  }
  for (const auto &[Stride, BCoeff] : B.Coefficients) {
    if (A.Coefficients.lookup(Stride) > BCoeff)
      return false;
    if (AddOverflow(BCorner, BCoeff, BCorner))
      return false;
  }
  return ACorner <= BCorner;
}

/// Find the members that can define the merged bound on one side.
/// Example for the minimum side (\p ForMin == true), two members:
///   A: 0   - 80*s1
///   B: -40 - 40*s1
/// For every s1 >= 1, A sits at or below B, so B can never be the lowest
/// member: A beats B. The members nobody beats are the candidates.
/// The maximum side works the same way with the comparison flipped.
/// When two members have equal offsets, only the first one is kept.
/// In other words: "beats" is a partial order on the offsets, and the
/// candidates are its minimal elements.
/// Returns indices into \p Offsets.
/// TODO: Worst case compares every pair of members: O(N^2). Fine for real
/// stencils.
static SmallVector<unsigned, 4>
collectCandidateMembers(ArrayRef<StencilDecomposition> Offsets, bool ForMin) {
  // A beats B when A always bounds at least as well as B: for the minimum
  // side A is never above B, for the maximum side A is never below B.
  auto Beats = [&](unsigned A, unsigned B) {
    return ForMin ? isNeverAbove(Offsets[A], Offsets[B])
                  : isNeverAbove(Offsets[B], Offsets[A]);
  };
  // Skipping a beaten member loses nothing: Beats is transitive, so
  // whoever beat it also beats anyone it would have beaten.
  BitVector Beaten(Offsets.size());
  for (unsigned K = 0; K < Offsets.size(); ++K) {
    if (Beaten.test(K))
      continue;
    // Walk J = K + 1 .. N to avoid checking the same pair twice, as
    // (K, J) and again as (J, K). The order in a pair does not matter.
    for (unsigned J = K + 1; J < Offsets.size(); ++J) {
      if (Beaten.test(J))
        continue;
      // Checking K first settles ties: on equal offsets K survives.
      if (Beats(K, J)) {
        Beaten.set(J);
      } else if (Beats(J, K)) {
        Beaten.set(K);
        break;
      }
    }
  }
  SmallVector<unsigned, 4> Candidates;
  for (unsigned K = 0; K < Offsets.size(); ++K)
    if (!Beaten.test(K))
      Candidates.push_back(K);
  return Candidates;
}

/// Local cost model: count the runtime checks required before and after
/// replacing one DepSet's groups (\p GroupIndices) with the single merged
/// group. Everything is counted in the same unit, one check, even though a
/// stride predicate or an extra umin/umax operand is cheaper at runtime
/// than a full group-pair check. The cheaper items only appear on the
/// After side, and we merge only when After < Before, so the rounding
/// always errs toward not merging.
///
/// Before = NumGroups * NumExternalChecks, where NumExternalChecks is the
/// number of groups outside this DepSet that need a check against it. The
/// product is exact: needsChecking() looks only at (DependencySetId,
/// AliasSetId) and at whether a group writes, and all groups in this
/// DepSet agree on those, so an external group is checked against all of
/// them or against none.
///
/// After = NumExternalChecks + NewPredicates + NumBoundOperands:
/// - the merged group keeps the same IDs, so it is checked against exactly
///   the same external groups;
/// - one check per stride needing a lower or upper limit, unless an earlier
///   DepSet already paid for either limit;
/// - a umin over k members costs k-1 compare+selects, same for the umax.
///   \p NumBoundOperands is the sum of the two. A single candidate costs
///   nothing: the bound is that member's own address.
///
/// Returns {ChecksBefore, ChecksAfter}.
static std::pair<unsigned, unsigned> computeStencilMergeCost(
    const RuntimePointerChecking &RtCheck, ArrayRef<unsigned> GroupIndices,
    const StrideLimits &Local, const StrideLimits &Committed,
    unsigned NumBoundOperands) {
  unsigned NumGroups = GroupIndices.size();
  unsigned NumExternalChecks =
      count_if(RtCheck.CheckingGroups, [&](const RuntimeCheckingPtrGroup &G) {
        return any_of(GroupIndices, [&](unsigned GI) {
          return RtCheck.needsChecking(RtCheck.CheckingGroups[GI], G);
        });
      });

  unsigned NewPredicates = Local.countNew(Committed);

  LLVM_DEBUG(dbgs() << "LAA:   Cost model: NumGroups=" << NumGroups
                    << ", NumExternalChecks=" << NumExternalChecks
                    << ", predicates=" << NewPredicates
                    << ", bound operands=" << NumBoundOperands << ", checks "
                    << NumGroups * NumExternalChecks << "->"
                    << NumExternalChecks + NewPredicates + NumBoundOperands
                    << "\n");

  return {NumGroups * NumExternalChecks,
          NumExternalChecks + NewPredicates + NumBoundOperands};
}

/// Build the merged stencil group for one DepSet, after the cost model has
/// decided the merge is profitable. Constructs the bounding group over
/// \p AllMembers with bounds [\p MergedLow, \p MergedHigh]. Returns the new
/// group.
static RuntimeCheckingPtrGroup
buildMergedStencilGroup(const RuntimePointerChecking &RtCheck,
                        ArrayRef<unsigned> AllMembers, const SCEV *MergedLow,
                        const SCEV *MergedHigh,
                        ArrayRef<unsigned> GroupIndices) {
  RuntimeCheckingPtrGroup CandidateGroup(AllMembers[0], RtCheck);
  CandidateGroup.Low = MergedLow;
  CandidateGroup.High = MergedHigh;
  append_range(CandidateGroup.Members, drop_begin(AllMembers));
  CandidateGroup.NeedsFreeze = any_of(GroupIndices, [&](unsigned GI) {
    return RtCheck.CheckingGroups[GI].NeedsFreeze;
  });
  return CandidateGroup;
}

void RuntimePointerChecking::mergeStencilGroups() {
  LLVM_DEBUG(dbgs() << "LAA: Attempting stencil group merging on "
                    << CheckingGroups.size() << " groups\n");

  if (CheckingGroups.size() < 2)
    return;

  // groupChecks merges two pointers only when their bounds differ by a
  // compile-time constant, because only then it can tell which bound is
  // lower or higher. A stencil kernel reads one object at several
  // loop-invariant offsets, so its bounds differ by expressions like
  // -40 - 40*s1, and every such pointer stays in its own group - often
  // too many checks. Here we merge those groups anyway: what we cannot
  // compare at compile time we compare at runtime, with a umin/umax over
  // the few members that can be lowest or highest. The cost: the merged
  // range also covers the gaps between the members, so the merged check
  // can report a conflict where the per-group checks would not.
  //
  // We only merge ranges for reads that happen on every loop iteration.
  // These reads must stay inside the array; otherwise, the original loop
  // already has undefined behaviour. We choose the merged bounds from
  // these ranges.
  //
  // We use the following algorithm to construct a merged stencil group:
  //   - collect checking groups that share both DependencySetId and AliasSetId;
  //   - reject groups with writes, predicated accesses, forked pointers,
  //     different access ranges, or different recurrence steps;
  //   - use one member as the base and decompose each other member's offset
  //     from that base as C + sum(Coeff[Stride] * Stride), where Stride is
  //     loop-invariant;
  //   - keep the members that can hold the lowest or the highest address at
  //     runtime (the candidate members), and build the merged bounds as a
  //     umin over their Start values and a umax over their End values,
  //     adding predicates for strides not already known positive and within
  //     their limits;
  //   - commit the merge only if the local cost model reduces the number of
  //     checks after accounting for any new predicates.

  // Stencil merging runs when either:
  //   - the flag is set to 'force' (-stencil-runtime-check-merge=force), or
  //   - the flag is set to 'auto' (-stencil-runtime-check-merge=auto) AND the
  //     current check count exceeds the auto-trigger threshold, which defaults
  //     to the vectorizer's own runtime-check cutoff
  //     (-vectorize-memory-check-threshold). Above it the vectorizer would
  //     otherwise reject the loop for having too many runtime checks. In that
  //     case the merge can only improve things: at worst we decline to merge
  //     and behave as before.
  if (StencilMerge == StencilMergePolicy::Off) {
    LLVM_DEBUG(dbgs() << "LAA: stencil merge disabled\n");
    return;
  }

  const Loop &L = *DC.getInnermostLoop();

  // visitPointers expands non-header pointer PHIs before runtime checks are
  // created, so their alternatives are not marked IsForked. An unused
  // alternative may wrap and make the merged bounds miss a real overlap.
  for (BasicBlock *BB : L.blocks())
    if (BB != L.getHeader())
      for (PHINode &PN : BB->phis())
        if (PN.getType()->isPointerTy())
          return;

  // For each checking group this pass decomposes each member's offset into
  // stencil form, keeps the candidate members (the ones that can hold the
  // lowest or highest address at runtime), and builds the merged bounds from
  // their own Start and End values. That extra SCEV work adds up on a loop
  // with very many groups, so bail out above a configurable limit as a
  // safety net against pathological inputs.
  if (CheckingGroups.size() > StencilMergeMaxGroups) {
    LLVM_DEBUG(
        dbgs() << "LAA: " << CheckingGroups.size()
               << " groups exceeds stencil-merge-max-groups, skipping\n");
    return;
  }

  if (StencilMerge == StencilMergePolicy::Auto) {
    unsigned TotalChecks = 0;
    for (unsigned I = 0; I < CheckingGroups.size(); ++I)
      for (unsigned J = I + 1; J < CheckingGroups.size(); ++J)
        if (needsChecking(CheckingGroups[I], CheckingGroups[J]))
          ++TotalChecks;

    // Above this many checks the vectorizer gives up on the loop, so that is
    // where merging starts to matter.
    if (TotalChecks <= VectorizerParams::VectorizeMemoryCheckThreshold) {
      LLVM_DEBUG(dbgs() << "LAA: " << TotalChecks
                        << " checks <= threshold, skipping stencil merge\n");
      return;
    }
    LLVM_DEBUG(
        dbgs() << "LAA: " << TotalChecks
               << " checks > threshold, proceeding with stencil merge\n");
  } else {
    LLVM_DEBUG(dbgs() << "LAA: stencil merge forced via flag\n");
  }

  // Group CheckingGroups by (DependencySetId, AliasSetId) pair.
  // DependencySetId alone is not unique: it resets per alias set, so
  // pointers in different alias sets can share the same DependencySetId.
  // Use MapVector for deterministic iteration order across platforms.
  using DepAliasKey = std::pair<unsigned, unsigned>;
  MapVector<DepAliasKey, SmallVector<unsigned, 4>> DepSetToGroups;
  for (unsigned I = 0; I < CheckingGroups.size(); ++I) {
    const auto &P = Pointers[CheckingGroups[I].Members[0]];
    DepSetToGroups[{P.DependencySetId, P.AliasSetId}].push_back(I);
  }

  SmallDenseSet<unsigned, 4> MergedGroupIndices;
  SmallVector<RuntimeCheckingPtrGroup, 2> NewMergedGroups;
  // Stride checks from the accepted DepSets. A later DepSet can lower an
  // upper limit, so the predicates are added only after the last DepSet.
  StrideLimits CommittedStrideLimits;

  for (auto &[DepAliasKey, GroupIndices] : DepSetToGroups) {
    [[maybe_unused]] auto [DepId, ASId] = DepAliasKey;
    if (GroupIndices.size() < 2)
      continue;

    // Collect all member pointers across these groups. Only merge read-only
    // groups: stencil patterns read an array at multiple offsets and write to a
    // different array (a different DepSet). Mixing reads and writes within a
    // merged group complicates the cost model and doesn't match known stencil
    // patterns, so stop and skip the whole DepSet as soon as we see a write.
    SmallVector<unsigned, 8> AllMembers;
    bool CanMerge = true;
    for (unsigned GI : GroupIndices) {
      ArrayRef<unsigned> Members = CheckingGroups[GI].Members;
      if (any_of(Members,
                 [&](unsigned Idx) { return Pointers[Idx].IsWritePtr; })) {
        LLVM_DEBUG(dbgs() << "LAA: Skipping DepSet(" << DepId << "," << ASId
                          << ") with write access\n");
        CanMerge = false;
        break;
      }
      // For a forked pointer, LAA considers both possible addresses, even if
      // the loop only uses one of them. The unused address can be outside the
      // array. Its bounds can underflow or overflow, so merging them can hide
      // an overlap and allow unsafe vectorization.
      if (any_of(Members,
                 [&](unsigned Idx) { return Pointers[Idx].IsForked; })) {
        LLVM_DEBUG(dbgs() << "LAA: Skipping DepSet(" << DepId << "," << ASId
                          << ") with forked pointer\n");
        CanMerge = false;
        break;
      }
      append_range(AllMembers, Members);
    }
    if (!CanMerge)
      continue;

    // A predicated access does not happen in every iteration. In the skipped
    // iterations its address can be outside the array. Its bounds can
    // underflow or overflow, so merging them can hide an overlap and allow
    // unsafe vectorization.
    // Look at the block of the actual load/store, not of the pointer: a
    // loop-invariant address is computed in the preheader, outside the loop.
    if (any_of(AllMembers, [&](unsigned Idx) {
          const PointerInfo &P = Pointers[Idx];
          assert(!P.IsWritePtr && "only read members reach this point");
          return any_of(
              DC.getInstructionsForAccess(P.PointerValue, /*isWrite=*/false),
              [&](Instruction *I) {
                return LoopAccessInfo::blockNeedsPredication(I->getParent(), &L,
                                                             DC.getDT());
              });
        })) {
      LLVM_DEBUG(dbgs() << "LAA: Skipping DepSet(" << DepId << "," << ASId
                        << ") with predicated access\n");
      continue;
    }

    // Use the first member as the reference for decomposition. All offsets
    // are computed relative to BaseLow. BaseHigh is only used to check that
    // every member covers the same range. The merged bounds are built later
    // from the members' own Start and End values.
    unsigned Member0 = AllMembers[0];
    const SCEV *BaseLow = Pointers[Member0].Start;
    const SCEV *BaseHigh = Pointers[Member0].End;

    // Keep stencil decomposition and stride-limit arithmetic within 64 bits.
    // All offsets relative to BaseLow have the same index width.
    if (SE->getTypeSizeInBits(BaseLow->getType()) > 64)
      continue;

    LLVM_DEBUG(dbgs() << "LAA: Analyzing DepSet(" << DepId << "," << ASId
                      << ") with " << AllMembers.size()
                      << " members, base: " << *BaseLow << "\n");

    auto GetStepForPointer = [&](unsigned Idx) -> const SCEV * {
      if (const auto *AR = dyn_cast<SCEVAddRecExpr>(Pointers[Idx].Expr))
        if (AR->getLoop() == &L)
          return AR->getStepRecurrence(*SE);
      return nullptr;
    };

    const SCEV *BaseStep = GetStepForPointer(Member0);
    if (!BaseStep)
      continue;

    // Verify all members have the same access range (End - Start). The
    // merged upper bound is a umax over the members' own End values. The
    // same decompositions order both the Start and the End values
    // only when End = Start + Range with one shared Range for every member.
    // That is what this check enforces.
    // Compare each member's range (End - Start) and test Range - BaseRange ==
    // 0, rather than Range == BaseRange, so algebraically equal but
    // non-identical SCEVs still match. Bail out if any subtraction produces
    // SCEVCouldNotCompute.
    const SCEV *BaseRange = SE->getMinusSCEV(BaseHigh, BaseLow);
    if (isa<SCEVCouldNotCompute>(BaseRange)) {
      LLVM_DEBUG(dbgs() << "LAA:   Base access range not computable, "
                           "skipping DepSet\n");
      continue;
    }
    if (any_of(drop_begin(AllMembers), [&](unsigned Idx) {
          const SCEV *Range =
              SE->getMinusSCEV(Pointers[Idx].End, Pointers[Idx].Start);
          if (isa<SCEVCouldNotCompute>(Range))
            return true;
          if (Range == BaseRange)
            return false;
          const SCEV *RangeDiff = SE->getMinusSCEV(Range, BaseRange);
          return isa<SCEVCouldNotCompute>(RangeDiff) || !RangeDiff->isZero();
        })) {
      LLVM_DEBUG(
          dbgs() << "LAA:   Member with different or not computable access "
                    "range, skipping DepSet\n");
      continue;
    }

    // Require all members to have the same recurrence step. Equal ranges
    // (checked above) are what the merged bounds actually need, and a different
    // step usually means a different range. But ranges can be equal by accident
    // - e.g. an invariant access whose range matches the stride, or a loop with
    // a single iteration. The base member is picked arbitrarily, so together
    // with the BaseStep check above this keeps the decision the same no matter
    // which member comes first: we only merge recurrences with one common step.
    if (any_of(drop_begin(AllMembers), [&](unsigned Idx) {
          return GetStepForPointer(Idx) != BaseStep;
        })) {
      LLVM_DEBUG(dbgs() << "LAA:   Member with different step, "
                           "skipping DepSet\n");
      continue;
    }
    // One decomposition per member, in AllMembers order. Each entry holds the
    // member's constant offset and its coefficient for each stride, all
    // relative to BaseLow.
    SmallVector<StencilDecomposition, 8> MemberOffsets;
    MemberOffsets.reserve(AllMembers.size());
    // The base member's offset from itself is zero: Constant 0, no strides.
    MemberOffsets.emplace_back();
    // Stride checks this DepSet needs if it is merged.
    StrideLimits LocalStrideLimits;

    // Decompose one member's offset (relative to BaseLow) and append it to
    // MemberOffsets. Returns false if the offset is not in stencil form (so
    // the whole DepSet is skipped).
    const auto CollectOffset = [&](unsigned Idx) -> bool {
      const SCEV *LowOffset = SE->getMinusSCEV(Pointers[Idx].Start, BaseLow);
      if (isa<SCEVCouldNotCompute>(LowOffset))
        return false;
      auto DLow = decomposeStencilOffset(LowOffset, *SE, L);
      if (!DLow) {
        LLVM_DEBUG(dbgs() << "LAA:   Member " << Idx
                          << " NOT decomposable: " << *LowOffset << "\n");
        return false;
      }
      if (!collectStrideLimits(*DLow,
                               SE->getTypeSizeInBits(LowOffset->getType()), *SE,
                               LocalStrideLimits))
        return false;

      LLVM_DEBUG(dbgs() << "LAA:   Member " << Idx
                        << ": Const=" << DLow->Constant
                        << ", strides=" << DLow->Coefficients.size() << "\n");
      MemberOffsets.push_back(std::move(*DLow));
      return true;
    };

    if (!all_of(drop_begin(AllMembers), CollectOffset))
      continue;

    SmallVector<unsigned, 4> MinCandidates =
        collectCandidateMembers(MemberOffsets, /*ForMin=*/true);
    SmallVector<unsigned, 4> MaxCandidates =
        collectCandidateMembers(MemberOffsets, /*ForMin=*/false);
    assert(!MinCandidates.empty() && !MaxCandidates.empty() &&
           "a non-empty member list always has a candidate");
    LLVM_DEBUG(dbgs() << "LAA:   Candidate members: min="
                      << MinCandidates.size()
                      << ", max=" << MaxCandidates.size() << " of "
                      << MemberOffsets.size() << "\n");

    // Extra bound operands: one compare-and-select per operand past the first
    // in the merged umin, and the same for the umax.
    unsigned NumBoundOperands =
        (MinCandidates.size() - 1) + (MaxCandidates.size() - 1);

    // Local cost model: decide whether replacing this DepSet's groups with the
    // single merged group actually reduces the number of runtime checks. Run
    // it before building the merged bounds: a rejected DepSet then creates no
    // umin/umax expressions that would only be thrown away.
    auto [ChecksBefore, ChecksAfter] =
        computeStencilMergeCost(*this, GroupIndices, LocalStrideLimits,
                                CommittedStrideLimits, NumBoundOperands);
    if (ChecksAfter >= ChecksBefore) {
      LLVM_DEBUG(dbgs() << "LAA:   Not beneficial, skipping DepSet\n");
      continue;
    }

    // Build one side of the merged bounds from its candidate members.
    // With one candidate the bound is that member's own Start (or End): the
    // exact value the member's own check used before the merge. With several
    // candidates the bound is a umin (umax) over their Starts (Ends). Either
    // way every value is a real member address, so the merge computes no new
    // address and no new overflow is possible.
    // The umin/umax are on pointers. The expander turns them into the same
    // icmp and select that a plain check uses, so no address conversion is
    // needed.
    const auto BuildBound = [&](ArrayRef<unsigned> Candidates, bool IsLow) {
      SmallVector<SCEVUse, 4> Ops;
      for (unsigned K : Candidates) {
        const PointerInfo &P = Pointers[AllMembers[K]];
        Ops.push_back(IsLow ? P.Start : P.End);
      }
      return IsLow ? SE->getUMinExpr(Ops) : SE->getUMaxExpr(Ops);
    };

    const SCEV *MergedLow = BuildBound(MinCandidates, /*IsLow=*/true);
    const SCEV *MergedHigh = BuildBound(MaxCandidates, /*IsLow=*/false);

    LLVM_DEBUG(dbgs() << "LAA:   Merged bounds: Low=" << *MergedLow
                      << ", High=" << *MergedHigh << "\n");
    LLVM_DEBUG(dbgs() << "LAA:   Merging, net saving "
                      << ChecksBefore - ChecksAfter << "\n");

    NewMergedGroups.push_back(buildMergedStencilGroup(
        *this, AllMembers, MergedLow, MergedHigh, GroupIndices));
    CommittedStrideLimits.addFrom(LocalStrideLimits);
    MergedGroupIndices.insert(GroupIndices.begin(), GroupIndices.end());
  }

  CommittedStrideLimits.addPredicates(DC.getPSE());

  // Rebuild CheckingGroups if we merged anything.
  if (!NewMergedGroups.empty()) {
    SmallVector<RuntimeCheckingPtrGroup, 2> FinalGroups;
    for (unsigned I = 0; I < CheckingGroups.size(); ++I)
      if (!MergedGroupIndices.contains(I))
        FinalGroups.push_back(std::move(CheckingGroups[I]));
    FinalGroups.append(std::make_move_iterator(NewMergedGroups.begin()),
                       std::make_move_iterator(NewMergedGroups.end()));
    CheckingGroups = std::move(FinalGroups);

    LLVM_DEBUG(dbgs() << "LAA: After stencil merging: " << CheckingGroups.size()
                      << " groups\n");
  }
}

bool RuntimePointerChecking::arePointersInSamePartition(
    const SmallVectorImpl<int> &PtrToPartition, unsigned PtrIdx1,
    unsigned PtrIdx2) {
  return (PtrToPartition[PtrIdx1] != -1 &&
          PtrToPartition[PtrIdx1] == PtrToPartition[PtrIdx2]);
}

bool RuntimePointerChecking::needsChecking(unsigned I, unsigned J) const {
  const PointerInfo &PointerI = Pointers[I];
  const PointerInfo &PointerJ = Pointers[J];

  // No need to check if two readonly pointers intersect.
  if (!PointerI.IsWritePtr && !PointerJ.IsWritePtr)
    return false;

  // Only need to check pointers between two different dependency sets.
  if (PointerI.DependencySetId == PointerJ.DependencySetId)
    return false;

  // Only need to check pointers in the same alias set.
  return PointerI.AliasSetId == PointerJ.AliasSetId;
}

/// Assign each RuntimeCheckingPtrGroup pointer an index for stable UTC output.
static DenseMap<const RuntimeCheckingPtrGroup *, unsigned>
getPtrToIdxMap(ArrayRef<RuntimeCheckingPtrGroup> CheckingGroups) {
  DenseMap<const RuntimeCheckingPtrGroup *, unsigned> PtrIndices;
  for (const auto &[Idx, CG] : enumerate(CheckingGroups))
    PtrIndices[&CG] = Idx;
  return PtrIndices;
}

void RuntimePointerChecking::printChecks(
    raw_ostream &OS, const SmallVectorImpl<RuntimePointerCheck> &Checks,
    unsigned Depth) const {
  unsigned N = 0;
  auto PtrIndices = getPtrToIdxMap(CheckingGroups);
  for (const auto &[Check1, Check2] : Checks) {
    const auto &First = Check1->Members, &Second = Check2->Members;
    OS.indent(Depth) << "Check " << N++ << ":\n";
    OS.indent(Depth + 2) << "Comparing group GRP" << PtrIndices.at(Check1)
                         << ":\n";
    for (unsigned K : First)
      OS.indent(Depth + 2) << *Pointers[K].PointerValue << "\n";
    OS.indent(Depth + 2) << "Against group GRP" << PtrIndices.at(Check2)
                         << ":\n";
    for (unsigned K : Second)
      OS.indent(Depth + 2) << *Pointers[K].PointerValue << "\n";
  }
}

void RuntimePointerChecking::print(raw_ostream &OS, unsigned Depth) const {

  OS.indent(Depth) << "Run-time memory checks:\n";
  printChecks(OS, Checks, Depth);

  OS.indent(Depth) << "Grouped accesses:\n";
  auto PtrIndices = getPtrToIdxMap(CheckingGroups);
  for (const auto &CG : CheckingGroups) {
    OS.indent(Depth + 2) << "Group GRP" << PtrIndices.at(&CG) << ":\n";
    OS.indent(Depth + 4) << "(Low: " << *CG.Low << " High: " << *CG.High
                         << ")\n";
    for (unsigned Member : CG.Members) {
      OS.indent(Depth + 6) << "Member: " << *Pointers[Member].Expr << "\n";
    }
  }
}

namespace {

/// Analyses memory accesses in a loop.
///
/// Checks whether run time pointer checks are needed and builds sets for data
/// dependence checking.
class AccessAnalysis {
public:
  using MemAccessInfo =
      PointerIntPair<Value * /* AccessPtr */, 1, bool /* IsWrite */>;

  AccessAnalysis(const Loop *TheLoop, AAResults *AA, const LoopInfo *LI,
                 DominatorTree &DT, MemoryDepChecker::DepCandidates &DA,
                 PredicatedScalarEvolution &PSE,
                 SmallPtrSetImpl<MDNode *> &LoopAliasScopes)
      : TheLoop(TheLoop), EEA(DT, LI), BAA(*AA, &EEA), AST(BAA), LI(LI), DT(DT),
        DepCands(DA), PSE(PSE), LoopAliasScopes(LoopAliasScopes) {
    // We're analyzing dependences across loop iterations.
    BAA.enableCrossIterationMode();
  }

  /// Register a load  and whether it is only read from.
  void addLoad(const MemoryLocation &Loc, Type *AccessTy, bool IsReadOnly) {
    Value *Ptr = const_cast<Value *>(Loc.Ptr);
    AST.add(adjustLoc(Loc));
    Accesses[MemAccessInfo(Ptr, false)].insert(AccessTy);
    if (IsReadOnly)
      ReadOnlyPtr.insert(Ptr);
  }

  /// Register a store.
  void addStore(const MemoryLocation &Loc, Type *AccessTy) {
    Value *Ptr = const_cast<Value *>(Loc.Ptr);
    AST.add(adjustLoc(Loc));
    Accesses[MemAccessInfo(Ptr, true)].insert(AccessTy);
  }

  /// Check if we can emit a run-time no-alias check for \p Access.
  ///
  /// Returns true if we can emit a run-time no alias check for \p Access.
  /// If we can check this access, this also adds it to a dependence set and
  /// adds a run-time to check for it to \p RtCheck. If \p Assume is true,
  /// we will attempt to use additional run-time checks in order to get
  /// the bounds of the pointer.
  bool createCheckForAccess(RuntimePointerChecking &RtCheck,
                            MemAccessInfo Access, Type *AccessTy,
                            const SymbolicStrideMap &Strides,
                            DenseMap<Value *, unsigned> &DepSetId,
                            Loop *TheLoop, unsigned &RunningDepId,
                            unsigned ASId, bool Assume);

  /// Check whether we can check the pointers at runtime for
  /// non-intersection.
  ///
  /// Returns true if we need no check or if we do and we can generate them
  /// (i.e. the pointers have computable bounds). A return value of false means
  /// we couldn't analyze and generate runtime checks for all pointers in the
  /// loop, but if \p AllowPartial is set then we will have checks for those
  /// pointers we could analyze. \p DepChecker is used to remove unknown
  /// dependences from DepCands.
  bool canCheckPtrAtRT(RuntimePointerChecking &RtCheck, Loop *TheLoop,
                       const SymbolicStrideMap &Strides,
                       Value *&UncomputablePtr, bool AllowPartial,
                       const MemoryDepChecker &DepChecker);

  /// Goes over all memory accesses, checks whether a RT check is needed
  /// and builds sets of dependent accesses.
  void buildDependenceSets();

  /// Initial processing of memory accesses determined that we need to
  /// perform dependency checking.
  ///
  /// Note that this can later be cleared if we retry memcheck analysis without
  /// dependency checking (i.e. ShouldRetryWithRuntimeChecks).
  bool isDependencyCheckNeeded() const { return !CheckDeps.empty(); }

  /// We decided that no dependence analysis would be used.  Reset the state.
  void resetDepChecks(MemoryDepChecker &DepChecker) {
    CheckDeps.clear();
    DepChecker.clearDependences();
  }

  ArrayRef<MemAccessInfo> getDependenciesToCheck() const { return CheckDeps; }

private:
  using PtrAccessMap = MapVector<MemAccessInfo, SmallSetVector<Type *, 1>>;

  /// Adjust the MemoryLocation so that it represents accesses to this
  /// location across all iterations, rather than a single one.
  MemoryLocation adjustLoc(MemoryLocation Loc) const {
    // The accessed location varies within the loop, but remains within the
    // underlying object.
    Loc.Size = LocationSize::beforeOrAfterPointer();
    Loc.AATags.Scope = adjustAliasScopeList(Loc.AATags.Scope);
    Loc.AATags.NoAlias = adjustAliasScopeList(Loc.AATags.NoAlias);
    return Loc;
  }

  /// Drop alias scopes that are only valid within a single loop iteration.
  MDNode *adjustAliasScopeList(MDNode *ScopeList) const {
    if (!ScopeList)
      return nullptr;

    // For the sake of simplicity, drop the whole scope list if any scope is
    // iteration-local.
    if (any_of(ScopeList->operands(), [&](Metadata *Scope) {
          return LoopAliasScopes.contains(cast<MDNode>(Scope));
        }))
      return nullptr;

    return ScopeList;
  }

  /// Map of all accesses. Values are the types used to access memory pointed to
  /// by the pointer.
  PtrAccessMap Accesses;

  /// The loop being checked.
  const Loop *TheLoop;

  /// List of accesses that need a further dependence check.
  SmallVector<MemAccessInfo, 8> CheckDeps;

  /// Set of pointers that are read only.
  SmallPtrSet<Value*, 16> ReadOnlyPtr;

  /// Capture analysis for BAA.
  EarliestEscapeAnalysis EEA;

  /// Batched alias analysis results.
  BatchAAResults BAA;

  /// An alias set tracker to partition the access set by underlying object and
  //intrinsic property (such as TBAA metadata).
  AliasSetTracker AST;

  /// The LoopInfo of the loop being checked.
  const LoopInfo *LI;

  /// The dominator tree of the function.
  DominatorTree &DT;

  /// Sets of potentially dependent accesses - members of one set share an
  /// underlying pointer. The set "CheckDeps" identfies which sets really need a
  /// dependence check.
  MemoryDepChecker::DepCandidates &DepCands;

  /// Initial processing of memory accesses determined that we may need
  /// to add memchecks.  Perform the analysis to determine the necessary checks.
  ///
  /// Note that, this is different from isDependencyCheckNeeded.  When we retry
  /// memcheck analysis without dependency checking
  /// (i.e. ShouldRetryWithRuntimeChecks), isDependencyCheckNeeded is
  /// cleared while this remains set if we have potentially dependent accesses.
  bool IsRTCheckAnalysisNeeded = false;

  /// The SCEV predicate containing all the SCEV-related assumptions.
  PredicatedScalarEvolution &PSE;

  DenseMap<Value *, SmallVector<const Value *, 16>> UnderlyingObjects;

  /// Alias scopes that are declared inside the loop, and as such not valid
  /// across iterations.
  SmallPtrSetImpl<MDNode *> &LoopAliasScopes;
};

} // end anonymous namespace

std::optional<int64_t>
llvm::getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp,
                          Type *AccessTy, Value *Ptr,
                          PredicatedScalarEvolution &PSE) {
  if (isa<ScalableVectorType>(AccessTy)) {
    LLVM_DEBUG(dbgs() << "LAA: Bad stride - Scalable object: " << *AccessTy
                      << "\n");
    return std::nullopt;
  }

  // The access function must stride over the innermost loop.
  if (Lp != AR->getLoop()) {
    LLVM_DEBUG({
      dbgs() << "LAA: Bad stride - Not striding over innermost loop ";
      if (Ptr)
        dbgs() << *Ptr << " ";

      dbgs() << "SCEV: " << *AR << "\n";
    });
    return std::nullopt;
  }

  // Check the step is constant.
  const SCEV *Step = AR->getStepRecurrence(*PSE.getSE());

  // Calculate the pointer stride and check if it is constant.
  const APInt *APStepVal;
  if (!match(Step, m_scev_APInt(APStepVal))) {
    LLVM_DEBUG({
      dbgs() << "LAA: Bad stride - Not a constant strided ";
      if (Ptr)
        dbgs() << *Ptr << " ";
      dbgs() << "SCEV: " << *AR << "\n";
    });
    return std::nullopt;
  }

  const auto &DL = Lp->getHeader()->getDataLayout();
  TypeSize AllocSize = DL.getTypeAllocSize(AccessTy);
  int64_t Size = AllocSize.getFixedValue();

  // Huge step value - give up.
  std::optional<int64_t> StepVal = APStepVal->trySExtValue();
  if (!StepVal)
    return std::nullopt;

  // Strided access.
  return *StepVal % Size ? std::nullopt : std::make_optional(*StepVal / Size);
}

/// Check whether \p AR is a non-wrapping AddRec. If \p Ptr is not nullptr, use
/// information from the IR pointer value to determine no-wrap. If \p Predicates
/// is not nullptr add no-wrap assumptions if needed.
static bool
isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR, Value *Ptr,
         Type *AccessTy, const Loop *L, const DominatorTree &DT,
         std::optional<int64_t> Stride = std::nullopt,
         SmallVectorImpl<const SCEVPredicate *> *Predicates = nullptr) {
  // FIXME: This should probably only return true for NUW.
  if (any(AR->getNoWrapFlags()))
    return true;

  // An nusw getelementptr that is an AddRec cannot wrap. If it would wrap,
  // the distance between the previously accessed location and the wrapped
  // location will be larger than half the pointer index type space. In that
  // case, the GEP would be  poison and any memory access dependent on it would
  // be immediate UB when executed.
  if (auto *GEP = dyn_cast_if_present<GetElementPtrInst>(Ptr);
      GEP && GEP->hasNoUnsignedSignedWrap()) {
    // For the above reasoning to apply, the pointer must be dereferenced in
    // every iteration.
    if (L->getHeader() == L->getLoopLatch() ||
        any_of(GEP->users(), [L, &DT, GEP](User *U) {
          if (getLoadStorePointerOperand(U) != GEP)
            return false;
          BasicBlock *UserBB = cast<Instruction>(U)->getParent();
          if (!L->contains(UserBB))
            return false;
          return !LoopAccessInfo::blockNeedsPredication(UserBB, L, &DT);
        }))
      return true;
  }

  if (!Stride)
    Stride = getStrideFromAddRec(AR, L, AccessTy, Ptr, PSE);
  if (Stride) {
    // If the null pointer is undefined, then a access sequence which would
    // otherwise access it can be assumed not to unsigned wrap.  Note that this
    // assumes the object in memory is aligned to the natural alignment.
    unsigned AddrSpace = AR->getType()->getPointerAddressSpace();
    if (!NullPointerIsDefined(L->getHeader()->getParent(), AddrSpace) &&
        (Stride == 1 || Stride == -1))
      return true;
  }

  ScalarEvolution &SE = *PSE.getSE();
  const SCEVPredicate *WrapPred =
      SE.getWrapPredicate(AR, SCEVWrapPredicate::IncrementNUSW);
  if (Ptr && Predicates) {
    Predicates->push_back(WrapPred);
    LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n"
                      << "LAA:   Pointer: " << *Ptr << "\n"
                      << "LAA:   SCEV: " << *AR << "\n"
                      << "LAA:   Added an overflow assumption\n");
    return true;
  }

  // Without adding a new predicate, AR may still be known not to wrap if the
  // predicates of PSE already imply it, e.g. because a wrap predicate for AR
  // was added while analyzing the dependences of the loop.
  return PSE.getPredicate().implies(WrapPred, SE);
}

static void visitPointers(Value *StartPtr, const Loop &InnermostLoop,
                          function_ref<void(Value *)> AddPointer) {
  SmallPtrSet<Value *, 8> Visited;
  SmallVector<Value *> WorkList;
  WorkList.push_back(StartPtr);

  while (!WorkList.empty()) {
    Value *Ptr = WorkList.pop_back_val();
    if (!Visited.insert(Ptr).second)
      continue;
    auto *PN = dyn_cast<PHINode>(Ptr);
    // SCEV does not look through non-header PHIs inside the loop. Such phis
    // can be analyzed by adding separate accesses for each incoming pointer
    // value.
    if (PN && InnermostLoop.contains(PN->getParent()) &&
        PN->getParent() != InnermostLoop.getHeader()) {
      llvm::append_range(WorkList, PN->incoming_values());
    } else
      AddPointer(Ptr);
  }
}

// Walk back through the IR for a pointer, looking for a select like the
// following:
//
//  %offset = select i1 %cmp, i64 %a, i64 %b
//  %addr = getelementptr double, double* %base, i64 %offset
//  %ld = load double, double* %addr, align 8
//
// We won't be able to form a single SCEVAddRecExpr from this since the
// address for each loop iteration depends on %cmp. We could potentially
// produce multiple valid SCEVAddRecExprs, though, and check all of them for
// memory safety/aliasing if needed.
//
// If we encounter some IR we don't yet handle, or something obviously fine
// like a constant, then we just add the SCEV for that term to the list passed
// in by the caller. If we have a node that may potentially yield a valid
// SCEVAddRecExpr then we decompose it into parts and build the SCEV terms
// ourselves before adding to the list.
static void findForkedSCEVs(
    ScalarEvolution *SE, const Loop *L, Value *Ptr,
    SmallVectorImpl<PointerIntPair<const SCEV *, 1, bool>> &ScevList,
    unsigned Depth) {
  // If our Value is a SCEVAddRecExpr, loop invariant, not an instruction, or
  // we've exceeded our limit on recursion, just return whatever we have
  // regardless of whether it can be used for a forked pointer or not, along
  // with an indication of whether it might be a poison or undef value.
  const SCEV *Scev = SE->getSCEV(Ptr);
  if (isa<SCEVAddRecExpr>(Scev) || L->isLoopInvariant(Ptr) ||
      !isa<Instruction>(Ptr) || Depth == 0) {
    ScevList.emplace_back(Scev, !isGuaranteedNotToBeUndefOrPoison(Ptr));
    return;
  }

  Depth--;

  auto UndefPoisonCheck = [](PointerIntPair<const SCEV *, 1, bool> S) {
    return get<1>(S);
  };

  auto GetBinOpExpr = [&SE](unsigned Opcode, const SCEV *L,
                            const SCEV *R) -> const SCEV * {
    switch (Opcode) {
    case Instruction::Add:
      return SE->getAddExpr(L, R);
    case Instruction::Sub:
      return SE->getMinusSCEV(L, R);
    default:
      llvm_unreachable("Unexpected binary operator when walking ForkedPtrs");
    }
  };

  Instruction *I = cast<Instruction>(Ptr);
  unsigned Opcode = I->getOpcode();
  switch (Opcode) {
  case Instruction::GetElementPtr: {
    auto *GEP = cast<GetElementPtrInst>(I);
    Type *SourceTy = GEP->getSourceElementType();
    // We only handle base + single offset GEPs here for now.
    // Not dealing with preexisting gathers yet, so no vectors.
    if (I->getNumOperands() != 2 || SourceTy->isVectorTy()) {
      ScevList.emplace_back(Scev, !isGuaranteedNotToBeUndefOrPoison(GEP));
      break;
    }
    SmallVector<PointerIntPair<const SCEV *, 1, bool>, 2> BaseScevs;
    SmallVector<PointerIntPair<const SCEV *, 1, bool>, 2> OffsetScevs;
    findForkedSCEVs(SE, L, I->getOperand(0), BaseScevs, Depth);
    findForkedSCEVs(SE, L, I->getOperand(1), OffsetScevs, Depth);

    // See if we need to freeze our fork...
    bool NeedsFreeze = any_of(BaseScevs, UndefPoisonCheck) ||
                       any_of(OffsetScevs, UndefPoisonCheck);

    // Check that we only have a single fork, on either the base or the offset.
    // Copy the SCEV across for the one without a fork in order to generate
    // the full SCEV for both sides of the GEP.
    if (OffsetScevs.size() == 2 && BaseScevs.size() == 1)
      BaseScevs.push_back(BaseScevs[0]);
    else if (BaseScevs.size() == 2 && OffsetScevs.size() == 1)
      OffsetScevs.push_back(OffsetScevs[0]);
    else {
      ScevList.emplace_back(Scev, NeedsFreeze);
      break;
    }

    Type *IntPtrTy = SE->getEffectiveSCEVType(GEP->getPointerOperandType());

    // Find the size of the type being pointed to. We only have a single
    // index term (guarded above) so we don't need to index into arrays or
    // structures, just get the size of the scalar value.
    const SCEV *Size = SE->getSizeOfExpr(IntPtrTy, SourceTy);

    for (auto [B, O] : zip(BaseScevs, OffsetScevs)) {
      const SCEV *Base = get<0>(B);
      const SCEV *Offset = get<0>(O);

      // Scale up the offsets by the size of the type, then add to the bases.
      const SCEV *Scaled =
          SE->getMulExpr(Size, SE->getTruncateOrSignExtend(Offset, IntPtrTy));
      ScevList.emplace_back(SE->getAddExpr(Base, Scaled), NeedsFreeze);
    }
    break;
  }
  case Instruction::Select: {
    SmallVector<PointerIntPair<const SCEV *, 1, bool>, 2> ChildScevs;
    // A select means we've found a forked pointer, but we currently only
    // support a single select per pointer so if there's another behind this
    // then we just bail out and return the generic SCEV.
    findForkedSCEVs(SE, L, I->getOperand(1), ChildScevs, Depth);
    findForkedSCEVs(SE, L, I->getOperand(2), ChildScevs, Depth);
    if (ChildScevs.size() == 2)
      append_range(ScevList, ChildScevs);
    else
      ScevList.emplace_back(Scev, !isGuaranteedNotToBeUndefOrPoison(Ptr));
    break;
  }
  case Instruction::PHI: {
    SmallVector<PointerIntPair<const SCEV *, 1, bool>, 2> ChildScevs;
    // A phi means we've found a forked pointer, but we currently only
    // support a single phi per pointer so if there's another behind this
    // then we just bail out and return the generic SCEV.
    if (I->getNumOperands() == 2) {
      findForkedSCEVs(SE, L, I->getOperand(0), ChildScevs, Depth);
      findForkedSCEVs(SE, L, I->getOperand(1), ChildScevs, Depth);
    }
    if (ChildScevs.size() == 2)
      append_range(ScevList, ChildScevs);
    else
      ScevList.emplace_back(Scev, !isGuaranteedNotToBeUndefOrPoison(Ptr));
    break;
  }
  case Instruction::Add:
  case Instruction::Sub: {
    SmallVector<PointerIntPair<const SCEV *, 1, bool>> LScevs;
    SmallVector<PointerIntPair<const SCEV *, 1, bool>> RScevs;
    findForkedSCEVs(SE, L, I->getOperand(0), LScevs, Depth);
    findForkedSCEVs(SE, L, I->getOperand(1), RScevs, Depth);

    // See if we need to freeze our fork...
    bool NeedsFreeze =
        any_of(LScevs, UndefPoisonCheck) || any_of(RScevs, UndefPoisonCheck);

    // Check that we only have a single fork, on either the left or right side.
    // Copy the SCEV across for the one without a fork in order to generate
    // the full SCEV for both sides of the BinOp.
    if (LScevs.size() == 2 && RScevs.size() == 1)
      RScevs.push_back(RScevs[0]);
    else if (RScevs.size() == 2 && LScevs.size() == 1)
      LScevs.push_back(LScevs[0]);
    else {
      ScevList.emplace_back(Scev, NeedsFreeze);
      break;
    }

    for (auto [L, R] : zip(LScevs, RScevs))
      ScevList.emplace_back(GetBinOpExpr(Opcode, get<0>(L), get<0>(R)),
                            NeedsFreeze);
    break;
  }
  default:
    // Just return the current SCEV if we haven't handled the instruction yet.
    LLVM_DEBUG(dbgs() << "ForkedPtr unhandled instruction: " << *I << "\n");
    ScevList.emplace_back(Scev, !isGuaranteedNotToBeUndefOrPoison(Ptr));
    break;
  }
}

bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
                                          MemAccessInfo Access, Type *AccessTy,
                                          const SymbolicStrideMap &StridesMap,
                                          DenseMap<Value *, unsigned> &DepSetId,
                                          Loop *TheLoop, unsigned &RunningDepId,
                                          unsigned ASId, bool Assume) {
  Value *Ptr = Access.getPointer();
  ScalarEvolution *SE = PSE.getSE();
  const DataLayout &DL = TheLoop->getHeader()->getDataLayout();
  assert(SE->isSCEVable(Ptr->getType()) && "Value is not SCEVable!");

  SmallVector<PointerIntPair<const SCEV *, 1, bool>> RTCheckPtrs;
  findForkedSCEVs(SE, TheLoop, Ptr, RTCheckPtrs, MaxForkedSCEVDepth);
  assert(!RTCheckPtrs.empty() &&
         "Must have some runtime-check pointer candidates");

  // RTCheckPtrs must have size 2 if there are forked pointers. Otherwise, there
  // are no forked pointers; replaceSymbolicStridesSCEV in this case.
  auto IsLoopInvariantOrAR =
      [&SE, &TheLoop](const PointerIntPair<const SCEV *, 1, bool> &P) {
        return SE->isLoopInvariant(P.getPointer(), TheLoop) ||
               isa<SCEVAddRecExpr>(P.getPointer());
      };
  if (RTCheckPtrs.size() == 2 && all_of(RTCheckPtrs, IsLoopInvariantOrAR)) {
    LLVM_DEBUG(dbgs() << "LAA: Found forked pointer: " << *Ptr << "\n";
               for (const auto &[Idx, Q] : enumerate(RTCheckPtrs)) dbgs()
               << "\t(" << Idx << ") " << *Q.getPointer() << "\n");
  } else {
    RTCheckPtrs = {
        {replaceSymbolicStrideSCEV(PSE, TheLoop, StridesMap, Ptr), false}};
  }

  /// Check whether all pointers can participate in a runtime bounds check. They
  /// must either be invariant or non-wrapping affine AddRecs.
  SmallVector<const SCEVPredicate *> Predicates;
  for (auto &P : RTCheckPtrs) {
    // The bounds for loop-invariant pointer is trivial.
    if (SE->isLoopInvariant(P.getPointer(), TheLoop))
      continue;

    const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(P.getPointer());
    if (!AR && Assume)
      AR = PSE.getAsAddRec(Ptr, &Predicates);
    if (!AR || !AR->isAffine()) {
      // Check if bounds for non-affine monotonic expressions can be formed.
      const SCEV *EltSizeSCEV = SE->getStoreSizeOfExpr(
          DL.getIndexType(P.getPointer()->getType()), AccessTy);
      if (!Assume ||
          !getNonAffineMonotonicBounds(TheLoop, P.getPointer(), EltSizeSCEV, SE)
               .first)
        return false;
      continue;
    }

    // If there's only one option for Ptr, commit the predicates collected by
    // getAsAddRec and look Ptr up again afterwards: the lookup below reads the
    // assumptions back from PSE, so they need to be committed first.
    if (RTCheckPtrs.size() == 1) {
      PSE.addPredicates(Predicates);
      Predicates.clear();
      if (auto *StrideAR = dyn_cast<SCEVAddRecExpr>(
              replaceSymbolicStrideSCEV(PSE, TheLoop, StridesMap, Ptr)))
        AR = StrideAR;
      P.setPointer(AR);
    }

    if (!isNoWrap(PSE, AR, RTCheckPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
                  TheLoop, DT, /*Stride=*/std::nullopt,
                  Assume ? &Predicates : nullptr))
      return false;
  }
  PSE.addPredicates(Predicates);

  // Remember the number of pointers inserted so far, to remove the pointers of
  // this access again if the bounds of any of them cannot be computed, to avoid
  // partial inserts.
  unsigned NumPointers = RtCheck.Pointers.size();
  for (const auto &[PtrExpr, NeedsFreeze] : RTCheckPtrs) {
    // The id of the dependence set.
    unsigned DepId;

    if (DepCands.contains(Access)) {
      Value *Leader = DepCands.getLeaderValue(Access).getPointer();
      unsigned &LeaderId = DepSetId[Leader];
      if (!LeaderId)
        LeaderId = RunningDepId++;
      DepId = LeaderId;
    } else
      // Each access has its own dependence set.
      DepId = RunningDepId++;

    bool IsWrite = Access.getInt();
    if (!RtCheck.insert(TheLoop, Ptr, PtrExpr, AccessTy, IsWrite, DepId, ASId,
                        PSE, NeedsFreeze,
                        /*IsForked=*/RTCheckPtrs.size() > 1)) {
      RtCheck.Pointers.truncate(NumPointers);
      return false;
    }
    LLVM_DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n');
  }

  return true;
}

bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
                                     Loop *TheLoop,
                                     const SymbolicStrideMap &StridesMap,
                                     Value *&UncomputablePtr, bool AllowPartial,
                                     const MemoryDepChecker &DepChecker) {
  // Find pointers with computable bounds. We are going to use this information
  // to place a runtime bound check.
  bool CanDoRT = true;

  bool MayNeedRTCheck = false;
  if (!IsRTCheckAnalysisNeeded) return true;

  if (auto *Deps = DepChecker.getDependences()) {
    // If there are unknown dependences, this means runtime checks are needed to
    // ensure there's no overlap between accesses to the same underlying object.
    // Remove the equivalence classes containing both source and destination
    // accesses from DepCands. This ensures runtime checks will be generated
    // between those accesses and prevents them from being grouped together.
    for (const auto &Dep : *Deps) {
      if (Dep.Type != MemoryDepChecker::Dependence::Unknown) {
        assert(MemoryDepChecker::Dependence::isSafeForVectorization(Dep.Type) ==
                   MemoryDepChecker::VectorizationSafetyStatus::Safe &&
               "Should only skip safe dependences");
        continue;
      }
      Instruction *Src = Dep.getSource(DepChecker);
      Instruction *Dst = Dep.getDestination(DepChecker);
      DepCands.eraseClass({getPointerOperand(Src), Src->mayWriteToMemory()});
      DepCands.eraseClass({getPointerOperand(Dst), Dst->mayWriteToMemory()});
    }
  } else {
    CheckDeps.clear();
    DepCands = {};
  }

  // We assign a consecutive id to access from different alias sets.
  // Accesses between different groups doesn't need to be checked.
  unsigned ASId = 0;
  for (const auto &AS : AST) {
    int NumReadPtrChecks = 0;
    int NumWritePtrChecks = 0;
    bool CanDoAliasSetRT = true;
    ++ASId;
    auto ASPointers = AS.getPointers();

    // We assign consecutive id to access from different dependence sets.
    // Accesses within the same set don't need a runtime check.
    unsigned RunningDepId = 1;
    DenseMap<Value *, unsigned> DepSetId;

    SmallVector<std::pair<MemAccessInfo, Type *>, 4> Retries;

    // First, count how many write and read accesses are in the alias set. Also
    // collect MemAccessInfos for later.
    SmallVector<MemAccessInfo, 4> AccessInfos;
    for (const Value *ConstPtr : ASPointers) {
      Value *Ptr = const_cast<Value *>(ConstPtr);
      bool IsWrite = Accesses.contains(MemAccessInfo(Ptr, true));
      if (IsWrite)
        ++NumWritePtrChecks;
      else
        ++NumReadPtrChecks;
      AccessInfos.emplace_back(Ptr, IsWrite);
    }

    // We do not need runtime checks for this alias set, if there are no writes
    // or a single write and no reads.
    if (NumWritePtrChecks == 0 ||
        (NumWritePtrChecks == 1 && NumReadPtrChecks == 0)) {
      assert((ASPointers.size() <= 1 ||
              all_of(ASPointers,
                     [this](const Value *Ptr) {
                       MemAccessInfo AccessWrite(const_cast<Value *>(Ptr),
                                                 true);
                       return !DepCands.contains(AccessWrite);
                     })) &&
             "Can only skip updating CanDoRT below, if all entries in AS "
             "are reads or there is at most 1 entry");
      continue;
    }

    const DataLayout &DL = TheLoop->getHeader()->getDataLayout();
    auto StoreSize = [&DL](Type *Ty) { return DL.getTypeStoreSize(Ty); };

    for (auto &Access : AccessInfos) {
      // A written pointer is only checked via its write access, so its bounds
      // must also cover the types it is loaded with.
      SmallSetVector<Type *, 1> AccessTys = Accesses.lookup(Access);
      if (Access.getInt()) {
        auto ReadIt = Accesses.find(MemAccessInfo(Access.getPointer(), false));
        if (ReadIt != Accesses.end())
          AccessTys.insert_range(ReadIt->second);
      }

      // The widest fixed and scalable types cover all accesses of their kind.
      for (bool Scalable : {false, true}) {
        auto HasMatchingSizeKind = [&](Type *Ty) {
          return StoreSize(Ty).isScalable() == Scalable;
        };
        auto Tys = make_filter_range(AccessTys, std::ref(HasMatchingSizeKind));
        if (Tys.empty())
          continue;

        Type *AccessTy = *max_element(Tys, [&](Type *A, Type *B) {
          return TypeSize::isKnownLT(StoreSize(A), StoreSize(B));
        });

        if (!createCheckForAccess(RtCheck, Access, AccessTy, StridesMap,
                                  DepSetId, TheLoop, RunningDepId, ASId,
                                  /*Assume=*/false)) {
          LLVM_DEBUG(dbgs() << "LAA: Can't find bounds for ptr:"
                            << *Access.getPointer() << '\n');
          Retries.emplace_back(Access, AccessTy);
          CanDoAliasSetRT = false;
        }
      }
    }

    // Note that this function computes CanDoRT and MayNeedRTCheck
    // independently. For example CanDoRT=false, MayNeedRTCheck=false means that
    // we have a pointer for which we couldn't find the bounds but we don't
    // actually need to emit any checks so it does not matter.
    //
    // We need runtime checks for this alias set, if there are at least 2
    // dependence sets (in which case RunningDepId > 2) or if we need to re-try
    // any bound checks (because in that case the number of dependence sets is
    // incomplete).
    bool NeedsAliasSetRTCheck = RunningDepId > 2 || !Retries.empty();

    // We need to perform run-time alias checks, but some pointers had bounds
    // that couldn't be checked.
    if (NeedsAliasSetRTCheck && !CanDoAliasSetRT) {
      // Reset the CanDoSetRt flag and retry all accesses that have failed.
      // We know that we need these checks, so we can now be more aggressive
      // and add further checks if required (overflow checks).
      CanDoAliasSetRT = true;
      for (const auto &[Access, AccessTy] : Retries) {
        if (!createCheckForAccess(RtCheck, Access, AccessTy, StridesMap,
                                  DepSetId, TheLoop, RunningDepId, ASId,
                                  /*Assume=*/true)) {
          CanDoAliasSetRT = false;
          UncomputablePtr = Access.getPointer();
          if (!AllowPartial)
            break;
        }
      }
    }

    CanDoRT &= CanDoAliasSetRT;
    MayNeedRTCheck |= NeedsAliasSetRTCheck;
    ++ASId;
  }

  // If the pointers that we would use for the bounds comparison have different
  // address spaces, assume the values aren't directly comparable, so we can't
  // use them for the runtime check. We also have to assume they could
  // overlap. In the future there should be metadata for whether address spaces
  // are disjoint.
  unsigned NumPointers = RtCheck.Pointers.size();
  for (unsigned i = 0; i < NumPointers; ++i) {
    for (unsigned j = i + 1; j < NumPointers; ++j) {
      // Only need to check pointers between two different dependency sets.
      if (RtCheck.Pointers[i].DependencySetId ==
          RtCheck.Pointers[j].DependencySetId)
       continue;
      // Only need to check pointers in the same alias set.
      if (RtCheck.Pointers[i].AliasSetId != RtCheck.Pointers[j].AliasSetId)
        continue;

      Value *PtrI = RtCheck.Pointers[i].PointerValue;
      Value *PtrJ = RtCheck.Pointers[j].PointerValue;

      unsigned ASi = PtrI->getType()->getPointerAddressSpace();
      unsigned ASj = PtrJ->getType()->getPointerAddressSpace();
      if (ASi != ASj) {
        LLVM_DEBUG(
            dbgs() << "LAA: Runtime check would require comparison between"
                      " different address spaces\n");
        return false;
      }
    }
  }

  if (MayNeedRTCheck && (CanDoRT || AllowPartial))
    RtCheck.generateChecks(DepCands);

  LLVM_DEBUG(dbgs() << "LAA: We need to do " << RtCheck.getNumberOfChecks()
                    << " pointer comparisons.\n");

  // If we can do run-time checks, but there are no checks, no runtime checks
  // are needed. This can happen when all pointers point to the same underlying
  // object for example.
  RtCheck.Need = CanDoRT ? RtCheck.getNumberOfChecks() != 0 : MayNeedRTCheck;

  bool CanDoRTIfNeeded = !RtCheck.Need || CanDoRT;
  assert(CanDoRTIfNeeded == (CanDoRT || !MayNeedRTCheck) &&
         "CanDoRTIfNeeded depends on RtCheck.Need");
  if (!CanDoRTIfNeeded && !AllowPartial)
    RtCheck.reset();
  return CanDoRTIfNeeded;
}

void AccessAnalysis::buildDependenceSets() {
  // We process the set twice: first we process read-write pointers, last we
  // process read-only pointers. This allows us to skip dependence tests for
  // read-only pointers.

  LLVM_DEBUG(dbgs() << "LAA: Processing memory accesses...\n");
  LLVM_DEBUG(dbgs() << "  AST: "; AST.dump());
  LLVM_DEBUG(dbgs() << "LAA:   Accesses(" << Accesses.size() << "):\n");
  LLVM_DEBUG({
    for (const auto &[A, _] : Accesses)
      dbgs() << "\t" << *A.getPointer() << " ("
             << (A.getInt()
                     ? "write"
                     : (ReadOnlyPtr.contains(A.getPointer()) ? "read-only"
                                                             : "read"))
             << ")\n";
  });

  // The AliasSetTracker has nicely partitioned our pointers by metadata
  // compatibility and potential for underlying-object overlap. As a result, we
  // only need to check for potential pointer dependencies within each alias
  // set.
  for (const auto &AS : AST) {
    bool AliasSetHasWrite = false;

    // Map of (pointer to underlying objects, accessed address space) to last
    // access encountered.
    using UnderlyingObjToAccessMap =
        DenseMap<std::pair<const Value *, unsigned>, MemAccessInfo>;
    UnderlyingObjToAccessMap ObjToLastAccess;

    // Set of access to check after all writes have been processed.
    PtrAccessMap DeferredAccesses;

    // Iterate over each alias set twice, once to process read/write pointers,
    // and then to process read-only pointers.

    auto ProcessAccesses = [&](bool UseDeferred) {
      PtrAccessMap &S = UseDeferred ? DeferredAccesses : Accesses;

      // Note that both the alias-set tracker and the alias sets themselves used
      // ordered collections internally and so the iteration order here is
      // deterministic.
      for (const Value *ConstPtr : AS.getPointers()) {
        Value *Ptr = const_cast<Value *>(ConstPtr);

        // For a single memory access in AliasSetTracker, Accesses may contain
        // both read and write, and they both need to be handled for CheckDeps.
        for (auto [AccessPtr, IsWrite] : S.keys()) {
          if (AccessPtr != Ptr)
            continue;

          // If we're using the deferred access set, then it contains only
          // reads.
          bool IsReadOnlyPtr = ReadOnlyPtr.contains(Ptr) && !IsWrite;
          if (UseDeferred && !IsReadOnlyPtr)
            continue;
          // Otherwise, the pointer must be in the PtrAccessSet, either as a
          // read or a write.
          assert(((IsReadOnlyPtr && UseDeferred) || IsWrite ||
                  S.contains(MemAccessInfo(Ptr, false))) &&
                 "Alias-set pointer not in the access set?");

          MemAccessInfo Access(Ptr, IsWrite);
          DepCands.insert(Access);

          // Memorize read-only pointers for later processing and skip them in
          // the first round (they need to be checked after we have seen all
          // write pointers). Note: we also mark pointer that are not
          // consecutive as "read-only" pointers (so that we check
          // "a[b[i]] +="). Hence, we need the second check for "!IsWrite".
          if (!UseDeferred && IsReadOnlyPtr) {
            // We only use the pointer keys, the types vector values don't
            // matter.
            DeferredAccesses.insert({Access, {}});
            continue;
          }

          // If this is a write - check other reads and writes for conflicts. If
          // this is a read only check other writes for conflicts (but only if
          // there is no other write to the ptr - this is an optimization to
          // catch "a[i] = a[i] + " without having to do a dependence check).
          if ((IsWrite || IsReadOnlyPtr) && AliasSetHasWrite) {
            CheckDeps.push_back(Access);
            IsRTCheckAnalysisNeeded = true;
          }

          if (IsWrite)
            AliasSetHasWrite = true;

          // Create sets of pointers connected by a shared alias set and
          // underlying object.
          SmallVector<const Value *, 16> &UOs = UnderlyingObjects[Ptr];
          UOs = {};
          ::getUnderlyingObjects(Ptr, UOs, LI);
          LLVM_DEBUG(dbgs()
                     << "Underlying objects for pointer " << *Ptr << "\n");
          for (const Value *UnderlyingObj : UOs) {
            // nullptr never alias, don't join sets for pointer that have "null"
            // in their UnderlyingObjects list.
            if (isa<ConstantPointerNull>(UnderlyingObj) &&
                !NullPointerIsDefined(
                    TheLoop->getHeader()->getParent(),
                    UnderlyingObj->getType()->getPointerAddressSpace()))
              continue;

            auto [It, Inserted] = ObjToLastAccess.try_emplace(
                {UnderlyingObj,
                 cast<PointerType>(Ptr->getType())->getAddressSpace()},
                Access);
            if (!Inserted) {
              DepCands.unionSets(Access, It->second);
              It->second = Access;
            }

            LLVM_DEBUG(dbgs() << "  " << *UnderlyingObj << "\n");
          }
        }
      }
    };

    ProcessAccesses(false);
    ProcessAccesses(true);
  }
}

/// Check whether the access through \p Ptr has a constant stride.
std::optional<int64_t>
llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
                   const Loop *Lp, const DominatorTree &DT,
                   const SymbolicStrideMap &StridesMap, bool ShouldCheckWrap,
                   SmallVectorImpl<const SCEVPredicate *> *Predicates) {
  const SCEV *PtrScev =
      replaceSymbolicStrideSCEV(PSE, Lp, StridesMap, Ptr, Predicates);
  if (PSE.getSE()->isLoopInvariant(PtrScev, Lp))
    return 0;

  assert(Ptr->getType()->isPointerTy() && "Unexpected non-ptr");

  const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev);
  if (Predicates && !AR) {
    AR = PSE.getSE()->convertSCEVToAddRecWithPredicates(PtrScev, Lp,
                                                        *Predicates);
  }

  if (!AR) {
    LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not an AddRecExpr pointer " << *Ptr
                      << " SCEV: " << *PtrScev << "\n");
    return std::nullopt;
  }

  std::optional<int64_t> Stride =
      getStrideFromAddRec(AR, Lp, AccessTy, Ptr, PSE);
  if (!ShouldCheckWrap || !Stride)
    return Stride;

  if (isNoWrap(PSE, AR, Ptr, AccessTy, Lp, DT, Stride, Predicates))
    return Stride;

  LLVM_DEBUG(
      dbgs() << "LAA: Bad stride - Pointer may wrap in the address space "
             << *Ptr << " SCEV: " << *AR << "\n");
  return std::nullopt;
}

std::optional<int64_t> llvm::getPointersDiff(Type *ElemTyA, Value *PtrA,
                                             Type *ElemTyB, Value *PtrB,
                                             const DataLayout &DL,
                                             ScalarEvolution &SE,
                                             bool StrictCheck, bool CheckType) {
  assert(PtrA && PtrB && "Expected non-nullptr pointers.");

  // Make sure that A and B are different pointers.
  if (PtrA == PtrB)
    return 0;

  // Make sure that the element types are the same if required.
  if (CheckType && ElemTyA != ElemTyB)
    return std::nullopt;

  unsigned ASA = PtrA->getType()->getPointerAddressSpace();
  unsigned ASB = PtrB->getType()->getPointerAddressSpace();

  // Check that the address spaces match.
  if (ASA != ASB)
    return std::nullopt;
  unsigned IdxWidth = DL.getIndexSizeInBits(ASA);

  APInt OffsetA(IdxWidth, 0), OffsetB(IdxWidth, 0);
  const Value *PtrA1 = PtrA->stripAndAccumulateConstantOffsets(
      DL, OffsetA, /*AllowNonInbounds=*/true);
  const Value *PtrB1 = PtrB->stripAndAccumulateConstantOffsets(
      DL, OffsetB, /*AllowNonInbounds=*/true);

  std::optional<int64_t> Val;
  if (PtrA1 == PtrB1) {
    // Retrieve the address space again as pointer stripping now tracks through
    // `addrspacecast`.
    ASA = cast<PointerType>(PtrA1->getType())->getAddressSpace();
    ASB = cast<PointerType>(PtrB1->getType())->getAddressSpace();
    // Check that the address spaces match and that the pointers are valid.
    if (ASA != ASB)
      return std::nullopt;

    IdxWidth = DL.getIndexSizeInBits(ASA);
    OffsetA = OffsetA.sextOrTrunc(IdxWidth);
    OffsetB = OffsetB.sextOrTrunc(IdxWidth);

    OffsetB -= OffsetA;
    Val = OffsetB.trySExtValue();
  } else {
    // Otherwise compute the distance with SCEV between the base pointers.
    const SCEV *PtrSCEVA = SE.getSCEV(PtrA);
    const SCEV *PtrSCEVB = SE.getSCEV(PtrB);
    std::optional<APInt> Diff =
        SE.computeConstantDifference(PtrSCEVB, PtrSCEVA);
    if (!Diff)
      return std::nullopt;
    Val = Diff->trySExtValue();
  }

  if (!Val)
    return std::nullopt;

  int64_t Size = DL.getTypeStoreSize(ElemTyA);
  int64_t Dist = *Val / Size;

  // Ensure that the calculated distance matches the type-based one after all
  // the bitcasts removal in the provided pointers.
  if (!StrictCheck || Dist * Size == Val)
    return Dist;
  return std::nullopt;
}

bool llvm::sortPtrAccesses(ArrayRef<Value *> VL, Type *ElemTy,
                           const DataLayout &DL, ScalarEvolution &SE,
                           SmallVectorImpl<unsigned> &SortedIndices) {
  assert(llvm::all_of(
             VL, [](const Value *V) { return V->getType()->isPointerTy(); }) &&
         "Expected list of pointer operands.");
  // Walk over the pointers, and map each of them to an offset relative to
  // first pointer in the array.
  Value *Ptr0 = VL[0];

  using DistOrdPair = std::pair<int64_t, unsigned>;
  auto Compare = llvm::less_first();
  std::set<DistOrdPair, decltype(Compare)> Offsets(Compare);
  Offsets.emplace(0, 0);
  bool IsConsecutive = true;
  for (auto [Idx, Ptr] : drop_begin(enumerate(VL))) {
    std::optional<int64_t> Diff =
        getPointersDiff(ElemTy, Ptr0, ElemTy, Ptr, DL, SE,
                        /*StrictCheck=*/true);
    if (!Diff)
      return false;

    // Check if the pointer with the same offset is found.
    int64_t Offset = *Diff;
    auto [It, IsInserted] = Offsets.emplace(Offset, Idx);
    if (!IsInserted)
      return false;
    // Consecutive order if the inserted element is the last one.
    IsConsecutive &= std::next(It) == Offsets.end();
  }
  SortedIndices.clear();
  if (!IsConsecutive) {
    // Fill SortedIndices array only if it is non-consecutive.
    SortedIndices.resize(VL.size());
    for (auto [Idx, Off] : enumerate(Offsets))
      SortedIndices[Idx] = Off.second;
  }
  return true;
}

/// Returns true if the memory operations \p A and \p B are consecutive.
bool llvm::isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL,
                               ScalarEvolution &SE, bool CheckType) {
  Value *PtrA = getLoadStorePointerOperand(A);
  Value *PtrB = getLoadStorePointerOperand(B);
  if (!PtrA || !PtrB)
    return false;
  Type *ElemTyA = getLoadStoreType(A);
  Type *ElemTyB = getLoadStoreType(B);
  std::optional<int64_t> Diff =
      getPointersDiff(ElemTyA, PtrA, ElemTyB, PtrB, DL, SE,
                      /*StrictCheck=*/true, CheckType);
  return Diff == 1;
}

void MemoryDepChecker::addAccess(StoreInst *SI) {
  visitPointers(SI->getPointerOperand(), *InnermostLoop,
                [this, SI](Value *Ptr) {
                  Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx);
                  InstMap.push_back(SI);
                  ++AccessIdx;
                });
}

void MemoryDepChecker::addAccess(LoadInst *LI) {
  visitPointers(LI->getPointerOperand(), *InnermostLoop,
                [this, LI](Value *Ptr) {
                  Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx);
                  InstMap.push_back(LI);
                  ++AccessIdx;
                });
}

MemoryDepChecker::VectorizationSafetyStatus
MemoryDepChecker::Dependence::isSafeForVectorization(DepType Type) {
  switch (Type) {
  case NoDep:
  case Forward:
  case BackwardVectorizable:
    return VectorizationSafetyStatus::Safe;

  case Unknown:
    return VectorizationSafetyStatus::PossiblySafeWithRtChecks;
  case ForwardButPreventsForwarding:
  case Backward:
  case BackwardVectorizableButPreventsForwarding:
  case IndirectUnsafe:
  case InvariantUnsafe:
    return VectorizationSafetyStatus::Unsafe;
  }
  llvm_unreachable("unexpected DepType!");
}

bool MemoryDepChecker::Dependence::isBackward() const {
  switch (Type) {
  case NoDep:
  case Forward:
  case ForwardButPreventsForwarding:
  case Unknown:
  case IndirectUnsafe:
  case InvariantUnsafe:
    return false;

  case BackwardVectorizable:
  case Backward:
  case BackwardVectorizableButPreventsForwarding:
    return true;
  }
  llvm_unreachable("unexpected DepType!");
}

bool MemoryDepChecker::Dependence::isPossiblyBackward() const {
  return isBackward() || Type == Unknown || Type == IndirectUnsafe ||
         Type == InvariantUnsafe;
}

bool MemoryDepChecker::Dependence::isForward() const {
  switch (Type) {
  case Forward:
  case ForwardButPreventsForwarding:
    return true;

  case NoDep:
  case Unknown:
  case BackwardVectorizable:
  case Backward:
  case BackwardVectorizableButPreventsForwarding:
  case IndirectUnsafe:
  case InvariantUnsafe:
    return false;
  }
  llvm_unreachable("unexpected DepType!");
}

bool MemoryDepChecker::couldPreventStoreLoadForward(uint64_t Distance,
                                                    uint64_t TypeByteSize,
                                                    unsigned CommonStride) {
  // If loads occur at a distance that is not a multiple of a feasible vector
  // factor store-load forwarding does not take place.
  // Positive dependences might cause troubles because vectorizing them might
  // prevent store-load forwarding making vectorized code run a lot slower.
  //   a[i] = a[i-3] ^ a[i-8];
  //   The stores to a[i:i+1] don't align with the stores to a[i-3:i-2] and
  //   hence on your typical architecture store-load forwarding does not take
  //   place. Vectorizing in such cases does not make sense.
  // Store-load forwarding distance.

  // Maximum vector factor.
  uint64_t MaxVFWithoutSLForwardIssuesPowerOf2 =
      std::min(VectorizerParams::MaxVectorWidth * TypeByteSize,
               MaxStoreLoadForwardSafeDistanceInBits);

  // Compute the smallest VF at which the store and load would be misaligned
  // and recent enough to still be in the store buffer.
  for (uint64_t VF = 2 * TypeByteSize;
       VF <= MaxVFWithoutSLForwardIssuesPowerOf2; VF *= 2) {
    if (isStoreLoadForwardingConflict(Distance, VF, TypeByteSize, VF)) {
      MaxVFWithoutSLForwardIssuesPowerOf2 = (VF >> 1);
      break;
    }
  }

  if (MaxVFWithoutSLForwardIssuesPowerOf2 < 2 * TypeByteSize) {
    LLVM_DEBUG(
        dbgs() << "LAA: Distance " << Distance
               << " that could cause a store-load forwarding conflict\n");
    return true;
  }

  if (CommonStride &&
      MaxVFWithoutSLForwardIssuesPowerOf2 <
          MaxStoreLoadForwardSafeDistanceInBits &&
      MaxVFWithoutSLForwardIssuesPowerOf2 !=
          VectorizerParams::MaxVectorWidth * TypeByteSize) {
    uint64_t MaxVF =
        bit_floor(MaxVFWithoutSLForwardIssuesPowerOf2 / CommonStride);
    uint64_t MaxVFInBits = MaxVF * TypeByteSize * 8;
    MaxStoreLoadForwardSafeDistanceInBits =
        std::min(MaxStoreLoadForwardSafeDistanceInBits, MaxVFInBits);

    if (MaxVF < 2) {
      LLVM_DEBUG(
          dbgs() << "LAA: strided access with Distance " << Distance
                 << " that could cause a store-load forwarding conflict\n");
      return true;
    }
  }
  return false;
}

void MemoryDepChecker::mergeInStatus(VectorizationSafetyStatus S) {
  if (Status < S)
    Status = S;
}

/// Given a dependence-distance \p Dist between two memory accesses, that have
/// strides in the same direction whose absolute value of the maximum stride is
/// given in \p MaxStride, in a loop whose maximum backedge taken count is \p
/// MaxBTC, check if it is possible to prove statically that the dependence
/// distance is larger than the range that the accesses will travel through the
/// execution of the loop. If so, return true; false otherwise. This is useful
/// for example in loops such as the following (PR31098):
///
///     for (i = 0; i < D; ++i) {
///                = out[i];
///       out[i+D] =
///     }
static bool isSafeDependenceDistance(ScalarEvolution &SE, const SCEV &MaxBTC,
                                     const SCEV &Dist, uint64_t MaxStride) {

  // If we can prove that
  //      (**) |Dist| > MaxBTC * Step
  // where Step is the absolute stride of the memory accesses in bytes,
  // then there is no dependence.
  //
  // Rationale:
  // We basically want to check if the absolute distance (|Dist/Step|)
  // is >= the loop iteration count (or > MaxBTC).
  // This is equivalent to the Strong SIV Test (Practical Dependence Testing,
  // Section 4.2.1); Note, that for vectorization it is sufficient to prove
  // that the dependence distance is >= VF; This is checked elsewhere.
  // But in some cases we can prune dependence distances early, and
  // even before selecting the VF, and without a runtime test, by comparing
  // the distance against the loop iteration count. Since the vectorized code
  // will be executed only if LoopCount >= VF, proving distance >= LoopCount
  // also guarantees that distance >= VF.
  //
  // The dependence distance can be positive/negative, so we sign-extend Dist.
  // MaxBTC is non-negative, so we zero-extended to the wider type before
  // computing MaxBTC * Step.
  // FIXME: The checks below can still wrap if MaxBTC * MaxStride does not fit
  // in WideTy with two bits to spare, e.g. for an unbounded i64 MaxBTC.
  Type *WideTy = SE.getWiderType(Dist.getType(), MaxBTC.getType());
  const SCEV *Step = SE.getConstant(WideTy, MaxStride);
  const SCEV *CastedDist = SE.getNoopOrSignExtend(&Dist, WideTy);
  const SCEV *CastedProduct =
      SE.getMulExpr(SE.getNoopOrZeroExtend(&MaxBTC, WideTy), Step);

  // Is  Dist - (MaxBTC * Step) > 0 ?
  // (If so, then we have proven (**) because |Dist| >= Dist)
  const SCEV *Minus = SE.getMinusSCEV(CastedDist, CastedProduct);
  if (SE.isKnownPositive(Minus))
    return true;

  // Second try: Is  -Dist - (MaxBTC * Step) > 0 ?
  // (If so, then we have proven (**) because |Dist| >= -1*Dist)
  const SCEV *NegDist = SE.getNegativeSCEV(CastedDist);
  Minus = SE.getMinusSCEV(NegDist, CastedProduct);
  return SE.isKnownPositive(Minus);
}

/// Check the dependence for two accesses with the same stride \p Stride.
/// \p Distance is the positive distance in bytes, and \p TypeByteSize is type
/// size in bytes.
///
/// \returns true if they are independent.
static bool areStridedAccessesIndependent(uint64_t Distance, uint64_t Stride,
                                          uint64_t TypeByteSize) {
  assert(Stride > 1 && "The stride must be greater than 1");
  assert(TypeByteSize > 0 && "The type size in byte must be non-zero");
  assert(Distance > 0 && "The distance must be non-zero");

  // Skip if the distance is not multiple of type byte size.
  if (Distance % TypeByteSize)
    return false;

  // No dependence if the distance is not multiple of the stride.
  // E.g.
  //      for (i = 0; i < 1024 ; i += 4)
  //        A[i+2] = A[i] + 1;
  //
  // Two accesses in memory (distance is 2, stride is 4):
  //     | A[0] |      |      |      | A[4] |      |      |      |
  //     |      |      | A[2] |      |      |      | A[6] |      |
  //
  // E.g.
  //      for (i = 0; i < 1024 ; i += 3)
  //        A[i+4] = A[i] + 1;
  //
  // Two accesses in memory (distance is 4, stride is 3):
  //     | A[0] |      |      | A[3] |      |      | A[6] |      |      |
  //     |      |      |      |      | A[4] |      |      | A[7] |      |
  return Distance % Stride;
}

bool MemoryDepChecker::areAccessesCompletelyBeforeOrAfter(const SCEV *Src,
                                                          Type *SrcTy,
                                                          const SCEV *Sink,
                                                          Type *SinkTy) {
  const SCEV *BTC = PSE.getBackedgeTakenCount();
  const SCEV *SymbolicMaxBTC = PSE.getSymbolicMaxBackedgeTakenCount();
  ScalarEvolution &SE = *PSE.getSE();
  const auto &[SrcStart_, SrcEnd_] =
      getStartAndEndForAccess(InnermostLoop, Src, SrcTy, BTC, SymbolicMaxBTC,
                              &SE, &PointerBounds, DT, AC, LoopGuards);
  if (isa<SCEVCouldNotCompute>(SrcStart_) || isa<SCEVCouldNotCompute>(SrcEnd_))
    return false;

  const auto &[SinkStart_, SinkEnd_] =
      getStartAndEndForAccess(InnermostLoop, Sink, SinkTy, BTC, SymbolicMaxBTC,
                              &SE, &PointerBounds, DT, AC, LoopGuards);
  if (isa<SCEVCouldNotCompute>(SinkStart_) ||
      isa<SCEVCouldNotCompute>(SinkEnd_))
    return false;

  auto SrcEnd = SE.applyLoopGuards(SrcEnd_, LoopGuards);
  auto SinkStart = SE.applyLoopGuards(SinkStart_, LoopGuards);
  if (SE.isKnownPredicate(CmpInst::ICMP_ULE, SrcEnd, SinkStart))
    return true;

  auto SinkEnd = SE.applyLoopGuards(SinkEnd_, LoopGuards);
  auto SrcStart = SE.applyLoopGuards(SrcStart_, LoopGuards);
  return SE.isKnownPredicate(CmpInst::ICMP_ULE, SinkEnd, SrcStart);
}

std::variant<MemoryDepChecker::Dependence::DepType,
             MemoryDepChecker::DepDistanceStrideAndSizeInfo>
MemoryDepChecker::getDependenceDistanceStrideAndSize(
    const AccessAnalysis::MemAccessInfo &A, Instruction *AInst,
    const AccessAnalysis::MemAccessInfo &B, Instruction *BInst) {
  const auto &DL = InnermostLoop->getHeader()->getDataLayout();
  auto &SE = *PSE.getSE();
  const auto &[APtr, AIsWrite] = A;
  const auto &[BPtr, BIsWrite] = B;

  // Two reads are independent.
  if (!AIsWrite && !BIsWrite)
    return MemoryDepChecker::Dependence::NoDep;

  Type *ATy = getLoadStoreType(AInst);
  Type *BTy = getLoadStoreType(BInst);

  // We cannot check pointers in different address spaces.
  if (APtr->getType()->getPointerAddressSpace() !=
      BPtr->getType()->getPointerAddressSpace())
    return MemoryDepChecker::Dependence::Unknown;

  SmallVector<const SCEVPredicate *> Predicates;
  std::optional<int64_t> StrideAPtr =
      getPtrStride(PSE, ATy, APtr, InnermostLoop, *DT, SymbolicStrides,
                   /*ShouldCheckWrap=*/true, &Predicates);
  std::optional<int64_t> StrideBPtr =
      getPtrStride(PSE, BTy, BPtr, InnermostLoop, *DT, SymbolicStrides,
                   /*ShouldCheckWrap=*/true, &Predicates);
  PSE.addPredicates(Predicates);

  const SCEV *Src = PSE.getSCEV(APtr);
  const SCEV *Sink = PSE.getSCEV(BPtr);

  // If the induction step is negative we have to invert source and sink of the
  // dependence when measuring the distance between them. We should not swap
  // AIsWrite with BIsWrite, as their uses expect them in program order.
  if (StrideAPtr && *StrideAPtr < 0) {
    std::swap(Src, Sink);
    std::swap(AInst, BInst);
    std::swap(ATy, BTy);
    std::swap(StrideAPtr, StrideBPtr);
  }

  const SCEV *Dist = SE.getMinusSCEV(Sink, Src);

  LLVM_DEBUG(dbgs() << "LAA: Src Scev: " << *Src << "Sink Scev: " << *Sink
                    << "\n");
  LLVM_DEBUG(dbgs() << "LAA: Distance for " << *AInst << " to " << *BInst
                    << ": " << *Dist << "\n");

  // Need accesses with constant strides and the same direction for further
  // dependence analysis. We don't want to vectorize "A[B[i]] += ..." and
  // similar code or pointer arithmetic that could wrap in the address space.

  // If either Src or Sink are not strided (i.e. not a non-wrapping AddRec) and
  // not loop-invariant (stride will be 0 in that case), we cannot analyze the
  // dependence further and also cannot generate runtime checks.
  if (!StrideAPtr || !StrideBPtr) {
    LLVM_DEBUG(dbgs() << "Pointer access with non-constant stride\n");
    return MemoryDepChecker::Dependence::IndirectUnsafe;
  }

  int64_t StrideAPtrInt = *StrideAPtr;
  int64_t StrideBPtrInt = *StrideBPtr;
  LLVM_DEBUG(dbgs() << "LAA:  Src induction step: " << StrideAPtrInt
                    << " Sink induction step: " << StrideBPtrInt << "\n");
  // At least Src or Sink are loop invariant and the other is strided or
  // invariant.
  if (!StrideAPtrInt || !StrideBPtrInt) {
    // If both are loop-invariant and access the same location, we cannot
    // vectorize.
    if (!StrideAPtrInt && !StrideBPtrInt && Dist->isZero())
      return MemoryDepChecker::Dependence::InvariantUnsafe;
    // Otherwise, we can generate a runtime check to disambiguate the accesses.
    return MemoryDepChecker::Dependence::Unknown;
  }

  // Both Src and Sink have a constant stride, check if they are in the same
  // direction.
  if ((StrideAPtrInt > 0) != (StrideBPtrInt > 0)) {
    LLVM_DEBUG(
        dbgs() << "Pointer access with strides in different directions\n");
    return MemoryDepChecker::Dependence::Unknown;
  }

  TypeSize AStoreSz = DL.getTypeStoreSize(ATy);
  TypeSize BStoreSz = DL.getTypeStoreSize(BTy);

  // If store sizes are not the same, set TypeByteSize to zero, so we can check
  // it in the caller isDependent.
  uint64_t ASz = DL.getTypeAllocSize(ATy);
  uint64_t BSz = DL.getTypeAllocSize(BTy);
  uint64_t TypeByteSize = (AStoreSz == BStoreSz) ? BSz : 0;

  uint64_t StrideAScaled = AbsoluteValue(StrideAPtrInt) * ASz;
  uint64_t StrideBScaled = AbsoluteValue(StrideBPtrInt) * BSz;

  uint64_t MaxStride = std::max(StrideAScaled, StrideBScaled);

  std::optional<uint64_t> CommonStride;
  if (StrideAScaled == StrideBScaled)
    CommonStride = StrideAScaled;

  // TODO: Historically, we didn't retry with runtime checks when (unscaled)
  // strides were different but there is no inherent reason to.
  if (!isa<SCEVConstant>(Dist))
    ShouldRetryWithRuntimeChecks |= StrideAPtrInt == StrideBPtrInt;

  // If distance is a SCEVCouldNotCompute, return Unknown immediately.
  if (isa<SCEVCouldNotCompute>(Dist)) {
    LLVM_DEBUG(dbgs() << "LAA: Uncomputable distance.\n");
    return Dependence::Unknown;
  }

  return DepDistanceStrideAndSizeInfo(Dist, MaxStride, CommonStride,
                                      TypeByteSize, AIsWrite, BIsWrite);
}

MemoryDepChecker::Dependence::DepType
MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
                              const MemAccessInfo &B, unsigned BIdx) {
  assert(AIdx < BIdx && "Must pass arguments in program order");

  // Check if we can prove that Sink only accesses memory after Src's end or
  // vice versa. The helper is used to perform the checks only on the exit paths
  // where it helps to improve the analysis result.
  auto CheckCompletelyBeforeOrAfter = [&]() {
    auto *APtr = A.getPointer();
    auto *BPtr = B.getPointer();
    Type *ATy = getLoadStoreType(InstMap[AIdx]);
    Type *BTy = getLoadStoreType(InstMap[BIdx]);
    const SCEV *Src = PSE.getSCEV(APtr);
    const SCEV *Sink = PSE.getSCEV(BPtr);
    return areAccessesCompletelyBeforeOrAfter(Src, ATy, Sink, BTy);
  };

  // Get the dependence distance, stride, type size and what access writes for
  // the dependence between A and B.
  auto Res =
      getDependenceDistanceStrideAndSize(A, InstMap[AIdx], B, InstMap[BIdx]);
  if (std::holds_alternative<Dependence::DepType>(Res)) {
    if (std::get<Dependence::DepType>(Res) == Dependence::Unknown &&
        CheckCompletelyBeforeOrAfter())
      return Dependence::NoDep;
    return std::get<Dependence::DepType>(Res);
  }

  auto &[Dist, MaxStride, CommonStride, TypeByteSize, AIsWrite, BIsWrite] =
      std::get<DepDistanceStrideAndSizeInfo>(Res);
  bool HasSameSize = TypeByteSize > 0;

  ScalarEvolution &SE = *PSE.getSE();
  auto &DL = InnermostLoop->getHeader()->getDataLayout();

  // If the distance between the acecsses is larger than their maximum absolute
  // stride multiplied by the symbolic maximum backedge taken count (which is an
  // upper bound of the number of iterations), the accesses are independet, i.e.
  // they are far enough appart that accesses won't access the same location
  // across all loop ierations.
  if (HasSameSize &&
      isSafeDependenceDistance(SE, *(PSE.getSymbolicMaxBackedgeTakenCount()),
                               *Dist, MaxStride))
    return Dependence::NoDep;

  const APInt *APDist = nullptr;
  uint64_t ConstDist = 0;
  if (match(Dist, m_scev_APInt(APDist))) {
    std::optional<uint64_t> Val = APDist->abs().tryZExtValue();
    if (!Val) {
      LLVM_DEBUG(dbgs() << "LAA: Constant distance does not fit in 64 bits.\n");
      return Dependence::Unknown;
    }
    ConstDist = *Val;
  }

  // Attempt to prove strided accesses independent.
  if (APDist) {
    // If the distance between accesses and their strides are known constants,
    // check whether the accesses interlace each other.
    if (ConstDist > 0 && CommonStride && CommonStride > 1 && HasSameSize &&
        areStridedAccessesIndependent(ConstDist, *CommonStride, TypeByteSize)) {
      LLVM_DEBUG(dbgs() << "LAA: Strided accesses are independent\n");
      return Dependence::NoDep;
    }
  } else {
    Dist = SE.applyLoopGuards(Dist, LoopGuards);
  }

  // Negative distances are not plausible dependencies.
  if (SE.isKnownNonPositive(Dist)) {
    if (SE.isKnownNonNegative(Dist)) {
      // Equal-sized accesses to the same location are forward.
      if (HasSameSize)
        return Dependence::Forward;

      if (CommonStride) {
        // For mixed sizes, CommonStride is asserted to cover both accesses when
        // computed in getDependenceDistanceStrideAndSize, so different
        // iterations cannot overlap.
        [[maybe_unused]] uint64_t ASz =
            DL.getTypeAllocSize(getLoadStoreType(InstMap[AIdx]));
        [[maybe_unused]] uint64_t BSz =
            DL.getTypeAllocSize(getLoadStoreType(InstMap[BIdx]));
        assert(*CommonStride >= std::max(ASz, BSz) &&
               "Invariant from getDependenceDistanceStrideAndSize broken!");
        return Dependence::Forward;
      }
      LLVM_DEBUG(dbgs() << "LAA: possibly zero dependence difference but "
                           "different type sizes\n");
      return Dependence::Unknown;
    }

    bool IsTrueDataDependence = (AIsWrite && !BIsWrite);
    // Check if the first access writes to a location that is read in a later
    // iteration, where the distance between them is not a multiple of a vector
    // factor and relatively small.
    //
    // NOTE: There is no need to update MaxSafeVectorWidthInBits after call to
    // couldPreventStoreLoadForward, even if it changed MinDepDistBytes, since a
    // forward dependency will allow vectorization using any width.

    if (IsTrueDataDependence && EnableForwardingConflictDetection) {
      if (!ConstDist) {
        return CheckCompletelyBeforeOrAfter() ? Dependence::NoDep
                                              : Dependence::Unknown;
      }
      if (!HasSameSize ||
          couldPreventStoreLoadForward(ConstDist, TypeByteSize)) {
        LLVM_DEBUG(
            dbgs() << "LAA: Forward but may prevent st->ld forwarding\n");
        return Dependence::ForwardButPreventsForwarding;
      }
    }

    LLVM_DEBUG(dbgs() << "LAA: Dependence is negative\n");
    return Dependence::Forward;
  }

  std::optional<int64_t> MinDistanceOpt =
      SE.getSignedRangeMin(Dist).trySExtValue();
  if (!MinDistanceOpt) {
    LLVM_DEBUG(dbgs() << "LAA: Minimum distance does not fit in 64 bits.\n");
    return Dependence::Unknown;
  }
  int64_t MinDistance = *MinDistanceOpt;
  // Below we only handle strictly positive distances.
  if (MinDistance <= 0) {
    return CheckCompletelyBeforeOrAfter() ? Dependence::NoDep
                                          : Dependence::Unknown;
  }

  if (!HasSameSize) {
    if (CheckCompletelyBeforeOrAfter())
      return Dependence::NoDep;
    LLVM_DEBUG(dbgs() << "LAA: ReadWrite-Write positive dependency with "
                         "different type sizes\n");
    return Dependence::Unknown;
  }
  // Bail out early if passed-in parameters make vectorization not feasible.
  unsigned MinForcedFactor =
      std::max(1U, VectorizerParams::VectorizationFactor.getKnownMinValue());
  unsigned ForcedUnroll = (VectorizerParams::VectorizationInterleave ?
                           VectorizerParams::VectorizationInterleave : 1);
  // The minimum number of iterations for a vectorized/unrolled version.
  unsigned MinNumIter = std::max(MinForcedFactor * ForcedUnroll, 2U);

  // It's not vectorizable if the distance is smaller than the minimum distance
  // needed for a vectroized/unrolled version. Vectorizing one iteration in
  // front needs MaxStride. Vectorizing the last iteration needs TypeByteSize.
  // (No need to plus the last gap distance).
  //
  // E.g. Assume one char is 1 byte in memory and one int is 4 bytes.
  //      foo(int *A) {
  //        int *B = (int *)((char *)A + 14);
  //        for (i = 0 ; i < 1024 ; i += 2)
  //          B[i] = A[i] + 1;
  //      }
  //
  // Two accesses in memory (stride is 4 * 2):
  //     | A[0] |      | A[2] |      | A[4] |      | A[6] |      |
  //                              | B[0] |      | B[2] |      | B[4] |
  //
  // MinDistance needs for vectorizing iterations except the last iteration:
  // 4 * 2 * (MinNumIter - 1). MinDistance needs for the last iteration: 4.
  // So the minimum distance needed is: 4 * 2 * (MinNumIter - 1) + 4.
  //
  // If MinNumIter is 2, it is vectorizable as the minimum distance needed is
  // 12, which is less than distance.
  //
  // If MinNumIter is 4 (Say if a user forces the vectorization factor to be 4),
  // the minimum distance needed is 28, which is greater than distance. It is
  // not safe to do vectorization.
  //
  // We use MaxStride (maximum of src and sink strides) to get a conservative
  // lower bound on the MinDistanceNeeded in case of different strides.

  // We know that Dist is positive, but it may not be constant. Use the signed
  // minimum for computations below, as this ensures we compute the closest
  // possible dependence distance.
  uint64_t MinDistanceNeeded = MaxStride * (MinNumIter - 1) + TypeByteSize;
  if (MinDistanceNeeded > static_cast<uint64_t>(MinDistance)) {
    if (!ConstDist) {
      // For non-constant distances, we checked the lower bound of the
      // dependence distance and the distance may be larger at runtime (and safe
      // for vectorization). Classify it as Unknown, so we re-try with runtime
      // checks, unless we can prove both accesses cannot overlap.
      return CheckCompletelyBeforeOrAfter() ? Dependence::NoDep
                                            : Dependence::Unknown;
    }
    LLVM_DEBUG(dbgs() << "LAA: Failure because of positive minimum distance "
                      << MinDistance << '\n');
    return Dependence::Backward;
  }

  // Unsafe if the minimum distance needed is greater than smallest dependence
  // distance distance.
  if (MinDistanceNeeded > MinDepDistBytes) {
    LLVM_DEBUG(dbgs() << "LAA: Failure because it needs at least "
                      << MinDistanceNeeded << " size in bytes\n");
    return Dependence::Backward;
  }

  MinDepDistBytes =
      std::min(static_cast<uint64_t>(MinDistance), MinDepDistBytes);

  bool IsTrueDataDependence = (!AIsWrite && BIsWrite);
  if (IsTrueDataDependence && EnableForwardingConflictDetection && ConstDist &&
      couldPreventStoreLoadForward(MinDistance, TypeByteSize, *CommonStride))
    return Dependence::BackwardVectorizableButPreventsForwarding;

  uint64_t MaxVF = MinDepDistBytes / MaxStride;
  LLVM_DEBUG(dbgs() << "LAA: Positive min distance " << MinDistance
                    << " with max VF = " << MaxVF << '\n');

  uint64_t MaxVFInBits = MaxVF * TypeByteSize * 8;
  if (!ConstDist && MaxVFInBits < MaxTargetVectorWidthInBits) {
    // For non-constant distances, we checked the lower bound of the dependence
    // distance and the distance may be larger at runtime (and safe for
    // vectorization). Classify it as Unknown, so we re-try with runtime checks,
    // unless we can prove both accesses cannot overlap.
    return CheckCompletelyBeforeOrAfter() ? Dependence::NoDep
                                          : Dependence::Unknown;
  }

  if (CheckCompletelyBeforeOrAfter())
    return Dependence::NoDep;

  MaxSafeVectorWidthInBits = std::min(MaxSafeVectorWidthInBits, MaxVFInBits);
  return Dependence::BackwardVectorizable;
}

bool MemoryDepChecker::areDepsSafe(const DepCandidates &DepCands,
                                   ArrayRef<MemAccessInfo> CheckDeps) {

  MinDepDistBytes = -1;
  SmallPtrSet<MemAccessInfo, 8> Visited;
  for (MemAccessInfo CurAccess : CheckDeps) {
    if (Visited.contains(CurAccess))
      continue;

    // Check accesses within this set.
    EquivalenceClasses<MemAccessInfo>::member_iterator AI =
        DepCands.findLeader(CurAccess);
    EquivalenceClasses<MemAccessInfo>::member_iterator AE =
        DepCands.member_end();

    // Check every access pair.
    while (AI != AE) {
      Visited.insert(*AI);
      bool AIIsWrite = AI->getInt();
      // Reads from the same pointer don't create extra hazards, but multiple
      // stores do (WAW), so start from AI for writes and next(AI) for reads.
      EquivalenceClasses<MemAccessInfo>::member_iterator OI =
          (AIIsWrite ? AI : std::next(AI));
      while (OI != AE) {
        // Check every accessing instruction pair in program order.
        auto &Acc = Accesses[*AI];
        for (std::vector<unsigned>::iterator I1 = Acc.begin(), I1E = Acc.end();
             I1 != I1E; ++I1)
          // When checking for WAW (OI == AI) caused by multiple writes to the
          // same pointer, start I2 at the next access past I1 to avoid
          // self-comparison.
          for (std::vector<unsigned>::iterator
                   I2 = (OI == AI ? std::next(I1) : Accesses[*OI].begin()),
                   I2E = (OI == AI ? I1E : Accesses[*OI].end());
               I2 != I2E; ++I2) {
            auto A = std::make_pair(&*AI, *I1);
            auto B = std::make_pair(&*OI, *I2);

            assert(*I1 != *I2);
            if (*I1 > *I2)
              std::swap(A, B);

            Dependence::DepType Type =
                isDependent(*A.first, A.second, *B.first, B.second);
            mergeInStatus(Dependence::isSafeForVectorization(Type));

            // Gather dependences unless we accumulated MaxDependences
            // dependences.  In that case return as soon as we find the first
            // unsafe dependence.  This puts a limit on this quadratic
            // algorithm.
            if (RecordDependences) {
              if (Type != Dependence::NoDep)
                Dependences.emplace_back(A.second, B.second, Type);

              if (Dependences.size() >= MaxDependences) {
                RecordDependences = false;
                Dependences.clear();
                LLVM_DEBUG(dbgs()
                           << "Too many dependences, stopped recording\n");
              }
            }
            if (!RecordDependences && !isSafeForVectorization())
              return false;
          }
        ++OI;
      }
      ++AI;
    }
  }

  LLVM_DEBUG(dbgs() << "Total Dependences: " << Dependences.size() << "\n");
  return isSafeForVectorization();
}

SmallVector<Instruction *, 4>
MemoryDepChecker::getInstructionsForAccess(Value *Ptr, bool IsWrite) const {
  MemAccessInfo Access(Ptr, IsWrite);
  auto I = Accesses.find(Access);
  SmallVector<Instruction *, 4> Insts;
  if (I != Accesses.end()) {
    transform(I->second, std::back_inserter(Insts),
              [&](unsigned Idx) { return this->InstMap[Idx]; });
  }

  return Insts;
}

const char *MemoryDepChecker::Dependence::DepName[] = {
    "NoDep",
    "Unknown",
    "IndirectUnsafe",
    "InvariantUnsafe",
    "Forward",
    "ForwardButPreventsForwarding",
    "Backward",
    "BackwardVectorizable",
    "BackwardVectorizableButPreventsForwarding"};

void MemoryDepChecker::Dependence::print(
    raw_ostream &OS, unsigned Depth,
    const SmallVectorImpl<Instruction *> &Instrs) const {
  OS.indent(Depth) << DepName[Type] << ":\n";
  OS.indent(Depth + 2) << *Instrs[Source] << " -> \n";
  OS.indent(Depth + 2) << *Instrs[Destination] << "\n";
}

bool LoopAccessInfo::canAnalyzeLoop() {
  // We need to have a loop header.
  LLVM_DEBUG(dbgs() << "\nLAA: Checking a loop in '"
                    << TheLoop->getHeader()->getParent()->getName() << "' from "
                    << TheLoop->getLocStr() << "\n");

  // We can only analyze innermost loops.
  if (!TheLoop->isInnermost()) {
    LLVM_DEBUG(dbgs() << "LAA: loop is not the innermost loop\n");
    recordAnalysis("NotInnerMostLoop") << "loop is not the innermost loop";
    return false;
  }

  // We must have a single backedge.
  if (TheLoop->getNumBackEdges() != 1) {
    LLVM_DEBUG(
        dbgs() << "LAA: loop control flow is not understood by analyzer\n");
    recordAnalysis("CFGNotUnderstood")
        << "loop control flow is not understood by analyzer";
    return false;
  }

  // ScalarEvolution needs to be able to find the symbolic max backedge taken
  // count, which is an upper bound on the number of loop iterations. The loop
  // may execute fewer iterations, if it exits via an uncountable exit.
  const SCEV *ExitCount = PSE->getSymbolicMaxBackedgeTakenCount();
  if (isa<SCEVCouldNotCompute>(ExitCount)) {
    recordAnalysis("CantComputeNumberOfIterations")
        << "could not determine number of loop iterations";
    LLVM_DEBUG(dbgs() << "LAA: SCEV could not compute the loop exit count.\n");
    return false;
  }

  LLVM_DEBUG(dbgs() << "LAA: Found an analyzable loop: "
                    << TheLoop->getHeader()->getName() << "\n");
  return true;
}

bool LoopAccessInfo::analyzeLoop(AAResults *AA, const LoopInfo *LI,
                                 const TargetLibraryInfo *TLI,
                                 DominatorTree *DT) {
  // Holds the Load and Store instructions.
  SmallVector<LoadInst *, 16> Loads;
  SmallVector<StoreInst *, 16> Stores;
  SmallPtrSet<MDNode *, 8> LoopAliasScopes;

  // Holds all the different accesses in the loop.
  unsigned NumReads = 0;
  unsigned NumReadWrites = 0;

  bool HasComplexMemInst = false;

  // A runtime check is only legal to insert if there are no convergent calls.
  HasConvergentOp = false;

  PtrRtChecking->Pointers.clear();
  PtrRtChecking->Need = false;

  const bool IsAnnotatedParallel = TheLoop->isAnnotatedParallel();

  const bool EnableMemAccessVersioningOfLoop =
      EnableMemAccessVersioning &&
      !TheLoop->getHeader()->getParent()->hasOptSize();

  // Traverse blocks in fixed RPOT order, regardless of their storage in the
  // loop info, as it may be arbitrary.
  LoopBlocksRPO RPOT(TheLoop);
  RPOT.perform(LI);

  // Don't return early as soon as we found a memory access that cannot be
  // vectorize - HasConvergentOp must still be computed as it is part of LAI's
  // public API (used by LoopDistribute).
  for (BasicBlock *BB : RPOT) {
    // Scan the BB and collect legal loads and stores. Also detect any
    // convergent instructions.
    for (Instruction &I : *BB) {
      if (auto *Call = dyn_cast<CallBase>(&I)) {
        if (Call->isConvergent())
          HasConvergentOp = true;
      }

      // Unsafe to vectorize and we already found a convergent operation, can
      // early return now.
      if (HasComplexMemInst && HasConvergentOp)
        return false;

      // Already unsafe to vectorize; keep scanning for convergent ops.
      if (HasComplexMemInst)
        continue;

      // Record alias scopes defined inside the loop.
      if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
        for (Metadata *Op : Decl->getScopeList()->operands())
          LoopAliasScopes.insert(cast<MDNode>(Op));

      // Many math library functions read the rounding mode. We will only
      // vectorize a loop if it contains known function calls that don't set
      // the flag. Therefore, it is safe to ignore this read from memory.
      auto *Call = dyn_cast<CallInst>(&I);
      if (Call && getVectorIntrinsicIDForCall(Call, TLI))
        continue;

      // If this is a load, save it. If this instruction can read from memory
      // but is not a load, we only allow it if it's a call to a function with a
      // vector mapping and no pointer arguments.
      if (I.mayReadFromMemory()) {
        auto hasPointerArgs = [](CallBase *CB) {
          return any_of(CB->args(), [](Value const *Arg) {
            return Arg->getType()->isPointerTy();
          });
        };

        // If the function has an explicit vectorized counterpart, and does not
        // take output/input pointers, we can safely assume that it can be
        // vectorized.
        if (Call && !Call->isNoBuiltin() && Call->getCalledFunction() &&
            !hasPointerArgs(Call) && !VFDatabase::getMappings(*Call).empty())
          continue;

        auto *Ld = dyn_cast<LoadInst>(&I);
        if (!Ld) {
          recordAnalysis("CantVectorizeInstruction", &I)
              << "instruction cannot be vectorized";
          HasComplexMemInst = true;
          continue;
        }
        if (!Ld->isSimple() && !IsAnnotatedParallel) {
          recordAnalysis("NonSimpleLoad", Ld)
              << "read with atomic ordering or volatile read";
          LLVM_DEBUG(dbgs() << "LAA: Found a non-simple load.\n");
          HasComplexMemInst = true;
          continue;
        }
        Loads.push_back(Ld);
        DepChecker->addAccess(Ld);
        if (EnableMemAccessVersioningOfLoop)
          collectStridedAccess(Ld);
        continue;
      }

      // Save 'store' instructions. Abort if other instructions write to memory.
      if (I.mayWriteToMemory()) {
        auto *St = dyn_cast<StoreInst>(&I);
        if (!St) {
          recordAnalysis("CantVectorizeInstruction", &I)
              << "instruction cannot be vectorized";
          HasComplexMemInst = true;
          continue;
        }
        if (!St->isSimple() && !IsAnnotatedParallel) {
          recordAnalysis("NonSimpleStore", St)
              << "write with atomic ordering or volatile write";
          LLVM_DEBUG(dbgs() << "LAA: Found a non-simple store.\n");
          HasComplexMemInst = true;
          continue;
        }
        Stores.push_back(St);
        DepChecker->addAccess(St);
        if (EnableMemAccessVersioningOfLoop)
          collectStridedAccess(St);
      }
    } // Next instr.
  } // Next block.

  if (HasComplexMemInst)
    return false;

  // Now we have two lists that hold the loads and the stores.
  // Next, we find the pointers that they use.

  // Check if we see any stores. If there are no stores, then we don't
  // care if the pointers are *restrict*.
  if (!Stores.size()) {
    LLVM_DEBUG(dbgs() << "LAA: Found a read-only loop!\n");
    return true;
  }

  MemoryDepChecker::DepCandidates DepCands;
  AccessAnalysis Accesses(TheLoop, AA, LI, *DT, DepCands, *PSE,
                          LoopAliasScopes);

  // Holds the analyzed pointers. We don't want to call getUnderlyingObjects
  // multiple times on the same object. If the ptr is accessed twice, once
  // for read and once for write, it will only appear once (on the write
  // list). This is okay, since we are going to check for conflicts between
  // writes and between reads and writes, but not between reads and reads.
  SmallSet<std::pair<Value *, Type *>, 16> Seen;

  // Record uniform store addresses to identify if we have multiple stores
  // to the same address.
  SmallPtrSet<Value *, 16> UniformStores;

  for (StoreInst *ST : Stores) {
    Value *Ptr = ST->getPointerOperand();

    if (isInvariant(Ptr)) {
      // Record store instructions to loop invariant addresses
      StoresToInvariantAddresses.push_back(ST);
      HasStoreStoreDependenceInvolvingLoopInvariantAddress |=
          !UniformStores.insert(Ptr).second;
    }

    // If we did *not* see this pointer before, insert it to  the read-write
    // list. At this phase it is only a 'write' list.
    Type *AccessTy = getLoadStoreType(ST);
    if (Seen.insert({Ptr, AccessTy}).second) {
      ++NumReadWrites;

      MemoryLocation Loc = MemoryLocation::get(ST);
      // The TBAA metadata could have a control dependency on the predication
      // condition, so we cannot rely on it when determining whether or not we
      // need runtime pointer checks.
      if (blockNeedsPredication(ST->getParent(), TheLoop, DT))
        Loc.AATags.TBAA = nullptr;

      // Expand forked pointers (i.e., a phi of multiple strided pointers) into
      // all alternatives.
      visitPointers(const_cast<Value *>(Loc.Ptr), *TheLoop,
                    [&Accesses, AccessTy, Loc](Value *Ptr) {
                      MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr);
                      Accesses.addStore(NewLoc, AccessTy);
                    });
    }
  }

  if (IsAnnotatedParallel) {
    LLVM_DEBUG(
        dbgs() << "LAA: A loop annotated parallel, ignore memory dependency "
               << "checks.\n");
    return true;
  }

  for (LoadInst *LD : Loads) {
    Value *Ptr = LD->getPointerOperand();
    // If we did *not* see this pointer before, insert it to the read list. If
    // we *did* see it before, then it is already in the read-write list. This
    // allows us to vectorize expressions such as A[i] += x; Because the address
    // of A[i] is a read-write pointer. This only works if the index of A[i] is
    // strictly monotonic, which we approximate (conservatively) via
    // getPtrStride. If the address is unknown (e.g. A[B[i]]) then we may read,
    // modify, and write overlapping words. Note that "zero stride" is unsafe
    // and is being handled below.
    bool IsReadOnlyPtr = false;
    Type *AccessTy = getLoadStoreType(LD);
    if (Seen.insert({Ptr, AccessTy}).second ||
        !getPtrStride(*PSE, AccessTy, Ptr, TheLoop, *DT, SymbolicStrides,
                      true)) {
      ++NumReads;
      IsReadOnlyPtr = true;
    }

    // See if there is an unsafe dependency between a load to a uniform address and
    // store to the same uniform address.
    if (UniformStores.contains(Ptr)) {
      LLVM_DEBUG(dbgs() << "LAA: Found an unsafe dependency between a uniform "
                           "load and uniform store to the same address!\n");
      HasLoadStoreDependenceInvolvingLoopInvariantAddress = true;
    }

    MemoryLocation Loc = MemoryLocation::get(LD);
    // The TBAA metadata could have a control dependency on the predication
    // condition, so we cannot rely on it when determining whether or not we
    // need runtime pointer checks.
    if (blockNeedsPredication(LD->getParent(), TheLoop, DT))
      Loc.AATags.TBAA = nullptr;

    // Expand forked pointers (i.e., a phi of multiple strided pointers) into
    // all alternatives.
    visitPointers(const_cast<Value *>(Loc.Ptr), *TheLoop,
                  [&Accesses, AccessTy, Loc, IsReadOnlyPtr](Value *Ptr) {
                    MemoryLocation NewLoc = Loc.getWithNewPtr(Ptr);
                    Accesses.addLoad(NewLoc, AccessTy, IsReadOnlyPtr);
                  });
  }

  // If we write (or read-write) to a single destination and there are no other
  // reads in this loop then is it safe to vectorize: the vectorized stores
  // preserve ordering via replication or order-preserving @llvm.masked.scatter.
  if (NumReadWrites == 1 && NumReads == 0) {
    LLVM_DEBUG(dbgs() << "LAA: Found a write-only loop!\n");
    return true;
  }

  // Build dependence sets and check whether we need a runtime pointer bounds
  // check.
  Accesses.buildDependenceSets();

  // Find pointers with computable bounds. We are going to use this information
  // to place a runtime bound check.
  Value *UncomputablePtr = nullptr;
  HasCompletePtrRtChecking =
      Accesses.canCheckPtrAtRT(*PtrRtChecking, TheLoop, SymbolicStrides,
                               UncomputablePtr, AllowPartial, getDepChecker());
  if (!HasCompletePtrRtChecking) {
    const auto *I = dyn_cast_or_null<Instruction>(UncomputablePtr);
    recordAnalysis("CantIdentifyArrayBounds", I)
        << "cannot identify array bounds";
    LLVM_DEBUG(dbgs() << "LAA: We can't vectorize because we can't find "
                      << "the array bounds.\n");
    return false;
  }

  LLVM_DEBUG(
    dbgs() << "LAA: May be able to perform a memory runtime check if needed.\n");

  bool DepsAreSafe = true;
  if (Accesses.isDependencyCheckNeeded()) {
    LLVM_DEBUG(dbgs() << "LAA: Checking memory dependencies\n");
    DepsAreSafe =
        DepChecker->areDepsSafe(DepCands, Accesses.getDependenciesToCheck());

    if (!DepsAreSafe && DepChecker->shouldRetryWithRuntimeChecks()) {
      LLVM_DEBUG(dbgs() << "LAA: Retrying with memory checks\n");

      PtrRtChecking->reset();
      PtrRtChecking->Need = true;

      UncomputablePtr = nullptr;
      HasCompletePtrRtChecking = Accesses.canCheckPtrAtRT(
          *PtrRtChecking, TheLoop, SymbolicStrides, UncomputablePtr,
          AllowPartial, getDepChecker());

      // Check that we found the bounds for the pointer.
      if (!HasCompletePtrRtChecking) {
        auto *I = dyn_cast_or_null<Instruction>(UncomputablePtr);
        recordAnalysis("CantCheckMemDepsAtRunTime", I)
            << "cannot check memory dependencies at runtime";
        LLVM_DEBUG(dbgs() << "LAA: Can't vectorize with memory checks\n");
        return false;
      }

      // Clear the dependency checks. They are no longer needed.
      Accesses.resetDepChecks(*DepChecker);

      DepsAreSafe = true;
    }
  }

  // Update the invariant address dependence flags based on dependences found
  // by the dep checker. Even if dependences were not recorded (too many to
  // track), any InvariantUnsafe dep would still have set the status to Unsafe
  if (const auto *Deps = DepChecker->getDependences()) {
    for (const auto &Dep : *Deps) {
      if (Dep.Type != MemoryDepChecker::Dependence::InvariantUnsafe)
        continue;
      Instruction *Src = Dep.getSource(*DepChecker);
      Instruction *Dst = Dep.getDestination(*DepChecker);
      if (isa<LoadInst>(Src) != isa<LoadInst>(Dst)) {
        HasLoadStoreDependenceInvolvingLoopInvariantAddress = true;
      } else {
        assert(isa<StoreInst>(Src) && isa<StoreInst>(Dst) &&
               "Expected both to be stores");
        HasStoreStoreDependenceInvolvingLoopInvariantAddress = true;
      }
    }
  }

  if (HasConvergentOp) {
    recordAnalysis("CantInsertRuntimeCheckWithConvergent")
        << "cannot add control dependency to convergent operation";
    LLVM_DEBUG(dbgs() << "LAA: We can't vectorize because a runtime check "
                         "would be needed with a convergent operation\n");
    return false;
  }

  if (DepsAreSafe) {
    LLVM_DEBUG(
        dbgs() << "LAA: No unsafe dependent memory operations in loop.  We"
               << (PtrRtChecking->Need ? "" : " don't")
               << " need runtime memory checks.\n");
    return true;
  }

  emitUnsafeDependenceRemark();
  return false;
}

void LoopAccessInfo::emitUnsafeDependenceRemark() {
  const auto *Deps = getDepChecker().getDependences();
  if (!Deps)
    return;
  const auto *Found =
      llvm::find_if(*Deps, [](const MemoryDepChecker::Dependence &D) {
        return MemoryDepChecker::Dependence::isSafeForVectorization(D.Type) !=
               MemoryDepChecker::VectorizationSafetyStatus::Safe;
      });
  if (Found == Deps->end())
    return;
  MemoryDepChecker::Dependence Dep = *Found;

  LLVM_DEBUG(dbgs() << "LAA: unsafe dependent memory operations in loop\n");

  // Emit remark for first unsafe dependence
  bool HasForcedDistribution =
      getBooleanLoopAttribute(TheLoop, "llvm.loop.distribute.enable");

  const std::string Info =
      HasForcedDistribution
          ? "unsafe dependent memory operations in loop."
          : "unsafe dependent memory operations in loop. Use "
            "#pragma clang loop distribute(enable) to allow loop distribution "
            "to attempt to isolate the offending operations into a separate "
            "loop";
  OptimizationRemarkAnalysis &R =
      recordAnalysis("UnsafeDep", Dep.getDestination(getDepChecker())) << Info;

  switch (Dep.Type) {
  case MemoryDepChecker::Dependence::NoDep:
  case MemoryDepChecker::Dependence::Forward:
  case MemoryDepChecker::Dependence::BackwardVectorizable:
    llvm_unreachable("Unexpected dependence");
  case MemoryDepChecker::Dependence::Backward:
    R << "\nBackward loop carried data dependence.";
    break;
  case MemoryDepChecker::Dependence::ForwardButPreventsForwarding:
    R << "\nForward loop carried data dependence that prevents "
         "store-to-load forwarding.";
    break;
  case MemoryDepChecker::Dependence::BackwardVectorizableButPreventsForwarding:
    R << "\nBackward loop carried data dependence that prevents "
         "store-to-load forwarding.";
    break;
  case MemoryDepChecker::Dependence::IndirectUnsafe:
    R << "\nUnsafe indirect dependence.";
    break;
  case MemoryDepChecker::Dependence::InvariantUnsafe:
    R << "\nUnsafe dependence on loop-invariant address.";
    break;
  case MemoryDepChecker::Dependence::Unknown:
    R << "\nUnknown data dependence.";
    break;
  }

  if (Instruction *I = Dep.getSource(getDepChecker())) {
    DebugLoc SourceLoc = I->getDebugLoc();
    if (auto *DD = dyn_cast_or_null<Instruction>(getPointerOperand(I)))
      SourceLoc = DD->getDebugLoc();
    if (SourceLoc)
      R << " Memory location is the same as accessed at "
        << ore::NV("Location", SourceLoc);
  }
}

bool LoopAccessInfo::blockNeedsPredication(const BasicBlock *BB,
                                           const Loop *TheLoop,
                                           const DominatorTree *DT) {
  assert(TheLoop->contains(BB) && "Unknown block used");

  // Blocks that do not dominate the latch need predication.
  const BasicBlock *Latch = TheLoop->getLoopLatch();
  assert(Latch && "Loop expected to have a single latch.");
  return !DT->dominates(BB, Latch);
}

OptimizationRemarkAnalysis &
LoopAccessInfo::recordAnalysis(StringRef RemarkName, const Instruction *I) {
  assert(!Report && "Multiple reports generated");

  const BasicBlock *CodeRegion = TheLoop->getHeader();
  DebugLoc DL = TheLoop->getStartLoc();

  if (I) {
    CodeRegion = I->getParent();
    // If there is no debug location attached to the instruction, revert back to
    // using the loop's.
    if (I->getDebugLoc())
      DL = I->getDebugLoc();
  }

  Report = std::make_unique<OptimizationRemarkAnalysis>(DEBUG_TYPE, RemarkName,
                                                        DL, CodeRegion);
  return *Report;
}

bool LoopAccessInfo::isInvariant(Value *V) const {
  auto *SE = PSE->getSE();
  if (TheLoop->isLoopInvariant(V))
    return true;
  if (!SE->isSCEVable(V->getType()))
    return false;
  const SCEV *S = SE->getSCEV(V);
  return SE->isLoopInvariant(S, TheLoop);
}

/// If \p Ptr is a GEP, which has a loop-variant operand, return that operand.
/// Otherwise, return \p Ptr.
static Value *getLoopVariantGEPOperand(Value *Ptr, ScalarEvolution *SE,
                                       Loop *Lp) {
  auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
  if (!GEP)
    return Ptr;

  Value *V = Ptr;
  for (const Use &U : GEP->operands()) {
    if (!SE->isLoopInvariant(SE->getSCEV(U), Lp)) {
      if (V == Ptr)
        V = U;
      else
        // There must be exactly one loop-variant operand.
        return Ptr;
    }
  }
  return V;
}

/// Get the stride of a pointer access in a loop. Looks for symbolic
/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise.
static const SCEV *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp) {
  auto *PtrTy = dyn_cast<PointerType>(Ptr->getType());
  if (!PtrTy)
    return nullptr;

  // Try to remove a gep instruction to make the pointer (actually index at this
  // point) easier analyzable. If OrigPtr is equal to Ptr we are analyzing the
  // pointer, otherwise, we are analyzing the index.
  Value *OrigPtr = Ptr;

  Ptr = getLoopVariantGEPOperand(Ptr, SE, Lp);
  const SCEV *V = SE->getSCEV(Ptr);

  if (Ptr != OrigPtr)
    // Strip off casts.
    while (auto *C = dyn_cast<SCEVIntegralCastExpr>(V))
      V = C->getOperand();

  if (!match(V, m_scev_AffineAddRec(m_SCEV(), m_SCEV(V), m_SpecificLoop(Lp))))
    return nullptr;

  // Note that the restriction after this loop invariant check are only
  // profitability restrictions.
  if (!SE->isLoopInvariant(V, Lp))
    return nullptr;

  // Look for the loop invariant symbolic value.
  if (isa<SCEVUnknown>(V))
    return V;

  // Look through multiplies that scale a stride by a constant.
  match(V, m_scev_Mul(m_SCEVConstant(), m_SCEV(V)));
  if (auto *C = dyn_cast<SCEVIntegralCastExpr>(V))
    if (isa<SCEVUnknown>(C->getOperand()))
      return V;

  return nullptr;
}

void LoopAccessInfo::collectStridedAccess(Value *MemAccess) {
  Value *Ptr = getLoadStorePointerOperand(MemAccess);
  if (!Ptr)
    return;

  // Note: getStrideFromPointer is a *profitability* heuristic.  We
  // could broaden the scope of values returned here - to anything
  // which happens to be loop invariant and contributes to the
  // computation of an interesting IV - but we chose not to as we
  // don't have a cost model here, and broadening the scope exposes
  // far too many unprofitable cases.
  const SCEV *StrideExpr = getStrideFromPointer(Ptr, PSE->getSE(), TheLoop);
  if (!StrideExpr)
    return;

  if (match(StrideExpr, m_scev_UndefOrPoison()))
    return;

  LLVM_DEBUG(dbgs() << "LAA: Found a strided access that is a candidate for "
                       "versioning:");
  LLVM_DEBUG(dbgs() << "  Ptr: " << *Ptr << " Stride: " << *StrideExpr << "\n");

  if (!SpeculateUnitStride) {
    LLVM_DEBUG(dbgs() << "  Chose not to due to -laa-speculate-unit-stride\n");
    return;
  }

  // Avoid adding the "Stride == 1" predicate when we know that
  // Stride >= Trip-Count. Such a predicate will effectively optimize a single
  // or zero iteration loop, as Trip-Count <= Stride == 1.
  //
  // TODO: We are currently not making a very informed decision on when it is
  // beneficial to apply stride versioning. It might make more sense that the
  // users of this analysis (such as the vectorizer) will trigger it, based on
  // their specific cost considerations; For example, in cases where stride
  // versioning does  not help resolving memory accesses/dependences, the
  // vectorizer should evaluate the cost of the runtime test, and the benefit
  // of various possible stride specializations, considering the alternatives
  // of using gather/scatters (if available).

  const SCEV *MaxBTC = PSE->getSymbolicMaxBackedgeTakenCount();

  // Match the types so we can compare the stride and the MaxBTC.
  // The Stride can be positive/negative, so we sign extend Stride;
  // The backedgeTakenCount is non-negative, so we zero extend MaxBTC.
  const DataLayout &DL = TheLoop->getHeader()->getDataLayout();
  uint64_t StrideTypeSizeBits = DL.getTypeSizeInBits(StrideExpr->getType());
  uint64_t BETypeSizeBits = DL.getTypeSizeInBits(MaxBTC->getType());
  const SCEV *CastedStride = StrideExpr;
  const SCEV *CastedBECount = MaxBTC;
  ScalarEvolution *SE = PSE->getSE();
  if (BETypeSizeBits >= StrideTypeSizeBits)
    CastedStride = SE->getNoopOrSignExtend(StrideExpr, MaxBTC->getType());
  else
    CastedBECount = SE->getZeroExtendExpr(MaxBTC, StrideExpr->getType());
  const SCEV *StrideMinusBETaken = SE->getMinusSCEV(CastedStride, CastedBECount);
  // Since TripCount == BackEdgeTakenCount + 1, checking:
  // "Stride >= TripCount" is equivalent to checking:
  // Stride - MaxBTC> 0
  if (SE->isKnownPositive(StrideMinusBETaken)) {
    LLVM_DEBUG(
        dbgs() << "LAA: Stride>=TripCount; No point in versioning as the "
                  "Stride==1 predicate will imply that the loop executes "
                  "at most once.\n");
    return;
  }
  LLVM_DEBUG(dbgs() << "LAA: Found a strided access that we can version.\n");

  // Strip back off the integer cast, and check that our result is a
  // SCEVUnknown as we expect.
  const SCEV *StrideBase = StrideExpr;
  if (const auto *C = dyn_cast<SCEVIntegralCastExpr>(StrideBase))
    StrideBase = C->getOperand();
  assert(SE->isLoopInvariant(StrideBase, TheLoop) &&
         "users of the map rely on the stride being loop invariant");
  SymbolicStrides[Ptr] = cast<SCEVUnknown>(StrideBase);
}

LoopAccessInfo::LoopAccessInfo(Loop *L, ScalarEvolution *SE,
                               const TargetTransformInfo *TTI,
                               const TargetLibraryInfo *TLI, AAResults *AA,
                               DominatorTree *DT, LoopInfo *LI,
                               AssumptionCache *AC, bool AllowPartial)
    : PSE(std::make_unique<PredicatedScalarEvolution>(*SE, *L)),
      PtrRtChecking(nullptr), TheLoop(L),
      LoopGuards(ScalarEvolution::LoopGuards::collectOnDemand(L, *SE)),
      AllowPartial(AllowPartial) {
  unsigned MaxTargetVectorWidthInBits = std::numeric_limits<unsigned>::max();
  if (TTI && !TTI->enableScalableVectorization())
    // Scale the vector width by 2 as rough estimate to also consider
    // interleaving.
    MaxTargetVectorWidthInBits =
        TTI->getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector) * 2;

  DepChecker = std::make_unique<MemoryDepChecker>(
      *PSE, AC, DT, L, SymbolicStrides, MaxTargetVectorWidthInBits, LoopGuards);
  PtrRtChecking =
      std::make_unique<RuntimePointerChecking>(*DepChecker, SE, LoopGuards);
  if (canAnalyzeLoop())
    CanVecMem = analyzeLoop(AA, LI, TLI, DT);
}

void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const {
  if (CanVecMem) {
    OS.indent(Depth) << "Memory dependences are safe";
    const MemoryDepChecker &DC = getDepChecker();
    if (!DC.isSafeForAnyVectorWidth())
      OS << " with a maximum safe vector width of "
         << DC.getMaxSafeVectorWidthInBits() << " bits";
    if (!DC.isSafeForAnyStoreLoadForwardDistances()) {
      uint64_t SLDist = DC.getStoreLoadForwardSafeDistanceInBits();
      OS << ", with a maximum safe store-load forward width of " << SLDist
         << " bits";
    }
    if (PtrRtChecking->Need)
      OS << " with run-time checks";
    OS << "\n";
  }

  if (HasConvergentOp)
    OS.indent(Depth) << "Has convergent operation in loop\n";

  if (Report)
    OS.indent(Depth) << "Report: " << Report->getMsg() << "\n";

  if (auto *Dependences = DepChecker->getDependences()) {
    OS.indent(Depth) << "Dependences:\n";
    for (const auto &Dep : *Dependences) {
      Dep.print(OS, Depth + 2, DepChecker->getMemoryInstructions());
      OS << "\n";
    }
  } else
    OS.indent(Depth) << "Too many dependences, not recorded\n";

  // List the pair of accesses need run-time checks to prove independence.
  PtrRtChecking->print(OS, Depth);
  if (PtrRtChecking->Need && !HasCompletePtrRtChecking)
    OS.indent(Depth) << "Generated run-time checks are incomplete\n";
  OS << "\n";

  OS.indent(Depth)
      << "Non vectorizable stores to invariant address were "
      << (HasStoreStoreDependenceInvolvingLoopInvariantAddress ||
                  HasLoadStoreDependenceInvolvingLoopInvariantAddress
              ? ""
              : "not ")
      << "found in loop.\n";

  OS.indent(Depth) << "SCEV assumptions:\n";
  PSE->getPredicate().print(OS, Depth);

  OS << "\n";

  OS.indent(Depth) << "Expressions re-written:\n";
  PSE->print(OS, Depth);
}

const LoopAccessInfo &LoopAccessInfoManager::getInfo(Loop &L,
                                                     bool AllowPartial) {
  const auto &[It, Inserted] = LoopAccessInfoMap.try_emplace(&L);

  // We need to create the LoopAccessInfo if either we don't already have one,
  // or if it was created with a different value of AllowPartial.
  if (Inserted || It->second->hasAllowPartial() != AllowPartial)
    It->second = std::make_unique<LoopAccessInfo>(&L, &SE, TTI, TLI, &AA, &DT,
                                                  &LI, AC, AllowPartial);

  return *It->second;
}
void LoopAccessInfoManager::clear() {
  // Collect LoopAccessInfo entries that may keep references to IR outside the
  // analyzed loop or SCEVs that may have been modified or invalidated. At the
  // moment, that is loops requiring memory or SCEV runtime checks, as those cache
  // SCEVs, e.g. for pointer expressions.
  LoopAccessInfoMap.remove_if([](const auto &Entry) {
    const auto &LAI = Entry.second;
    return !(LAI->getRuntimePointerChecking()->getChecks().empty() &&
             LAI->getPSE().getPredicate().isAlwaysTrue());
  });
}

bool LoopAccessInfoManager::invalidate(
    Function &F, const PreservedAnalyses &PA,
    FunctionAnalysisManager::Invalidator &Inv) {
  // Check whether our analysis is preserved.
  auto PAC = PA.getChecker<LoopAccessAnalysis>();
  if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>())
    // If not, give up now.
    return true;

  // Check whether the analyses we depend on became invalid for any reason.
  // Skip checking TargetLibraryAnalysis as it is immutable and can't become
  // invalid.
  return Inv.invalidate<AAManager>(F, PA) ||
         Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) ||
         Inv.invalidate<LoopAnalysis>(F, PA) ||
         Inv.invalidate<DominatorTreeAnalysis>(F, PA);
}

LoopAccessInfoManager LoopAccessAnalysis::run(Function &F,
                                              FunctionAnalysisManager &FAM) {
  auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
  auto &AA = FAM.getResult<AAManager>(F);
  auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
  auto &LI = FAM.getResult<LoopAnalysis>(F);
  auto &TTI = FAM.getResult<TargetIRAnalysis>(F);
  auto &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
  auto &AC = FAM.getResult<AssumptionAnalysis>(F);
  return LoopAccessInfoManager(SE, AA, DT, LI, &TTI, &TLI, &AC);
}

AnalysisKey LoopAccessAnalysis::Key;
