[llvm] [SCEV] Add SafeWrap flag to AddRecs (PR #118483)

via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 3 04:48:26 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: JĂșlio De Bastiani (OtherRandomUser)

<details>
<summary>Changes</summary>

Added a flag to signal that an AddRec is expected to wrap. This allows for the vectorization of a few masking operations that would otherwise be discarded based on no wrap predicates, such as:

```
float arr1[8192];
float arr2[8192];
float arr3[8192];
float arr4[8192];
float arr5[8192];
float arr6[8192];
float arr7[8192];
float arr8[8192];
float arr9[8192];

void test() {
  for(int i = 0; i < 8192; i += 1) {
    int ind = i & 0x7f;
    arr1[ind] = i;
    arr2[ind] = i;
    arr3[ind] = i;
    arr4[ind] = i;
    arr5[ind] = i;
    arr6[ind] = i;
    arr7[ind] = i;
    arr8[ind] = i;
    arr9[ind] = i;
  }
}
```

There was also one last test, Transforms/LoopVectorize/X86/multi-exit-cost.ll, that failed. Adding the safe wrap flag in this case prevents any vectorization, but the vectorization done before doesn't make much sense to me, am I missing something?

---

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


10 Files Affected:

- (modified) llvm/include/llvm/Analysis/ScalarEvolution.h (+17-10) 
- (modified) llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h (+4) 
- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+29-20) 
- (modified) llvm/test/Analysis/ScalarEvolution/pr87798.ll (+2-2) 
- (modified) llvm/test/Analysis/ScalarEvolution/shift-recurrences.ll (+1-1) 
- (modified) llvm/test/Analysis/ScalarEvolution/solve-quadratic-i1.ll (+2-2) 
- (modified) llvm/test/Analysis/ScalarEvolution/solve-quadratic.ll (+2-2) 
- (modified) llvm/test/Transforms/IndVarSimplify/shrunk-constant.ll (+1-1) 
- (added) llvm/test/Transforms/LoopVectorize/RISCV/safe-wrap.ll (+112) 
- (modified) llvm/test/Transforms/LoopVectorize/X86/x86_fp80-vector-store.ll (+1-2) 


``````````diff
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index b20c6a13cb6bd7..586b6232647c1e 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -124,11 +124,12 @@ class SCEV : public FoldingSetNode {
   /// at runtime.  A SCEV being defined does not require the existence of any
   /// instruction within the defined scope.
   enum NoWrapFlags {
-    FlagAnyWrap = 0,    // No guarantee.
-    FlagNW = (1 << 0),  // No self-wrap.
-    FlagNUW = (1 << 1), // No unsigned wrap.
-    FlagNSW = (1 << 2), // No signed wrap.
-    NoWrapMask = (1 << 3) - 1
+    FlagAnyWrap = 0,         // No guarantee.
+    FlagSafeWrap = (1 << 0), // Expected to wrap.
+    FlagNW = (1 << 1),       // No self-wrap.
+    FlagNUW = (1 << 2),      // No unsigned wrap.
+    FlagNSW = (1 << 3),      // No signed wrap.
+    NoWrapMask = (1 << 4) - 1
   };
 
   explicit SCEV(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
@@ -562,7 +563,9 @@ class ScalarEvolution {
   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 *getTruncateExpr(const SCEV *Op, Type *Ty,
+                              SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                              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);
@@ -707,13 +710,17 @@ class ScalarEvolution {
 
   /// 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);
+  const SCEV *
+  getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
+                          SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                          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);
+  const SCEV *
+  getTruncateOrSignExtend(const SCEV *V, Type *Ty,
+                          SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                          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
diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
index 6eb1aca1cf76ad..6a894bd9dcb4f4 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -233,6 +233,10 @@ class SCEVNAryExpr : public SCEV {
 
   bool hasNoSelfWrap() const { return getNoWrapFlags(FlagNW) != FlagAnyWrap; }
 
+  bool hasSafeWrap() const {
+    return getNoWrapFlags(FlagSafeWrap) != FlagAnyWrap;
+  }
+
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const SCEV *S) {
     return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr ||
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 882e938e69c0c2..3c6fb4498b9d64 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -317,6 +317,9 @@ void SCEV::print(raw_ostream &OS) const {
     if (AR->hasNoSelfWrap() &&
         !AR->getNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)))
       OS << "nw><";
+    if (AR->hasSafeWrap() &&
+        !AR->getNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW | FlagNW)))
+      OS << "sw><";
     AR->getLoop()->getHeader()->printAsOperand(OS, /*PrintType=*/false);
     OS << ">";
     return;
@@ -1158,6 +1161,7 @@ const SCEV *ScalarEvolution::getPtrToIntExpr(const SCEV *Op, Type *Ty) {
 }
 
 const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
+                                             SCEV::NoWrapFlags Flags,
                                              unsigned Depth) {
   assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) &&
          "This is not a truncating conversion!");
