[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