[llvm] [SCEV] Add option to request use-specific SCEV for a GEP expr, (PR #190677)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 6 13:42:45 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

<details>
<summary>Changes</summary>



---

Patch is 55.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/190677.diff


9 Files Affected:

- (modified) llvm/include/llvm/Analysis/ScalarEvolution.h (+27-18) 
- (modified) llvm/lib/Analysis/IVDescriptors.cpp (+1-1) 
- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+68-35) 
- (modified) llvm/lib/Passes/PassRegistry.def (+10-1) 
- (modified) llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp (+1-1) 
- (modified) llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp (+1-1) 
- (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp (+1-1) 
- (added) llvm/test/Analysis/ScalarEvolution/use-specific-flags-cache.ll (+34) 
- (added) llvm/test/Analysis/ScalarEvolution/use-specific-flags-gep.ll (+594) 


``````````diff
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 5c01da0855f66..fffe7e47c903a 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -145,6 +145,10 @@ struct SCEVUseT : private PointerIntPair<SCEVPtrT, 2> {
   SCEVNoWrapFlags
   getNoWrapFlags(SCEVNoWrapFlags Mask = SCEVNoWrapFlags::NoWrapMask) const;
 
+  bool hasNoUnsignedWrap() const {
+    return any(getNoWrapFlags() & SCEVNoWrapFlags::FlagNUW);
+  }
+
   /// Return only the use-specific no-wrap flags (NUW/NSW) without the
   /// underlying SCEV's flags.
   SCEVNoWrapFlags getUseNoWrapFlags() const {
@@ -730,11 +734,12 @@ class ScalarEvolution {
   LLVM_ABI bool containsErasedValue(const SCEV *S) const;
 
   /// Return a SCEV expression for the full generality of the specified
-  /// expression.
-  LLVM_ABI const SCEV *getSCEV(Value *V);
+  /// expression. If \p UseCtx is true, returns a SCEV with use-specific flags
+  /// valid only for existing uses of \p V.
+  LLVM_ABI SCEVUse getSCEV(Value *V, bool UseCtx = false);
 
   /// Return an existing SCEV for V if there is one, otherwise return nullptr.
-  LLVM_ABI const SCEV *getExistingSCEV(Value *V);
+  LLVM_ABI SCEVUse getExistingSCEV(Value *V);
 
   LLVM_ABI const SCEV *getConstant(ConstantInt *V);
   LLVM_ABI const SCEV *getConstant(const APInt &Val);
@@ -816,12 +821,12 @@ 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.
-  LLVM_ABI const SCEV *getGEPExpr(GEPOperator *GEP,
-                                  ArrayRef<SCEVUse> IndexExprs);
-  LLVM_ABI const SCEV *getGEPExpr(SCEVUse BaseExpr,
-                                  ArrayRef<SCEVUse> IndexExprs,
-                                  Type *SrcElementTy,
-                                  GEPNoWrapFlags NW = GEPNoWrapFlags::none());
+  LLVM_ABI SCEVUse getGEPExpr(GEPOperator *GEP, ArrayRef<SCEVUse> IndexExprs,
+                              bool UseCtx = false);
+  LLVM_ABI SCEVUse
+  getGEPExpr(SCEVUse BaseExpr, ArrayRef<SCEVUse> IndexExprs, Type *SrcElementTy,
+             GEPNoWrapFlags NW = GEPNoWrapFlags::none(),
+             GEPNoWrapFlags UseSpecificNW = GEPNoWrapFlags::none());
   LLVM_ABI const SCEV *getAbsExpr(const SCEV *Op, bool IsNSW);
   LLVM_ABI const SCEV *getMinMaxExpr(SCEVTypes Kind,
                                      SmallVectorImpl<SCEVUse> &Operands);
@@ -1483,7 +1488,7 @@ class ScalarEvolution {
   /// Return the size of an element read or written by Inst.
   LLVM_ABI const SCEV *getElementSize(Instruction *Inst);
 
-  LLVM_ABI void print(raw_ostream &OS) const;
+  LLVM_ABI void print(raw_ostream &OS, bool UseCtx = false) const;
   LLVM_ABI void verify() const;
   LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA,
                            FunctionAnalysisManager::Invalidator &Inv);
@@ -1677,7 +1682,7 @@ 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;
@@ -1987,12 +1992,14 @@ class ScalarEvolution {
   ConstantRange getRangeForUnknownRecurrence(const SCEVUnknown *U);
 
   /// We know that there is no SCEV for the specified value.  Analyze the
-  /// expression recursively.
-  const SCEV *createSCEV(Value *V);
+  /// expression recursively. If \p UseCtx is true, create a SCEV with
+  /// use-specific flags valid only for existing uses of \p 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.
-  const SCEV *createSCEVIter(Value *V);
+  /// for \p V iteratively. If \p UseCtx is true, create a SCEV with
+  /// use-specific flags valid only for existing uses of \p 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.
@@ -2036,7 +2043,7 @@ class ScalarEvolution {
                                        Value *FalseVal);
 
   /// Provide the special handling we need to analyze GEP SCEVs.
-  const SCEV *createNodeForGEP(GEPOperator *GEP);
+  SCEVUse createNodeForGEP(GEPOperator *GEP, bool UseCtx = false);
 
   /// Implementation code for getSCEVAtScope; called at most once for each
   /// SCEV+Loop pair.
@@ -2349,7 +2356,7 @@ class ScalarEvolution {
   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.
@@ -2557,9 +2564,11 @@ class ScalarEvolutionVerifierPass
 class ScalarEvolutionPrinterPass
     : public PassInfoMixin<ScalarEvolutionPrinterPass> {
   raw_ostream &OS;
+  bool UseCtx;
 
 public:
-  explicit ScalarEvolutionPrinterPass(raw_ostream &OS) : OS(OS) {}
+  explicit ScalarEvolutionPrinterPass(raw_ostream &OS, bool UseCtx = false)
+      : OS(OS), UseCtx(UseCtx) {}
 
   LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
 
diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp
index 185943e0a9d2e..27bebfe9489ea 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -1606,7 +1606,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 SCEV *Step;
 
   // FIXME: We are currently matching the specific loop TheLoop; if it doesn't
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 2862acfedb91d..62d01ed758d68 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -3887,9 +3887,9 @@ const SCEV *ScalarEvolution::getAddRecExpr(SmallVectorImpl<SCEVUse> &Operands,
   return getOrCreateAddRecExpr(Operands, L, Flags);
 }
 
-const SCEV *ScalarEvolution::getGEPExpr(GEPOperator *GEP,
-                                        ArrayRef<SCEVUse> IndexExprs) {
-  const SCEV *BaseExpr = getSCEV(GEP->getPointerOperand());
+SCEVUse ScalarEvolution::getGEPExpr(GEPOperator *GEP,
+                                    ArrayRef<SCEVUse> IndexExprs, bool UseCtx) {
+  SCEVUse BaseExpr = getSCEV(GEP->getPointerOperand(), UseCtx);
   // getSCEV(Base)->getType() has the same address space as Base->getType()
   // because SCEV::getType() preserves the address space.
   GEPNoWrapFlags NW = GEP->getNoWrapFlags();
@@ -3904,12 +3904,15 @@ const SCEV *ScalarEvolution::getGEPExpr(GEPOperator *GEP,
       NW = GEPNoWrapFlags::none();
   }
 
-  return getGEPExpr(BaseExpr, IndexExprs, GEP->getSourceElementType(), NW);
+  return getGEPExpr(BaseExpr, IndexExprs, GEP->getSourceElementType(), NW,
+                    /*UseSpecificNW=*/
+                    UseCtx ? GEP->getNoWrapFlags() : GEPNoWrapFlags::none());
 }
 
-const SCEV *ScalarEvolution::getGEPExpr(SCEVUse BaseExpr,
-                                        ArrayRef<SCEVUse> IndexExprs,
-                                        Type *SrcElementTy, GEPNoWrapFlags NW) {
+SCEVUse ScalarEvolution::getGEPExpr(SCEVUse BaseExpr,
+                                    ArrayRef<SCEVUse> IndexExprs,
+                                    Type *SrcElementTy, GEPNoWrapFlags NW,
+                                    GEPNoWrapFlags UseSpecificNW) {
   SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap;
   if (NW.hasNoUnsignedSignedWrap())
     OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNSW);
@@ -3967,6 +3970,30 @@ const SCEV *ScalarEvolution::getGEPExpr(SCEVUse BaseExpr,
   auto *GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
   assert(BaseExpr->getType() == GEPExpr->getType() &&
          "GEP should not change type mid-flight.");
+  if (!NUW) {
+    if (UseSpecificNW.hasNoUnsignedWrap() ||
+        (UseSpecificNW.isInBounds() && isKnownNonNegative(Offset))) {
+      // Check if it is safe to annotate the expression with use-specific NUW.
+      // Don't apply it if Base or Offset contain potentially wrapping
+      // sub-expressions that could be flattened into a larger Add expression.
+      auto IsSafeForUseNUW = [](SCEVUse S) {
+        if (any(S.getUseNoWrapFlags() & SCEV::FlagNUW))
+          return true;
+        // Add and AddRec expressions could be flattened into a wider
+        // add, so they need NUW to be safe.
+        if (isa<SCEVAddExpr, SCEVAddRecExpr>(S))
+          return S.hasNoUnsignedWrap();
+        // Conservatively allow a small set of expression forms that are
+        // known safe: they won't be flattened into a wider add.
+        const SCEVUnknown *U;
+        return match(
+            S, m_CombineOr(m_scev_ZExt(m_SCEVUnknown(U)), m_SCEVUnknown(U)));
+        match(S, m_SCEVConstant());
+      };
+      if (IsSafeForUseNUW(BaseExpr) && IsSafeForUseNUW(Offset))
+        return SCEVUse(&*GEPExpr, SCEV::FlagNUW);
+    }
+  }
   return GEPExpr;
 }
 
@@ -4705,7 +4732,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.
@@ -4718,20 +4745,26 @@ 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, bool UseCtx) {
   assert(isSCEVable(V->getType()) && "Value is not SCEVable!");
 
-  if (const SCEV *S = getExistingSCEV(V))
+  if (SCEVUse S = getExistingSCEV(V)) {
+    // When not using context-specific flags, return the canonical SCEV
+    // without any use-specific flags.
+    if (!UseCtx)
+      return S.getPointer();
     return S;
-  return createSCEVIter(V);
+  }
+  // TODO: Should we always create use-specific SCEVs?
+  return createSCEVIter(V, UseCtx);
 }
 
-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;
@@ -6412,9 +6445,9 @@ createNodeForSelectViaUMinSeq(ScalarEvolution *SE, Value *Cond, Value *TrueVal,
   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 SCEV *SECond = SE->getSCEV(Cond);
+  const SCEV *SETrue = SE->getSCEV(TrueVal);
+  const SCEV *SEFalse = SE->getSCEV(FalseVal);
   return createNodeForSelectViaUMinSeq(SE, SECond, SETrue, SEFalse);
 }
 
@@ -6458,14 +6491,14 @@ 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, 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(const SCEV *S,
@@ -7689,7 +7722,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, bool UseCtx) {
   // Worklist item with a Value and a bool indicating whether all operands have
   // been visited already.
   using PointerTy = PointerIntPair<Value *, 1, bool>;
@@ -7705,10 +7738,10 @@ const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
       continue;
 
     SmallVector<Value *> Ops;
-    const SCEV *CreatedSCEV = nullptr;
+    SCEVUse CreatedSCEV;
     // 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,
@@ -7964,7 +7997,7 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
   return nullptr;
 }
 
-const SCEV *ScalarEvolution::createSCEV(Value *V) {
+SCEVUse ScalarEvolution::createSCEV(Value *V, bool UseCtx) {
   if (!isSCEVable(V->getType()))
     return getUnknown(V);
 
@@ -7999,7 +8032,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
       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;
           }
@@ -8045,7 +8078,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
       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;
           }
@@ -8381,7 +8414,7 @@ const SCEV *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));
@@ -9342,7 +9375,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromCondImpl(
     NWR.getEquivalentICmp(Pred, NewRHSC, Offset);
     if (!ExitIfTrue)
       Pred = ICmpInst::getInversePredicate(Pred);
-    auto *LHS = getSCEV(WO->getLHS());
+    const SCEV *LHS = getSCEV(WO->getLHS());
     if (Offset != 0)
       LHS = getAddExpr(LHS, getConstant(Offset));
     auto EL = computeExitLimitFromICmp(L, Pred, LHS, getConstant(NewRHSC),
@@ -12783,7 +12816,7 @@ bool ScalarEvolution::isImpliedCondOperandsViaShift(CmpPredicate Pred,
   using namespace PatternMatch;
   if (match(SUFoundRHS->getValue(),
             m_LShr(m_Value(Shiftee), m_Value(ShiftValue)))) {
-    auto *ShifteeS = getSCEV(Shiftee);
+    const SCEV *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
@@ -13000,7 +13033,7 @@ bool ScalarEvolution::isImpliedViaOperations(CmpPredicate Pred, const SCEV *LHS,
 
       // 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;
 
@@ -14258,7 +14291,7 @@ static raw_ostream &operator<<(raw_ostream &OS,
 }
 } // namespace llvm
 
-void ScalarEvolution::print(raw_ostream &OS) const {
+void ScalarEvolution::print(raw_ostream &OS, bool UseCtx) const {
   // ScalarEvolution's implementation of the print method is to print
   // out SCEV values of all instructions that are interesting. Doing
   // this potentially causes it to create new SCEV objects though,
@@ -14275,8 +14308,8 @@ void ScalarEvolution::print(raw_ostream &OS) const {
       if (isSCEVable(I.getType()) && !isa<CmpInst>(I)) {
         OS << I << '\n';
         OS << "  -->  ";
-        const SCEV *SV = SE.getSCEV(&I);
-        SV->print(OS);
+        SCEVUse SV = SE.getSCEV(&I, UseCtx);
+        SV.print(OS);
         if (!isa<SCEVCouldNotCompute>(SV)) {
           OS << " U: ";
           SE.getUnsignedRange(SV).print(OS);
@@ -15010,7 +15043,7 @@ ScalarEvolutionPrinterPass::run(Function &F, FunctionAnalysisManager &AM) {
   // update_analyze_test_checks.py working.
   OS << "Printing analysis 'Scalar Evolution Analysis' for function '"
      << F.getName() << "':\n";
-  AM.getResult<ScalarEvolutionAnalysis>(F).print(OS);
+  AM.getResult<ScalarEvolutionAnalysis>(F).print(OS, UseCtx);
   return PreservedAnalyses::all();
 }
 
@@ -15621,7 +15654,7 @@ void PredicatedScalarEvolution::print(raw_ostream &OS, unsigned Depth) const {
       if (!SE.isSCEVable(I.getType()))
         continue;
 
-      auto *Expr = SE.getSCEV(&I);
+      const SCEV *Expr = SE.getSCEV(&I);
       auto II = RewriteMap.find(Expr);
 
       if (II == RewriteMap.end())
@@ -16104,8 +16137,8 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
       if (auto *Cmp = dyn_cast<ICmpInst>(Cond)) {
         auto Predicate =
             EnterIfTrue ? Cmp->getPredicate() : Cmp->getInversePredicate();
-        const auto *LHS = SE.getSCEV(Cmp->getOperand(0));
-        const auto *RHS = SE.getSCEV(Cmp->getOperand(1));
+        const SCEV *LHS = SE.getSCEV(Cmp->getOperand(0));
+        const SCEV *RHS = SE.getSCEV(Cmp->getOperand(1));
         // If LHS is a constant, apply information to the other expression.
         // TODO: If LHS is not a constant, check if using CompareSCEVComplexity
         // can improve results.
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index c92d93d7ae396..9479d9f1fd38c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -522,7 +522,6 @@ FUNCTION_PASS("print<memoryssa-walker>", MemorySSAWalkerPrinterPass(errs()))
 FUNCTION_PASS("print<phi-values>", PhiValuesPrinterPass(errs()))
 FUNCTION_PASS("print<postdomtree>", PostDominatorTreePrinterPass(errs()))
 FUNCTION_PASS("print<regions>", RegionInfoPrinterPass(errs()))
-FUNCTION_PASS("print<scalar-evolution>", ScalarEvolutionPrinterPass(errs()))
 FUNCTION_PASS("print<scev-division>", SCEVDivisionPrinterPass(errs()))
 FUNCTION_PASS("print<stack-safety-local>", StackSafetyPrinterPass(errs()))
 FUNCTION_PASS("print<uniformity>", UniformityInfoPrinterPass(errs()))
@@ -671,6 +670,16 @@ FUNCTION_PASS_WITH_PARAMS(
       return MemorySSAPrinterPass(errs(), !NoEnsureOptimizedUses);
     },
     parseMemorySSAPrinterPassOptions, "no-ensure-optimized-uses")
+FUNCTION_PASS_WITH_PARAMS(
+    "print<scalar-evolution>", "ScalarEvolutionPrinterPass",
+    [](bool UseCtx) {
+      return ScalarEvolutionPrinterPass(errs(), UseCtx);
+    },
+    [](StringRef Params) {
+      return PassBuilder::parseSinglePassOption(
+          Params, "use-context", "ScalarEvolutionPrinterPass");
+    },
+    "use-context")
 FUNCTION_PASS_WITH_PARAMS(
     "print<stack-lifetime>", "StackLifetimePrinterPass",
     [](StackLifetime::LivenessType Type) {
diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index ed43fb4b63f87..cd8f4436cb447 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -492,7 +492,7 @@ class StraightLineStrengthReduce {
   } CandidateDict;
 
   const SCEV *getAndRecordSCEV(Value *V) {
-    auto *S = SE->getSCEV(V);
+    const SCEV *S = SE->getSCEV(V);
     if (isa<Instruction>(V) && !(isa<SCEVCouldNotCompute>(S) ||
                                  isa<SCEVUnknown>(S) || isa<SCEVConstant>(S)))
       SCEVToInsts[S].insert(cast<Instruction>(V));
diff --git a/llvm/...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/190677


More information about the llvm-commits mailing list