@@ -1180,15 +1184,15 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
 
   // trunc(trunc(x)) --> trunc(x)
   if (const SCEVTruncateExpr *ST = dyn_cast<SCEVTruncateExpr>(Op))
-    return getTruncateExpr(ST->getOperand(), Ty, Depth + 1);
+    return getTruncateExpr(ST->getOperand(), Ty, Flags, Depth + 1);
 
   // trunc(sext(x)) --> sext(x) if widening or trunc(x) if narrowing
   if (const SCEVSignExtendExpr *SS = dyn_cast<SCEVSignExtendExpr>(Op))
-    return getTruncateOrSignExtend(SS->getOperand(), Ty, Depth + 1);
+    return getTruncateOrSignExtend(SS->getOperand(), Ty, Flags, Depth + 1);
 
   // trunc(zext(x)) --> zext(x) if widening or trunc(x) if narrowing
   if (const SCEVZeroExtendExpr *SZ = dyn_cast<SCEVZeroExtendExpr>(Op))
-    return getTruncateOrZeroExtend(SZ->getOperand(), Ty, Depth + 1);
+    return getTruncateOrZeroExtend(SZ->getOperand(), Ty, Flags, Depth + 1);
 
   if (Depth > MaxCastDepth) {
     SCEV *S =
@@ -1208,7 +1212,8 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
     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);
+      const SCEV *S =
+          getTruncateExpr(CommOp->getOperand(i), Ty, Flags, Depth + 1);
       if (!isa<SCEVIntegralCastExpr>(CommOp->getOperand(i)) &&
           isa<SCEVTruncateExpr>(S))
         numTruncs++;
@@ -1232,8 +1237,8 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
   if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Op)) {
     SmallVector<const SCEV *, 4> Operands;
     for (const SCEV *Op : AddRec->operands())
-      Operands.push_back(getTruncateExpr(Op, Ty, Depth + 1));
-    return getAddRecExpr(Operands, AddRec->getLoop(), SCEV::FlagAnyWrap);
+      Operands.push_back(getTruncateExpr(Op, Ty, Flags, Depth + 1));
+    return getAddRecExpr(Operands, AddRec->getLoop(), Flags);
   }
 
   // Return zero if truncating to known zeros.
@@ -1632,7 +1637,7 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
     unsigned NewBits = getTypeSizeInBits(Ty);
     if (CR.truncate(TruncBits).zeroExtend(NewBits).contains(
             CR.zextOrTrunc(NewBits)))
-      return getTruncateOrZeroExtend(X, Ty, Depth);
+      return getTruncateOrZeroExtend(X, Ty, SCEV::FlagAnyWrap, Depth);
   }
 
   // If the input value is a chrec scev, and we can prove that the value
@@ -1669,10 +1674,10 @@ const SCEV *ScalarEvolution::getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
 
         // Check whether the backedge-taken count can be losslessly casted to
         // the addrec's type. The count is always unsigned.
