[llvm-branch-commits] [llvm] [SCEV] Add option to request use-specific SCEV for a GEP expr (WIP). (PR #91964)

Florian Hahn via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed May 22 07:23:20 PDT 2024


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/91964

>From e84a4f9eae24f7319955854a9483cdc05a61fd42 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Mon, 13 May 2024 09:49:39 +0100
Subject: [PATCH 1/3] [SCEV] Use const SCEV * explicitly in more places.

---
 llvm/lib/Analysis/Delinearization.cpp         |   2 +-
 llvm/lib/Analysis/IVUsers.cpp                 |   4 +-
 llvm/lib/Analysis/LoopAccessAnalysis.cpp      |   8 +-
 llvm/lib/Target/ARM/MVETailPredication.cpp    |  16 ++-
 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp |  10 +-
 llvm/lib/Transforms/Scalar/LoopDeletion.cpp   |   4 +-
 .../lib/Transforms/Scalar/LoopPredication.cpp |   4 +-
 .../Transforms/Utils/LowerMemIntrinsics.cpp   |   4 +-
 llvm/lib/Transforms/Utils/SimplifyIndVar.cpp  |  10 +-
 .../Vectorize/LoopVectorizationLegality.cpp   |   9 +-
 .../Transforms/Vectorize/SLPVectorizer.cpp    |   4 +-
 .../Analysis/ScalarEvolutionTest.cpp          | 122 +++++++++---------
 .../Transforms/Utils/LoopUtilsTest.cpp        |   4 +-
 .../Utils/ScalarEvolutionExpanderTest.cpp     |  10 +-
 14 files changed, 109 insertions(+), 102 deletions(-)

diff --git a/llvm/lib/Analysis/Delinearization.cpp b/llvm/lib/Analysis/Delinearization.cpp
index a45d8815e54ce..857778e3e75df 100644
--- a/llvm/lib/Analysis/Delinearization.cpp
+++ b/llvm/lib/Analysis/Delinearization.cpp
@@ -131,7 +131,7 @@ struct SCEVCollectAddRecMultiplies {
     if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) {
       bool HasAddRec = false;
       SmallVector<const SCEV *, 0> Operands;
-      for (const auto *Op : Mul->operands()) {
+      for (const SCEV *Op : Mul->operands()) {
         const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op);
         if (Unknown && !isa<CallInst>(Unknown->getValue())) {
           Operands.push_back(Op);
diff --git a/llvm/lib/Analysis/IVUsers.cpp b/llvm/lib/Analysis/IVUsers.cpp
index 5c7883fb3b37c..681d0ebf53f27 100644
--- a/llvm/lib/Analysis/IVUsers.cpp
+++ b/llvm/lib/Analysis/IVUsers.cpp
@@ -73,7 +73,7 @@ static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L,
   // An add is interesting if exactly one of its operands is interesting.
   if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
     bool AnyInterestingYet = false;
-    for (const auto *Op : Add->operands())
+    for (const SCEV *Op : Add->operands())
       if (isInteresting(Op, I, L, SE, LI)) {
         if (AnyInterestingYet)
           return false;
@@ -346,7 +346,7 @@ static const SCEVAddRecExpr *findAddRecForLoop(const SCEV *S, const Loop *L) {
   }
 
   if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
-    for (const auto *Op : Add->operands())
+    for (const SCEV *Op : Add->operands())
       if (const SCEVAddRecExpr *AR = findAddRecForLoop(Op, L))
         return AR;
     return nullptr;
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 2a967f570c4aa..9405625c7d074 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -171,9 +171,9 @@ const SCEV *llvm::replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE,
   assert(isa<SCEVUnknown>(StrideSCEV) && "shouldn't be in map");
 
   ScalarEvolution *SE = PSE.getSE();
-  const auto *CT = SE->getOne(StrideSCEV->getType());
+  const SCEV *CT = SE->getOne(StrideSCEV->getType());
   PSE.addPredicate(*SE->getEqualPredicate(StrideSCEV, CT));
-  auto *Expr = PSE.getSCEV(Ptr);
+  const SCEV *Expr = PSE.getSCEV(Ptr);
 
   LLVM_DEBUG(dbgs() << "LAA: Replacing SCEV: " << *OrigSCEV
 	     << " by: " << *Expr << "\n");
@@ -1089,7 +1089,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
         return false;
 
       if (!isNoWrap(PSE, StridesMap, Ptr, AccessTy, TheLoop)) {
-        auto *Expr = PSE.getSCEV(Ptr);
+        const SCEV *Expr = PSE.getSCEV(Ptr);
         if (!Assume || !isa<SCEVAddRecExpr>(Expr))
           return false;
         PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
@@ -1448,7 +1448,7 @@ static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR,
         // Assume constant for other the operand so that the AddRec can be
         // easily found.
         isa<ConstantInt>(OBO->getOperand(1))) {
-      auto *OpScev = PSE.getSCEV(OBO->getOperand(0));
+      const SCEV *OpScev = PSE.getSCEV(OBO->getOperand(0));
 
       if (auto *OpAR = dyn_cast<SCEVAddRecExpr>(OpScev))
         return OpAR->getLoop() == L && OpAR->getNoWrapFlags(SCEV::FlagNSW);
diff --git a/llvm/lib/Target/ARM/MVETailPredication.cpp b/llvm/lib/Target/ARM/MVETailPredication.cpp
index fe97d4f758997..58ab5195efa88 100644
--- a/llvm/lib/Target/ARM/MVETailPredication.cpp
+++ b/llvm/lib/Target/ARM/MVETailPredication.cpp
@@ -205,8 +205,8 @@ const SCEV *MVETailPredication::IsSafeActiveMask(IntrinsicInst *ActiveLaneMask,
   if (!L->makeLoopInvariant(ElemCount, Changed))
     return nullptr;
 
-  auto *EC= SE->getSCEV(ElemCount);
-  auto *TC = SE->getSCEV(TripCount);
+  const SCEV *EC = SE->getSCEV(ElemCount);
+  const SCEV *TC = SE->getSCEV(TripCount);
   int VectorWidth =
       cast<FixedVectorType>(ActiveLaneMask->getType())->getNumElements();
   if (VectorWidth != 2 && VectorWidth != 4 && VectorWidth != 8 &&
@@ -228,7 +228,7 @@ const SCEV *MVETailPredication::IsSafeActiveMask(IntrinsicInst *ActiveLaneMask,
   // different counter. Using SCEV, we check that the induction is of the
   // form i = i + 4, where the increment must be equal to the VectorWidth.
   auto *IV = ActiveLaneMask->getOperand(0);
-  auto *IVExpr = SE->getSCEV(IV);
+  const SCEV *IVExpr = SE->getSCEV(IV);
   auto *AddExpr = dyn_cast<SCEVAddRecExpr>(IVExpr);
 
   if (!AddExpr) {
@@ -291,14 +291,16 @@ const SCEV *MVETailPredication::IsSafeActiveMask(IntrinsicInst *ActiveLaneMask,
     //
     // which what we will be using here.
     //
-    auto *VW = SE->getSCEV(ConstantInt::get(TripCount->getType(), VectorWidth));
+    const SCEV *VW =
+        SE->getSCEV(ConstantInt::get(TripCount->getType(), VectorWidth));
     // ElementCount + (VW-1):
-    auto *Start = AddExpr->getStart();
-    auto *ECPlusVWMinus1 = SE->getAddExpr(EC,
+    const SCEV *Start = AddExpr->getStart();
+    const SCEV *ECPlusVWMinus1 = SE->getAddExpr(
+        EC,
         SE->getSCEV(ConstantInt::get(TripCount->getType(), VectorWidth - 1)));
 
     // Ceil = ElementCount + (VW-1) / VW
-    auto *Ceil = SE->getUDivExpr(ECPlusVWMinus1, VW);
+    const SCEV *Ceil = SE->getUDivExpr(ECPlusVWMinus1, VW);
 
     // Prevent unused variable warnings with TC
     (void)TC;
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index dd7c89034ca09..dfb4352e501c6 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -1287,7 +1287,7 @@ createReplacement(ICmpInst *ICmp, const Loop *L, BasicBlock *ExitingBB,
     MaxIter = SE->getZeroExtendExpr(MaxIter, ARTy);
   else if (SE->getTypeSizeInBits(ARTy) < SE->getTypeSizeInBits(MaxIterTy)) {
     const SCEV *MinusOne = SE->getMinusOne(ARTy);
-    auto *MaxAllowedIter = SE->getZeroExtendExpr(MinusOne, MaxIterTy);
+    const SCEV *MaxAllowedIter = SE->getZeroExtendExpr(MinusOne, MaxIterTy);
     if (SE->isKnownPredicateAt(ICmpInst::ICMP_ULE, MaxIter, MaxAllowedIter, BI))
       MaxIter = SE->getTruncateExpr(MaxIter, ARTy);
   }
@@ -1299,7 +1299,7 @@ createReplacement(ICmpInst *ICmp, const Loop *L, BasicBlock *ExitingBB,
     // So we manually construct umin(a - 1, b - 1).
     SmallVector<const SCEV *, 4> Elements;
     if (auto *UMin = dyn_cast<SCEVUMinExpr>(MaxIter)) {
-      for (auto *Op : UMin->operands())
+      for (const SCEV *Op : UMin->operands())
         Elements.push_back(SE->getMinusSCEV(Op, SE->getOne(Op->getType())));
       MaxIter = SE->getUMinFromMismatchedTypes(Elements);
     } else
@@ -1376,15 +1376,15 @@ static bool optimizeLoopExitWithUnknownExitCount(
     for (auto *ICmp : LeafConditions) {
       auto EL = SE->computeExitLimitFromCond(L, ICmp, Inverted,
                                              /*ControlsExit*/ false);
-      auto *ExitMax = EL.SymbolicMaxNotTaken;
+      const SCEV *ExitMax = EL.SymbolicMaxNotTaken;
       if (isa<SCEVCouldNotCompute>(ExitMax))
         continue;
       // They could be of different types (specifically this happens after
       // IV widening).
       auto *WiderType =
           SE->getWiderType(ExitMax->getType(), MaxIter->getType());
-      auto *WideExitMax = SE->getNoopOrZeroExtend(ExitMax, WiderType);
-      auto *WideMaxIter = SE->getNoopOrZeroExtend(MaxIter, WiderType);
+      const SCEV *WideExitMax = SE->getNoopOrZeroExtend(ExitMax, WiderType);
+      const SCEV *WideMaxIter = SE->getNoopOrZeroExtend(MaxIter, WiderType);
       if (WideExitMax == WideMaxIter)
         ICmpsFailingOnLastIter.insert(ICmp);
     }
diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index bfe9374cf2f8c..a8cf8ab3dfde2 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -404,9 +404,9 @@ breakBackedgeIfNotTaken(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
   if (!L->getLoopLatch())
     return LoopDeletionResult::Unmodified;
 
-  auto *BTCMax = SE.getConstantMaxBackedgeTakenCount(L);
+  const SCEV *BTCMax = SE.getConstantMaxBackedgeTakenCount(L);
   if (!BTCMax->isZero()) {
-    auto *BTC = SE.getBackedgeTakenCount(L);
+    const SCEV *BTC = SE.getBackedgeTakenCount(L);
     if (!BTC->isZero()) {
       if (!isa<SCEVCouldNotCompute>(BTC) && SE.isKnownNonZero(BTC))
         return LoopDeletionResult::Unmodified;
diff --git a/llvm/lib/Transforms/Scalar/LoopPredication.cpp b/llvm/lib/Transforms/Scalar/LoopPredication.cpp
index 027dbb9c0f71a..209b083a4e91a 100644
--- a/llvm/lib/Transforms/Scalar/LoopPredication.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopPredication.cpp
@@ -677,7 +677,7 @@ LoopPredication::widenICmpRangeCheck(ICmpInst *ICI, SCEVExpander &Expander,
     LLVM_DEBUG(dbgs() << "Range check IV is not affine!\n");
     return std::nullopt;
   }
-  auto *Step = RangeCheckIV->getStepRecurrence(*SE);
+  const SCEV *Step = RangeCheckIV->getStepRecurrence(*SE);
   // We cannot just compare with latch IV step because the latch and range IVs
   // may have different types.
   if (!isSupportedStep(Step)) {
@@ -845,7 +845,7 @@ std::optional<LoopICmp> LoopPredication::parseLoopLatchICmp() {
     return std::nullopt;
   }
 
-  auto *Step = Result->IV->getStepRecurrence(*SE);
+  const SCEV *Step = Result->IV->getStepRecurrence(*SE);
   if (!isSupportedStep(Step)) {
     LLVM_DEBUG(dbgs() << "Unsupported loop stride(" << *Step << ")!\n");
     return std::nullopt;
diff --git a/llvm/lib/Transforms/Utils/LowerMemIntrinsics.cpp b/llvm/lib/Transforms/Utils/LowerMemIntrinsics.cpp
index acd3f2802031e..505eef02d8161 100644
--- a/llvm/lib/Transforms/Utils/LowerMemIntrinsics.cpp
+++ b/llvm/lib/Transforms/Utils/LowerMemIntrinsics.cpp
@@ -497,8 +497,8 @@ static void createMemSetLoop(Instruction *InsertBefore, Value *DstAddr,
 template <typename T>
 static bool canOverlap(MemTransferBase<T> *Memcpy, ScalarEvolution *SE) {
   if (SE) {
-    auto *SrcSCEV = SE->getSCEV(Memcpy->getRawSource());
-    auto *DestSCEV = SE->getSCEV(Memcpy->getRawDest());
+    const SCEV *SrcSCEV = SE->getSCEV(Memcpy->getRawSource());
+    const SCEV *DestSCEV = SE->getSCEV(Memcpy->getRawDest());
     if (SE->isKnownPredicateAt(CmpInst::ICMP_NE, SrcSCEV, DestSCEV, Memcpy))
       return false;
   }
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 912c02c2ed3ae..cdc17e36af4a4 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -162,8 +162,8 @@ Value *SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand)
       D = ConstantInt::get(UseInst->getContext(),
                            APInt::getOneBitSet(BitWidth, D->getZExtValue()));
     }
-    const auto *LHS = SE->getSCEV(IVSrc);
-    const auto *RHS = SE->getSCEV(D);
+    const SCEV *LHS = SE->getSCEV(IVSrc);
+    const SCEV *RHS = SE->getSCEV(D);
     FoldedExpr = SE->getUDivExpr(LHS, RHS);
     // We might have 'exact' flag set at this point which will no longer be
     // correct after we make the replacement.
@@ -292,8 +292,8 @@ void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp,
 
 bool SimplifyIndvar::eliminateSDiv(BinaryOperator *SDiv) {
   // Get the SCEVs for the ICmp operands.
-  auto *N = SE->getSCEV(SDiv->getOperand(0));
-  auto *D = SE->getSCEV(SDiv->getOperand(1));
+  const SCEV *N = SE->getSCEV(SDiv->getOperand(0));
+  const SCEV *D = SE->getSCEV(SDiv->getOperand(1));
 
   // Simplify unnecessary loops away.
   const Loop *L = LI->getLoopFor(SDiv->getParent());
@@ -389,7 +389,7 @@ void SimplifyIndvar::simplifyIVRemainder(BinaryOperator *Rem,
     }
 
     auto *T = Rem->getType();
-    const auto *NLessOne = SE->getMinusSCEV(N, SE->getOne(T));
+    const SCEV *NLessOne = SE->getMinusSCEV(N, SE->getOne(T));
     if (SE->isKnownPredicate(LT, NLessOne, D)) {
       replaceRemWithNumeratorOrZero(Rem);
       return;
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 9de49d1bcfeac..93382c901f381 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -511,14 +511,15 @@ class SCEVAddRecForUniformityRewriter
     // Build a new AddRec by multiplying the step by StepMultiplier and
     // incrementing the start by Offset * step.
     Type *Ty = Expr->getType();
-    auto *Step = Expr->getStepRecurrence(SE);
+    const SCEV *Step = Expr->getStepRecurrence(SE);
     if (!SE.isLoopInvariant(Step, TheLoop)) {
       CannotAnalyze = true;
       return Expr;
     }
-    auto *NewStep = SE.getMulExpr(Step, SE.getConstant(Ty, StepMultiplier));
-    auto *ScaledOffset = SE.getMulExpr(Step, SE.getConstant(Ty, Offset));
-    auto *NewStart = SE.getAddExpr(Expr->getStart(), ScaledOffset);
+    const SCEV *NewStep =
+        SE.getMulExpr(Step, SE.getConstant(Ty, StepMultiplier));
+    const SCEV *ScaledOffset = SE.getMulExpr(Step, SE.getConstant(Ty, Offset));
+    const SCEV *NewStart = SE.getAddExpr(Expr->getStart(), ScaledOffset);
     return SE.getAddRecExpr(NewStart, NewStep, TheLoop, SCEV::FlagAnyWrap);
   }
 
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 140a1b1ffbafe..4adbdf2938fd1 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -18649,10 +18649,10 @@ bool SLPVectorizerPass::vectorizeGEPIndices(BasicBlock *BB, BoUpSLP &R) {
         auto *GEPI = GEPList[I];
         if (!Candidates.count(GEPI))
           continue;
-        auto *SCEVI = SE->getSCEV(GEPList[I]);
+        const SCEV *SCEVI = SE->getSCEV(GEPList[I]);
         for (int J = I + 1; J < E && Candidates.size() > 1; ++J) {
           auto *GEPJ = GEPList[J];
-          auto *SCEVJ = SE->getSCEV(GEPList[J]);
+          const SCEV *SCEVJ = SE->getSCEV(GEPList[J]);
           if (isa<SCEVConstant>(SE->getMinusSCEV(SCEVI, SCEVJ))) {
             Candidates.remove(GEPI);
             Candidates.remove(GEPJ);
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index a7b3c5c404ab7..8ab22ef746c25 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -141,9 +141,9 @@ TEST_F(ScalarEvolutionsTest, SimplifiedPHI) {
   PN->addIncoming(Constant::getNullValue(Ty), EntryBB);
   PN->addIncoming(UndefValue::get(Ty), LoopBB);
   ScalarEvolution SE = buildSE(*F);
-  auto *S1 = SE.getSCEV(PN);
-  auto *S2 = SE.getSCEV(PN);
-  auto *ZeroConst = SE.getConstant(Ty, 0);
+  const SCEV *S1 = SE.getSCEV(PN);
+  const SCEV *S2 = SE.getSCEV(PN);
+  const SCEV *ZeroConst = SE.getConstant(Ty, 0);
 
   // At some point, only the first call to getSCEV returned the simplified
   // SCEVConstant and later calls just returned a SCEVUnknown referencing the
@@ -238,9 +238,9 @@ TEST_F(ScalarEvolutionsTest, CommutativeExprOperandOrder) {
     auto *IV0 = getInstructionByName(F, "iv0");
     auto *IV0Inc = getInstructionByName(F, "iv0.inc");
 
-    auto *FirstExprForIV0 = SE.getSCEV(IV0);
-    auto *FirstExprForIV0Inc = SE.getSCEV(IV0Inc);
-    auto *SecondExprForIV0 = SE.getSCEV(IV0);
+    const SCEV *FirstExprForIV0 = SE.getSCEV(IV0);
+    const SCEV *FirstExprForIV0Inc = SE.getSCEV(IV0Inc);
+    const SCEV *SecondExprForIV0 = SE.getSCEV(IV0);
 
     EXPECT_TRUE(isa<SCEVAddRecExpr>(FirstExprForIV0));
     EXPECT_TRUE(isa<SCEVAddRecExpr>(FirstExprForIV0Inc));
@@ -260,12 +260,12 @@ TEST_F(ScalarEvolutionsTest, CommutativeExprOperandOrder) {
     SmallVector<const SCEV *, 3> Ops4 = {C, B, A};
     SmallVector<const SCEV *, 3> Ops5 = {C, A, B};
 
-    auto *Mul0 = SE.getMulExpr(Ops0);
-    auto *Mul1 = SE.getMulExpr(Ops1);
-    auto *Mul2 = SE.getMulExpr(Ops2);
-    auto *Mul3 = SE.getMulExpr(Ops3);
-    auto *Mul4 = SE.getMulExpr(Ops4);
-    auto *Mul5 = SE.getMulExpr(Ops5);
+    const SCEV *Mul0 = SE.getMulExpr(Ops0);
+    const SCEV *Mul1 = SE.getMulExpr(Ops1);
+    const SCEV *Mul2 = SE.getMulExpr(Ops2);
+    const SCEV *Mul3 = SE.getMulExpr(Ops3);
+    const SCEV *Mul4 = SE.getMulExpr(Ops4);
+    const SCEV *Mul5 = SE.getMulExpr(Ops5);
 
     EXPECT_EQ(Mul0, Mul1) << "Expected " << *Mul0 << " == " << *Mul1;
     EXPECT_EQ(Mul1, Mul2) << "Expected " << *Mul1 << " == " << *Mul2;
@@ -383,8 +383,8 @@ TEST_F(ScalarEvolutionsTest, CompareValueComplexity) {
   // CompareValueComplexity that is both fast and more accurate.
 
   ScalarEvolution SE = buildSE(*F);
-  auto *A = SE.getSCEV(MulA);
-  auto *B = SE.getSCEV(MulB);
+  const SCEV *A = SE.getSCEV(MulA);
+  const SCEV *B = SE.getSCEV(MulB);
   EXPECT_NE(A, B);
 }
 
@@ -430,21 +430,21 @@ TEST_F(ScalarEvolutionsTest, SCEVAddExpr) {
   EXPECT_EQ(AddWithNUW->getNumOperands(), 3u);
   EXPECT_EQ(AddWithNUW->getNoWrapFlags(), SCEV::FlagNUW);
 
-  auto *AddWithAnyWrap =
+  const SCEV *AddWithAnyWrap =
       SE.getAddExpr(SE.getSCEV(A3), SE.getSCEV(A4), SCEV::FlagAnyWrap);
   auto *AddWithAnyWrapNUW = cast<SCEVAddExpr>(
       SE.getAddExpr(AddWithAnyWrap, SE.getSCEV(A5), SCEV::FlagNUW));
   EXPECT_EQ(AddWithAnyWrapNUW->getNumOperands(), 3u);
   EXPECT_EQ(AddWithAnyWrapNUW->getNoWrapFlags(), SCEV::FlagAnyWrap);
 
-  auto *AddWithNSW = SE.getAddExpr(
+  const SCEV *AddWithNSW = SE.getAddExpr(
       SE.getSCEV(A2), SE.getConstant(APInt(32, 99)), SCEV::FlagNSW);
   auto *AddWithNSW_NUW = cast<SCEVAddExpr>(
       SE.getAddExpr(AddWithNSW, SE.getSCEV(A5), SCEV::FlagNUW));
   EXPECT_EQ(AddWithNSW_NUW->getNumOperands(), 3u);
   EXPECT_EQ(AddWithNSW_NUW->getNoWrapFlags(), SCEV::FlagAnyWrap);
 
-  auto *AddWithNSWNUW =
+  const SCEV *AddWithNSWNUW =
       SE.getAddExpr(SE.getSCEV(A2), SE.getSCEV(A4),
                     ScalarEvolution::setFlags(SCEV::FlagNUW, SCEV::FlagNSW));
   auto *AddWithNSWNUW_NUW = cast<SCEVAddExpr>(
@@ -780,8 +780,8 @@ TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetLoop) {
 
   // The add recurrence {5,+,1} does not correspond to any PHI in the IR, and
   // that is relevant to this test.
-  auto *Five = SE.getConstant(APInt(/*numBits=*/64, 5));
-  auto *AR =
+  const SCEV *Five = SE.getConstant(APInt(/*numBits=*/64, 5));
+  const SCEV *AR =
       SE.getAddRecExpr(Five, SE.getOne(T_int64), Loop, SCEV::FlagAnyWrap);
   const SCEV *ARAtLoopExit = SE.getSCEVAtScope(AR, nullptr);
   EXPECT_FALSE(isa<SCEVCouldNotCompute>(ARAtLoopExit));
@@ -1019,19 +1019,19 @@ TEST_F(ScalarEvolutionsTest, SCEVFoldSumOfTruncs) {
   ScalarEvolution SE = buildSE(*F);
 
   auto *Arg = &*(F->arg_begin());
-  const auto *ArgSCEV = SE.getSCEV(Arg);
+  const SCEV *ArgSCEV = SE.getSCEV(Arg);
 
   // Build the SCEV
-  const auto *A0 = SE.getNegativeSCEV(ArgSCEV);
-  const auto *A1 = SE.getTruncateExpr(A0, Int32Ty);
-  const auto *A = SE.getNegativeSCEV(A1);
+  const SCEV *A0 = SE.getNegativeSCEV(ArgSCEV);
+  const SCEV *A1 = SE.getTruncateExpr(A0, Int32Ty);
+  const SCEV *A = SE.getNegativeSCEV(A1);
 
-  const auto *B0 = SE.getTruncateExpr(ArgSCEV, Int32Ty);
-  const auto *B = SE.getNegativeSCEV(B0);
+  const SCEV *B0 = SE.getTruncateExpr(ArgSCEV, Int32Ty);
+  const SCEV *B = SE.getNegativeSCEV(B0);
 
-  const auto *Expr = SE.getAddExpr(A, B);
+  const SCEV *Expr = SE.getAddExpr(A, B);
   // Verify that the SCEV was folded to 0
-  const auto *ZeroConst = SE.getConstant(Int32Ty, 0);
+  const SCEV *ZeroConst = SE.getConstant(Int32Ty, 0);
   EXPECT_EQ(Expr, ZeroConst);
 }
 
@@ -1108,7 +1108,7 @@ TEST_F(ScalarEvolutionsTest, SCEVLoopDecIntrinsic) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *ScevInc = SE.getSCEV(getInstructionByName(F, "inc"));
+    const SCEV *ScevInc = SE.getSCEV(getInstructionByName(F, "inc"));
     EXPECT_TRUE(isa<SCEVAddRecExpr>(ScevInc));
   });
 }
@@ -1139,13 +1139,15 @@ TEST_F(ScalarEvolutionsTest, SCEVComputeConstantDifference) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *ScevV0 = SE.getSCEV(getInstructionByName(F, "v0")); // %pp
-    auto *ScevV3 = SE.getSCEV(getInstructionByName(F, "v3")); // (3 + %pp)
-    auto *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
-    auto *ScevXA = SE.getSCEV(getInstructionByName(F, "xa")); // {%pp,+,1}
-    auto *ScevYY = SE.getSCEV(getInstructionByName(F, "yy")); // {(3 + %pp),+,1}
-    auto *ScevXB = SE.getSCEV(getInstructionByName(F, "xb")); // {%pp,+,1}
-    auto *ScevIVNext = SE.getSCEV(getInstructionByName(F, "iv.next")); // {1,+,1}
+    const SCEV *ScevV0 = SE.getSCEV(getInstructionByName(F, "v0")); // %pp
+    const SCEV *ScevV3 = SE.getSCEV(getInstructionByName(F, "v3")); // (3 + %pp)
+    const SCEV *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
+    const SCEV *ScevXA = SE.getSCEV(getInstructionByName(F, "xa")); // {%pp,+,1}
+    const SCEV *ScevYY =
+        SE.getSCEV(getInstructionByName(F, "yy")); // {(3 + %pp),+,1}
+    const SCEV *ScevXB = SE.getSCEV(getInstructionByName(F, "xb")); // {%pp,+,1}
+    const SCEV *ScevIVNext =
+        SE.getSCEV(getInstructionByName(F, "iv.next")); // {1,+,1}
 
     auto diff = [&SE](const SCEV *LHS, const SCEV *RHS) -> std::optional<int> {
       auto ConstantDiffOrNone = computeConstantDifference(SE, LHS, RHS);
@@ -1197,16 +1199,17 @@ TEST_F(ScalarEvolutionsTest, SCEVrewriteUnknowns) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
-    auto *ScevI = SE.getSCEV(getArgByName(F, "i"));           // {0,+,1}
+    const SCEV *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
+    const SCEV *ScevI = SE.getSCEV(getArgByName(F, "i"));           // {0,+,1}
 
     ValueToSCEVMapTy RewriteMap;
     RewriteMap[cast<SCEVUnknown>(ScevI)->getValue()] =
         SE.getUMinExpr(ScevI, SE.getConstant(ScevI->getType(), 17));
-    auto *WithUMin = SCEVParameterRewriter::rewrite(ScevIV, SE, RewriteMap);
+    const SCEV *WithUMin =
+        SCEVParameterRewriter::rewrite(ScevIV, SE, RewriteMap);
 
     EXPECT_NE(WithUMin, ScevIV);
-    auto *AR = dyn_cast<SCEVAddRecExpr>(WithUMin);
+    const auto *AR = dyn_cast<SCEVAddRecExpr>(WithUMin);
     EXPECT_TRUE(AR);
     EXPECT_EQ(AR->getStart(),
               SE.getUMinExpr(ScevI, SE.getConstant(ScevI->getType(), 17)));
@@ -1227,9 +1230,9 @@ TEST_F(ScalarEvolutionsTest, SCEVAddNUW) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *X = SE.getSCEV(getArgByName(F, "x"));
-    auto *One = SE.getOne(X->getType());
-    auto *Sum = SE.getAddExpr(X, One, SCEV::FlagNUW);
+    const SCEV *X = SE.getSCEV(getArgByName(F, "x"));
+    const SCEV *One = SE.getOne(X->getType());
+    const SCEV *Sum = SE.getAddExpr(X, One, SCEV::FlagNUW);
     EXPECT_TRUE(SE.isKnownPredicate(ICmpInst::ICMP_UGE, Sum, X));
     EXPECT_TRUE(SE.isKnownPredicate(ICmpInst::ICMP_UGT, Sum, X));
   });
@@ -1253,16 +1256,17 @@ TEST_F(ScalarEvolutionsTest, SCEVgetRanges) {
       Err, C);
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
-    auto *ScevI = SE.getSCEV(getArgByName(F, "i"));
+    const SCEV *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
+    const SCEV *ScevI = SE.getSCEV(getArgByName(F, "i"));
     EXPECT_EQ(SE.getUnsignedRange(ScevIV).getLower(), 0);
     EXPECT_EQ(SE.getUnsignedRange(ScevIV).getUpper(), 16);
 
-    auto *Add = SE.getAddExpr(ScevI, ScevIV);
+    const SCEV *Add = SE.getAddExpr(ScevI, ScevIV);
     ValueToSCEVMapTy RewriteMap;
     RewriteMap[cast<SCEVUnknown>(ScevI)->getValue()] =
         SE.getUMinExpr(ScevI, SE.getConstant(ScevI->getType(), 17));
-    auto *AddWithUMin = SCEVParameterRewriter::rewrite(Add, SE, RewriteMap);
+    const SCEV *AddWithUMin =
+        SCEVParameterRewriter::rewrite(Add, SE, RewriteMap);
     EXPECT_EQ(SE.getUnsignedRange(AddWithUMin).getLower(), 0);
     EXPECT_EQ(SE.getUnsignedRange(AddWithUMin).getUpper(), 33);
   });
@@ -1290,7 +1294,7 @@ TEST_F(ScalarEvolutionsTest, SCEVgetExitLimitForGuardedLoop) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
+    const SCEV *ScevIV = SE.getSCEV(getInstructionByName(F, "iv")); // {0,+,1}
     const Loop *L = cast<SCEVAddRecExpr>(ScevIV)->getLoop();
 
     const SCEV *BTC = SE.getBackedgeTakenCount(L);
@@ -1325,7 +1329,7 @@ TEST_F(ScalarEvolutionsTest, ImpliedViaAddRecStart) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *X = SE.getSCEV(getInstructionByName(F, "x"));
+    const SCEV *X = SE.getSCEV(getInstructionByName(F, "x"));
     auto *Context = getInstructionByName(F, "iv.next");
     EXPECT_TRUE(SE.isKnownPredicateAt(ICmpInst::ICMP_NE, X,
                                       SE.getZero(X->getType()), Context));
@@ -1354,8 +1358,8 @@ TEST_F(ScalarEvolutionsTest, UnsignedIsImpliedViaOperations) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *X = SE.getSCEV(getInstructionByName(F, "x"));
-    auto *Y = SE.getSCEV(getInstructionByName(F, "y"));
+    const SCEV *X = SE.getSCEV(getInstructionByName(F, "x"));
+    const SCEV *Y = SE.getSCEV(getInstructionByName(F, "y"));
     auto *Guarded = getInstructionByName(F, "y")->getParent();
     ASSERT_TRUE(Guarded);
     EXPECT_TRUE(
@@ -1397,8 +1401,8 @@ TEST_F(ScalarEvolutionsTest, ProveImplicationViaNarrowing) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *IV = SE.getSCEV(getInstructionByName(F, "iv"));
-    auto *Zero = SE.getZero(IV->getType());
+    const SCEV *IV = SE.getSCEV(getInstructionByName(F, "iv"));
+    const SCEV *Zero = SE.getZero(IV->getType());
     auto *Backedge = getInstructionByName(F, "iv.next")->getParent();
     ASSERT_TRUE(Backedge);
     (void)IV;
@@ -1525,8 +1529,8 @@ TEST_F(ScalarEvolutionsTest, SCEVUDivFloorCeiling) {
         using namespace llvm::APIntOps;
         APInt FloorInt = RoundingUDiv(NInt, DInt, APInt::Rounding::DOWN);
         APInt CeilingInt = RoundingUDiv(NInt, DInt, APInt::Rounding::UP);
-        auto *NS = SE.getConstant(NInt);
-        auto *DS = SE.getConstant(DInt);
+        const SCEV *NS = SE.getConstant(NInt);
+        const SCEV *DS = SE.getConstant(DInt);
         auto *FloorS = cast<SCEVConstant>(SE.getUDivExpr(NS, DS));
         auto *CeilingS = cast<SCEVConstant>(SE.getUDivCeilSCEV(NS, DS));
         ASSERT_TRUE(FloorS->getAPInt() == FloorInt);
@@ -1578,13 +1582,13 @@ TEST_F(ScalarEvolutionsTest, ApplyLoopGuards) {
   ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
 
   runWithSE(*M, "test", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
-    auto *TCScev = SE.getSCEV(getArgByName(F, "num"));
-    auto *ApplyLoopGuardsTC = SE.applyLoopGuards(TCScev, *LI.begin());
+    const SCEV *TCScev = SE.getSCEV(getArgByName(F, "num"));
+    const SCEV *ApplyLoopGuardsTC = SE.applyLoopGuards(TCScev, *LI.begin());
     // Assert that the new TC is (4 * ((4 umax %num) /u 4))
     APInt Four(32, 4);
-    auto *Constant4 = SE.getConstant(Four);
-    auto *Max = SE.getUMaxExpr(TCScev, Constant4);
-    auto *Mul = SE.getMulExpr(SE.getUDivExpr(Max, Constant4), Constant4);
+    const SCEV *Constant4 = SE.getConstant(Four);
+    const SCEV *Max = SE.getUMaxExpr(TCScev, Constant4);
+    const SCEV *Mul = SE.getMulExpr(SE.getUDivExpr(Max, Constant4), Constant4);
     ASSERT_TRUE(Mul == ApplyLoopGuardsTC);
   });
 }
diff --git a/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp b/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
index 8272c304ba288..193ff087ae6c8 100644
--- a/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
+++ b/llvm/unittests/Transforms/Utils/LoopUtilsTest.cpp
@@ -113,7 +113,7 @@ TEST(LoopUtils, IsKnownPositiveInLoopTest) {
         Loop *L = *LI.begin();
         assert(L && L->getName() == "loop" && "Expecting loop 'loop'");
         auto *Arg = F.getArg(0);
-        auto *ArgSCEV = SE.getSCEV(Arg);
+        const SCEV *ArgSCEV = SE.getSCEV(Arg);
         EXPECT_EQ(isKnownPositiveInLoop(ArgSCEV, L, SE), true);
       });
 }
@@ -137,7 +137,7 @@ TEST(LoopUtils, IsKnownNonPositiveInLoopTest) {
         Loop *L = *LI.begin();
         assert(L && L->getName() == "loop" && "Expecting loop 'loop'");
         auto *Arg = F.getArg(0);
-        auto *ArgSCEV = SE.getSCEV(Arg);
+        const SCEV *ArgSCEV = SE.getSCEV(Arg);
         EXPECT_EQ(isKnownNonPositiveInLoop(ArgSCEV, L, SE), true);
       });
 }
diff --git a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
index eb27e69da47fa..67bcfd87a15d9 100644
--- a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
+++ b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
@@ -117,7 +117,7 @@ TEST_F(ScalarEvolutionExpanderTest, ExpandPtrTypeSCEV) {
       CastInst::CreateBitOrPointerCast(Sel, I32PtrTy, "bitcast2", Br);
 
   ScalarEvolution SE = buildSE(*F);
-  auto *S = SE.getSCEV(CastB);
+  const SCEV *S = SE.getSCEV(CastB);
   EXPECT_TRUE(isa<SCEVUnknown>(S));
 }
 
@@ -185,7 +185,7 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVZeroExtendExprNonIntegral) {
   Instruction *Ret = Builder.CreateRetVoid();
 
   ScalarEvolution SE = buildSE(*F);
-  auto *AddRec =
+  const SCEV *AddRec =
       SE.getAddRecExpr(SE.getUnknown(GepBase), SE.getConstant(T_int64, 1),
                        LI->getLoopFor(L), SCEV::FlagNUW);
 
@@ -762,7 +762,7 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
                     SCEVExpander Exp(SE, M->getDataLayout(), "expander");
                     auto *InsertAt = I.getNextNode();
                     Value *V = Exp.expandCodeFor(AR, nullptr, InsertAt);
-                    auto *ExpandedAR = SE.getSCEV(V);
+                    const SCEV *ExpandedAR = SE.getSCEV(V);
                     // Check that the expansion happened literally.
                     EXPECT_EQ(AR, ExpandedAR);
                   });
@@ -811,7 +811,7 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
       SCEVExpander Exp(SE, M->getDataLayout(), "expander");
       auto *InsertAt = I.getNextNode();
       Value *V = Exp.expandCodeFor(AR, nullptr, InsertAt);
-      auto *ExpandedAR = SE.getSCEV(V);
+      const SCEV *ExpandedAR = SE.getSCEV(V);
       // Check that the expansion happened literally.
       EXPECT_EQ(AR, ExpandedAR);
     });
@@ -866,7 +866,7 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
               SCEVExpander Exp(SE, M->getDataLayout(), "expander");
               auto *InsertAt = I.getNextNode();
               Value *V = Exp.expandCodeFor(AR, nullptr, InsertAt);
-              auto *ExpandedAR = SE.getSCEV(V);
+              const SCEV *ExpandedAR = SE.getSCEV(V);
               // Check that the expansion happened literally.
               EXPECT_EQ(AR, ExpandedAR);
             });

>From 28c77e596611933119fb39ef36e84711b72fb947 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sat, 11 May 2024 19:32:57 +0100
Subject: [PATCH 2/3] [SCEV] Introduce SCEVUse, use it instead of const SCEV *
 (NFCI) (WIP).

This patch introduces SCEVUse, which is a tagged pointer containing the
used const SCEV *, plus extra bits to store NUW/NSW flags that are only
valid at the specific use.

This was suggested by @nikic as an alternative
to https://github.com/llvm/llvm-project/pull/90742.

This patch just updates most SCEV infrastructure to operate on SCEVUse
instead of const SCEV *. It does not introduce any code that makes use
of the use-specific flags yet which I'll share as follow-ups.

Note that this should be NFC, but currently there's at least one case
where it is not (turn-to-invariant.ll), which I'll investigate once we
agree on the overall direction.

This PR at the moment also contains a commit that updates various SCEV
clients to use `const SCEV *` instead of `const auto *`, to prepare for
this patch. This reduces the number of changes needed, as SCEVUse will
automatically convert to `const SCEV *`. This is a safe default, as it
just drops the use-specific flags for the expression (it will not drop
any use-specific flags for any of its operands though).

This probably
SCEVUse could probably also be used to address mis-compiles due to
equivalent AddRecs modulo flags result in an AddRec with incorrect flags
for some uses of some phis, e.g. the one
https://github.com/llvm/llvm-project/pull/80430 attempted to fix

Compile-time impact:
stage1-O3: +0.06%
stage1-ReleaseThinLTO: +0.07%
stage1-ReleaseLTO-g: +0.07%
stage2-O3: +0.11%

https://llvm-compile-time-tracker.com/compare.php?from=ce055843e2be9643bd58764783a7bb69f6db8c9a&to=8c7f4e9e154ebc4862c4e2716cedc3c688352d7c&stat=instructions:u
---
 llvm/include/llvm/Analysis/ScalarEvolution.h  |  804 +++---
 .../Analysis/ScalarEvolutionExpressions.h     |  287 +-
 llvm/lib/Analysis/DependenceAnalysis.cpp      |   20 +-
 llvm/lib/Analysis/IVDescriptors.cpp           |    2 +-
 llvm/lib/Analysis/LoopCacheAnalysis.cpp       |    3 +-
 llvm/lib/Analysis/ScalarEvolution.cpp         | 2359 ++++++++---------
 .../Scalar/InductiveRangeCheckElimination.cpp |    6 +-
 .../Transforms/Scalar/LoopIdiomRecognize.cpp  |   10 +-
 .../Transforms/Scalar/LoopStrengthReduce.cpp  |    9 +-
 .../IndVarSimplify/turn-to-invariant.ll       |    8 +-
 .../Analysis/ScalarEvolutionTest.cpp          |   16 +-
 11 files changed, 1804 insertions(+), 1720 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 5828cc156cc78..2859df9964555 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -69,6 +69,97 @@ enum SCEVTypes : unsigned short;
 
 extern bool VerifySCEV;
 
+class SCEV;
+
+class SCEVUse : public PointerIntPair<const SCEV *, 2> {
+public:
+  SCEVUse() : PointerIntPair(nullptr, 0) {}
+  SCEVUse(const SCEV *S) : PointerIntPair(S, 0) {}
+  SCEVUse(const SCEV *S, int Flags) : PointerIntPair(S, Flags) {}
+
+  operator const SCEV *() const { return getPointer(); }
+  const SCEV *operator->() const { return getPointer(); }
+  const SCEV *operator->() { return getPointer(); }
+
+  /// Print out the internal representation of this scalar to the specified
+  /// stream.  This should really only be used for debugging purposes.
+  void print(raw_ostream &OS) const;
+
+  /// This method is used for debugging.
+  void dump() const;
+};
+
+template <> struct PointerLikeTypeTraits<SCEVUse> {
+  static inline void *getAsVoidPointer(SCEVUse U) { return U.getOpaqueValue(); }
+  static inline SCEVUse getFromVoidPointer(void *P) {
+    SCEVUse U;
+    U.setFromOpaqueValue(P);
+    return U;
+  }
+
+  /// Note, we assume here that void* is related to raw malloc'ed memory and
+  /// that malloc returns objects at least 4-byte aligned. However, this may be
+  /// wrong, or pointers may be from something other than malloc. In this case,
+  /// you should specify a real typed pointer or avoid this template.
+  ///
+  /// All clients should use assertions to do a run-time check to ensure that
+  /// this is actually true.
+  static constexpr int NumLowBitsAvailable = 0;
+};
+
+template <> struct DenseMapInfo<SCEVUse> {
+  // The following should hold, but it would require T to be complete:
+  // static_assert(alignof(T) <= (1 << Log2MaxAlign),
+  //               "DenseMap does not support pointer keys requiring more than "
+  //               "Log2MaxAlign bits of alignment");
+  static constexpr uintptr_t Log2MaxAlign = 12;
+
+  static inline SCEVUse getEmptyKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= Log2MaxAlign;
+    return PointerLikeTypeTraits<SCEVUse>::getFromVoidPointer((void *)Val);
+  }
+
+  static inline SCEVUse getTombstoneKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-2);
+    Val <<= Log2MaxAlign;
+    return PointerLikeTypeTraits<SCEVUse>::getFromVoidPointer((void *)Val);
+  }
+
+  static unsigned getHashValue(SCEVUse U) {
+    void *PtrVal = PointerLikeTypeTraits<SCEVUse>::getAsVoidPointer(U);
+    return (unsigned((uintptr_t)PtrVal) >> 4) ^
+           (unsigned((uintptr_t)PtrVal) >> 9);
+  }
+
+  static bool isEqual(const SCEVUse LHS, const SCEVUse RHS) {
+    return LHS == RHS;
+  }
+};
+
+template <typename To> [[nodiscard]] inline decltype(auto) dyn_cast(SCEVUse U) {
+  assert(detail::isPresent(U.getPointer()) &&
+         "dyn_cast on a non-existent value");
+  return CastInfo<To, const SCEV *>::doCastIfPossible(U.getPointer());
+}
+
+template <typename To> [[nodiscard]] inline decltype(auto) cast(SCEVUse U) {
+  assert(detail::isPresent(U.getPointer()) &&
+         "dyn_cast on a non-existent value");
+  return CastInfo<To, const SCEV *>::doCast(U.getPointer());
+}
+
+template <typename To> [[nodiscard]] inline bool isa(SCEVUse U) {
+  return CastInfo<To, const SCEV *>::isPossible(U.getPointer());
+}
+
+template <class X> auto dyn_cast_or_null(SCEVUse U) {
+  const SCEV *Val = U.getPointer();
+  if (!detail::isPresent(Val))
+    return CastInfo<X, const SCEV *>::castFailed();
+  return CastInfo<X, const SCEV *>::doCastIfPossible(detail::unwrapValue(Val));
+}
+
 /// This class represents an analyzed expression in the program.  These are
 /// opaque objects that the client is not allowed to do much with directly.
 ///
@@ -147,7 +238,7 @@ class SCEV : public FoldingSetNode {
   Type *getType() const;
 
   /// Return operands of this SCEV expression.
-  ArrayRef<const SCEV *> operands() const;
+  ArrayRef<SCEVUse> operands() const;
 
   /// Return true if the expression is a constant zero.
   bool isZero() const;
@@ -202,6 +293,11 @@ inline raw_ostream &operator<<(raw_ostream &OS, const SCEV &S) {
   return OS;
 }
 
+inline raw_ostream &operator<<(raw_ostream &OS, const SCEVUse &S) {
+  S.print(OS);
+  return OS;
+}
+
 /// An object of this class is returned by queries that could not be answered.
 /// For example, if you ask for the number of iterations of a linked-list
 /// traversal loop, you will get one of these.  None of the standard SCEV
@@ -211,6 +307,7 @@ struct SCEVCouldNotCompute : public SCEV {
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S);
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents an assumption made using SCEV expressions which can
@@ -281,13 +378,13 @@ struct FoldingSetTrait<SCEVPredicate> : DefaultFoldingSetTrait<SCEVPredicate> {
 class SCEVComparePredicate final : public SCEVPredicate {
   /// We assume that LHS Pred RHS is true.
   const ICmpInst::Predicate Pred;
-  const SCEV *LHS;
-  const SCEV *RHS;
+  SCEVUse LHS;
+  SCEVUse RHS;
 
 public:
   SCEVComparePredicate(const FoldingSetNodeIDRef ID,
-                       const ICmpInst::Predicate Pred,
-                       const SCEV *LHS, const SCEV *RHS);
+                       const ICmpInst::Predicate Pred, SCEVUse LHS,
+                       SCEVUse RHS);
 
   /// Implementation of the SCEVPredicate interface
   bool implies(const SCEVPredicate *N) const override;
@@ -297,10 +394,10 @@ class SCEVComparePredicate final : public SCEVPredicate {
   ICmpInst::Predicate getPredicate() const { return Pred; }
 
   /// Returns the left hand side of the predicate.
-  const SCEV *getLHS() const { return LHS; }
+  SCEVUse getLHS() const { return LHS; }
 
   /// Returns the right hand side of the predicate.
-  const SCEV *getRHS() const { return RHS; }
+  SCEVUse getRHS() const { return RHS; }
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEVPredicate *P) {
@@ -415,8 +512,7 @@ class SCEVWrapPredicate final : public SCEVPredicate {
 /// ScalarEvolution::Preds folding set.  This is why the \c add function is sound.
 class SCEVUnionPredicate final : public SCEVPredicate {
 private:
-  using PredicateMap =
-      DenseMap<const SCEV *, SmallVector<const SCEVPredicate *, 4>>;
+  using PredicateMap = DenseMap<SCEVUse, SmallVector<const SCEVPredicate *, 4>>;
 
   /// Vector with references to all predicates in this union.
   SmallVector<const SCEVPredicate *, 16> Preds;
@@ -525,18 +621,17 @@ class ScalarEvolution {
   ///     loop { v2 = load @global2; }
   /// }
   /// No SCEV with operand V1, and v2 can exist in this program.
-  bool instructionCouldExistWithOperands(const SCEV *A, const SCEV *B);
+  bool instructionCouldExistWithOperands(SCEVUse A, SCEVUse B);
 
   /// Return true if the SCEV is a scAddRecExpr or it contains
   /// scAddRecExpr. The result will be cached in HasRecMap.
-  bool containsAddRecurrence(const SCEV *S);
+  bool containsAddRecurrence(SCEVUse S);
 
   /// Is operation \p BinOp between \p LHS and \p RHS provably does not have
   /// a signed/unsigned overflow (\p Signed)? If \p CtxI is specified, the
   /// no-overflow fact should be true in the context of this instruction.
-  bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed,
-                       const SCEV *LHS, const SCEV *RHS,
-                       const Instruction *CtxI = nullptr);
+  bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, SCEVUse LHS,
+                       SCEVUse RHS, const Instruction *CtxI = nullptr);
 
   /// Parse NSW/NUW flags from add/sub/mul IR binary operation \p Op into
   /// SCEV no-wrap flags, and deduce flag[s] that aren't known yet.
@@ -547,78 +642,84 @@ class ScalarEvolution {
   getStrengthenedNoWrapFlagsFromBinOp(const OverflowingBinaryOperator *OBO);
 
   /// Notify this ScalarEvolution that \p User directly uses SCEVs in \p Ops.
-  void registerUser(const SCEV *User, ArrayRef<const SCEV *> Ops);
+  void registerUser(SCEVUse User, ArrayRef<SCEVUse> Ops);
 
   /// Return true if the SCEV expression contains an undef value.
-  bool containsUndefs(const SCEV *S) const;
+  bool containsUndefs(SCEVUse S) const;
 
   /// Return true if the SCEV expression contains a Value that has been
   /// optimised out and is now a nullptr.
-  bool containsErasedValue(const SCEV *S) const;
+  bool containsErasedValue(SCEVUse S) const;
 
   /// Return a SCEV expression for the full generality of the specified
   /// expression.
-  const SCEV *getSCEV(Value *V);
+  SCEVUse getSCEV(Value *V);
 
   /// Return an existing SCEV for V if there is one, otherwise return nullptr.
-  const SCEV *getExistingSCEV(Value *V);
-
-  const SCEV *getConstant(ConstantInt *V);
-  const SCEV *getConstant(const APInt &Val);
-  const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
-  const SCEV *getLosslessPtrToIntExpr(const SCEV *Op, unsigned Depth = 0);
-  const SCEV *getPtrToIntExpr(const SCEV *Op, Type *Ty);
-  const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
-  const SCEV *getVScale(Type *Ty);
-  const SCEV *getElementCount(Type *Ty, ElementCount EC);
-  const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
-  const SCEV *getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
-                                    unsigned Depth = 0);
-  const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
-  const SCEV *getSignExtendExprImpl(const SCEV *Op, Type *Ty,
-                                    unsigned Depth = 0);
-  const SCEV *getCastExpr(SCEVTypes Kind, const SCEV *Op, Type *Ty);
-  const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
-  const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
-                         SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                         unsigned Depth = 0);
-  const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS,
-                         SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                         unsigned Depth = 0) {
-    SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
+  SCEVUse getExistingSCEV(Value *V);
+
+  SCEVUse getConstant(ConstantInt *V);
+  SCEVUse getConstant(const APInt &Val);
+  SCEVUse getConstant(Type *Ty, uint64_t V, bool isSigned = false);
+  SCEVUse getLosslessPtrToIntExpr(SCEVUse Op, unsigned Depth = 0);
+  SCEVUse getPtrToIntExpr(SCEVUse Op, Type *Ty);
+  SCEVUse getTruncateExpr(SCEVUse Op, Type *Ty, unsigned Depth = 0);
+  SCEVUse getVScale(Type *Ty);
+  SCEVUse getElementCount(Type *Ty, ElementCount EC);
+  SCEVUse getZeroExtendExpr(SCEVUse Op, Type *Ty, unsigned Depth = 0);
+  SCEVUse getZeroExtendExprImpl(SCEVUse Op, Type *Ty, unsigned Depth = 0);
+  SCEVUse getSignExtendExpr(SCEVUse Op, Type *Ty, unsigned Depth = 0);
+  SCEVUse getSignExtendExprImpl(SCEVUse Op, Type *Ty, unsigned Depth = 0);
+  SCEVUse getCastExpr(SCEVTypes Kind, SCEVUse Op, Type *Ty);
+  SCEVUse getAnyExtendExpr(SCEVUse Op, Type *Ty);
+  SCEVUse getAddExpr(ArrayRef<const SCEV *> Ops,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0);
+  SCEVUse getAddExpr(SmallVectorImpl<SCEVUse> &Ops,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0);
+  SCEVUse getAddExpr(SCEVUse LHS, SCEVUse RHS,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0) {
+    SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
     return getAddExpr(Ops, Flags, Depth);
   }
-  const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
-                         SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                         unsigned Depth = 0) {
-    SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2};
+  SCEVUse getAddExpr(SCEVUse Op0, SCEVUse Op1, SCEVUse Op2,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0) {
+    SmallVector<SCEVUse, 3> Ops = {Op0, Op1, Op2};
     return getAddExpr(Ops, Flags, Depth);
   }
-  const SCEV *getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
-                         SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                         unsigned Depth = 0);
-  const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS,
-                         SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                         unsigned Depth = 0) {
-    SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
+  SCEVUse getMulExpr(ArrayRef<const SCEV *> Ops,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0);
+  SCEVUse getMulExpr(SmallVectorImpl<SCEVUse> &Ops,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0);
+  SCEVUse getMulExpr(SCEVUse LHS, SCEVUse RHS,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0) {
+    SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
     return getMulExpr(Ops, Flags, Depth);
   }
-  const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
-                         SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                         unsigned Depth = 0) {
-    SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2};
+  SCEVUse getMulExpr(SCEVUse Op0, SCEVUse Op1, SCEVUse Op2,
+                     SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                     unsigned Depth = 0) {
+    SmallVector<SCEVUse, 3> Ops = {Op0, Op1, Op2};
     return getMulExpr(Ops, Flags, Depth);
   }
-  const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS);
-  const SCEV *getUDivExactExpr(const SCEV *LHS, const SCEV *RHS);
-  const SCEV *getURemExpr(const SCEV *LHS, const SCEV *RHS);
-  const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L,
-                            SCEV::NoWrapFlags Flags);
-  const SCEV *getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
-                            const Loop *L, SCEV::NoWrapFlags Flags);
-  const SCEV *getAddRecExpr(const SmallVectorImpl<const SCEV *> &Operands,
-                            const Loop *L, SCEV::NoWrapFlags Flags) {
-    SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
+  SCEVUse getUDivExpr(SCEVUse LHS, SCEVUse RHS);
+  SCEVUse getUDivExactExpr(SCEVUse LHS, SCEVUse RHS);
+  SCEVUse getURemExpr(SCEVUse LHS, SCEVUse RHS);
+  SCEVUse getAddRecExpr(SCEVUse Start, SCEVUse Step, const Loop *L,
+                        SCEV::NoWrapFlags Flags);
+  SCEVUse getAddRecExpr(ArrayRef<const SCEV *> Operands, const Loop *L,
+                        SCEV::NoWrapFlags Flags);
+  SCEVUse getAddRecExpr(SmallVectorImpl<SCEVUse> &Operands, const Loop *L,
+                        SCEV::NoWrapFlags Flags);
+  SCEVUse getAddRecExpr(const SmallVectorImpl<SCEVUse> &Operands, const Loop *L,
+                        SCEV::NoWrapFlags Flags) {
+    SmallVector<SCEVUse, 4> NewOp(Operands.begin(), Operands.end());
     return getAddRecExpr(NewOp, L, Flags);
   }
 
@@ -626,7 +727,7 @@ class ScalarEvolution {
   /// Predicates. If successful return these <AddRecExpr, Predicates>;
   /// The function is intended to be called from PSCEV (the caller will decide
   /// whether to actually add the predicates and carry out the rewrites).
-  std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
+  std::optional<std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>>>
   createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI);
 
   /// Returns an expression for a GEP
@@ -634,61 +735,61 @@ class ScalarEvolution {
   /// \p GEP The GEP. The indices contained in the GEP itself are ignored,
   /// instead we use IndexExprs.
   /// \p IndexExprs The expressions for the indices.
-  const SCEV *getGEPExpr(GEPOperator *GEP,
-                         const SmallVectorImpl<const SCEV *> &IndexExprs);
-  const SCEV *getAbsExpr(const SCEV *Op, bool IsNSW);
-  const SCEV *getMinMaxExpr(SCEVTypes Kind,
-                            SmallVectorImpl<const SCEV *> &Operands);
-  const SCEV *getSequentialMinMaxExpr(SCEVTypes Kind,
-                                      SmallVectorImpl<const SCEV *> &Operands);
-  const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS);
-  const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
-  const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS);
-  const SCEV *getUMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
-  const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS);
-  const SCEV *getSMinExpr(SmallVectorImpl<const SCEV *> &Operands);
-  const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS,
-                          bool Sequential = false);
-  const SCEV *getUMinExpr(SmallVectorImpl<const SCEV *> &Operands,
-                          bool Sequential = false);
-  const SCEV *getUnknown(Value *V);
-  const SCEV *getCouldNotCompute();
+  SCEVUse getGEPExpr(GEPOperator *GEP, ArrayRef<const SCEV *> IndexExprs);
+  SCEVUse getGEPExpr(GEPOperator *GEP,
+                     const SmallVectorImpl<SCEVUse> &IndexExprs);
+  SCEVUse getAbsExpr(SCEVUse Op, bool IsNSW);
+  SCEVUse getMinMaxExpr(SCEVTypes Kind, ArrayRef<const SCEV *> Operands);
+  SCEVUse getMinMaxExpr(SCEVTypes Kind, SmallVectorImpl<SCEVUse> &Operands);
+  SCEVUse getSequentialMinMaxExpr(SCEVTypes Kind,
+                                  SmallVectorImpl<SCEVUse> &Operands);
+  SCEVUse getSMaxExpr(SCEVUse LHS, SCEVUse RHS);
+  SCEVUse getSMaxExpr(SmallVectorImpl<SCEVUse> &Operands);
+  SCEVUse getUMaxExpr(SCEVUse LHS, SCEVUse RHS);
+  SCEVUse getUMaxExpr(SmallVectorImpl<SCEVUse> &Operands);
+  SCEVUse getSMinExpr(SCEVUse LHS, SCEVUse RHS);
+  SCEVUse getSMinExpr(SmallVectorImpl<SCEVUse> &Operands);
+  SCEVUse getUMinExpr(SCEVUse LHS, SCEVUse RHS, bool Sequential = false);
+  SCEVUse getUMinExpr(SmallVectorImpl<SCEVUse> &Operands,
+                      bool Sequential = false);
+  SCEVUse getUnknown(Value *V);
+  SCEVUse getCouldNotCompute();
 
   /// Return a SCEV for the constant 0 of a specific type.
-  const SCEV *getZero(Type *Ty) { return getConstant(Ty, 0); }
+  SCEVUse getZero(Type *Ty) { return getConstant(Ty, 0); }
 
   /// Return a SCEV for the constant 1 of a specific type.
-  const SCEV *getOne(Type *Ty) { return getConstant(Ty, 1); }
+  SCEVUse getOne(Type *Ty) { return getConstant(Ty, 1); }
 
   /// Return a SCEV for the constant \p Power of two.
-  const SCEV *getPowerOfTwo(Type *Ty, unsigned Power) {
+  SCEVUse getPowerOfTwo(Type *Ty, unsigned Power) {
     assert(Power < getTypeSizeInBits(Ty) && "Power out of range");
     return getConstant(APInt::getOneBitSet(getTypeSizeInBits(Ty), Power));
   }
 
   /// Return a SCEV for the constant -1 of a specific type.
-  const SCEV *getMinusOne(Type *Ty) {
+  SCEVUse getMinusOne(Type *Ty) {
     return getConstant(Ty, -1, /*isSigned=*/true);
   }
 
   /// Return an expression for a TypeSize.
-  const SCEV *getSizeOfExpr(Type *IntTy, TypeSize Size);
+  SCEVUse getSizeOfExpr(Type *IntTy, TypeSize Size);
 
   /// Return an expression for the alloc size of AllocTy that is type IntTy
-  const SCEV *getSizeOfExpr(Type *IntTy, Type *AllocTy);
+  SCEVUse getSizeOfExpr(Type *IntTy, Type *AllocTy);
 
   /// Return an expression for the store size of StoreTy that is type IntTy
-  const SCEV *getStoreSizeOfExpr(Type *IntTy, Type *StoreTy);
+  SCEVUse getStoreSizeOfExpr(Type *IntTy, Type *StoreTy);
 
   /// Return an expression for offsetof on the given field with type IntTy
-  const SCEV *getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo);
+  SCEVUse getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo);
 
   /// Return the SCEV object corresponding to -V.
-  const SCEV *getNegativeSCEV(const SCEV *V,
-                              SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
+  SCEVUse getNegativeSCEV(SCEVUse V,
+                          SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
 
   /// Return the SCEV object corresponding to ~V.
-  const SCEV *getNotSCEV(const SCEV *V);
+  SCEVUse getNotSCEV(SCEVUse V);
 
   /// Return LHS-RHS.  Minus is represented in SCEV as A+B*-1.
   ///
@@ -697,9 +798,9 @@ class ScalarEvolution {
   /// To compute the difference between two unrelated pointers, you can
   /// explicitly convert the arguments using getPtrToIntExpr(), for pointer
   /// types that support it.
-  const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
-                           SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                           unsigned Depth = 0);
+  SCEVUse getMinusSCEV(SCEVUse LHS, SCEVUse RHS,
+                       SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                       unsigned Depth = 0);
 
   /// Compute ceil(N / D). N and D are treated as unsigned values.
   ///
@@ -709,59 +810,59 @@ class ScalarEvolution {
   /// umin(N, 1) + floor((N - umin(N, 1)) / D)
   ///
   /// A denominator of zero or poison is handled the same way as getUDivExpr().
-  const SCEV *getUDivCeilSCEV(const SCEV *N, const SCEV *D);
+  SCEVUse getUDivCeilSCEV(SCEVUse N, SCEVUse D);
 
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type.  If the type must be extended, it is zero extended.
-  const SCEV *getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
-                                      unsigned Depth = 0);
+  SCEVUse getTruncateOrZeroExtend(SCEVUse V, Type *Ty, unsigned Depth = 0);
 
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type.  If the type must be extended, it is sign extended.
-  const SCEV *getTruncateOrSignExtend(const SCEV *V, Type *Ty,
-                                      unsigned Depth = 0);
+  SCEVUse getTruncateOrSignExtend(SCEVUse V, Type *Ty, unsigned Depth = 0);
 
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type.  If the type must be extended, it is zero extended.  The
   /// conversion must not be narrowing.
-  const SCEV *getNoopOrZeroExtend(const SCEV *V, Type *Ty);
+  SCEVUse getNoopOrZeroExtend(SCEVUse V, Type *Ty);
 
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type.  If the type must be extended, it is sign extended.  The
   /// conversion must not be narrowing.
-  const SCEV *getNoopOrSignExtend(const SCEV *V, Type *Ty);
+  SCEVUse getNoopOrSignExtend(SCEVUse V, Type *Ty);
 
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type. If the type must be extended, it is extended with
   /// unspecified bits. The conversion must not be narrowing.
-  const SCEV *getNoopOrAnyExtend(const SCEV *V, Type *Ty);
+  SCEVUse getNoopOrAnyExtend(SCEVUse V, Type *Ty);
 
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type.  The conversion must not be widening.
-  const SCEV *getTruncateOrNoop(const SCEV *V, Type *Ty);
+  SCEVUse getTruncateOrNoop(SCEVUse V, Type *Ty);
 
   /// Promote the operands to the wider of the types using zero-extension, and
   /// then perform a umax operation with them.
-  const SCEV *getUMaxFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS);
+  SCEVUse getUMaxFromMismatchedTypes(SCEVUse LHS, SCEVUse RHS);
 
   /// Promote the operands to the wider of the types using zero-extension, and
   /// then perform a umin operation with them.
-  const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS,
-                                         bool Sequential = false);
+  SCEVUse getUMinFromMismatchedTypes(SCEVUse LHS, SCEVUse RHS,
+                                     bool Sequential = false);
 
   /// Promote the operands to the wider of the types using zero-extension, and
   /// then perform a umin operation with them. N-ary function.
-  const SCEV *getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
-                                         bool Sequential = false);
+  SCEVUse getUMinFromMismatchedTypes(ArrayRef<const SCEV *> Ops,
+                                     bool Sequential = false);
+  SCEVUse getUMinFromMismatchedTypes(SmallVectorImpl<SCEVUse> &Ops,
+                                     bool Sequential = false);
 
   /// Transitively follow the chain of pointer-type operands until reaching a
   /// SCEV that does not have a single pointer operand. This returns a
   /// SCEVUnknown pointer for well-formed pointer-type expressions, but corner
   /// cases do exist.
-  const SCEV *getPointerBase(const SCEV *V);
+  SCEVUse getPointerBase(SCEVUse V);
 
   /// Compute an expression equivalent to S - getPointerBase(S).
-  const SCEV *removePointerBase(const SCEV *S);
+  SCEVUse removePointerBase(SCEVUse S);
 
   /// Return a SCEV expression for the specified value at the specified scope
   /// in the program.  The L value specifies a loop nest to evaluate the
@@ -773,31 +874,31 @@ class ScalarEvolution {
   ///
   /// In the case that a relevant loop exit value cannot be computed, the
   /// original value V is returned.
-  const SCEV *getSCEVAtScope(const SCEV *S, const Loop *L);
+  SCEVUse getSCEVAtScope(SCEVUse S, const Loop *L);
 
   /// This is a convenience function which does getSCEVAtScope(getSCEV(V), L).
-  const SCEV *getSCEVAtScope(Value *V, const Loop *L);
+  SCEVUse getSCEVAtScope(Value *V, const Loop *L);
 
   /// Test whether entry to the loop is protected by a conditional between LHS
   /// and RHS.  This is used to help avoid max expressions in loop trip
   /// counts, and to eliminate casts.
   bool isLoopEntryGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
-                                const SCEV *LHS, const SCEV *RHS);
+                                SCEVUse LHS, SCEVUse RHS);
 
   /// Test whether entry to the basic block is protected by a conditional
   /// between LHS and RHS.
   bool isBasicBlockEntryGuardedByCond(const BasicBlock *BB,
-                                      ICmpInst::Predicate Pred, const SCEV *LHS,
-                                      const SCEV *RHS);
+                                      ICmpInst::Predicate Pred, SCEVUse LHS,
+                                      SCEVUse RHS);
 
   /// Test whether the backedge of the loop is protected by a conditional
   /// between LHS and RHS.  This is used to eliminate casts.
   bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
-                                   const SCEV *LHS, const SCEV *RHS);
+                                   SCEVUse LHS, SCEVUse RHS);
 
   /// A version of getTripCountFromExitCount below which always picks an
   /// evaluation type which can not result in overflow.
-  const SCEV *getTripCountFromExitCount(const SCEV *ExitCount);
+  SCEVUse getTripCountFromExitCount(SCEVUse ExitCount);
 
   /// Convert from an "exit count" (i.e. "backedge taken count") to a "trip
   /// count".  A "trip count" is the number of times the header of the loop
@@ -806,8 +907,8 @@ class ScalarEvolution {
   /// expression can overflow if ExitCount = UINT_MAX.  If EvalTy is not wide
   /// enough to hold the result without overflow, result unsigned wraps with
   /// 2s-complement semantics.  ex: EC = 255 (i8), TC = 0 (i8)
-  const SCEV *getTripCountFromExitCount(const SCEV *ExitCount, Type *EvalTy,
-                                        const Loop *L);
+  SCEVUse getTripCountFromExitCount(SCEVUse ExitCount, Type *EvalTy,
+                                    const Loop *L);
 
   /// Returns the exact trip count of the loop if we can compute it, and
   /// the result is a small constant.  '0' is used to represent an unknown
@@ -838,8 +939,7 @@ class ScalarEvolution {
   /// unknown or not guaranteed to be the multiple of a constant., Will also
   /// return 1 if the trip count is very large (>= 2^32).
   /// Note that the argument is an exit count for loop L, NOT a trip count.
-  unsigned getSmallConstantTripMultiple(const Loop *L,
-                                        const SCEV *ExitCount);
+  unsigned getSmallConstantTripMultiple(const Loop *L, SCEVUse ExitCount);
 
   /// Returns the largest constant divisor of the trip count of the
   /// loop.  Will return 1 if no trip count could be computed, or if a
@@ -874,8 +974,8 @@ class ScalarEvolution {
   /// getBackedgeTakenCount.  The loop is guaranteed to exit (via *some* exit)
   /// before the backedge is executed (ExitCount + 1) times.  Note that there
   /// is no guarantee about *which* exit is taken on the exiting iteration.
-  const SCEV *getExitCount(const Loop *L, const BasicBlock *ExitingBlock,
-                           ExitCountKind Kind = Exact);
+  SCEVUse getExitCount(const Loop *L, const BasicBlock *ExitingBlock,
+                       ExitCountKind Kind = Exact);
 
   /// If the specified loop has a predictable backedge-taken count, return it,
   /// otherwise return a SCEVCouldNotCompute object. The backedge-taken count is
@@ -887,20 +987,20 @@ class ScalarEvolution {
   /// Note that it is not valid to call this method on a loop without a
   /// loop-invariant backedge-taken count (see
   /// hasLoopInvariantBackedgeTakenCount).
-  const SCEV *getBackedgeTakenCount(const Loop *L, ExitCountKind Kind = Exact);
+  SCEVUse getBackedgeTakenCount(const Loop *L, ExitCountKind Kind = Exact);
 
   /// Similar to getBackedgeTakenCount, except it will add a set of
   /// SCEV predicates to Predicates that are required to be true in order for
   /// the answer to be correct. Predicates can be checked with run-time
   /// checks and can be used to perform loop versioning.
-  const SCEV *getPredicatedBackedgeTakenCount(const Loop *L,
-                                              SmallVector<const SCEVPredicate *, 4> &Predicates);
+  SCEVUse getPredicatedBackedgeTakenCount(
+      const Loop *L, SmallVector<const SCEVPredicate *, 4> &Predicates);
 
   /// When successful, this returns a SCEVConstant that is greater than or equal
   /// to (i.e. a "conservative over-approximation") of the value returend by
   /// getBackedgeTakenCount.  If such a value cannot be computed, it returns the
   /// SCEVCouldNotCompute object.
-  const SCEV *getConstantMaxBackedgeTakenCount(const Loop *L) {
+  SCEVUse getConstantMaxBackedgeTakenCount(const Loop *L) {
     return getBackedgeTakenCount(L, ConstantMaximum);
   }
 
@@ -908,7 +1008,7 @@ class ScalarEvolution {
   /// to (i.e. a "conservative over-approximation") of the value returend by
   /// getBackedgeTakenCount.  If such a value cannot be computed, it returns the
   /// SCEVCouldNotCompute object.
-  const SCEV *getSymbolicMaxBackedgeTakenCount(const Loop *L) {
+  SCEVUse getSymbolicMaxBackedgeTakenCount(const Loop *L) {
     return getBackedgeTakenCount(L, SymbolicMaximum);
   }
 
@@ -966,60 +1066,60 @@ class ScalarEvolution {
   /// (at every loop iteration).  It is, at the same time, the minimum number
   /// of times S is divisible by 2.  For example, given {4,+,8} it returns 2.
   /// If S is guaranteed to be 0, it returns the bitwidth of S.
-  uint32_t getMinTrailingZeros(const SCEV *S);
+  uint32_t getMinTrailingZeros(SCEVUse S);
 
   /// Returns the max constant multiple of S.
-  APInt getConstantMultiple(const SCEV *S);
+  APInt getConstantMultiple(SCEVUse S);
 
   // Returns the max constant multiple of S. If S is exactly 0, return 1.
-  APInt getNonZeroConstantMultiple(const SCEV *S);
+  APInt getNonZeroConstantMultiple(SCEVUse S);
 
   /// Determine the unsigned range for a particular SCEV.
   /// NOTE: This returns a copy of the reference returned by getRangeRef.
-  ConstantRange getUnsignedRange(const SCEV *S) {
+  ConstantRange getUnsignedRange(SCEVUse S) {
     return getRangeRef(S, HINT_RANGE_UNSIGNED);
   }
 
   /// Determine the min of the unsigned range for a particular SCEV.
-  APInt getUnsignedRangeMin(const SCEV *S) {
+  APInt getUnsignedRangeMin(SCEVUse S) {
     return getRangeRef(S, HINT_RANGE_UNSIGNED).getUnsignedMin();
   }
 
   /// Determine the max of the unsigned range for a particular SCEV.
-  APInt getUnsignedRangeMax(const SCEV *S) {
+  APInt getUnsignedRangeMax(SCEVUse S) {
     return getRangeRef(S, HINT_RANGE_UNSIGNED).getUnsignedMax();
   }
 
   /// Determine the signed range for a particular SCEV.
   /// NOTE: This returns a copy of the reference returned by getRangeRef.
-  ConstantRange getSignedRange(const SCEV *S) {
+  ConstantRange getSignedRange(SCEVUse S) {
     return getRangeRef(S, HINT_RANGE_SIGNED);
   }
 
   /// Determine the min of the signed range for a particular SCEV.
-  APInt getSignedRangeMin(const SCEV *S) {
+  APInt getSignedRangeMin(SCEVUse S) {
     return getRangeRef(S, HINT_RANGE_SIGNED).getSignedMin();
   }
 
   /// Determine the max of the signed range for a particular SCEV.
-  APInt getSignedRangeMax(const SCEV *S) {
+  APInt getSignedRangeMax(SCEVUse S) {
     return getRangeRef(S, HINT_RANGE_SIGNED).getSignedMax();
   }
 
   /// Test if the given expression is known to be negative.
-  bool isKnownNegative(const SCEV *S);
+  bool isKnownNegative(SCEVUse S);
 
   /// Test if the given expression is known to be positive.
-  bool isKnownPositive(const SCEV *S);
+  bool isKnownPositive(SCEVUse S);
 
   /// Test if the given expression is known to be non-negative.
-  bool isKnownNonNegative(const SCEV *S);
+  bool isKnownNonNegative(SCEVUse S);
 
   /// Test if the given expression is known to be non-positive.
-  bool isKnownNonPositive(const SCEV *S);
+  bool isKnownNonPositive(SCEVUse S);
 
   /// Test if the given expression is known to be non-zero.
-  bool isKnownNonZero(const SCEV *S);
+  bool isKnownNonZero(SCEVUse S);
 
   /// Splits SCEV expression \p S into two SCEVs. One of them is obtained from
   /// \p S by substitution of all AddRec sub-expression related to loop \p L
@@ -1037,8 +1137,7 @@ class ScalarEvolution {
   /// 0 (initial value) for the first element and to {1, +, 1}<L1> (post
   /// increment value) for the second one. In both cases AddRec expression
   /// related to L2 remains the same.
-  std::pair<const SCEV *, const SCEV *> SplitIntoInitAndPostInc(const Loop *L,
-                                                                const SCEV *S);
+  std::pair<SCEVUse, SCEVUse> SplitIntoInitAndPostInc(const Loop *L, SCEVUse S);
 
   /// We'd like to check the predicate on every iteration of the most dominated
   /// loop between loops used in LHS and RHS.
@@ -1058,46 +1157,43 @@ class ScalarEvolution {
   ///    so we can assert on that.
   /// e. Return true if isLoopEntryGuardedByCond(Pred, E(LHS), E(RHS)) &&
   ///                   isLoopBackedgeGuardedByCond(Pred, B(LHS), B(RHS))
-  bool isKnownViaInduction(ICmpInst::Predicate Pred, const SCEV *LHS,
-                           const SCEV *RHS);
+  bool isKnownViaInduction(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS);
 
   /// Test if the given expression is known to satisfy the condition described
   /// by Pred, LHS, and RHS.
-  bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
-                        const SCEV *RHS);
+  bool isKnownPredicate(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS);
 
   /// Check whether the condition described by Pred, LHS, and RHS is true or
   /// false. If we know it, return the evaluation of this condition. If neither
   /// is proved, return std::nullopt.
-  std::optional<bool> evaluatePredicate(ICmpInst::Predicate Pred,
-                                        const SCEV *LHS, const SCEV *RHS);
+  std::optional<bool> evaluatePredicate(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                        SCEVUse RHS);
 
   /// Test if the given expression is known to satisfy the condition described
   /// by Pred, LHS, and RHS in the given Context.
-  bool isKnownPredicateAt(ICmpInst::Predicate Pred, const SCEV *LHS,
-                          const SCEV *RHS, const Instruction *CtxI);
+  bool isKnownPredicateAt(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
+                          const Instruction *CtxI);
 
   /// Check whether the condition described by Pred, LHS, and RHS is true or
   /// false in the given \p Context. If we know it, return the evaluation of
   /// this condition. If neither is proved, return std::nullopt.
-  std::optional<bool> evaluatePredicateAt(ICmpInst::Predicate Pred,
-                                          const SCEV *LHS, const SCEV *RHS,
-                                          const Instruction *CtxI);
+  std::optional<bool> evaluatePredicateAt(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                          SCEVUse RHS, const Instruction *CtxI);
 
   /// Test if the condition described by Pred, LHS, RHS is known to be true on
   /// every iteration of the loop of the recurrency LHS.
   bool isKnownOnEveryIteration(ICmpInst::Predicate Pred,
-                               const SCEVAddRecExpr *LHS, const SCEV *RHS);
+                               const SCEVAddRecExpr *LHS, SCEVUse RHS);
 
   /// Information about the number of loop iterations for which a loop exit's
   /// branch condition evaluates to the not-taken path.  This is a temporary
   /// pair of exact and max expressions that are eventually summarized in
   /// ExitNotTakenInfo and BackedgeTakenInfo.
   struct ExitLimit {
-    const SCEV *ExactNotTaken; // The exit is not taken exactly this many times
-    const SCEV *ConstantMaxNotTaken; // The exit is not taken at most this many
-                                     // times
-    const SCEV *SymbolicMaxNotTaken;
+    SCEVUse ExactNotTaken; // The exit is not taken exactly this many times
+    SCEVUse ConstantMaxNotTaken; // The exit is not taken at most this many
+                                 // times
+    SCEVUse SymbolicMaxNotTaken;
 
     // Not taken either exactly ConstantMaxNotTaken or zero times
     bool MaxOrZero = false;
@@ -1115,16 +1211,15 @@ class ScalarEvolution {
     /// Construct either an exact exit limit from a constant, or an unknown
     /// one from a SCEVCouldNotCompute.  No other types of SCEVs are allowed
     /// as arguments and asserts enforce that internally.
-    /*implicit*/ ExitLimit(const SCEV *E);
+    /*implicit*/ ExitLimit(SCEVUse E);
 
-    ExitLimit(
-        const SCEV *E, const SCEV *ConstantMaxNotTaken,
-        const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
-        ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *> PredSetList =
-            std::nullopt);
+    ExitLimit(SCEVUse E, SCEVUse ConstantMaxNotTaken,
+              SCEVUse SymbolicMaxNotTaken, bool MaxOrZero,
+              ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *>
+                  PredSetList = std::nullopt);
 
-    ExitLimit(const SCEV *E, const SCEV *ConstantMaxNotTaken,
-              const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
+    ExitLimit(SCEVUse E, SCEVUse ConstantMaxNotTaken,
+              SCEVUse SymbolicMaxNotTaken, bool MaxOrZero,
               const SmallPtrSetImpl<const SCEVPredicate *> &PredSet);
 
     /// Test whether this ExitLimit contains any computed information, or
@@ -1175,20 +1270,18 @@ class ScalarEvolution {
 
   struct LoopInvariantPredicate {
     ICmpInst::Predicate Pred;
-    const SCEV *LHS;
-    const SCEV *RHS;
+    SCEVUse LHS;
+    SCEVUse RHS;
 
-    LoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
-                           const SCEV *RHS)
+    LoopInvariantPredicate(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS)
         : Pred(Pred), LHS(LHS), RHS(RHS) {}
   };
   /// If the result of the predicate LHS `Pred` RHS is loop invariant with
   /// respect to L, return a LoopInvariantPredicate with LHS and RHS being
   /// invariants, available at L's entry. Otherwise, return std::nullopt.
   std::optional<LoopInvariantPredicate>
-  getLoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
-                            const SCEV *RHS, const Loop *L,
-                            const Instruction *CtxI = nullptr);
+  getLoopInvariantPredicate(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
+                            const Loop *L, const Instruction *CtxI = nullptr);
 
   /// If the result of the predicate LHS `Pred` RHS is loop invariant with
   /// respect to L at given Context during at least first MaxIter iterations,
@@ -1197,59 +1290,61 @@ class ScalarEvolution {
   /// should be the loop's exit condition.
   std::optional<LoopInvariantPredicate>
   getLoopInvariantExitCondDuringFirstIterations(ICmpInst::Predicate Pred,
-                                                const SCEV *LHS,
-                                                const SCEV *RHS, const Loop *L,
+                                                SCEVUse LHS, SCEVUse RHS,
+                                                const Loop *L,
                                                 const Instruction *CtxI,
-                                                const SCEV *MaxIter);
+                                                SCEVUse MaxIter);
 
   std::optional<LoopInvariantPredicate>
-  getLoopInvariantExitCondDuringFirstIterationsImpl(
-      ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const Loop *L,
-      const Instruction *CtxI, const SCEV *MaxIter);
+  getLoopInvariantExitCondDuringFirstIterationsImpl(ICmpInst::Predicate Pred,
+                                                    SCEVUse LHS, SCEVUse RHS,
+                                                    const Loop *L,
+                                                    const Instruction *CtxI,
+                                                    SCEVUse MaxIter);
 
   /// Simplify LHS and RHS in a comparison with predicate Pred. Return true
   /// iff any changes were made. If the operands are provably equal or
   /// unequal, LHS and RHS are set to the same value and Pred is set to either
   /// ICMP_EQ or ICMP_NE.
-  bool SimplifyICmpOperands(ICmpInst::Predicate &Pred, const SCEV *&LHS,
-                            const SCEV *&RHS, unsigned Depth = 0);
+  bool SimplifyICmpOperands(ICmpInst::Predicate &Pred, SCEVUse &LHS,
+                            SCEVUse &RHS, unsigned Depth = 0);
 
   /// Return the "disposition" of the given SCEV with respect to the given
   /// loop.
-  LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L);
+  LoopDisposition getLoopDisposition(SCEVUse S, const Loop *L);
 
   /// Return true if the value of the given SCEV is unchanging in the
   /// specified loop.
-  bool isLoopInvariant(const SCEV *S, const Loop *L);
+  bool isLoopInvariant(SCEVUse S, const Loop *L);
 
   /// Determine if the SCEV can be evaluated at loop's entry. It is true if it
   /// doesn't depend on a SCEVUnknown of an instruction which is dominated by
   /// the header of loop L.
-  bool isAvailableAtLoopEntry(const SCEV *S, const Loop *L);
+  bool isAvailableAtLoopEntry(SCEVUse S, const Loop *L);
 
   /// Return true if the given SCEV changes value in a known way in the
   /// specified loop.  This property being true implies that the value is
   /// variant in the loop AND that we can emit an expression to compute the
   /// value of the expression at any particular loop iteration.
-  bool hasComputableLoopEvolution(const SCEV *S, const Loop *L);
+  bool hasComputableLoopEvolution(SCEVUse S, const Loop *L);
 
   /// Return the "disposition" of the given SCEV with respect to the given
   /// block.
-  BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB);
+  BlockDisposition getBlockDisposition(SCEVUse S, const BasicBlock *BB);
 
   /// Return true if elements that makes up the given SCEV dominate the
   /// specified basic block.
-  bool dominates(const SCEV *S, const BasicBlock *BB);
+  bool dominates(SCEVUse S, const BasicBlock *BB);
 
   /// Return true if elements that makes up the given SCEV properly dominate
   /// the specified basic block.
-  bool properlyDominates(const SCEV *S, const BasicBlock *BB);
+  bool properlyDominates(SCEVUse S, const BasicBlock *BB);
 
   /// Test whether the given SCEV has Op as a direct or indirect operand.
-  bool hasOperand(const SCEV *S, const SCEV *Op) const;
+  bool hasOperand(SCEVUse S, SCEVUse Op) const;
 
   /// Return the size of an element read or written by Inst.
-  const SCEV *getElementSize(Instruction *Inst);
+  SCEVUse getElementSize(Instruction *Inst);
 
   void print(raw_ostream &OS) const;
   void verify() const;
@@ -1262,22 +1357,21 @@ class ScalarEvolution {
     return F.getParent()->getDataLayout();
   }
 
-  const SCEVPredicate *getEqualPredicate(const SCEV *LHS, const SCEV *RHS);
+  const SCEVPredicate *getEqualPredicate(SCEVUse LHS, SCEVUse RHS);
   const SCEVPredicate *getComparePredicate(ICmpInst::Predicate Pred,
-                                           const SCEV *LHS, const SCEV *RHS);
+                                           SCEVUse LHS, SCEVUse RHS);
 
   const SCEVPredicate *
   getWrapPredicate(const SCEVAddRecExpr *AR,
                    SCEVWrapPredicate::IncrementWrapFlags AddedFlags);
 
   /// Re-writes the SCEV according to the Predicates in \p A.
-  const SCEV *rewriteUsingPredicate(const SCEV *S, const Loop *L,
-                                    const SCEVPredicate &A);
+  SCEVUse rewriteUsingPredicate(SCEVUse S, const Loop *L,
+                                const SCEVPredicate &A);
   /// Tries to convert the \p S expression to an AddRec expression,
   /// adding additional predicates to \p Preds as required.
   const SCEVAddRecExpr *convertSCEVToAddRecWithPredicates(
-      const SCEV *S, const Loop *L,
-      SmallPtrSetImpl<const SCEVPredicate *> &Preds);
+      SCEVUse S, const Loop *L, SmallPtrSetImpl<const SCEVPredicate *> &Preds);
 
   /// Compute \p LHS - \p RHS and returns the result as an APInt if it is a
   /// constant, and std::nullopt if it isn't.
@@ -1286,8 +1380,7 @@ class ScalarEvolution {
   /// frugal here since we just bail out of actually constructing and
   /// canonicalizing an expression in the cases where the result isn't going
   /// to be a constant.
-  std::optional<APInt> computeConstantDifference(const SCEV *LHS,
-                                                 const SCEV *RHS);
+  std::optional<APInt> computeConstantDifference(SCEVUse LHS, SCEVUse RHS);
 
   /// Update no-wrap flags of an AddRec. This may drop the cached info about
   /// this AddRec (such as range info) in case if new flags may potentially
@@ -1295,7 +1388,7 @@ class ScalarEvolution {
   void setNoWrapFlags(SCEVAddRecExpr *AddRec, SCEV::NoWrapFlags Flags);
 
   /// Try to apply information from loop guards for \p L to \p Expr.
-  const SCEV *applyLoopGuards(const SCEV *Expr, const Loop *L);
+  SCEVUse applyLoopGuards(SCEVUse Expr, const Loop *L);
 
   /// Return true if the loop has no abnormal exits. That is, if the loop
   /// is not infinite, it must exit through an explicit edge in the CFG.
@@ -1313,22 +1406,22 @@ class ScalarEvolution {
   /// being poison as well. The returned set may be incomplete, i.e. there can
   /// be additional Values that also result in S being poison.
   void getPoisonGeneratingValues(SmallPtrSetImpl<const Value *> &Result,
-                                 const SCEV *S);
+                                 SCEVUse S);
 
   /// Check whether it is poison-safe to represent the expression S using the
   /// instruction I. If such a replacement is performed, the poison flags of
   /// instructions in DropPoisonGeneratingInsts must be dropped.
   bool canReuseInstruction(
-      const SCEV *S, Instruction *I,
+      SCEVUse S, Instruction *I,
       SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts);
 
   class FoldID {
-    const SCEV *Op = nullptr;
+    SCEVUse Op = nullptr;
     const Type *Ty = nullptr;
     unsigned short C;
 
   public:
-    FoldID(SCEVTypes C, const SCEV *Op, const Type *Ty) : Op(Op), Ty(Ty), C(C) {
+    FoldID(SCEVTypes C, SCEVUse Op, const Type *Ty) : Op(Op), Ty(Ty), C(C) {
       assert(Op);
       assert(Ty);
     }
@@ -1337,8 +1430,9 @@ class ScalarEvolution {
 
     unsigned computeHash() const {
       return detail::combineHashValue(
-          C, detail::combineHashValue(reinterpret_cast<uintptr_t>(Op),
-                                      reinterpret_cast<uintptr_t>(Ty)));
+          C,
+          detail::combineHashValue(reinterpret_cast<uintptr_t>(Op.getPointer()),
+                                   reinterpret_cast<uintptr_t>(Ty)));
     }
 
     bool operator==(const FoldID &RHS) const {
@@ -1387,14 +1481,14 @@ class ScalarEvolution {
   std::unique_ptr<SCEVCouldNotCompute> CouldNotCompute;
 
   /// The type for HasRecMap.
-  using HasRecMapType = DenseMap<const SCEV *, bool>;
+  using HasRecMapType = DenseMap<SCEVUse, bool>;
 
   /// This is a cache to record whether a SCEV contains any scAddRecExpr.
   HasRecMapType HasRecMap;
 
   /// The type for ExprValueMap.
   using ValueSetVector = SmallSetVector<Value *, 4>;
-  using ExprValueMapType = DenseMap<const SCEV *, ValueSetVector>;
+  using ExprValueMapType = DenseMap<SCEVUse, ValueSetVector>;
 
   /// ExprValueMap -- This map records the original values from which
   /// the SCEV expr is generated from.
@@ -1402,15 +1496,15 @@ class ScalarEvolution {
 
   /// The type for ValueExprMap.
   using ValueExprMapType =
-      DenseMap<SCEVCallbackVH, const SCEV *, DenseMapInfo<Value *>>;
+      DenseMap<SCEVCallbackVH, SCEVUse, DenseMapInfo<Value *>>;
 
   /// This is a cache of the values we have analyzed so far.
   ValueExprMapType ValueExprMap;
 
   /// This is a cache for expressions that got folded to a different existing
   /// SCEV.
-  DenseMap<FoldID, const SCEV *> FoldCache;
-  DenseMap<const SCEV *, SmallVector<FoldID, 2>> FoldCacheUser;
+  DenseMap<FoldID, SCEVUse> FoldCache;
+  DenseMap<SCEVUse, SmallVector<FoldID, 2>> FoldCacheUser;
 
   /// Mark predicate values currently being processed by isImpliedCond.
   SmallPtrSet<const Value *, 6> PendingLoopPredicates;
@@ -1433,26 +1527,26 @@ class ScalarEvolution {
   bool ProvingSplitPredicate = false;
 
   /// Memoized values for the getConstantMultiple
-  DenseMap<const SCEV *, APInt> ConstantMultipleCache;
+  DenseMap<SCEVUse, APInt> ConstantMultipleCache;
 
   /// Return the Value set from which the SCEV expr is generated.
-  ArrayRef<Value *> getSCEVValues(const SCEV *S);
+  ArrayRef<Value *> getSCEVValues(SCEVUse S);
 
   /// Private helper method for the getConstantMultiple method.
-  APInt getConstantMultipleImpl(const SCEV *S);
+  APInt getConstantMultipleImpl(SCEVUse S);
 
   /// Information about the number of times a particular loop exit may be
   /// reached before exiting the loop.
   struct ExitNotTakenInfo {
     PoisoningVH<BasicBlock> ExitingBlock;
-    const SCEV *ExactNotTaken;
-    const SCEV *ConstantMaxNotTaken;
-    const SCEV *SymbolicMaxNotTaken;
+    SCEVUse ExactNotTaken;
+    SCEVUse ConstantMaxNotTaken;
+    SCEVUse SymbolicMaxNotTaken;
     SmallPtrSet<const SCEVPredicate *, 4> Predicates;
 
     explicit ExitNotTakenInfo(
-        PoisoningVH<BasicBlock> ExitingBlock, const SCEV *ExactNotTaken,
-        const SCEV *ConstantMaxNotTaken, const SCEV *SymbolicMaxNotTaken,
+        PoisoningVH<BasicBlock> ExitingBlock, SCEVUse ExactNotTaken,
+        SCEVUse ConstantMaxNotTaken, SCEVUse SymbolicMaxNotTaken,
         const SmallPtrSet<const SCEVPredicate *, 4> &Predicates)
         : ExitingBlock(ExitingBlock), ExactNotTaken(ExactNotTaken),
           ConstantMaxNotTaken(ConstantMaxNotTaken),
@@ -1476,7 +1570,7 @@ class ScalarEvolution {
     /// Expression indicating the least constant maximum backedge-taken count of
     /// the loop that is known, or a SCEVCouldNotCompute. This expression is
     /// only valid if the redicates associated with all loop exits are true.
-    const SCEV *ConstantMax = nullptr;
+    SCEVUse ConstantMax = nullptr;
 
     /// Indicating if \c ExitNotTaken has an element for every exiting block in
     /// the loop.
@@ -1484,13 +1578,13 @@ class ScalarEvolution {
 
     /// Expression indicating the least maximum backedge-taken count of the loop
     /// that is known, or a SCEVCouldNotCompute. Lazily computed on first query.
-    const SCEV *SymbolicMax = nullptr;
+    SCEVUse SymbolicMax = nullptr;
 
     /// True iff the backedge is taken either exactly Max or zero times.
     bool MaxOrZero = false;
 
     bool isComplete() const { return IsComplete; }
-    const SCEV *getConstantMax() const { return ConstantMax; }
+    SCEVUse getConstantMax() const { return ConstantMax; }
 
   public:
     BackedgeTakenInfo() = default;
@@ -1501,7 +1595,7 @@ class ScalarEvolution {
 
     /// Initialize BackedgeTakenInfo from a list of exact exit counts.
     BackedgeTakenInfo(ArrayRef<EdgeExitInfo> ExitCounts, bool IsComplete,
-                      const SCEV *ConstantMax, bool MaxOrZero);
+                      SCEVUse ConstantMax, bool MaxOrZero);
 
     /// Test whether this BackedgeTakenInfo contains any computed information,
     /// or whether it's all SCEVCouldNotCompute values.
@@ -1531,29 +1625,29 @@ class ScalarEvolution {
     /// If we allowed SCEV predicates to be generated when populating this
     /// vector, this information can contain them and therefore a
     /// SCEVPredicate argument should be added to getExact.
-    const SCEV *getExact(const Loop *L, ScalarEvolution *SE,
-                         SmallVector<const SCEVPredicate *, 4> *Predicates = nullptr) const;
+    SCEVUse
+    getExact(const Loop *L, ScalarEvolution *SE,
+             SmallVector<const SCEVPredicate *, 4> *Predicates = nullptr) const;
 
     /// Return the number of times this loop exit may fall through to the back
     /// edge, or SCEVCouldNotCompute. The loop is guaranteed not to exit via
     /// this block before this number of iterations, but may exit via another
     /// block.
-    const SCEV *getExact(const BasicBlock *ExitingBlock,
-                         ScalarEvolution *SE) const;
+    SCEVUse getExact(const BasicBlock *ExitingBlock, ScalarEvolution *SE) const;
 
     /// Get the constant max backedge taken count for the loop.
-    const SCEV *getConstantMax(ScalarEvolution *SE) const;
+    SCEVUse getConstantMax(ScalarEvolution *SE) const;
 
     /// Get the constant max backedge taken count for the particular loop exit.
-    const SCEV *getConstantMax(const BasicBlock *ExitingBlock,
-                               ScalarEvolution *SE) const;
+    SCEVUse getConstantMax(const BasicBlock *ExitingBlock,
+                           ScalarEvolution *SE) const;
 
     /// Get the symbolic max backedge taken count for the loop.
-    const SCEV *getSymbolicMax(const Loop *L, ScalarEvolution *SE);
+    SCEVUse getSymbolicMax(const Loop *L, ScalarEvolution *SE);
 
     /// Get the symbolic max backedge taken count for the particular loop exit.
-    const SCEV *getSymbolicMax(const BasicBlock *ExitingBlock,
-                               ScalarEvolution *SE) const;
+    SCEVUse getSymbolicMax(const BasicBlock *ExitingBlock,
+                           ScalarEvolution *SE) const;
 
     /// Return true if the number of times this backedge is taken is either the
     /// value returned by getConstantMax or zero.
@@ -1569,7 +1663,7 @@ class ScalarEvolution {
   DenseMap<const Loop *, BackedgeTakenInfo> PredicatedBackedgeTakenCounts;
 
   /// Loops whose backedge taken counts directly use this non-constant SCEV.
-  DenseMap<const SCEV *, SmallPtrSet<PointerIntPair<const Loop *, 1, bool>, 4>>
+  DenseMap<SCEVUse, SmallPtrSet<PointerIntPair<const Loop *, 1, bool>, 4>>
       BECountUsers;
 
   /// This map contains entries for all of the PHI instructions that we
@@ -1581,16 +1675,16 @@ class ScalarEvolution {
   /// This map contains entries for all the expressions that we attempt to
   /// compute getSCEVAtScope information for, which can be expensive in
   /// extreme cases.
-  DenseMap<const SCEV *, SmallVector<std::pair<const Loop *, const SCEV *>, 2>>
+  DenseMap<SCEVUse, SmallVector<std::pair<const Loop *, SCEVUse>, 2>>
       ValuesAtScopes;
 
   /// Reverse map for invalidation purposes: Stores of which SCEV and which
   /// loop this is the value-at-scope of.
-  DenseMap<const SCEV *, SmallVector<std::pair<const Loop *, const SCEV *>, 2>>
+  DenseMap<SCEVUse, SmallVector<std::pair<const Loop *, SCEVUse>, 2>>
       ValuesAtScopesUsers;
 
   /// Memoized computeLoopDisposition results.
-  DenseMap<const SCEV *,
+  DenseMap<SCEVUse,
            SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>>
       LoopDispositions;
 
@@ -1618,33 +1712,33 @@ class ScalarEvolution {
   }
 
   /// Compute a LoopDisposition value.
-  LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
+  LoopDisposition computeLoopDisposition(SCEVUse S, const Loop *L);
 
   /// Memoized computeBlockDisposition results.
   DenseMap<
-      const SCEV *,
+      SCEVUse,
       SmallVector<PointerIntPair<const BasicBlock *, 2, BlockDisposition>, 2>>
       BlockDispositions;
 
   /// Compute a BlockDisposition value.
-  BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB);
+  BlockDisposition computeBlockDisposition(SCEVUse S, const BasicBlock *BB);
 
   /// Stores all SCEV that use a given SCEV as its direct operand.
-  DenseMap<const SCEV *, SmallPtrSet<const SCEV *, 8> > SCEVUsers;
+  DenseMap<SCEVUse, SmallPtrSet<SCEVUse, 8>> SCEVUsers;
 
   /// Memoized results from getRange
-  DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
+  DenseMap<SCEVUse, ConstantRange> UnsignedRanges;
 
   /// Memoized results from getRange
-  DenseMap<const SCEV *, ConstantRange> SignedRanges;
+  DenseMap<SCEVUse, ConstantRange> SignedRanges;
 
   /// Used to parameterize getRange
   enum RangeSignHint { HINT_RANGE_UNSIGNED, HINT_RANGE_SIGNED };
 
   /// Set the memoized range for the given SCEV.
-  const ConstantRange &setRange(const SCEV *S, RangeSignHint Hint,
+  const ConstantRange &setRange(SCEVUse S, RangeSignHint Hint,
                                 ConstantRange CR) {
-    DenseMap<const SCEV *, ConstantRange> &Cache =
+    DenseMap<SCEVUse, ConstantRange> &Cache =
         Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges;
 
     auto Pair = Cache.try_emplace(S, std::move(CR));
@@ -1656,29 +1750,29 @@ class ScalarEvolution {
   /// Determine the range for a particular SCEV.
   /// NOTE: This returns a reference to an entry in a cache. It must be
   /// copied if its needed for longer.
-  const ConstantRange &getRangeRef(const SCEV *S, RangeSignHint Hint,
+  const ConstantRange &getRangeRef(SCEVUse S, RangeSignHint Hint,
                                    unsigned Depth = 0);
 
   /// Determine the range for a particular SCEV, but evaluates ranges for
   /// operands iteratively first.
-  const ConstantRange &getRangeRefIter(const SCEV *S, RangeSignHint Hint);
+  const ConstantRange &getRangeRefIter(SCEVUse S, RangeSignHint Hint);
 
   /// Determines the range for the affine SCEVAddRecExpr {\p Start,+,\p Step}.
   /// Helper for \c getRange.
-  ConstantRange getRangeForAffineAR(const SCEV *Start, const SCEV *Step,
+  ConstantRange getRangeForAffineAR(SCEVUse Start, SCEVUse Step,
                                     const APInt &MaxBECount);
 
   /// Determines the range for the affine non-self-wrapping SCEVAddRecExpr {\p
   /// Start,+,\p Step}<nw>.
   ConstantRange getRangeForAffineNoSelfWrappingAR(const SCEVAddRecExpr *AddRec,
-                                                  const SCEV *MaxBECount,
+                                                  SCEVUse MaxBECount,
                                                   unsigned BitWidth,
                                                   RangeSignHint SignHint);
 
   /// Try to compute a range for the affine SCEVAddRecExpr {\p Start,+,\p
   /// Step} by "factoring out" a ternary expression from the add recurrence.
   /// Helper called by \c getRange.
-  ConstantRange getRangeViaFactoring(const SCEV *Start, const SCEV *Step,
+  ConstantRange getRangeViaFactoring(SCEVUse Start, SCEVUse Step,
                                      const APInt &MaxBECount);
 
   /// If the unknown expression U corresponds to a simple recurrence, return
@@ -1689,55 +1783,54 @@ class ScalarEvolution {
 
   /// We know that there is no SCEV for the specified value.  Analyze the
   /// expression recursively.
-  const SCEV *createSCEV(Value *V);
+  SCEVUse createSCEV(Value *V);
 
   /// We know that there is no SCEV for the specified value. Create a new SCEV
   /// for \p V iteratively.
-  const SCEV *createSCEVIter(Value *V);
+  SCEVUse createSCEVIter(Value *V);
   /// Collect operands of \p V for which SCEV expressions should be constructed
   /// first. Returns a SCEV directly if it can be constructed trivially for \p
   /// V.
-  const SCEV *getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops);
+  SCEVUse getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops);
 
   /// Provide the special handling we need to analyze PHI SCEVs.
-  const SCEV *createNodeForPHI(PHINode *PN);
+  SCEVUse createNodeForPHI(PHINode *PN);
 
   /// Helper function called from createNodeForPHI.
-  const SCEV *createAddRecFromPHI(PHINode *PN);
+  SCEVUse createAddRecFromPHI(PHINode *PN);
 
   /// A helper function for createAddRecFromPHI to handle simple cases.
-  const SCEV *createSimpleAffineAddRec(PHINode *PN, Value *BEValueV,
-                                            Value *StartValueV);
+  SCEVUse createSimpleAffineAddRec(PHINode *PN, Value *BEValueV,
+                                   Value *StartValueV);
 
   /// Helper function called from createNodeForPHI.
-  const SCEV *createNodeFromSelectLikePHI(PHINode *PN);
+  SCEVUse createNodeFromSelectLikePHI(PHINode *PN);
 
   /// Provide special handling for a select-like instruction (currently this
   /// is either a select instruction or a phi node).  \p Ty is the type of the
   /// instruction being processed, that is assumed equivalent to
   /// "Cond ? TrueVal : FalseVal".
-  std::optional<const SCEV *>
+  std::optional<SCEVUse>
   createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty, ICmpInst *Cond,
                                                Value *TrueVal, Value *FalseVal);
 
   /// See if we can model this select-like instruction via umin_seq expression.
-  const SCEV *createNodeForSelectOrPHIViaUMinSeq(Value *I, Value *Cond,
-                                                 Value *TrueVal,
-                                                 Value *FalseVal);
+  SCEVUse createNodeForSelectOrPHIViaUMinSeq(Value *I, Value *Cond,
+                                             Value *TrueVal, Value *FalseVal);
 
   /// Given a value \p V, which is a select-like instruction (currently this is
   /// either a select instruction or a phi node), which is assumed equivalent to
   ///   Cond ? TrueVal : FalseVal
   /// see if we can model it as a SCEV expression.
-  const SCEV *createNodeForSelectOrPHI(Value *V, Value *Cond, Value *TrueVal,
-                                       Value *FalseVal);
+  SCEVUse createNodeForSelectOrPHI(Value *V, Value *Cond, Value *TrueVal,
+                                   Value *FalseVal);
 
   /// Provide the special handling we need to analyze GEP SCEVs.
-  const SCEV *createNodeForGEP(GEPOperator *GEP);
+  SCEVUse createNodeForGEP(GEPOperator *GEP);
 
   /// Implementation code for getSCEVAtScope; called at most once for each
   /// SCEV+Loop pair.
-  const SCEV *computeSCEVAtScope(const SCEV *S, const Loop *L);
+  SCEVUse computeSCEVAtScope(SCEVUse S, const Loop *L);
 
   /// Return the BackedgeTakenInfo for the given loop, lazily computing new
   /// values if the loop hasn't been analyzed yet. The returned result is
@@ -1764,7 +1857,7 @@ class ScalarEvolution {
   /// Return a symbolic upper bound for the backedge taken count of the loop.
   /// This is more general than getConstantMaxBackedgeTakenCount as it returns
   /// an arbitrary expression as opposed to only constants.
-  const SCEV *computeSymbolicMaxBackedgeTakenCount(const Loop *L);
+  SCEVUse computeSymbolicMaxBackedgeTakenCount(const Loop *L);
 
   // Helper functions for computeExitLimitFromCond to avoid exponential time
   // complexity.
@@ -1824,8 +1917,7 @@ class ScalarEvolution {
   /// return more precise results in some cases and is preferred when caller
   /// has a materialized ICmp.
   ExitLimit computeExitLimitFromICmp(const Loop *L, ICmpInst::Predicate Pred,
-                                     const SCEV *LHS, const SCEV *RHS,
-                                     bool IsSubExpr,
+                                     SCEVUse LHS, SCEVUse RHS, bool IsSubExpr,
                                      bool AllowPredicates = false);
 
   /// Compute the number of times the backedge of the specified loop will
@@ -1851,20 +1943,20 @@ class ScalarEvolution {
   /// of the loop until we get the exit condition gets a value of ExitWhen
   /// (true or false).  If we cannot evaluate the exit count of the loop,
   /// return CouldNotCompute.
-  const SCEV *computeExitCountExhaustively(const Loop *L, Value *Cond,
-                                           bool ExitWhen);
+  SCEVUse computeExitCountExhaustively(const Loop *L, Value *Cond,
+                                       bool ExitWhen);
 
   /// Return the number of times an exit condition comparing the specified
   /// value to zero will execute.  If not computable, return CouldNotCompute.
   /// If AllowPredicates is set, this call will try to use a minimal set of
   /// SCEV predicates in order to return an exact answer.
-  ExitLimit howFarToZero(const SCEV *V, const Loop *L, bool IsSubExpr,
+  ExitLimit howFarToZero(SCEVUse V, const Loop *L, bool IsSubExpr,
                          bool AllowPredicates = false);
 
   /// Return the number of times an exit condition checking the specified
   /// value for nonzero will execute.  If not computable, return
   /// CouldNotCompute.
-  ExitLimit howFarToNonZero(const SCEV *V, const Loop *L);
+  ExitLimit howFarToNonZero(SCEVUse V, const Loop *L);
 
   /// Return the number of times an exit condition containing the specified
   /// less-than comparison will execute.  If not computable, return
@@ -1878,11 +1970,11 @@ class ScalarEvolution {
   ///
   /// If \p AllowPredicates is set, this call will try to use a minimal set of
   /// SCEV predicates in order to return an exact answer.
-  ExitLimit howManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L,
+  ExitLimit howManyLessThans(SCEVUse LHS, SCEVUse RHS, const Loop *L,
                              bool isSigned, bool ControlsOnlyExit,
                              bool AllowPredicates = false);
 
-  ExitLimit howManyGreaterThans(const SCEV *LHS, const SCEV *RHS, const Loop *L,
+  ExitLimit howManyGreaterThans(SCEVUse LHS, SCEVUse RHS, const Loop *L,
                                 bool isSigned, bool IsSubExpr,
                                 bool AllowPredicates = false);
 
@@ -1896,7 +1988,7 @@ class ScalarEvolution {
   /// whenever the given FoundCondValue value evaluates to true in given
   /// Context. If Context is nullptr, then the found predicate is true
   /// everywhere. LHS and FoundLHS may have different type width.
-  bool isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
+  bool isImpliedCond(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
                      const Value *FoundCondValue, bool Inverse,
                      const Instruction *Context = nullptr);
 
@@ -1904,65 +1996,60 @@ class ScalarEvolution {
   /// whenever the given FoundCondValue value evaluates to true in given
   /// Context. If Context is nullptr, then the found predicate is true
   /// everywhere. LHS and FoundLHS must have same type width.
-  bool isImpliedCondBalancedTypes(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                  const SCEV *RHS,
-                                  ICmpInst::Predicate FoundPred,
-                                  const SCEV *FoundLHS, const SCEV *FoundRHS,
+  bool isImpliedCondBalancedTypes(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                  SCEVUse RHS, ICmpInst::Predicate FoundPred,
+                                  SCEVUse FoundLHS, SCEVUse FoundRHS,
                                   const Instruction *CtxI);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by FoundPred, FoundLHS, FoundRHS is
   /// true in given Context. If Context is nullptr, then the found predicate is
   /// true everywhere.
-  bool isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
-                     ICmpInst::Predicate FoundPred, const SCEV *FoundLHS,
-                     const SCEV *FoundRHS,
-                     const Instruction *Context = nullptr);
+  bool isImpliedCond(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
+                     ICmpInst::Predicate FoundPred, SCEVUse FoundLHS,
+                     SCEVUse FoundRHS, const Instruction *Context = nullptr);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
   /// true in given Context. If Context is nullptr, then the found predicate is
   /// true everywhere.
-  bool isImpliedCondOperands(ICmpInst::Predicate Pred, const SCEV *LHS,
-                             const SCEV *RHS, const SCEV *FoundLHS,
-                             const SCEV *FoundRHS,
+  bool isImpliedCondOperands(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
+                             SCEVUse FoundLHS, SCEVUse FoundRHS,
                              const Instruction *Context = nullptr);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
   /// true. Here LHS is an operation that includes FoundLHS as one of its
   /// arguments.
-  bool isImpliedViaOperations(ICmpInst::Predicate Pred,
-                              const SCEV *LHS, const SCEV *RHS,
-                              const SCEV *FoundLHS, const SCEV *FoundRHS,
+  bool isImpliedViaOperations(ICmpInst::Predicate Pred, SCEVUse LHS,
+                              SCEVUse RHS, SCEVUse FoundLHS, SCEVUse FoundRHS,
                               unsigned Depth = 0);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true.
   /// Use only simple non-recursive types of checks, such as range analysis etc.
-  bool isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred,
-                                       const SCEV *LHS, const SCEV *RHS);
+  bool isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                       SCEVUse RHS);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
   /// true.
-  bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                   const SCEV *RHS, const SCEV *FoundLHS,
-                                   const SCEV *FoundRHS);
+  bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                   SCEVUse RHS, SCEVUse FoundLHS,
+                                   SCEVUse FoundRHS);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
   /// true.  Utility function used by isImpliedCondOperands.  Tries to get
   /// cases like "X `sgt` 0 => X - 1 `sgt` -1".
-  bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                      const SCEV *RHS,
+  bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                      SCEVUse RHS,
                                       ICmpInst::Predicate FoundPred,
-                                      const SCEV *FoundLHS,
-                                      const SCEV *FoundRHS);
+                                      SCEVUse FoundLHS, SCEVUse FoundRHS);
 
   /// Return true if the condition denoted by \p LHS \p Pred \p RHS is implied
   /// by a call to @llvm.experimental.guard in \p BB.
   bool isImpliedViaGuard(const BasicBlock *BB, ICmpInst::Predicate Pred,
-                         const SCEV *LHS, const SCEV *RHS);
+                         SCEVUse LHS, SCEVUse RHS);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
@@ -1970,10 +2057,9 @@ class ScalarEvolution {
   ///
   /// This routine tries to rule out certain kinds of integer overflow, and
   /// then tries to reason about arithmetic properties of the predicates.
-  bool isImpliedCondOperandsViaNoOverflow(ICmpInst::Predicate Pred,
-                                          const SCEV *LHS, const SCEV *RHS,
-                                          const SCEV *FoundLHS,
-                                          const SCEV *FoundRHS);
+  bool isImpliedCondOperandsViaNoOverflow(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                          SCEVUse RHS, SCEVUse FoundLHS,
+                                          SCEVUse FoundRHS);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
@@ -1982,9 +2068,8 @@ class ScalarEvolution {
   /// This routine tries to weaken the known condition basing on fact that
   /// FoundLHS is an AddRec.
   bool isImpliedCondOperandsViaAddRecStart(ICmpInst::Predicate Pred,
-                                           const SCEV *LHS, const SCEV *RHS,
-                                           const SCEV *FoundLHS,
-                                           const SCEV *FoundRHS,
+                                           SCEVUse LHS, SCEVUse RHS,
+                                           SCEVUse FoundLHS, SCEVUse FoundRHS,
                                            const Instruction *CtxI);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
@@ -1994,19 +2079,17 @@ class ScalarEvolution {
   /// This routine tries to figure out predicate for Phis which are SCEVUnknown
   /// if it is true for every possible incoming value from their respective
   /// basic blocks.
-  bool isImpliedViaMerge(ICmpInst::Predicate Pred,
-                         const SCEV *LHS, const SCEV *RHS,
-                         const SCEV *FoundLHS, const SCEV *FoundRHS,
-                         unsigned Depth);
+  bool isImpliedViaMerge(ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
+                         SCEVUse FoundLHS, SCEVUse FoundRHS, unsigned Depth);
 
   /// Test whether the condition described by Pred, LHS, and RHS is true
   /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
   /// true.
   ///
   /// This routine tries to reason about shifts.
-  bool isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                     const SCEV *RHS, const SCEV *FoundLHS,
-                                     const SCEV *FoundRHS);
+  bool isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                     SCEVUse RHS, SCEVUse FoundLHS,
+                                     SCEVUse FoundRHS);
 
   /// If we know that the specified Phi is in the header of its containing
   /// loop, we know the loop executes a constant number of times, and the PHI
@@ -2016,50 +2099,50 @@ class ScalarEvolution {
 
   /// Test if the given expression is known to satisfy the condition described
   /// by Pred and the known constant ranges of LHS and RHS.
-  bool isKnownPredicateViaConstantRanges(ICmpInst::Predicate Pred,
-                                         const SCEV *LHS, const SCEV *RHS);
+  bool isKnownPredicateViaConstantRanges(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                         SCEVUse RHS);
 
   /// Try to prove the condition described by "LHS Pred RHS" by ruling out
   /// integer overflow.
   ///
   /// For instance, this will return true for "A s< (A + C)<nsw>" if C is
   /// positive.
-  bool isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                     const SCEV *RHS);
+  bool isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                     SCEVUse RHS);
 
   /// Try to split Pred LHS RHS into logical conjunctions (and's) and try to
   /// prove them individually.
-  bool isKnownPredicateViaSplitting(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                    const SCEV *RHS);
+  bool isKnownPredicateViaSplitting(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                    SCEVUse RHS);
 
   /// Try to match the Expr as "(L + R)<Flags>".
-  bool splitBinaryAdd(const SCEV *Expr, const SCEV *&L, const SCEV *&R,
+  bool splitBinaryAdd(SCEVUse Expr, SCEVUse &L, SCEVUse &R,
                       SCEV::NoWrapFlags &Flags);
 
   /// Forget predicated/non-predicated backedge taken counts for the given loop.
   void forgetBackedgeTakenCounts(const Loop *L, bool Predicated);
 
   /// Drop memoized information for all \p SCEVs.
-  void forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs);
+  void forgetMemoizedResults(ArrayRef<SCEVUse> SCEVs);
 
   /// Helper for forgetMemoizedResults.
-  void forgetMemoizedResultsImpl(const SCEV *S);
+  void forgetMemoizedResultsImpl(SCEVUse S);
 
   /// Iterate over instructions in \p Worklist and their users. Erase entries
   /// from ValueExprMap and collect SCEV expressions in \p ToForget
   void visitAndClearUsers(SmallVectorImpl<Instruction *> &Worklist,
                           SmallPtrSetImpl<Instruction *> &Visited,
-                          SmallVectorImpl<const SCEV *> &ToForget);
+                          SmallVectorImpl<SCEVUse> &ToForget);
 
   /// Erase Value from ValueExprMap and ExprValueMap.
   void eraseValueFromMap(Value *V);
 
   /// Insert V to S mapping into ValueExprMap and ExprValueMap.
-  void insertValueToMap(Value *V, const SCEV *S);
+  void insertValueToMap(Value *V, SCEVUse S);
 
   /// Return false iff given SCEV contains a SCEVUnknown with NULL value-
   /// pointer.
-  bool checkValidity(const SCEV *S) const;
+  bool checkValidity(SCEVUse S) const;
 
   /// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be
   /// equal to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}.  This is
@@ -2067,8 +2150,7 @@ class ScalarEvolution {
   /// {`Start`,+,`Step`} if `ExtendOpTy` is `SCEVSignExtendExpr`
   /// (resp. `SCEVZeroExtendExpr`).
   template <typename ExtendOpTy>
-  bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
-                                 const Loop *L);
+  bool proveNoWrapByVaryingStart(SCEVUse Start, SCEVUse Step, const Loop *L);
 
   /// Try to prove NSW or NUW on \p AR relying on ConstantRange manipulation.
   SCEV::NoWrapFlags proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR);
@@ -2094,17 +2176,17 @@ class ScalarEvolution {
   /// 'S'. Specifically, return the first instruction in said bounding scope.
   /// Return nullptr if the scope is trivial (function entry).
   /// (See scope definition rules associated with flag discussion above)
-  const Instruction *getNonTrivialDefiningScopeBound(const SCEV *S);
+  const Instruction *getNonTrivialDefiningScopeBound(SCEVUse S);
 
   /// Return a scope which provides an upper bound on the defining scope for
   /// a SCEV with the operands in Ops.  The outparam Precise is set if the
   /// bound found is a precise bound (i.e. must be the defining scope.)
-  const Instruction *getDefiningScopeBound(ArrayRef<const SCEV *> Ops,
+  const Instruction *getDefiningScopeBound(ArrayRef<SCEVUse> Ops,
                                            bool &Precise);
 
   /// Wrapper around the above for cases which don't care if the bound
   /// is precise.
-  const Instruction *getDefiningScopeBound(ArrayRef<const SCEV *> Ops);
+  const Instruction *getDefiningScopeBound(ArrayRef<SCEVUse> Ops);
 
   /// Given two instructions in the same function, return true if we can
   /// prove B must execute given A executes.
@@ -2145,7 +2227,7 @@ class ScalarEvolution {
   /// If the analysis is not successful, a mapping from the \p SymbolicPHI to
   /// itself (with no predicates) is recorded, and a nullptr with an empty
   /// predicates vector is returned as a pair.
-  std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
+  std::optional<std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>>>
   createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI);
 
   /// Compute the maximum backedge count based on the range of values
@@ -2157,47 +2239,44 @@ class ScalarEvolution {
   /// * the induction variable is assumed not to overflow (i.e. either it
   ///   actually doesn't, or we'd have to immediately execute UB)
   /// We *don't* assert these preconditions so please be careful.
-  const SCEV *computeMaxBECountForLT(const SCEV *Start, const SCEV *Stride,
-                                     const SCEV *End, unsigned BitWidth,
-                                     bool IsSigned);
+  SCEVUse computeMaxBECountForLT(SCEVUse Start, SCEVUse Stride, SCEVUse End,
+                                 unsigned BitWidth, bool IsSigned);
 
   /// Verify if an linear IV with positive stride can overflow when in a
   /// less-than comparison, knowing the invariant term of the comparison,
   /// the stride.
-  bool canIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride, bool IsSigned);
+  bool canIVOverflowOnLT(SCEVUse RHS, SCEVUse Stride, bool IsSigned);
 
   /// Verify if an linear IV with negative stride can overflow when in a
   /// greater-than comparison, knowing the invariant term of the comparison,
   /// the stride.
-  bool canIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, bool IsSigned);
+  bool canIVOverflowOnGT(SCEVUse RHS, SCEVUse Stride, bool IsSigned);
 
   /// Get add expr already created or create a new one.
-  const SCEV *getOrCreateAddExpr(ArrayRef<const SCEV *> Ops,
-                                 SCEV::NoWrapFlags Flags);
+  SCEVUse getOrCreateAddExpr(ArrayRef<SCEVUse> Ops, SCEV::NoWrapFlags Flags);
 
   /// Get mul expr already created or create a new one.
-  const SCEV *getOrCreateMulExpr(ArrayRef<const SCEV *> Ops,
-                                 SCEV::NoWrapFlags Flags);
+  SCEVUse getOrCreateMulExpr(ArrayRef<SCEVUse> Ops, SCEV::NoWrapFlags Flags);
 
   // Get addrec expr already created or create a new one.
-  const SCEV *getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops,
-                                    const Loop *L, SCEV::NoWrapFlags Flags);
+  SCEVUse getOrCreateAddRecExpr(ArrayRef<SCEVUse> Ops, const Loop *L,
+                                SCEV::NoWrapFlags Flags);
 
   /// Return x if \p Val is f(x) where f is a 1-1 function.
-  const SCEV *stripInjectiveFunctions(const SCEV *Val) const;
+  SCEVUse stripInjectiveFunctions(SCEVUse Val) const;
 
   /// Find all of the loops transitively used in \p S, and fill \p LoopsUsed.
   /// A loop is considered "used" by an expression if it contains
   /// an add rec on said loop.
-  void getUsedLoops(const SCEV *S, SmallPtrSetImpl<const Loop *> &LoopsUsed);
+  void getUsedLoops(SCEVUse S, SmallPtrSetImpl<const Loop *> &LoopsUsed);
 
   /// Try to match the pattern generated by getURemExpr(A, B). If successful,
   /// Assign A and B to LHS and RHS, respectively.
-  bool matchURem(const SCEV *Expr, const SCEV *&LHS, const SCEV *&RHS);
+  bool matchURem(SCEVUse Expr, SCEVUse &LHS, SCEVUse &RHS);
 
   /// Look for a SCEV expression with type `SCEVType` and operands `Ops` in
   /// `UniqueSCEVs`.  Return if found, else nullptr.
-  SCEV *findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef<const SCEV *> Ops);
+  SCEV *findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef<SCEVUse> Ops);
 
   /// Get reachable blocks in this function, making limited use of SCEV
   /// reasoning about conditions.
@@ -2206,8 +2285,7 @@ class ScalarEvolution {
 
   /// Return the given SCEV expression with a new set of operands.
   /// This preserves the origial nowrap flags.
-  const SCEV *getWithOperands(const SCEV *S,
-                              SmallVectorImpl<const SCEV *> &NewOps);
+  SCEVUse getWithOperands(SCEVUse S, SmallVectorImpl<SCEVUse> &NewOps);
 
   FoldingSet<SCEV> UniqueSCEVs;
   FoldingSet<SCEVPredicate> UniquePreds;
@@ -2219,7 +2297,7 @@ class ScalarEvolution {
   /// Cache tentative mappings from UnknownSCEVs in a Loop, to a SCEV expression
   /// they can be rewritten into under certain predicates.
   DenseMap<std::pair<const SCEVUnknown *, const Loop *>,
-           std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
+           std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>>>
       PredicatedSCEVRewrites;
 
   /// Set of AddRecs for which proving NUW via an induction has already been
@@ -2311,10 +2389,10 @@ class PredicatedScalarEvolution {
   /// predicate.  The order of transformations applied on the expression of V
   /// returned by ScalarEvolution is guaranteed to be preserved, even when
   /// adding new predicates.
-  const SCEV *getSCEV(Value *V);
+  SCEVUse getSCEV(Value *V);
 
   /// Get the (predicated) backedge count for the analyzed loop.
-  const SCEV *getBackedgeTakenCount();
+  SCEVUse getBackedgeTakenCount();
 
   /// Adds a new predicate.
   void addPredicate(const SCEVPredicate &Pred);
@@ -2354,7 +2432,7 @@ class PredicatedScalarEvolution {
 
   /// Holds a SCEV and the version number of the SCEV predicate used to
   /// perform the rewrite of the expression.
-  using RewriteEntry = std::pair<unsigned, const SCEV *>;
+  using RewriteEntry = std::pair<unsigned, SCEVUse>;
 
   /// Maps a SCEV to the rewrite result of that SCEV at a certain version
   /// number. If this number doesn't match the current Generation, we will
@@ -2383,7 +2461,7 @@ class PredicatedScalarEvolution {
   unsigned Generation = 0;
 
   /// The backedge taken count.
-  const SCEV *BackedgeCount = nullptr;
+  SCEVUse BackedgeCount = nullptr;
 };
 
 template <> struct DenseMapInfo<ScalarEvolution::FoldID> {
diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
index fd884f2a2f55b..b72d9fbe64fab 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -90,11 +90,12 @@ class SCEVVScale : public SCEV {
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scVScale; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
-inline unsigned short computeExpressionSize(ArrayRef<const SCEV *> Args) {
+inline unsigned short computeExpressionSize(ArrayRef<SCEVUse> Args) {
   APInt Size(16, 1);
-  for (const auto *Arg : Args)
+  for (const auto Arg : Args)
     Size = Size.uadd_sat(APInt(16, Arg->getExpressionSize()));
   return (unsigned short)Size.getZExtValue();
 }
@@ -102,19 +103,19 @@ inline unsigned short computeExpressionSize(ArrayRef<const SCEV *> Args) {
 /// This is the base class for unary cast operator classes.
 class SCEVCastExpr : public SCEV {
 protected:
-  const SCEV *Op;
+  SCEVUse Op;
   Type *Ty;
 
-  SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, const SCEV *op,
+  SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, SCEVUse op,
                Type *ty);
 
 public:
-  const SCEV *getOperand() const { return Op; }
-  const SCEV *getOperand(unsigned i) const {
+  SCEVUse getOperand() const { return Op; }
+  SCEVUse getOperand(unsigned i) const {
     assert(i == 0 && "Operand index out of range!");
     return Op;
   }
-  ArrayRef<const SCEV *> operands() const { return Op; }
+  ArrayRef<SCEVUse> operands() const { return Op; }
   size_t getNumOperands() const { return 1; }
   Type *getType() const { return Ty; }
 
@@ -123,6 +124,7 @@ class SCEVCastExpr : public SCEV {
     return S->getSCEVType() == scPtrToInt || S->getSCEVType() == scTruncate ||
            S->getSCEVType() == scZeroExtend || S->getSCEVType() == scSignExtend;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents a cast from a pointer to a pointer-sized integer
@@ -130,18 +132,19 @@ class SCEVCastExpr : public SCEV {
 class SCEVPtrToIntExpr : public SCEVCastExpr {
   friend class ScalarEvolution;
 
-  SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op, Type *ITy);
+  SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, SCEVUse Op, Type *ITy);
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scPtrToInt; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This is the base class for unary integral cast operator classes.
 class SCEVIntegralCastExpr : public SCEVCastExpr {
 protected:
   SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
-                       const SCEV *op, Type *ty);
+                       SCEVUse op, Type *ty);
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -149,6 +152,7 @@ class SCEVIntegralCastExpr : public SCEVCastExpr {
     return S->getSCEVType() == scTruncate || S->getSCEVType() == scZeroExtend ||
            S->getSCEVType() == scSignExtend;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents a truncation of an integer value to a
@@ -156,11 +160,12 @@ class SCEVIntegralCastExpr : public SCEVCastExpr {
 class SCEVTruncateExpr : public SCEVIntegralCastExpr {
   friend class ScalarEvolution;
 
-  SCEVTruncateExpr(const FoldingSetNodeIDRef ID, const SCEV *op, Type *ty);
+  SCEVTruncateExpr(const FoldingSetNodeIDRef ID, SCEVUse op, Type *ty);
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scTruncate; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents a zero extension of a small integer value
@@ -168,13 +173,14 @@ class SCEVTruncateExpr : public SCEVIntegralCastExpr {
 class SCEVZeroExtendExpr : public SCEVIntegralCastExpr {
   friend class ScalarEvolution;
 
-  SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, const SCEV *op, Type *ty);
+  SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, SCEVUse op, Type *ty);
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) {
     return S->getSCEVType() == scZeroExtend;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents a sign extension of a small integer value
@@ -182,13 +188,14 @@ class SCEVZeroExtendExpr : public SCEVIntegralCastExpr {
 class SCEVSignExtendExpr : public SCEVIntegralCastExpr {
   friend class ScalarEvolution;
 
-  SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, const SCEV *op, Type *ty);
+  SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, SCEVUse op, Type *ty);
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) {
     return S->getSCEVType() == scSignExtend;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This node is a base class providing common functionality for
@@ -199,25 +206,23 @@ class SCEVNAryExpr : public SCEV {
   // arrays with its SCEVAllocator, so this class just needs a simple
   // pointer rather than a more elaborate vector-like data structure.
   // This also avoids the need for a non-trivial destructor.
-  const SCEV *const *Operands;
+  SCEVUse const *Operands;
   size_t NumOperands;
 
-  SCEVNAryExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
-               const SCEV *const *O, size_t N)
+  SCEVNAryExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T, SCEVUse const *O,
+               size_t N)
       : SCEV(ID, T, computeExpressionSize(ArrayRef(O, N))), Operands(O),
         NumOperands(N) {}
 
 public:
   size_t getNumOperands() const { return NumOperands; }
 
-  const SCEV *getOperand(unsigned i) const {
+  SCEVUse getOperand(unsigned i) const {
     assert(i < NumOperands && "Operand index out of range!");
     return Operands[i];
   }
 
-  ArrayRef<const SCEV *> operands() const {
-    return ArrayRef(Operands, NumOperands);
-  }
+  ArrayRef<SCEVUse> operands() const { return ArrayRef(Operands, NumOperands); }
 
   NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const {
     return (NoWrapFlags)(SubclassData & Mask);
@@ -241,13 +246,14 @@ class SCEVNAryExpr : public SCEV {
            S->getSCEVType() == scSequentialUMinExpr ||
            S->getSCEVType() == scAddRecExpr;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This node is the base class for n'ary commutative operators.
 class SCEVCommutativeExpr : public SCEVNAryExpr {
 protected:
   SCEVCommutativeExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
-                      const SCEV *const *O, size_t N)
+                      SCEVUse const *O, size_t N)
       : SCEVNAryExpr(ID, T, O, N) {}
 
 public:
@@ -257,6 +263,7 @@ class SCEVCommutativeExpr : public SCEVNAryExpr {
            S->getSCEVType() == scSMaxExpr || S->getSCEVType() == scUMaxExpr ||
            S->getSCEVType() == scSMinExpr || S->getSCEVType() == scUMinExpr;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 
   /// Set flags for a non-recurrence without clearing previously set flags.
   void setNoWrapFlags(NoWrapFlags Flags) { SubclassData |= Flags; }
@@ -268,11 +275,10 @@ class SCEVAddExpr : public SCEVCommutativeExpr {
 
   Type *Ty;
 
-  SCEVAddExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
+  SCEVAddExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O, size_t N)
       : SCEVCommutativeExpr(ID, scAddExpr, O, N) {
-    auto *FirstPointerTypedOp = find_if(operands(), [](const SCEV *Op) {
-      return Op->getType()->isPointerTy();
-    });
+    auto *FirstPointerTypedOp = find_if(
+        operands(), [](SCEVUse Op) { return Op->getType()->isPointerTy(); });
     if (FirstPointerTypedOp != operands().end())
       Ty = (*FirstPointerTypedOp)->getType();
     else
@@ -284,13 +290,14 @@ class SCEVAddExpr : public SCEVCommutativeExpr {
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scAddExpr; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This node represents multiplication of some number of SCEVs.
 class SCEVMulExpr : public SCEVCommutativeExpr {
   friend class ScalarEvolution;
 
-  SCEVMulExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
+  SCEVMulExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O, size_t N)
       : SCEVCommutativeExpr(ID, scMulExpr, O, N) {}
 
 public:
@@ -298,30 +305,31 @@ class SCEVMulExpr : public SCEVCommutativeExpr {
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scMulExpr; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents a binary unsigned division operation.
 class SCEVUDivExpr : public SCEV {
   friend class ScalarEvolution;
 
-  std::array<const SCEV *, 2> Operands;
+  std::array<SCEVUse, 2> Operands;
 
-  SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs)
+  SCEVUDivExpr(const FoldingSetNodeIDRef ID, SCEVUse lhs, SCEVUse rhs)
       : SCEV(ID, scUDivExpr, computeExpressionSize({lhs, rhs})) {
     Operands[0] = lhs;
     Operands[1] = rhs;
   }
 
 public:
-  const SCEV *getLHS() const { return Operands[0]; }
-  const SCEV *getRHS() const { return Operands[1]; }
+  SCEVUse getLHS() const { return Operands[0]; }
+  SCEVUse getRHS() const { return Operands[1]; }
   size_t getNumOperands() const { return 2; }
-  const SCEV *getOperand(unsigned i) const {
+  SCEVUse getOperand(unsigned i) const {
     assert((i == 0 || i == 1) && "Operand index out of range!");
     return i == 0 ? getLHS() : getRHS();
   }
 
-  ArrayRef<const SCEV *> operands() const { return Operands; }
+  ArrayRef<SCEVUse> operands() const { return Operands; }
 
   Type *getType() const {
     // In most cases the types of LHS and RHS will be the same, but in some
@@ -334,6 +342,7 @@ class SCEVUDivExpr : public SCEV {
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scUDivExpr; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This node represents a polynomial recurrence on the trip count
@@ -349,25 +358,24 @@ class SCEVAddRecExpr : public SCEVNAryExpr {
 
   const Loop *L;
 
-  SCEVAddRecExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N,
+  SCEVAddRecExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O, size_t N,
                  const Loop *l)
       : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {}
 
 public:
   Type *getType() const { return getStart()->getType(); }
-  const SCEV *getStart() const { return Operands[0]; }
+  SCEVUse getStart() const { return Operands[0]; }
   const Loop *getLoop() const { return L; }
 
   /// Constructs and returns the recurrence indicating how much this
   /// expression steps by.  If this is a polynomial of degree N, it
   /// returns a chrec of degree N-1.  We cannot determine whether
   /// the step recurrence has self-wraparound.
-  const SCEV *getStepRecurrence(ScalarEvolution &SE) const {
+  SCEVUse getStepRecurrence(ScalarEvolution &SE) const {
     if (isAffine())
       return getOperand(1);
-    return SE.getAddRecExpr(
-        SmallVector<const SCEV *, 3>(operands().drop_front()), getLoop(),
-        FlagAnyWrap);
+    return SE.getAddRecExpr(SmallVector<SCEVUse, 3>(operands().drop_front()),
+                            getLoop(), FlagAnyWrap);
   }
 
   /// Return true if this represents an expression A + B*x where A
@@ -394,12 +402,12 @@ class SCEVAddRecExpr : public SCEVNAryExpr {
 
   /// Return the value of this chain of recurrences at the specified
   /// iteration number.
-  const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const;
+  SCEVUse evaluateAtIteration(SCEVUse It, ScalarEvolution &SE) const;
 
   /// Return the value of this chain of recurrences at the specified iteration
   /// number. Takes an explicit list of operands to represent an AddRec.
-  static const SCEV *evaluateAtIteration(ArrayRef<const SCEV *> Operands,
-                                         const SCEV *It, ScalarEvolution &SE);
+  static SCEVUse evaluateAtIteration(ArrayRef<SCEVUse> Operands, SCEVUse It,
+                                     ScalarEvolution &SE);
 
   /// Return the number of iterations of this loop that produce
   /// values in the specified constant range.  Another way of
@@ -407,8 +415,8 @@ class SCEVAddRecExpr : public SCEVNAryExpr {
   /// where the value is not in the condition, thus computing the
   /// exit count.  If the iteration count can't be computed, an
   /// instance of SCEVCouldNotCompute is returned.
-  const SCEV *getNumIterationsInRange(const ConstantRange &Range,
-                                      ScalarEvolution &SE) const;
+  SCEVUse getNumIterationsInRange(const ConstantRange &Range,
+                                  ScalarEvolution &SE) const;
 
   /// Return an expression representing the value of this expression
   /// one iteration of the loop ahead.
@@ -418,6 +426,7 @@ class SCEVAddRecExpr : public SCEVNAryExpr {
   static bool classof(const SCEV *S) {
     return S->getSCEVType() == scAddRecExpr;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This node is the base class min/max selections.
@@ -432,7 +441,7 @@ class SCEVMinMaxExpr : public SCEVCommutativeExpr {
 protected:
   /// Note: Constructing subclasses via this constructor is allowed
   SCEVMinMaxExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
-                 const SCEV *const *O, size_t N)
+                 SCEVUse const *O, size_t N)
       : SCEVCommutativeExpr(ID, T, O, N) {
     assert(isMinMaxType(T));
     // Min and max never overflow
@@ -443,6 +452,7 @@ class SCEVMinMaxExpr : public SCEVCommutativeExpr {
   Type *getType() const { return getOperand(0)->getType(); }
 
   static bool classof(const SCEV *S) { return isMinMaxType(S->getSCEVType()); }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 
   static enum SCEVTypes negate(enum SCEVTypes T) {
     switch (T) {
@@ -464,48 +474,52 @@ class SCEVMinMaxExpr : public SCEVCommutativeExpr {
 class SCEVSMaxExpr : public SCEVMinMaxExpr {
   friend class ScalarEvolution;
 
-  SCEVSMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
+  SCEVSMaxExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O, size_t N)
       : SCEVMinMaxExpr(ID, scSMaxExpr, O, N) {}
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scSMaxExpr; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents an unsigned maximum selection.
 class SCEVUMaxExpr : public SCEVMinMaxExpr {
   friend class ScalarEvolution;
 
-  SCEVUMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
+  SCEVUMaxExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O, size_t N)
       : SCEVMinMaxExpr(ID, scUMaxExpr, O, N) {}
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scUMaxExpr; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents a signed minimum selection.
 class SCEVSMinExpr : public SCEVMinMaxExpr {
   friend class ScalarEvolution;
 
-  SCEVSMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
+  SCEVSMinExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O, size_t N)
       : SCEVMinMaxExpr(ID, scSMinExpr, O, N) {}
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scSMinExpr; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents an unsigned minimum selection.
 class SCEVUMinExpr : public SCEVMinMaxExpr {
   friend class ScalarEvolution;
 
-  SCEVUMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
+  SCEVUMinExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O, size_t N)
       : SCEVMinMaxExpr(ID, scUMinExpr, O, N) {}
 
 public:
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scUMinExpr; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This node is the base class for sequential/in-order min/max selections.
@@ -526,7 +540,7 @@ class SCEVSequentialMinMaxExpr : public SCEVNAryExpr {
 protected:
   /// Note: Constructing subclasses via this constructor is allowed
   SCEVSequentialMinMaxExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
-                           const SCEV *const *O, size_t N)
+                           SCEVUse const *O, size_t N)
       : SCEVNAryExpr(ID, T, O, N) {
     assert(isSequentialMinMaxType(T));
     // Min and max never overflow
@@ -553,13 +567,14 @@ class SCEVSequentialMinMaxExpr : public SCEVNAryExpr {
   static bool classof(const SCEV *S) {
     return isSequentialMinMaxType(S->getSCEVType());
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class represents a sequential/in-order unsigned minimum selection.
 class SCEVSequentialUMinExpr : public SCEVSequentialMinMaxExpr {
   friend class ScalarEvolution;
 
-  SCEVSequentialUMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O,
+  SCEVSequentialUMinExpr(const FoldingSetNodeIDRef ID, SCEVUse const *O,
                          size_t N)
       : SCEVSequentialMinMaxExpr(ID, scSequentialUMinExpr, O, N) {}
 
@@ -568,6 +583,7 @@ class SCEVSequentialUMinExpr : public SCEVSequentialMinMaxExpr {
   static bool classof(const SCEV *S) {
     return S->getSCEVType() == scSequentialUMinExpr;
   }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This means that we are dealing with an entirely unknown SCEV
@@ -600,48 +616,56 @@ class SCEVUnknown final : public SCEV, private CallbackVH {
 
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) { return S->getSCEVType() == scUnknown; }
+  static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
 };
 
 /// This class defines a simple visitor class that may be used for
 /// various SCEV analysis purposes.
 template <typename SC, typename RetVal = void> struct SCEVVisitor {
-  RetVal visit(const SCEV *S) {
+  RetVal visit(SCEVUse S) {
     switch (S->getSCEVType()) {
     case scConstant:
-      return ((SC *)this)->visitConstant((const SCEVConstant *)S);
+      return ((SC *)this)->visitConstant((const SCEVConstant *)S.getPointer());
     case scVScale:
-      return ((SC *)this)->visitVScale((const SCEVVScale *)S);
+      return ((SC *)this)->visitVScale((const SCEVVScale *)S.getPointer());
     case scPtrToInt:
-      return ((SC *)this)->visitPtrToIntExpr((const SCEVPtrToIntExpr *)S);
+      return ((SC *)this)
+          ->visitPtrToIntExpr((const SCEVPtrToIntExpr *)S.getPointer());
     case scTruncate:
-      return ((SC *)this)->visitTruncateExpr((const SCEVTruncateExpr *)S);
+      return ((SC *)this)
+          ->visitTruncateExpr((const SCEVTruncateExpr *)S.getPointer());
     case scZeroExtend:
-      return ((SC *)this)->visitZeroExtendExpr((const SCEVZeroExtendExpr *)S);
+      return ((SC *)this)
+          ->visitZeroExtendExpr((const SCEVZeroExtendExpr *)S.getPointer());
     case scSignExtend:
-      return ((SC *)this)->visitSignExtendExpr((const SCEVSignExtendExpr *)S);
+      return ((SC *)this)
+          ->visitSignExtendExpr((const SCEVSignExtendExpr *)S.getPointer());
     case scAddExpr:
-      return ((SC *)this)->visitAddExpr((const SCEVAddExpr *)S);
+      return ((SC *)this)->visitAddExpr((const SCEVAddExpr *)S.getPointer());
     case scMulExpr:
-      return ((SC *)this)->visitMulExpr((const SCEVMulExpr *)S);
+      return ((SC *)this)->visitMulExpr((const SCEVMulExpr *)S.getPointer());
     case scUDivExpr:
-      return ((SC *)this)->visitUDivExpr((const SCEVUDivExpr *)S);
+      return ((SC *)this)->visitUDivExpr((const SCEVUDivExpr *)S.getPointer());
     case scAddRecExpr:
-      return ((SC *)this)->visitAddRecExpr((const SCEVAddRecExpr *)S);
+      return ((SC *)this)
+          ->visitAddRecExpr((const SCEVAddRecExpr *)S.getPointer());
     case scSMaxExpr:
-      return ((SC *)this)->visitSMaxExpr((const SCEVSMaxExpr *)S);
+      return ((SC *)this)->visitSMaxExpr((const SCEVSMaxExpr *)S.getPointer());
     case scUMaxExpr:
-      return ((SC *)this)->visitUMaxExpr((const SCEVUMaxExpr *)S);
+      return ((SC *)this)->visitUMaxExpr((const SCEVUMaxExpr *)S.getPointer());
     case scSMinExpr:
-      return ((SC *)this)->visitSMinExpr((const SCEVSMinExpr *)S);
+      return ((SC *)this)->visitSMinExpr((const SCEVSMinExpr *)S.getPointer());
     case scUMinExpr:
-      return ((SC *)this)->visitUMinExpr((const SCEVUMinExpr *)S);
+      return ((SC *)this)->visitUMinExpr((const SCEVUMinExpr *)S.getPointer());
     case scSequentialUMinExpr:
       return ((SC *)this)
-          ->visitSequentialUMinExpr((const SCEVSequentialUMinExpr *)S);
+          ->visitSequentialUMinExpr(
+              (const SCEVSequentialUMinExpr *)S.getPointer());
     case scUnknown:
-      return ((SC *)this)->visitUnknown((const SCEVUnknown *)S);
+      return ((SC *)this)->visitUnknown((const SCEVUnknown *)S.getPointer());
     case scCouldNotCompute:
-      return ((SC *)this)->visitCouldNotCompute((const SCEVCouldNotCompute *)S);
+      return ((SC *)this)
+          ->visitCouldNotCompute((const SCEVCouldNotCompute *)S.getPointer());
     }
     llvm_unreachable("Unknown SCEV kind!");
   }
@@ -655,15 +679,15 @@ template <typename SC, typename RetVal = void> struct SCEVVisitor {
 ///
 /// Visitor implements:
 ///   // return true to follow this node.
-///   bool follow(const SCEV *S);
+///   bool follow(SCEVUse S);
 ///   // return true to terminate the search.
 ///   bool isDone();
 template <typename SV> class SCEVTraversal {
   SV &Visitor;
-  SmallVector<const SCEV *, 8> Worklist;
-  SmallPtrSet<const SCEV *, 8> Visited;
+  SmallVector<SCEVUse, 8> Worklist;
+  SmallPtrSet<SCEVUse, 8> Visited;
 
-  void push(const SCEV *S) {
+  void push(SCEVUse S) {
     if (Visited.insert(S).second && Visitor.follow(S))
       Worklist.push_back(S);
   }
@@ -671,10 +695,10 @@ template <typename SV> class SCEVTraversal {
 public:
   SCEVTraversal(SV &V) : Visitor(V) {}
 
-  void visitAll(const SCEV *Root) {
+  void visitAll(SCEVUse Root) {
     push(Root);
     while (!Worklist.empty() && !Visitor.isDone()) {
-      const SCEV *S = Worklist.pop_back_val();
+      SCEVUse S = Worklist.pop_back_val();
 
       switch (S->getSCEVType()) {
       case scConstant:
@@ -694,7 +718,7 @@ template <typename SV> class SCEVTraversal {
       case scUMinExpr:
       case scSequentialUMinExpr:
       case scAddRecExpr:
-        for (const auto *Op : S->operands()) {
+        for (const auto Op : S->operands()) {
           push(Op);
           if (Visitor.isDone())
             break;
@@ -709,21 +733,20 @@ template <typename SV> class SCEVTraversal {
 };
 
 /// Use SCEVTraversal to visit all nodes in the given expression tree.
-template <typename SV> void visitAll(const SCEV *Root, SV &Visitor) {
+template <typename SV> void visitAll(SCEVUse Root, SV &Visitor) {
   SCEVTraversal<SV> T(Visitor);
   T.visitAll(Root);
 }
 
 /// Return true if any node in \p Root satisfies the predicate \p Pred.
-template <typename PredTy>
-bool SCEVExprContains(const SCEV *Root, PredTy Pred) {
+template <typename PredTy> bool SCEVExprContains(SCEVUse Root, PredTy Pred) {
   struct FindClosure {
     bool Found = false;
     PredTy Pred;
 
     FindClosure(PredTy Pred) : Pred(Pred) {}
 
-    bool follow(const SCEV *S) {
+    bool follow(SCEVUse S) {
       if (!Pred(S))
         return true;
 
@@ -743,7 +766,7 @@ bool SCEVExprContains(const SCEV *Root, PredTy Pred) {
 /// The result from each visit is cached, so it will return the same
 /// SCEV for the same input.
 template <typename SC>
-class SCEVRewriteVisitor : public SCEVVisitor<SC, const SCEV *> {
+class SCEVRewriteVisitor : public SCEVVisitor<SC, SCEVUse> {
 protected:
   ScalarEvolution &SE;
   // Memoize the result of each visit so that we only compute once for
@@ -751,84 +774,84 @@ class SCEVRewriteVisitor : public SCEVVisitor<SC, const SCEV *> {
   // a SCEV is referenced by multiple SCEVs. Without memoization, this
   // visit algorithm would have exponential time complexity in the worst
   // case, causing the compiler to hang on certain tests.
-  SmallDenseMap<const SCEV *, const SCEV *> RewriteResults;
+  SmallDenseMap<const SCEV *, SCEVUse> RewriteResults;
 
 public:
   SCEVRewriteVisitor(ScalarEvolution &SE) : SE(SE) {}
 
-  const SCEV *visit(const SCEV *S) {
+  SCEVUse visit(SCEVUse S) {
     auto It = RewriteResults.find(S);
     if (It != RewriteResults.end())
       return It->second;
-    auto *Visited = SCEVVisitor<SC, const SCEV *>::visit(S);
+    auto Visited = SCEVVisitor<SC, SCEVUse>::visit(S);
     auto Result = RewriteResults.try_emplace(S, Visited);
     assert(Result.second && "Should insert a new entry");
     return Result.first->second;
   }
 
-  const SCEV *visitConstant(const SCEVConstant *Constant) { return Constant; }
+  SCEVUse visitConstant(const SCEVConstant *Constant) { return Constant; }
 
-  const SCEV *visitVScale(const SCEVVScale *VScale) { return VScale; }
+  SCEVUse visitVScale(const SCEVVScale *VScale) { return VScale; }
 
-  const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
-    const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
+  SCEVUse visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
+    SCEVUse Operand = ((SC *)this)->visit(Expr->getOperand());
     return Operand == Expr->getOperand()
                ? Expr
                : SE.getPtrToIntExpr(Operand, Expr->getType());
   }
 
-  const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
-    const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
+  SCEVUse visitTruncateExpr(const SCEVTruncateExpr *Expr) {
+    SCEVUse Operand = ((SC *)this)->visit(Expr->getOperand());
     return Operand == Expr->getOperand()
                ? Expr
                : SE.getTruncateExpr(Operand, Expr->getType());
   }
 
-  const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
-    const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
+  SCEVUse visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
+    SCEVUse Operand = ((SC *)this)->visit(Expr->getOperand());
     return Operand == Expr->getOperand()
                ? Expr
                : SE.getZeroExtendExpr(Operand, Expr->getType());
   }
 
-  const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
-    const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
+  SCEVUse visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
+    SCEVUse Operand = ((SC *)this)->visit(Expr->getOperand());
     return Operand == Expr->getOperand()
                ? Expr
                : SE.getSignExtendExpr(Operand, Expr->getType());
   }
 
-  const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitAddExpr(const SCEVAddExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
     return !Changed ? Expr : SE.getAddExpr(Operands);
   }
 
-  const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitMulExpr(const SCEVMulExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
     return !Changed ? Expr : SE.getMulExpr(Operands);
   }
 
-  const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) {
-    auto *LHS = ((SC *)this)->visit(Expr->getLHS());
-    auto *RHS = ((SC *)this)->visit(Expr->getRHS());
+  SCEVUse visitUDivExpr(const SCEVUDivExpr *Expr) {
+    auto LHS = ((SC *)this)->visit(Expr->getLHS());
+    auto RHS = ((SC *)this)->visit(Expr->getRHS());
     bool Changed = LHS != Expr->getLHS() || RHS != Expr->getRHS();
     return !Changed ? Expr : SE.getUDivExpr(LHS, RHS);
   }
 
-  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
@@ -837,72 +860,70 @@ class SCEVRewriteVisitor : public SCEVVisitor<SC, const SCEV *> {
                                        Expr->getNoWrapFlags());
   }
 
-  const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitSMaxExpr(const SCEVSMaxExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
     return !Changed ? Expr : SE.getSMaxExpr(Operands);
   }
 
-  const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitUMaxExpr(const SCEVUMaxExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
     return !Changed ? Expr : SE.getUMaxExpr(Operands);
   }
 
-  const SCEV *visitSMinExpr(const SCEVSMinExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitSMinExpr(const SCEVSMinExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
     return !Changed ? Expr : SE.getSMinExpr(Operands);
   }
 
-  const SCEV *visitUMinExpr(const SCEVUMinExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitUMinExpr(const SCEVUMinExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
     return !Changed ? Expr : SE.getUMinExpr(Operands);
   }
 
-  const SCEV *visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
+  SCEVUse visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
     bool Changed = false;
-    for (const auto *Op : Expr->operands()) {
+    for (const auto Op : Expr->operands()) {
       Operands.push_back(((SC *)this)->visit(Op));
       Changed |= Op != Operands.back();
     }
     return !Changed ? Expr : SE.getUMinExpr(Operands, /*Sequential=*/true);
   }
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) { return Expr; }
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) { return Expr; }
 
-  const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) {
-    return Expr;
-  }
+  SCEVUse visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { return Expr; }
 };
 
 using ValueToValueMap = DenseMap<const Value *, Value *>;
-using ValueToSCEVMapTy = DenseMap<const Value *, const SCEV *>;
+using ValueToSCEVMapTy = DenseMap<const Value *, SCEVUse>;
 
 /// The SCEVParameterRewriter takes a scalar evolution expression and updates
 /// the SCEVUnknown components following the Map (Value -> SCEV).
 class SCEVParameterRewriter : public SCEVRewriteVisitor<SCEVParameterRewriter> {
 public:
-  static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE,
-                             ValueToSCEVMapTy &Map) {
+  static SCEVUse rewrite(SCEVUse Scev, ScalarEvolution &SE,
+                         ValueToSCEVMapTy &Map) {
     SCEVParameterRewriter Rewriter(SE, Map);
     return Rewriter.visit(Scev);
   }
@@ -910,7 +931,7 @@ class SCEVParameterRewriter : public SCEVRewriteVisitor<SCEVParameterRewriter> {
   SCEVParameterRewriter(ScalarEvolution &SE, ValueToSCEVMapTy &M)
       : SCEVRewriteVisitor(SE), Map(M) {}
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) {
     auto I = Map.find(Expr->getValue());
     if (I == Map.end())
       return Expr;
@@ -921,7 +942,7 @@ class SCEVParameterRewriter : public SCEVRewriteVisitor<SCEVParameterRewriter> {
   ValueToSCEVMapTy ⤅
 };
 
-using LoopToScevMapT = DenseMap<const Loop *, const SCEV *>;
+using LoopToScevMapT = DenseMap<const Loop *, SCEVUse>;
 
 /// The SCEVLoopAddRecRewriter takes a scalar evolution expression and applies
 /// the Map (Loop -> SCEV) to all AddRecExprs.
@@ -931,15 +952,15 @@ class SCEVLoopAddRecRewriter
   SCEVLoopAddRecRewriter(ScalarEvolution &SE, LoopToScevMapT &M)
       : SCEVRewriteVisitor(SE), Map(M) {}
 
-  static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map,
-                             ScalarEvolution &SE) {
+  static SCEVUse rewrite(SCEVUse Scev, LoopToScevMapT &Map,
+                         ScalarEvolution &SE) {
     SCEVLoopAddRecRewriter Rewriter(SE, Map);
     return Rewriter.visit(Scev);
   }
 
-  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
-    SmallVector<const SCEV *, 2> Operands;
-    for (const SCEV *Op : Expr->operands())
+  SCEVUse visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+    SmallVector<SCEVUse, 2> Operands;
+    for (SCEVUse Op : Expr->operands())
       Operands.push_back(visit(Op));
 
     const Loop *L = Expr->getLoop();
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index e0e7dd18cd8d4..c50616eb2e0ea 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1250,10 +1250,12 @@ bool DependenceInfo::strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
   if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
     LLVM_DEBUG(dbgs() << "\t    UpperBound = " << *UpperBound);
     LLVM_DEBUG(dbgs() << ", " << *UpperBound->getType() << "\n");
-    const SCEV *AbsDelta =
-      SE->isKnownNonNegative(Delta) ? Delta : SE->getNegativeSCEV(Delta);
-    const SCEV *AbsCoeff =
-      SE->isKnownNonNegative(Coeff) ? Coeff : SE->getNegativeSCEV(Coeff);
+    const SCEV *AbsDelta = SE->isKnownNonNegative(Delta)
+                               ? Delta
+                               : SE->getNegativeSCEV(Delta).getPointer();
+    const SCEV *AbsCoeff = SE->isKnownNonNegative(Coeff)
+                               ? Coeff
+                               : SE->getNegativeSCEV(Coeff).getPointer();
     const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
     if (isKnownPredicate(CmpInst::ICMP_SGT, AbsDelta, Product)) {
       // Distance greater than trip count - no dependence
@@ -1791,8 +1793,9 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
   const SCEV *AbsCoeff =
     SE->isKnownNegative(ConstCoeff) ?
     SE->getNegativeSCEV(ConstCoeff) : ConstCoeff;
-  const SCEV *NewDelta =
-    SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
+  const SCEV *NewDelta = SE->isKnownNegative(ConstCoeff)
+                             ? SE->getNegativeSCEV(Delta).getPointer()
+                             : Delta;
 
   // check that Delta/SrcCoeff < iteration count
   // really check NewDelta < count*AbsCoeff
@@ -1900,8 +1903,9 @@ bool DependenceInfo::weakZeroDstSIVtest(const SCEV *SrcCoeff,
   const SCEV *AbsCoeff =
     SE->isKnownNegative(ConstCoeff) ?
     SE->getNegativeSCEV(ConstCoeff) : ConstCoeff;
-  const SCEV *NewDelta =
-    SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
+  const SCEV *NewDelta = SE->isKnownNegative(ConstCoeff)
+                             ? SE->getNegativeSCEV(Delta).getPointer()
+                             : Delta;
 
   // check that Delta/SrcCoeff < iteration count
   // really check NewDelta < count*AbsCoeff
diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp
index 055f121e74341..cbfa768ca7a39 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -1485,7 +1485,7 @@ bool InductionDescriptor::isInductionPHI(
     return false;
 
   // Check that the PHI is consecutive.
-  const SCEV *PhiScev = Expr ? Expr : SE->getSCEV(Phi);
+  const SCEV *PhiScev = Expr ? Expr : SE->getSCEV(Phi).getPointer();
   const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PhiScev);
 
   if (!AR) {
diff --git a/llvm/lib/Analysis/LoopCacheAnalysis.cpp b/llvm/lib/Analysis/LoopCacheAnalysis.cpp
index 284d8d16d264e..a7ed60cc022da 100644
--- a/llvm/lib/Analysis/LoopCacheAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopCacheAnalysis.cpp
@@ -489,7 +489,8 @@ bool IndexedReference::isConsecutive(const Loop &L, const SCEV *&Stride,
                          SE.getNoopOrSignExtend(ElemSize, WiderType));
   const SCEV *CacheLineSize = SE.getConstant(Stride->getType(), CLS);
 
-  Stride = SE.isKnownNegative(Stride) ? SE.getNegativeSCEV(Stride) : Stride;
+  Stride = SE.isKnownNegative(Stride) ? SE.getNegativeSCEV(Stride).getPointer()
+                                      : Stride;
   return SE.isKnownPredicate(ICmpInst::ICMP_ULT, Stride, CacheLineSize);
 }
 
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 704f92669a117..605b66f2ad633 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -253,6 +253,22 @@ static cl::opt<bool> UseContextForNoWrapFlagInference(
 //                           SCEV class definitions
 //===----------------------------------------------------------------------===//
 
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void SCEVUse::dump() const {
+  print(dbgs());
+  dbgs() << '\n';
+}
+#endif
+
+void SCEVUse::print(raw_ostream &OS) const {
+  getPointer()->print(OS);
+  SCEV::NoWrapFlags Flags = static_cast<SCEV::NoWrapFlags>(getInt());
+  if (Flags & SCEV::FlagNUW)
+    OS << "(u nuw)";
+  if (Flags & SCEV::FlagNSW)
+    OS << "(u nsw)";
+}
+
 //===----------------------------------------------------------------------===//
 // Implementation of the SCEV class.
 //
@@ -274,28 +290,28 @@ void SCEV::print(raw_ostream &OS) const {
     return;
   case scPtrToInt: {
     const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(this);
-    const SCEV *Op = PtrToInt->getOperand();
-    OS << "(ptrtoint " << *Op->getType() << " " << *Op << " to "
+    SCEVUse Op = PtrToInt->getOperand();
+    OS << "(ptrtoint " << *Op->getType() << " " << Op << " to "
        << *PtrToInt->getType() << ")";
     return;
   }
   case scTruncate: {
     const SCEVTruncateExpr *Trunc = cast<SCEVTruncateExpr>(this);
-    const SCEV *Op = Trunc->getOperand();
-    OS << "(trunc " << *Op->getType() << " " << *Op << " to "
+    SCEVUse Op = Trunc->getOperand();
+    OS << "(trunc " << *Op->getType() << " " << Op << " to "
        << *Trunc->getType() << ")";
     return;
   }
   case scZeroExtend: {
     const SCEVZeroExtendExpr *ZExt = cast<SCEVZeroExtendExpr>(this);
-    const SCEV *Op = ZExt->getOperand();
-    OS << "(zext " << *Op->getType() << " " << *Op << " to "
-       << *ZExt->getType() << ")";
+    SCEVUse Op = ZExt->getOperand();
+    OS << "(zext " << *Op->getType() << " " << Op << " to " << *ZExt->getType()
+       << ")";
     return;
   }
   case scSignExtend: {
     const SCEVSignExtendExpr *SExt = cast<SCEVSignExtendExpr>(this);
-    const SCEV *Op = SExt->getOperand();
+    SCEVUse Op = SExt->getOperand();
     OS << "(sext " << *Op->getType() << " " << *Op << " to "
        << *SExt->getType() << ")";
     return;
@@ -345,8 +361,8 @@ void SCEV::print(raw_ostream &OS) const {
     }
     OS << "(";
     ListSeparator LS(OpStr);
-    for (const SCEV *Op : NAry->operands())
-      OS << LS << *Op;
+    for (SCEVUse Op : NAry->operands())
+      OS << LS << Op;
     OS << ")";
     switch (NAry->getSCEVType()) {
     case scAddExpr:
@@ -411,7 +427,7 @@ Type *SCEV::getType() const {
   llvm_unreachable("Unknown SCEV kind!");
 }
 
-ArrayRef<const SCEV *> SCEV::operands() const {
+ArrayRef<SCEVUse> SCEV::operands() const {
   switch (getSCEVType()) {
   case scConstant:
   case scVScale:
@@ -476,51 +492,51 @@ bool SCEVCouldNotCompute::classof(const SCEV *S) {
   return S->getSCEVType() == scCouldNotCompute;
 }
 
-const SCEV *ScalarEvolution::getConstant(ConstantInt *V) {
+SCEVUse ScalarEvolution::getConstant(ConstantInt *V) {
   FoldingSetNodeID ID;
   ID.AddInteger(scConstant);
   ID.AddPointer(V);
   void *IP = nullptr;
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return S;
   SCEV *S = new (SCEVAllocator) SCEVConstant(ID.Intern(SCEVAllocator), V);
   UniqueSCEVs.InsertNode(S, IP);
   return S;
 }
 
-const SCEV *ScalarEvolution::getConstant(const APInt &Val) {
+SCEVUse ScalarEvolution::getConstant(const APInt &Val) {
   return getConstant(ConstantInt::get(getContext(), Val));
 }
 
-const SCEV *
-ScalarEvolution::getConstant(Type *Ty, uint64_t V, bool isSigned) {
+SCEVUse ScalarEvolution::getConstant(Type *Ty, uint64_t V, bool isSigned) {
   IntegerType *ITy = cast<IntegerType>(getEffectiveSCEVType(Ty));
   return getConstant(ConstantInt::get(ITy, V, isSigned));
 }
 
-const SCEV *ScalarEvolution::getVScale(Type *Ty) {
+SCEVUse ScalarEvolution::getVScale(Type *Ty) {
   FoldingSetNodeID ID;
   ID.AddInteger(scVScale);
   ID.AddPointer(Ty);
   void *IP = nullptr;
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
     return S;
   SCEV *S = new (SCEVAllocator) SCEVVScale(ID.Intern(SCEVAllocator), Ty);
   UniqueSCEVs.InsertNode(S, IP);
   return S;
 }
 
-const SCEV *ScalarEvolution::getElementCount(Type *Ty, ElementCount EC) {
-  const SCEV *Res = getConstant(Ty, EC.getKnownMinValue());
+SCEVUse ScalarEvolution::getElementCount(Type *Ty, ElementCount EC) {
+  SCEVUse Res = getConstant(Ty, EC.getKnownMinValue());
   if (EC.isScalable())
     Res = getMulExpr(Res, getVScale(Ty));
   return Res;
 }
 
 SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
-                           const SCEV *op, Type *ty)
+                           SCEVUse op, Type *ty)
     : SCEV(ID, SCEVTy, computeExpressionSize(op)), Op(op), Ty(ty) {}
 
-SCEVPtrToIntExpr::SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op,
+SCEVPtrToIntExpr::SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, SCEVUse Op,
                                    Type *ITy)
     : SCEVCastExpr(ID, scPtrToInt, Op, ITy) {
   assert(getOperand()->getType()->isPointerTy() && Ty->isIntegerTy() &&
@@ -528,26 +544,26 @@ SCEVPtrToIntExpr::SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op,
 }
 
 SCEVIntegralCastExpr::SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID,
-                                           SCEVTypes SCEVTy, const SCEV *op,
+                                           SCEVTypes SCEVTy, SCEVUse op,
                                            Type *ty)
     : SCEVCastExpr(ID, SCEVTy, op, ty) {}
 
-SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID, const SCEV *op,
+SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID, SCEVUse op,
                                    Type *ty)
     : SCEVIntegralCastExpr(ID, scTruncate, op, ty) {
   assert(getOperand()->getType()->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot truncate non-integer value!");
 }
 
-SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
-                                       const SCEV *op, Type *ty)
+SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, SCEVUse op,
+                                       Type *ty)
     : SCEVIntegralCastExpr(ID, scZeroExtend, op, ty) {
   assert(getOperand()->getType()->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot zero extend non-integer value!");
 }
 
-SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
-                                       const SCEV *op, Type *ty)
+SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, SCEVUse op,
+                                       Type *ty)
     : SCEVIntegralCastExpr(ID, scSignExtend, op, ty) {
   assert(getOperand()->getType()->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot sign extend non-integer value!");
@@ -555,7 +571,7 @@ SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
 
 void SCEVUnknown::deleted() {
   // Clear this SCEVUnknown from various maps.
-  SE->forgetMemoizedResults(this);
+  SE->forgetMemoizedResults(SCEVUse(this));
 
   // Remove this SCEVUnknown from the uniquing map.
   SE->UniqueSCEVs.RemoveNode(this);
@@ -566,7 +582,7 @@ void SCEVUnknown::deleted() {
 
 void SCEVUnknown::allUsesReplacedWith(Value *New) {
   // Clear this SCEVUnknown from various maps.
-  SE->forgetMemoizedResults(this);
+  SE->forgetMemoizedResults(SCEVUse(this));
 
   // Remove this SCEVUnknown from the uniquing map.
   SE->UniqueSCEVs.RemoveNode(this);
@@ -678,10 +694,10 @@ CompareValueComplexity(EquivalenceClasses<const Value *> &EqCacheValue,
 // If the max analysis depth was reached, return std::nullopt, assuming we do
 // not know if they are equivalent for sure.
 static std::optional<int>
-CompareSCEVComplexity(EquivalenceClasses<const SCEV *> &EqCacheSCEV,
+CompareSCEVComplexity(EquivalenceClasses<SCEVUse> &EqCacheSCEV,
                       EquivalenceClasses<const Value *> &EqCacheValue,
-                      const LoopInfo *const LI, const SCEV *LHS,
-                      const SCEV *RHS, DominatorTree &DT, unsigned Depth = 0) {
+                      const LoopInfo *const LI, SCEVUse LHS, SCEVUse RHS,
+                      DominatorTree &DT, unsigned Depth = 0) {
   // Fast-path: SCEVs are uniqued so we can do a quick equality check.
   if (LHS == RHS)
     return 0;
@@ -764,8 +780,8 @@ CompareSCEVComplexity(EquivalenceClasses<const SCEV *> &EqCacheSCEV,
   case scSMinExpr:
   case scUMinExpr:
   case scSequentialUMinExpr: {
-    ArrayRef<const SCEV *> LOps = LHS->operands();
-    ArrayRef<const SCEV *> ROps = RHS->operands();
+    ArrayRef<SCEVUse> LOps = LHS->operands();
+    ArrayRef<SCEVUse> ROps = RHS->operands();
 
     // Lexicographically compare n-ary-like expressions.
     unsigned LNumOps = LOps.size(), RNumOps = ROps.size();
@@ -797,15 +813,15 @@ CompareSCEVComplexity(EquivalenceClasses<const SCEV *> &EqCacheSCEV,
 /// results from this routine.  In other words, we don't want the results of
 /// this to depend on where the addresses of various SCEV objects happened to
 /// land in memory.
-static void GroupByComplexity(SmallVectorImpl<const SCEV *> &Ops,
-                              LoopInfo *LI, DominatorTree &DT) {
+static void GroupByComplexity(SmallVectorImpl<SCEVUse> &Ops, LoopInfo *LI,
+                              DominatorTree &DT) {
   if (Ops.size() < 2) return;  // Noop
 
-  EquivalenceClasses<const SCEV *> EqCacheSCEV;
+  EquivalenceClasses<SCEVUse> EqCacheSCEV;
   EquivalenceClasses<const Value *> EqCacheValue;
 
   // Whether LHS has provably less complexity than RHS.
-  auto IsLessComplex = [&](const SCEV *LHS, const SCEV *RHS) {
+  auto IsLessComplex = [&](SCEVUse LHS, SCEVUse RHS) {
     auto Complexity =
         CompareSCEVComplexity(EqCacheSCEV, EqCacheValue, LI, LHS, RHS, DT);
     return Complexity && *Complexity < 0;
@@ -813,23 +829,22 @@ static void GroupByComplexity(SmallVectorImpl<const SCEV *> &Ops,
   if (Ops.size() == 2) {
     // This is the common case, which also happens to be trivially simple.
     // Special case it.
-    const SCEV *&LHS = Ops[0], *&RHS = Ops[1];
+    SCEVUse &LHS = Ops[0], &RHS = Ops[1];
     if (IsLessComplex(RHS, LHS))
       std::swap(LHS, RHS);
     return;
   }
 
   // Do the rough sort by complexity.
-  llvm::stable_sort(Ops, [&](const SCEV *LHS, const SCEV *RHS) {
-    return IsLessComplex(LHS, RHS);
-  });
+  llvm::stable_sort(
+      Ops, [&](SCEVUse LHS, SCEVUse RHS) { return IsLessComplex(LHS, RHS); });
 
   // Now that we are sorted by complexity, group elements of the same
   // complexity.  Note that this is, at worst, N^2, but the vector is likely to
   // be extremely short in practice.  Note that we take this approach because we
   // do not want to depend on the addresses of the objects we are grouping.
   for (unsigned i = 0, e = Ops.size(); i != e-2; ++i) {
-    const SCEV *S = Ops[i];
+    SCEVUse S = Ops[i];
     unsigned Complexity = S->getSCEVType();
 
     // If there are any objects of the same complexity and same value as this
@@ -847,8 +862,8 @@ static void GroupByComplexity(SmallVectorImpl<const SCEV *> &Ops,
 
 /// Returns true if \p Ops contains a huge SCEV (the subtree of S contains at
 /// least HugeExprThreshold nodes).
-static bool hasHugeExpression(ArrayRef<const SCEV *> Ops) {
-  return any_of(Ops, [](const SCEV *S) {
+static bool hasHugeExpression(ArrayRef<SCEVUse> Ops) {
+  return any_of(Ops, [](SCEVUse S) {
     return S->getExpressionSize() >= HugeExprThreshold;
   });
 }
@@ -858,9 +873,8 @@ static bool hasHugeExpression(ArrayRef<const SCEV *> Ops) {
 //===----------------------------------------------------------------------===//
 
 /// Compute BC(It, K).  The result has width W.  Assume, K > 0.
-static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K,
-                                       ScalarEvolution &SE,
-                                       Type *ResultTy) {
+static SCEVUse BinomialCoefficient(SCEVUse It, unsigned K, ScalarEvolution &SE,
+                                   Type *ResultTy) {
   // Handle the simplest case efficiently.
   if (K == 1)
     return SE.getTruncateOrZeroExtend(It, ResultTy);
@@ -947,15 +961,15 @@ static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K,
   // Calculate the product, at width T+W
   IntegerType *CalculationTy = IntegerType::get(SE.getContext(),
                                                       CalculationBits);
-  const SCEV *Dividend = SE.getTruncateOrZeroExtend(It, CalculationTy);
+  SCEVUse Dividend = SE.getTruncateOrZeroExtend(It, CalculationTy);
   for (unsigned i = 1; i != K; ++i) {
-    const SCEV *S = SE.getMinusSCEV(It, SE.getConstant(It->getType(), i));
+    SCEVUse S = SE.getMinusSCEV(It, SE.getConstant(It->getType(), i));
     Dividend = SE.getMulExpr(Dividend,
                              SE.getTruncateOrZeroExtend(S, CalculationTy));
   }
 
   // Divide by 2^T
-  const SCEV *DivResult = SE.getUDivExpr(Dividend, SE.getConstant(DivFactor));
+  SCEVUse DivResult = SE.getUDivExpr(Dividend, SE.getConstant(DivFactor));
 
   // Truncate the result, and divide by K! / 2^T.
 
@@ -971,21 +985,20 @@ static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K,
 ///   A*BC(It, 0) + B*BC(It, 1) + C*BC(It, 2) + D*BC(It, 3)
 ///
 /// where BC(It, k) stands for binomial coefficient.
-const SCEV *SCEVAddRecExpr::evaluateAtIteration(const SCEV *It,
-                                                ScalarEvolution &SE) const {
+SCEVUse SCEVAddRecExpr::evaluateAtIteration(SCEVUse It,
+                                            ScalarEvolution &SE) const {
   return evaluateAtIteration(operands(), It, SE);
 }
 
-const SCEV *
-SCEVAddRecExpr::evaluateAtIteration(ArrayRef<const SCEV *> Operands,
-                                    const SCEV *It, ScalarEvolution &SE) {
+SCEVUse SCEVAddRecExpr::evaluateAtIteration(ArrayRef<SCEVUse> Operands,
+                                            SCEVUse It, ScalarEvolution &SE) {
   assert(Operands.size() > 0);
-  const SCEV *Result = Operands[0];
+  SCEVUse Result = Operands[0];
   for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
     // The computation is correct in the face of overflow provided that the
     // multiplication is performed _after_ the evaluation of the binomial
     // coefficient.
-    const SCEV *Coeff = BinomialCoefficient(It, i, SE, Result->getType());
+    SCEVUse Coeff = BinomialCoefficient(It, i, SE, Result->getType());
     if (isa<SCEVCouldNotCompute>(Coeff))
       return Coeff;
 
@@ -998,8 +1011,7 @@ SCEVAddRecExpr::evaluateAtIteration(ArrayRef<const SCEV *> Operands,
 //                    SCEV Expression folder implementations
 //===----------------------------------------------------------------------===//
 
-const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
-                                                     unsigned Depth) {
+SCEVUse ScalarEvolution::getLosslessPtrToIntExpr(SCEVUse Op, unsigned Depth) {
   assert(Depth <= 1 &&
          "getLosslessPtrToIntExpr() should self-recurse at most once.");
 
@@ -1016,7 +1028,7 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
   void *IP = nullptr;
 
   // Is there already an expression for such a cast?
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
     return S;
 
   // It isn't legal for optimizations to construct new ptrtoint expressions
@@ -1073,12 +1085,12 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
   public:
     SCEVPtrToIntSinkingRewriter(ScalarEvolution &SE) : SCEVRewriteVisitor(SE) {}
 
-    static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE) {
+    static SCEVUse rewrite(SCEVUse Scev, ScalarEvolution &SE) {
       SCEVPtrToIntSinkingRewriter Rewriter(SE);
       return Rewriter.visit(Scev);
     }
 
-    const SCEV *visit(const SCEV *S) {
+    SCEVUse visit(SCEVUse S) {
       Type *STy = S->getType();
       // If the expression is not pointer-typed, just keep it as-is.
       if (!STy->isPointerTy())
@@ -1087,27 +1099,27 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
       return Base::visit(S);
     }
 
-    const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
-      SmallVector<const SCEV *, 2> Operands;
+    SCEVUse visitAddExpr(const SCEVAddExpr *Expr) {
+      SmallVector<SCEVUse, 2> Operands;
       bool Changed = false;
-      for (const auto *Op : Expr->operands()) {
+      for (const auto Op : Expr->operands()) {
         Operands.push_back(visit(Op));
         Changed |= Op != Operands.back();
       }
       return !Changed ? Expr : SE.getAddExpr(Operands, Expr->getNoWrapFlags());
     }
 
-    const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
-      SmallVector<const SCEV *, 2> Operands;
+    SCEVUse visitMulExpr(const SCEVMulExpr *Expr) {
+      SmallVector<SCEVUse, 2> Operands;
       bool Changed = false;
-      for (const auto *Op : Expr->operands()) {
+      for (const auto Op : Expr->operands()) {
         Operands.push_back(visit(Op));
         Changed |= Op != Operands.back();
       }
       return !Changed ? Expr : SE.getMulExpr(Operands, Expr->getNoWrapFlags());
     }
 
-    const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+    SCEVUse visitUnknown(const SCEVUnknown *Expr) {
       assert(Expr->getType()->isPointerTy() &&
              "Should only reach pointer-typed SCEVUnknown's.");
       return SE.getLosslessPtrToIntExpr(Expr, /*Depth=*/1);
@@ -1115,25 +1127,24 @@ const SCEV *ScalarEvolution::getLosslessPtrToIntExpr(const SCEV *Op,
   };
 
   // And actually perform the cast sinking.
-  const SCEV *IntOp = SCEVPtrToIntSinkingRewriter::rewrite(Op, *this);
+  SCEVUse IntOp = SCEVPtrToIntSinkingRewriter::rewrite(Op, *this);
   assert(IntOp->getType()->isIntegerTy() &&
          "We must have succeeded in sinking the cast, "
          "and ending up with an integer-typed expression!");
   return IntOp;
 }
 
-const SCEV *ScalarEvolution::getPtrToIntExpr(const SCEV *Op, Type *Ty) {
+SCEVUse ScalarEvolution::getPtrToIntExpr(SCEVUse Op, Type *Ty) {
   assert(Ty->isIntegerTy() && "Target type must be an integer type!");
 
-  const SCEV *IntOp = getLosslessPtrToIntExpr(Op);
+  SCEVUse IntOp = getLosslessPtrToIntExpr(Op);
   if (isa<SCEVCouldNotCompute>(IntOp))
     return IntOp;
 
   return getTruncateOrZeroExtend(IntOp, Ty);
 }
 
-const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
-                                             unsigned Depth) {
+SCEVUse ScalarEvolution::getTruncateExpr(SCEVUse Op, Type *Ty, unsigned Depth) {
   assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) &&
          "This is not a truncating conversion!");
   assert(isSCEVable(Ty) &&
@@ -1146,7 +1157,8 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
   ID.AddPointer(Op);
   ID.AddPointer(Ty);
   void *IP = nullptr;
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return S;
 
   // Fold if the operand is constant.
   if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(Op))
@@ -1179,11 +1191,11 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
   // that replace other casts.
   if (isa<SCEVAddExpr>(Op) || isa<SCEVMulExpr>(Op)) {
     auto *CommOp = cast<SCEVCommutativeExpr>(Op);
-    SmallVector<const SCEV *, 4> Operands;
+    SmallVector<SCEVUse, 4> Operands;
     unsigned numTruncs = 0;
     for (unsigned i = 0, e = CommOp->getNumOperands(); i != e && numTruncs < 2;
          ++i) {
-      const SCEV *S = getTruncateExpr(CommOp->getOperand(i), Ty, Depth + 1);
+      SCEVUse S = getTruncateExpr(CommOp->getOperand(i), Ty, Depth + 1);
       if (!isa<SCEVIntegralCastExpr>(CommOp->getOperand(i)) &&
           isa<SCEVTruncateExpr>(S))
         numTruncs++;
@@ -1199,14 +1211,14 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
     // Although we checked in the beginning that ID is not in the cache, it is
     // possible that during recursion and different modification ID was inserted
     // into the cache. So if we find it, just return it.
-    if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
       return S;
   }
 
   // If the input value is a chrec scev, truncate the chrec's operands.
   if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Op)) {
-    SmallVector<const SCEV *, 4> Operands;
-    for (const SCEV *Op : AddRec->operands())
+    SmallVector<SCEVUse, 4> Operands;
+    for (SCEVUse Op : AddRec->operands())
       Operands.push_back(getTruncateExpr(Op, Ty, Depth + 1));
     return getAddRecExpr(Operands, AddRec->getLoop(), SCEV::FlagAnyWrap);
   }
@@ -1229,9 +1241,9 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
 // Get the limit of a recurrence such that incrementing by Step cannot cause
 // signed overflow as long as the value of the recurrence within the
 // loop does not exceed this limit before incrementing.
-static const SCEV *getSignedOverflowLimitForStep(const SCEV *Step,
-                                                 ICmpInst::Predicate *Pred,
-                                                 ScalarEvolution *SE) {
+static SCEVUse getSignedOverflowLimitForStep(SCEVUse Step,
+                                             ICmpInst::Predicate *Pred,
+                                             ScalarEvolution *SE) {
   unsigned BitWidth = SE->getTypeSizeInBits(Step->getType());
   if (SE->isKnownPositive(Step)) {
     *Pred = ICmpInst::ICMP_SLT;
@@ -1249,9 +1261,9 @@ static const SCEV *getSignedOverflowLimitForStep(const SCEV *Step,
 // Get the limit of a recurrence such that incrementing by Step cannot cause
 // unsigned overflow as long as the value of the recurrence within the loop does
 // not exceed this limit before incrementing.
-static const SCEV *getUnsignedOverflowLimitForStep(const SCEV *Step,
-                                                   ICmpInst::Predicate *Pred,
-                                                   ScalarEvolution *SE) {
+static SCEVUse getUnsignedOverflowLimitForStep(SCEVUse Step,
+                                               ICmpInst::Predicate *Pred,
+                                               ScalarEvolution *SE) {
   unsigned BitWidth = SE->getTypeSizeInBits(Step->getType());
   *Pred = ICmpInst::ICMP_ULT;
 
@@ -1262,8 +1274,8 @@ static const SCEV *getUnsignedOverflowLimitForStep(const SCEV *Step,
 namespace {
 
 struct ExtendOpTraitsBase {
-  typedef const SCEV *(ScalarEvolution::*GetExtendExprTy)(const SCEV *, Type *,
-                                                          unsigned);
+  typedef SCEVUse (ScalarEvolution:: *GetExtendExprTy)(SCEVUse, Type *,
+                                                       unsigned);
 };
 
 // Used to make code generic over signed and unsigned overflow.
@@ -1274,7 +1286,7 @@ template <typename ExtendOp> struct ExtendOpTraits {
   //
   // static const ExtendOpTraitsBase::GetExtendExprTy GetExtendExpr;
   //
-  // static const SCEV *getOverflowLimitForStep(const SCEV *Step,
+  // static SCEVUse getOverflowLimitForStep(SCEVUse Step,
   //                                           ICmpInst::Predicate *Pred,
   //                                           ScalarEvolution *SE);
 };
@@ -1285,9 +1297,9 @@ struct ExtendOpTraits<SCEVSignExtendExpr> : public ExtendOpTraitsBase {
 
   static const GetExtendExprTy GetExtendExpr;
 
-  static const SCEV *getOverflowLimitForStep(const SCEV *Step,
-                                             ICmpInst::Predicate *Pred,
-                                             ScalarEvolution *SE) {
+  static SCEVUse getOverflowLimitForStep(SCEVUse Step,
+                                         ICmpInst::Predicate *Pred,
+                                         ScalarEvolution *SE) {
     return getSignedOverflowLimitForStep(Step, Pred, SE);
   }
 };
@@ -1301,9 +1313,9 @@ struct ExtendOpTraits<SCEVZeroExtendExpr> : public ExtendOpTraitsBase {
 
   static const GetExtendExprTy GetExtendExpr;
 
-  static const SCEV *getOverflowLimitForStep(const SCEV *Step,
-                                             ICmpInst::Predicate *Pred,
-                                             ScalarEvolution *SE) {
+  static SCEVUse getOverflowLimitForStep(SCEVUse Step,
+                                         ICmpInst::Predicate *Pred,
+                                         ScalarEvolution *SE) {
     return getUnsignedOverflowLimitForStep(Step, Pred, SE);
   }
 };
@@ -1321,14 +1333,14 @@ const ExtendOpTraitsBase::GetExtendExprTy ExtendOpTraits<
 // expression "Step + sext/zext(PreIncAR)" is congruent with
 // "sext/zext(PostIncAR)"
 template <typename ExtendOpTy>
-static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
-                                        ScalarEvolution *SE, unsigned Depth) {
+static SCEVUse getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
+                                    ScalarEvolution *SE, unsigned Depth) {
   auto WrapType = ExtendOpTraits<ExtendOpTy>::WrapType;
   auto GetExtendExpr = ExtendOpTraits<ExtendOpTy>::GetExtendExpr;
 
   const Loop *L = AR->getLoop();
-  const SCEV *Start = AR->getStart();
-  const SCEV *Step = AR->getStepRecurrence(*SE);
+  SCEVUse Start = AR->getStart();
+  SCEVUse Step = AR->getStepRecurrence(*SE);
 
   // Check for a simple looking step prior to loop entry.
   const SCEVAddExpr *SA = dyn_cast<SCEVAddExpr>(Start);
@@ -1339,7 +1351,7 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
   // subtraction is expensive. For this purpose, perform a quick and dirty
   // difference, by checking for Step in the operand list. Note, that
   // SA might have repeated ops, like %a + %a + ..., so only remove one.
-  SmallVector<const SCEV *, 4> DiffOps(SA->operands());
+  SmallVector<SCEVUse, 4> DiffOps(SA->operands());
   for (auto It = DiffOps.begin(); It != DiffOps.end(); ++It)
     if (*It == Step) {
       DiffOps.erase(It);
@@ -1355,7 +1367,7 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
   // 1. NSW/NUW flags on the step increment.
   auto PreStartFlags =
     ScalarEvolution::maskFlags(SA->getNoWrapFlags(), SCEV::FlagNUW);
-  const SCEV *PreStart = SE->getAddExpr(DiffOps, PreStartFlags);
+  SCEVUse PreStart = SE->getAddExpr(DiffOps, PreStartFlags);
   const SCEVAddRecExpr *PreAR = dyn_cast<SCEVAddRecExpr>(
       SE->getAddRecExpr(PreStart, Step, L, SCEV::FlagAnyWrap));
 
@@ -1363,7 +1375,7 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
   // "S+X does not sign/unsign-overflow".
   //
 
-  const SCEV *BECount = SE->getBackedgeTakenCount(L);
+  SCEVUse BECount = SE->getBackedgeTakenCount(L);
   if (PreAR && PreAR->getNoWrapFlags(WrapType) &&
       !isa<SCEVCouldNotCompute>(BECount) && SE->isKnownPositive(BECount))
     return PreStart;
@@ -1371,7 +1383,7 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
   // 2. Direct overflow check on the step operation's expression.
   unsigned BitWidth = SE->getTypeSizeInBits(AR->getType());
   Type *WideTy = IntegerType::get(SE->getContext(), BitWidth * 2);
-  const SCEV *OperandExtendedStart =
+  SCEVUse OperandExtendedStart =
       SE->getAddExpr((SE->*GetExtendExpr)(PreStart, WideTy, Depth),
                      (SE->*GetExtendExpr)(Step, WideTy, Depth));
   if ((SE->*GetExtendExpr)(Start, WideTy, Depth) == OperandExtendedStart) {
@@ -1386,7 +1398,7 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
 
   // 3. Loop precondition.
   ICmpInst::Predicate Pred;
-  const SCEV *OverflowLimit =
+  SCEVUse OverflowLimit =
       ExtendOpTraits<ExtendOpTy>::getOverflowLimitForStep(Step, &Pred, SE);
 
   if (OverflowLimit &&
@@ -1398,12 +1410,11 @@ static const SCEV *getPreStartForExtend(const SCEVAddRecExpr *AR, Type *Ty,
 
 // Get the normalized zero or sign extended expression for this AddRec's Start.
 template <typename ExtendOpTy>
-static const SCEV *getExtendAddRecStart(const SCEVAddRecExpr *AR, Type *Ty,
-                                        ScalarEvolution *SE,
-                                        unsigned Depth) {
+static SCEVUse getExtendAddRecStart(const SCEVAddRecExpr *AR, Type *Ty,
+                                    ScalarEvolution *SE, unsigned Depth) {
   auto GetExtendExpr = ExtendOpTraits<ExtendOpTy>::GetExtendExpr;
 
-  const SCEV *PreStart = getPreStartForExtend<ExtendOpTy>(AR, Ty, SE, Depth);
+  SCEVUse PreStart = getPreStartForExtend<ExtendOpTy>(AR, Ty, SE, Depth);
   if (!PreStart)
     return (SE->*GetExtendExpr)(AR->getStart(), Ty, Depth);
 
@@ -1445,8 +1456,7 @@ static const SCEV *getExtendAddRecStart(const SCEVAddRecExpr *AR, Type *Ty,
 // In the current context, S is `Start`, X is `Step`, Ext is `ExtendOpTy` and T
 // is `Delta` (defined below).
 template <typename ExtendOpTy>
-bool ScalarEvolution::proveNoWrapByVaryingStart(const SCEV *Start,
-                                                const SCEV *Step,
+bool ScalarEvolution::proveNoWrapByVaryingStart(SCEVUse Start, SCEVUse Step,
                                                 const Loop *L) {
   auto WrapType = ExtendOpTraits<ExtendOpTy>::WrapType;
 
@@ -1461,7 +1471,7 @@ bool ScalarEvolution::proveNoWrapByVaryingStart(const SCEV *Start,
   APInt StartAI = StartC->getAPInt();
 
   for (unsigned Delta : {-2, -1, 1, 2}) {
-    const SCEV *PreStart = getConstant(StartAI - Delta);
+    SCEVUse PreStart = getConstant(StartAI - Delta);
 
     FoldingSetNodeID ID;
     ID.AddInteger(scAddRecExpr);
@@ -1475,9 +1485,9 @@ bool ScalarEvolution::proveNoWrapByVaryingStart(const SCEV *Start,
     // Give up if we don't already have the add recurrence we need because
     // actually constructing an add recurrence is relatively expensive.
     if (PreAR && PreAR->getNoWrapFlags(WrapType)) {  // proves (2)
-      const SCEV *DeltaS = getConstant(StartC->getType(), Delta);
+      SCEVUse DeltaS = getConstant(StartC->getType(), Delta);
       ICmpInst::Predicate Pred = ICmpInst::BAD_ICMP_PREDICATE;
-      const SCEV *Limit = ExtendOpTraits<ExtendOpTy>::getOverflowLimitForStep(
+      SCEVUse Limit = ExtendOpTraits<ExtendOpTy>::getOverflowLimitForStep(
           DeltaS, &Pred, this);
       if (Limit && isKnownPredicate(Pred, PreAR, Limit))  // proves (1)
         return true;
@@ -1515,7 +1525,7 @@ static APInt extractConstantWithoutWrapping(ScalarEvolution &SE,
 // ConstantStart, x is an arbitrary \p Step, and n is the loop trip count.
 static APInt extractConstantWithoutWrapping(ScalarEvolution &SE,
                                             const APInt &ConstantStart,
-                                            const SCEV *Step) {
+                                            SCEVUse Step) {
   const unsigned BitWidth = ConstantStart.getBitWidth();
   const uint32_t TZ = SE.getMinTrailingZeros(Step);
   if (TZ)
@@ -1525,10 +1535,9 @@ static APInt extractConstantWithoutWrapping(ScalarEvolution &SE,
 }
 
 static void insertFoldCacheEntry(
-    const ScalarEvolution::FoldID &ID, const SCEV *S,
-    DenseMap<ScalarEvolution::FoldID, const SCEV *> &FoldCache,
-    DenseMap<const SCEV *, SmallVector<ScalarEvolution::FoldID, 2>>
-        &FoldCacheUser) {
+    const ScalarEvolution::FoldID &ID, SCEVUse S,
+    DenseMap<ScalarEvolution::FoldID, SCEVUse> &FoldCache,
+    DenseMap<SCEVUse, SmallVector<ScalarEvolution::FoldID, 2>> &FoldCacheUser) {
   auto I = FoldCache.insert({ID, S});
   if (!I.second) {
     // Remove FoldCacheUser entry for ID when replacing an existing FoldCache
@@ -1547,8 +1556,8 @@ static void insertFoldCacheEntry(
   R.first->second.push_back(ID);
 }
 
-const SCEV *
-ScalarEvolution::getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) {
+SCEVUse ScalarEvolution::getZeroExtendExpr(SCEVUse Op, Type *Ty,
+                                           unsigned Depth) {
   assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
          "This is not an extending conversion!");
   assert(isSCEVable(Ty) &&
@@ -1561,14 +1570,14 @@ ScalarEvolution::getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) {
   if (Iter != FoldCache.end())
     return Iter->second;
 
-  const SCEV *S = getZeroExtendExprImpl(Op, Ty, Depth);
+  SCEVUse S = getZeroExtendExprImpl(Op, Ty, Depth);
   if (!isa<SCEVZeroExtendExpr>(S))
     insertFoldCacheEntry(ID, S, FoldCache, FoldCacheUser);
   return S;
 }
 
-const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
-                                                   unsigned Depth) {
+SCEVUse ScalarEvolution::getZeroExtendExprImpl(SCEVUse Op, Type *Ty,
+                                               unsigned Depth) {
   assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
          "This is not an extending conversion!");
   assert(isSCEVable(Ty) && "This is not a conversion to a SCEVable type!");
@@ -1589,7 +1598,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
   ID.AddPointer(Op);
   ID.AddPointer(Ty);
   void *IP = nullptr;
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return S;
   if (Depth > MaxCastDepth) {
     SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator),
                                                      Op, Ty);
@@ -1602,7 +1612,7 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
   if (const SCEVTruncateExpr *ST = dyn_cast<SCEVTruncateExpr>(Op)) {
     // It's possible the bits taken off by the truncate were all zero bits. If
     // so, we should be able to simplify this further.
-    const SCEV *X = ST->getOperand();
+    SCEVUse X = ST->getOperand();
     ConstantRange CR = getUnsignedRange(X);
     unsigned TruncBits = getTypeSizeInBits(ST->getType());
     unsigned NewBits = getTypeSizeInBits(Ty);
@@ -1617,8 +1627,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
   // this:  for (unsigned char X = 0; X < 100; ++X) { int Y = X; }
   if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op))
     if (AR->isAffine()) {
-      const SCEV *Start = AR->getStart();
-      const SCEV *Step = AR->getStepRecurrence(*this);
+      SCEVUse Start = AR->getStart();
+      SCEVUse Step = AR->getStepRecurrence(*this);
       unsigned BitWidth = getTypeSizeInBits(AR->getType());
       const Loop *L = AR->getLoop();
 
@@ -1639,34 +1649,33 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
       // in infinite recursion. In the later case, the analysis code will
       // cope with a conservative value, and it will take care to purge
       // that value once it has finished.
-      const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);
+      SCEVUse MaxBECount = getConstantMaxBackedgeTakenCount(L);
       if (!isa<SCEVCouldNotCompute>(MaxBECount)) {
         // Manually compute the final value for AR, checking for overflow.
 
         // Check whether the backedge-taken count can be losslessly casted to
         // the addrec's type. The count is always unsigned.
-        const SCEV *CastedMaxBECount =
+        SCEVUse CastedMaxBECount =
             getTruncateOrZeroExtend(MaxBECount, Start->getType(), Depth);
-        const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(
+        SCEVUse RecastedMaxBECount = getTruncateOrZeroExtend(
             CastedMaxBECount, MaxBECount->getType(), Depth);
         if (MaxBECount == RecastedMaxBECount) {
           Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
           // Check whether Start+Step*MaxBECount has no unsigned overflow.
-          const SCEV *ZMul = getMulExpr(CastedMaxBECount, Step,
-                                        SCEV::FlagAnyWrap, Depth + 1);
-          const SCEV *ZAdd = getZeroExtendExpr(getAddExpr(Start, ZMul,
-                                                          SCEV::FlagAnyWrap,
-                                                          Depth + 1),
-                                               WideTy, Depth + 1);
-          const SCEV *WideStart = getZeroExtendExpr(Start, WideTy, Depth + 1);
-          const SCEV *WideMaxBECount =
-            getZeroExtendExpr(CastedMaxBECount, WideTy, Depth + 1);
-          const SCEV *OperandExtendedAdd =
-            getAddExpr(WideStart,
-                       getMulExpr(WideMaxBECount,
-                                  getZeroExtendExpr(Step, WideTy, Depth + 1),
-                                  SCEV::FlagAnyWrap, Depth + 1),
-                       SCEV::FlagAnyWrap, Depth + 1);
+          SCEVUse ZMul =
+              getMulExpr(CastedMaxBECount, Step, SCEV::FlagAnyWrap, Depth + 1);
+          SCEVUse ZAdd = getZeroExtendExpr(
+              getAddExpr(Start, ZMul, SCEV::FlagAnyWrap, Depth + 1), WideTy,
+              Depth + 1);
+          SCEVUse WideStart = getZeroExtendExpr(Start, WideTy, Depth + 1);
+          SCEVUse WideMaxBECount =
+              getZeroExtendExpr(CastedMaxBECount, WideTy, Depth + 1);
+          SCEVUse OperandExtendedAdd =
+              getAddExpr(WideStart,
+                         getMulExpr(WideMaxBECount,
+                                    getZeroExtendExpr(Step, WideTy, Depth + 1),
+                                    SCEV::FlagAnyWrap, Depth + 1),
+                         SCEV::FlagAnyWrap, Depth + 1);
           if (ZAdd == OperandExtendedAdd) {
             // Cache knowledge of AR NUW, which is propagated to this AddRec.
             setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNUW);
@@ -1723,8 +1732,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
         // For a negative step, we can extend the operands iff doing so only
         // traverses values in the range zext([0,UINT_MAX]).
         if (isKnownNegative(Step)) {
-          const SCEV *N = getConstant(APInt::getMaxValue(BitWidth) -
-                                      getSignedRangeMin(Step));
+          SCEVUse N = getConstant(APInt::getMaxValue(BitWidth) -
+                                  getSignedRangeMin(Step));
           if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, AR, N) ||
               isKnownOnEveryIteration(ICmpInst::ICMP_UGT, AR, N)) {
             // Cache knowledge of AR NW, which is propagated to this
@@ -1747,10 +1756,10 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
         const APInt &C = SC->getAPInt();
         const APInt &D = extractConstantWithoutWrapping(*this, C, Step);
         if (D != 0) {
-          const SCEV *SZExtD = getZeroExtendExpr(getConstant(D), Ty, Depth);
-          const SCEV *SResidual =
+          SCEVUse SZExtD = getZeroExtendExpr(getConstant(D), Ty, Depth);
+          SCEVUse SResidual =
               getAddRecExpr(getConstant(C - D), Step, L, AR->getNoWrapFlags());
-          const SCEV *SZExtR = getZeroExtendExpr(SResidual, Ty, Depth + 1);
+          SCEVUse SZExtR = getZeroExtendExpr(SResidual, Ty, Depth + 1);
           return getAddExpr(SZExtD, SZExtR,
                             (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                             Depth + 1);
@@ -1768,8 +1777,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
 
   // zext(A % B) --> zext(A) % zext(B)
   {
-    const SCEV *LHS;
-    const SCEV *RHS;
+    SCEVUse LHS;
+    SCEVUse RHS;
     if (matchURem(Op, LHS, RHS))
       return getURemExpr(getZeroExtendExpr(LHS, Ty, Depth + 1),
                          getZeroExtendExpr(RHS, Ty, Depth + 1));
@@ -1785,8 +1794,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
     if (SA->hasNoUnsignedWrap()) {
       // If the addition does not unsign overflow then we can, by definition,
       // commute the zero extension with the addition operation.
-      SmallVector<const SCEV *, 4> Ops;
-      for (const auto *Op : SA->operands())
+      SmallVector<SCEVUse, 4> Ops;
+      for (const auto Op : SA->operands())
         Ops.push_back(getZeroExtendExpr(Op, Ty, Depth + 1));
       return getAddExpr(Ops, SCEV::FlagNUW, Depth + 1);
     }
@@ -1802,10 +1811,10 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
     if (const auto *SC = dyn_cast<SCEVConstant>(SA->getOperand(0))) {
       const APInt &D = extractConstantWithoutWrapping(*this, SC, SA);
       if (D != 0) {
-        const SCEV *SZExtD = getZeroExtendExpr(getConstant(D), Ty, Depth);
-        const SCEV *SResidual =
+        SCEVUse SZExtD = getZeroExtendExpr(getConstant(D), Ty, Depth);
+        SCEVUse SResidual =
             getAddExpr(getConstant(-D), SA, SCEV::FlagAnyWrap, Depth);
-        const SCEV *SZExtR = getZeroExtendExpr(SResidual, Ty, Depth + 1);
+        SCEVUse SZExtR = getZeroExtendExpr(SResidual, Ty, Depth + 1);
         return getAddExpr(SZExtD, SZExtR,
                           (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                           Depth + 1);
@@ -1818,8 +1827,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
     if (SM->hasNoUnsignedWrap()) {
       // If the multiply does not unsign overflow then we can, by definition,
       // commute the zero extension with the multiply operation.
-      SmallVector<const SCEV *, 4> Ops;
-      for (const auto *Op : SM->operands())
+      SmallVector<SCEVUse, 4> Ops;
+      for (const auto Op : SM->operands())
         Ops.push_back(getZeroExtendExpr(Op, Ty, Depth + 1));
       return getMulExpr(Ops, SCEV::FlagNUW, Depth + 1);
     }
@@ -1855,8 +1864,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
   // zext(umax(x, y)) -> umax(zext(x), zext(y))
   if (isa<SCEVUMinExpr>(Op) || isa<SCEVUMaxExpr>(Op)) {
     auto *MinMax = cast<SCEVMinMaxExpr>(Op);
-    SmallVector<const SCEV *, 4> Operands;
-    for (auto *Operand : MinMax->operands())
+    SmallVector<SCEVUse, 4> Operands;
+    for (auto Operand : MinMax->operands())
       Operands.push_back(getZeroExtendExpr(Operand, Ty));
     if (isa<SCEVUMinExpr>(MinMax))
       return getUMinExpr(Operands);
@@ -1866,15 +1875,16 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
   // zext(umin_seq(x, y)) -> umin_seq(zext(x), zext(y))
   if (auto *MinMax = dyn_cast<SCEVSequentialMinMaxExpr>(Op)) {
     assert(isa<SCEVSequentialUMinExpr>(MinMax) && "Not supported!");
-    SmallVector<const SCEV *, 4> Operands;
-    for (auto *Operand : MinMax->operands())
+    SmallVector<SCEVUse, 4> Operands;
+    for (auto Operand : MinMax->operands())
       Operands.push_back(getZeroExtendExpr(Operand, Ty));
     return getUMinExpr(Operands, /*Sequential*/ true);
   }
 
   // The cast wasn't folded; create an explicit cast node.
   // Recompute the insert position, as it may have been invalidated.
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return S;
   SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator),
                                                    Op, Ty);
   UniqueSCEVs.InsertNode(S, IP);
@@ -1882,8 +1892,8 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
   return S;
 }
 
-const SCEV *
-ScalarEvolution::getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) {
+SCEVUse ScalarEvolution::getSignExtendExpr(SCEVUse Op, Type *Ty,
+                                           unsigned Depth) {
   assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
          "This is not an extending conversion!");
   assert(isSCEVable(Ty) &&
@@ -1896,14 +1906,14 @@ ScalarEvolution::getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth) {
   if (Iter != FoldCache.end())
     return Iter->second;
 
-  const SCEV *S = getSignExtendExprImpl(Op, Ty, Depth);
+  SCEVUse S = getSignExtendExprImpl(Op, Ty, Depth);
   if (!isa<SCEVSignExtendExpr>(S))
     insertFoldCacheEntry(ID, S, FoldCache, FoldCacheUser);
   return S;
 }
 
-const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
-                                                   unsigned Depth) {
+SCEVUse ScalarEvolution::getSignExtendExprImpl(SCEVUse Op, Type *Ty,
+                                               unsigned Depth) {
   assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
          "This is not an extending conversion!");
   assert(isSCEVable(Ty) && "This is not a conversion to a SCEVable type!");
@@ -1929,7 +1939,8 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
   ID.AddPointer(Op);
   ID.AddPointer(Ty);
   void *IP = nullptr;
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return S;
   // Limit recursion depth.
   if (Depth > MaxCastDepth) {
     SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator),
@@ -1943,7 +1954,7 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
   if (const SCEVTruncateExpr *ST = dyn_cast<SCEVTruncateExpr>(Op)) {
     // It's possible the bits taken off by the truncate were all sign bits. If
     // so, we should be able to simplify this further.
-    const SCEV *X = ST->getOperand();
+    SCEVUse X = ST->getOperand();
     ConstantRange CR = getSignedRange(X);
     unsigned TruncBits = getTypeSizeInBits(ST->getType());
     unsigned NewBits = getTypeSizeInBits(Ty);
@@ -1957,8 +1968,8 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
     if (SA->hasNoSignedWrap()) {
       // If the addition does not sign overflow then we can, by definition,
       // commute the sign extension with the addition operation.
-      SmallVector<const SCEV *, 4> Ops;
-      for (const auto *Op : SA->operands())
+      SmallVector<SCEVUse, 4> Ops;
+      for (const auto Op : SA->operands())
         Ops.push_back(getSignExtendExpr(Op, Ty, Depth + 1));
       return getAddExpr(Ops, SCEV::FlagNSW, Depth + 1);
     }
@@ -1975,10 +1986,10 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
     if (const auto *SC = dyn_cast<SCEVConstant>(SA->getOperand(0))) {
       const APInt &D = extractConstantWithoutWrapping(*this, SC, SA);
       if (D != 0) {
-        const SCEV *SSExtD = getSignExtendExpr(getConstant(D), Ty, Depth);
-        const SCEV *SResidual =
+        SCEVUse SSExtD = getSignExtendExpr(getConstant(D), Ty, Depth);
+        SCEVUse SResidual =
             getAddExpr(getConstant(-D), SA, SCEV::FlagAnyWrap, Depth);
-        const SCEV *SSExtR = getSignExtendExpr(SResidual, Ty, Depth + 1);
+        SCEVUse SSExtR = getSignExtendExpr(SResidual, Ty, Depth + 1);
         return getAddExpr(SSExtD, SSExtR,
                           (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                           Depth + 1);
@@ -1991,8 +2002,8 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
   // this:  for (signed char X = 0; X < 100; ++X) { int Y = X; }
   if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op))
     if (AR->isAffine()) {
-      const SCEV *Start = AR->getStart();
-      const SCEV *Step = AR->getStepRecurrence(*this);
+      SCEVUse Start = AR->getStart();
+      SCEVUse Step = AR->getStepRecurrence(*this);
       unsigned BitWidth = getTypeSizeInBits(AR->getType());
       const Loop *L = AR->getLoop();
 
@@ -2013,35 +2024,34 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
       // in infinite recursion. In the later case, the analysis code will
       // cope with a conservative value, and it will take care to purge
       // that value once it has finished.
-      const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);
+      SCEVUse MaxBECount = getConstantMaxBackedgeTakenCount(L);
       if (!isa<SCEVCouldNotCompute>(MaxBECount)) {
         // Manually compute the final value for AR, checking for
         // overflow.
 
         // Check whether the backedge-taken count can be losslessly casted to
         // the addrec's type. The count is always unsigned.
-        const SCEV *CastedMaxBECount =
+        SCEVUse CastedMaxBECount =
             getTruncateOrZeroExtend(MaxBECount, Start->getType(), Depth);
-        const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(
+        SCEVUse RecastedMaxBECount = getTruncateOrZeroExtend(
             CastedMaxBECount, MaxBECount->getType(), Depth);
         if (MaxBECount == RecastedMaxBECount) {
           Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
           // Check whether Start+Step*MaxBECount has no signed overflow.
-          const SCEV *SMul = getMulExpr(CastedMaxBECount, Step,
-                                        SCEV::FlagAnyWrap, Depth + 1);
-          const SCEV *SAdd = getSignExtendExpr(getAddExpr(Start, SMul,
-                                                          SCEV::FlagAnyWrap,
-                                                          Depth + 1),
-                                               WideTy, Depth + 1);
-          const SCEV *WideStart = getSignExtendExpr(Start, WideTy, Depth + 1);
-          const SCEV *WideMaxBECount =
-            getZeroExtendExpr(CastedMaxBECount, WideTy, Depth + 1);
-          const SCEV *OperandExtendedAdd =
-            getAddExpr(WideStart,
-                       getMulExpr(WideMaxBECount,
-                                  getSignExtendExpr(Step, WideTy, Depth + 1),
-                                  SCEV::FlagAnyWrap, Depth + 1),
-                       SCEV::FlagAnyWrap, Depth + 1);
+          SCEVUse SMul =
+              getMulExpr(CastedMaxBECount, Step, SCEV::FlagAnyWrap, Depth + 1);
+          SCEVUse SAdd = getSignExtendExpr(
+              getAddExpr(Start, SMul, SCEV::FlagAnyWrap, Depth + 1), WideTy,
+              Depth + 1);
+          SCEVUse WideStart = getSignExtendExpr(Start, WideTy, Depth + 1);
+          SCEVUse WideMaxBECount =
+              getZeroExtendExpr(CastedMaxBECount, WideTy, Depth + 1);
+          SCEVUse OperandExtendedAdd =
+              getAddExpr(WideStart,
+                         getMulExpr(WideMaxBECount,
+                                    getSignExtendExpr(Step, WideTy, Depth + 1),
+                                    SCEV::FlagAnyWrap, Depth + 1),
+                         SCEV::FlagAnyWrap, Depth + 1);
           if (SAdd == OperandExtendedAdd) {
             // Cache knowledge of AR NSW, which is propagated to this AddRec.
             setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNSW);
@@ -2099,10 +2109,10 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
         const APInt &C = SC->getAPInt();
         const APInt &D = extractConstantWithoutWrapping(*this, C, Step);
         if (D != 0) {
-          const SCEV *SSExtD = getSignExtendExpr(getConstant(D), Ty, Depth);
-          const SCEV *SResidual =
+          SCEVUse SSExtD = getSignExtendExpr(getConstant(D), Ty, Depth);
+          SCEVUse SResidual =
               getAddRecExpr(getConstant(C - D), Step, L, AR->getNoWrapFlags());
-          const SCEV *SSExtR = getSignExtendExpr(SResidual, Ty, Depth + 1);
+          SCEVUse SSExtR = getSignExtendExpr(SResidual, Ty, Depth + 1);
           return getAddExpr(SSExtD, SSExtR,
                             (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW),
                             Depth + 1);
@@ -2127,8 +2137,8 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
   // sext(smax(x, y)) -> smax(sext(x), sext(y))
   if (isa<SCEVSMinExpr>(Op) || isa<SCEVSMaxExpr>(Op)) {
     auto *MinMax = cast<SCEVMinMaxExpr>(Op);
-    SmallVector<const SCEV *, 4> Operands;
-    for (auto *Operand : MinMax->operands())
+    SmallVector<SCEVUse, 4> Operands;
+    for (auto Operand : MinMax->operands())
       Operands.push_back(getSignExtendExpr(Operand, Ty));
     if (isa<SCEVSMinExpr>(MinMax))
       return getSMinExpr(Operands);
@@ -2137,7 +2147,8 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
 
   // The cast wasn't folded; create an explicit cast node.
   // Recompute the insert position, as it may have been invalidated.
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return S;
   SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator),
                                                    Op, Ty);
   UniqueSCEVs.InsertNode(S, IP);
@@ -2145,8 +2156,7 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
   return S;
 }
 
-const SCEV *ScalarEvolution::getCastExpr(SCEVTypes Kind, const SCEV *Op,
-                                         Type *Ty) {
+SCEVUse ScalarEvolution::getCastExpr(SCEVTypes Kind, SCEVUse Op, Type *Ty) {
   switch (Kind) {
   case scTruncate:
     return getTruncateExpr(Op, Ty);
@@ -2163,8 +2173,7 @@ const SCEV *ScalarEvolution::getCastExpr(SCEVTypes Kind, const SCEV *Op,
 
 /// getAnyExtendExpr - Return a SCEV for the given operand extended with
 /// unspecified bits out to the given type.
-const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op,
-                                              Type *Ty) {
+SCEVUse ScalarEvolution::getAnyExtendExpr(SCEVUse Op, Type *Ty) {
   assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) &&
          "This is not an extending conversion!");
   assert(isSCEVable(Ty) &&
@@ -2178,26 +2187,26 @@ const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op,
 
   // Peel off a truncate cast.
   if (const SCEVTruncateExpr *T = dyn_cast<SCEVTruncateExpr>(Op)) {
-    const SCEV *NewOp = T->getOperand();
+    SCEVUse NewOp = T->getOperand();
     if (getTypeSizeInBits(NewOp->getType()) < getTypeSizeInBits(Ty))
       return getAnyExtendExpr(NewOp, Ty);
     return getTruncateOrNoop(NewOp, Ty);
   }
 
   // Next try a zext cast. If the cast is folded, use it.
-  const SCEV *ZExt = getZeroExtendExpr(Op, Ty);
+  SCEVUse ZExt = getZeroExtendExpr(Op, Ty);
   if (!isa<SCEVZeroExtendExpr>(ZExt))
     return ZExt;
 
   // Next try a sext cast. If the cast is folded, use it.
-  const SCEV *SExt = getSignExtendExpr(Op, Ty);
+  SCEVUse SExt = getSignExtendExpr(Op, Ty);
   if (!isa<SCEVSignExtendExpr>(SExt))
     return SExt;
 
   // Force the cast to be folded into the operands of an addrec.
   if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Op)) {
-    SmallVector<const SCEV *, 4> Ops;
-    for (const SCEV *Op : AR->operands())
+    SmallVector<SCEVUse, 4> Ops;
+    for (SCEVUse Op : AR->operands())
       Ops.push_back(getAnyExtendExpr(Op, Ty));
     return getAddRecExpr(Ops, AR->getLoop(), SCEV::FlagNW);
   }
@@ -2233,12 +2242,12 @@ const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op,
 /// may be exposed. This helps getAddRecExpr short-circuit extra work in
 /// the common case where no interesting opportunities are present, and
 /// is also used as a check to avoid infinite recursion.
-static bool
-CollectAddOperandsWithScales(DenseMap<const SCEV *, APInt> &M,
-                             SmallVectorImpl<const SCEV *> &NewOps,
-                             APInt &AccumulatedConstant,
-                             ArrayRef<const SCEV *> Ops, const APInt &Scale,
-                             ScalarEvolution &SE) {
+static bool CollectAddOperandsWithScales(DenseMap<const SCEV *, APInt> &M,
+                                         SmallVectorImpl<SCEVUse> &NewOps,
+                                         APInt &AccumulatedConstant,
+                                         ArrayRef<SCEVUse> Ops,
+                                         const APInt &Scale,
+                                         ScalarEvolution &SE) {
   bool Interesting = false;
 
   // Iterate over the add operands. They are sorted, with constants first.
@@ -2267,8 +2276,8 @@ CollectAddOperandsWithScales(DenseMap<const SCEV *, APInt> &M,
       } else {
         // A multiplication of a constant with some other value. Update
         // the map.
-        SmallVector<const SCEV *, 4> MulOps(drop_begin(Mul->operands()));
-        const SCEV *Key = SE.getMulExpr(MulOps);
+        SmallVector<SCEVUse, 4> MulOps(drop_begin(Mul->operands()));
+        SCEVUse Key = SE.getMulExpr(MulOps);
         auto Pair = M.insert({Key, NewScale});
         if (Pair.second) {
           NewOps.push_back(Pair.first->first);
@@ -2298,10 +2307,10 @@ CollectAddOperandsWithScales(DenseMap<const SCEV *, APInt> &M,
 }
 
 bool ScalarEvolution::willNotOverflow(Instruction::BinaryOps BinOp, bool Signed,
-                                      const SCEV *LHS, const SCEV *RHS,
+                                      SCEVUse LHS, SCEVUse RHS,
                                       const Instruction *CtxI) {
-  const SCEV *(ScalarEvolution::*Operation)(const SCEV *, const SCEV *,
-                                            SCEV::NoWrapFlags, unsigned);
+  SCEVUse (ScalarEvolution:: *Operation)(SCEVUse, SCEVUse, SCEV::NoWrapFlags,
+                                         unsigned);
   switch (BinOp) {
   default:
     llvm_unreachable("Unsupported binary op");
@@ -2316,7 +2325,7 @@ bool ScalarEvolution::willNotOverflow(Instruction::BinaryOps BinOp, bool Signed,
     break;
   }
 
-  const SCEV *(ScalarEvolution::*Extension)(const SCEV *, Type *, unsigned) =
+  SCEVUse (ScalarEvolution:: *Extension)(SCEVUse, Type *, unsigned) =
       Signed ? &ScalarEvolution::getSignExtendExpr
              : &ScalarEvolution::getZeroExtendExpr;
 
@@ -2325,11 +2334,11 @@ bool ScalarEvolution::willNotOverflow(Instruction::BinaryOps BinOp, bool Signed,
   auto *WideTy =
       IntegerType::get(NarrowTy->getContext(), NarrowTy->getBitWidth() * 2);
 
-  const SCEV *A = (this->*Extension)(
+  SCEVUse A = (this->*Extension)(
       (this->*Operation)(LHS, RHS, SCEV::FlagAnyWrap, 0), WideTy, 0);
-  const SCEV *LHSB = (this->*Extension)(LHS, WideTy, 0);
-  const SCEV *RHSB = (this->*Extension)(RHS, WideTy, 0);
-  const SCEV *B = (this->*Operation)(LHSB, RHSB, SCEV::FlagAnyWrap, 0);
+  SCEVUse LHSB = (this->*Extension)(LHS, WideTy, 0);
+  SCEVUse RHSB = (this->*Extension)(RHS, WideTy, 0);
+  SCEVUse B = (this->*Operation)(LHSB, RHSB, SCEV::FlagAnyWrap, 0);
   if (A == B)
     return true;
   // Can we use context to prove the fact we need?
@@ -2394,8 +2403,8 @@ ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(
       OBO->getOpcode() != Instruction::Mul)
     return std::nullopt;
 
-  const SCEV *LHS = getSCEV(OBO->getOperand(0));
-  const SCEV *RHS = getSCEV(OBO->getOperand(1));
+  SCEVUse LHS = getSCEV(OBO->getOperand(0));
+  SCEVUse RHS = getSCEV(OBO->getOperand(1));
 
   const Instruction *CtxI =
       UseContextForNoWrapFlagInference ? dyn_cast<Instruction>(OBO) : nullptr;
@@ -2421,10 +2430,10 @@ ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(
 // We're trying to construct a SCEV of type `Type' with `Ops' as operands and
 // `OldFlags' as can't-wrap behavior.  Infer a more aggressive set of
 // can't-overflow flags for the operation if possible.
-static SCEV::NoWrapFlags
-StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type,
-                      const ArrayRef<const SCEV *> Ops,
-                      SCEV::NoWrapFlags Flags) {
+static SCEV::NoWrapFlags StrengthenNoWrapFlags(ScalarEvolution *SE,
+                                               SCEVTypes Type,
+                                               const ArrayRef<SCEVUse> Ops,
+                                               SCEV::NoWrapFlags Flags) {
   using namespace std::placeholders;
 
   using OBO = OverflowingBinaryOperator;
@@ -2439,7 +2448,7 @@ StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type,
       ScalarEvolution::maskFlags(Flags, SignOrUnsignMask);
 
   // If FlagNSW is true and all the operands are non-negative, infer FlagNUW.
-  auto IsKnownNonNegative = [&](const SCEV *S) {
+  auto IsKnownNonNegative = [&](SCEVUse S) {
     return SE->isKnownNonNegative(S);
   };
 
@@ -2504,14 +2513,20 @@ StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type,
   return Flags;
 }
 
-bool ScalarEvolution::isAvailableAtLoopEntry(const SCEV *S, const Loop *L) {
+bool ScalarEvolution::isAvailableAtLoopEntry(SCEVUse S, const Loop *L) {
   return isLoopInvariant(S, L) && properlyDominates(S, L->getHeader());
 }
 
+SCEVUse ScalarEvolution::getAddExpr(ArrayRef<const SCEV *> Ops,
+                                    SCEV::NoWrapFlags Flags, unsigned Depth) {
+  SmallVector<SCEVUse> Ops2(Ops.begin(), Ops.end());
+  return getAddExpr(Ops2, Flags, Depth);
+}
+
 /// Get a canonical add expression, or something simpler if possible.
-const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
-                                        SCEV::NoWrapFlags OrigFlags,
-                                        unsigned Depth) {
+SCEVUse ScalarEvolution::getAddExpr(SmallVectorImpl<SCEVUse> &Ops,
+                                    SCEV::NoWrapFlags OrigFlags,
+                                    unsigned Depth) {
   assert(!(OrigFlags & ~(SCEV::FlagNUW | SCEV::FlagNSW)) &&
          "only nuw or nsw allowed");
   assert(!Ops.empty() && "Cannot get empty add!");
@@ -2521,8 +2536,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
   for (unsigned i = 1, e = Ops.size(); i != e; ++i)
     assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy &&
            "SCEVAddExpr operand types don't match!");
-  unsigned NumPtrs = count_if(
-      Ops, [](const SCEV *Op) { return Op->getType()->isPointerTy(); });
+  unsigned NumPtrs =
+      count_if(Ops, [](SCEVUse Op) { return Op->getType()->isPointerTy(); });
   assert(NumPtrs <= 1 && "add has at most one pointer operand");
 #endif
 
@@ -2552,7 +2567,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
   }
 
   // Delay expensive flag strengthening until necessary.
-  auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) {
+  auto ComputeFlags = [this, OrigFlags](const ArrayRef<SCEVUse> Ops) {
     return StrengthenNoWrapFlags(this, scAddExpr, Ops, OrigFlags);
   };
 
@@ -2580,8 +2595,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
       while (i+Count != e && Ops[i+Count] == Ops[i])
         ++Count;
       // Merge the values into a multiply.
-      const SCEV *Scale = getConstant(Ty, Count);
-      const SCEV *Mul = getMulExpr(Scale, Ops[i], SCEV::FlagAnyWrap, Depth + 1);
+      SCEVUse Scale = getConstant(Ty, Count);
+      SCEVUse Mul = getMulExpr(Scale, Ops[i], SCEV::FlagAnyWrap, Depth + 1);
       if (Ops.size() == Count)
         return Mul;
       Ops[i] = Mul;
@@ -2604,14 +2619,14 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
     if (auto *T = dyn_cast<SCEVTruncateExpr>(Ops[Idx]))
       return T->getOperand()->getType();
     if (const auto *Mul = dyn_cast<SCEVMulExpr>(Ops[Idx])) {
-      const auto *LastOp = Mul->getOperand(Mul->getNumOperands() - 1);
+      const auto LastOp = Mul->getOperand(Mul->getNumOperands() - 1);
       if (const auto *T = dyn_cast<SCEVTruncateExpr>(LastOp))
         return T->getOperand()->getType();
     }
     return nullptr;
   };
   if (auto *SrcType = FindTruncSrcType()) {
-    SmallVector<const SCEV *, 8> LargeOps;
+    SmallVector<SCEVUse, 8> LargeOps;
     bool Ok = true;
     // Check all the operands to see if they can be represented in the
     // source type of the truncate.
@@ -2625,7 +2640,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
       } else if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Ops[i])) {
         LargeOps.push_back(getAnyExtendExpr(C, SrcType));
       } else if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Ops[i])) {
-        SmallVector<const SCEV *, 8> LargeMulOps;
+        SmallVector<SCEVUse, 8> LargeMulOps;
         for (unsigned j = 0, f = M->getNumOperands(); j != f && Ok; ++j) {
           if (const SCEVTruncateExpr *T =
                 dyn_cast<SCEVTruncateExpr>(M->getOperand(j))) {
@@ -2650,7 +2665,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
     }
     if (Ok) {
       // Evaluate the expression in the larger type.
-      const SCEV *Fold = getAddExpr(LargeOps, SCEV::FlagAnyWrap, Depth + 1);
+      SCEVUse Fold = getAddExpr(LargeOps, SCEV::FlagAnyWrap, Depth + 1);
       // If it folds to something simple, use it. Otherwise, don't.
       if (isa<SCEVConstant>(Fold) || isa<SCEVUnknown>(Fold))
         return getTruncateExpr(Fold, Ty);
@@ -2661,8 +2676,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
     // Check if we have an expression of the form ((X + C1) - C2), where C1 and
     // C2 can be folded in a way that allows retaining wrapping flags of (X +
     // C1).
-    const SCEV *A = Ops[0];
-    const SCEV *B = Ops[1];
+    SCEVUse A = Ops[0];
+    SCEVUse B = Ops[1];
     auto *AddExpr = dyn_cast<SCEVAddExpr>(B);
     auto *C = dyn_cast<SCEVConstant>(A);
     if (AddExpr && C && isa<SCEVConstant>(AddExpr->getOperand(0))) {
@@ -2689,7 +2704,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
       }
 
       if (PreservedFlags != SCEV::FlagAnyWrap) {
-        SmallVector<const SCEV *, 4> NewOps(AddExpr->operands());
+        SmallVector<SCEVUse, 4> NewOps(AddExpr->operands());
         NewOps[0] = getConstant(ConstAdd);
         return getAddExpr(NewOps, PreservedFlags);
       }
@@ -2701,8 +2716,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
     const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[0]);
     if (Mul && Mul->getNumOperands() == 2 &&
         Mul->getOperand(0)->isAllOnesValue()) {
-      const SCEV *X;
-      const SCEV *Y;
+      SCEVUse X;
+      SCEVUse Y;
       if (matchURem(Mul->getOperand(1), X, Y) && X == Ops[1]) {
         return getMulExpr(Y, getUDivExpr(X, Y));
       }
@@ -2748,7 +2763,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
   if (Idx < Ops.size() && isa<SCEVMulExpr>(Ops[Idx])) {
     uint64_t BitWidth = getTypeSizeInBits(Ty);
     DenseMap<const SCEV *, APInt> M;
-    SmallVector<const SCEV *, 8> NewOps;
+    SmallVector<SCEVUse, 8> NewOps;
     APInt AccumulatedConstant(BitWidth, 0);
     if (CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant,
                                      Ops, APInt(BitWidth, 1), *this)) {
@@ -2761,8 +2776,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
       // Some interesting folding opportunity is present, so its worthwhile to
       // re-generate the operands list. Group the operands by constant scale,
       // to avoid multiplying by the same constant scale multiple times.
-      std::map<APInt, SmallVector<const SCEV *, 4>, APIntCompare> MulOpLists;
-      for (const SCEV *NewOp : NewOps)
+      std::map<APInt, SmallVector<SCEVUse, 4>, APIntCompare> MulOpLists;
+      for (SCEVUse NewOp : NewOps)
         MulOpLists[M.find(NewOp)->second].push_back(NewOp);
       // Re-generate the operands list.
       Ops.clear();
@@ -2792,25 +2807,24 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
   for (; Idx < Ops.size() && isa<SCEVMulExpr>(Ops[Idx]); ++Idx) {
     const SCEVMulExpr *Mul = cast<SCEVMulExpr>(Ops[Idx]);
     for (unsigned MulOp = 0, e = Mul->getNumOperands(); MulOp != e; ++MulOp) {
-      const SCEV *MulOpSCEV = Mul->getOperand(MulOp);
+      SCEVUse MulOpSCEV = Mul->getOperand(MulOp);
       if (isa<SCEVConstant>(MulOpSCEV))
         continue;
       for (unsigned AddOp = 0, e = Ops.size(); AddOp != e; ++AddOp)
         if (MulOpSCEV == Ops[AddOp]) {
           // Fold W + X + (X * Y * Z)  -->  W + (X * ((Y*Z)+1))
-          const SCEV *InnerMul = Mul->getOperand(MulOp == 0);
+          SCEVUse InnerMul = Mul->getOperand(MulOp == 0);
           if (Mul->getNumOperands() != 2) {
             // If the multiply has more than two operands, we must get the
             // Y*Z term.
-            SmallVector<const SCEV *, 4> MulOps(
-                Mul->operands().take_front(MulOp));
+            SmallVector<SCEVUse, 4> MulOps(Mul->operands().take_front(MulOp));
             append_range(MulOps, Mul->operands().drop_front(MulOp + 1));
             InnerMul = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
           }
-          SmallVector<const SCEV *, 2> TwoOps = {getOne(Ty), InnerMul};
-          const SCEV *AddOne = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
-          const SCEV *OuterMul = getMulExpr(AddOne, MulOpSCEV,
-                                            SCEV::FlagAnyWrap, Depth + 1);
+          SmallVector<SCEVUse, 2> TwoOps = {getOne(Ty), InnerMul};
+          SCEVUse AddOne = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
+          SCEVUse OuterMul =
+              getMulExpr(AddOne, MulOpSCEV, SCEV::FlagAnyWrap, Depth + 1);
           if (Ops.size() == 2) return OuterMul;
           if (AddOp < Idx) {
             Ops.erase(Ops.begin()+AddOp);
@@ -2834,25 +2848,24 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
              OMulOp != e; ++OMulOp)
           if (OtherMul->getOperand(OMulOp) == MulOpSCEV) {
             // Fold X + (A*B*C) + (A*D*E) --> X + (A*(B*C+D*E))
-            const SCEV *InnerMul1 = Mul->getOperand(MulOp == 0);
+            SCEVUse InnerMul1 = Mul->getOperand(MulOp == 0);
             if (Mul->getNumOperands() != 2) {
-              SmallVector<const SCEV *, 4> MulOps(
-                  Mul->operands().take_front(MulOp));
+              SmallVector<SCEVUse, 4> MulOps(Mul->operands().take_front(MulOp));
               append_range(MulOps, Mul->operands().drop_front(MulOp+1));
               InnerMul1 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
             }
-            const SCEV *InnerMul2 = OtherMul->getOperand(OMulOp == 0);
+            SCEVUse InnerMul2 = OtherMul->getOperand(OMulOp == 0);
             if (OtherMul->getNumOperands() != 2) {
-              SmallVector<const SCEV *, 4> MulOps(
+              SmallVector<SCEVUse, 4> MulOps(
                   OtherMul->operands().take_front(OMulOp));
               append_range(MulOps, OtherMul->operands().drop_front(OMulOp+1));
               InnerMul2 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
             }
-            SmallVector<const SCEV *, 2> TwoOps = {InnerMul1, InnerMul2};
-            const SCEV *InnerMulSum =
+            SmallVector<SCEVUse, 2> TwoOps = {InnerMul1, InnerMul2};
+            SCEVUse InnerMulSum =
                 getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
-            const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum,
-                                              SCEV::FlagAnyWrap, Depth + 1);
+            SCEVUse OuterMul = getMulExpr(MulOpSCEV, InnerMulSum,
+                                          SCEV::FlagAnyWrap, Depth + 1);
             if (Ops.size() == 2) return OuterMul;
             Ops.erase(Ops.begin()+Idx);
             Ops.erase(Ops.begin()+OtherMulIdx-1);
@@ -2873,7 +2886,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
   for (; Idx < Ops.size() && isa<SCEVAddRecExpr>(Ops[Idx]); ++Idx) {
     // Scan all of the other operands to this add and add them to the vector if
     // they are loop invariant w.r.t. the recurrence.
-    SmallVector<const SCEV *, 8> LIOps;
+    SmallVector<SCEVUse, 8> LIOps;
     const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
     const Loop *AddRecLoop = AddRec->getLoop();
     for (unsigned i = 0, e = Ops.size(); i != e; ++i)
@@ -2895,7 +2908,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
       //  NLI + LI + {Start,+,Step}  -->  NLI + {LI+Start,+,Step}
       LIOps.push_back(AddRec->getStart());
 
-      SmallVector<const SCEV *, 4> AddRecOps(AddRec->operands());
+      SmallVector<SCEVUse, 4> AddRecOps(AddRec->operands());
 
       // It is not in general safe to propagate flags valid on an add within
       // the addrec scope to one outside it.  We must prove that the inner
@@ -2920,7 +2933,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
       // outer add and the inner addrec are guaranteed to have no overflow.
       // Always propagate NW.
       Flags = AddRec->getNoWrapFlags(setFlags(Flags, SCEV::FlagNW));
-      const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRecLoop, Flags);
+      SCEVUse NewRec = getAddRecExpr(AddRecOps, AddRecLoop, Flags);
 
       // If all of the other operands were loop invariant, we are done.
       if (Ops.size() == 1) return NewRec;
@@ -2948,7 +2961,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
         "AddRecExprs are not sorted in reverse dominance order?");
       if (AddRecLoop == cast<SCEVAddRecExpr>(Ops[OtherIdx])->getLoop()) {
         // Other + {A,+,B}<L> + {C,+,D}<L>  -->  Other + {A+C,+,B+D}<L>
-        SmallVector<const SCEV *, 4> AddRecOps(AddRec->operands());
+        SmallVector<SCEVUse, 4> AddRecOps(AddRec->operands());
         for (; OtherIdx != Ops.size() && isa<SCEVAddRecExpr>(Ops[OtherIdx]);
              ++OtherIdx) {
           const auto *OtherAddRec = cast<SCEVAddRecExpr>(Ops[OtherIdx]);
@@ -2959,8 +2972,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
                 append_range(AddRecOps, OtherAddRec->operands().drop_front(i));
                 break;
               }
-              SmallVector<const SCEV *, 2> TwoOps = {
-                  AddRecOps[i], OtherAddRec->getOperand(i)};
+              SmallVector<SCEVUse, 2> TwoOps = {AddRecOps[i],
+                                                OtherAddRec->getOperand(i)};
               AddRecOps[i] = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
             }
             Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
@@ -2981,18 +2994,17 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
   return getOrCreateAddExpr(Ops, ComputeFlags(Ops));
 }
 
-const SCEV *
-ScalarEvolution::getOrCreateAddExpr(ArrayRef<const SCEV *> Ops,
-                                    SCEV::NoWrapFlags Flags) {
+SCEVUse ScalarEvolution::getOrCreateAddExpr(ArrayRef<SCEVUse> Ops,
+                                            SCEV::NoWrapFlags Flags) {
   FoldingSetNodeID ID;
   ID.AddInteger(scAddExpr);
-  for (const SCEV *Op : Ops)
+  for (SCEVUse Op : Ops)
     ID.AddPointer(Op);
   void *IP = nullptr;
   SCEVAddExpr *S =
       static_cast<SCEVAddExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
   if (!S) {
-    const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
+    SCEVUse *O = SCEVAllocator.Allocate<SCEVUse>(Ops.size());
     std::uninitialized_copy(Ops.begin(), Ops.end(), O);
     S = new (SCEVAllocator)
         SCEVAddExpr(ID.Intern(SCEVAllocator), O, Ops.size());
@@ -3003,19 +3015,19 @@ ScalarEvolution::getOrCreateAddExpr(ArrayRef<const SCEV *> Ops,
   return S;
 }
 
-const SCEV *
-ScalarEvolution::getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops,
-                                       const Loop *L, SCEV::NoWrapFlags Flags) {
+SCEVUse ScalarEvolution::getOrCreateAddRecExpr(ArrayRef<SCEVUse> Ops,
+                                               const Loop *L,
+                                               SCEV::NoWrapFlags Flags) {
   FoldingSetNodeID ID;
   ID.AddInteger(scAddRecExpr);
-  for (const SCEV *Op : Ops)
+  for (SCEVUse Op : Ops)
     ID.AddPointer(Op);
   ID.AddPointer(L);
   void *IP = nullptr;
   SCEVAddRecExpr *S =
       static_cast<SCEVAddRecExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
   if (!S) {
-    const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
+    SCEVUse *O = SCEVAllocator.Allocate<SCEVUse>(Ops.size());
     std::uninitialized_copy(Ops.begin(), Ops.end(), O);
     S = new (SCEVAllocator)
         SCEVAddRecExpr(ID.Intern(SCEVAllocator), O, Ops.size(), L);
@@ -3027,18 +3039,17 @@ ScalarEvolution::getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops,
   return S;
 }
 
-const SCEV *
-ScalarEvolution::getOrCreateMulExpr(ArrayRef<const SCEV *> Ops,
-                                    SCEV::NoWrapFlags Flags) {
+SCEVUse ScalarEvolution::getOrCreateMulExpr(ArrayRef<SCEVUse> Ops,
+                                            SCEV::NoWrapFlags Flags) {
   FoldingSetNodeID ID;
   ID.AddInteger(scMulExpr);
-  for (const SCEV *Op : Ops)
+  for (SCEVUse Op : Ops)
     ID.AddPointer(Op);
   void *IP = nullptr;
   SCEVMulExpr *S =
     static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
   if (!S) {
-    const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
+    SCEVUse *O = SCEVAllocator.Allocate<SCEVUse>(Ops.size());
     std::uninitialized_copy(Ops.begin(), Ops.end(), O);
     S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator),
                                         O, Ops.size());
@@ -3083,11 +3094,11 @@ static uint64_t Choose(uint64_t n, uint64_t k, bool &Overflow) {
 
 /// Determine if any of the operands in this SCEV are a constant or if
 /// any of the add or multiply expressions in this SCEV contain a constant.
-static bool containsConstantInAddMulChain(const SCEV *StartExpr) {
+static bool containsConstantInAddMulChain(SCEVUse StartExpr) {
   struct FindConstantInAddMulChain {
     bool FoundConstant = false;
 
-    bool follow(const SCEV *S) {
+    bool follow(SCEVUse S) {
       FoundConstant |= isa<SCEVConstant>(S);
       return isa<SCEVAddExpr>(S) || isa<SCEVMulExpr>(S);
     }
@@ -3104,9 +3115,16 @@ static bool containsConstantInAddMulChain(const SCEV *StartExpr) {
 }
 
 /// Get a canonical multiply expression, or something simpler if possible.
-const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
-                                        SCEV::NoWrapFlags OrigFlags,
-                                        unsigned Depth) {
+SCEVUse ScalarEvolution::getMulExpr(ArrayRef<const SCEV *> Ops,
+                                    SCEV::NoWrapFlags OrigFlags,
+                                    unsigned Depth) {
+  SmallVector<SCEVUse> Ops2(Ops);
+  return getMulExpr(Ops2, OrigFlags, Depth);
+}
+
+SCEVUse ScalarEvolution::getMulExpr(SmallVectorImpl<SCEVUse> &Ops,
+                                    SCEV::NoWrapFlags OrigFlags,
+                                    unsigned Depth) {
   assert(OrigFlags == maskFlags(OrigFlags, SCEV::FlagNUW | SCEV::FlagNSW) &&
          "only nuw or nsw allowed");
   assert(!Ops.empty() && "Cannot get empty mul!");
@@ -3150,7 +3168,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
   }
 
   // Delay expensive flag strengthening until necessary.
-  auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) {
+  auto ComputeFlags = [this, OrigFlags](const ArrayRef<SCEVUse> Ops) {
     return StrengthenNoWrapFlags(this, scMulExpr, Ops, OrigFlags);
   };
 
@@ -3177,10 +3195,10 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
         // profitable; for example, Add = (C0 + X) * Y + Z.  Maybe the scope of
         // this transformation should be narrowed down.
         if (Add->getNumOperands() == 2 && containsConstantInAddMulChain(Add)) {
-          const SCEV *LHS = getMulExpr(LHSC, Add->getOperand(0),
-                                       SCEV::FlagAnyWrap, Depth + 1);
-          const SCEV *RHS = getMulExpr(LHSC, Add->getOperand(1),
-                                       SCEV::FlagAnyWrap, Depth + 1);
+          SCEVUse LHS = getMulExpr(LHSC, Add->getOperand(0), SCEV::FlagAnyWrap,
+                                   Depth + 1);
+          SCEVUse RHS = getMulExpr(LHSC, Add->getOperand(1), SCEV::FlagAnyWrap,
+                                   Depth + 1);
           return getAddExpr(LHS, RHS, SCEV::FlagAnyWrap, Depth + 1);
         }
 
@@ -3188,11 +3206,11 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
         // If we have a mul by -1 of an add, try distributing the -1 among the
         // add operands.
         if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[1])) {
-          SmallVector<const SCEV *, 4> NewOps;
+          SmallVector<SCEVUse, 4> NewOps;
           bool AnyFolded = false;
-          for (const SCEV *AddOp : Add->operands()) {
-            const SCEV *Mul = getMulExpr(Ops[0], AddOp, SCEV::FlagAnyWrap,
-                                         Depth + 1);
+          for (SCEVUse AddOp : Add->operands()) {
+            SCEVUse Mul =
+                getMulExpr(Ops[0], AddOp, SCEV::FlagAnyWrap, Depth + 1);
             if (!isa<SCEVMulExpr>(Mul)) AnyFolded = true;
             NewOps.push_back(Mul);
           }
@@ -3200,8 +3218,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
             return getAddExpr(NewOps, SCEV::FlagAnyWrap, Depth + 1);
         } else if (const auto *AddRec = dyn_cast<SCEVAddRecExpr>(Ops[1])) {
           // Negation preserves a recurrence's no self-wrap property.
-          SmallVector<const SCEV *, 4> Operands;
-          for (const SCEV *AddRecOp : AddRec->operands())
+          SmallVector<SCEVUse, 4> Operands;
+          for (SCEVUse AddRecOp : AddRec->operands())
             Operands.push_back(getMulExpr(Ops[0], AddRecOp, SCEV::FlagAnyWrap,
                                           Depth + 1));
           // Let M be the minimum representable signed value. AddRec with nsw
@@ -3257,7 +3275,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
   for (; Idx < Ops.size() && isa<SCEVAddRecExpr>(Ops[Idx]); ++Idx) {
     // Scan all of the other operands to this mul and add them to the vector
     // if they are loop invariant w.r.t. the recurrence.
-    SmallVector<const SCEV *, 8> LIOps;
+    SmallVector<SCEVUse, 8> LIOps;
     const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
     for (unsigned i = 0, e = Ops.size(); i != e; ++i)
       if (isAvailableAtLoopEntry(Ops[i], AddRec->getLoop())) {
@@ -3269,9 +3287,9 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
     // If we found some loop invariants, fold them into the recurrence.
     if (!LIOps.empty()) {
       //  NLI * LI * {Start,+,Step}  -->  NLI * {LI*Start,+,LI*Step}
-      SmallVector<const SCEV *, 4> NewOps;
+      SmallVector<SCEVUse, 4> NewOps;
       NewOps.reserve(AddRec->getNumOperands());
-      const SCEV *Scale = getMulExpr(LIOps, SCEV::FlagAnyWrap, Depth + 1);
+      SCEVUse Scale = getMulExpr(LIOps, SCEV::FlagAnyWrap, Depth + 1);
 
       // If both the mul and addrec are nuw, we can preserve nuw.
       // If both the mul and addrec are nsw, we can only preserve nsw if either
@@ -3293,7 +3311,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
         }
       }
 
-      const SCEV *NewRec = getAddRecExpr(NewOps, AddRec->getLoop(), Flags);
+      SCEVUse NewRec = getAddRecExpr(NewOps, AddRec->getLoop(), Flags);
 
       // If all of the other operands were loop invariant, we are done.
       if (Ops.size() == 1) return NewRec;
@@ -3339,10 +3357,10 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
       bool Overflow = false;
       Type *Ty = AddRec->getType();
       bool LargerThan64Bits = getTypeSizeInBits(Ty) > 64;
-      SmallVector<const SCEV*, 7> AddRecOps;
+      SmallVector<SCEVUse, 7> AddRecOps;
       for (int x = 0, xe = AddRec->getNumOperands() +
              OtherAddRec->getNumOperands() - 1; x != xe && !Overflow; ++x) {
-        SmallVector <const SCEV *, 7> SumOps;
+        SmallVector<SCEVUse, 7> SumOps;
         for (int y = x, ye = 2*x+1; y != ye && !Overflow; ++y) {
           uint64_t Coeff1 = Choose(x, 2*x - y, Overflow);
           for (int z = std::max(y-x, y-(int)AddRec->getNumOperands()+1),
@@ -3354,9 +3372,9 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
               Coeff = umul_ov(Coeff1, Coeff2, Overflow);
             else
               Coeff = Coeff1*Coeff2;
-            const SCEV *CoeffTerm = getConstant(Ty, Coeff);
-            const SCEV *Term1 = AddRec->getOperand(y-z);
-            const SCEV *Term2 = OtherAddRec->getOperand(z);
+            SCEVUse CoeffTerm = getConstant(Ty, Coeff);
+            SCEVUse Term1 = AddRec->getOperand(y - z);
+            SCEVUse Term2 = OtherAddRec->getOperand(z);
             SumOps.push_back(getMulExpr(CoeffTerm, Term1, Term2,
                                         SCEV::FlagAnyWrap, Depth + 1));
           }
@@ -3366,8 +3384,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
         AddRecOps.push_back(getAddExpr(SumOps, SCEV::FlagAnyWrap, Depth + 1));
       }
       if (!Overflow) {
-        const SCEV *NewAddRec = getAddRecExpr(AddRecOps, AddRec->getLoop(),
-                                              SCEV::FlagAnyWrap);
+        SCEVUse NewAddRec =
+            getAddRecExpr(AddRecOps, AddRec->getLoop(), SCEV::FlagAnyWrap);
         if (Ops.size() == 2) return NewAddRec;
         Ops[Idx] = NewAddRec;
         Ops.erase(Ops.begin() + OtherIdx); --OtherIdx;
@@ -3390,8 +3408,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
 }
 
 /// Represents an unsigned remainder expression based on unsigned division.
-const SCEV *ScalarEvolution::getURemExpr(const SCEV *LHS,
-                                         const SCEV *RHS) {
+SCEVUse ScalarEvolution::getURemExpr(SCEVUse LHS, SCEVUse RHS) {
   assert(getEffectiveSCEVType(LHS->getType()) ==
          getEffectiveSCEVType(RHS->getType()) &&
          "SCEVURemExpr operand types don't match!");
@@ -3412,15 +3429,14 @@ const SCEV *ScalarEvolution::getURemExpr(const SCEV *LHS,
   }
 
   // Fallback to %a == %x urem %y == %x -<nuw> ((%x udiv %y) *<nuw> %y)
-  const SCEV *UDiv = getUDivExpr(LHS, RHS);
-  const SCEV *Mult = getMulExpr(UDiv, RHS, SCEV::FlagNUW);
+  SCEVUse UDiv = getUDivExpr(LHS, RHS);
+  SCEVUse Mult = getMulExpr(UDiv, RHS, SCEV::FlagNUW);
   return getMinusSCEV(LHS, Mult, SCEV::FlagNUW);
 }
 
 /// Get a canonical unsigned division expression, or something simpler if
 /// possible.
-const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
-                                         const SCEV *RHS) {
+SCEVUse ScalarEvolution::getUDivExpr(SCEVUse LHS, SCEVUse RHS) {
   assert(!LHS->getType()->isPointerTy() &&
          "SCEVUDivExpr operand can't be pointer!");
   assert(LHS->getType() == RHS->getType() &&
@@ -3431,7 +3447,7 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
   ID.AddPointer(LHS);
   ID.AddPointer(RHS);
   void *IP = nullptr;
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
     return S;
 
   // 0 udiv Y == 0
@@ -3469,8 +3485,8 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
               getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
                             getZeroExtendExpr(Step, ExtTy),
                             AR->getLoop(), SCEV::FlagAnyWrap)) {
-            SmallVector<const SCEV *, 4> Operands;
-            for (const SCEV *Op : AR->operands())
+            SmallVector<SCEVUse, 4> Operands;
+            for (SCEVUse Op : AR->operands())
               Operands.push_back(getUDivExpr(Op, RHS));
             return getAddRecExpr(Operands, AR->getLoop(), SCEV::FlagNW);
           }
@@ -3486,9 +3502,8 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
             const APInt &StartInt = StartC->getAPInt();
             const APInt &StartRem = StartInt.urem(StepInt);
             if (StartRem != 0) {
-              const SCEV *NewLHS =
-                  getAddRecExpr(getConstant(StartInt - StartRem), Step,
-                                AR->getLoop(), SCEV::FlagNW);
+              SCEVUse NewLHS = getAddRecExpr(getConstant(StartInt - StartRem),
+                                             Step, AR->getLoop(), SCEV::FlagNW);
               if (LHS != NewLHS) {
                 LHS = NewLHS;
 
@@ -3499,7 +3514,7 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
                 ID.AddPointer(LHS);
                 ID.AddPointer(RHS);
                 IP = nullptr;
-                if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+                if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
                   return S;
               }
             }
@@ -3507,16 +3522,16 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
         }
       // (A*B)/C --> A*(B/C) if safe and B/C can be folded.
       if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(LHS)) {
-        SmallVector<const SCEV *, 4> Operands;
-        for (const SCEV *Op : M->operands())
+        SmallVector<SCEVUse, 4> Operands;
+        for (SCEVUse Op : M->operands())
           Operands.push_back(getZeroExtendExpr(Op, ExtTy));
         if (getZeroExtendExpr(M, ExtTy) == getMulExpr(Operands))
           // Find an operand that's safely divisible.
           for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) {
-            const SCEV *Op = M->getOperand(i);
-            const SCEV *Div = getUDivExpr(Op, RHSC);
+            SCEVUse Op = M->getOperand(i);
+            SCEVUse Div = getUDivExpr(Op, RHSC);
             if (!isa<SCEVUDivExpr>(Div) && getMulExpr(Div, RHSC) == Op) {
-              Operands = SmallVector<const SCEV *, 4>(M->operands());
+              Operands = SmallVector<SCEVUse, 4>(M->operands());
               Operands[i] = Div;
               return getMulExpr(Operands);
             }
@@ -3539,13 +3554,13 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
 
       // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded.
       if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(LHS)) {
-        SmallVector<const SCEV *, 4> Operands;
-        for (const SCEV *Op : A->operands())
+        SmallVector<SCEVUse, 4> Operands;
+        for (SCEVUse Op : A->operands())
           Operands.push_back(getZeroExtendExpr(Op, ExtTy));
         if (getZeroExtendExpr(A, ExtTy) == getAddExpr(Operands)) {
           Operands.clear();
           for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) {
-            const SCEV *Op = getUDivExpr(A->getOperand(i), RHS);
+            SCEVUse Op = getUDivExpr(A->getOperand(i), RHS);
             if (isa<SCEVUDivExpr>(Op) ||
                 getMulExpr(Op, RHS) != A->getOperand(i))
               break;
@@ -3565,7 +3580,8 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
   // The Insertion Point (IP) might be invalid by now (due to UniqueSCEVs
   // changes). Make sure we get a new one.
   IP = nullptr;
-  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
+  if (SCEVUse S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return S;
   SCEV *S = new (SCEVAllocator) SCEVUDivExpr(ID.Intern(SCEVAllocator),
                                              LHS, RHS);
   UniqueSCEVs.InsertNode(S, IP);
@@ -3591,8 +3607,7 @@ APInt gcd(const SCEVConstant *C1, const SCEVConstant *C2) {
 /// possible. There is no representation for an exact udiv in SCEV IR, but we
 /// can attempt to remove factors from the LHS and RHS.  We can't do this when
 /// it's not exact because the udiv may be clearing bits.
-const SCEV *ScalarEvolution::getUDivExactExpr(const SCEV *LHS,
-                                              const SCEV *RHS) {
+SCEVUse ScalarEvolution::getUDivExactExpr(SCEVUse LHS, SCEVUse RHS) {
   // TODO: we could try to find factors in all sorts of things, but for now we
   // just deal with u/exact (multiply, constant). See SCEVDivision towards the
   // end of this file for inspiration.
@@ -3606,7 +3621,7 @@ const SCEV *ScalarEvolution::getUDivExactExpr(const SCEV *LHS,
     // first element of the mulexpr.
     if (const auto *LHSCst = dyn_cast<SCEVConstant>(Mul->getOperand(0))) {
       if (LHSCst == RHSCst) {
-        SmallVector<const SCEV *, 2> Operands(drop_begin(Mul->operands()));
+        SmallVector<SCEVUse, 2> Operands(drop_begin(Mul->operands()));
         return getMulExpr(Operands);
       }
 
@@ -3619,7 +3634,7 @@ const SCEV *ScalarEvolution::getUDivExactExpr(const SCEV *LHS,
             cast<SCEVConstant>(getConstant(LHSCst->getAPInt().udiv(Factor)));
         RHSCst =
             cast<SCEVConstant>(getConstant(RHSCst->getAPInt().udiv(Factor)));
-        SmallVector<const SCEV *, 2> Operands;
+        SmallVector<SCEVUse, 2> Operands;
         Operands.push_back(LHSCst);
         append_range(Operands, Mul->operands().drop_front());
         LHS = getMulExpr(Operands);
@@ -3633,7 +3648,7 @@ const SCEV *ScalarEvolution::getUDivExactExpr(const SCEV *LHS,
 
   for (int i = 0, e = Mul->getNumOperands(); i != e; ++i) {
     if (Mul->getOperand(i) == RHS) {
-      SmallVector<const SCEV *, 2> Operands;
+      SmallVector<SCEVUse, 2> Operands;
       append_range(Operands, Mul->operands().take_front(i));
       append_range(Operands, Mul->operands().drop_front(i + 1));
       return getMulExpr(Operands);
@@ -3645,10 +3660,9 @@ const SCEV *ScalarEvolution::getUDivExactExpr(const SCEV *LHS,
 
 /// Get an add recurrence expression for the specified loop.  Simplify the
 /// expression as much as possible.
-const SCEV *ScalarEvolution::getAddRecExpr(const SCEV *Start, const SCEV *Step,
-                                           const Loop *L,
-                                           SCEV::NoWrapFlags Flags) {
-  SmallVector<const SCEV *, 4> Operands;
+SCEVUse ScalarEvolution::getAddRecExpr(SCEVUse Start, SCEVUse Step,
+                                       const Loop *L, SCEV::NoWrapFlags Flags) {
+  SmallVector<SCEVUse, 4> Operands;
   Operands.push_back(Start);
   if (const SCEVAddRecExpr *StepChrec = dyn_cast<SCEVAddRecExpr>(Step))
     if (StepChrec->getLoop() == L) {
@@ -3660,11 +3674,16 @@ const SCEV *ScalarEvolution::getAddRecExpr(const SCEV *Start, const SCEV *Step,
   return getAddRecExpr(Operands, L, Flags);
 }
 
+SCEVUse ScalarEvolution::getAddRecExpr(ArrayRef<const SCEV *> Operands,
+                                       const Loop *L, SCEV::NoWrapFlags Flags) {
+  SmallVector<SCEVUse> Ops2(Operands);
+  return getAddRecExpr(Ops2, L, Flags);
+}
+
 /// Get an add recurrence expression for the specified loop.  Simplify the
 /// expression as much as possible.
-const SCEV *
-ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
-                               const Loop *L, SCEV::NoWrapFlags Flags) {
+SCEVUse ScalarEvolution::getAddRecExpr(SmallVectorImpl<SCEVUse> &Operands,
+                                       const Loop *L, SCEV::NoWrapFlags Flags) {
   if (Operands.size() == 1) return Operands[0];
 #ifndef NDEBUG
   Type *ETy = getEffectiveSCEVType(Operands[0]->getType());
@@ -3698,13 +3717,13 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
             ? (L->getLoopDepth() < NestedLoop->getLoopDepth())
             : (!NestedLoop->contains(L) &&
                DT.dominates(L->getHeader(), NestedLoop->getHeader()))) {
-      SmallVector<const SCEV *, 4> NestedOperands(NestedAR->operands());
+      SmallVector<SCEVUse, 4> NestedOperands(NestedAR->operands());
       Operands[0] = NestedAR->getStart();
       // AddRecs require their operands be loop-invariant with respect to their
       // loops. Don't perform this transformation if it would break this
       // requirement.
-      bool AllInvariant = all_of(
-          Operands, [&](const SCEV *Op) { return isLoopInvariant(Op, L); });
+      bool AllInvariant =
+          all_of(Operands, [&](SCEVUse Op) { return isLoopInvariant(Op, L); });
 
       if (AllInvariant) {
         // Create a recurrence for the outer loop with the same step size.
@@ -3715,7 +3734,7 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
           maskFlags(Flags, SCEV::FlagNW | NestedAR->getNoWrapFlags());
 
         NestedOperands[0] = getAddRecExpr(Operands, L, OuterFlags);
-        AllInvariant = all_of(NestedOperands, [&](const SCEV *Op) {
+        AllInvariant = all_of(NestedOperands, [&](SCEVUse Op) {
           return isLoopInvariant(Op, NestedLoop);
         });
 
@@ -3739,10 +3758,15 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
   return getOrCreateAddRecExpr(Operands, L, Flags);
 }
 
-const SCEV *
+SCEVUse ScalarEvolution::getGEPExpr(GEPOperator *GEP,
+                                    ArrayRef<const SCEV *> IndexExprs) {
+  return getGEPExpr(GEP, SmallVector<SCEVUse>(IndexExprs));
+}
+
+SCEVUse
 ScalarEvolution::getGEPExpr(GEPOperator *GEP,
-                            const SmallVectorImpl<const SCEV *> &IndexExprs) {
-  const SCEV *BaseExpr = getSCEV(GEP->getPointerOperand());
+                            const SmallVectorImpl<SCEVUse> &IndexExprs) {
+  SCEVUse BaseExpr = getSCEV(GEP->getPointerOperand());
   // getSCEV(Base)->getType() has the same address space as Base->getType()
   // because SCEV::getType() preserves the address space.
   Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
@@ -3764,14 +3788,14 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
 
   Type *CurTy = GEP->getType();
   bool FirstIter = true;
-  SmallVector<const SCEV *, 4> Offsets;
-  for (const SCEV *IndexExpr : IndexExprs) {
+  SmallVector<SCEVUse, 4> Offsets;
+  for (SCEVUse IndexExpr : IndexExprs) {
     // Compute the (potentially symbolic) offset in bytes for this index.
     if (StructType *STy = dyn_cast<StructType>(CurTy)) {
       // For a struct, add the member offset.
       ConstantInt *Index = cast<SCEVConstant>(IndexExpr)->getValue();
       unsigned FieldNo = Index->getZExtValue();
-      const SCEV *FieldOffset = getOffsetOfExpr(IntIdxTy, STy, FieldNo);
+      SCEVUse FieldOffset = getOffsetOfExpr(IntIdxTy, STy, FieldNo);
       Offsets.push_back(FieldOffset);
 
       // Update CurTy to the type of the field at Index.
@@ -3787,12 +3811,12 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
         CurTy = GetElementPtrInst::getTypeAtIndex(CurTy, (uint64_t)0);
       }
       // For an array, add the element offset, explicitly scaled.
-      const SCEV *ElementSize = getSizeOfExpr(IntIdxTy, CurTy);
+      SCEVUse ElementSize = getSizeOfExpr(IntIdxTy, CurTy);
       // Getelementptr indices are signed.
       IndexExpr = getTruncateOrSignExtend(IndexExpr, IntIdxTy);
 
       // Multiply the index by the element size to compute the element offset.
-      const SCEV *LocalOffset = getMulExpr(IndexExpr, ElementSize, OffsetWrap);
+      SCEVUse LocalOffset = getMulExpr(IndexExpr, ElementSize, OffsetWrap);
       Offsets.push_back(LocalOffset);
     }
   }
@@ -3802,35 +3826,41 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
     return BaseExpr;
 
   // Add the offsets together, assuming nsw if inbounds.
-  const SCEV *Offset = getAddExpr(Offsets, OffsetWrap);
+  SCEVUse Offset = getAddExpr(Offsets, OffsetWrap);
   // Add the base address and the offset. We cannot use the nsw flag, as the
   // base address is unsigned. However, if we know that the offset is
   // non-negative, we can use nuw.
   SCEV::NoWrapFlags BaseWrap = AssumeInBoundsFlags && isKnownNonNegative(Offset)
                                    ? SCEV::FlagNUW : SCEV::FlagAnyWrap;
-  auto *GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
+  auto GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
   assert(BaseExpr->getType() == GEPExpr->getType() &&
          "GEP should not change type mid-flight.");
   return GEPExpr;
 }
 
 SCEV *ScalarEvolution::findExistingSCEVInCache(SCEVTypes SCEVType,
-                                               ArrayRef<const SCEV *> Ops) {
+                                               ArrayRef<SCEVUse> Ops) {
   FoldingSetNodeID ID;
   ID.AddInteger(SCEVType);
-  for (const SCEV *Op : Ops)
+  for (SCEVUse Op : Ops)
     ID.AddPointer(Op);
   void *IP = nullptr;
   return UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
 }
 
-const SCEV *ScalarEvolution::getAbsExpr(const SCEV *Op, bool IsNSW) {
+SCEVUse ScalarEvolution::getAbsExpr(SCEVUse Op, bool IsNSW) {
   SCEV::NoWrapFlags Flags = IsNSW ? SCEV::FlagNSW : SCEV::FlagAnyWrap;
   return getSMaxExpr(Op, getNegativeSCEV(Op, Flags));
 }
 
-const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind,
-                                           SmallVectorImpl<const SCEV *> &Ops) {
+SCEVUse ScalarEvolution::getMinMaxExpr(SCEVTypes Kind,
+                                       ArrayRef<const SCEV *> Ops) {
+  SmallVector<SCEVUse> Ops2(Ops);
+  return getMinMaxExpr(Kind, Ops2);
+}
+
+SCEVUse ScalarEvolution::getMinMaxExpr(SCEVTypes Kind,
+                                       SmallVectorImpl<SCEVUse> &Ops) {
   assert(SCEVMinMaxExpr::isMinMaxType(Kind) && "Not a SCEVMinMaxExpr!");
   assert(!Ops.empty() && "Cannot get empty (u|s)(min|max)!");
   if (Ops.size() == 1) return Ops[0];
@@ -3852,7 +3882,7 @@ const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind,
   GroupByComplexity(Ops, &LI, DT);
 
   // Check if we have created the same expression before.
-  if (const SCEV *S = findExistingSCEVInCache(Kind, Ops)) {
+  if (SCEVUse S = findExistingSCEVInCache(Kind, Ops)) {
     return S;
   }
 
@@ -3958,10 +3988,10 @@ const SCEV *ScalarEvolution::getMinMaxExpr(SCEVTypes Kind,
   for (unsigned i = 0, e = Ops.size(); i != e; ++i)
     ID.AddPointer(Ops[i]);
   void *IP = nullptr;
-  const SCEV *ExistingSCEV = UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
+  SCEVUse ExistingSCEV = UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
   if (ExistingSCEV)
     return ExistingSCEV;
-  const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
+  SCEVUse *O = SCEVAllocator.Allocate<SCEVUse>(Ops.size());
   std::uninitialized_copy(Ops.begin(), Ops.end(), O);
   SCEV *S = new (SCEVAllocator)
       SCEVMinMaxExpr(ID.Intern(SCEVAllocator), Kind, O, Ops.size());
@@ -3975,14 +4005,14 @@ namespace {
 
 class SCEVSequentialMinMaxDeduplicatingVisitor final
     : public SCEVVisitor<SCEVSequentialMinMaxDeduplicatingVisitor,
-                         std::optional<const SCEV *>> {
-  using RetVal = std::optional<const SCEV *>;
+                         std::optional<SCEVUse>> {
+  using RetVal = std::optional<SCEVUse>;
   using Base = SCEVVisitor<SCEVSequentialMinMaxDeduplicatingVisitor, RetVal>;
 
   ScalarEvolution &SE;
   const SCEVTypes RootKind; // Must be a sequential min/max expression.
   const SCEVTypes NonSequentialRootKind; // Non-sequential variant of RootKind.
-  SmallPtrSet<const SCEV *, 16> SeenOps;
+  SmallPtrSet<SCEVUse, 16> SeenOps;
 
   bool canRecurseInto(SCEVTypes Kind) const {
     // We can only recurse into the SCEV expression of the same effective type
@@ -3990,7 +4020,7 @@ class SCEVSequentialMinMaxDeduplicatingVisitor final
     return RootKind == Kind || NonSequentialRootKind == Kind;
   };
 
-  RetVal visitAnyMinMaxExpr(const SCEV *S) {
+  RetVal visitAnyMinMaxExpr(SCEVUse S) {
     assert((isa<SCEVMinMaxExpr>(S) || isa<SCEVSequentialMinMaxExpr>(S)) &&
            "Only for min/max expressions.");
     SCEVTypes Kind = S->getSCEVType();
@@ -3999,7 +4029,7 @@ class SCEVSequentialMinMaxDeduplicatingVisitor final
       return S;
 
     auto *NAry = cast<SCEVNAryExpr>(S);
-    SmallVector<const SCEV *> NewOps;
+    SmallVector<SCEVUse> NewOps;
     bool Changed = visit(Kind, NAry->operands(), NewOps);
 
     if (!Changed)
@@ -4012,7 +4042,7 @@ class SCEVSequentialMinMaxDeduplicatingVisitor final
                : SE.getMinMaxExpr(Kind, NewOps);
   }
 
-  RetVal visit(const SCEV *S) {
+  RetVal visit(SCEVUse S) {
     // Has the whole operand been seen already?
     if (!SeenOps.insert(S).second)
       return std::nullopt;
@@ -4027,13 +4057,13 @@ class SCEVSequentialMinMaxDeduplicatingVisitor final
             SCEVSequentialMinMaxExpr::getEquivalentNonSequentialSCEVType(
                 RootKind)) {}
 
-  bool /*Changed*/ visit(SCEVTypes Kind, ArrayRef<const SCEV *> OrigOps,
-                         SmallVectorImpl<const SCEV *> &NewOps) {
+  bool /*Changed*/ visit(SCEVTypes Kind, ArrayRef<SCEVUse> OrigOps,
+                         SmallVectorImpl<SCEVUse> &NewOps) {
     bool Changed = false;
-    SmallVector<const SCEV *> Ops;
+    SmallVector<SCEVUse> Ops;
     Ops.reserve(OrigOps.size());
 
-    for (const SCEV *Op : OrigOps) {
+    for (SCEVUse Op : OrigOps) {
       RetVal NewOp = visit(Op);
       if (NewOp != Op)
         Changed = true;
@@ -4136,7 +4166,7 @@ struct SCEVPoisonCollector {
   SCEVPoisonCollector(bool LookThroughMaybePoisonBlocking)
       : LookThroughMaybePoisonBlocking(LookThroughMaybePoisonBlocking) {}
 
-  bool follow(const SCEV *S) {
+  bool follow(SCEVUse S) {
     if (!LookThroughMaybePoisonBlocking &&
         !scevUnconditionallyPropagatesPoisonFromOperands(S->getSCEVType()))
       return false;
@@ -4152,7 +4182,7 @@ struct SCEVPoisonCollector {
 } // namespace
 
 /// Return true if V is poison given that AssumedPoison is already poison.
-static bool impliesPoison(const SCEV *AssumedPoison, const SCEV *S) {
+static bool impliesPoison(SCEVUse AssumedPoison, SCEVUse S) {
   // First collect all SCEVs that might result in AssumedPoison to be poison.
   // We need to look through potentially poison-blocking operations here,
   // because we want to find all SCEVs that *might* result in poison, not only
@@ -4179,7 +4209,7 @@ static bool impliesPoison(const SCEV *AssumedPoison, const SCEV *S) {
 }
 
 void ScalarEvolution::getPoisonGeneratingValues(
-    SmallPtrSetImpl<const Value *> &Result, const SCEV *S) {
+    SmallPtrSetImpl<const Value *> &Result, SCEVUse S) {
   SCEVPoisonCollector PC(/* LookThroughMaybePoisonBlocking */ false);
   visitAll(S, PC);
   for (const SCEVUnknown *SU : PC.MaybePoison)
@@ -4187,7 +4217,7 @@ void ScalarEvolution::getPoisonGeneratingValues(
 }
 
 bool ScalarEvolution::canReuseInstruction(
-    const SCEV *S, Instruction *I,
+    SCEVUse S, Instruction *I,
     SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts) {
   // If the instruction cannot be poison, it's always safe to reuse.
   if (programUndefinedIfPoison(I))
@@ -4248,9 +4278,9 @@ bool ScalarEvolution::canReuseInstruction(
   return true;
 }
 
-const SCEV *
+SCEVUse
 ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
-                                         SmallVectorImpl<const SCEV *> &Ops) {
+                                         SmallVectorImpl<SCEVUse> &Ops) {
   assert(SCEVSequentialMinMaxExpr::isSequentialMinMaxType(Kind) &&
          "Not a SCEVSequentialMinMaxExpr!");
   assert(!Ops.empty() && "Cannot get empty (u|s)(min|max)!");
@@ -4271,7 +4301,7 @@ ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
   // so we can *NOT* do any kind of sorting of the expressions!
 
   // Check if we have created the same expression before.
-  if (const SCEV *S = findExistingSCEVInCache(Kind, Ops))
+  if (SCEVUse S = findExistingSCEVInCache(Kind, Ops))
     return S;
 
   // FIXME: there are *some* simplifications that we can do here.
@@ -4305,7 +4335,7 @@ ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
       return getSequentialMinMaxExpr(Kind, Ops);
   }
 
-  const SCEV *SaturationPoint;
+  SCEVUse SaturationPoint;
   ICmpInst::Predicate Pred;
   switch (Kind) {
   case scSequentialUMinExpr:
@@ -4323,7 +4353,7 @@ ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
     if (::impliesPoison(Ops[i], Ops[i - 1]) ||
         isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_NE, Ops[i - 1],
                                         SaturationPoint)) {
-      SmallVector<const SCEV *> SeqOps = {Ops[i - 1], Ops[i]};
+      SmallVector<SCEVUse> SeqOps = {Ops[i - 1], Ops[i]};
       Ops[i - 1] = getMinMaxExpr(
           SCEVSequentialMinMaxExpr::getEquivalentNonSequentialSCEVType(Kind),
           SeqOps);
@@ -4345,11 +4375,11 @@ ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
   for (unsigned i = 0, e = Ops.size(); i != e; ++i)
     ID.AddPointer(Ops[i]);
   void *IP = nullptr;
-  const SCEV *ExistingSCEV = UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
+  SCEVUse ExistingSCEV = UniqueSCEVs.FindNodeOrInsertPos(ID, IP);
   if (ExistingSCEV)
     return ExistingSCEV;
 
-  const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
+  SCEVUse *O = SCEVAllocator.Allocate<SCEVUse>(Ops.size());
   std::uninitialized_copy(Ops.begin(), Ops.end(), O);
   SCEV *S = new (SCEVAllocator)
       SCEVSequentialMinMaxExpr(ID.Intern(SCEVAllocator), Kind, O, Ops.size());
@@ -4359,65 +4389,62 @@ ScalarEvolution::getSequentialMinMaxExpr(SCEVTypes Kind,
   return S;
 }
 
-const SCEV *ScalarEvolution::getSMaxExpr(const SCEV *LHS, const SCEV *RHS) {
-  SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
+SCEVUse ScalarEvolution::getSMaxExpr(SCEVUse LHS, SCEVUse RHS) {
+  SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
   return getSMaxExpr(Ops);
 }
 
-const SCEV *ScalarEvolution::getSMaxExpr(SmallVectorImpl<const SCEV *> &Ops) {
+SCEVUse ScalarEvolution::getSMaxExpr(SmallVectorImpl<SCEVUse> &Ops) {
   return getMinMaxExpr(scSMaxExpr, Ops);
 }
 
-const SCEV *ScalarEvolution::getUMaxExpr(const SCEV *LHS, const SCEV *RHS) {
-  SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
+SCEVUse ScalarEvolution::getUMaxExpr(SCEVUse LHS, SCEVUse RHS) {
+  SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
   return getUMaxExpr(Ops);
 }
 
-const SCEV *ScalarEvolution::getUMaxExpr(SmallVectorImpl<const SCEV *> &Ops) {
+SCEVUse ScalarEvolution::getUMaxExpr(SmallVectorImpl<SCEVUse> &Ops) {
   return getMinMaxExpr(scUMaxExpr, Ops);
 }
 
-const SCEV *ScalarEvolution::getSMinExpr(const SCEV *LHS,
-                                         const SCEV *RHS) {
-  SmallVector<const SCEV *, 2> Ops = { LHS, RHS };
+SCEVUse ScalarEvolution::getSMinExpr(SCEVUse LHS, SCEVUse RHS) {
+  SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
   return getSMinExpr(Ops);
 }
 
-const SCEV *ScalarEvolution::getSMinExpr(SmallVectorImpl<const SCEV *> &Ops) {
+SCEVUse ScalarEvolution::getSMinExpr(SmallVectorImpl<SCEVUse> &Ops) {
   return getMinMaxExpr(scSMinExpr, Ops);
 }
 
-const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, const SCEV *RHS,
-                                         bool Sequential) {
-  SmallVector<const SCEV *, 2> Ops = { LHS, RHS };
+SCEVUse ScalarEvolution::getUMinExpr(SCEVUse LHS, SCEVUse RHS,
+                                     bool Sequential) {
+  SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
   return getUMinExpr(Ops, Sequential);
 }
 
-const SCEV *ScalarEvolution::getUMinExpr(SmallVectorImpl<const SCEV *> &Ops,
-                                         bool Sequential) {
+SCEVUse ScalarEvolution::getUMinExpr(SmallVectorImpl<SCEVUse> &Ops,
+                                     bool Sequential) {
   return Sequential ? getSequentialMinMaxExpr(scSequentialUMinExpr, Ops)
                     : getMinMaxExpr(scUMinExpr, Ops);
 }
 
-const SCEV *
-ScalarEvolution::getSizeOfExpr(Type *IntTy, TypeSize Size) {
-  const SCEV *Res = getConstant(IntTy, Size.getKnownMinValue());
+SCEVUse ScalarEvolution::getSizeOfExpr(Type *IntTy, TypeSize Size) {
+  SCEVUse Res = getConstant(IntTy, Size.getKnownMinValue());
   if (Size.isScalable())
     Res = getMulExpr(Res, getVScale(IntTy));
   return Res;
 }
 
-const SCEV *ScalarEvolution::getSizeOfExpr(Type *IntTy, Type *AllocTy) {
+SCEVUse ScalarEvolution::getSizeOfExpr(Type *IntTy, Type *AllocTy) {
   return getSizeOfExpr(IntTy, getDataLayout().getTypeAllocSize(AllocTy));
 }
 
-const SCEV *ScalarEvolution::getStoreSizeOfExpr(Type *IntTy, Type *StoreTy) {
+SCEVUse ScalarEvolution::getStoreSizeOfExpr(Type *IntTy, Type *StoreTy) {
   return getSizeOfExpr(IntTy, getDataLayout().getTypeStoreSize(StoreTy));
 }
 
-const SCEV *ScalarEvolution::getOffsetOfExpr(Type *IntTy,
-                                             StructType *STy,
-                                             unsigned FieldNo) {
+SCEVUse ScalarEvolution::getOffsetOfExpr(Type *IntTy, StructType *STy,
+                                         unsigned FieldNo) {
   // We can bypass creating a target-independent constant expression and then
   // folding it back into a ConstantInt. This is just a compile-time
   // optimization.
@@ -4427,7 +4454,7 @@ const SCEV *ScalarEvolution::getOffsetOfExpr(Type *IntTy,
   return getConstant(IntTy, SL->getElementOffset(FieldNo));
 }
 
-const SCEV *ScalarEvolution::getUnknown(Value *V) {
+SCEVUse ScalarEvolution::getUnknown(Value *V) {
   // Don't attempt to do anything other than create a SCEVUnknown object
   // here.  createSCEV only calls getUnknown after checking for all other
   // interesting possibilities, and any other code that calls getUnknown
@@ -4489,8 +4516,7 @@ Type *ScalarEvolution::getWiderType(Type *T1, Type *T2) const {
   return  getTypeSizeInBits(T1) >= getTypeSizeInBits(T2) ? T1 : T2;
 }
 
-bool ScalarEvolution::instructionCouldExistWithOperands(const SCEV *A,
-                                                        const SCEV *B) {
+bool ScalarEvolution::instructionCouldExistWithOperands(SCEVUse A, SCEVUse B) {
   /// For a valid use point to exist, the defining scope of one operand
   /// must dominate the other.
   bool PreciseA, PreciseB;
@@ -4503,12 +4529,10 @@ bool ScalarEvolution::instructionCouldExistWithOperands(const SCEV *A,
     DT.dominates(ScopeB, ScopeA);
 }
 
-const SCEV *ScalarEvolution::getCouldNotCompute() {
-  return CouldNotCompute.get();
-}
+SCEVUse ScalarEvolution::getCouldNotCompute() { return CouldNotCompute.get(); }
 
-bool ScalarEvolution::checkValidity(const SCEV *S) const {
-  bool ContainsNulls = SCEVExprContains(S, [](const SCEV *S) {
+bool ScalarEvolution::checkValidity(SCEVUse S) const {
+  bool ContainsNulls = SCEVExprContains(S, [](SCEVUse S) {
     auto *SU = dyn_cast<SCEVUnknown>(S);
     return SU && SU->getValue() == nullptr;
   });
@@ -4516,20 +4540,20 @@ bool ScalarEvolution::checkValidity(const SCEV *S) const {
   return !ContainsNulls;
 }
 
-bool ScalarEvolution::containsAddRecurrence(const SCEV *S) {
+bool ScalarEvolution::containsAddRecurrence(SCEVUse S) {
   HasRecMapType::iterator I = HasRecMap.find(S);
   if (I != HasRecMap.end())
     return I->second;
 
   bool FoundAddRec =
-      SCEVExprContains(S, [](const SCEV *S) { return isa<SCEVAddRecExpr>(S); });
+      SCEVExprContains(S, [](SCEVUse S) { return isa<SCEVAddRecExpr>(S); });
   HasRecMap.insert({S, FoundAddRec});
   return FoundAddRec;
 }
 
 /// Return the ValueOffsetPair set for \p S. \p S can be represented
 /// by the value and offset from any ValueOffsetPair in the set.
-ArrayRef<Value *> ScalarEvolution::getSCEVValues(const SCEV *S) {
+ArrayRef<Value *> ScalarEvolution::getSCEVValues(SCEVUse S) {
   ExprValueMapType::iterator SI = ExprValueMap.find_as(S);
   if (SI == ExprValueMap.end())
     return std::nullopt;
@@ -4550,7 +4574,7 @@ void ScalarEvolution::eraseValueFromMap(Value *V) {
   }
 }
 
-void ScalarEvolution::insertValueToMap(Value *V, const SCEV *S) {
+void ScalarEvolution::insertValueToMap(Value *V, SCEVUse S) {
   // A recursive query may have already computed the SCEV. It should be
   // equivalent, but may not necessarily be exactly the same, e.g. due to lazily
   // inferred nowrap flags.
@@ -4563,20 +4587,20 @@ void ScalarEvolution::insertValueToMap(Value *V, const SCEV *S) {
 
 /// Return an existing SCEV if it exists, otherwise analyze the expression and
 /// create a new one.
-const SCEV *ScalarEvolution::getSCEV(Value *V) {
+SCEVUse ScalarEvolution::getSCEV(Value *V) {
   assert(isSCEVable(V->getType()) && "Value is not SCEVable!");
 
-  if (const SCEV *S = getExistingSCEV(V))
+  if (SCEVUse S = getExistingSCEV(V))
     return S;
   return createSCEVIter(V);
 }
 
-const SCEV *ScalarEvolution::getExistingSCEV(Value *V) {
+SCEVUse ScalarEvolution::getExistingSCEV(Value *V) {
   assert(isSCEVable(V->getType()) && "Value is not SCEVable!");
 
   ValueExprMapType::iterator I = ValueExprMap.find_as(V);
   if (I != ValueExprMap.end()) {
-    const SCEV *S = I->second;
+    SCEVUse S = I->second;
     assert(checkValidity(S) &&
            "existing SCEV has not been properly invalidated");
     return S;
@@ -4585,8 +4609,7 @@ const SCEV *ScalarEvolution::getExistingSCEV(Value *V) {
 }
 
 /// Return a SCEV corresponding to -V = -1*V
-const SCEV *ScalarEvolution::getNegativeSCEV(const SCEV *V,
-                                             SCEV::NoWrapFlags Flags) {
+SCEVUse ScalarEvolution::getNegativeSCEV(SCEVUse V, SCEV::NoWrapFlags Flags) {
   if (const SCEVConstant *VC = dyn_cast<SCEVConstant>(V))
     return getConstant(
                cast<ConstantInt>(ConstantExpr::getNeg(VC->getValue())));
@@ -4597,7 +4620,7 @@ const SCEV *ScalarEvolution::getNegativeSCEV(const SCEV *V,
 }
 
 /// If Expr computes ~A, return A else return nullptr
-static const SCEV *MatchNotExpr(const SCEV *Expr) {
+static SCEVUse MatchNotExpr(SCEVUse Expr) {
   const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Expr);
   if (!Add || Add->getNumOperands() != 2 ||
       !Add->getOperand(0)->isAllOnesValue())
@@ -4612,7 +4635,7 @@ static const SCEV *MatchNotExpr(const SCEV *Expr) {
 }
 
 /// Return a SCEV corresponding to ~V = -1-V
-const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) {
+SCEVUse ScalarEvolution::getNotSCEV(SCEVUse V) {
   assert(!V->getType()->isPointerTy() && "Can't negate pointer");
 
   if (const SCEVConstant *VC = dyn_cast<SCEVConstant>(V))
@@ -4622,17 +4645,17 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) {
   // Fold ~(u|s)(min|max)(~x, ~y) to (u|s)(max|min)(x, y)
   if (const SCEVMinMaxExpr *MME = dyn_cast<SCEVMinMaxExpr>(V)) {
     auto MatchMinMaxNegation = [&](const SCEVMinMaxExpr *MME) {
-      SmallVector<const SCEV *, 2> MatchedOperands;
-      for (const SCEV *Operand : MME->operands()) {
-        const SCEV *Matched = MatchNotExpr(Operand);
+      SmallVector<SCEVUse, 2> MatchedOperands;
+      for (SCEVUse Operand : MME->operands()) {
+        SCEVUse Matched = MatchNotExpr(Operand);
         if (!Matched)
-          return (const SCEV *)nullptr;
+          return (SCEVUse) nullptr;
         MatchedOperands.push_back(Matched);
       }
       return getMinMaxExpr(SCEVMinMaxExpr::negate(MME->getSCEVType()),
                            MatchedOperands);
     };
-    if (const SCEV *Replaced = MatchMinMaxNegation(MME))
+    if (SCEVUse Replaced = MatchMinMaxNegation(MME))
       return Replaced;
   }
 
@@ -4641,12 +4664,12 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) {
   return getMinusSCEV(getMinusOne(Ty), V);
 }
 
-const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
+SCEVUse ScalarEvolution::removePointerBase(SCEVUse P) {
   assert(P->getType()->isPointerTy());
 
   if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(P)) {
     // The base of an AddRec is the first operand.
-    SmallVector<const SCEV *> Ops{AddRec->operands()};
+    SmallVector<SCEVUse> Ops{AddRec->operands()};
     Ops[0] = removePointerBase(Ops[0]);
     // Don't try to transfer nowrap flags for now. We could in some cases
     // (for example, if pointer operand of the AddRec is a SCEVUnknown).
@@ -4654,9 +4677,9 @@ const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
   }
   if (auto *Add = dyn_cast<SCEVAddExpr>(P)) {
     // The base of an Add is the pointer operand.
-    SmallVector<const SCEV *> Ops{Add->operands()};
-    const SCEV **PtrOp = nullptr;
-    for (const SCEV *&AddOp : Ops) {
+    SmallVector<SCEVUse> Ops{Add->operands()};
+    SCEVUse *PtrOp = nullptr;
+    for (SCEVUse &AddOp : Ops) {
       if (AddOp->getType()->isPointerTy()) {
         assert(!PtrOp && "Cannot have multiple pointer ops");
         PtrOp = &AddOp;
@@ -4671,9 +4694,8 @@ const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
   return getZero(P->getType());
 }
 
-const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
-                                          SCEV::NoWrapFlags Flags,
-                                          unsigned Depth) {
+SCEVUse ScalarEvolution::getMinusSCEV(SCEVUse LHS, SCEVUse RHS,
+                                      SCEV::NoWrapFlags Flags, unsigned Depth) {
   // Fast path: X - X --> 0.
   if (LHS == RHS)
     return getZero(LHS->getType());
@@ -4721,8 +4743,8 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
   return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags, Depth);
 }
 
-const SCEV *ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
-                                                     unsigned Depth) {
+SCEVUse ScalarEvolution::getTruncateOrZeroExtend(SCEVUse V, Type *Ty,
+                                                 unsigned Depth) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot truncate or zero extend with non-integer arguments!");
@@ -4733,8 +4755,8 @@ const SCEV *ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
   return getZeroExtendExpr(V, Ty, Depth);
 }
 
-const SCEV *ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, Type *Ty,
-                                                     unsigned Depth) {
+SCEVUse ScalarEvolution::getTruncateOrSignExtend(SCEVUse V, Type *Ty,
+                                                 unsigned Depth) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot truncate or zero extend with non-integer arguments!");
@@ -4745,8 +4767,7 @@ const SCEV *ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, Type *Ty,
   return getSignExtendExpr(V, Ty, Depth);
 }
 
-const SCEV *
-ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, Type *Ty) {
+SCEVUse ScalarEvolution::getNoopOrZeroExtend(SCEVUse V, Type *Ty) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot noop or zero extend with non-integer arguments!");
@@ -4757,8 +4778,7 @@ ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, Type *Ty) {
   return getZeroExtendExpr(V, Ty);
 }
 
-const SCEV *
-ScalarEvolution::getNoopOrSignExtend(const SCEV *V, Type *Ty) {
+SCEVUse ScalarEvolution::getNoopOrSignExtend(SCEVUse V, Type *Ty) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot noop or sign extend with non-integer arguments!");
@@ -4769,8 +4789,7 @@ ScalarEvolution::getNoopOrSignExtend(const SCEV *V, Type *Ty) {
   return getSignExtendExpr(V, Ty);
 }
 
-const SCEV *
-ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, Type *Ty) {
+SCEVUse ScalarEvolution::getNoopOrAnyExtend(SCEVUse V, Type *Ty) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot noop or any extend with non-integer arguments!");
@@ -4781,8 +4800,7 @@ ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, Type *Ty) {
   return getAnyExtendExpr(V, Ty);
 }
 
-const SCEV *
-ScalarEvolution::getTruncateOrNoop(const SCEV *V, Type *Ty) {
+SCEVUse ScalarEvolution::getTruncateOrNoop(SCEVUse V, Type *Ty) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
          "Cannot truncate or noop with non-integer arguments!");
@@ -4793,10 +4811,9 @@ ScalarEvolution::getTruncateOrNoop(const SCEV *V, Type *Ty) {
   return getTruncateExpr(V, Ty);
 }
 
-const SCEV *ScalarEvolution::getUMaxFromMismatchedTypes(const SCEV *LHS,
-                                                        const SCEV *RHS) {
-  const SCEV *PromotedLHS = LHS;
-  const SCEV *PromotedRHS = RHS;
+SCEVUse ScalarEvolution::getUMaxFromMismatchedTypes(SCEVUse LHS, SCEVUse RHS) {
+  SCEVUse PromotedLHS = LHS;
+  SCEVUse PromotedRHS = RHS;
 
   if (getTypeSizeInBits(LHS->getType()) > getTypeSizeInBits(RHS->getType()))
     PromotedRHS = getZeroExtendExpr(RHS, LHS->getType());
@@ -4806,15 +4823,20 @@ const SCEV *ScalarEvolution::getUMaxFromMismatchedTypes(const SCEV *LHS,
   return getUMaxExpr(PromotedLHS, PromotedRHS);
 }
 
-const SCEV *ScalarEvolution::getUMinFromMismatchedTypes(const SCEV *LHS,
-                                                        const SCEV *RHS,
-                                                        bool Sequential) {
-  SmallVector<const SCEV *, 2> Ops = { LHS, RHS };
+SCEVUse ScalarEvolution::getUMinFromMismatchedTypes(SCEVUse LHS, SCEVUse RHS,
+                                                    bool Sequential) {
+  SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
   return getUMinFromMismatchedTypes(Ops, Sequential);
 }
 
-const SCEV *
-ScalarEvolution::getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
+SCEVUse ScalarEvolution::getUMinFromMismatchedTypes(ArrayRef<const SCEV *> Ops,
+                                                    bool Sequential) {
+  SmallVector<SCEVUse> Ops2(Ops);
+  return getUMinFromMismatchedTypes(Ops2, Sequential);
+}
+
+SCEVUse
+ScalarEvolution::getUMinFromMismatchedTypes(SmallVectorImpl<SCEVUse> &Ops,
                                             bool Sequential) {
   assert(!Ops.empty() && "At least one operand must be!");
   // Trivial case.
@@ -4823,7 +4845,7 @@ ScalarEvolution::getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
 
   // Find the max type first.
   Type *MaxType = nullptr;
-  for (const auto *S : Ops)
+  for (const auto S : Ops)
     if (MaxType)
       MaxType = getWiderType(MaxType, S->getType());
     else
@@ -4831,15 +4853,15 @@ ScalarEvolution::getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
   assert(MaxType && "Failed to find maximum type!");
 
   // Extend all ops to max type.
-  SmallVector<const SCEV *, 2> PromotedOps;
-  for (const auto *S : Ops)
+  SmallVector<SCEVUse, 2> PromotedOps;
+  for (const auto S : Ops)
     PromotedOps.push_back(getNoopOrZeroExtend(S, MaxType));
 
   // Generate umin.
   return getUMinExpr(PromotedOps, Sequential);
 }
 
-const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) {
+SCEVUse ScalarEvolution::getPointerBase(SCEVUse V) {
   // A pointer operand may evaluate to a nonpointer expression, such as null.
   if (!V->getType()->isPointerTy())
     return V;
@@ -4848,8 +4870,8 @@ const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) {
     if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V)) {
       V = AddRec->getStart();
     } else if (auto *Add = dyn_cast<SCEVAddExpr>(V)) {
-      const SCEV *PtrOp = nullptr;
-      for (const SCEV *AddOp : Add->operands()) {
+      SCEVUse PtrOp = nullptr;
+      for (SCEVUse AddOp : Add->operands()) {
         if (AddOp->getType()->isPointerTy()) {
           assert(!PtrOp && "Cannot have multiple pointer ops");
           PtrOp = AddOp;
@@ -4883,10 +4905,10 @@ namespace {
 /// If SCEV contains non-invariant unknown SCEV rewrite cannot be done.
 class SCEVInitRewriter : public SCEVRewriteVisitor<SCEVInitRewriter> {
 public:
-  static const SCEV *rewrite(const SCEV *S, const Loop *L, ScalarEvolution &SE,
-                             bool IgnoreOtherLoops = true) {
+  static SCEVUse rewrite(SCEVUse S, const Loop *L, ScalarEvolution &SE,
+                         bool IgnoreOtherLoops = true) {
     SCEVInitRewriter Rewriter(L, SE);
-    const SCEV *Result = Rewriter.visit(S);
+    SCEVUse Result = Rewriter.visit(S);
     if (Rewriter.hasSeenLoopVariantSCEVUnknown())
       return SE.getCouldNotCompute();
     return Rewriter.hasSeenOtherLoops() && !IgnoreOtherLoops
@@ -4894,13 +4916,13 @@ class SCEVInitRewriter : public SCEVRewriteVisitor<SCEVInitRewriter> {
                : Result;
   }
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) {
     if (!SE.isLoopInvariant(Expr, L))
       SeenLoopVariantSCEVUnknown = true;
     return Expr;
   }
 
-  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+  SCEVUse visitAddRecExpr(const SCEVAddRecExpr *Expr) {
     // Only re-write AddRecExprs for this loop.
     if (Expr->getLoop() == L)
       return Expr->getStart();
@@ -4927,21 +4949,21 @@ class SCEVInitRewriter : public SCEVRewriteVisitor<SCEVInitRewriter> {
 /// If SCEV contains non-invariant unknown SCEV rewrite cannot be done.
 class SCEVPostIncRewriter : public SCEVRewriteVisitor<SCEVPostIncRewriter> {
 public:
-  static const SCEV *rewrite(const SCEV *S, const Loop *L, ScalarEvolution &SE) {
+  static SCEVUse rewrite(SCEVUse S, const Loop *L, ScalarEvolution &SE) {
     SCEVPostIncRewriter Rewriter(L, SE);
-    const SCEV *Result = Rewriter.visit(S);
+    SCEVUse Result = Rewriter.visit(S);
     return Rewriter.hasSeenLoopVariantSCEVUnknown()
         ? SE.getCouldNotCompute()
         : Result;
   }
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) {
     if (!SE.isLoopInvariant(Expr, L))
       SeenLoopVariantSCEVUnknown = true;
     return Expr;
   }
 
-  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+  SCEVUse visitAddRecExpr(const SCEVAddRecExpr *Expr) {
     // Only re-write AddRecExprs for this loop.
     if (Expr->getLoop() == L)
       return Expr->getPostIncExpr(SE);
@@ -4968,8 +4990,7 @@ class SCEVPostIncRewriter : public SCEVRewriteVisitor<SCEVPostIncRewriter> {
 class SCEVBackedgeConditionFolder
     : public SCEVRewriteVisitor<SCEVBackedgeConditionFolder> {
 public:
-  static const SCEV *rewrite(const SCEV *S, const Loop *L,
-                             ScalarEvolution &SE) {
+  static SCEVUse rewrite(SCEVUse S, const Loop *L, ScalarEvolution &SE) {
     bool IsPosBECond = false;
     Value *BECond = nullptr;
     if (BasicBlock *Latch = L->getLoopLatch()) {
@@ -4987,8 +5008,8 @@ class SCEVBackedgeConditionFolder
     return Rewriter.visit(S);
   }
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
-    const SCEV *Result = Expr;
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) {
+    SCEVUse Result = Expr;
     bool InvariantF = SE.isLoopInvariant(Expr, L);
 
     if (!InvariantF) {
@@ -4996,7 +5017,7 @@ class SCEVBackedgeConditionFolder
       switch (I->getOpcode()) {
       case Instruction::Select: {
         SelectInst *SI = cast<SelectInst>(I);
-        std::optional<const SCEV *> Res =
+        std::optional<SCEVUse> Res =
             compareWithBackedgeCondition(SI->getCondition());
         if (Res) {
           bool IsOne = cast<SCEVConstant>(*Res)->getValue()->isOne();
@@ -5005,7 +5026,7 @@ class SCEVBackedgeConditionFolder
         break;
       }
       default: {
-        std::optional<const SCEV *> Res = compareWithBackedgeCondition(I);
+        std::optional<SCEVUse> Res = compareWithBackedgeCondition(I);
         if (Res)
           Result = *Res;
         break;
@@ -5021,7 +5042,7 @@ class SCEVBackedgeConditionFolder
       : SCEVRewriteVisitor(SE), L(L), BackedgeCond(BECond),
         IsPositiveBECond(IsPosBECond) {}
 
-  std::optional<const SCEV *> compareWithBackedgeCondition(Value *IC);
+  std::optional<SCEVUse> compareWithBackedgeCondition(Value *IC);
 
   const Loop *L;
   /// Loop back condition.
@@ -5030,7 +5051,7 @@ class SCEVBackedgeConditionFolder
   bool IsPositiveBECond;
 };
 
-std::optional<const SCEV *>
+std::optional<SCEVUse>
 SCEVBackedgeConditionFolder::compareWithBackedgeCondition(Value *IC) {
 
   // If value matches the backedge condition for loop latch,
@@ -5044,21 +5065,20 @@ SCEVBackedgeConditionFolder::compareWithBackedgeCondition(Value *IC) {
 
 class SCEVShiftRewriter : public SCEVRewriteVisitor<SCEVShiftRewriter> {
 public:
-  static const SCEV *rewrite(const SCEV *S, const Loop *L,
-                             ScalarEvolution &SE) {
+  static SCEVUse rewrite(SCEVUse S, const Loop *L, ScalarEvolution &SE) {
     SCEVShiftRewriter Rewriter(L, SE);
-    const SCEV *Result = Rewriter.visit(S);
+    SCEVUse Result = Rewriter.visit(S);
     return Rewriter.isValid() ? Result : SE.getCouldNotCompute();
   }
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) {
     // Only allow AddRecExprs for this loop.
     if (!SE.isLoopInvariant(Expr, L))
       Valid = false;
     return Expr;
   }
 
-  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+  SCEVUse visitAddRecExpr(const SCEVAddRecExpr *Expr) {
     if (Expr->getLoop() == L && Expr->isAffine())
       return SE.getMinusSCEV(Expr, Expr->getStepRecurrence(SE));
     Valid = false;
@@ -5087,7 +5107,7 @@ ScalarEvolution::proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR) {
   SCEV::NoWrapFlags Result = SCEV::FlagAnyWrap;
 
   if (!AR->hasNoSelfWrap()) {
-    const SCEV *BECount = getConstantMaxBackedgeTakenCount(AR->getLoop());
+    SCEVUse BECount = getConstantMaxBackedgeTakenCount(AR->getLoop());
     if (const SCEVConstant *BECountMax = dyn_cast<SCEVConstant>(BECount)) {
       ConstantRange StepCR = getSignedRange(AR->getStepRecurrence(*this));
       const APInt &BECountAP = BECountMax->getAPInt();
@@ -5135,7 +5155,7 @@ ScalarEvolution::proveNoSignedWrapViaInduction(const SCEVAddRecExpr *AR) {
   if (!SignedWrapViaInductionTried.insert(AR).second)
     return Result;
 
-  const SCEV *Step = AR->getStepRecurrence(*this);
+  SCEVUse Step = AR->getStepRecurrence(*this);
   const Loop *L = AR->getLoop();
 
   // Check whether the backedge-taken count is SCEVCouldNotCompute.
@@ -5146,7 +5166,7 @@ ScalarEvolution::proveNoSignedWrapViaInduction(const SCEVAddRecExpr *AR) {
   // in infinite recursion. In the later case, the analysis code will
   // cope with a conservative value, and it will take care to purge
   // that value once it has finished.
-  const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);
+  SCEVUse MaxBECount = getConstantMaxBackedgeTakenCount(L);
 
   // Normally, in the cases we can prove no-overflow via a
   // backedge guarding condition, we can also compute a backedge
@@ -5165,8 +5185,7 @@ ScalarEvolution::proveNoSignedWrapViaInduction(const SCEVAddRecExpr *AR) {
   // start value and the backedge is guarded by a comparison with the post-inc
   // value, the addrec is safe.
   ICmpInst::Predicate Pred;
-  const SCEV *OverflowLimit =
-    getSignedOverflowLimitForStep(Step, &Pred, this);
+  SCEVUse OverflowLimit = getSignedOverflowLimitForStep(Step, &Pred, this);
   if (OverflowLimit &&
       (isLoopBackedgeGuardedByCond(L, Pred, AR, OverflowLimit) ||
        isKnownOnEveryIteration(Pred, AR, OverflowLimit))) {
@@ -5188,7 +5207,7 @@ ScalarEvolution::proveNoUnsignedWrapViaInduction(const SCEVAddRecExpr *AR) {
   if (!UnsignedWrapViaInductionTried.insert(AR).second)
     return Result;
 
-  const SCEV *Step = AR->getStepRecurrence(*this);
+  SCEVUse Step = AR->getStepRecurrence(*this);
   unsigned BitWidth = getTypeSizeInBits(AR->getType());
   const Loop *L = AR->getLoop();
 
@@ -5200,7 +5219,7 @@ ScalarEvolution::proveNoUnsignedWrapViaInduction(const SCEVAddRecExpr *AR) {
   // in infinite recursion. In the later case, the analysis code will
   // cope with a conservative value, and it will take care to purge
   // that value once it has finished.
-  const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);
+  SCEVUse MaxBECount = getConstantMaxBackedgeTakenCount(L);
 
   // Normally, in the cases we can prove no-overflow via a
   // backedge guarding condition, we can also compute a backedge
@@ -5219,8 +5238,8 @@ ScalarEvolution::proveNoUnsignedWrapViaInduction(const SCEVAddRecExpr *AR) {
   // start value and the backedge is guarded by a comparison with the post-inc
   // value, the addrec is safe.
   if (isKnownPositive(Step)) {
-    const SCEV *N = getConstant(APInt::getMinValue(BitWidth) -
-                                getUnsignedRangeMax(Step));
+    SCEVUse N =
+        getConstant(APInt::getMinValue(BitWidth) - getUnsignedRangeMax(Step));
     if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N) ||
         isKnownOnEveryIteration(ICmpInst::ICMP_ULT, AR, N)) {
       Result = setFlags(Result, SCEV::FlagNUW);
@@ -5369,7 +5388,7 @@ static std::optional<BinaryOp> MatchBinaryOp(Value *V, const DataLayout &DL,
 /// we return the type of the truncation operation, and indicate whether the
 /// truncated type should be treated as signed/unsigned by setting
 /// \p Signed to true/false, respectively.
-static Type *isSimpleCastedPHI(const SCEV *Op, const SCEVUnknown *SymbolicPHI,
+static Type *isSimpleCastedPHI(SCEVUse Op, const SCEVUnknown *SymbolicPHI,
                                bool &Signed, ScalarEvolution &SE) {
   // The case where Op == SymbolicPHI (that is, with no type conversions on
   // the way) is handled by the regular add recurrence creating logic and
@@ -5398,7 +5417,7 @@ static Type *isSimpleCastedPHI(const SCEV *Op, const SCEVUnknown *SymbolicPHI,
            : dyn_cast<SCEVTruncateExpr>(ZExt->getOperand());
   if (!Trunc)
     return nullptr;
-  const SCEV *X = Trunc->getOperand();
+  SCEVUse X = Trunc->getOperand();
   if (X != SymbolicPHI)
     return nullptr;
   Signed = SExt != nullptr;
@@ -5467,8 +5486,9 @@ static const Loop *isIntegerLoopHeaderPHI(const PHINode *PN, LoopInfo &LI) {
 //    which correspond to a phi->trunc->add->sext/zext->phi update chain.
 //
 // 3) Outline common code with createAddRecFromPHI to avoid duplication.
-std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
-ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI) {
+std::optional<std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>>>
+ScalarEvolution::createAddRecFromPHIWithCastsImpl(
+    const SCEVUnknown *SymbolicPHI) {
   SmallVector<const SCEVPredicate *, 3> Predicates;
 
   // *** Part1: Analyze if we have a phi-with-cast pattern for which we can
@@ -5501,7 +5521,7 @@ ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI
   if (!BEValueV || !StartValueV)
     return std::nullopt;
 
-  const SCEV *BEValue = getSCEV(BEValueV);
+  SCEVUse BEValue = getSCEV(BEValueV);
 
   // If the value coming around the backedge is an add with the symbolic
   // value we just inserted, possibly with casts that we can ignore under
@@ -5527,11 +5547,11 @@ ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI
     return std::nullopt;
 
   // Create an add with everything but the specified operand.
-  SmallVector<const SCEV *, 8> Ops;
+  SmallVector<SCEVUse, 8> Ops;
   for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
     if (i != FoundIndex)
       Ops.push_back(Add->getOperand(i));
-  const SCEV *Accum = getAddExpr(Ops);
+  SCEVUse Accum = getAddExpr(Ops);
 
   // The runtime checks will not be valid if the step amount is
   // varying inside the loop.
@@ -5589,8 +5609,8 @@ ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI
   //
 
   // Create a truncated addrec for which we will add a no overflow check (P1).
-  const SCEV *StartVal = getSCEV(StartValueV);
-  const SCEV *PHISCEV =
+  SCEVUse StartVal = getSCEV(StartValueV);
+  SCEVUse PHISCEV =
       getAddRecExpr(getTruncateExpr(StartVal, TruncTy),
                     getTruncateExpr(Accum, TruncTy), L, SCEV::FlagAnyWrap);
 
@@ -5617,11 +5637,10 @@ ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI
 
   // Construct the extended SCEV: (Ext ix (Trunc iy (Expr) to ix) to iy)
   // for each of StartVal and Accum
-  auto getExtendedExpr = [&](const SCEV *Expr,
-                             bool CreateSignExtend) -> const SCEV * {
+  auto getExtendedExpr = [&](SCEVUse Expr, bool CreateSignExtend) -> SCEVUse {
     assert(isLoopInvariant(Expr, L) && "Expr is expected to be invariant");
-    const SCEV *TruncatedExpr = getTruncateExpr(Expr, TruncTy);
-    const SCEV *ExtendedExpr =
+    SCEVUse TruncatedExpr = getTruncateExpr(Expr, TruncTy);
+    SCEVUse ExtendedExpr =
         CreateSignExtend ? getSignExtendExpr(TruncatedExpr, Expr->getType())
                          : getZeroExtendExpr(TruncatedExpr, Expr->getType());
     return ExtendedExpr;
@@ -5632,13 +5651,12 @@ ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI
   //               = getExtendedExpr(Expr)
   // Determine whether the predicate P: Expr == ExtendedExpr
   // is known to be false at compile time
-  auto PredIsKnownFalse = [&](const SCEV *Expr,
-                              const SCEV *ExtendedExpr) -> bool {
+  auto PredIsKnownFalse = [&](SCEVUse Expr, SCEVUse ExtendedExpr) -> bool {
     return Expr != ExtendedExpr &&
            isKnownPredicate(ICmpInst::ICMP_NE, Expr, ExtendedExpr);
   };
 
-  const SCEV *StartExtended = getExtendedExpr(StartVal, Signed);
+  SCEVUse StartExtended = getExtendedExpr(StartVal, Signed);
   if (PredIsKnownFalse(StartVal, StartExtended)) {
     LLVM_DEBUG(dbgs() << "P2 is compile-time false\n";);
     return std::nullopt;
@@ -5646,14 +5664,13 @@ ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI
 
   // The Step is always Signed (because the overflow checks are either
   // NSSW or NUSW)
-  const SCEV *AccumExtended = getExtendedExpr(Accum, /*CreateSignExtend=*/true);
+  SCEVUse AccumExtended = getExtendedExpr(Accum, /*CreateSignExtend=*/true);
   if (PredIsKnownFalse(Accum, AccumExtended)) {
     LLVM_DEBUG(dbgs() << "P3 is compile-time false\n";);
     return std::nullopt;
   }
 
-  auto AppendPredicate = [&](const SCEV *Expr,
-                             const SCEV *ExtendedExpr) -> void {
+  auto AppendPredicate = [&](SCEVUse Expr, SCEVUse ExtendedExpr) -> void {
     if (Expr != ExtendedExpr &&
         !isKnownPredicate(ICmpInst::ICMP_EQ, Expr, ExtendedExpr)) {
       const SCEVPredicate *Pred = getEqualPredicate(Expr, ExtendedExpr);
@@ -5669,16 +5686,16 @@ ScalarEvolution::createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI
   // which the casts had been folded away. The caller can rewrite SymbolicPHI
   // into NewAR if it will also add the runtime overflow checks specified in
   // Predicates.
-  auto *NewAR = getAddRecExpr(StartVal, Accum, L, SCEV::FlagAnyWrap);
+  auto NewAR = getAddRecExpr(StartVal, Accum, L, SCEV::FlagAnyWrap);
 
-  std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>> PredRewrite =
+  std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>> PredRewrite =
       std::make_pair(NewAR, Predicates);
   // Remember the result of the analysis for this SCEV at this locayyytion.
   PredicatedSCEVRewrites[{SymbolicPHI, L}] = PredRewrite;
   return PredRewrite;
 }
 
-std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
+std::optional<std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>>>
 ScalarEvolution::createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI) {
   auto *PN = cast<PHINode>(SymbolicPHI->getValue());
   const Loop *L = isIntegerLoopHeaderPHI(PN, LI);
@@ -5688,7 +5705,7 @@ ScalarEvolution::createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI) {
   // Check to see if we already analyzed this PHI.
   auto I = PredicatedSCEVRewrites.find({SymbolicPHI, L});
   if (I != PredicatedSCEVRewrites.end()) {
-    std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>> Rewrite =
+    std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>> Rewrite =
         I->second;
     // Analysis was done before and failed to create an AddRec:
     if (Rewrite.first == SymbolicPHI)
@@ -5700,8 +5717,8 @@ ScalarEvolution::createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI) {
     return Rewrite;
   }
 
-  std::optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
-    Rewrite = createAddRecFromPHIWithCastsImpl(SymbolicPHI);
+  std::optional<std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>>>
+      Rewrite = createAddRecFromPHIWithCastsImpl(SymbolicPHI);
 
   // Record in the cache that the analysis failed
   if (!Rewrite) {
@@ -5724,7 +5741,7 @@ bool PredicatedScalarEvolution::areAddRecsEqualWithPreds(
   if (AR1 == AR2)
     return true;
 
-  auto areExprsEqual = [&](const SCEV *Expr1, const SCEV *Expr2) -> bool {
+  auto areExprsEqual = [&](SCEVUse Expr1, SCEVUse Expr2) -> bool {
     if (Expr1 != Expr2 && !Preds->implies(SE.getEqualPredicate(Expr1, Expr2)) &&
         !Preds->implies(SE.getEqualPredicate(Expr2, Expr1)))
       return false;
@@ -5743,9 +5760,8 @@ bool PredicatedScalarEvolution::areAddRecsEqualWithPreds(
 /// common) cases: PN = PHI(Start, OP(Self, LoopInvariant)).
 /// If it fails, createAddRecFromPHI will use a more general, but slow,
 /// technique for finding the AddRec expression.
-const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
-                                                      Value *BEValueV,
-                                                      Value *StartValueV) {
+SCEVUse ScalarEvolution::createSimpleAffineAddRec(PHINode *PN, Value *BEValueV,
+                                                  Value *StartValueV) {
   const Loop *L = LI.getLoopFor(PN->getParent());
   assert(L && L->getHeader() == PN->getParent());
   assert(BEValueV && StartValueV);
@@ -5757,7 +5773,7 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
   if (BO->Opcode != Instruction::Add)
     return nullptr;
 
-  const SCEV *Accum = nullptr;
+  SCEVUse Accum = nullptr;
   if (BO->LHS == PN && L->isLoopInvariant(BO->RHS))
     Accum = getSCEV(BO->RHS);
   else if (BO->RHS == PN && L->isLoopInvariant(BO->LHS))
@@ -5772,8 +5788,8 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
   if (BO->IsNSW)
     Flags = setFlags(Flags, SCEV::FlagNSW);
 
-  const SCEV *StartVal = getSCEV(StartValueV);
-  const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);
+  SCEVUse StartVal = getSCEV(StartValueV);
+  SCEVUse PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);
   insertValueToMap(PN, PHISCEV);
 
   if (auto *AR = dyn_cast<SCEVAddRecExpr>(PHISCEV)) {
@@ -5795,7 +5811,7 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
   return PHISCEV;
 }
 
-const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
+SCEVUse ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
   const Loop *L = LI.getLoopFor(PN->getParent());
   if (!L || L->getHeader() != PN->getParent())
     return nullptr;
@@ -5828,16 +5844,16 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
 
   // First, try to find AddRec expression without creating a fictituos symbolic
   // value for PN.
-  if (auto *S = createSimpleAffineAddRec(PN, BEValueV, StartValueV))
+  if (auto S = createSimpleAffineAddRec(PN, BEValueV, StartValueV))
     return S;
 
   // Handle PHI node value symbolically.
-  const SCEV *SymbolicName = getUnknown(PN);
+  SCEVUse SymbolicName = getUnknown(PN);
   insertValueToMap(PN, SymbolicName);
 
   // Using this symbolic name for the PHI, analyze the value coming around
   // the back-edge.
-  const SCEV *BEValue = getSCEV(BEValueV);
+  SCEVUse BEValue = getSCEV(BEValueV);
 
   // NOTE: If BEValue is loop invariant, we know that the PHI node just
   // has a special value for the first iteration of the loop.
@@ -5857,12 +5873,12 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
 
     if (FoundIndex != Add->getNumOperands()) {
       // Create an add with everything but the specified operand.
-      SmallVector<const SCEV *, 8> Ops;
+      SmallVector<SCEVUse, 8> Ops;
       for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
         if (i != FoundIndex)
           Ops.push_back(SCEVBackedgeConditionFolder::rewrite(Add->getOperand(i),
                                                              L, *this));
-      const SCEV *Accum = getAddExpr(Ops);
+      SCEVUse Accum = getAddExpr(Ops);
 
       // This is not a valid addrec if the step amount is varying each
       // loop iteration, but is not itself an addrec in this loop.
@@ -5896,8 +5912,8 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
           // for instance.
         }
 
-        const SCEV *StartVal = getSCEV(StartValueV);
-        const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);
+        SCEVUse StartVal = getSCEV(StartValueV);
+        SCEVUse PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);
 
         // Okay, for the entire analysis of this edge we assumed the PHI
         // to be symbolic.  We now need to go back and purge all of the
@@ -5931,11 +5947,11 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
     // We can generalize this saying that i is the shifted value of BEValue
     // by one iteration:
     //   PHI(f(0), f({1,+,1})) --> f({0,+,1})
-    const SCEV *Shifted = SCEVShiftRewriter::rewrite(BEValue, L, *this);
-    const SCEV *Start = SCEVInitRewriter::rewrite(Shifted, L, *this, false);
+    SCEVUse Shifted = SCEVShiftRewriter::rewrite(BEValue, L, *this);
+    SCEVUse Start = SCEVInitRewriter::rewrite(Shifted, L, *this, false);
     if (Shifted != getCouldNotCompute() &&
         Start != getCouldNotCompute()) {
-      const SCEV *StartVal = getSCEV(StartValueV);
+      SCEVUse StartVal = getSCEV(StartValueV);
       if (Start == StartVal) {
         // Okay, for the entire analysis of this edge we assumed the PHI
         // to be symbolic.  We now need to go back and purge all of the
@@ -5989,7 +6005,7 @@ static bool BrPHIToSelect(DominatorTree &DT, BranchInst *BI, PHINode *Merge,
   return false;
 }
 
-const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
+SCEVUse ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
   auto IsReachable =
       [&](BasicBlock *BB) { return DT.isReachableFromEntry(BB); };
   if (PN->getNumIncomingValues() == 2 && all_of(PN->blocks(), IsReachable)) {
@@ -6021,24 +6037,24 @@ const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
   return nullptr;
 }
 
-const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
-  if (const SCEV *S = createAddRecFromPHI(PN))
+SCEVUse ScalarEvolution::createNodeForPHI(PHINode *PN) {
+  if (SCEVUse S = createAddRecFromPHI(PN))
     return S;
 
   if (Value *V = simplifyInstruction(PN, {getDataLayout(), &TLI, &DT, &AC}))
     return getSCEV(V);
 
-  if (const SCEV *S = createNodeFromSelectLikePHI(PN))
+  if (SCEVUse S = createNodeFromSelectLikePHI(PN))
     return S;
 
   // If it's not a loop phi, we can't handle it yet.
   return getUnknown(PN);
 }
 
-bool SCEVMinMaxExprContains(const SCEV *Root, const SCEV *OperandToFind,
+bool SCEVMinMaxExprContains(SCEVUse Root, SCEVUse OperandToFind,
                             SCEVTypes RootKind) {
   struct FindClosure {
-    const SCEV *OperandToFind;
+    SCEVUse OperandToFind;
     const SCEVTypes RootKind; // Must be a sequential min/max expression.
     const SCEVTypes NonSequentialRootKind; // Non-seq variant of RootKind.
 
@@ -6051,13 +6067,13 @@ bool SCEVMinMaxExprContains(const SCEV *Root, const SCEV *OperandToFind,
              scZeroExtend == Kind;
     };
 
-    FindClosure(const SCEV *OperandToFind, SCEVTypes RootKind)
+    FindClosure(SCEVUse OperandToFind, SCEVTypes RootKind)
         : OperandToFind(OperandToFind), RootKind(RootKind),
           NonSequentialRootKind(
               SCEVSequentialMinMaxExpr::getEquivalentNonSequentialSCEVType(
                   RootKind)) {}
 
-    bool follow(const SCEV *S) {
+    bool follow(SCEVUse S) {
       Found = S == OperandToFind;
 
       return !isDone() && canRecurseInto(S->getSCEVType());
@@ -6071,7 +6087,7 @@ bool SCEVMinMaxExprContains(const SCEV *Root, const SCEV *OperandToFind,
   return FC.Found;
 }
 
-std::optional<const SCEV *>
+std::optional<SCEVUse>
 ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
                                                               ICmpInst *Cond,
                                                               Value *TrueVal,
@@ -6097,10 +6113,10 @@ ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
     // a > b ? b+x : a+x  ->  min(a, b)+x
     if (getTypeSizeInBits(LHS->getType()) <= getTypeSizeInBits(Ty)) {
       bool Signed = ICI->isSigned();
-      const SCEV *LA = getSCEV(TrueVal);
-      const SCEV *RA = getSCEV(FalseVal);
-      const SCEV *LS = getSCEV(LHS);
-      const SCEV *RS = getSCEV(RHS);
+      SCEVUse LA = getSCEV(TrueVal);
+      SCEVUse RA = getSCEV(FalseVal);
+      SCEVUse LS = getSCEV(LHS);
+      SCEVUse RS = getSCEV(RHS);
       if (LA->getType()->isPointerTy()) {
         // FIXME: Handle cases where LS/RS are pointers not equal to LA/RA.
         // Need to make sure we can't produce weird expressions involving
@@ -6110,7 +6126,7 @@ ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
         if (LA == RS && RA == LS)
           return Signed ? getSMinExpr(LS, RS) : getUMinExpr(LS, RS);
       }
-      auto CoerceOperand = [&](const SCEV *Op) -> const SCEV * {
+      auto CoerceOperand = [&](SCEVUse Op) -> SCEVUse {
         if (Op->getType()->isPointerTy()) {
           Op = getLosslessPtrToIntExpr(Op);
           if (isa<SCEVCouldNotCompute>(Op))
@@ -6126,8 +6142,8 @@ ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
       RS = CoerceOperand(RS);
       if (isa<SCEVCouldNotCompute>(LS) || isa<SCEVCouldNotCompute>(RS))
         break;
-      const SCEV *LDiff = getMinusSCEV(LA, LS);
-      const SCEV *RDiff = getMinusSCEV(RA, RS);
+      SCEVUse LDiff = getMinusSCEV(LA, LS);
+      SCEVUse RDiff = getMinusSCEV(RA, RS);
       if (LDiff == RDiff)
         return getAddExpr(Signed ? getSMaxExpr(LS, RS) : getUMaxExpr(LS, RS),
                           LDiff);
@@ -6146,11 +6162,11 @@ ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
     // x == 0 ? C+y : x+y  ->  umax(x, C)+y   iff C u<= 1
     if (getTypeSizeInBits(LHS->getType()) <= getTypeSizeInBits(Ty) &&
         isa<ConstantInt>(RHS) && cast<ConstantInt>(RHS)->isZero()) {
-      const SCEV *X = getNoopOrZeroExtend(getSCEV(LHS), Ty);
-      const SCEV *TrueValExpr = getSCEV(TrueVal);    // C+y
-      const SCEV *FalseValExpr = getSCEV(FalseVal);  // x+y
-      const SCEV *Y = getMinusSCEV(FalseValExpr, X); // y = (x+y)-x
-      const SCEV *C = getMinusSCEV(TrueValExpr, Y);  // C = (C+y)-y
+      SCEVUse X = getNoopOrZeroExtend(getSCEV(LHS), Ty);
+      SCEVUse TrueValExpr = getSCEV(TrueVal);    // C+y
+      SCEVUse FalseValExpr = getSCEV(FalseVal);  // x+y
+      SCEVUse Y = getMinusSCEV(FalseValExpr, X); // y = (x+y)-x
+      SCEVUse C = getMinusSCEV(TrueValExpr, Y);  // C = (C+y)-y
       if (isa<SCEVConstant>(C) && cast<SCEVConstant>(C)->getAPInt().ule(1))
         return getAddExpr(getUMaxExpr(X, C), Y);
     }
@@ -6160,11 +6176,11 @@ ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
     //                    ->  umin_seq(x, umin (..., umin_seq(...), ...))
     if (isa<ConstantInt>(RHS) && cast<ConstantInt>(RHS)->isZero() &&
         isa<ConstantInt>(TrueVal) && cast<ConstantInt>(TrueVal)->isZero()) {
-      const SCEV *X = getSCEV(LHS);
+      SCEVUse X = getSCEV(LHS);
       while (auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(X))
         X = ZExt->getOperand();
       if (getTypeSizeInBits(X->getType()) <= getTypeSizeInBits(Ty)) {
-        const SCEV *FalseValExpr = getSCEV(FalseVal);
+        SCEVUse FalseValExpr = getSCEV(FalseVal);
         if (SCEVMinMaxExprContains(FalseValExpr, X, scSequentialUMinExpr))
           return getUMinExpr(getNoopOrZeroExtend(X, Ty), FalseValExpr,
                              /*Sequential=*/true);
@@ -6178,9 +6194,10 @@ ScalarEvolution::createNodeForSelectOrPHIInstWithICmpInstCond(Type *Ty,
   return std::nullopt;
 }
 
-static std::optional<const SCEV *>
-createNodeForSelectViaUMinSeq(ScalarEvolution *SE, const SCEV *CondExpr,
-                              const SCEV *TrueExpr, const SCEV *FalseExpr) {
+static std::optional<SCEVUse> createNodeForSelectViaUMinSeq(ScalarEvolution *SE,
+                                                            SCEVUse CondExpr,
+                                                            SCEVUse TrueExpr,
+                                                            SCEVUse FalseExpr) {
   assert(CondExpr->getType()->isIntegerTy(1) &&
          TrueExpr->getType() == FalseExpr->getType() &&
          TrueExpr->getType()->isIntegerTy(1) &&
@@ -6198,7 +6215,7 @@ createNodeForSelectViaUMinSeq(ScalarEvolution *SE, const SCEV *CondExpr,
   if (!isa<SCEVConstant>(TrueExpr) && !isa<SCEVConstant>(FalseExpr))
     return std::nullopt;
 
-  const SCEV *X, *C;
+  SCEVUse X, C;
   if (isa<SCEVConstant>(TrueExpr)) {
     CondExpr = SE->getNotSCEV(CondExpr);
     X = FalseExpr;
@@ -6211,20 +6228,23 @@ createNodeForSelectViaUMinSeq(ScalarEvolution *SE, const SCEV *CondExpr,
                                            /*Sequential=*/true));
 }
 
-static std::optional<const SCEV *>
-createNodeForSelectViaUMinSeq(ScalarEvolution *SE, Value *Cond, Value *TrueVal,
-                              Value *FalseVal) {
+static std::optional<SCEVUse> createNodeForSelectViaUMinSeq(ScalarEvolution *SE,
+                                                            Value *Cond,
+                                                            Value *TrueVal,
+                                                            Value *FalseVal) {
   if (!isa<ConstantInt>(TrueVal) && !isa<ConstantInt>(FalseVal))
     return std::nullopt;
 
-  const auto *SECond = SE->getSCEV(Cond);
-  const auto *SETrue = SE->getSCEV(TrueVal);
-  const auto *SEFalse = SE->getSCEV(FalseVal);
+  const auto SECond = SE->getSCEV(Cond);
+  const auto SETrue = SE->getSCEV(TrueVal);
+  const auto SEFalse = SE->getSCEV(FalseVal);
   return createNodeForSelectViaUMinSeq(SE, SECond, SETrue, SEFalse);
 }
 
-const SCEV *ScalarEvolution::createNodeForSelectOrPHIViaUMinSeq(
-    Value *V, Value *Cond, Value *TrueVal, Value *FalseVal) {
+SCEVUse ScalarEvolution::createNodeForSelectOrPHIViaUMinSeq(Value *V,
+                                                            Value *Cond,
+                                                            Value *TrueVal,
+                                                            Value *FalseVal) {
   assert(Cond->getType()->isIntegerTy(1) && "Select condition is not an i1?");
   assert(TrueVal->getType() == FalseVal->getType() &&
          V->getType() == TrueVal->getType() &&
@@ -6234,16 +6254,16 @@ const SCEV *ScalarEvolution::createNodeForSelectOrPHIViaUMinSeq(
   if (!V->getType()->isIntegerTy(1))
     return getUnknown(V);
 
-  if (std::optional<const SCEV *> S =
+  if (std::optional<SCEVUse> S =
           createNodeForSelectViaUMinSeq(this, Cond, TrueVal, FalseVal))
     return *S;
 
   return getUnknown(V);
 }
 
-const SCEV *ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
-                                                      Value *TrueVal,
-                                                      Value *FalseVal) {
+SCEVUse ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
+                                                  Value *TrueVal,
+                                                  Value *FalseVal) {
   // Handle "constant" branch or select. This can occur for instance when a
   // loop pass transforms an inner loop and moves on to process the outer loop.
   if (auto *CI = dyn_cast<ConstantInt>(Cond))
@@ -6251,7 +6271,7 @@ const SCEV *ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
 
   if (auto *I = dyn_cast<Instruction>(V)) {
     if (auto *ICI = dyn_cast<ICmpInst>(Cond)) {
-      if (std::optional<const SCEV *> S =
+      if (std::optional<SCEVUse> S =
               createNodeForSelectOrPHIInstWithICmpInstCond(I->getType(), ICI,
                                                            TrueVal, FalseVal))
         return *S;
@@ -6263,17 +6283,17 @@ const SCEV *ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
 
 /// Expand GEP instructions into add and multiply operations. This allows them
 /// to be analyzed by regular SCEV code.
-const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
+SCEVUse ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
   assert(GEP->getSourceElementType()->isSized() &&
          "GEP source element type must be sized");
 
-  SmallVector<const SCEV *, 4> IndexExprs;
+  SmallVector<SCEVUse, 4> IndexExprs;
   for (Value *Index : GEP->indices())
     IndexExprs.push_back(getSCEV(Index));
   return getGEPExpr(GEP, IndexExprs);
 }
 
-APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S) {
+APInt ScalarEvolution::getConstantMultipleImpl(SCEVUse S) {
   uint64_t BitWidth = getTypeSizeInBits(S->getType());
   auto GetShiftedByZeros = [BitWidth](uint32_t TrailingZeros) {
     return TrailingZeros >= BitWidth
@@ -6316,7 +6336,7 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S) {
     if (M->hasNoUnsignedWrap()) {
       // The result is the product of all operand results.
       APInt Res = getConstantMultiple(M->getOperand(0));
-      for (const SCEV *Operand : M->operands().drop_front())
+      for (SCEVUse Operand : M->operands().drop_front())
         Res = Res * getConstantMultiple(Operand);
       return Res;
     }
@@ -6324,7 +6344,7 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S) {
     // If there are no wrap guarentees, find the trailing zeros, which is the
     // sum of trailing zeros for all its operands.
     uint32_t TZ = 0;
-    for (const SCEV *Operand : M->operands())
+    for (SCEVUse Operand : M->operands())
       TZ += getMinTrailingZeros(Operand);
     return GetShiftedByZeros(TZ);
   }
@@ -6335,7 +6355,7 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S) {
         return GetGCDMultiple(N);
     // Find the trailing bits, which is the minimum of its operands.
     uint32_t TZ = getMinTrailingZeros(N->getOperand(0));
-    for (const SCEV *Operand : N->operands().drop_front())
+    for (SCEVUse Operand : N->operands().drop_front())
       TZ = std::min(TZ, getMinTrailingZeros(Operand));
     return GetShiftedByZeros(TZ);
   }
@@ -6359,7 +6379,7 @@ APInt ScalarEvolution::getConstantMultipleImpl(const SCEV *S) {
   llvm_unreachable("Unknown SCEV kind!");
 }
 
-APInt ScalarEvolution::getConstantMultiple(const SCEV *S) {
+APInt ScalarEvolution::getConstantMultiple(SCEVUse S) {
   auto I = ConstantMultipleCache.find(S);
   if (I != ConstantMultipleCache.end())
     return I->second;
@@ -6370,12 +6390,12 @@ APInt ScalarEvolution::getConstantMultiple(const SCEV *S) {
   return InsertPair.first->second;
 }
 
-APInt ScalarEvolution::getNonZeroConstantMultiple(const SCEV *S) {
+APInt ScalarEvolution::getNonZeroConstantMultiple(SCEVUse S) {
   APInt Multiple = getConstantMultiple(S);
   return Multiple == 0 ? APInt(Multiple.getBitWidth(), 1) : Multiple;
 }
 
-uint32_t ScalarEvolution::getMinTrailingZeros(const SCEV *S) {
+uint32_t ScalarEvolution::getMinTrailingZeros(SCEVUse S) {
   return std::min(getConstantMultiple(S).countTrailingZeros(),
                   (unsigned)getTypeSizeInBits(S->getType()));
 }
@@ -6526,17 +6546,17 @@ getRangeForUnknownRecurrence(const SCEVUnknown *U) {
 }
 
 const ConstantRange &
-ScalarEvolution::getRangeRefIter(const SCEV *S,
+ScalarEvolution::getRangeRefIter(SCEVUse S,
                                  ScalarEvolution::RangeSignHint SignHint) {
-  DenseMap<const SCEV *, ConstantRange> &Cache =
+  DenseMap<SCEVUse, ConstantRange> &Cache =
       SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? UnsignedRanges
                                                        : SignedRanges;
-  SmallVector<const SCEV *> WorkList;
-  SmallPtrSet<const SCEV *, 8> Seen;
+  SmallVector<SCEVUse> WorkList;
+  SmallPtrSet<SCEVUse, 8> Seen;
 
   // Add Expr to the worklist, if Expr is either an N-ary expression or a
   // SCEVUnknown PHI node.
-  auto AddToWorklist = [&WorkList, &Seen, &Cache](const SCEV *Expr) {
+  auto AddToWorklist = [&WorkList, &Seen, &Cache](SCEVUse Expr) {
     if (!Seen.insert(Expr).second)
       return;
     if (Cache.contains(Expr))
@@ -6571,11 +6591,11 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
 
   // Build worklist by queuing operands of N-ary expressions and phi nodes.
   for (unsigned I = 0; I != WorkList.size(); ++I) {
-    const SCEV *P = WorkList[I];
+    SCEVUse P = WorkList[I];
     auto *UnknownS = dyn_cast<SCEVUnknown>(P);
     // If it is not a `SCEVUnknown`, just recurse into operands.
     if (!UnknownS) {
-      for (const SCEV *Op : P->operands())
+      for (SCEVUse Op : P->operands())
         AddToWorklist(Op);
       continue;
     }
@@ -6592,7 +6612,7 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
     // Use getRangeRef to compute ranges for items in the worklist in reverse
     // order. This will force ranges for earlier operands to be computed before
     // their users in most cases.
-    for (const SCEV *P : reverse(drop_begin(WorkList))) {
+    for (SCEVUse P : reverse(drop_begin(WorkList))) {
       getRangeRef(P, SignHint);
 
       if (auto *UnknownS = dyn_cast<SCEVUnknown>(P))
@@ -6607,9 +6627,10 @@ ScalarEvolution::getRangeRefIter(const SCEV *S,
 /// Determine the range for a particular SCEV.  If SignHint is
 /// HINT_RANGE_UNSIGNED (resp. HINT_RANGE_SIGNED) then getRange prefers ranges
 /// with a "cleaner" unsigned (resp. signed) representation.
-const ConstantRange &ScalarEvolution::getRangeRef(
-    const SCEV *S, ScalarEvolution::RangeSignHint SignHint, unsigned Depth) {
-  DenseMap<const SCEV *, ConstantRange> &Cache =
+const ConstantRange &
+ScalarEvolution::getRangeRef(SCEVUse S, ScalarEvolution::RangeSignHint SignHint,
+                             unsigned Depth) {
+  DenseMap<SCEVUse, ConstantRange> &Cache =
       SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? UnsignedRanges
                                                        : SignedRanges;
   ConstantRange::PreferredRangeType RangeType =
@@ -6617,7 +6638,7 @@ const ConstantRange &ScalarEvolution::getRangeRef(
                                                        : ConstantRange::Signed;
 
   // See if we've computed this range already.
-  DenseMap<const SCEV *, ConstantRange>::iterator I = Cache.find(S);
+  DenseMap<SCEVUse, ConstantRange>::iterator I = Cache.find(S);
   if (I != Cache.end())
     return I->second;
 
@@ -6752,8 +6773,7 @@ const ConstantRange &ScalarEvolution::getRangeRef(
 
     // TODO: non-affine addrec
     if (AddRec->isAffine()) {
-      const SCEV *MaxBEScev =
-          getConstantMaxBackedgeTakenCount(AddRec->getLoop());
+      SCEVUse MaxBEScev = getConstantMaxBackedgeTakenCount(AddRec->getLoop());
       if (!isa<SCEVCouldNotCompute>(MaxBEScev)) {
         APInt MaxBECount = cast<SCEVConstant>(MaxBEScev)->getAPInt();
 
@@ -6780,7 +6800,7 @@ const ConstantRange &ScalarEvolution::getRangeRef(
 
       // Now try symbolic BE count and more powerful methods.
       if (UseExpensiveRangeSharpening) {
-        const SCEV *SymbolicMaxBECount =
+        SCEVUse SymbolicMaxBECount =
             getSymbolicMaxBackedgeTakenCount(AddRec->getLoop());
         if (!isa<SCEVCouldNotCompute>(SymbolicMaxBECount) &&
             getTypeSizeInBits(MaxBEScev->getType()) <= BitWidth &&
@@ -7011,8 +7031,7 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
   return ConstantRange::getNonEmpty(std::move(NewLower), std::move(NewUpper));
 }
 
-ConstantRange ScalarEvolution::getRangeForAffineAR(const SCEV *Start,
-                                                   const SCEV *Step,
+ConstantRange ScalarEvolution::getRangeForAffineAR(SCEVUse Start, SCEVUse Step,
                                                    const APInt &MaxBECount) {
   assert(getTypeSizeInBits(Start->getType()) ==
              getTypeSizeInBits(Step->getType()) &&
@@ -7041,13 +7060,13 @@ ConstantRange ScalarEvolution::getRangeForAffineAR(const SCEV *Start,
 }
 
 ConstantRange ScalarEvolution::getRangeForAffineNoSelfWrappingAR(
-    const SCEVAddRecExpr *AddRec, const SCEV *MaxBECount, unsigned BitWidth,
+    const SCEVAddRecExpr *AddRec, SCEVUse MaxBECount, unsigned BitWidth,
     ScalarEvolution::RangeSignHint SignHint) {
   assert(AddRec->isAffine() && "Non-affine AddRecs are not suppored!\n");
   assert(AddRec->hasNoSelfWrap() &&
          "This only works for non-self-wrapping AddRecs!");
   const bool IsSigned = SignHint == HINT_RANGE_SIGNED;
-  const SCEV *Step = AddRec->getStepRecurrence(*this);
+  SCEVUse Step = AddRec->getStepRecurrence(*this);
   // Only deal with constant step to save compile time.
   if (!isa<SCEVConstant>(Step))
     return ConstantRange::getFull(BitWidth);
@@ -7060,9 +7079,9 @@ ConstantRange ScalarEvolution::getRangeForAffineNoSelfWrappingAR(
       getTypeSizeInBits(AddRec->getType()))
     return ConstantRange::getFull(BitWidth);
   MaxBECount = getNoopOrZeroExtend(MaxBECount, AddRec->getType());
-  const SCEV *RangeWidth = getMinusOne(AddRec->getType());
-  const SCEV *StepAbs = getUMinExpr(Step, getNegativeSCEV(Step));
-  const SCEV *MaxItersWithoutWrap = getUDivExpr(RangeWidth, StepAbs);
+  SCEVUse RangeWidth = getMinusOne(AddRec->getType());
+  SCEVUse StepAbs = getUMinExpr(Step, getNegativeSCEV(Step));
+  SCEVUse MaxItersWithoutWrap = getUDivExpr(RangeWidth, StepAbs);
   if (!isKnownPredicateViaConstantRanges(ICmpInst::ICMP_ULE, MaxBECount,
                                          MaxItersWithoutWrap))
     return ConstantRange::getFull(BitWidth);
@@ -7071,7 +7090,7 @@ ConstantRange ScalarEvolution::getRangeForAffineNoSelfWrappingAR(
       IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
   ICmpInst::Predicate GEPred =
       IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
-  const SCEV *End = AddRec->evaluateAtIteration(MaxBECount, *this);
+  SCEVUse End = AddRec->evaluateAtIteration(MaxBECount, *this);
 
   // We know that there is no self-wrap. Let's take Start and End values and
   // look at all intermediate values V1, V2, ..., Vn that IndVar takes during
@@ -7085,7 +7104,7 @@ ConstantRange ScalarEvolution::getRangeForAffineNoSelfWrappingAR(
   // outside and inside the range [Min(Start, End), Max(Start, End)]. Using that
   // knowledge, let's try to prove that we are dealing with Case 1. It is so if
   // Start <= End and step is positive, or Start >= End and step is negative.
-  const SCEV *Start = applyLoopGuards(AddRec->getStart(), AddRec->getLoop());
+  SCEVUse Start = applyLoopGuards(AddRec->getStart(), AddRec->getLoop());
   ConstantRange StartRange = getRangeRef(Start, SignHint);
   ConstantRange EndRange = getRangeRef(End, SignHint);
   ConstantRange RangeBetween = StartRange.unionWith(EndRange);
@@ -7108,8 +7127,7 @@ ConstantRange ScalarEvolution::getRangeForAffineNoSelfWrappingAR(
   return ConstantRange::getFull(BitWidth);
 }
 
-ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
-                                                    const SCEV *Step,
+ConstantRange ScalarEvolution::getRangeViaFactoring(SCEVUse Start, SCEVUse Step,
                                                     const APInt &MaxBECount) {
   //    RangeOf({C?A:B,+,C?P:Q}) == RangeOf(C?{A,+,P}:{B,+,Q})
   // == RangeOf({A,+,P}) union RangeOf({B,+,Q})
@@ -7124,8 +7142,7 @@ ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
     APInt TrueValue;
     APInt FalseValue;
 
-    explicit SelectPattern(ScalarEvolution &SE, unsigned BitWidth,
-                           const SCEV *S) {
+    explicit SelectPattern(ScalarEvolution &SE, unsigned BitWidth, SCEVUse S) {
       std::optional<unsigned> CastOp;
       APInt Offset(BitWidth, 0);
 
@@ -7214,10 +7231,10 @@ ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
   // FIXME: without the explicit `this` receiver below, MSVC errors out with
   // C2352 and C2512 (otherwise it isn't needed).
 
-  const SCEV *TrueStart = this->getConstant(StartPattern.TrueValue);
-  const SCEV *TrueStep = this->getConstant(StepPattern.TrueValue);
-  const SCEV *FalseStart = this->getConstant(StartPattern.FalseValue);
-  const SCEV *FalseStep = this->getConstant(StepPattern.FalseValue);
+  SCEVUse TrueStart = this->getConstant(StartPattern.TrueValue);
+  SCEVUse TrueStep = this->getConstant(StepPattern.TrueValue);
+  SCEVUse FalseStart = this->getConstant(StartPattern.FalseValue);
+  SCEVUse FalseStep = this->getConstant(StepPattern.FalseValue);
 
   ConstantRange TrueRange =
       this->getRangeForAffineAR(TrueStart, TrueStep, MaxBECount);
@@ -7243,8 +7260,7 @@ SCEV::NoWrapFlags ScalarEvolution::getNoWrapFlagsFromUB(const Value *V) {
   return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap;
 }
 
-const Instruction *
-ScalarEvolution::getNonTrivialDefiningScopeBound(const SCEV *S) {
+const Instruction *ScalarEvolution::getNonTrivialDefiningScopeBound(SCEVUse S) {
   if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S))
     return &*AddRec->getLoop()->getHeader()->begin();
   if (auto *U = dyn_cast<SCEVUnknown>(S))
@@ -7253,14 +7269,13 @@ ScalarEvolution::getNonTrivialDefiningScopeBound(const SCEV *S) {
   return nullptr;
 }
 
-const Instruction *
-ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops,
-                                       bool &Precise) {
+const Instruction *ScalarEvolution::getDefiningScopeBound(ArrayRef<SCEVUse> Ops,
+                                                          bool &Precise) {
   Precise = true;
   // Do a bounded search of the def relation of the requested SCEVs.
-  SmallSet<const SCEV *, 16> Visited;
-  SmallVector<const SCEV *> Worklist;
-  auto pushOp = [&](const SCEV *S) {
+  SmallSet<SCEVUse, 16> Visited;
+  SmallVector<SCEVUse> Worklist;
+  auto pushOp = [&](SCEVUse S) {
     if (!Visited.insert(S).second)
       return;
     // Threshold of 30 here is arbitrary.
@@ -7271,17 +7286,17 @@ ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops,
     Worklist.push_back(S);
   };
 
-  for (const auto *S : Ops)
+  for (const auto S : Ops)
     pushOp(S);
 
   const Instruction *Bound = nullptr;
   while (!Worklist.empty()) {
-    auto *S = Worklist.pop_back_val();
+    auto S = Worklist.pop_back_val();
     if (auto *DefI = getNonTrivialDefiningScopeBound(S)) {
       if (!Bound || DT.dominates(Bound, DefI))
         Bound = DefI;
     } else {
-      for (const auto *Op : S->operands())
+      for (const auto Op : S->operands())
         pushOp(Op);
     }
   }
@@ -7289,7 +7304,7 @@ ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops,
 }
 
 const Instruction *
-ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops) {
+ScalarEvolution::getDefiningScopeBound(ArrayRef<SCEVUse> Ops) {
   bool Discard;
   return getDefiningScopeBound(Ops, Discard);
 }
@@ -7329,7 +7344,7 @@ bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
   // executed every time we enter that scope.  When the bounding scope is a
   // loop (the common case), this is equivalent to proving I executes on every
   // iteration of that loop.
-  SmallVector<const SCEV *> SCEVOps;
+  SmallVector<SCEVUse> SCEVOps;
   for (const Use &Op : I->operands()) {
     // I could be an extractvalue from a call to an overflow intrinsic.
     // TODO: We can do better here in some cases.
@@ -7425,7 +7440,7 @@ bool ScalarEvolution::loopIsFiniteByAssumption(const Loop *L) {
   return isFinite(L) || (isMustProgress(L) && loopHasNoSideEffects(L));
 }
 
-const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
+SCEVUse ScalarEvolution::createSCEVIter(Value *V) {
   // Worklist item with a Value and a bool indicating whether all operands have
   // been visited already.
   using PointerTy = PointerIntPair<Value *, 1, bool>;
@@ -7441,7 +7456,7 @@ const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
       continue;
 
     SmallVector<Value *> Ops;
-    const SCEV *CreatedSCEV = nullptr;
+    SCEVUse CreatedSCEV = nullptr;
     // If all operands have been visited already, create the SCEV.
     if (E.getInt()) {
       CreatedSCEV = createSCEV(CurV);
@@ -7466,8 +7481,8 @@ const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
   return getExistingSCEV(V);
 }
 
-const SCEV *
-ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
+SCEVUse ScalarEvolution::getOperandsToCreate(Value *V,
+                                             SmallVectorImpl<Value *> &Ops) {
   if (!isSCEVable(V->getType()))
     return getUnknown(V);
 
@@ -7653,7 +7668,7 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
   return nullptr;
 }
 
-const SCEV *ScalarEvolution::createSCEV(Value *V) {
+SCEVUse ScalarEvolution::createSCEV(Value *V) {
   if (!isSCEVable(V->getType()))
     return getUnknown(V);
 
@@ -7671,8 +7686,8 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
   else if (!isa<ConstantExpr>(V))
     return getUnknown(V);
 
-  const SCEV *LHS;
-  const SCEV *RHS;
+  SCEVUse LHS;
+  SCEVUse RHS;
 
   Operator *U = cast<Operator>(V);
   if (auto BO =
@@ -7685,10 +7700,10 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
       // because it leads to N-1 getAddExpr calls for N ultimate operands.
       // Instead, gather up all the operands and make a single getAddExpr call.
       // LLVM IR canonical form means we need only traverse the left operands.
-      SmallVector<const SCEV *, 4> AddOps;
+      SmallVector<SCEVUse, 4> AddOps;
       do {
         if (BO->Op) {
-          if (auto *OpSCEV = getExistingSCEV(BO->Op)) {
+          if (auto OpSCEV = getExistingSCEV(BO->Op)) {
             AddOps.push_back(OpSCEV);
             break;
           }
@@ -7700,10 +7715,10 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
           // since the flags are only known to apply to this particular
           // addition - they may not apply to other additions that can be
           // formed with operands from AddOps.
-          const SCEV *RHS = getSCEV(BO->RHS);
+          SCEVUse RHS = getSCEV(BO->RHS);
           SCEV::NoWrapFlags Flags = getNoWrapFlagsFromUB(BO->Op);
           if (Flags != SCEV::FlagAnyWrap) {
-            const SCEV *LHS = getSCEV(BO->LHS);
+            SCEVUse LHS = getSCEV(BO->LHS);
             if (BO->Opcode == Instruction::Sub)
               AddOps.push_back(getMinusSCEV(LHS, RHS, Flags));
             else
@@ -7731,10 +7746,10 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
     }
 
     case Instruction::Mul: {
-      SmallVector<const SCEV *, 4> MulOps;
+      SmallVector<SCEVUse, 4> MulOps;
       do {
         if (BO->Op) {
-          if (auto *OpSCEV = getExistingSCEV(BO->Op)) {
+          if (auto OpSCEV = getExistingSCEV(BO->Op)) {
             MulOps.push_back(OpSCEV);
             break;
           }
@@ -7800,19 +7815,19 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
         APInt EffectiveMask =
             APInt::getLowBitsSet(BitWidth, BitWidth - LZ - TZ).shl(TZ);
         if ((LZ != 0 || TZ != 0) && !((~A & ~Known.Zero) & EffectiveMask)) {
-          const SCEV *MulCount = getConstant(APInt::getOneBitSet(BitWidth, TZ));
-          const SCEV *LHS = getSCEV(BO->LHS);
-          const SCEV *ShiftedLHS = nullptr;
+          SCEVUse MulCount = getConstant(APInt::getOneBitSet(BitWidth, TZ));
+          SCEVUse LHS = getSCEV(BO->LHS);
+          SCEVUse ShiftedLHS = nullptr;
           if (auto *LHSMul = dyn_cast<SCEVMulExpr>(LHS)) {
             if (auto *OpC = dyn_cast<SCEVConstant>(LHSMul->getOperand(0))) {
               // For an expression like (x * 8) & 8, simplify the multiply.
               unsigned MulZeros = OpC->getAPInt().countr_zero();
               unsigned GCD = std::min(MulZeros, TZ);
               APInt DivAmt = APInt::getOneBitSet(BitWidth, TZ - GCD);
-              SmallVector<const SCEV*, 4> MulOps;
+              SmallVector<SCEVUse, 4> MulOps;
               MulOps.push_back(getConstant(OpC->getAPInt().lshr(GCD)));
               append_range(MulOps, LHSMul->operands().drop_front());
-              auto *NewMul = getMulExpr(MulOps, LHSMul->getNoWrapFlags());
+              auto NewMul = getMulExpr(MulOps, LHSMul->getNoWrapFlags());
               ShiftedLHS = getUDivExpr(NewMul, getConstant(DivAmt));
             }
           }
@@ -7860,7 +7875,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
               if (const SCEVZeroExtendExpr *Z =
                       dyn_cast<SCEVZeroExtendExpr>(getSCEV(BO->LHS))) {
                 Type *UTy = BO->LHS->getType();
-                const SCEV *Z0 = Z->getOperand();
+                SCEVUse Z0 = Z->getOperand();
                 Type *Z0Ty = Z0->getType();
                 unsigned Z0TySize = getTypeSizeInBits(Z0Ty);
 
@@ -7936,9 +7951,9 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
       Type *TruncTy = IntegerType::get(getContext(), BitWidth - AShrAmt);
 
       Operator *L = dyn_cast<Operator>(BO->LHS);
-      const SCEV *AddTruncateExpr = nullptr;
+      SCEVUse AddTruncateExpr = nullptr;
       ConstantInt *ShlAmtCI = nullptr;
-      const SCEV *AddConstant = nullptr;
+      SCEVUse AddConstant = nullptr;
 
       if (L && L->getOpcode() == Instruction::Add) {
         // X = Shl A, n
@@ -7950,7 +7965,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
         ConstantInt *AddOperandCI = dyn_cast<ConstantInt>(L->getOperand(1));
         if (LShift && LShift->getOpcode() == Instruction::Shl) {
           if (AddOperandCI) {
-            const SCEV *ShlOp0SCEV = getSCEV(LShift->getOperand(0));
+            SCEVUse ShlOp0SCEV = getSCEV(LShift->getOperand(0));
             ShlAmtCI = dyn_cast<ConstantInt>(LShift->getOperand(1));
             // since we truncate to TruncTy, the AddConstant should be of the
             // same type, so create a new Constant with type same as TruncTy.
@@ -7968,7 +7983,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
         // Y = AShr X, m
         // Both n and m are constant.
 
-        const SCEV *ShlOp0SCEV = getSCEV(L->getOperand(0));
+        SCEVUse ShlOp0SCEV = getSCEV(L->getOperand(0));
         ShlAmtCI = dyn_cast<ConstantInt>(L->getOperand(1));
         AddTruncateExpr = getTruncateExpr(ShlOp0SCEV, TruncTy);
       }
@@ -7989,8 +8004,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
         if (ShlAmt.ult(BitWidth) && ShlAmt.uge(AShrAmt)) {
           APInt Mul = APInt::getOneBitSet(BitWidth - AShrAmt,
                                           ShlAmtCI->getZExtValue() - AShrAmt);
-          const SCEV *CompositeExpr =
-              getMulExpr(AddTruncateExpr, getConstant(Mul));
+          SCEVUse CompositeExpr = getMulExpr(AddTruncateExpr, getConstant(Mul));
           if (L->getOpcode() != Instruction::Shl)
             CompositeExpr = getAddExpr(CompositeExpr, AddConstant);
 
@@ -8020,8 +8034,8 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
       // but by that point the NSW information has potentially been lost.
       if (BO->Opcode == Instruction::Sub && BO->IsNSW) {
         Type *Ty = U->getType();
-        auto *V1 = getSignExtendExpr(getSCEV(BO->LHS), Ty);
-        auto *V2 = getSignExtendExpr(getSCEV(BO->RHS), Ty);
+        auto V1 = getSignExtendExpr(getSCEV(BO->LHS), Ty);
+        auto V2 = getSignExtendExpr(getSCEV(BO->RHS), Ty);
         return getMinusSCEV(V1, V2, SCEV::FlagNSW);
       }
     }
@@ -8035,11 +8049,11 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
 
   case Instruction::PtrToInt: {
     // Pointer to integer cast is straight-forward, so do model it.
-    const SCEV *Op = getSCEV(U->getOperand(0));
+    SCEVUse Op = getSCEV(U->getOperand(0));
     Type *DstIntTy = U->getType();
     // But only if effective SCEV (integer) type is wide enough to represent
     // all possible pointer values.
-    const SCEV *IntOp = getPtrToIntExpr(Op, DstIntTy);
+    SCEVUse IntOp = getPtrToIntExpr(Op, DstIntTy);
     if (isa<SCEVCouldNotCompute>(IntOp))
       return getUnknown(V);
     return IntOp;
@@ -8100,15 +8114,15 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
         RHS = getSCEV(II->getArgOperand(1));
         return getSMinExpr(LHS, RHS);
       case Intrinsic::usub_sat: {
-        const SCEV *X = getSCEV(II->getArgOperand(0));
-        const SCEV *Y = getSCEV(II->getArgOperand(1));
-        const SCEV *ClampedY = getUMinExpr(X, Y);
+        SCEVUse X = getSCEV(II->getArgOperand(0));
+        SCEVUse Y = getSCEV(II->getArgOperand(1));
+        SCEVUse ClampedY = getUMinExpr(X, Y);
         return getMinusSCEV(X, ClampedY, SCEV::FlagNUW);
       }
       case Intrinsic::uadd_sat: {
-        const SCEV *X = getSCEV(II->getArgOperand(0));
-        const SCEV *Y = getSCEV(II->getArgOperand(1));
-        const SCEV *ClampedX = getUMinExpr(X, getNotSCEV(Y));
+        SCEVUse X = getSCEV(II->getArgOperand(0));
+        SCEVUse Y = getSCEV(II->getArgOperand(1));
+        SCEVUse ClampedX = getUMinExpr(X, getNotSCEV(Y));
         return getAddExpr(ClampedX, Y, SCEV::FlagNUW);
       }
       case Intrinsic::start_loop_iterations:
@@ -8133,7 +8147,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
 //                   Iteration Count Computation Code
 //
 
-const SCEV *ScalarEvolution::getTripCountFromExitCount(const SCEV *ExitCount) {
+SCEVUse ScalarEvolution::getTripCountFromExitCount(SCEVUse ExitCount) {
   if (isa<SCEVCouldNotCompute>(ExitCount))
     return getCouldNotCompute();
 
@@ -8144,9 +8158,9 @@ const SCEV *ScalarEvolution::getTripCountFromExitCount(const SCEV *ExitCount) {
   return getTripCountFromExitCount(ExitCount, EvalTy, nullptr);
 }
 
-const SCEV *ScalarEvolution::getTripCountFromExitCount(const SCEV *ExitCount,
-                                                       Type *EvalTy,
-                                                       const Loop *L) {
+SCEVUse ScalarEvolution::getTripCountFromExitCount(SCEVUse ExitCount,
+                                                   Type *EvalTy,
+                                                   const Loop *L) {
   if (isa<SCEVCouldNotCompute>(ExitCount))
     return getCouldNotCompute();
 
@@ -8225,12 +8239,12 @@ unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L) {
 }
 
 unsigned ScalarEvolution::getSmallConstantTripMultiple(const Loop *L,
-                                                       const SCEV *ExitCount) {
+                                                       SCEVUse ExitCount) {
   if (ExitCount == getCouldNotCompute())
     return 1;
 
   // Get the trip count
-  const SCEV *TCExpr = getTripCountFromExitCount(applyLoopGuards(ExitCount, L));
+  SCEVUse TCExpr = getTripCountFromExitCount(applyLoopGuards(ExitCount, L));
 
   APInt Multiple = getNonZeroConstantMultiple(TCExpr);
   // If a trip multiple is huge (>=2^32), the trip count is still divisible by
@@ -8258,13 +8272,13 @@ ScalarEvolution::getSmallConstantTripMultiple(const Loop *L,
   assert(ExitingBlock && "Must pass a non-null exiting block!");
   assert(L->isLoopExiting(ExitingBlock) &&
          "Exiting block must actually branch out of the loop!");
-  const SCEV *ExitCount = getExitCount(L, ExitingBlock);
+  SCEVUse ExitCount = getExitCount(L, ExitingBlock);
   return getSmallConstantTripMultiple(L, ExitCount);
 }
 
-const SCEV *ScalarEvolution::getExitCount(const Loop *L,
-                                          const BasicBlock *ExitingBlock,
-                                          ExitCountKind Kind) {
+SCEVUse ScalarEvolution::getExitCount(const Loop *L,
+                                      const BasicBlock *ExitingBlock,
+                                      ExitCountKind Kind) {
   switch (Kind) {
   case Exact:
     return getBackedgeTakenInfo(L).getExact(ExitingBlock, this);
@@ -8276,14 +8290,13 @@ const SCEV *ScalarEvolution::getExitCount(const Loop *L,
   llvm_unreachable("Invalid ExitCountKind!");
 }
 
-const SCEV *
-ScalarEvolution::getPredicatedBackedgeTakenCount(const Loop *L,
-                                                 SmallVector<const SCEVPredicate *, 4> &Preds) {
+SCEVUse ScalarEvolution::getPredicatedBackedgeTakenCount(
+    const Loop *L, SmallVector<const SCEVPredicate *, 4> &Preds) {
   return getPredicatedBackedgeTakenInfo(L).getExact(L, this, &Preds);
 }
 
-const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L,
-                                                   ExitCountKind Kind) {
+SCEVUse ScalarEvolution::getBackedgeTakenCount(const Loop *L,
+                                               ExitCountKind Kind) {
   switch (Kind) {
   case Exact:
     return getBackedgeTakenInfo(L).getExact(L, this);
@@ -8352,7 +8365,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
   // only done to produce more precise results.
   if (Result.hasAnyInfo()) {
     // Invalidate any expression using an addrec in this loop.
-    SmallVector<const SCEV *, 8> ToForget;
+    SmallVector<SCEVUse, 8> ToForget;
     auto LoopUsersIt = LoopUsers.find(L);
     if (LoopUsersIt != LoopUsers.end())
       append_range(ToForget, LoopUsersIt->second);
@@ -8399,7 +8412,7 @@ void ScalarEvolution::forgetAllLoops() {
 void ScalarEvolution::visitAndClearUsers(
     SmallVectorImpl<Instruction *> &Worklist,
     SmallPtrSetImpl<Instruction *> &Visited,
-    SmallVectorImpl<const SCEV *> &ToForget) {
+    SmallVectorImpl<SCEVUse> &ToForget) {
   while (!Worklist.empty()) {
     Instruction *I = Worklist.pop_back_val();
     if (!isSCEVable(I->getType()))
@@ -8422,7 +8435,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
   SmallVector<const Loop *, 16> LoopWorklist(1, L);
   SmallVector<Instruction *, 32> Worklist;
   SmallPtrSet<Instruction *, 16> Visited;
-  SmallVector<const SCEV *, 16> ToForget;
+  SmallVector<SCEVUse, 16> ToForget;
 
   // Iterate over all the loops and sub-loops to drop SCEV information.
   while (!LoopWorklist.empty()) {
@@ -8435,7 +8448,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
     // Drop information about predicated SCEV rewrites for this loop.
     for (auto I = PredicatedSCEVRewrites.begin();
          I != PredicatedSCEVRewrites.end();) {
-      std::pair<const SCEV *, const Loop *> Entry = I->first;
+      std::pair<SCEVUse, const Loop *> Entry = I->first;
       if (Entry.second == CurrL)
         PredicatedSCEVRewrites.erase(I++);
       else
@@ -8471,7 +8484,7 @@ void ScalarEvolution::forgetValue(Value *V) {
   // Drop information about expressions based on loop-header PHIs.
   SmallVector<Instruction *, 16> Worklist;
   SmallPtrSet<Instruction *, 8> Visited;
-  SmallVector<const SCEV *, 8> ToForget;
+  SmallVector<SCEVUse, 8> ToForget;
   Worklist.push_back(I);
   Visited.insert(I);
   visitAndClearUsers(Worklist, Visited, ToForget);
@@ -8487,14 +8500,14 @@ void ScalarEvolution::forgetLcssaPhiWithNewPredecessor(Loop *L, PHINode *V) {
   // directly using a SCEVUnknown/SCEVAddRec defined in the loop. After an
   // extra predecessor is added, this is no longer valid. Find all Unknowns and
   // AddRecs defined in the loop and invalidate any SCEV's making use of them.
-  if (const SCEV *S = getExistingSCEV(V)) {
+  if (SCEVUse S = getExistingSCEV(V)) {
     struct InvalidationRootCollector {
       Loop *L;
-      SmallVector<const SCEV *, 8> Roots;
+      SmallVector<SCEVUse, 8> Roots;
 
       InvalidationRootCollector(Loop *L) : L(L) {}
 
-      bool follow(const SCEV *S) {
+      bool follow(SCEVUse S) {
         if (auto *SU = dyn_cast<SCEVUnknown>(S)) {
           if (auto *I = dyn_cast<Instruction>(SU->getValue()))
             if (L->contains(I))
@@ -8531,7 +8544,7 @@ void ScalarEvolution::forgetBlockAndLoopDispositions(Value *V) {
   if (!isSCEVable(V->getType()))
     return;
 
-  const SCEV *S = getExistingSCEV(V);
+  SCEVUse S = getExistingSCEV(V);
   if (!S)
     return;
 
@@ -8539,17 +8552,17 @@ void ScalarEvolution::forgetBlockAndLoopDispositions(Value *V) {
   // S's users may change if S's disposition changes (i.e. a user may change to
   // loop-invariant, if S changes to loop invariant), so also invalidate
   // dispositions of S's users recursively.
-  SmallVector<const SCEV *, 8> Worklist = {S};
-  SmallPtrSet<const SCEV *, 8> Seen = {S};
+  SmallVector<SCEVUse, 8> Worklist = {S};
+  SmallPtrSet<SCEVUse, 8> Seen = {S};
   while (!Worklist.empty()) {
-    const SCEV *Curr = Worklist.pop_back_val();
+    SCEVUse Curr = Worklist.pop_back_val();
     bool LoopDispoRemoved = LoopDispositions.erase(Curr);
     bool BlockDispoRemoved = BlockDispositions.erase(Curr);
     if (!LoopDispoRemoved && !BlockDispoRemoved)
       continue;
     auto Users = SCEVUsers.find(Curr);
     if (Users != SCEVUsers.end())
-      for (const auto *User : Users->second)
+      for (const auto User : Users->second)
         if (Seen.insert(User).second)
           Worklist.push_back(User);
   }
@@ -8561,9 +8574,9 @@ void ScalarEvolution::forgetBlockAndLoopDispositions(Value *V) {
 /// is never skipped. This is a valid assumption as long as the loop exits via
 /// that test. For precise results, it is the caller's responsibility to specify
 /// the relevant loop exiting block using getExact(ExitingBlock, SE).
-const SCEV *
-ScalarEvolution::BackedgeTakenInfo::getExact(const Loop *L, ScalarEvolution *SE,
-                                             SmallVector<const SCEVPredicate *, 4> *Preds) const {
+SCEVUse ScalarEvolution::BackedgeTakenInfo::getExact(
+    const Loop *L, ScalarEvolution *SE,
+    SmallVector<const SCEVPredicate *, 4> *Preds) const {
   // If any exits were not computable, the loop is not computable.
   if (!isComplete() || ExitNotTaken.empty())
     return SE->getCouldNotCompute();
@@ -8575,9 +8588,9 @@ ScalarEvolution::BackedgeTakenInfo::getExact(const Loop *L, ScalarEvolution *SE,
 
   // All exiting blocks we have gathered dominate loop's latch, so exact trip
   // count is simply a minimum out of all these calculated exit counts.
-  SmallVector<const SCEV *, 2> Ops;
+  SmallVector<SCEVUse, 2> Ops;
   for (const auto &ENT : ExitNotTaken) {
-    const SCEV *BECount = ENT.ExactNotTaken;
+    SCEVUse BECount = ENT.ExactNotTaken;
     assert(BECount != SE->getCouldNotCompute() && "Bad exit SCEV!");
     assert(SE->DT.dominates(ENT.ExitingBlock, Latch) &&
            "We should only have known counts for exiting blocks that dominate "
@@ -8600,7 +8613,7 @@ ScalarEvolution::BackedgeTakenInfo::getExact(const Loop *L, ScalarEvolution *SE,
 }
 
 /// Get the exact not taken count for this loop exit.
-const SCEV *
+SCEVUse
 ScalarEvolution::BackedgeTakenInfo::getExact(const BasicBlock *ExitingBlock,
                                              ScalarEvolution *SE) const {
   for (const auto &ENT : ExitNotTaken)
@@ -8610,7 +8623,7 @@ ScalarEvolution::BackedgeTakenInfo::getExact(const BasicBlock *ExitingBlock,
   return SE->getCouldNotCompute();
 }
 
-const SCEV *ScalarEvolution::BackedgeTakenInfo::getConstantMax(
+SCEVUse ScalarEvolution::BackedgeTakenInfo::getConstantMax(
     const BasicBlock *ExitingBlock, ScalarEvolution *SE) const {
   for (const auto &ENT : ExitNotTaken)
     if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePredicate())
@@ -8619,7 +8632,7 @@ const SCEV *ScalarEvolution::BackedgeTakenInfo::getConstantMax(
   return SE->getCouldNotCompute();
 }
 
-const SCEV *ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(
+SCEVUse ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(
     const BasicBlock *ExitingBlock, ScalarEvolution *SE) const {
   for (const auto &ENT : ExitNotTaken)
     if (ENT.ExitingBlock == ExitingBlock && ENT.hasAlwaysTruePredicate())
@@ -8629,7 +8642,7 @@ const SCEV *ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(
 }
 
 /// getConstantMax - Get the constant max backedge taken count for the loop.
-const SCEV *
+SCEVUse
 ScalarEvolution::BackedgeTakenInfo::getConstantMax(ScalarEvolution *SE) const {
   auto PredicateNotAlwaysTrue = [](const ExitNotTakenInfo &ENT) {
     return !ENT.hasAlwaysTruePredicate();
@@ -8644,7 +8657,7 @@ ScalarEvolution::BackedgeTakenInfo::getConstantMax(ScalarEvolution *SE) const {
   return getConstantMax();
 }
 
-const SCEV *
+SCEVUse
 ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(const Loop *L,
                                                    ScalarEvolution *SE) {
   if (!SymbolicMax)
@@ -8660,12 +8673,12 @@ bool ScalarEvolution::BackedgeTakenInfo::isConstantMaxOrZero(
   return MaxOrZero && !any_of(ExitNotTaken, PredicateNotAlwaysTrue);
 }
 
-ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E)
+ScalarEvolution::ExitLimit::ExitLimit(SCEVUse E)
     : ExitLimit(E, E, E, false, std::nullopt) {}
 
 ScalarEvolution::ExitLimit::ExitLimit(
-    const SCEV *E, const SCEV *ConstantMaxNotTaken,
-    const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
+    SCEVUse E, SCEVUse ConstantMaxNotTaken, SCEVUse SymbolicMaxNotTaken,
+    bool MaxOrZero,
     ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *> PredSetList)
     : ExactNotTaken(E), ConstantMaxNotTaken(ConstantMaxNotTaken),
       SymbolicMaxNotTaken(SymbolicMaxNotTaken), MaxOrZero(MaxOrZero) {
@@ -8700,17 +8713,16 @@ ScalarEvolution::ExitLimit::ExitLimit(
 }
 
 ScalarEvolution::ExitLimit::ExitLimit(
-    const SCEV *E, const SCEV *ConstantMaxNotTaken,
-    const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
-    const SmallPtrSetImpl<const SCEVPredicate *> &PredSet)
+    SCEVUse E, SCEVUse ConstantMaxNotTaken, SCEVUse SymbolicMaxNotTaken,
+    bool MaxOrZero, const SmallPtrSetImpl<const SCEVPredicate *> &PredSet)
     : ExitLimit(E, ConstantMaxNotTaken, SymbolicMaxNotTaken, MaxOrZero,
-                { &PredSet }) {}
+                {&PredSet}) {}
 
 /// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each
 /// computable exit into a persistent ExitNotTakenInfo array.
 ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo(
     ArrayRef<ScalarEvolution::BackedgeTakenInfo::EdgeExitInfo> ExitCounts,
-    bool IsComplete, const SCEV *ConstantMax, bool MaxOrZero)
+    bool IsComplete, SCEVUse ConstantMax, bool MaxOrZero)
     : ConstantMax(ConstantMax), IsComplete(IsComplete), MaxOrZero(MaxOrZero) {
   using EdgeExitInfo = ScalarEvolution::BackedgeTakenInfo::EdgeExitInfo;
 
@@ -8741,8 +8753,8 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
   SmallVector<EdgeExitInfo, 4> ExitCounts;
   bool CouldComputeBECount = true;
   BasicBlock *Latch = L->getLoopLatch(); // may be NULL.
-  const SCEV *MustExitMaxBECount = nullptr;
-  const SCEV *MayExitMaxBECount = nullptr;
+  SCEVUse MustExitMaxBECount = nullptr;
+  SCEVUse MayExitMaxBECount = nullptr;
   bool MustExitMaxOrZero = false;
 
   // Compute the ExitLimit for each loop exit. Use this to populate ExitCounts
@@ -8813,8 +8825,10 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
       }
     }
   }
-  const SCEV *MaxBECount = MustExitMaxBECount ? MustExitMaxBECount :
-    (MayExitMaxBECount ? MayExitMaxBECount : getCouldNotCompute());
+  SCEVUse MaxBECount =
+      MustExitMaxBECount
+          ? MustExitMaxBECount
+          : (MayExitMaxBECount ? MayExitMaxBECount : getCouldNotCompute());
   // The loop backedge will be taken the maximum or zero times if there's
   // a single exit that must be taken the maximum or zero times.
   bool MaxOrZero = (MustExitMaxOrZero && ExitingBlocks.size() == 1);
@@ -8978,7 +8992,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromCondImpl(
     NWR.getEquivalentICmp(Pred, NewRHSC, Offset);
     if (!ExitIfTrue)
       Pred = ICmpInst::getInversePredicate(Pred);
-    auto *LHS = getSCEV(WO->getLHS());
+    auto LHS = getSCEV(WO->getLHS());
     if (Offset != 0)
       LHS = getAddExpr(LHS, getConstant(Offset));
     auto EL = computeExitLimitFromICmp(L, Pred, LHS, getConstant(NewRHSC),
@@ -9023,9 +9037,9 @@ ScalarEvolution::computeExitLimitFromCondFromBinOp(
   if (isa<ConstantInt>(Op0))
     return Op0 == NeutralElement ? EL1 : EL0;
 
-  const SCEV *BECount = getCouldNotCompute();
-  const SCEV *ConstantMaxBECount = getCouldNotCompute();
-  const SCEV *SymbolicMaxBECount = getCouldNotCompute();
+  SCEVUse BECount = getCouldNotCompute();
+  SCEVUse ConstantMaxBECount = getCouldNotCompute();
+  SCEVUse SymbolicMaxBECount = getCouldNotCompute();
   if (EitherMayExit) {
     bool UseSequentialUMin = !isa<BinaryOperator>(ExitCond);
     // Both conditions must be same for the loop to continue executing.
@@ -9083,16 +9097,15 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
     Pred = ExitCond->getInversePredicate();
   const ICmpInst::Predicate OriginalPred = Pred;
 
-  const SCEV *LHS = getSCEV(ExitCond->getOperand(0));
-  const SCEV *RHS = getSCEV(ExitCond->getOperand(1));
+  SCEVUse LHS = getSCEV(ExitCond->getOperand(0));
+  SCEVUse RHS = getSCEV(ExitCond->getOperand(1));
 
   ExitLimit EL = computeExitLimitFromICmp(L, Pred, LHS, RHS, ControlsOnlyExit,
                                           AllowPredicates);
   if (EL.hasAnyInfo())
     return EL;
 
-  auto *ExhaustiveCount =
-      computeExitCountExhaustively(L, ExitCond, ExitIfTrue);
+  auto ExhaustiveCount = computeExitCountExhaustively(L, ExitCond, ExitIfTrue);
 
   if (!isa<SCEVCouldNotCompute>(ExhaustiveCount))
     return ExhaustiveCount;
@@ -9101,7 +9114,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
                                       ExitCond->getOperand(1), L, OriginalPred);
 }
 ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
-    const Loop *L, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
+    const Loop *L, ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
     bool ControlsOnlyExit, bool AllowPredicates) {
 
   // Try to evaluate any dependencies out of the loop.
@@ -9130,7 +9143,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
         ConstantRange CompRange =
             ConstantRange::makeExactICmpRegion(Pred, RHSC->getAPInt());
 
-        const SCEV *Ret = AddRec->getNumIterationsInRange(CompRange, *this);
+        SCEVUse Ret = AddRec->getNumIterationsInRange(CompRange, *this);
         if (!isa<SCEVCouldNotCompute>(Ret)) return Ret;
       }
 
@@ -9142,7 +9155,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
   if (ControllingFiniteLoop && isLoopInvariant(RHS, L)) {
     // TODO: We can peel off any functions which are invertible *in L*.  Loop
     // invariant terms are effectively constants for our purposes here.
-    auto *InnerLHS = LHS;
+    auto InnerLHS = LHS;
     if (auto *ZExt = dyn_cast<SCEVZeroExtendExpr>(LHS))
       InnerLHS = ZExt->getOperand();
     if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(InnerLHS)) {
@@ -9151,7 +9164,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
           StrideC && StrideC->getAPInt().isPowerOf2()) {
         auto Flags = AR->getNoWrapFlags();
         Flags = setFlags(Flags, SCEV::FlagNW);
-        SmallVector<const SCEV*> Operands{AR->operands()};
+        SmallVector<SCEVUse> Operands{AR->operands()};
         Flags = StrengthenNoWrapFlags(this, scAddRecExpr, Operands, Flags);
         setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), Flags);
       }
@@ -9249,8 +9262,8 @@ ScalarEvolution::computeExitLimitFromSingleExitSwitch(const Loop *L,
 
   assert(L->contains(Switch->getDefaultDest()) &&
          "Default case must not exit the loop!");
-  const SCEV *LHS = getSCEVAtScope(Switch->getCondition(), L);
-  const SCEV *RHS = getConstant(Switch->findCaseDest(ExitingBlock));
+  SCEVUse LHS = getSCEVAtScope(Switch->getCondition(), L);
+  SCEVUse RHS = getConstant(Switch->findCaseDest(ExitingBlock));
 
   // while (X != Y) --> while (X-Y != 0)
   ExitLimit EL = howFarToZero(getMinusSCEV(LHS, RHS), L, ControlsOnlyExit);
@@ -9263,8 +9276,8 @@ ScalarEvolution::computeExitLimitFromSingleExitSwitch(const Loop *L,
 static ConstantInt *
 EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C,
                                 ScalarEvolution &SE) {
-  const SCEV *InVal = SE.getConstant(C);
-  const SCEV *Val = AddRec->evaluateAtIteration(InVal, SE);
+  SCEVUse InVal = SE.getConstant(C);
+  SCEVUse Val = AddRec->evaluateAtIteration(InVal, SE);
   assert(isa<SCEVConstant>(Val) &&
          "Evaluation of SCEV at constant didn't fold correctly?");
   return cast<SCEVConstant>(Val)->getValue();
@@ -9405,7 +9418,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeShiftCompareExitLimit(
 
   if (Result->isZeroValue()) {
     unsigned BitWidth = getTypeSizeInBits(RHS->getType());
-    const SCEV *UpperBound =
+    SCEVUse UpperBound =
         getConstant(getEffectiveSCEVType(RHS->getType()), BitWidth);
     return ExitLimit(getCouldNotCompute(), UpperBound, UpperBound, false);
   }
@@ -9655,9 +9668,9 @@ ScalarEvolution::getConstantEvolutionLoopExitValue(PHINode *PN,
   }
 }
 
-const SCEV *ScalarEvolution::computeExitCountExhaustively(const Loop *L,
-                                                          Value *Cond,
-                                                          bool ExitWhen) {
+SCEVUse ScalarEvolution::computeExitCountExhaustively(const Loop *L,
+                                                      Value *Cond,
+                                                      bool ExitWhen) {
   PHINode *PN = getConstantEvolvingPHI(Cond, L);
   if (!PN) return getCouldNotCompute();
 
@@ -9722,9 +9735,8 @@ const SCEV *ScalarEvolution::computeExitCountExhaustively(const Loop *L,
   return getCouldNotCompute();
 }
 
-const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
-  SmallVector<std::pair<const Loop *, const SCEV *>, 2> &Values =
-      ValuesAtScopes[V];
+SCEVUse ScalarEvolution::getSCEVAtScope(SCEVUse V, const Loop *L) {
+  SmallVector<std::pair<const Loop *, SCEVUse>, 2> &Values = ValuesAtScopes[V];
   // Check to see if we've folded this expression at this loop before.
   for (auto &LS : Values)
     if (LS.first == L)
@@ -9733,7 +9745,7 @@ const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
   Values.emplace_back(L, nullptr);
 
   // Otherwise compute it.
-  const SCEV *C = computeSCEVAtScope(V, L);
+  SCEVUse C = computeSCEVAtScope(V, L);
   for (auto &LS : reverse(ValuesAtScopes[V]))
     if (LS.first == L) {
       LS.second = C;
@@ -9748,7 +9760,7 @@ const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
 /// will return Constants for objects which aren't represented by a
 /// SCEVConstant, because SCEVConstant is restricted to ConstantInt.
 /// Returns NULL if the SCEV isn't representable as a Constant.
-static Constant *BuildConstantFromSCEV(const SCEV *V) {
+static Constant *BuildConstantFromSCEV(SCEVUse V) {
   switch (V->getSCEVType()) {
   case scCouldNotCompute:
   case scAddRecExpr:
@@ -9774,7 +9786,7 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
   case scAddExpr: {
     const SCEVAddExpr *SA = cast<SCEVAddExpr>(V);
     Constant *C = nullptr;
-    for (const SCEV *Op : SA->operands()) {
+    for (SCEVUse Op : SA->operands()) {
       Constant *OpC = BuildConstantFromSCEV(Op);
       if (!OpC)
         return nullptr;
@@ -9809,9 +9821,8 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
   llvm_unreachable("Unknown SCEV kind!");
 }
 
-const SCEV *
-ScalarEvolution::getWithOperands(const SCEV *S,
-                                 SmallVectorImpl<const SCEV *> &NewOps) {
+SCEVUse ScalarEvolution::getWithOperands(SCEVUse S,
+                                         SmallVectorImpl<SCEVUse> &NewOps) {
   switch (S->getSCEVType()) {
   case scTruncate:
   case scZeroExtend:
@@ -9845,7 +9856,7 @@ ScalarEvolution::getWithOperands(const SCEV *S,
   llvm_unreachable("Unknown SCEV kind!");
 }
 
-const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
+SCEVUse ScalarEvolution::computeSCEVAtScope(SCEVUse V, const Loop *L) {
   switch (V->getSCEVType()) {
   case scConstant:
   case scVScale:
@@ -9858,21 +9869,21 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
     // Avoid performing the look-up in the common case where the specified
     // expression has no loop-variant portions.
     for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) {
-      const SCEV *OpAtScope = getSCEVAtScope(AddRec->getOperand(i), L);
+      SCEVUse OpAtScope = getSCEVAtScope(AddRec->getOperand(i), L);
       if (OpAtScope == AddRec->getOperand(i))
         continue;
 
       // Okay, at least one of these operands is loop variant but might be
       // foldable.  Build a new instance of the folded commutative expression.
-      SmallVector<const SCEV *, 8> NewOps;
+      SmallVector<SCEVUse, 8> NewOps;
       NewOps.reserve(AddRec->getNumOperands());
       append_range(NewOps, AddRec->operands().take_front(i));
       NewOps.push_back(OpAtScope);
       for (++i; i != e; ++i)
         NewOps.push_back(getSCEVAtScope(AddRec->getOperand(i), L));
 
-      const SCEV *FoldedRec = getAddRecExpr(
-          NewOps, AddRec->getLoop(), AddRec->getNoWrapFlags(SCEV::FlagNW));
+      SCEVUse FoldedRec = getAddRecExpr(NewOps, AddRec->getLoop(),
+                                        AddRec->getNoWrapFlags(SCEV::FlagNW));
       AddRec = dyn_cast<SCEVAddRecExpr>(FoldedRec);
       // The addrec may be folded to a nonrecurrence, for example, if the
       // induction variable is multiplied by zero after constant folding. Go
@@ -9887,7 +9898,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
     if (!AddRec->getLoop()->contains(L)) {
       // To evaluate this recurrence, we need to know how many times the AddRec
       // loop iterates.  Compute this now.
-      const SCEV *BackedgeTakenCount = getBackedgeTakenCount(AddRec->getLoop());
+      SCEVUse BackedgeTakenCount = getBackedgeTakenCount(AddRec->getLoop());
       if (BackedgeTakenCount == getCouldNotCompute())
         return AddRec;
 
@@ -9909,15 +9920,15 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
   case scUMinExpr:
   case scSMinExpr:
   case scSequentialUMinExpr: {
-    ArrayRef<const SCEV *> Ops = V->operands();
+    ArrayRef<SCEVUse> Ops = V->operands();
     // Avoid performing the look-up in the common case where the specified
     // expression has no loop-variant portions.
     for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
-      const SCEV *OpAtScope = getSCEVAtScope(Ops[i], L);
+      SCEVUse OpAtScope = getSCEVAtScope(Ops[i], L);
       if (OpAtScope != Ops[i]) {
         // Okay, at least one of these operands is loop variant but might be
         // foldable.  Build a new instance of the folded commutative expression.
-        SmallVector<const SCEV *, 8> NewOps;
+        SmallVector<SCEVUse, 8> NewOps;
         NewOps.reserve(Ops.size());
         append_range(NewOps, Ops.take_front(i));
         NewOps.push_back(OpAtScope);
@@ -9950,7 +9961,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
         // to see if the loop that contains it has a known backedge-taken
         // count.  If so, we may be able to force computation of the exit
         // value.
-        const SCEV *BackedgeTakenCount = getBackedgeTakenCount(CurrLoop);
+        SCEVUse BackedgeTakenCount = getBackedgeTakenCount(CurrLoop);
         // This trivial case can show up in some degenerate cases where
         // the incoming IR has not yet been fully simplified.
         if (BackedgeTakenCount->isZero()) {
@@ -10015,8 +10026,8 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
       if (!isSCEVable(Op->getType()))
         return V;
 
-      const SCEV *OrigV = getSCEV(Op);
-      const SCEV *OpV = getSCEVAtScope(OrigV, L);
+      SCEVUse OrigV = getSCEV(Op);
+      SCEVUse OpV = getSCEVAtScope(OrigV, L);
       MadeImprovement |= OrigV != OpV;
 
       Constant *C = BuildConstantFromSCEV(OpV);
@@ -10044,11 +10055,11 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
   llvm_unreachable("Unknown SCEV type!");
 }
 
-const SCEV *ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) {
+SCEVUse ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) {
   return getSCEVAtScope(getSCEV(V), L);
 }
 
-const SCEV *ScalarEvolution::stripInjectiveFunctions(const SCEV *S) const {
+SCEVUse ScalarEvolution::stripInjectiveFunctions(SCEVUse S) const {
   if (const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S))
     return stripInjectiveFunctions(ZExt->getOperand());
   if (const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S))
@@ -10064,8 +10075,8 @@ const SCEV *ScalarEvolution::stripInjectiveFunctions(const SCEV *S) const {
 /// A and B isn't important.
 ///
 /// If the equation does not have a solution, SCEVCouldNotCompute is returned.
-static const SCEV *SolveLinEquationWithOverflow(const APInt &A, const SCEV *B,
-                                               ScalarEvolution &SE) {
+static SCEVUse SolveLinEquationWithOverflow(const APInt &A, SCEVUse B,
+                                            ScalarEvolution &SE) {
   uint32_t BW = A.getBitWidth();
   assert(BW == SE.getTypeSizeInBits(B->getType()));
   assert(A != 0 && "A must be non-zero.");
@@ -10097,7 +10108,7 @@ static const SCEV *SolveLinEquationWithOverflow(const APInt &A, const SCEV *B,
   // I * (B / D) mod (N / D)
   // To simplify the computation, we factor out the divide by D:
   // (I * B mod N) / D
-  const SCEV *D = SE.getConstant(APInt::getOneBitSet(BW, Mult2));
+  SCEVUse D = SE.getConstant(APInt::getOneBitSet(BW, Mult2));
   return SE.getUDivExactExpr(SE.getMulExpr(B, SE.getConstant(I)), D);
 }
 
@@ -10374,7 +10385,7 @@ SolveQuadraticAddRecRange(const SCEVAddRecExpr *AddRec,
   return TruncIfPossible(MinOptional(SL.first, SU.first), BitWidth);
 }
 
-ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
+ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(SCEVUse V,
                                                          const Loop *L,
                                                          bool ControlsOnlyExit,
                                                          bool AllowPredicates) {
@@ -10388,7 +10399,8 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
   // If the value is a constant
   if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
     // If the value is already zero, the branch will execute zero times.
-    if (C->getValue()->isZero()) return C;
+    if (C->getValue()->isZero())
+      return SCEVUse(C);
     return getCouldNotCompute();  // Otherwise it will loop infinitely.
   }
 
@@ -10433,8 +10445,8 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
   // where BW is the common bit width of Start and Step.
 
   // Get the initial value for the loop.
-  const SCEV *Start = getSCEVAtScope(AddRec->getStart(), L->getParentLoop());
-  const SCEV *Step = getSCEVAtScope(AddRec->getOperand(1), L->getParentLoop());
+  SCEVUse Start = getSCEVAtScope(AddRec->getStart(), L->getParentLoop());
+  SCEVUse Step = getSCEVAtScope(AddRec->getOperand(1), L->getParentLoop());
 
   // For now we handle only constant steps.
   //
@@ -10452,7 +10464,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
   //   N = Start/-Step
   // First compute the unsigned distance from zero in the direction of Step.
   bool CountDown = StepC->getAPInt().isNegative();
-  const SCEV *Distance = CountDown ? Start : getNegativeSCEV(Start);
+  SCEVUse Distance = CountDown ? Start : getNegativeSCEV(Start);
 
   // Handle unitary steps, which cannot wraparound.
   // 1*N = -Start; -1*N = Start (mod 2^BW), so:
@@ -10468,9 +10480,9 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
     // Explicitly handling this here is necessary because getUnsignedRange
     // isn't context-sensitive; it doesn't know that we only care about the
     // range inside the loop.
-    const SCEV *Zero = getZero(Distance->getType());
-    const SCEV *One = getOne(Distance->getType());
-    const SCEV *DistancePlusOne = getAddExpr(Distance, One);
+    SCEVUse Zero = getZero(Distance->getType());
+    SCEVUse One = getOne(Distance->getType());
+    SCEVUse DistancePlusOne = getAddExpr(Distance, One);
     if (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_NE, DistancePlusOne, Zero)) {
       // If Distance + 1 doesn't overflow, we can compute the maximum distance
       // as "unsigned_max(Distance + 1) - 1".
@@ -10488,34 +10500,33 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
   // will have undefined behavior due to wrapping.
   if (ControlsOnlyExit && AddRec->hasNoSelfWrap() &&
       loopHasNoAbnormalExits(AddRec->getLoop())) {
-    const SCEV *Exact =
+    SCEVUse Exact =
         getUDivExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step);
-    const SCEV *ConstantMax = getCouldNotCompute();
+    SCEVUse ConstantMax = getCouldNotCompute();
     if (Exact != getCouldNotCompute()) {
       APInt MaxInt = getUnsignedRangeMax(applyLoopGuards(Exact, L));
       ConstantMax =
           getConstant(APIntOps::umin(MaxInt, getUnsignedRangeMax(Exact)));
     }
-    const SCEV *SymbolicMax =
-        isa<SCEVCouldNotCompute>(Exact) ? ConstantMax : Exact;
+    SCEVUse SymbolicMax = isa<SCEVCouldNotCompute>(Exact) ? ConstantMax : Exact;
     return ExitLimit(Exact, ConstantMax, SymbolicMax, false, Predicates);
   }
 
   // Solve the general equation.
-  const SCEV *E = SolveLinEquationWithOverflow(StepC->getAPInt(),
-                                               getNegativeSCEV(Start), *this);
+  SCEVUse E = SolveLinEquationWithOverflow(StepC->getAPInt(),
+                                           getNegativeSCEV(Start), *this);
 
-  const SCEV *M = E;
+  SCEVUse M = E;
   if (E != getCouldNotCompute()) {
     APInt MaxWithGuards = getUnsignedRangeMax(applyLoopGuards(E, L));
     M = getConstant(APIntOps::umin(MaxWithGuards, getUnsignedRangeMax(E)));
   }
-  auto *S = isa<SCEVCouldNotCompute>(E) ? M : E;
+  auto S = isa<SCEVCouldNotCompute>(E) ? M : E;
   return ExitLimit(E, M, S, false, Predicates);
 }
 
-ScalarEvolution::ExitLimit
-ScalarEvolution::howFarToNonZero(const SCEV *V, const Loop *L) {
+ScalarEvolution::ExitLimit ScalarEvolution::howFarToNonZero(SCEVUse V,
+                                                            const Loop *L) {
   // Loops that look like: while (X == 0) are very strange indeed.  We don't
   // handle them yet except for the trivial case.  This could be expanded in the
   // future as needed.
@@ -10555,7 +10566,7 @@ ScalarEvolution::getPredecessorWithUniqueSuccessorForBB(const BasicBlock *BB)
 /// expressions are equal, however for the purposes of looking for a condition
 /// guarding a loop, it can be useful to be a little more general, since a
 /// front-end may have replicated the controlling expression.
-static bool HasSameValue(const SCEV *A, const SCEV *B) {
+static bool HasSameValue(SCEVUse A, SCEVUse B) {
   // Quick check to see if they are the same SCEV.
   if (A == B) return true;
 
@@ -10579,7 +10590,7 @@ static bool HasSameValue(const SCEV *A, const SCEV *B) {
   return false;
 }
 
-static bool MatchBinarySub(const SCEV *S, const SCEV *&LHS, const SCEV *&RHS) {
+static bool MatchBinarySub(SCEVUse S, SCEVUse &LHS, SCEVUse &RHS) {
   const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S);
   if (!Add || Add->getNumOperands() != 2)
     return false;
@@ -10599,7 +10610,7 @@ static bool MatchBinarySub(const SCEV *S, const SCEV *&LHS, const SCEV *&RHS) {
 }
 
 bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred,
-                                           const SCEV *&LHS, const SCEV *&RHS,
+                                           SCEVUse &LHS, SCEVUse &RHS,
                                            unsigned Depth) {
   bool Changed = false;
   // Simplifies ICMP to trivial true or false by turning it into '0 == 0' or
@@ -10783,23 +10794,23 @@ bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred,
   return Changed;
 }
 
-bool ScalarEvolution::isKnownNegative(const SCEV *S) {
+bool ScalarEvolution::isKnownNegative(SCEVUse S) {
   return getSignedRangeMax(S).isNegative();
 }
 
-bool ScalarEvolution::isKnownPositive(const SCEV *S) {
+bool ScalarEvolution::isKnownPositive(SCEVUse S) {
   return getSignedRangeMin(S).isStrictlyPositive();
 }
 
-bool ScalarEvolution::isKnownNonNegative(const SCEV *S) {
+bool ScalarEvolution::isKnownNonNegative(SCEVUse S) {
   return !getSignedRangeMin(S).isNegative();
 }
 
-bool ScalarEvolution::isKnownNonPositive(const SCEV *S) {
+bool ScalarEvolution::isKnownNonPositive(SCEVUse S) {
   return !getSignedRangeMax(S).isStrictlyPositive();
 }
 
-bool ScalarEvolution::isKnownNonZero(const SCEV *S) {
+bool ScalarEvolution::isKnownNonZero(SCEVUse S) {
   // Query push down for cases where the unsigned range is
   // less than sufficient.
   if (const auto *SExt = dyn_cast<SCEVSignExtendExpr>(S))
@@ -10807,20 +10818,20 @@ bool ScalarEvolution::isKnownNonZero(const SCEV *S) {
   return getUnsignedRangeMin(S) != 0;
 }
 
-std::pair<const SCEV *, const SCEV *>
-ScalarEvolution::SplitIntoInitAndPostInc(const Loop *L, const SCEV *S) {
+std::pair<SCEVUse, SCEVUse>
+ScalarEvolution::SplitIntoInitAndPostInc(const Loop *L, SCEVUse S) {
   // Compute SCEV on entry of loop L.
-  const SCEV *Start = SCEVInitRewriter::rewrite(S, L, *this);
+  SCEVUse Start = SCEVInitRewriter::rewrite(S, L, *this);
   if (Start == getCouldNotCompute())
     return { Start, Start };
   // Compute post increment SCEV for loop L.
-  const SCEV *PostInc = SCEVPostIncRewriter::rewrite(S, L, *this);
+  SCEVUse PostInc = SCEVPostIncRewriter::rewrite(S, L, *this);
   assert(PostInc != getCouldNotCompute() && "Unexpected could not compute");
   return { Start, PostInc };
 }
 
-bool ScalarEvolution::isKnownViaInduction(ICmpInst::Predicate Pred,
-                                          const SCEV *LHS, const SCEV *RHS) {
+bool ScalarEvolution::isKnownViaInduction(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                          SCEVUse RHS) {
   // First collect all loops.
   SmallPtrSet<const Loop *, 8> LoopsUsed;
   getUsedLoops(LHS, LoopsUsed);
@@ -10869,8 +10880,8 @@ bool ScalarEvolution::isKnownViaInduction(ICmpInst::Predicate Pred,
          isLoopEntryGuardedByCond(MDL, Pred, SplitLHS.first, SplitRHS.first);
 }
 
-bool ScalarEvolution::isKnownPredicate(ICmpInst::Predicate Pred,
-                                       const SCEV *LHS, const SCEV *RHS) {
+bool ScalarEvolution::isKnownPredicate(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                       SCEVUse RHS) {
   // Canonicalize the inputs first.
   (void)SimplifyICmpOperands(Pred, LHS, RHS);
 
@@ -10885,8 +10896,8 @@ bool ScalarEvolution::isKnownPredicate(ICmpInst::Predicate Pred,
 }
 
 std::optional<bool> ScalarEvolution::evaluatePredicate(ICmpInst::Predicate Pred,
-                                                       const SCEV *LHS,
-                                                       const SCEV *RHS) {
+                                                       SCEVUse LHS,
+                                                       SCEVUse RHS) {
   if (isKnownPredicate(Pred, LHS, RHS))
     return true;
   if (isKnownPredicate(ICmpInst::getInversePredicate(Pred), LHS, RHS))
@@ -10894,17 +10905,16 @@ std::optional<bool> ScalarEvolution::evaluatePredicate(ICmpInst::Predicate Pred,
   return std::nullopt;
 }
 
-bool ScalarEvolution::isKnownPredicateAt(ICmpInst::Predicate Pred,
-                                         const SCEV *LHS, const SCEV *RHS,
-                                         const Instruction *CtxI) {
+bool ScalarEvolution::isKnownPredicateAt(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                         SCEVUse RHS, const Instruction *CtxI) {
   // TODO: Analyze guards and assumes from Context's block.
   return isKnownPredicate(Pred, LHS, RHS) ||
          isBasicBlockEntryGuardedByCond(CtxI->getParent(), Pred, LHS, RHS);
 }
 
 std::optional<bool>
-ScalarEvolution::evaluatePredicateAt(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                     const SCEV *RHS, const Instruction *CtxI) {
+ScalarEvolution::evaluatePredicateAt(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                     SCEVUse RHS, const Instruction *CtxI) {
   std::optional<bool> KnownWithoutContext = evaluatePredicate(Pred, LHS, RHS);
   if (KnownWithoutContext)
     return KnownWithoutContext;
@@ -10920,7 +10930,7 @@ ScalarEvolution::evaluatePredicateAt(ICmpInst::Predicate Pred, const SCEV *LHS,
 
 bool ScalarEvolution::isKnownOnEveryIteration(ICmpInst::Predicate Pred,
                                               const SCEVAddRecExpr *LHS,
-                                              const SCEV *RHS) {
+                                              SCEVUse RHS) {
   const Loop *L = LHS->getLoop();
   return isLoopEntryGuardedByCond(L, Pred, LHS->getStart(), RHS) &&
          isLoopBackedgeGuardedByCond(L, Pred, LHS->getPostIncExpr(*this), RHS);
@@ -10978,7 +10988,7 @@ ScalarEvolution::getMonotonicPredicateTypeImpl(const SCEVAddRecExpr *LHS,
   if (!LHS->hasNoSignedWrap())
     return std::nullopt;
 
-  const SCEV *Step = LHS->getStepRecurrence(*this);
+  SCEVUse Step = LHS->getStepRecurrence(*this);
 
   if (isKnownNonNegative(Step))
     return IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;
@@ -10991,7 +11001,7 @@ ScalarEvolution::getMonotonicPredicateTypeImpl(const SCEVAddRecExpr *LHS,
 
 std::optional<ScalarEvolution::LoopInvariantPredicate>
 ScalarEvolution::getLoopInvariantPredicate(ICmpInst::Predicate Pred,
-                                           const SCEV *LHS, const SCEV *RHS,
+                                           SCEVUse LHS, SCEVUse RHS,
                                            const Loop *L,
                                            const Instruction *CtxI) {
   // If there is a loop-invariant, force it into the RHS, otherwise bail out.
@@ -11077,8 +11087,8 @@ ScalarEvolution::getLoopInvariantPredicate(ICmpInst::Predicate Pred,
 
 std::optional<ScalarEvolution::LoopInvariantPredicate>
 ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(
-    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const Loop *L,
-    const Instruction *CtxI, const SCEV *MaxIter) {
+    ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS, const Loop *L,
+    const Instruction *CtxI, SCEVUse MaxIter) {
   if (auto LIP = getLoopInvariantExitCondDuringFirstIterationsImpl(
           Pred, LHS, RHS, L, CtxI, MaxIter))
     return LIP;
@@ -11088,7 +11098,7 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(
     // work, try the following trick: if the a predicate is invariant for X, it
     // is also invariant for umin(X, ...). So try to find something that works
     // among subexpressions of MaxIter expressed as umin.
-    for (auto *Op : UMin->operands())
+    for (auto Op : UMin->operands())
       if (auto LIP = getLoopInvariantExitCondDuringFirstIterationsImpl(
               Pred, LHS, RHS, L, CtxI, Op))
         return LIP;
@@ -11097,8 +11107,8 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(
 
 std::optional<ScalarEvolution::LoopInvariantPredicate>
 ScalarEvolution::getLoopInvariantExitCondDuringFirstIterationsImpl(
-    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, const Loop *L,
-    const Instruction *CtxI, const SCEV *MaxIter) {
+    ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS, const Loop *L,
+    const Instruction *CtxI, SCEVUse MaxIter) {
   // Try to prove the following set of facts:
   // - The predicate is monotonic in the iteration space.
   // - If the check does not fail on the 1st iteration:
@@ -11125,9 +11135,9 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterationsImpl(
     return std::nullopt;
 
   // TODO: Support steps other than +/- 1.
-  const SCEV *Step = AR->getStepRecurrence(*this);
-  auto *One = getOne(Step->getType());
-  auto *MinusOne = getNegativeSCEV(One);
+  SCEVUse Step = AR->getStepRecurrence(*this);
+  auto One = getOne(Step->getType());
+  auto MinusOne = getNegativeSCEV(One);
   if (Step != One && Step != MinusOne)
     return std::nullopt;
 
@@ -11138,7 +11148,7 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterationsImpl(
     return std::nullopt;
 
   // Value of IV on suggested last iteration.
-  const SCEV *Last = AR->evaluateAtIteration(MaxIter, *this);
+  SCEVUse Last = AR->evaluateAtIteration(MaxIter, *this);
   // Does it still meet the requirement?
   if (!isLoopBackedgeGuardedByCond(L, Pred, Last, RHS))
     return std::nullopt;
@@ -11151,7 +11161,7 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterationsImpl(
       CmpInst::isSigned(Pred) ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
   if (Step == MinusOne)
     NoOverflowPred = CmpInst::getSwappedPredicate(NoOverflowPred);
-  const SCEV *Start = AR->getStart();
+  SCEVUse Start = AR->getStart();
   if (!isKnownPredicateAt(NoOverflowPred, Start, Last, CtxI))
     return std::nullopt;
 
@@ -11160,7 +11170,7 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterationsImpl(
 }
 
 bool ScalarEvolution::isKnownPredicateViaConstantRanges(
-    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS) {
+    ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS) {
   if (HasSameValue(LHS, RHS))
     return ICmpInst::isTrueWhenEqual(Pred);
 
@@ -11186,7 +11196,7 @@ bool ScalarEvolution::isKnownPredicateViaConstantRanges(
     auto UR = getUnsignedRange(RHS);
     if (CheckRanges(UL, UR))
       return true;
-    auto *Diff = getMinusSCEV(LHS, RHS);
+    auto Diff = getMinusSCEV(LHS, RHS);
     return !isa<SCEVCouldNotCompute>(Diff) && isKnownNonZero(Diff);
   }
 
@@ -11202,17 +11212,16 @@ bool ScalarEvolution::isKnownPredicateViaConstantRanges(
 }
 
 bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
-                                                    const SCEV *LHS,
-                                                    const SCEV *RHS) {
+                                                    SCEVUse LHS, SCEVUse RHS) {
   // Match X to (A + C1)<ExpectedFlags> and Y to (A + C2)<ExpectedFlags>, where
   // C1 and C2 are constant integers. If either X or Y are not add expressions,
   // consider them as X + 0 and Y + 0 respectively. C1 and C2 are returned via
   // OutC1 and OutC2.
-  auto MatchBinaryAddToConst = [this](const SCEV *X, const SCEV *Y,
-                                      APInt &OutC1, APInt &OutC2,
+  auto MatchBinaryAddToConst = [this](SCEVUse X, SCEVUse Y, APInt &OutC1,
+                                      APInt &OutC2,
                                       SCEV::NoWrapFlags ExpectedFlags) {
-    const SCEV *XNonConstOp, *XConstOp;
-    const SCEV *YNonConstOp, *YConstOp;
+    SCEVUse XNonConstOp, XConstOp;
+    SCEVUse YNonConstOp, YConstOp;
     SCEV::NoWrapFlags XFlagsPresent;
     SCEV::NoWrapFlags YFlagsPresent;
 
@@ -11295,8 +11304,7 @@ bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,
 }
 
 bool ScalarEvolution::isKnownPredicateViaSplitting(ICmpInst::Predicate Pred,
-                                                   const SCEV *LHS,
-                                                   const SCEV *RHS) {
+                                                   SCEVUse LHS, SCEVUse RHS) {
   if (Pred != ICmpInst::ICMP_ULT || ProvingSplitPredicate)
     return false;
 
@@ -11317,8 +11325,8 @@ bool ScalarEvolution::isKnownPredicateViaSplitting(ICmpInst::Predicate Pred,
 }
 
 bool ScalarEvolution::isImpliedViaGuard(const BasicBlock *BB,
-                                        ICmpInst::Predicate Pred,
-                                        const SCEV *LHS, const SCEV *RHS) {
+                                        ICmpInst::Predicate Pred, SCEVUse LHS,
+                                        SCEVUse RHS) {
   // No need to even try if we know the module has no guards.
   if (!HasGuards)
     return false;
@@ -11336,10 +11344,9 @@ bool ScalarEvolution::isImpliedViaGuard(const BasicBlock *BB,
 /// isLoopBackedgeGuardedByCond - Test whether the backedge of the loop is
 /// protected by a conditional between LHS and RHS.  This is used to
 /// to eliminate casts.
-bool
-ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
-                                             ICmpInst::Predicate Pred,
-                                             const SCEV *LHS, const SCEV *RHS) {
+bool ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
+                                                  ICmpInst::Predicate Pred,
+                                                  SCEVUse LHS, SCEVUse RHS) {
   // Interpret a null as meaning no loop, where there is obviously no guard
   // (interprocedural conditions notwithstanding). Do not bother about
   // unreachable loops.
@@ -11375,15 +11382,15 @@ ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
 
   // See if we can exploit a trip count to prove the predicate.
   const auto &BETakenInfo = getBackedgeTakenInfo(L);
-  const SCEV *LatchBECount = BETakenInfo.getExact(Latch, this);
+  SCEVUse LatchBECount = BETakenInfo.getExact(Latch, this);
   if (LatchBECount != getCouldNotCompute()) {
     // We know that Latch branches back to the loop header exactly
     // LatchBECount times.  This means the backdege condition at Latch is
     // equivalent to  "{0,+,1} u< LatchBECount".
     Type *Ty = LatchBECount->getType();
     auto NoWrapFlags = SCEV::NoWrapFlags(SCEV::FlagNUW | SCEV::FlagNW);
-    const SCEV *LoopCounter =
-      getAddRecExpr(getZero(Ty), getOne(Ty), L, NoWrapFlags);
+    SCEVUse LoopCounter =
+        getAddRecExpr(getZero(Ty), getOne(Ty), L, NoWrapFlags);
     if (isImpliedCond(Pred, LHS, RHS, ICmpInst::ICMP_ULT, LoopCounter,
                       LatchBECount))
       return true;
@@ -11444,8 +11451,7 @@ ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
 
 bool ScalarEvolution::isBasicBlockEntryGuardedByCond(const BasicBlock *BB,
                                                      ICmpInst::Predicate Pred,
-                                                     const SCEV *LHS,
-                                                     const SCEV *RHS) {
+                                                     SCEVUse LHS, SCEVUse RHS) {
   // Do not bother proving facts for unreachable code.
   if (!DT.isReachableFromEntry(BB))
     return true;
@@ -11544,8 +11550,7 @@ bool ScalarEvolution::isBasicBlockEntryGuardedByCond(const BasicBlock *BB,
 
 bool ScalarEvolution::isLoopEntryGuardedByCond(const Loop *L,
                                                ICmpInst::Predicate Pred,
-                                               const SCEV *LHS,
-                                               const SCEV *RHS) {
+                                               SCEVUse LHS, SCEVUse RHS) {
   // Interpret a null as meaning no loop, where there is obviously no guard
   // (interprocedural conditions notwithstanding).
   if (!L)
@@ -11563,10 +11568,9 @@ bool ScalarEvolution::isLoopEntryGuardedByCond(const Loop *L,
   return isBasicBlockEntryGuardedByCond(L->getHeader(), Pred, LHS, RHS);
 }
 
-bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                    const SCEV *RHS,
-                                    const Value *FoundCondValue, bool Inverse,
-                                    const Instruction *CtxI) {
+bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                    SCEVUse RHS, const Value *FoundCondValue,
+                                    bool Inverse, const Instruction *CtxI) {
   // False conditions implies anything. Do not bother analyzing it further.
   if (FoundCondValue ==
       ConstantInt::getBool(FoundCondValue->getContext(), Inverse))
@@ -11601,16 +11605,15 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
   else
     FoundPred = ICI->getPredicate();
 
-  const SCEV *FoundLHS = getSCEV(ICI->getOperand(0));
-  const SCEV *FoundRHS = getSCEV(ICI->getOperand(1));
+  SCEVUse FoundLHS = getSCEV(ICI->getOperand(0));
+  SCEVUse FoundRHS = getSCEV(ICI->getOperand(1));
 
   return isImpliedCond(Pred, LHS, RHS, FoundPred, FoundLHS, FoundRHS, CtxI);
 }
 
-bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
-                                    const SCEV *RHS,
-                                    ICmpInst::Predicate FoundPred,
-                                    const SCEV *FoundLHS, const SCEV *FoundRHS,
+bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                    SCEVUse RHS, ICmpInst::Predicate FoundPred,
+                                    SCEVUse FoundLHS, SCEVUse FoundRHS,
                                     const Instruction *CtxI) {
   // Balance the types.
   if (getTypeSizeInBits(LHS->getType()) <
@@ -11623,14 +11626,14 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
       auto *NarrowType = LHS->getType();
       auto *WideType = FoundLHS->getType();
       auto BitWidth = getTypeSizeInBits(NarrowType);
-      const SCEV *MaxValue = getZeroExtendExpr(
+      SCEVUse MaxValue = getZeroExtendExpr(
           getConstant(APInt::getMaxValue(BitWidth)), WideType);
       if (isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, FoundLHS,
                                           MaxValue) &&
           isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_ULE, FoundRHS,
                                           MaxValue)) {
-        const SCEV *TruncFoundLHS = getTruncateExpr(FoundLHS, NarrowType);
-        const SCEV *TruncFoundRHS = getTruncateExpr(FoundRHS, NarrowType);
+        SCEVUse TruncFoundLHS = getTruncateExpr(FoundLHS, NarrowType);
+        SCEVUse TruncFoundRHS = getTruncateExpr(FoundRHS, NarrowType);
         if (isImpliedCondBalancedTypes(Pred, LHS, RHS, FoundPred, TruncFoundLHS,
                                        TruncFoundRHS, CtxI))
           return true;
@@ -11662,10 +11665,12 @@ bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, const SCEV *LHS,
                                     FoundRHS, CtxI);
 }
 
-bool ScalarEvolution::isImpliedCondBalancedTypes(
-    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
-    ICmpInst::Predicate FoundPred, const SCEV *FoundLHS, const SCEV *FoundRHS,
-    const Instruction *CtxI) {
+bool ScalarEvolution::isImpliedCondBalancedTypes(ICmpInst::Predicate Pred,
+                                                 SCEVUse LHS, SCEVUse RHS,
+                                                 ICmpInst::Predicate FoundPred,
+                                                 SCEVUse FoundLHS,
+                                                 SCEVUse FoundRHS,
+                                                 const Instruction *CtxI) {
   assert(getTypeSizeInBits(LHS->getType()) ==
              getTypeSizeInBits(FoundLHS->getType()) &&
          "Types should be balanced!");
@@ -11743,8 +11748,8 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
     // Create local copies that we can freely swap and canonicalize our
     // conditions to "le/lt".
     ICmpInst::Predicate CanonicalPred = Pred, CanonicalFoundPred = FoundPred;
-    const SCEV *CanonicalLHS = LHS, *CanonicalRHS = RHS,
-               *CanonicalFoundLHS = FoundLHS, *CanonicalFoundRHS = FoundRHS;
+    SCEVUse CanonicalLHS = LHS, CanonicalRHS = RHS,
+            CanonicalFoundLHS = FoundLHS, CanonicalFoundRHS = FoundRHS;
     if (ICmpInst::isGT(CanonicalPred) || ICmpInst::isGE(CanonicalPred)) {
       CanonicalPred = ICmpInst::getSwappedPredicate(CanonicalPred);
       CanonicalFoundPred = ICmpInst::getSwappedPredicate(CanonicalFoundPred);
@@ -11777,7 +11782,7 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
       (isa<SCEVConstant>(FoundLHS) || isa<SCEVConstant>(FoundRHS))) {
 
     const SCEVConstant *C = nullptr;
-    const SCEV *V = nullptr;
+    SCEVUse V = nullptr;
 
     if (isa<SCEVConstant>(FoundLHS)) {
       C = cast<SCEVConstant>(FoundLHS);
@@ -11866,8 +11871,7 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
   return false;
 }
 
-bool ScalarEvolution::splitBinaryAdd(const SCEV *Expr,
-                                     const SCEV *&L, const SCEV *&R,
+bool ScalarEvolution::splitBinaryAdd(SCEVUse Expr, SCEVUse &L, SCEVUse &R,
                                      SCEV::NoWrapFlags &Flags) {
   const auto *AE = dyn_cast<SCEVAddExpr>(Expr);
   if (!AE || AE->getNumOperands() != 2)
@@ -11879,8 +11883,8 @@ bool ScalarEvolution::splitBinaryAdd(const SCEV *Expr,
   return true;
 }
 
-std::optional<APInt>
-ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) {
+std::optional<APInt> ScalarEvolution::computeConstantDifference(SCEVUse More,
+                                                                SCEVUse Less) {
   // We avoid subtracting expressions here because this function is usually
   // fairly deep in the call stack (i.e. is called many times).
 
@@ -11916,8 +11920,8 @@ ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) {
   }
 
   SCEV::NoWrapFlags Flags;
-  const SCEV *LLess = nullptr, *RLess = nullptr;
-  const SCEV *LMore = nullptr, *RMore = nullptr;
+  SCEVUse LLess = nullptr, RLess = nullptr;
+  SCEVUse LMore = nullptr, RMore = nullptr;
   const SCEVConstant *C1 = nullptr, *C2 = nullptr;
   // Compare (X + C1) vs X.
   if (splitBinaryAdd(Less, LLess, RLess, Flags))
@@ -11939,8 +11943,8 @@ ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) {
 }
 
 bool ScalarEvolution::isImpliedCondOperandsViaAddRecStart(
-    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
-    const SCEV *FoundLHS, const SCEV *FoundRHS, const Instruction *CtxI) {
+    ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS, SCEVUse FoundLHS,
+    SCEVUse FoundRHS, const Instruction *CtxI) {
   // Try to recognize the following pattern:
   //
   //   FoundRHS = ...
@@ -11984,8 +11988,8 @@ bool ScalarEvolution::isImpliedCondOperandsViaAddRecStart(
 }
 
 bool ScalarEvolution::isImpliedCondOperandsViaNoOverflow(
-    ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
-    const SCEV *FoundLHS, const SCEV *FoundRHS) {
+    ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS, SCEVUse FoundLHS,
+    SCEVUse FoundRHS) {
   if (Pred != CmpInst::ICMP_SLT && Pred != CmpInst::ICMP_ULT)
     return false;
 
@@ -12060,10 +12064,9 @@ bool ScalarEvolution::isImpliedCondOperandsViaNoOverflow(
                                   getConstant(FoundRHSLimit));
 }
 
-bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
-                                        const SCEV *LHS, const SCEV *RHS,
-                                        const SCEV *FoundLHS,
-                                        const SCEV *FoundRHS, unsigned Depth) {
+bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                        SCEVUse RHS, SCEVUse FoundLHS,
+                                        SCEVUse FoundRHS, unsigned Depth) {
   const PHINode *LPhi = nullptr, *RPhi = nullptr;
 
   auto ClearOnExit = make_scope_exit([&]() {
@@ -12117,7 +12120,7 @@ bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
   const BasicBlock *LBB = LPhi->getParent();
   const SCEVAddRecExpr *RAR = dyn_cast<SCEVAddRecExpr>(RHS);
 
-  auto ProvedEasily = [&](const SCEV *S1, const SCEV *S2) {
+  auto ProvedEasily = [&](SCEVUse S1, SCEVUse S2) {
     return isKnownViaNonRecursiveReasoning(Pred, S1, S2) ||
            isImpliedCondOperandsViaRanges(Pred, S1, S2, Pred, FoundLHS, FoundRHS) ||
            isImpliedViaOperations(Pred, S1, S2, FoundLHS, FoundRHS, Depth);
@@ -12129,8 +12132,8 @@ bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
     // the predicate is true for incoming values from this block, then the
     // predicate is also true for the Phis.
     for (const BasicBlock *IncBB : predecessors(LBB)) {
-      const SCEV *L = getSCEV(LPhi->getIncomingValueForBlock(IncBB));
-      const SCEV *R = getSCEV(RPhi->getIncomingValueForBlock(IncBB));
+      SCEVUse L = getSCEV(LPhi->getIncomingValueForBlock(IncBB));
+      SCEVUse R = getSCEV(RPhi->getIncomingValueForBlock(IncBB));
       if (!ProvedEasily(L, R))
         return false;
     }
@@ -12145,12 +12148,12 @@ bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
     auto *RLoop = RAR->getLoop();
     auto *Predecessor = RLoop->getLoopPredecessor();
     assert(Predecessor && "Loop with AddRec with no predecessor?");
-    const SCEV *L1 = getSCEV(LPhi->getIncomingValueForBlock(Predecessor));
+    SCEVUse L1 = getSCEV(LPhi->getIncomingValueForBlock(Predecessor));
     if (!ProvedEasily(L1, RAR->getStart()))
       return false;
     auto *Latch = RLoop->getLoopLatch();
     assert(Latch && "Loop with AddRec with no latch?");
-    const SCEV *L2 = getSCEV(LPhi->getIncomingValueForBlock(Latch));
+    SCEVUse L2 = getSCEV(LPhi->getIncomingValueForBlock(Latch));
     if (!ProvedEasily(L2, RAR->getPostIncExpr(*this)))
       return false;
   } else {
@@ -12162,7 +12165,7 @@ bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
       // Check that RHS is available in this block.
       if (!dominates(RHS, IncBB))
         return false;
-      const SCEV *L = getSCEV(LPhi->getIncomingValueForBlock(IncBB));
+      SCEVUse L = getSCEV(LPhi->getIncomingValueForBlock(IncBB));
       // Make sure L does not refer to a value from a potentially previous
       // iteration of a loop.
       if (!properlyDominates(L, LBB))
@@ -12175,10 +12178,9 @@ bool ScalarEvolution::isImpliedViaMerge(ICmpInst::Predicate Pred,
 }
 
 bool ScalarEvolution::isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred,
-                                                    const SCEV *LHS,
-                                                    const SCEV *RHS,
-                                                    const SCEV *FoundLHS,
-                                                    const SCEV *FoundRHS) {
+                                                    SCEVUse LHS, SCEVUse RHS,
+                                                    SCEVUse FoundLHS,
+                                                    SCEVUse FoundRHS) {
   // We want to imply LHS < RHS from LHS < (RHS >> shiftvalue).  First, make
   // sure that we are dealing with same LHS.
   if (RHS == FoundRHS) {
@@ -12198,7 +12200,7 @@ bool ScalarEvolution::isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred,
   using namespace PatternMatch;
   if (match(SUFoundRHS->getValue(),
             m_LShr(m_Value(Shiftee), m_Value(ShiftValue)))) {
-    auto *ShifteeS = getSCEV(Shiftee);
+    auto ShifteeS = getSCEV(Shiftee);
     // Prove one of the following:
     // LHS <u (shiftee >> shiftvalue) && shiftee <=u RHS ---> LHS <u RHS
     // LHS <=u (shiftee >> shiftvalue) && shiftee <=u RHS ---> LHS <=u RHS
@@ -12217,9 +12219,8 @@ bool ScalarEvolution::isImpliedCondOperandsViaShift(ICmpInst::Predicate Pred,
 }
 
 bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred,
-                                            const SCEV *LHS, const SCEV *RHS,
-                                            const SCEV *FoundLHS,
-                                            const SCEV *FoundRHS,
+                                            SCEVUse LHS, SCEVUse RHS,
+                                            SCEVUse FoundLHS, SCEVUse FoundRHS,
                                             const Instruction *CtxI) {
   if (isImpliedCondOperandsViaRanges(Pred, LHS, RHS, Pred, FoundLHS, FoundRHS))
     return true;
@@ -12240,8 +12241,7 @@ bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred,
 
 /// Is MaybeMinMaxExpr an (U|S)(Min|Max) of Candidate and some other values?
 template <typename MinMaxExprType>
-static bool IsMinMaxConsistingOf(const SCEV *MaybeMinMaxExpr,
-                                 const SCEV *Candidate) {
+static bool IsMinMaxConsistingOf(SCEVUse MaybeMinMaxExpr, SCEVUse Candidate) {
   const MinMaxExprType *MinMaxExpr = dyn_cast<MinMaxExprType>(MaybeMinMaxExpr);
   if (!MinMaxExpr)
     return false;
@@ -12251,7 +12251,7 @@ static bool IsMinMaxConsistingOf(const SCEV *MaybeMinMaxExpr,
 
 static bool IsKnownPredicateViaAddRecStart(ScalarEvolution &SE,
                                            ICmpInst::Predicate Pred,
-                                           const SCEV *LHS, const SCEV *RHS) {
+                                           SCEVUse LHS, SCEVUse RHS) {
   // If both sides are affine addrecs for the same loop, with equal
   // steps, and we know the recurrences don't wrap, then we only
   // need to check the predicate on the starting values.
@@ -12284,8 +12284,8 @@ static bool IsKnownPredicateViaAddRecStart(ScalarEvolution &SE,
 /// Is LHS `Pred` RHS true on the virtue of LHS or RHS being a Min or Max
 /// expression?
 static bool IsKnownPredicateViaMinOrMax(ScalarEvolution &SE,
-                                        ICmpInst::Predicate Pred,
-                                        const SCEV *LHS, const SCEV *RHS) {
+                                        ICmpInst::Predicate Pred, SCEVUse LHS,
+                                        SCEVUse RHS) {
   switch (Pred) {
   default:
     return false;
@@ -12316,9 +12316,8 @@ static bool IsKnownPredicateViaMinOrMax(ScalarEvolution &SE,
 }
 
 bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
-                                             const SCEV *LHS, const SCEV *RHS,
-                                             const SCEV *FoundLHS,
-                                             const SCEV *FoundRHS,
+                                             SCEVUse LHS, SCEVUse RHS,
+                                             SCEVUse FoundLHS, SCEVUse FoundRHS,
                                              unsigned Depth) {
   assert(getTypeSizeInBits(LHS->getType()) ==
              getTypeSizeInBits(RHS->getType()) &&
@@ -12346,7 +12345,7 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
       // Knowing that both FoundLHS and FoundRHS are non-negative, and knowing
       // FoundLHS >u FoundRHS, we also know that FoundLHS >s FoundRHS. Let us
       // use this fact to prove that LHS and RHS are non-negative.
-      const SCEV *MinusOne = getMinusOne(LHS->getType());
+      SCEVUse MinusOne = getMinusOne(LHS->getType());
       if (isImpliedCondOperands(ICmpInst::ICMP_SGT, LHS, MinusOne, FoundLHS,
                                 FoundRHS) &&
           isImpliedCondOperands(ICmpInst::ICMP_SGT, RHS, MinusOne, FoundLHS,
@@ -12357,7 +12356,7 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
   if (Pred != ICmpInst::ICMP_SGT)
     return false;
 
-  auto GetOpFromSExt = [&](const SCEV *S) {
+  auto GetOpFromSExt = [&](SCEVUse S) {
     if (auto *Ext = dyn_cast<SCEVSignExtendExpr>(S))
       return Ext->getOperand();
     // TODO: If S is a SCEVConstant then you can cheaply "strip" the sext off
@@ -12366,13 +12365,13 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
   };
 
   // Acquire values from extensions.
-  auto *OrigLHS = LHS;
-  auto *OrigFoundLHS = FoundLHS;
+  auto OrigLHS = LHS;
+  auto OrigFoundLHS = FoundLHS;
   LHS = GetOpFromSExt(LHS);
   FoundLHS = GetOpFromSExt(FoundLHS);
 
   // Is the SGT predicate can be proved trivially or using the found context.
-  auto IsSGTViaContext = [&](const SCEV *S1, const SCEV *S2) {
+  auto IsSGTViaContext = [&](SCEVUse S1, SCEVUse S2) {
     return isKnownViaNonRecursiveReasoning(ICmpInst::ICMP_SGT, S1, S2) ||
            isImpliedViaOperations(ICmpInst::ICMP_SGT, S1, S2, OrigFoundLHS,
                                   FoundRHS, Depth + 1);
@@ -12391,12 +12390,12 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
     if (!LHSAddExpr->hasNoSignedWrap())
       return false;
 
-    auto *LL = LHSAddExpr->getOperand(0);
-    auto *LR = LHSAddExpr->getOperand(1);
-    auto *MinusOne = getMinusOne(RHS->getType());
+    auto LL = LHSAddExpr->getOperand(0);
+    auto LR = LHSAddExpr->getOperand(1);
+    auto MinusOne = getMinusOne(RHS->getType());
 
     // Checks that S1 >= 0 && S2 > RHS, trivially or using the found context.
-    auto IsSumGreaterThanRHS = [&](const SCEV *S1, const SCEV *S2) {
+    auto IsSumGreaterThanRHS = [&](SCEVUse S1, SCEVUse S2) {
       return IsSGTViaContext(S1, MinusOne) && IsSGTViaContext(S2, RHS);
     };
     // Try to prove the following rule:
@@ -12426,7 +12425,7 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
 
       // We want to make sure that LHS = FoundLHS / Denominator. If it is so,
       // then a SCEV for the numerator already exists and matches with FoundLHS.
-      auto *Numerator = getExistingSCEV(LL);
+      auto Numerator = getExistingSCEV(LL);
       if (!Numerator || Numerator->getType() != FoundLHS->getType())
         return false;
 
@@ -12447,14 +12446,14 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
       // Given that:
       // FoundLHS > FoundRHS, LHS = FoundLHS / Denominator, Denominator > 0.
       auto *WTy = getWiderType(DTy, FRHSTy);
-      auto *DenominatorExt = getNoopOrSignExtend(Denominator, WTy);
-      auto *FoundRHSExt = getNoopOrSignExtend(FoundRHS, WTy);
+      auto DenominatorExt = getNoopOrSignExtend(Denominator, WTy);
+      auto FoundRHSExt = getNoopOrSignExtend(FoundRHS, WTy);
 
       // Try to prove the following rule:
       // (FoundRHS > Denominator - 2) && (RHS <= 0) => (LHS > RHS).
       // For example, given that FoundLHS > 2. It means that FoundLHS is at
       // least 3. If we divide it by Denominator < 4, we will have at least 1.
-      auto *DenomMinusTwo = getMinusSCEV(DenominatorExt, getConstant(WTy, 2));
+      auto DenomMinusTwo = getMinusSCEV(DenominatorExt, getConstant(WTy, 2));
       if (isKnownNonPositive(RHS) &&
           IsSGTViaContext(FoundRHSExt, DenomMinusTwo))
         return true;
@@ -12466,8 +12465,8 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
       // 1. If FoundLHS is negative, then the result is 0.
       // 2. If FoundLHS is non-negative, then the result is non-negative.
       // Anyways, the result is non-negative.
-      auto *MinusOne = getMinusOne(WTy);
-      auto *NegDenomMinusOne = getMinusSCEV(MinusOne, DenominatorExt);
+      auto MinusOne = getMinusOne(WTy);
+      auto NegDenomMinusOne = getMinusSCEV(MinusOne, DenominatorExt);
       if (isKnownNegative(RHS) &&
           IsSGTViaContext(FoundRHSExt, NegDenomMinusOne))
         return true;
@@ -12483,8 +12482,8 @@ bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
   return false;
 }
 
-static bool isKnownPredicateExtendIdiom(ICmpInst::Predicate Pred,
-                                        const SCEV *LHS, const SCEV *RHS) {
+static bool isKnownPredicateExtendIdiom(ICmpInst::Predicate Pred, SCEVUse LHS,
+                                        SCEVUse RHS) {
   // zext x u<= sext x, sext x s<= zext x
   switch (Pred) {
   case ICmpInst::ICMP_SGE:
@@ -12515,9 +12514,9 @@ static bool isKnownPredicateExtendIdiom(ICmpInst::Predicate Pred,
   return false;
 }
 
-bool
-ScalarEvolution::isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred,
-                                           const SCEV *LHS, const SCEV *RHS) {
+bool ScalarEvolution::isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred,
+                                                      SCEVUse LHS,
+                                                      SCEVUse RHS) {
   return isKnownPredicateExtendIdiom(Pred, LHS, RHS) ||
          isKnownPredicateViaConstantRanges(Pred, LHS, RHS) ||
          IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
@@ -12525,11 +12524,10 @@ ScalarEvolution::isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred,
          isKnownPredicateViaNoOverflow(Pred, LHS, RHS);
 }
 
-bool
-ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
-                                             const SCEV *LHS, const SCEV *RHS,
-                                             const SCEV *FoundLHS,
-                                             const SCEV *FoundRHS) {
+bool ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
+                                                  SCEVUse LHS, SCEVUse RHS,
+                                                  SCEVUse FoundLHS,
+                                                  SCEVUse FoundRHS) {
   switch (Pred) {
   default: llvm_unreachable("Unexpected ICmpInst::Predicate value!");
   case ICmpInst::ICMP_EQ:
@@ -12570,12 +12568,9 @@ ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
   return false;
 }
 
-bool ScalarEvolution::isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
-                                                     const SCEV *LHS,
-                                                     const SCEV *RHS,
-                                                     ICmpInst::Predicate FoundPred,
-                                                     const SCEV *FoundLHS,
-                                                     const SCEV *FoundRHS) {
+bool ScalarEvolution::isImpliedCondOperandsViaRanges(
+    ICmpInst::Predicate Pred, SCEVUse LHS, SCEVUse RHS,
+    ICmpInst::Predicate FoundPred, SCEVUse FoundLHS, SCEVUse FoundRHS) {
   if (!isa<SCEVConstant>(RHS) || !isa<SCEVConstant>(FoundRHS))
     // The restriction on `FoundRHS` be lifted easily -- it exists only to
     // reduce the compile time impact of this optimization.
@@ -12603,12 +12598,12 @@ bool ScalarEvolution::isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred,
   return LHSRange.icmp(Pred, ConstRHS);
 }
 
-bool ScalarEvolution::canIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride,
+bool ScalarEvolution::canIVOverflowOnLT(SCEVUse RHS, SCEVUse Stride,
                                         bool IsSigned) {
   assert(isKnownPositive(Stride) && "Positive stride expected!");
 
   unsigned BitWidth = getTypeSizeInBits(RHS->getType());
-  const SCEV *One = getOne(Stride->getType());
+  SCEVUse One = getOne(Stride->getType());
 
   if (IsSigned) {
     APInt MaxRHS = getSignedRangeMax(RHS);
@@ -12627,11 +12622,11 @@ bool ScalarEvolution::canIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride,
   return (std::move(MaxValue) - MaxStrideMinusOne).ult(MaxRHS);
 }
 
-bool ScalarEvolution::canIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride,
+bool ScalarEvolution::canIVOverflowOnGT(SCEVUse RHS, SCEVUse Stride,
                                         bool IsSigned) {
 
   unsigned BitWidth = getTypeSizeInBits(RHS->getType());
-  const SCEV *One = getOne(Stride->getType());
+  SCEVUse One = getOne(Stride->getType());
 
   if (IsSigned) {
     APInt MinRHS = getSignedRangeMin(RHS);
@@ -12650,20 +12645,18 @@ bool ScalarEvolution::canIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride,
   return (std::move(MinValue) + MaxStrideMinusOne).ugt(MinRHS);
 }
 
-const SCEV *ScalarEvolution::getUDivCeilSCEV(const SCEV *N, const SCEV *D) {
+SCEVUse ScalarEvolution::getUDivCeilSCEV(SCEVUse N, SCEVUse D) {
   // umin(N, 1) + floor((N - umin(N, 1)) / D)
   // This is equivalent to "1 + floor((N - 1) / D)" for N != 0. The umin
   // expression fixes the case of N=0.
-  const SCEV *MinNOne = getUMinExpr(N, getOne(N->getType()));
-  const SCEV *NMinusOne = getMinusSCEV(N, MinNOne);
+  SCEVUse MinNOne = getUMinExpr(N, getOne(N->getType()));
+  SCEVUse NMinusOne = getMinusSCEV(N, MinNOne);
   return getAddExpr(MinNOne, getUDivExpr(NMinusOne, D));
 }
 
-const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start,
-                                                    const SCEV *Stride,
-                                                    const SCEV *End,
-                                                    unsigned BitWidth,
-                                                    bool IsSigned) {
+SCEVUse ScalarEvolution::computeMaxBECountForLT(SCEVUse Start, SCEVUse Stride,
+                                                SCEVUse End, unsigned BitWidth,
+                                                bool IsSigned) {
   // The logic in this function assumes we can represent a positive stride.
   // If we can't, the backedge-taken count must be zero.
   if (IsSigned && BitWidth == 1)
@@ -12709,9 +12702,9 @@ const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start,
 }
 
 ScalarEvolution::ExitLimit
-ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
-                                  const Loop *L, bool IsSigned,
-                                  bool ControlsOnlyExit, bool AllowPredicates) {
+ScalarEvolution::howManyLessThans(SCEVUse LHS, SCEVUse RHS, const Loop *L,
+                                  bool IsSigned, bool ControlsOnlyExit,
+                                  bool AllowPredicates) {
   SmallPtrSet<const SCEVPredicate *, 4> Predicates;
 
   const SCEVAddRecExpr *IV = dyn_cast<SCEVAddRecExpr>(LHS);
@@ -12784,11 +12777,11 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
         if (AR->hasNoUnsignedWrap()) {
           // Emulate what getZeroExtendExpr would have done during construction
           // if we'd been able to infer the fact just above at that time.
-          const SCEV *Step = AR->getStepRecurrence(*this);
+          SCEVUse Step = AR->getStepRecurrence(*this);
           Type *Ty = ZExt->getType();
-          auto *S = getAddRecExpr(
-            getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, 0),
-            getZeroExtendExpr(Step, Ty, 0), L, AR->getNoWrapFlags());
+          auto S = getAddRecExpr(
+              getExtendAddRecStart<SCEVZeroExtendExpr>(AR, Ty, this, 0),
+              getZeroExtendExpr(Step, Ty, 0), L, AR->getNoWrapFlags());
           IV = dyn_cast<SCEVAddRecExpr>(S);
         }
       }
@@ -12822,7 +12815,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
   bool NoWrap = ControlsOnlyExit && IV->getNoWrapFlags(WrapType);
   ICmpInst::Predicate Cond = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
 
-  const SCEV *Stride = IV->getStepRecurrence(*this);
+  SCEVUse Stride = IV->getStepRecurrence(*this);
 
   bool PositiveStride = isKnownPositive(Stride);
 
@@ -12888,7 +12881,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
         // Note: The (Start - Stride) term is used to get the start' term from
         // (start' + stride,+,stride). Remember that we only care about the
         // result of this expression when stride == 0 at runtime.
-        auto *StartIfZero = getMinusSCEV(IV->getStart(), Stride);
+        auto StartIfZero = getMinusSCEV(IV->getStart(), Stride);
         return isLoopEntryGuardedByCond(L, Cond, StartIfZero, RHS);
       };
       if (!wouldZeroStrideBeUB()) {
@@ -12922,14 +12915,14 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
   //      before any possible exit.
   // Note that we have not yet proved RHS invariant (in general).
 
-  const SCEV *Start = IV->getStart();
+  SCEVUse Start = IV->getStart();
 
   // Preserve pointer-typed Start/RHS to pass to isLoopEntryGuardedByCond.
   // If we convert to integers, isLoopEntryGuardedByCond will miss some cases.
   // Use integer-typed versions for actual computation; we can't subtract
   // pointers in general.
-  const SCEV *OrigStart = Start;
-  const SCEV *OrigRHS = RHS;
+  SCEVUse OrigStart = Start;
+  SCEVUse OrigRHS = RHS;
   if (Start->getType()->isPointerTy()) {
     Start = getLosslessPtrToIntExpr(Start);
     if (isa<SCEVCouldNotCompute>(Start))
@@ -12947,7 +12940,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
   // bound of the loop (RHS), and the fact that IV does not overflow (which is
   // checked above).
   if (!isLoopInvariant(RHS, L)) {
-    const SCEV *MaxBECount = computeMaxBECountForLT(
+    SCEVUse MaxBECount = computeMaxBECountForLT(
         Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned);
     return ExitLimit(getCouldNotCompute() /* ExactNotTaken */, MaxBECount,
                      MaxBECount, false /*MaxOrZero*/, Predicates);
@@ -12957,8 +12950,8 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
   // backedge count, as if the backedge is taken at least once max(End,Start)
   // is End and so the result is as above, and if not max(End,Start) is Start
   // so we get a backedge count of zero.
-  const SCEV *BECount = nullptr;
-  auto *OrigStartMinusStride = getMinusSCEV(OrigStart, Stride);
+  SCEVUse BECount = nullptr;
+  auto OrigStartMinusStride = getMinusSCEV(OrigStart, Stride);
   assert(isAvailableAtLoopEntry(OrigStartMinusStride, L) && "Must be!");
   assert(isAvailableAtLoopEntry(OrigStart, L) && "Must be!");
   assert(isAvailableAtLoopEntry(OrigRHS, L) && "Must be!");
@@ -12983,18 +12976,18 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
     //   "((RHS - 1) - (Start - Stride)) /u Stride" reassociates to
     //   "((RHS - (Start - Stride) - 1) /u Stride".
     //   Our preconditions trivially imply no overflow in that form.
-    const SCEV *MinusOne = getMinusOne(Stride->getType());
-    const SCEV *Numerator =
+    SCEVUse MinusOne = getMinusOne(Stride->getType());
+    SCEVUse Numerator =
         getMinusSCEV(getAddExpr(RHS, MinusOne), getMinusSCEV(Start, Stride));
     BECount = getUDivExpr(Numerator, Stride);
   }
 
-  const SCEV *BECountIfBackedgeTaken = nullptr;
+  SCEVUse BECountIfBackedgeTaken = nullptr;
   if (!BECount) {
     auto canProveRHSGreaterThanEqualStart = [&]() {
       auto CondGE = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
-      const SCEV *GuardedRHS = applyLoopGuards(OrigRHS, L);
-      const SCEV *GuardedStart = applyLoopGuards(OrigStart, L);
+      SCEVUse GuardedRHS = applyLoopGuards(OrigRHS, L);
+      SCEVUse GuardedStart = applyLoopGuards(OrigStart, L);
 
       if (isLoopEntryGuardedByCond(L, CondGE, OrigRHS, OrigStart) ||
           isKnownPredicate(CondGE, GuardedRHS, GuardedStart))
@@ -13010,14 +13003,14 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
       //
       // FIXME: Should isLoopEntryGuardedByCond do this for us?
       auto CondGT = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
-      auto *StartMinusOne = getAddExpr(OrigStart,
-                                       getMinusOne(OrigStart->getType()));
+      auto StartMinusOne =
+          getAddExpr(OrigStart, getMinusOne(OrigStart->getType()));
       return isLoopEntryGuardedByCond(L, CondGT, OrigRHS, StartMinusOne);
     };
 
     // If we know that RHS >= Start in the context of loop, then we know that
     // max(RHS, Start) = RHS at this point.
-    const SCEV *End;
+    SCEVUse End;
     if (canProveRHSGreaterThanEqualStart()) {
       End = RHS;
     } else {
@@ -13047,7 +13040,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
     //
     // Using this information, try to prove whether the addition in
     // "(Start - End) + (Stride - 1)" has unsigned overflow.
-    const SCEV *One = getOne(Stride->getType());
+    SCEVUse One = getOne(Stride->getType());
     bool MayAddOverflow = [&] {
       if (auto *StrideC = dyn_cast<SCEVConstant>(Stride)) {
         if (StrideC->getAPInt().isPowerOf2()) {
@@ -13106,7 +13099,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
       return true;
     }();
 
-    const SCEV *Delta = getMinusSCEV(End, Start);
+    SCEVUse Delta = getMinusSCEV(End, Start);
     if (!MayAddOverflow) {
       // floor((D + (S - 1)) / S)
       // We prefer this formulation if it's legal because it's fewer operations.
@@ -13117,7 +13110,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
     }
   }
 
-  const SCEV *ConstantMaxBECount;
+  SCEVUse ConstantMaxBECount;
   bool MaxOrZero = false;
   if (isa<SCEVConstant>(BECount)) {
     ConstantMaxBECount = BECount;
@@ -13137,15 +13130,16 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
       !isa<SCEVCouldNotCompute>(BECount))
     ConstantMaxBECount = getConstant(getUnsignedRangeMax(BECount));
 
-  const SCEV *SymbolicMaxBECount =
+  SCEVUse SymbolicMaxBECount =
       isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;
   return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount, MaxOrZero,
                    Predicates);
 }
 
-ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
-    const SCEV *LHS, const SCEV *RHS, const Loop *L, bool IsSigned,
-    bool ControlsOnlyExit, bool AllowPredicates) {
+ScalarEvolution::ExitLimit
+ScalarEvolution::howManyGreaterThans(SCEVUse LHS, SCEVUse RHS, const Loop *L,
+                                     bool IsSigned, bool ControlsOnlyExit,
+                                     bool AllowPredicates) {
   SmallPtrSet<const SCEVPredicate *, 4> Predicates;
   // We handle only IV > Invariant
   if (!isLoopInvariant(RHS, L))
@@ -13166,7 +13160,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
   bool NoWrap = ControlsOnlyExit && IV->getNoWrapFlags(WrapType);
   ICmpInst::Predicate Cond = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
 
-  const SCEV *Stride = getNegativeSCEV(IV->getStepRecurrence(*this));
+  SCEVUse Stride = getNegativeSCEV(IV->getStepRecurrence(*this));
 
   // Avoid negative or zero stride values
   if (!isKnownPositive(Stride))
@@ -13180,8 +13174,8 @@ ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
     if (canIVOverflowOnGT(RHS, Stride, IsSigned))
       return getCouldNotCompute();
 
-  const SCEV *Start = IV->getStart();
-  const SCEV *End = RHS;
+  SCEVUse Start = IV->getStart();
+  SCEVUse End = RHS;
   if (!isLoopEntryGuardedByCond(L, Cond, getAddExpr(Start, Stride), RHS)) {
     // If we know that Start >= RHS in the context of loop, then we know that
     // min(RHS, Start) = RHS at this point.
@@ -13206,8 +13200,8 @@ ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
   // Compute ((Start - End) + (Stride - 1)) / Stride.
   // FIXME: This can overflow. Holding off on fixing this for now;
   // howManyGreaterThans will hopefully be gone soon.
-  const SCEV *One = getOne(Stride->getType());
-  const SCEV *BECount = getUDivExpr(
+  SCEVUse One = getOne(Stride->getType());
+  SCEVUse BECount = getUDivExpr(
       getAddExpr(getMinusSCEV(Start, End), getMinusSCEV(Stride, One)), Stride);
 
   APInt MaxStart = IsSigned ? getSignedRangeMax(Start)
@@ -13227,7 +13221,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
     IsSigned ? APIntOps::smax(getSignedRangeMin(RHS), Limit)
              : APIntOps::umax(getUnsignedRangeMin(RHS), Limit);
 
-  const SCEV *ConstantMaxBECount =
+  SCEVUse ConstantMaxBECount =
       isa<SCEVConstant>(BECount)
           ? BECount
           : getUDivCeilSCEV(getConstant(MaxStart - MinEnd),
@@ -13235,25 +13229,25 @@ ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
 
   if (isa<SCEVCouldNotCompute>(ConstantMaxBECount))
     ConstantMaxBECount = BECount;
-  const SCEV *SymbolicMaxBECount =
+  SCEVUse SymbolicMaxBECount =
       isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;
 
   return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount, false,
                    Predicates);
 }
 
-const SCEV *SCEVAddRecExpr::getNumIterationsInRange(const ConstantRange &Range,
-                                                    ScalarEvolution &SE) const {
+SCEVUse SCEVAddRecExpr::getNumIterationsInRange(const ConstantRange &Range,
+                                                ScalarEvolution &SE) const {
   if (Range.isFullSet())  // Infinite loop.
     return SE.getCouldNotCompute();
 
   // If the start is a non-zero constant, shift the range to simplify things.
   if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(getStart()))
     if (!SC->getValue()->isZero()) {
-      SmallVector<const SCEV *, 4> Operands(operands());
+      SmallVector<SCEVUse, 4> Operands(operands());
       Operands[0] = SE.getZero(SC->getType());
-      const SCEV *Shifted = SE.getAddRecExpr(Operands, getLoop(),
-                                             getNoWrapFlags(FlagNW));
+      SCEVUse Shifted =
+          SE.getAddRecExpr(Operands, getLoop(), getNoWrapFlags(FlagNW));
       if (const auto *ShiftedAddRec = dyn_cast<SCEVAddRecExpr>(Shifted))
         return ShiftedAddRec->getNumIterationsInRange(
             Range.subtract(SC->getAPInt()), SE);
@@ -13263,7 +13257,7 @@ const SCEV *SCEVAddRecExpr::getNumIterationsInRange(const ConstantRange &Range,
 
   // The only time we can solve this is when we have all constant indices.
   // Otherwise, we cannot determine the overflow conditions.
-  if (any_of(operands(), [](const SCEV *Op) { return !isa<SCEVConstant>(Op); }))
+  if (any_of(operands(), [](SCEVUse Op) { return !isa<SCEVConstant>(Op); }))
     return SE.getCouldNotCompute();
 
   // Okay at this point we know that all elements of the chrec are constants and
@@ -13322,7 +13316,7 @@ SCEVAddRecExpr::getPostIncExpr(ScalarEvolution &SE) const {
   // simplification: it is legal to return ({rec1} + {rec2}). For example, it
   // may happen if we reach arithmetic depth limit while simplifying. So we
   // construct the returned value explicitly.
-  SmallVector<const SCEV *, 3> Ops;
+  SmallVector<SCEVUse, 3> Ops;
   // If this is {A,+,B,+,C,...,+,N}, then its step is {B,+,C,+,...,+,N}, and
   // (this + Step) is {A+B,+,B+C,+...,+,N}.
   for (unsigned i = 0, e = getNumOperands() - 1; i < e; ++i)
@@ -13331,7 +13325,7 @@ SCEVAddRecExpr::getPostIncExpr(ScalarEvolution &SE) const {
   // have been popped out earlier). This guarantees us that if the result has
   // the same last operand, then it will also not be popped out, meaning that
   // the returned value will be an AddRec.
-  const SCEV *Last = getOperand(getNumOperands() - 1);
+  SCEVUse Last = getOperand(getNumOperands() - 1);
   assert(!Last->isZero() && "Recurrency with zero step?");
   Ops.push_back(Last);
   return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, getLoop(),
@@ -13339,8 +13333,8 @@ SCEVAddRecExpr::getPostIncExpr(ScalarEvolution &SE) const {
 }
 
 // Return true when S contains at least an undef value.
-bool ScalarEvolution::containsUndefs(const SCEV *S) const {
-  return SCEVExprContains(S, [](const SCEV *S) {
+bool ScalarEvolution::containsUndefs(SCEVUse S) const {
+  return SCEVExprContains(S, [](SCEVUse S) {
     if (const auto *SU = dyn_cast<SCEVUnknown>(S))
       return isa<UndefValue>(SU->getValue());
     return false;
@@ -13348,8 +13342,8 @@ bool ScalarEvolution::containsUndefs(const SCEV *S) const {
 }
 
 // Return true when S contains a value that is a nullptr.
-bool ScalarEvolution::containsErasedValue(const SCEV *S) const {
-  return SCEVExprContains(S, [](const SCEV *S) {
+bool ScalarEvolution::containsErasedValue(SCEVUse S) const {
+  return SCEVExprContains(S, [](SCEVUse S) {
     if (const auto *SU = dyn_cast<SCEVUnknown>(S))
       return SU->getValue() == nullptr;
     return false;
@@ -13357,7 +13351,7 @@ bool ScalarEvolution::containsErasedValue(const SCEV *S) const {
 }
 
 /// Return the size of an element read or written by Inst.
-const SCEV *ScalarEvolution::getElementSize(Instruction *Inst) {
+SCEVUse ScalarEvolution::getElementSize(Instruction *Inst) {
   Type *Ty;
   if (StoreInst *Store = dyn_cast<StoreInst>(Inst))
     Ty = Store->getValueOperand()->getType();
@@ -13501,7 +13495,7 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
   if (ExitingBlocks.size() != 1)
     OS << "<multiple exits> ";
 
-  auto *BTC = SE->getBackedgeTakenCount(L);
+  auto BTC = SE->getBackedgeTakenCount(L);
   if (!isa<SCEVCouldNotCompute>(BTC)) {
     OS << "backedge-taken count is ";
     PrintSCEVWithTypeHint(OS, BTC);
@@ -13520,7 +13514,7 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
   L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
   OS << ": ";
 
-  auto *ConstantBTC = SE->getConstantMaxBackedgeTakenCount(L);
+  auto ConstantBTC = SE->getConstantMaxBackedgeTakenCount(L);
   if (!isa<SCEVCouldNotCompute>(ConstantBTC)) {
     OS << "constant max backedge-taken count is ";
     PrintSCEVWithTypeHint(OS, ConstantBTC);
@@ -13535,7 +13529,7 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
   L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
   OS << ": ";
 
-  auto *SymbolicBTC = SE->getSymbolicMaxBackedgeTakenCount(L);
+  auto SymbolicBTC = SE->getSymbolicMaxBackedgeTakenCount(L);
   if (!isa<SCEVCouldNotCompute>(SymbolicBTC)) {
     OS << "symbolic max backedge-taken count is ";
     PrintSCEVWithTypeHint(OS, SymbolicBTC);
@@ -13549,14 +13543,14 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
   if (ExitingBlocks.size() > 1)
     for (BasicBlock *ExitingBlock : ExitingBlocks) {
       OS << "  symbolic max exit count for " << ExitingBlock->getName() << ": ";
-      auto *ExitBTC = SE->getExitCount(L, ExitingBlock,
-                                       ScalarEvolution::SymbolicMaximum);
+      auto ExitBTC =
+          SE->getExitCount(L, ExitingBlock, ScalarEvolution::SymbolicMaximum);
       PrintSCEVWithTypeHint(OS, ExitBTC);
       OS << "\n";
     }
 
   SmallVector<const SCEVPredicate *, 4> Preds;
-  auto *PBT = SE->getPredicatedBackedgeTakenCount(L, Preds);
+  auto PBT = SE->getPredicatedBackedgeTakenCount(L, Preds);
   if (PBT != BTC || !Preds.empty()) {
     OS << "Loop ";
     L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
@@ -13629,7 +13623,7 @@ void ScalarEvolution::print(raw_ostream &OS) const {
       if (isSCEVable(I.getType()) && !isa<CmpInst>(I)) {
         OS << I << '\n';
         OS << "  -->  ";
-        const SCEV *SV = SE.getSCEV(&I);
+        SCEVUse SV = SE.getSCEV(&I);
         SV->print(OS);
         if (!isa<SCEVCouldNotCompute>(SV)) {
           OS << " U: ";
@@ -13640,7 +13634,7 @@ void ScalarEvolution::print(raw_ostream &OS) const {
 
         const Loop *L = LI.getLoopFor(I.getParent());
 
-        const SCEV *AtUse = SE.getSCEVAtScope(SV, L);
+        SCEVUse AtUse = SE.getSCEVAtScope(SV, L);
         if (AtUse != SV) {
           OS << "  -->  ";
           AtUse->print(OS);
@@ -13654,7 +13648,7 @@ void ScalarEvolution::print(raw_ostream &OS) const {
 
         if (L) {
           OS << "\t\t" "Exits: ";
-          const SCEV *ExitValue = SE.getSCEVAtScope(SV, L->getParentLoop());
+          SCEVUse ExitValue = SE.getSCEVAtScope(SV, L->getParentLoop());
           if (!SE.isLoopInvariant(ExitValue, L)) {
             OS << "<<Unknown>>";
           } else {
@@ -13703,7 +13697,7 @@ void ScalarEvolution::print(raw_ostream &OS) const {
 }
 
 ScalarEvolution::LoopDisposition
-ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) {
+ScalarEvolution::getLoopDisposition(SCEVUse S, const Loop *L) {
   auto &Values = LoopDispositions[S];
   for (auto &V : Values) {
     if (V.getPointer() == L)
@@ -13722,7 +13716,7 @@ ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) {
 }
 
 ScalarEvolution::LoopDisposition
-ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
+ScalarEvolution::computeLoopDisposition(SCEVUse S, const Loop *L) {
   switch (S->getSCEVType()) {
   case scConstant:
   case scVScale:
@@ -13750,7 +13744,7 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
 
     // This recurrence is variant w.r.t. L if any of its operands
     // are variant.
-    for (const auto *Op : AR->operands())
+    for (const auto Op : AR->operands())
       if (!isLoopInvariant(Op, L))
         return LoopVariant;
 
@@ -13770,7 +13764,7 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
   case scSMinExpr:
   case scSequentialUMinExpr: {
     bool HasVarying = false;
-    for (const auto *Op : S->operands()) {
+    for (const auto Op : S->operands()) {
       LoopDisposition D = getLoopDisposition(Op, L);
       if (D == LoopVariant)
         return LoopVariant;
@@ -13793,16 +13787,16 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
   llvm_unreachable("Unknown SCEV kind!");
 }
 
-bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) {
+bool ScalarEvolution::isLoopInvariant(SCEVUse S, const Loop *L) {
   return getLoopDisposition(S, L) == LoopInvariant;
 }
 
-bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) {
+bool ScalarEvolution::hasComputableLoopEvolution(SCEVUse S, const Loop *L) {
   return getLoopDisposition(S, L) == LoopComputable;
 }
 
 ScalarEvolution::BlockDisposition
-ScalarEvolution::getBlockDisposition(const SCEV *S, const BasicBlock *BB) {
+ScalarEvolution::getBlockDisposition(SCEVUse S, const BasicBlock *BB) {
   auto &Values = BlockDispositions[S];
   for (auto &V : Values) {
     if (V.getPointer() == BB)
@@ -13821,7 +13815,7 @@ ScalarEvolution::getBlockDisposition(const SCEV *S, const BasicBlock *BB) {
 }
 
 ScalarEvolution::BlockDisposition
-ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
+ScalarEvolution::computeBlockDisposition(SCEVUse S, const BasicBlock *BB) {
   switch (S->getSCEVType()) {
   case scConstant:
   case scVScale:
@@ -13851,7 +13845,7 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
   case scSMinExpr:
   case scSequentialUMinExpr: {
     bool Proper = true;
-    for (const SCEV *NAryOp : S->operands()) {
+    for (SCEVUse NAryOp : S->operands()) {
       BlockDisposition D = getBlockDisposition(NAryOp, BB);
       if (D == DoesNotDominateBlock)
         return DoesNotDominateBlock;
@@ -13876,16 +13870,16 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
   llvm_unreachable("Unknown SCEV kind!");
 }
 
-bool ScalarEvolution::dominates(const SCEV *S, const BasicBlock *BB) {
+bool ScalarEvolution::dominates(SCEVUse S, const BasicBlock *BB) {
   return getBlockDisposition(S, BB) >= DominatesBlock;
 }
 
-bool ScalarEvolution::properlyDominates(const SCEV *S, const BasicBlock *BB) {
+bool ScalarEvolution::properlyDominates(SCEVUse S, const BasicBlock *BB) {
   return getBlockDisposition(S, BB) == ProperlyDominatesBlock;
 }
 
-bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const {
-  return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; });
+bool ScalarEvolution::hasOperand(SCEVUse S, SCEVUse Op) const {
+  return SCEVExprContains(S, [&](SCEVUse Expr) { return Expr == Op; });
 }
 
 void ScalarEvolution::forgetBackedgeTakenCounts(const Loop *L,
@@ -13895,7 +13889,7 @@ void ScalarEvolution::forgetBackedgeTakenCounts(const Loop *L,
   auto It = BECounts.find(L);
   if (It != BECounts.end()) {
     for (const ExitNotTakenInfo &ENT : It->second.ExitNotTaken) {
-      for (const SCEV *S : {ENT.ExactNotTaken, ENT.SymbolicMaxNotTaken}) {
+      for (SCEVUse S : {ENT.ExactNotTaken, ENT.SymbolicMaxNotTaken}) {
         if (!isa<SCEVConstant>(S)) {
           auto UserIt = BECountUsers.find(S);
           assert(UserIt != BECountUsers.end());
@@ -13907,25 +13901,25 @@ void ScalarEvolution::forgetBackedgeTakenCounts(const Loop *L,
   }
 }
 
-void ScalarEvolution::forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs) {
-  SmallPtrSet<const SCEV *, 8> ToForget(SCEVs.begin(), SCEVs.end());
-  SmallVector<const SCEV *, 8> Worklist(ToForget.begin(), ToForget.end());
+void ScalarEvolution::forgetMemoizedResults(ArrayRef<SCEVUse> SCEVs) {
+  SmallPtrSet<SCEVUse, 8> ToForget(SCEVs.begin(), SCEVs.end());
+  SmallVector<SCEVUse, 8> Worklist(ToForget.begin(), ToForget.end());
 
   while (!Worklist.empty()) {
-    const SCEV *Curr = Worklist.pop_back_val();
+    SCEVUse Curr = Worklist.pop_back_val();
     auto Users = SCEVUsers.find(Curr);
     if (Users != SCEVUsers.end())
-      for (const auto *User : Users->second)
+      for (const auto User : Users->second)
         if (ToForget.insert(User).second)
           Worklist.push_back(User);
   }
 
-  for (const auto *S : ToForget)
+  for (const auto S : ToForget)
     forgetMemoizedResultsImpl(S);
 
   for (auto I = PredicatedSCEVRewrites.begin();
        I != PredicatedSCEVRewrites.end();) {
-    std::pair<const SCEV *, const Loop *> Entry = I->first;
+    std::pair<SCEVUse, const Loop *> Entry = I->first;
     if (ToForget.count(Entry.first))
       PredicatedSCEVRewrites.erase(I++);
     else
@@ -13933,7 +13927,7 @@ void ScalarEvolution::forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs) {
   }
 }
 
-void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
+void ScalarEvolution::forgetMemoizedResultsImpl(SCEVUse S) {
   LoopDispositions.erase(S);
   BlockDispositions.erase(S);
   UnsignedRanges.erase(S);
@@ -13988,14 +13982,13 @@ void ScalarEvolution::forgetMemoizedResultsImpl(const SCEV *S) {
   FoldCacheUser.erase(S);
 }
 
-void
-ScalarEvolution::getUsedLoops(const SCEV *S,
-                              SmallPtrSetImpl<const Loop *> &LoopsUsed) {
+void ScalarEvolution::getUsedLoops(SCEVUse S,
+                                   SmallPtrSetImpl<const Loop *> &LoopsUsed) {
   struct FindUsedLoops {
     FindUsedLoops(SmallPtrSetImpl<const Loop *> &LoopsUsed)
         : LoopsUsed(LoopsUsed) {}
     SmallPtrSetImpl<const Loop *> &LoopsUsed;
-    bool follow(const SCEV *S) {
+    bool follow(SCEVUse S) {
       if (auto *AR = dyn_cast<SCEVAddRecExpr>(S))
         LoopsUsed.insert(AR->getLoop());
       return true;
@@ -14027,8 +14020,8 @@ void ScalarEvolution::getReachableBlocks(
       }
 
       if (auto *Cmp = dyn_cast<ICmpInst>(Cond)) {
-        const SCEV *L = getSCEV(Cmp->getOperand(0));
-        const SCEV *R = getSCEV(Cmp->getOperand(1));
+        SCEVUse L = getSCEV(Cmp->getOperand(0));
+        SCEVUse R = getSCEV(Cmp->getOperand(1));
         if (isKnownPredicateViaConstantRanges(Cmp->getPredicate(), L, R)) {
           Worklist.push_back(TrueBB);
           continue;
@@ -14055,15 +14048,15 @@ void ScalarEvolution::verify() const {
   struct SCEVMapper : public SCEVRewriteVisitor<SCEVMapper> {
     SCEVMapper(ScalarEvolution &SE) : SCEVRewriteVisitor<SCEVMapper>(SE) {}
 
-    const SCEV *visitConstant(const SCEVConstant *Constant) {
+    SCEVUse visitConstant(const SCEVConstant *Constant) {
       return SE.getConstant(Constant->getAPInt());
     }
 
-    const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+    SCEVUse visitUnknown(const SCEVUnknown *Expr) {
       return SE.getUnknown(Expr->getValue());
     }
 
-    const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) {
+    SCEVUse visitCouldNotCompute(const SCEVCouldNotCompute *Expr) {
       return SE.getCouldNotCompute();
     }
   };
@@ -14072,7 +14065,7 @@ void ScalarEvolution::verify() const {
   SmallPtrSet<BasicBlock *, 16> ReachableBlocks;
   SE2.getReachableBlocks(ReachableBlocks, F);
 
-  auto GetDelta = [&](const SCEV *Old, const SCEV *New) -> const SCEV * {
+  auto GetDelta = [&](SCEVUse Old, SCEVUse New) -> SCEVUse {
     if (containsUndefs(Old) || containsUndefs(New)) {
       // SCEV treats "undef" as an unknown but consistent value (i.e. it does
       // not propagate undef aggressively).  This means we can (and do) fail
@@ -14083,7 +14076,7 @@ void ScalarEvolution::verify() const {
     }
 
     // Unless VerifySCEVStrict is set, we only compare constant deltas.
-    const SCEV *Delta = SE2.getMinusSCEV(Old, New);
+    SCEVUse Delta = SE2.getMinusSCEV(Old, New);
     if (!VerifySCEVStrict && !isa<SCEVConstant>(Delta))
       return nullptr;
 
@@ -14105,9 +14098,9 @@ void ScalarEvolution::verify() const {
     if (It == BackedgeTakenCounts.end())
       continue;
 
-    auto *CurBECount =
+    auto CurBECount =
         SCM.visit(It->second.getExact(L, const_cast<ScalarEvolution *>(this)));
-    auto *NewBECount = SE2.getBackedgeTakenCount(L);
+    auto NewBECount = SE2.getBackedgeTakenCount(L);
 
     if (CurBECount == SE2.getCouldNotCompute() ||
         NewBECount == SE2.getCouldNotCompute()) {
@@ -14126,7 +14119,7 @@ void ScalarEvolution::verify() const {
              SE.getTypeSizeInBits(NewBECount->getType()))
       CurBECount = SE2.getZeroExtendExpr(CurBECount, NewBECount->getType());
 
-    const SCEV *Delta = GetDelta(CurBECount, NewBECount);
+    SCEVUse Delta = GetDelta(CurBECount, NewBECount);
     if (Delta && !Delta->isZero()) {
       dbgs() << "Trip Count for " << *L << " Changed!\n";
       dbgs() << "Old: " << *CurBECount << "\n";
@@ -14164,9 +14157,9 @@ void ScalarEvolution::verify() const {
     if (auto *I = dyn_cast<Instruction>(&*KV.first)) {
       if (!ReachableBlocks.contains(I->getParent()))
         continue;
-      const SCEV *OldSCEV = SCM.visit(KV.second);
-      const SCEV *NewSCEV = SE2.getSCEV(I);
-      const SCEV *Delta = GetDelta(OldSCEV, NewSCEV);
+      SCEVUse OldSCEV = SCM.visit(KV.second);
+      SCEVUse NewSCEV = SE2.getSCEV(I);
+      SCEVUse Delta = GetDelta(OldSCEV, NewSCEV);
       if (Delta && !Delta->isZero()) {
         dbgs() << "SCEV for value " << *I << " changed!\n"
                << "Old: " << *OldSCEV << "\n"
@@ -14195,7 +14188,7 @@ void ScalarEvolution::verify() const {
 
   // Verify integrity of SCEV users.
   for (const auto &S : UniqueSCEVs) {
-    for (const auto *Op : S.operands()) {
+    for (const auto Op : S.operands()) {
       // We do not store dependencies of constants.
       if (isa<SCEVConstant>(Op))
         continue;
@@ -14210,10 +14203,10 @@ void ScalarEvolution::verify() const {
 
   // Verify integrity of ValuesAtScopes users.
   for (const auto &ValueAndVec : ValuesAtScopes) {
-    const SCEV *Value = ValueAndVec.first;
+    SCEVUse Value = ValueAndVec.first;
     for (const auto &LoopAndValueAtScope : ValueAndVec.second) {
       const Loop *L = LoopAndValueAtScope.first;
-      const SCEV *ValueAtScope = LoopAndValueAtScope.second;
+      SCEVUse ValueAtScope = LoopAndValueAtScope.second;
       if (!isa<SCEVConstant>(ValueAtScope)) {
         auto It = ValuesAtScopesUsers.find(ValueAtScope);
         if (It != ValuesAtScopesUsers.end() &&
@@ -14227,10 +14220,10 @@ void ScalarEvolution::verify() const {
   }
 
   for (const auto &ValueAtScopeAndVec : ValuesAtScopesUsers) {
-    const SCEV *ValueAtScope = ValueAtScopeAndVec.first;
+    SCEVUse ValueAtScope = ValueAtScopeAndVec.first;
     for (const auto &LoopAndValue : ValueAtScopeAndVec.second) {
       const Loop *L = LoopAndValue.first;
-      const SCEV *Value = LoopAndValue.second;
+      SCEVUse Value = LoopAndValue.second;
       assert(!isa<SCEVConstant>(Value));
       auto It = ValuesAtScopes.find(Value);
       if (It != ValuesAtScopes.end() &&
@@ -14248,7 +14241,7 @@ void ScalarEvolution::verify() const {
         Predicated ? PredicatedBackedgeTakenCounts : BackedgeTakenCounts;
     for (const auto &LoopAndBEInfo : BECounts) {
       for (const ExitNotTakenInfo &ENT : LoopAndBEInfo.second.ExitNotTaken) {
-        for (const SCEV *S : {ENT.ExactNotTaken, ENT.SymbolicMaxNotTaken}) {
+        for (SCEVUse S : {ENT.ExactNotTaken, ENT.SymbolicMaxNotTaken}) {
           if (!isa<SCEVConstant>(S)) {
             auto UserIt = BECountUsers.find(S);
             if (UserIt != BECountUsers.end() &&
@@ -14423,14 +14416,14 @@ void ScalarEvolutionWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequiredTransitive<TargetLibraryInfoWrapperPass>();
 }
 
-const SCEVPredicate *ScalarEvolution::getEqualPredicate(const SCEV *LHS,
-                                                        const SCEV *RHS) {
+const SCEVPredicate *ScalarEvolution::getEqualPredicate(SCEVUse LHS,
+                                                        SCEVUse RHS) {
   return getComparePredicate(ICmpInst::ICMP_EQ, LHS, RHS);
 }
 
 const SCEVPredicate *
 ScalarEvolution::getComparePredicate(const ICmpInst::Predicate Pred,
-                                     const SCEV *LHS, const SCEV *RHS) {
+                                     SCEVUse LHS, SCEVUse RHS) {
   FoldingSetNodeID ID;
   assert(LHS->getType() == RHS->getType() &&
          "Type mismatch between LHS and RHS");
@@ -14478,14 +14471,14 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
   ///
   /// If \p NewPreds is non-null, rewrite is free to add further predicates to
   /// \p NewPreds such that the result will be an AddRecExpr.
-  static const SCEV *rewrite(const SCEV *S, const Loop *L, ScalarEvolution &SE,
-                             SmallPtrSetImpl<const SCEVPredicate *> *NewPreds,
-                             const SCEVPredicate *Pred) {
+  static SCEVUse rewrite(SCEVUse S, const Loop *L, ScalarEvolution &SE,
+                         SmallPtrSetImpl<const SCEVPredicate *> *NewPreds,
+                         const SCEVPredicate *Pred) {
     SCEVPredicateRewriter Rewriter(L, SE, NewPreds, Pred);
     return Rewriter.visit(S);
   }
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) {
     if (Pred) {
       if (auto *U = dyn_cast<SCEVUnionPredicate>(Pred)) {
         for (const auto *Pred : U->getPredicates())
@@ -14502,13 +14495,13 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
     return convertToAddRecWithPreds(Expr);
   }
 
-  const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
-    const SCEV *Operand = visit(Expr->getOperand());
+  SCEVUse visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
+    SCEVUse Operand = visit(Expr->getOperand());
     const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Operand);
     if (AR && AR->getLoop() == L && AR->isAffine()) {
       // This couldn't be folded because the operand didn't have the nuw
       // flag. Add the nusw flag as an assumption that we could make.
-      const SCEV *Step = AR->getStepRecurrence(SE);
+      SCEVUse Step = AR->getStepRecurrence(SE);
       Type *Ty = Expr->getType();
       if (addOverflowAssumption(AR, SCEVWrapPredicate::IncrementNUSW))
         return SE.getAddRecExpr(SE.getZeroExtendExpr(AR->getStart(), Ty),
@@ -14518,13 +14511,13 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
     return SE.getZeroExtendExpr(Operand, Expr->getType());
   }
 
-  const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
-    const SCEV *Operand = visit(Expr->getOperand());
+  SCEVUse visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
+    SCEVUse Operand = visit(Expr->getOperand());
     const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Operand);
     if (AR && AR->getLoop() == L && AR->isAffine()) {
       // This couldn't be folded because the operand didn't have the nsw
       // flag. Add the nssw flag as an assumption that we could make.
-      const SCEV *Step = AR->getStepRecurrence(SE);
+      SCEVUse Step = AR->getStepRecurrence(SE);
       Type *Ty = Expr->getType();
       if (addOverflowAssumption(AR, SCEVWrapPredicate::IncrementNSSW))
         return SE.getAddRecExpr(SE.getSignExtendExpr(AR->getStart(), Ty),
@@ -14561,11 +14554,10 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
   // If \p Expr does not meet these conditions (is not a PHI node, or we
   // couldn't create an AddRec for it, or couldn't add the predicate), we just
   // return \p Expr.
-  const SCEV *convertToAddRecWithPreds(const SCEVUnknown *Expr) {
+  SCEVUse convertToAddRecWithPreds(const SCEVUnknown *Expr) {
     if (!isa<PHINode>(Expr->getValue()))
       return Expr;
-    std::optional<
-        std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
+    std::optional<std::pair<SCEVUse, SmallVector<const SCEVPredicate *, 3>>>
         PredicatedRewrite = SE.createAddRecFromPHIWithCasts(Expr);
     if (!PredicatedRewrite)
       return Expr;
@@ -14588,15 +14580,13 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
 
 } // end anonymous namespace
 
-const SCEV *
-ScalarEvolution::rewriteUsingPredicate(const SCEV *S, const Loop *L,
-                                       const SCEVPredicate &Preds) {
+SCEVUse ScalarEvolution::rewriteUsingPredicate(SCEVUse S, const Loop *L,
+                                               const SCEVPredicate &Preds) {
   return SCEVPredicateRewriter::rewrite(S, L, *this, nullptr, &Preds);
 }
 
 const SCEVAddRecExpr *ScalarEvolution::convertSCEVToAddRecWithPredicates(
-    const SCEV *S, const Loop *L,
-    SmallPtrSetImpl<const SCEVPredicate *> &Preds) {
+    SCEVUse S, const Loop *L, SmallPtrSetImpl<const SCEVPredicate *> &Preds) {
   SmallPtrSet<const SCEVPredicate *, 4> TransformPreds;
   S = SCEVPredicateRewriter::rewrite(S, L, *this, &TransformPreds, nullptr);
   auto *AddRec = dyn_cast<SCEVAddRecExpr>(S);
@@ -14618,9 +14608,9 @@ SCEVPredicate::SCEVPredicate(const FoldingSetNodeIDRef ID,
     : FastID(ID), Kind(Kind) {}
 
 SCEVComparePredicate::SCEVComparePredicate(const FoldingSetNodeIDRef ID,
-                                   const ICmpInst::Predicate Pred,
-                                   const SCEV *LHS, const SCEV *RHS)
-  : SCEVPredicate(ID, P_Compare), Pred(Pred), LHS(LHS), RHS(RHS) {
+                                           const ICmpInst::Predicate Pred,
+                                           SCEVUse LHS, SCEVUse RHS)
+    : SCEVPredicate(ID, P_Compare), Pred(Pred), LHS(LHS), RHS(RHS) {
   assert(LHS->getType() == RHS->getType() && "LHS and RHS types don't match");
   assert(LHS != RHS && "LHS and RHS are the same SCEV");
 }
@@ -14744,9 +14734,8 @@ PredicatedScalarEvolution::PredicatedScalarEvolution(ScalarEvolution &SE,
   Preds = std::make_unique<SCEVUnionPredicate>(Empty);
 }
 
-void ScalarEvolution::registerUser(const SCEV *User,
-                                   ArrayRef<const SCEV *> Ops) {
-  for (const auto *Op : Ops)
+void ScalarEvolution::registerUser(SCEVUse User, ArrayRef<SCEVUse> Ops) {
+  for (const auto Op : Ops)
     // We do not expect that forgetting cached data for SCEVConstants will ever
     // open any prospects for sharpening or introduce any correctness issues,
     // so we don't bother storing their dependencies.
@@ -14754,8 +14743,8 @@ void ScalarEvolution::registerUser(const SCEV *User,
       SCEVUsers[Op].insert(User);
 }
 
-const SCEV *PredicatedScalarEvolution::getSCEV(Value *V) {
-  const SCEV *Expr = SE.getSCEV(V);
+SCEVUse PredicatedScalarEvolution::getSCEV(Value *V) {
+  SCEVUse Expr = SE.getSCEV(V);
   RewriteEntry &Entry = RewriteMap[Expr];
 
   // If we already have an entry and the version matches, return it.
@@ -14767,13 +14756,13 @@ const SCEV *PredicatedScalarEvolution::getSCEV(Value *V) {
   if (Entry.second)
     Expr = Entry.second;
 
-  const SCEV *NewSCEV = SE.rewriteUsingPredicate(Expr, &L, *Preds);
+  SCEVUse NewSCEV = SE.rewriteUsingPredicate(Expr, &L, *Preds);
   Entry = {Generation, NewSCEV};
 
   return NewSCEV;
 }
 
-const SCEV *PredicatedScalarEvolution::getBackedgeTakenCount() {
+SCEVUse PredicatedScalarEvolution::getBackedgeTakenCount() {
   if (!BackedgeCount) {
     SmallVector<const SCEVPredicate *, 4> Preds;
     BackedgeCount = SE.getPredicatedBackedgeTakenCount(&L, Preds);
@@ -14802,7 +14791,7 @@ void PredicatedScalarEvolution::updateGeneration() {
   // If the generation number wrapped recompute everything.
   if (++Generation == 0) {
     for (auto &II : RewriteMap) {
-      const SCEV *Rewritten = II.second.second;
+      SCEVUse Rewritten = II.second.second;
       II.second = {Generation, SE.rewriteUsingPredicate(Rewritten, &L, *Preds)};
     }
   }
@@ -14810,7 +14799,7 @@ void PredicatedScalarEvolution::updateGeneration() {
 
 void PredicatedScalarEvolution::setNoOverflow(
     Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags) {
-  const SCEV *Expr = getSCEV(V);
+  SCEVUse Expr = getSCEV(V);
   const auto *AR = cast<SCEVAddRecExpr>(Expr);
 
   auto ImpliedFlags = SCEVWrapPredicate::getImpliedFlags(AR, SE);
@@ -14826,7 +14815,7 @@ void PredicatedScalarEvolution::setNoOverflow(
 
 bool PredicatedScalarEvolution::hasNoOverflow(
     Value *V, SCEVWrapPredicate::IncrementWrapFlags Flags) {
-  const SCEV *Expr = getSCEV(V);
+  SCEVUse Expr = getSCEV(V);
   const auto *AR = cast<SCEVAddRecExpr>(Expr);
 
   Flags = SCEVWrapPredicate::clearFlags(
@@ -14841,7 +14830,7 @@ bool PredicatedScalarEvolution::hasNoOverflow(
 }
 
 const SCEVAddRecExpr *PredicatedScalarEvolution::getAsAddRec(Value *V) {
-  const SCEV *Expr = this->getSCEV(V);
+  SCEVUse Expr = this->getSCEV(V);
   SmallPtrSet<const SCEVPredicate *, 4> NewPreds;
   auto *New = SE.convertSCEVToAddRecWithPredicates(Expr, &L, NewPreds);
 
@@ -14871,7 +14860,7 @@ void PredicatedScalarEvolution::print(raw_ostream &OS, unsigned Depth) const {
       if (!SE.isSCEVable(I.getType()))
         continue;
 
-      auto *Expr = SE.getSCEV(&I);
+      auto Expr = SE.getSCEV(&I);
       auto II = RewriteMap.find(Expr);
 
       if (II == RewriteMap.end())
@@ -14892,8 +14881,7 @@ void PredicatedScalarEvolution::print(raw_ostream &OS, unsigned Depth) const {
 // for URem with constant power-of-2 second operands.
 // It's not always easy, as A and B can be folded (imagine A is X / 2, and B is
 // 4, A / B becomes X / 8).
-bool ScalarEvolution::matchURem(const SCEV *Expr, const SCEV *&LHS,
-                                const SCEV *&RHS) {
+bool ScalarEvolution::matchURem(SCEVUse Expr, SCEVUse &LHS, SCEVUse &RHS) {
   // Try to match 'zext (trunc A to iB) to iY', which is used
   // for URem with constant power-of-2 second operands. Make sure the size of
   // the operand A matches the size of the whole expressions.
@@ -14915,13 +14903,13 @@ bool ScalarEvolution::matchURem(const SCEV *Expr, const SCEV *&LHS,
   if (Add == nullptr || Add->getNumOperands() != 2)
     return false;
 
-  const SCEV *A = Add->getOperand(1);
+  SCEVUse A = Add->getOperand(1);
   const auto *Mul = dyn_cast<SCEVMulExpr>(Add->getOperand(0));
 
   if (Mul == nullptr)
     return false;
 
-  const auto MatchURemWithDivisor = [&](const SCEV *B) {
+  const auto MatchURemWithDivisor = [&](SCEVUse B) {
     // (SomeExpr + (-(SomeExpr / B) * B)).
     if (Expr == getURemExpr(A, B)) {
       LHS = A;
@@ -14945,17 +14933,16 @@ bool ScalarEvolution::matchURem(const SCEV *Expr, const SCEV *&LHS,
   return false;
 }
 
-const SCEV *
-ScalarEvolution::computeSymbolicMaxBackedgeTakenCount(const Loop *L) {
+SCEVUse ScalarEvolution::computeSymbolicMaxBackedgeTakenCount(const Loop *L) {
   SmallVector<BasicBlock*, 16> ExitingBlocks;
   L->getExitingBlocks(ExitingBlocks);
 
   // Form an expression for the maximum exit count possible for this loop. We
   // merge the max and exact information to approximate a version of
   // getConstantMaxBackedgeTakenCount which isn't restricted to just constants.
-  SmallVector<const SCEV*, 4> ExitCounts;
+  SmallVector<SCEVUse, 4> ExitCounts;
   for (BasicBlock *ExitingBB : ExitingBlocks) {
-    const SCEV *ExitCount =
+    SCEVUse ExitCount =
         getExitCount(L, ExitingBB, ScalarEvolution::SymbolicMaximum);
     if (!isa<SCEVCouldNotCompute>(ExitCount)) {
       assert(DT.dominates(ExitingBB, L->getLoopLatch()) &&
@@ -14973,34 +14960,33 @@ ScalarEvolution::computeSymbolicMaxBackedgeTakenCount(const Loop *L) {
 /// in the map. It skips AddRecExpr because we cannot guarantee that the
 /// replacement is loop invariant in the loop of the AddRec.
 class SCEVLoopGuardRewriter : public SCEVRewriteVisitor<SCEVLoopGuardRewriter> {
-  const DenseMap<const SCEV *, const SCEV *> ⤅
+  const DenseMap<const SCEV *, SCEVUse> ⤅
 
 public:
-  SCEVLoopGuardRewriter(ScalarEvolution &SE,
-                        DenseMap<const SCEV *, const SCEV *> &M)
+  SCEVLoopGuardRewriter(ScalarEvolution &SE, DenseMap<const SCEV *, SCEVUse> &M)
       : SCEVRewriteVisitor(SE), Map(M) {}
 
-  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { return Expr; }
+  SCEVUse visitAddRecExpr(const SCEVAddRecExpr *Expr) { return Expr; }
 
-  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
+  SCEVUse visitUnknown(const SCEVUnknown *Expr) {
     auto I = Map.find(Expr);
     if (I == Map.end())
       return Expr;
     return I->second;
   }
 
-  const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
+  SCEVUse visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
     auto I = Map.find(Expr);
     if (I == Map.end()) {
       // If we didn't find the extact ZExt expr in the map, check if there's an
       // entry for a smaller ZExt we can use instead.
       Type *Ty = Expr->getType();
-      const SCEV *Op = Expr->getOperand(0);
+      SCEVUse Op = Expr->getOperand(0);
       unsigned Bitwidth = Ty->getScalarSizeInBits() / 2;
       while (Bitwidth % 8 == 0 && Bitwidth >= 8 &&
              Bitwidth > Op->getType()->getScalarSizeInBits()) {
         Type *NarrowTy = IntegerType::get(SE.getContext(), Bitwidth);
-        auto *NarrowExt = SE.getZeroExtendExpr(Op, NarrowTy);
+        auto NarrowExt = SE.getZeroExtendExpr(Op, NarrowTy);
         auto I = Map.find(NarrowExt);
         if (I != Map.end())
           return SE.getZeroExtendExpr(I->second, Ty);
@@ -15013,7 +14999,7 @@ class SCEVLoopGuardRewriter : public SCEVRewriteVisitor<SCEVLoopGuardRewriter> {
     return I->second;
   }
 
-  const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
+  SCEVUse visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
     auto I = Map.find(Expr);
     if (I == Map.end())
       return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSignExtendExpr(
@@ -15021,14 +15007,14 @@ class SCEVLoopGuardRewriter : public SCEVRewriteVisitor<SCEVLoopGuardRewriter> {
     return I->second;
   }
 
-  const SCEV *visitUMinExpr(const SCEVUMinExpr *Expr) {
+  SCEVUse visitUMinExpr(const SCEVUMinExpr *Expr) {
     auto I = Map.find(Expr);
     if (I == Map.end())
       return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitUMinExpr(Expr);
     return I->second;
   }
 
-  const SCEV *visitSMinExpr(const SCEVSMinExpr *Expr) {
+  SCEVUse visitSMinExpr(const SCEVSMinExpr *Expr) {
     auto I = Map.find(Expr);
     if (I == Map.end())
       return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSMinExpr(Expr);
@@ -15036,12 +15022,11 @@ class SCEVLoopGuardRewriter : public SCEVRewriteVisitor<SCEVLoopGuardRewriter> {
   }
 };
 
-const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
-  SmallVector<const SCEV *> ExprsToRewrite;
-  auto CollectCondition = [&](ICmpInst::Predicate Predicate, const SCEV *LHS,
-                              const SCEV *RHS,
-                              DenseMap<const SCEV *, const SCEV *>
-                                  &RewriteMap) {
+SCEVUse ScalarEvolution::applyLoopGuards(SCEVUse Expr, const Loop *L) {
+  SmallVector<SCEVUse> ExprsToRewrite;
+  auto CollectCondition = [&](ICmpInst::Predicate Predicate, SCEVUse LHS,
+                              SCEVUse RHS,
+                              DenseMap<const SCEV *, SCEVUse> &RewriteMap) {
     // WARNING: It is generally unsound to apply any wrap flags to the proposed
     // replacement SCEV which isn't directly implied by the structure of that
     // SCEV.  In particular, using contextual facts to imply flags is *NOT*
@@ -15076,7 +15061,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
       if (ExactRegion.isWrappedSet() || ExactRegion.isFullSet())
         return false;
       auto I = RewriteMap.find(LHSUnknown);
-      const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : LHSUnknown;
+      SCEVUse RewrittenLHS = I != RewriteMap.end() ? I->second : LHSUnknown;
       RewriteMap[LHSUnknown] = getUMaxExpr(
           getConstant(ExactRegion.getUnsignedMin()),
           getUMinExpr(RewrittenLHS, getConstant(ExactRegion.getUnsignedMax())));
@@ -15090,8 +15075,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // constant operand. If so, return in \p SCTy the SCEV type and in \p RHS
     // the non-constant operand and in \p LHS the constant operand.
     auto IsMinMaxSCEVWithNonNegativeConstant =
-        [&](const SCEV *Expr, SCEVTypes &SCTy, const SCEV *&LHS,
-            const SCEV *&RHS) {
+        [&](SCEVUse Expr, SCEVTypes &SCTy, SCEVUse &LHS, SCEVUse &RHS) {
           if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr)) {
             if (MinMax->getNumOperands() != 2)
               return false;
@@ -15109,7 +15093,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
 
     // Checks whether Expr is a non-negative constant, and Divisor is a positive
     // constant, and returns their APInt in ExprVal and in DivisorVal.
-    auto GetNonNegExprAndPosDivisor = [&](const SCEV *Expr, const SCEV *Divisor,
+    auto GetNonNegExprAndPosDivisor = [&](SCEVUse Expr, SCEVUse Divisor,
                                           APInt &ExprVal, APInt &DivisorVal) {
       auto *ConstExpr = dyn_cast<SCEVConstant>(Expr);
       auto *ConstDivisor = dyn_cast<SCEVConstant>(Divisor);
@@ -15123,8 +15107,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // Return a new SCEV that modifies \p Expr to the closest number divides by
     // \p Divisor and greater or equal than Expr.
     // For now, only handle constant Expr and Divisor.
-    auto GetNextSCEVDividesByDivisor = [&](const SCEV *Expr,
-                                           const SCEV *Divisor) {
+    auto GetNextSCEVDividesByDivisor = [&](SCEVUse Expr, SCEVUse Divisor) {
       APInt ExprVal;
       APInt DivisorVal;
       if (!GetNonNegExprAndPosDivisor(Expr, Divisor, ExprVal, DivisorVal))
@@ -15139,8 +15122,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // Return a new SCEV that modifies \p Expr to the closest number divides by
     // \p Divisor and less or equal than Expr.
     // For now, only handle constant Expr and Divisor.
-    auto GetPreviousSCEVDividesByDivisor = [&](const SCEV *Expr,
-                                               const SCEV *Divisor) {
+    auto GetPreviousSCEVDividesByDivisor = [&](SCEVUse Expr, SCEVUse Divisor) {
       APInt ExprVal;
       APInt DivisorVal;
       if (!GetNonNegExprAndPosDivisor(Expr, Divisor, ExprVal, DivisorVal))
@@ -15153,10 +15135,9 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // Apply divisibilty by \p Divisor on MinMaxExpr with constant values,
     // recursively. This is done by aligning up/down the constant value to the
     // Divisor.
-    std::function<const SCEV *(const SCEV *, const SCEV *)>
-        ApplyDivisibiltyOnMinMaxExpr = [&](const SCEV *MinMaxExpr,
-                                           const SCEV *Divisor) {
-          const SCEV *MinMaxLHS = nullptr, *MinMaxRHS = nullptr;
+    std::function<SCEVUse(SCEVUse, SCEVUse)> ApplyDivisibiltyOnMinMaxExpr =
+        [&](SCEVUse MinMaxExpr, SCEVUse Divisor) {
+          SCEVUse MinMaxLHS = nullptr, MinMaxRHS = nullptr;
           SCEVTypes SCTy;
           if (!IsMinMaxSCEVWithNonNegativeConstant(MinMaxExpr, SCTy, MinMaxLHS,
                                                    MinMaxRHS))
@@ -15165,10 +15146,10 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
               isa<SCEVSMinExpr>(MinMaxExpr) || isa<SCEVUMinExpr>(MinMaxExpr);
           assert(isKnownNonNegative(MinMaxLHS) &&
                  "Expected non-negative operand!");
-          auto *DivisibleExpr =
+          auto DivisibleExpr =
               IsMin ? GetPreviousSCEVDividesByDivisor(MinMaxLHS, Divisor)
                     : GetNextSCEVDividesByDivisor(MinMaxLHS, Divisor);
-          SmallVector<const SCEV *> Ops = {
+          SmallVector<SCEVUse> Ops = {
               ApplyDivisibiltyOnMinMaxExpr(MinMaxRHS, Divisor), DivisibleExpr};
           return getMinMaxExpr(SCTy, Ops);
         };
@@ -15180,15 +15161,14 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
         RHSC->getValue()->isNullValue()) {
       // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to
       // explicitly express that.
-      const SCEV *URemLHS = nullptr;
-      const SCEV *URemRHS = nullptr;
+      SCEVUse URemLHS = nullptr;
+      SCEVUse URemRHS = nullptr;
       if (matchURem(LHS, URemLHS, URemRHS)) {
         if (const SCEVUnknown *LHSUnknown = dyn_cast<SCEVUnknown>(URemLHS)) {
           auto I = RewriteMap.find(LHSUnknown);
-          const SCEV *RewrittenLHS =
-              I != RewriteMap.end() ? I->second : LHSUnknown;
+          SCEVUse RewrittenLHS = I != RewriteMap.end() ? I->second : LHSUnknown;
           RewrittenLHS = ApplyDivisibiltyOnMinMaxExpr(RewrittenLHS, URemRHS);
-          const auto *Multiple =
+          const auto Multiple =
               getMulExpr(getUDivExpr(RewrittenLHS, URemRHS), URemRHS);
           RewriteMap[LHSUnknown] = Multiple;
           ExprsToRewrite.push_back(LHSUnknown);
@@ -15211,8 +15191,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // and \p FromRewritten are the same (i.e. there has been no rewrite
     // registered for \p From), then puts this value in the list of rewritten
     // expressions.
-    auto AddRewrite = [&](const SCEV *From, const SCEV *FromRewritten,
-                          const SCEV *To) {
+    auto AddRewrite = [&](SCEVUse From, SCEVUse FromRewritten, SCEVUse To) {
       if (From == FromRewritten)
         ExprsToRewrite.push_back(From);
       RewriteMap[From] = To;
@@ -15221,7 +15200,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // Checks whether \p S has already been rewritten. In that case returns the
     // existing rewrite because we want to chain further rewrites onto the
     // already rewritten value. Otherwise returns \p S.
-    auto GetMaybeRewritten = [&](const SCEV *S) {
+    auto GetMaybeRewritten = [&](SCEVUse S) {
       auto I = RewriteMap.find(S);
       return I != RewriteMap.end() ? I->second : S;
     };
@@ -15233,13 +15212,13 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // example, if Expr = umin (umax ((A /u 8) * 8, 16), 64), return true since
     // (A /u 8) * 8 matched the pattern, and return the constant SCEV 8 in \p
     // DividesBy.
-    std::function<bool(const SCEV *, const SCEV *&)> HasDivisibiltyInfo =
-        [&](const SCEV *Expr, const SCEV *&DividesBy) {
+    std::function<bool(SCEVUse, SCEVUse &)> HasDivisibiltyInfo =
+        [&](SCEVUse Expr, SCEVUse &DividesBy) {
           if (auto *Mul = dyn_cast<SCEVMulExpr>(Expr)) {
             if (Mul->getNumOperands() != 2)
               return false;
-            auto *MulLHS = Mul->getOperand(0);
-            auto *MulRHS = Mul->getOperand(1);
+            auto MulLHS = Mul->getOperand(0);
+            auto MulRHS = Mul->getOperand(1);
             if (isa<SCEVConstant>(MulLHS))
               std::swap(MulLHS, MulRHS);
             if (auto *Div = dyn_cast<SCEVUDivExpr>(MulLHS))
@@ -15255,8 +15234,8 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
         };
 
     // Return true if Expr known to divide by \p DividesBy.
-    std::function<bool(const SCEV *, const SCEV *&)> IsKnownToDivideBy =
-        [&](const SCEV *Expr, const SCEV *DividesBy) {
+    std::function<bool(SCEVUse, SCEVUse &)> IsKnownToDivideBy =
+        [&](SCEVUse Expr, SCEVUse DividesBy) {
           if (getURemExpr(Expr, DividesBy)->isZero())
             return true;
           if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr))
@@ -15265,8 +15244,8 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
           return false;
         };
 
-    const SCEV *RewrittenLHS = GetMaybeRewritten(LHS);
-    const SCEV *DividesBy = nullptr;
+    SCEVUse RewrittenLHS = GetMaybeRewritten(LHS);
+    SCEVUse DividesBy = nullptr;
     if (HasDivisibiltyInfo(RewrittenLHS, DividesBy))
       // Check that the whole expression is divided by DividesBy
       DividesBy =
@@ -15283,50 +15262,50 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
     // We cannot express strict predicates in SCEV, so instead we replace them
     // with non-strict ones against plus or minus one of RHS depending on the
     // predicate.
-    const SCEV *One = getOne(RHS->getType());
+    SCEVUse One = getOne(RHS->getType());
     switch (Predicate) {
-      case CmpInst::ICMP_ULT:
-        if (RHS->getType()->isPointerTy())
-          return;
-        RHS = getUMaxExpr(RHS, One);
-        [[fallthrough]];
-      case CmpInst::ICMP_SLT: {
-        RHS = getMinusSCEV(RHS, One);
-        RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
-        break;
-      }
-      case CmpInst::ICMP_UGT:
-      case CmpInst::ICMP_SGT:
-        RHS = getAddExpr(RHS, One);
-        RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
-        break;
-      case CmpInst::ICMP_ULE:
-      case CmpInst::ICMP_SLE:
-        RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
-        break;
-      case CmpInst::ICMP_UGE:
-      case CmpInst::ICMP_SGE:
-        RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
-        break;
-      default:
-        break;
+    case CmpInst::ICMP_ULT:
+      if (RHS->getType()->isPointerTy())
+        return;
+      RHS = getUMaxExpr(RHS, One);
+      [[fallthrough]];
+    case CmpInst::ICMP_SLT: {
+      RHS = getMinusSCEV(RHS, One);
+      RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+      break;
+    }
+    case CmpInst::ICMP_UGT:
+    case CmpInst::ICMP_SGT:
+      RHS = getAddExpr(RHS, One);
+      RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+      break;
+    case CmpInst::ICMP_ULE:
+    case CmpInst::ICMP_SLE:
+      RHS = DividesBy ? GetPreviousSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+      break;
+    case CmpInst::ICMP_UGE:
+    case CmpInst::ICMP_SGE:
+      RHS = DividesBy ? GetNextSCEVDividesByDivisor(RHS, DividesBy) : RHS;
+      break;
+    default:
+      break;
     }
 
-    SmallVector<const SCEV *, 16> Worklist(1, LHS);
-    SmallPtrSet<const SCEV *, 16> Visited;
+    SmallVector<SCEVUse, 16> Worklist(1, LHS);
+    SmallPtrSet<SCEVUse, 16> Visited;
 
     auto EnqueueOperands = [&Worklist](const SCEVNAryExpr *S) {
       append_range(Worklist, S->operands());
     };
 
     while (!Worklist.empty()) {
-      const SCEV *From = Worklist.pop_back_val();
+      SCEVUse From = Worklist.pop_back_val();
       if (isa<SCEVConstant>(From))
         continue;
       if (!Visited.insert(From).second)
         continue;
-      const SCEV *FromRewritten = GetMaybeRewritten(From);
-      const SCEV *To = nullptr;
+      SCEVUse FromRewritten = GetMaybeRewritten(From);
+      SCEVUse To = nullptr;
 
       switch (Predicate) {
       case CmpInst::ICMP_ULT:
@@ -15360,7 +15339,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
       case CmpInst::ICMP_NE:
         if (isa<SCEVConstant>(RHS) &&
             cast<SCEVConstant>(RHS)->getValue()->isNullValue()) {
-          const SCEV *OneAlignedUp =
+          SCEVUse OneAlignedUp =
               DividesBy ? GetNextSCEVDividesByDivisor(One, DividesBy) : One;
           To = getUMaxExpr(FromRewritten, OneAlignedUp);
         }
@@ -15417,7 +15396,7 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
   // Conditions are processed in reverse order, so the earliest conditions is
   // processed first. This ensures the SCEVs with the shortest dependency chains
   // are constructed first.
-  DenseMap<const SCEV *, const SCEV *> RewriteMap;
+  DenseMap<const SCEV *, SCEVUse> RewriteMap;
   for (auto [Term, EnterIfTrue] : reverse(Terms)) {
     SmallVector<Value *, 8> Worklist;
     SmallPtrSet<Value *, 8> Visited;
@@ -15430,8 +15409,8 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
       if (auto *Cmp = dyn_cast<ICmpInst>(Cond)) {
         auto Predicate =
             EnterIfTrue ? Cmp->getPredicate() : Cmp->getInversePredicate();
-        const auto *LHS = getSCEV(Cmp->getOperand(0));
-        const auto *RHS = getSCEV(Cmp->getOperand(1));
+        const auto LHS = getSCEV(Cmp->getOperand(0));
+        const auto RHS = getSCEV(Cmp->getOperand(1));
         CollectCondition(Predicate, LHS, RHS, RewriteMap);
         continue;
       }
@@ -15452,8 +15431,8 @@ const SCEV *ScalarEvolution::applyLoopGuards(const SCEV *Expr, const Loop *L) {
   // expressions with the information in the map. This applies information to
   // sub-expressions.
   if (ExprsToRewrite.size() > 1) {
-    for (const SCEV *Expr : ExprsToRewrite) {
-      const SCEV *RewriteTo = RewriteMap[Expr];
+    for (SCEVUse Expr : ExprsToRewrite) {
+      SCEVUse RewriteTo = RewriteMap[Expr];
       RewriteMap.erase(Expr);
       SCEVLoopGuardRewriter Rewriter(*this, RewriteMap);
       RewriteMap.insert({Expr, Rewriter.visit(RewriteTo)});
diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
index 104e8ceb79670..081c75fb6950e 100644
--- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
@@ -430,8 +430,8 @@ bool InductiveRangeCheck::reassociateSubLHS(
   auto getExprScaledIfOverflow = [&](Instruction::BinaryOps BinOp,
                                      const SCEV *LHS,
                                      const SCEV *RHS) -> const SCEV * {
-    const SCEV *(ScalarEvolution::*Operation)(const SCEV *, const SCEV *,
-                                              SCEV::NoWrapFlags, unsigned);
+    SCEVUse (ScalarEvolution:: *Operation)(SCEVUse, SCEVUse, SCEV::NoWrapFlags,
+                                           unsigned);
     switch (BinOp) {
     default:
       llvm_unreachable("Unsupported binary op");
@@ -750,7 +750,7 @@ InductiveRangeCheck::computeSafeIterationSpace(ScalarEvolution &SE,
   const SCEV *Zero = SE.getZero(M->getType());
 
   // This function returns SCEV equal to 1 if X is non-negative 0 otherwise.
-  auto SCEVCheckNonNegative = [&](const SCEV *X) {
+  auto SCEVCheckNonNegative = [&](const SCEV *X) -> const SCEV * {
     const Loop *L = IndVar->getLoop();
     const SCEV *Zero = SE.getZero(X->getType());
     const SCEV *One = SE.getOne(X->getType());
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index c7e25c9f3d2c9..5f2110bb15544 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -842,8 +842,8 @@ bool LoopIdiomRecognize::processLoopMemSet(MemSetInst *MSI,
     return false;
   }
 
-  const SCEV *PointerStrideSCEV = Ev->getOperand(1);
-  const SCEV *MemsetSizeSCEV = SE->getSCEV(MSI->getLength());
+  SCEVUse PointerStrideSCEV = Ev->getOperand(1);
+  SCEVUse MemsetSizeSCEV = SE->getSCEV(MSI->getLength());
   if (!PointerStrideSCEV || !MemsetSizeSCEV)
     return false;
 
@@ -885,9 +885,9 @@ bool LoopIdiomRecognize::processLoopMemSet(MemSetInst *MSI,
 
     // Compare positive direction PointerStrideSCEV with MemsetSizeSCEV
     IsNegStride = PointerStrideSCEV->isNonConstantNegative();
-    const SCEV *PositiveStrideSCEV =
-        IsNegStride ? SE->getNegativeSCEV(PointerStrideSCEV)
-                    : PointerStrideSCEV;
+    SCEVUse PositiveStrideSCEV = IsNegStride
+                                     ? SE->getNegativeSCEV(PointerStrideSCEV)
+                                     : PointerStrideSCEV;
     LLVM_DEBUG(dbgs() << "  MemsetSizeSCEV: " << *MemsetSizeSCEV << "\n"
                       << "  PositiveStrideSCEV: " << *PositiveStrideSCEV
                       << "\n");
diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 35a17d6060c94..f094d6af136a8 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -3232,8 +3232,9 @@ void LSRInstance::GenerateIVChain(const IVChain &Chain,
       // IncExpr was the result of subtraction of two narrow values, so must
       // be signed.
       const SCEV *IncExpr = SE.getNoopOrSignExtend(Inc.IncExpr, IntTy);
-      LeftOverExpr = LeftOverExpr ?
-        SE.getAddExpr(LeftOverExpr, IncExpr) : IncExpr;
+      LeftOverExpr = LeftOverExpr
+                         ? SE.getAddExpr(LeftOverExpr, IncExpr).getPointer()
+                         : IncExpr;
     }
     if (LeftOverExpr && !LeftOverExpr->isZero()) {
       // Expand the IV increment.
@@ -3613,7 +3614,7 @@ static const SCEV *CollectSubexprs(const SCEV *S, const SCEVConstant *C,
     for (const SCEV *S : Add->operands()) {
       const SCEV *Remainder = CollectSubexprs(S, C, Ops, L, SE, Depth+1);
       if (Remainder)
-        Ops.push_back(C ? SE.getMulExpr(C, Remainder) : Remainder);
+        Ops.push_back(C ? SE.getMulExpr(C, Remainder).getPointer() : Remainder);
     }
     return nullptr;
   } else if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
@@ -3626,7 +3627,7 @@ static const SCEV *CollectSubexprs(const SCEV *S, const SCEVConstant *C,
     // Split the non-zero AddRec unless it is part of a nested recurrence that
     // does not pertain to this loop.
     if (Remainder && (AR->getLoop() == L || !isa<SCEVAddRecExpr>(Remainder))) {
-      Ops.push_back(C ? SE.getMulExpr(C, Remainder) : Remainder);
+      Ops.push_back(C ? SE.getMulExpr(C, Remainder).getPointer() : Remainder);
       Remainder = nullptr;
     }
     if (Remainder != AR->getStart()) {
diff --git a/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll b/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll
index 326ee75e135b0..bc9e8004ec5df 100644
--- a/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll
+++ b/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll
@@ -846,11 +846,9 @@ failed:
 define i32 @test_litter_conditions_constant(i32 %start, i32 %len) {
 ; CHECK-LABEL: @test_litter_conditions_constant(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[START:%.*]], -1
-; CHECK-NEXT:    [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN:%.*]]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
 ; CHECK-NEXT:    [[CANONICAL_IV:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[CANONICAL_IV_NEXT:%.*]], [[BACKEDGE]] ]
 ; CHECK-NEXT:    [[CONSTANT_CHECK:%.*]] = icmp ult i32 [[CANONICAL_IV]], 65635
 ; CHECK-NEXT:    br i1 [[CONSTANT_CHECK]], label [[CONSTANT_CHECK_PASSED:%.*]], label [[CONSTANT_CHECK_FAILED:%.*]]
@@ -860,8 +858,10 @@ define i32 @test_litter_conditions_constant(i32 %start, i32 %len) {
 ; CHECK-NEXT:    [[AND_1:%.*]] = and i1 [[ZERO_CHECK]], [[FAKE_1]]
 ; CHECK-NEXT:    br i1 [[AND_1]], label [[RANGE_CHECK_BLOCK:%.*]], label [[FAILED_1:%.*]]
 ; CHECK:       range_check_block:
+; CHECK-NEXT:    [[IV_MINUS_1:%.*]] = add i32 [[IV]], -1
+; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[IV_MINUS_1]], [[LEN:%.*]]
 ; CHECK-NEXT:    [[FAKE_2:%.*]] = call i1 @cond()
-; CHECK-NEXT:    [[AND_2:%.*]] = and i1 [[RANGE_CHECK_FIRST_ITER]], [[FAKE_2]]
+; CHECK-NEXT:    [[AND_2:%.*]] = and i1 [[RANGE_CHECK]], [[FAKE_2]]
 ; CHECK-NEXT:    br i1 [[AND_2]], label [[BACKEDGE]], label [[FAILED_2:%.*]]
 ; CHECK:       backedge:
 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], -1
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index 8ab22ef746c25..2ee98205d5ad2 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -63,10 +63,10 @@ static std::optional<APInt> computeConstantDifference(ScalarEvolution &SE,
   return SE.computeConstantDifference(LHS, RHS);
 }
 
-  static bool matchURem(ScalarEvolution &SE, const SCEV *Expr, const SCEV *&LHS,
-                        const SCEV *&RHS) {
-    return SE.matchURem(Expr, LHS, RHS);
-  }
+static bool matchURem(ScalarEvolution &SE, const SCEV *Expr, SCEVUse &LHS,
+                      SCEVUse &RHS) {
+  return SE.matchURem(Expr, LHS, RHS);
+}
 
   static bool isImpliedCond(
       ScalarEvolution &SE, ICmpInst::Predicate Pred, const SCEV *LHS,
@@ -1480,8 +1480,8 @@ TEST_F(ScalarEvolutionsTest, MatchURem) {
   runWithSE(*M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
     for (auto *N : {"rem1", "rem2", "rem3", "rem5"}) {
       auto *URemI = getInstructionByName(F, N);
-      auto *S = SE.getSCEV(URemI);
-      const SCEV *LHS, *RHS;
+      const SCEV *S = SE.getSCEV(URemI);
+      SCEVUse LHS, RHS;
       EXPECT_TRUE(matchURem(SE, S, LHS, RHS));
       EXPECT_EQ(LHS, SE.getSCEV(URemI->getOperand(0)));
       EXPECT_EQ(RHS, SE.getSCEV(URemI->getOperand(1)));
@@ -1493,8 +1493,8 @@ TEST_F(ScalarEvolutionsTest, MatchURem) {
     // match results are extended to the size of the input expression.
     auto *Ext = getInstructionByName(F, "ext");
     auto *URem1 = getInstructionByName(F, "rem4");
-    auto *S = SE.getSCEV(Ext);
-    const SCEV *LHS, *RHS;
+    const SCEV *S = SE.getSCEV(Ext);
+    SCEVUse LHS, RHS;
     EXPECT_TRUE(matchURem(SE, S, LHS, RHS));
     EXPECT_NE(LHS, SE.getSCEV(URem1->getOperand(0)));
     // RHS and URem1->getOperand(1) have different widths, so compare the

>From 9b5d058664cd80bb71b13e96f02ae29c280eeb37 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sun, 12 May 2024 09:57:54 +0100
Subject: [PATCH 3/3] [SCEV] Add option to request use-specific SCEV for a GEP
 expr (WIP).

Use SCEVUse from https://github.com/llvm/llvm-project/pull/91961 to
return a SCEVUse with use-specific no-wrap flags for GEP expr, when
demanded.

Clients need to opt-in, as the use-specific flags may not be valid in
some contexts (e.g. backedge taken counts).
---
 llvm/include/llvm/Analysis/ScalarEvolution.h  | 14 ++++----
 llvm/lib/Analysis/ScalarEvolution.cpp         | 36 +++++++++++--------
 .../Analysis/ScalarEvolution/min-max-exprs.ll |  2 +-
 .../ScalarEvolution/no-wrap-add-exprs.ll      | 12 +++----
 .../no-wrap-symbolic-becount.ll               |  2 +-
 .../test/Analysis/ScalarEvolution/ptrtoint.ll |  4 +--
 llvm/test/Analysis/ScalarEvolution/sdiv.ll    |  2 +-
 llvm/test/Analysis/ScalarEvolution/srem.ll    |  2 +-
 8 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 2859df9964555..4ca3dbc1c6703 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -653,7 +653,7 @@ class ScalarEvolution {
 
   /// Return a SCEV expression for the full generality of the specified
   /// expression.
-  SCEVUse getSCEV(Value *V);
+  SCEVUse getSCEV(Value *V, bool UseCtx = false);
 
   /// Return an existing SCEV for V if there is one, otherwise return nullptr.
   SCEVUse getExistingSCEV(Value *V);
@@ -735,9 +735,11 @@ class ScalarEvolution {
   /// \p GEP The GEP. The indices contained in the GEP itself are ignored,
   /// instead we use IndexExprs.
   /// \p IndexExprs The expressions for the indices.
-  SCEVUse getGEPExpr(GEPOperator *GEP, ArrayRef<const SCEV *> IndexExprs);
+  SCEVUse getGEPExpr(GEPOperator *GEP, ArrayRef<const SCEV *> IndexExprs,
+                     bool UseCtx = false);
   SCEVUse getGEPExpr(GEPOperator *GEP,
-                     const SmallVectorImpl<SCEVUse> &IndexExprs);
+                     const SmallVectorImpl<SCEVUse> &IndexExprs,
+                     bool UseCtx = false);
   SCEVUse getAbsExpr(SCEVUse Op, bool IsNSW);
   SCEVUse getMinMaxExpr(SCEVTypes Kind, ArrayRef<const SCEV *> Operands);
   SCEVUse getMinMaxExpr(SCEVTypes Kind, SmallVectorImpl<SCEVUse> &Operands);
@@ -1783,11 +1785,11 @@ class ScalarEvolution {
 
   /// We know that there is no SCEV for the specified value.  Analyze the
   /// expression recursively.
-  SCEVUse createSCEV(Value *V);
+  SCEVUse createSCEV(Value *V, bool UseCtx = false);
 
   /// We know that there is no SCEV for the specified value. Create a new SCEV
   /// for \p V iteratively.
-  SCEVUse createSCEVIter(Value *V);
+  SCEVUse createSCEVIter(Value *V, bool UseCtx = false);
   /// Collect operands of \p V for which SCEV expressions should be constructed
   /// first. Returns a SCEV directly if it can be constructed trivially for \p
   /// V.
@@ -1826,7 +1828,7 @@ class ScalarEvolution {
                                    Value *FalseVal);
 
   /// Provide the special handling we need to analyze GEP SCEVs.
-  SCEVUse createNodeForGEP(GEPOperator *GEP);
+  SCEVUse createNodeForGEP(GEPOperator *GEP, bool UseCtx = false);
 
   /// Implementation code for getSCEVAtScope; called at most once for each
   /// SCEV+Loop pair.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 605b66f2ad633..4b2999790e68c 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2741,6 +2741,8 @@ SCEVUse ScalarEvolution::getAddExpr(SmallVectorImpl<SCEVUse> &Ops,
         break;
       // If we have an add, expand the add operands onto the end of the operands
       // list.
+      // CommonFlags = maskFlags(CommonFlags, setFlags(Add->getNoWrapFlags(),
+      // static_cast<SCEV::NoWrapFlags>(Ops[Idx].getInt())));
       Ops.erase(Ops.begin()+Idx);
       append_range(Ops, Add->operands());
       DeletedAdd = true;
@@ -3759,13 +3761,14 @@ SCEVUse ScalarEvolution::getAddRecExpr(SmallVectorImpl<SCEVUse> &Operands,
 }
 
 SCEVUse ScalarEvolution::getGEPExpr(GEPOperator *GEP,
-                                    ArrayRef<const SCEV *> IndexExprs) {
-  return getGEPExpr(GEP, SmallVector<SCEVUse>(IndexExprs));
+                                    ArrayRef<const SCEV *> IndexExprs,
+                                    bool UseCtx) {
+  return getGEPExpr(GEP, SmallVector<SCEVUse>(IndexExprs), UseCtx);
 }
 
-SCEVUse
-ScalarEvolution::getGEPExpr(GEPOperator *GEP,
-                            const SmallVectorImpl<SCEVUse> &IndexExprs) {
+SCEVUse ScalarEvolution::getGEPExpr(GEPOperator *GEP,
+                                    const SmallVectorImpl<SCEVUse> &IndexExprs,
+                                    bool UseCtx) {
   SCEVUse BaseExpr = getSCEV(GEP->getPointerOperand());
   // getSCEV(Base)->getType() has the same address space as Base->getType()
   // because SCEV::getType() preserves the address space.
@@ -3835,6 +3838,9 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
   auto GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
   assert(BaseExpr->getType() == GEPExpr->getType() &&
          "GEP should not change type mid-flight.");
+  if (UseCtx && BaseWrap != SCEV::FlagNUW && GEP->isInBounds() &&
+      isKnownNonNegative(Offset))
+    GEPExpr = SCEVUse(&*GEPExpr, 2);
   return GEPExpr;
 }
 
@@ -4587,12 +4593,12 @@ void ScalarEvolution::insertValueToMap(Value *V, SCEVUse S) {
 
 /// Return an existing SCEV if it exists, otherwise analyze the expression and
 /// create a new one.
-SCEVUse ScalarEvolution::getSCEV(Value *V) {
+SCEVUse ScalarEvolution::getSCEV(Value *V, bool UseCtx) {
   assert(isSCEVable(V->getType()) && "Value is not SCEVable!");
 
   if (SCEVUse S = getExistingSCEV(V))
     return S;
-  return createSCEVIter(V);
+  return createSCEVIter(V, UseCtx);
 }
 
 SCEVUse ScalarEvolution::getExistingSCEV(Value *V) {
@@ -6283,14 +6289,14 @@ SCEVUse ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
 
 /// Expand GEP instructions into add and multiply operations. This allows them
 /// to be analyzed by regular SCEV code.
-SCEVUse ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
+SCEVUse ScalarEvolution::createNodeForGEP(GEPOperator *GEP, bool UseCtx) {
   assert(GEP->getSourceElementType()->isSized() &&
          "GEP source element type must be sized");
 
   SmallVector<SCEVUse, 4> IndexExprs;
   for (Value *Index : GEP->indices())
     IndexExprs.push_back(getSCEV(Index));
-  return getGEPExpr(GEP, IndexExprs);
+  return getGEPExpr(GEP, IndexExprs, UseCtx);
 }
 
 APInt ScalarEvolution::getConstantMultipleImpl(SCEVUse S) {
@@ -7440,7 +7446,7 @@ bool ScalarEvolution::loopIsFiniteByAssumption(const Loop *L) {
   return isFinite(L) || (isMustProgress(L) && loopHasNoSideEffects(L));
 }
 
-SCEVUse ScalarEvolution::createSCEVIter(Value *V) {
+SCEVUse ScalarEvolution::createSCEVIter(Value *V, bool UseCtx) {
   // Worklist item with a Value and a bool indicating whether all operands have
   // been visited already.
   using PointerTy = PointerIntPair<Value *, 1, bool>;
@@ -7459,7 +7465,7 @@ SCEVUse ScalarEvolution::createSCEVIter(Value *V) {
     SCEVUse CreatedSCEV = nullptr;
     // If all operands have been visited already, create the SCEV.
     if (E.getInt()) {
-      CreatedSCEV = createSCEV(CurV);
+      CreatedSCEV = createSCEV(CurV, UseCtx);
     } else {
       // Otherwise get the operands we need to create SCEV's for before creating
       // the SCEV for CurV. If the SCEV for CurV can be constructed trivially,
@@ -7668,7 +7674,7 @@ SCEVUse ScalarEvolution::getOperandsToCreate(Value *V,
   return nullptr;
 }
 
-SCEVUse ScalarEvolution::createSCEV(Value *V) {
+SCEVUse ScalarEvolution::createSCEV(Value *V, bool UseCtx) {
   if (!isSCEVable(V->getType()))
     return getUnknown(V);
 
@@ -8077,7 +8083,7 @@ SCEVUse ScalarEvolution::createSCEV(Value *V) {
     break;
 
   case Instruction::GetElementPtr:
-    return createNodeForGEP(cast<GEPOperator>(U));
+    return createNodeForGEP(cast<GEPOperator>(U), UseCtx);
 
   case Instruction::PHI:
     return createNodeForPHI(cast<PHINode>(U));
@@ -13623,8 +13629,8 @@ void ScalarEvolution::print(raw_ostream &OS) const {
       if (isSCEVable(I.getType()) && !isa<CmpInst>(I)) {
         OS << I << '\n';
         OS << "  -->  ";
-        SCEVUse SV = SE.getSCEV(&I);
-        SV->print(OS);
+        SCEVUse SV = SE.getSCEV(&I, /*UseCtx=*/true);
+        SV.print(OS);
         if (!isa<SCEVCouldNotCompute>(SV)) {
           OS << " U: ";
           SE.getUnsignedRange(SV).print(OS);
diff --git a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
index 6ededf2477711..a80c0f4ebc5ea 100644
--- a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
@@ -42,7 +42,7 @@ define void @f(ptr %A, i32 %N) {
 ; CHECK-NEXT:    %tmp19 = select i1 %tmp14, i64 0, i64 %tmp17
 ; CHECK-NEXT:    --> (-3 + (3 smax {0,+,1}<nuw><nsw><%bb1>))<nsw> U: [0,2147483645) S: [0,2147483645) Exits: (-3 + (3 smax (zext i32 (0 smax %N) to i64)))<nsw> LoopDispositions: { %bb1: Computable }
 ; CHECK-NEXT:    %tmp21 = getelementptr inbounds i32, ptr %A, i64 %tmp19
-; CHECK-NEXT:    --> (-12 + (4 * (3 smax {0,+,1}<nuw><nsw><%bb1>))<nuw><nsw> + %A) U: full-set S: full-set Exits: (-12 + (4 * (3 smax (zext i32 (0 smax %N) to i64)))<nuw><nsw> + %A) LoopDispositions: { %bb1: Computable }
+; CHECK-NEXT:    --> (-12 + (4 * (3 smax {0,+,1}<nuw><nsw><%bb1>))<nuw><nsw> + %A)(u nuw) U: full-set S: full-set Exits: (-12 + (4 * (3 smax (zext i32 (0 smax %N) to i64)))<nuw><nsw> + %A) LoopDispositions: { %bb1: Computable }
 ; CHECK-NEXT:    %tmp23 = add nuw nsw i32 %i.0, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><%bb1> U: [1,-2147483647) S: [1,-2147483647) Exits: (1 + (0 smax %N))<nuw> LoopDispositions: { %bb1: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @f
diff --git a/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
index bd2ffddf396fe..4e13de3a2a09c 100644
--- a/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
@@ -209,11 +209,11 @@ define void @f3(ptr %x_addr, ptr %y_addr, ptr %tmp_addr) {
 ; CHECK-NEXT:    %sunkaddr3 = mul i64 %add4.zext, 4
 ; CHECK-NEXT:    --> (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> U: [0,17179869169) S: [0,17179869181)
 ; CHECK-NEXT:    %sunkaddr4 = getelementptr inbounds i8, ptr @tmp_addr, i64 %sunkaddr3
-; CHECK-NEXT:    --> ((4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT:    --> ((4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:    %sunkaddr5 = getelementptr inbounds i8, ptr %sunkaddr4, i64 4096
-; CHECK-NEXT:    --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT:    --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:    %addr4.cast = bitcast ptr %sunkaddr5 to ptr
-; CHECK-NEXT:    --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT:    --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:    %addr4.incr = getelementptr i32, ptr %addr4.cast, i64 1
 ; CHECK-NEXT:    --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:    %add5 = add i32 %mul, 5
@@ -223,11 +223,11 @@ define void @f3(ptr %x_addr, ptr %y_addr, ptr %tmp_addr) {
 ; CHECK-NEXT:    %sunkaddr0 = mul i64 %add5.zext, 4
 ; CHECK-NEXT:    --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw>)<nuw><nsw> U: [4,17179869173) S: [4,17179869185)
 ; CHECK-NEXT:    %sunkaddr1 = getelementptr inbounds i8, ptr @tmp_addr, i64 %sunkaddr0
-; CHECK-NEXT:    --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT:    --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:    %sunkaddr2 = getelementptr inbounds i8, ptr %sunkaddr1, i64 4096
-; CHECK-NEXT:    --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT:    --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:    %addr5.cast = bitcast ptr %sunkaddr2 to ptr
-; CHECK-NEXT:    --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT:    --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:  Determining loop execution counts for: @f3
 ;
   entry:
diff --git a/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll b/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
index e13a8976bf5ac..20ebcd6158e98 100644
--- a/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
+++ b/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
@@ -96,7 +96,7 @@ define void @pointer_iv_nowrap(ptr %startptr, ptr %endptr) local_unnamed_addr {
 ; CHECK-LABEL: 'pointer_iv_nowrap'
 ; CHECK-NEXT:  Classifying expressions for: @pointer_iv_nowrap
 ; CHECK-NEXT:    %init = getelementptr inbounds i8, ptr %startptr, i64 2000
-; CHECK-NEXT:    --> (2000 + %startptr) U: full-set S: full-set
+; CHECK-NEXT:    --> (2000 + %startptr)(u nuw) U: full-set S: full-set
 ; CHECK-NEXT:    %iv = phi ptr [ %init, %entry ], [ %iv.next, %loop ]
 ; CHECK-NEXT:    --> {(2000 + %startptr),+,1}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.next = getelementptr inbounds i8, ptr %iv, i64 1
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
index e784d25385980..72f59682b023a 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
@@ -192,7 +192,7 @@ define void @ptrtoint_of_gep(ptr %in, ptr %out0) {
 ; X64-LABEL: 'ptrtoint_of_gep'
 ; X64-NEXT:  Classifying expressions for: @ptrtoint_of_gep
 ; X64-NEXT:    %in_adj = getelementptr inbounds i8, ptr %in, i64 42
-; X64-NEXT:    --> (42 + %in) U: full-set S: full-set
+; X64-NEXT:    --> (42 + %in)(u nuw) U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint ptr %in_adj to i64
 ; X64-NEXT:    --> (42 + (ptrtoint ptr %in to i64)) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_gep
@@ -200,7 +200,7 @@ define void @ptrtoint_of_gep(ptr %in, ptr %out0) {
 ; X32-LABEL: 'ptrtoint_of_gep'
 ; X32-NEXT:  Classifying expressions for: @ptrtoint_of_gep
 ; X32-NEXT:    %in_adj = getelementptr inbounds i8, ptr %in, i64 42
-; X32-NEXT:    --> (42 + %in) U: full-set S: full-set
+; X32-NEXT:    --> (42 + %in)(u nuw) U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint ptr %in_adj to i64
 ; X32-NEXT:    --> (zext i32 (42 + (ptrtoint ptr %in to i32)) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_gep
diff --git a/llvm/test/Analysis/ScalarEvolution/sdiv.ll b/llvm/test/Analysis/ScalarEvolution/sdiv.ll
index e01f84fb2226e..ce531a967f634 100644
--- a/llvm/test/Analysis/ScalarEvolution/sdiv.ll
+++ b/llvm/test/Analysis/ScalarEvolution/sdiv.ll
@@ -18,7 +18,7 @@ define dso_local void @_Z4loopi(i32 %width) local_unnamed_addr #0 {
 ; CHECK-NEXT:    %idxprom = sext i32 %rem to i64
 ; CHECK-NEXT:    --> ({0,+,1}<nuw><nsw><%for.cond> /u 2) U: [0,2147483648) S: [0,2147483648) Exits: ((zext i32 %width to i64) /u 2) LoopDispositions: { %for.cond: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds [2 x i32], ptr %storage, i64 0, i64 %idxprom
-; CHECK-NEXT:    --> ((4 * ({0,+,1}<nuw><nsw><%for.cond> /u 2))<nuw><nsw> + %storage) U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * ((zext i32 %width to i64) /u 2))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
+; CHECK-NEXT:    --> ((4 * ({0,+,1}<nuw><nsw><%for.cond> /u 2))<nuw><nsw> + %storage)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * ((zext i32 %width to i64) /u 2))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
 ; CHECK-NEXT:    %1 = load i32, ptr %arrayidx, align 4
 ; CHECK-NEXT:    --> %1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %call = call i32 @_Z3adji(i32 %1)
diff --git a/llvm/test/Analysis/ScalarEvolution/srem.ll b/llvm/test/Analysis/ScalarEvolution/srem.ll
index ff898c963d0dc..6ea3921880a2d 100644
--- a/llvm/test/Analysis/ScalarEvolution/srem.ll
+++ b/llvm/test/Analysis/ScalarEvolution/srem.ll
@@ -18,7 +18,7 @@ define dso_local void @_Z4loopi(i32 %width) local_unnamed_addr #0 {
 ; CHECK-NEXT:    %idxprom = sext i32 %rem to i64
 ; CHECK-NEXT:    --> (zext i1 {false,+,true}<%for.cond> to i64) U: [0,2) S: [0,2) Exits: (zext i1 (trunc i32 %width to i1) to i64) LoopDispositions: { %for.cond: Computable }
 ; CHECK-NEXT:    %arrayidx = getelementptr inbounds [2 x i32], ptr %storage, i64 0, i64 %idxprom
-; CHECK-NEXT:    --> ((4 * (zext i1 {false,+,true}<%for.cond> to i64))<nuw><nsw> + %storage) U: [4,-7) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * (zext i1 (trunc i32 %width to i1) to i64))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
+; CHECK-NEXT:    --> ((4 * (zext i1 {false,+,true}<%for.cond> to i64))<nuw><nsw> + %storage)(u nuw) U: [4,-7) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * (zext i1 (trunc i32 %width to i1) to i64))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
 ; CHECK-NEXT:    %1 = load i32, ptr %arrayidx, align 4
 ; CHECK-NEXT:    --> %1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %call = call i32 @_Z3adji(i32 %1)



More information about the llvm-branch-commits mailing list