//===- 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(); }

  /// Reset dependence checks after a successful runtime-check retry.
  /// Remove unknown dependences covered by runtime checks, but retain known
  /// dependences to constrain reordering.
  void resetDepChecks(MemoryDepChecker &DepChecker) {
    CheckDeps.clear();
    DepChecker.removeUnknownDependences();
  }

  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();

  if (Size == 0)
    return std::nullopt;

  // 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));

      // Operand bundles may access memory, even if the callee does not.
      auto *CB = dyn_cast<CallBase>(&I);
      if (CB && CB->hasReadingOperandBundles()) {
        recordAnalysis("CantVectorizeInstruction", &I)
            << "call instruction with operand bundles cannot be vectorized";
        HasComplexMemInst = true;
        continue;
      }

      // 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;
      }

      // The runtime checks cover the unknown dependences, so drop those. Keep
      // the known ones, as they still constrain reordering.
      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;