-        const SCEV *CastedMaxBECount =
-            getTruncateOrZeroExtend(MaxBECount, Start->getType(), Depth);
+        const SCEV *CastedMaxBECount = getTruncateOrZeroExtend(
+            MaxBECount, Start->getType(), SCEV::FlagAnyWrap, Depth);
         const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(
-            CastedMaxBECount, MaxBECount->getType(), Depth);
+            CastedMaxBECount, MaxBECount->getType(), SCEV::FlagAnyWrap, Depth);
         if (MaxBECount == RecastedMaxBECount) {
           Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
           // Check whether Start+Step*MaxBECount has no unsigned overflow.
@@ -1973,7 +1978,7 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
     unsigned NewBits = getTypeSizeInBits(Ty);
     if (CR.truncate(TruncBits).signExtend(NewBits).contains(
             CR.sextOrTrunc(NewBits)))
-      return getTruncateOrSignExtend(X, Ty, Depth);
+      return getTruncateOrSignExtend(X, Ty, SCEV::FlagAnyWrap, Depth);
   }
 
   if (auto *SA = dyn_cast<SCEVAddExpr>(Op)) {
@@ -2044,10 +2049,10 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
 
         // Check whether the backedge-taken count can be losslessly casted to
         // the addrec's type. The count is always unsigned.
-        const SCEV *CastedMaxBECount =
-            getTruncateOrZeroExtend(MaxBECount, Start->getType(), Depth);
+        const SCEV *CastedMaxBECount = getTruncateOrZeroExtend(
+            MaxBECount, Start->getType(), SCEV::FlagAnyWrap, Depth);
         const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(
-            CastedMaxBECount, MaxBECount->getType(), Depth);
+            CastedMaxBECount, MaxBECount->getType(), SCEV::FlagAnyWrap, Depth);
         if (MaxBECount == RecastedMaxBECount) {
           Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
           // Check whether Start+Step*MaxBECount has no signed overflow.
@@ -4714,6 +4719,7 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
 }
 
 const SCEV *ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
+                                                     SCEV::NoWrapFlags Flags,
                                                      unsigned Depth) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
@@ -4721,11 +4727,12 @@ const SCEV *ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
   if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
     return V;  // No conversion
   if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty))
-    return getTruncateExpr(V, Ty, Depth);
+    return getTruncateExpr(V, Ty, Flags, Depth);
   return getZeroExtendExpr(V, Ty, Depth);
 }
 
 const SCEV *ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, Type *Ty,
+                                                     SCEV::NoWrapFlags Flags,
                                                      unsigned Depth) {
   Type *SrcTy = V->getType();
   assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
@@ -4733,7 +4740,7 @@ const SCEV *ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, Type *Ty,
   if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
     return V;  // No conversion
   if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty))
-    return getTruncateExpr(V, Ty, Depth);
+    return getTruncateExpr(V, Ty, Flags, Depth);
   return getSignExtendExpr(V, Ty, Depth);
 }
 
@@ -7837,8 +7844,10 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
             ShiftedLHS = getUDivExpr(LHS, MulCount);
           return getMulExpr(
               getZeroExtendExpr(
-                  getTruncateExpr(ShiftedLHS,
-                      IntegerType::get(getContext(), BitWidth - LZ - TZ)),
+                  getTruncateExpr(
+                      ShiftedLHS,
+                      IntegerType::get(getContext(), BitWidth - LZ - TZ),
+                      SCEV::FlagSafeWrap, 0),
                   BO->LHS->getType()),
               MulCount);
         }
@@ -14790,7 +14799,7 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
   const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
     const SCEV *Operand = visit(Expr->getOperand());
     const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Operand);
-    if (AR && AR->getLoop() == L && AR->isAffine()) {
+    if (AR && AR->getLoop() == L && AR->isAffine() && !AR->hasSafeWrap()) {
       // 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);
@@ -14806,7 +14815,7 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
   const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
     const SCEV *Operand = visit(Expr->getOperand());
     const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Operand);
-    if (AR && AR->getLoop() == L && AR->isAffine()) {
+    if (AR && AR->getLoop() == L && AR->isAffine() && !AR->hasSafeWrap()) {
       // 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);
diff --git a/llvm/test/Analysis/ScalarEvolution/pr87798.ll b/llvm/test/Analysis/ScalarEvolution/pr87798.ll
index acd445993e47bc..c019c375cbb184 100644
--- a/llvm/test/Analysis/ScalarEvolution/pr87798.ll
+++ b/llvm/test/Analysis/ScalarEvolution/pr87798.ll
@@ -25,11 +25,11 @@ define i32 @pr87798() {
 ; CHECK-NEXT:    %add4 = add i32 %mul, %phi
 ; CHECK-NEXT:    --> {0,+,0,+,2,+,5,+,3}<%bb1> U: full-set S: full-set Exits: 0 LoopDispositions: { %bb1: Computable }
 ; CHECK-NEXT:    %and = and i32 %phi, 1
-; CHECK-NEXT:    --> (zext i1 {false,+,false,+,false,+,false,+,true}<%bb1> to i32) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %bb1: Computable }
+; CHECK-NEXT:    --> (zext i1 {false,+,false,+,false,+,false,+,true}<sw><%bb1> to i32) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %bb1: Computable }
 ; CHECK-NEXT:    %add5 = add i32 %phi3, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%bb1> U: [1,2) S: [1,2) Exits: 1 LoopDispositions: { %bb1: Computable }
 ; CHECK-NEXT:    %phi9 = phi i32 [ %and, %bb1 ]
-; CHECK-NEXT:    --> (zext i1 {false,+,false,+,false,+,false,+,true}<%bb1> to i32) U: [0,2) S: [0,2) --> 0 U: [0,1) S: [0,1)
+; CHECK-NEXT:    --> (zext i1 {false,+,false,+,false,+,false,+,true}<sw><%bb1> to i32) U: [0,2) S: [0,2) --> 0 U: [0,1) S: [0,1)
 ; CHECK-NEXT:    %zext = zext i32 %phi9 to i64
 ; CHECK-NEXT:    --> poison U: full-set S: full-set
 ; CHECK-NEXT:  Determining loop execution counts for: @pr87798
diff --git a/llvm/test/Analysis/ScalarEvolution/shift-recurrences.ll b/llvm/test/Analysis/ScalarEvolution/shift-recurrences.ll
index 6cd709bfff68f3..ed9220f9e001a2 100644
--- a/llvm/test/Analysis/ScalarEvolution/shift-recurrences.ll
+++ b/llvm/test/Analysis/ScalarEvolution/shift-recurrences.ll
@@ -323,7 +323,7 @@ define void @test_shl6(i1 %c) {
 ; CHECK-NEXT:    %iv.next = add i64 %iv, 1
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,6) S: [1,6) Exits: 5 LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %shiftamt = and i64 %iv, 1
-; CHECK-NEXT:    --> (zext i1 {false,+,true}<%loop> to i64) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    --> (zext i1 {false,+,true}<sw><%loop> to i64) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:    %iv.shl.next = shl i64 %iv.shl, %shiftamt
 ; CHECK-NEXT:    --> %iv.shl.next U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: 16 LoopDispositions: { %loop: Variant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_shl6
diff --git a/llvm/test/Analysis/ScalarEvolution/solve-quadratic-i1.ll b/llvm/test/Analysis/ScalarEvolution/solve-quadratic-i1.ll
index fa4e5fb0ac433e..bcf156bb949411 100644
--- a/llvm/test/Analysis/ScalarEvolution/solve-quadratic-i1.ll
+++ b/llvm/test/Analysis/ScalarEvolution/solve-quadratic-i1.ll
@@ -15,7 +15,7 @@ define void @f0() {
 ; CHECK-NEXT:    %v3 = add nsw i16 %v1, %v0
 ; CHECK-NEXT:    --> {3,+,3,+,1}<%b1> U: full-set S: full-set Exits: 6 LoopDispositions: { %b1: Computable }
 ; CHECK-NEXT:    %v4 = and i16 %v3, 1
-; CHECK-NEXT:    --> (zext i1 {true,+,true,+,true}<%b1> to i16) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %b1: Computable }
+; CHECK-NEXT:    --> (zext i1 {true,+,true,+,true}<sw><%b1> to i16) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %b1: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @f0
 ; CHECK-NEXT:  Loop %b1: backedge-taken count is i6 1
 ; CHECK-NEXT:  Loop %b1: constant max backedge-taken count is i6 1
@@ -54,7 +54,7 @@ define void @f1() #0 {
 ; CHECK-NEXT:    %v3 = add i16 %v0, %v2
 ; CHECK-NEXT:    --> {3,+,4,+,1}<%b1> U: full-set S: full-set Exits: 12 LoopDispositions: { %b1: Computable }
 ; CHECK-NEXT:    %v4 = and i16 %v3, 1
-; CHECK-NEXT:    --> (zext i1 {true,+,false,+,true}<%b1> to i16) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %b1: Computable }
+; CHECK-NEXT:    --> (zext i1 {true,+,false,+,true}<sw><%b1> to i16) U: [0,2) S: [0,2) Exits: 0 LoopDispositions: { %b1: Computable }
 ; CHECK-NEXT:    %v6 = add nuw nsw i32 %v1, 1
 ; CHECK-NEXT:    --> {4,+,1}<nuw><nsw><%b1> U: [4,7) S: [4,7) Exits: 6 LoopDispositions: { %b1: Computable }
 ; CHECK-NEXT:    %v7 = phi i32 [ %v1, %b1 ]
diff --git a/llvm/test/Analysis/ScalarEvolution/solve-quadratic.ll b/llvm/test/Analysis/ScalarEvolution/solve-quadratic.ll
index fd02ef672a969e..bafe0606d8cd9b 100644
--- a/llvm/test/Analysis/ScalarEvolution/solve-quadratic.ll
+++ b/llvm/test/Analysis/ScalarEvolution/solve-quadratic.ll
@@ -41,7 +41,7 @@
 ; {14,+,14,+,14} -> X=0, Y=14, Z=14
 ;
 ; CHECK-LABEL: Printing analysis 'Scalar Evolution Analysis' for function 'test01'
-; CHECK: {{.*}}GetQuadraticEquation{{.*}}: analyzing quadratic addrec: {-2,+,-2,+,-2}<%loop>
+; CHECK: {{.*}}GetQuadraticEquation{{.*}}: analyzing quadratic addrec: {-2,+,-2,+,-2}<sw><%loop>
 ; CHECK: {{.*}}GetQuadraticEquation{{.*}}: addrec coeff bw: 4
 ; CHECK: {{.*}}GetQuadraticEquation{{.*}}: equation -2x^2 + -2x + -4, coeff bw: 5, multiplied by 2
 ; CHECK: {{.*}}SolveQuadraticAddRecExact{{.*}}: solving for unsigned overflow
@@ -117,7 +117,7 @@ exit:
 ; {17,+,-1,+,2} -> X=-3, Y=20, Z=2
 ;
 ; CHECK-LABEL: Printing analysis 'Scalar Evolution Analysis' for function 'test03':
-; CHECK: {{.*}}GetQuadraticEquation{{.*}}: analyzing quadratic addrec: {1,+,-1,+,2}<%loop>
+; CHECK: {{.*}}GetQuadraticEquation{{.*}}: analyzing quadratic addrec: {1,+,-1,+,2}<sw><%loop>
 ; CHECK: {{.*}}GetQuadraticEquation{{.*}}: addrec coeff bw: 4
 ; CHECK: {{.*}}GetQuadraticEquation{{.*}}: equation 2x^2 + -4x + 2, coeff bw: 5, multiplied by 2
 ; CHECK: {{.*}}SolveQuadraticAddRecExact{{.*}}: solving for unsigned overflow
diff --git a/llvm/test/Transforms/IndVarSimplify/shrunk-constant.ll b/llvm/test/Transforms/IndVarSimplify/shrunk-constant.ll
index 8ec8ec2c9e1f2c..5fcff4b98629b2 100644
--- a/llvm/test/Transforms/IndVarSimplify/shrunk-constant.ll
+++ b/llvm/test/Transforms/IndVarSimplify/shrunk-constant.ll
@@ -1,6 +1,6 @@
 ; RUN: opt < %s -passes='print<scalar-evolution>' 2>&1 | FileCheck %s
 
-; CHECK: -->  (1 + (zext i4 {-8,+,-8}<%loop> to i32))<nuw><nsw>
+; CHECK: -->  (1 + (zext i4 {-8,+,-8}<sw><%loop> to i32))<nuw><nsw>
 
 define fastcc void @foo() nounwind {
 entry:
diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/safe-wrap.ll b/llvm/test/Transforms/LoopVectorize/RISCV/safe-wrap.ll
new file mode 100644
index 00000000000000..5f9275ba72cae5
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/safe-wrap.ll
@@ -0,0 +1,112 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=loop-vectorize,simplifycfg,instcombine -force-vector-interleave=1 -force-vector-width=4 -mtriple=riscv64 -mattr=+v < %s | FileCheck %s
+
+target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
+
+ at arr1 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr2 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr3 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr4 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr5 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr6 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr7 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr8 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+ at arr9 = dso_local local_unnamed_addr global [8192 x float] zeroinitializer, align 4
+
+define dso_local noundef float @loop3(i32 noundef signext %zero) local_unnamed_addr #0 {
+; CHECK-LABEL: define dso_local noundef float @loop3(
+; CHECK-SAME: i32 noundef signext [[ZERO:%.*]]) local_unnamed_addr #[[ATTR0:[0-...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list