Skip to content

Commit 8d201e5

Browse files
committed
[SCEV] Use getConstantMultiple in to get divisibility info from guards. (llvm#162617)
Simplify and generalize the code to get a common constant multiple for expressions when collecting guards, replacing the manual implementation. Split off from llvm#160012. PR: llvm#162617 (cherry picked from commit 6d905e4)
1 parent 037fffd commit 8d201e5

File tree

3 files changed

+43
-59
lines changed

3 files changed

+43
-59
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15683,51 +15683,11 @@ void ScalarEvolution::LoopGuards::collectFromBlock(
1568315683
return RewriteMap.lookup_or(S, S);
1568415684
};
1568515685

15686-
// Check for the SCEV expression (A /u B) * B while B is a constant, inside
15687-
// \p Expr. The check is done recuresively on \p Expr, which is assumed to
15688-
// be a composition of Min/Max SCEVs. Return whether the SCEV expression (A
15689-
// /u B) * B was found, and return the divisor B in \p DividesBy. For
15690-
// example, if Expr = umin (umax ((A /u 8) * 8, 16), 64), return true since
15691-
// (A /u 8) * 8 matched the pattern, and return the constant SCEV 8 in \p
15692-
// DividesBy.
15693-
std::function<bool(const SCEV *, const SCEV *&)> HasDivisibiltyInfo =
15694-
[&](const SCEV *Expr, const SCEV *&DividesBy) {
15695-
if (auto *Mul = dyn_cast<SCEVMulExpr>(Expr)) {
15696-
if (Mul->getNumOperands() != 2)
15697-
return false;
15698-
auto *MulLHS = Mul->getOperand(0);
15699-
auto *MulRHS = Mul->getOperand(1);
15700-
if (isa<SCEVConstant>(MulLHS))
15701-
std::swap(MulLHS, MulRHS);
15702-
if (auto *Div = dyn_cast<SCEVUDivExpr>(MulLHS))
15703-
if (Div->getOperand(1) == MulRHS) {
15704-
DividesBy = MulRHS;
15705-
return true;
15706-
}
15707-
}
15708-
if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr))
15709-
return HasDivisibiltyInfo(MinMax->getOperand(0), DividesBy) ||
15710-
HasDivisibiltyInfo(MinMax->getOperand(1), DividesBy);
15711-
return false;
15712-
};
15713-
15714-
// Return true if Expr known to divide by \p DividesBy.
15715-
std::function<bool(const SCEV *, const SCEV *&)> IsKnownToDivideBy =
15716-
[&](const SCEV *Expr, const SCEV *DividesBy) {
15717-
if (SE.getURemExpr(Expr, DividesBy)->isZero())
15718-
return true;
15719-
if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr))
15720-
return IsKnownToDivideBy(MinMax->getOperand(0), DividesBy) &&
15721-
IsKnownToDivideBy(MinMax->getOperand(1), DividesBy);
15722-
return false;
15723-
};
15724-
1572515686
const SCEV *RewrittenLHS = GetMaybeRewritten(LHS);
1572615687
const SCEV *DividesBy = nullptr;
15727-
if (HasDivisibiltyInfo(RewrittenLHS, DividesBy))
15728-
// Check that the whole expression is divided by DividesBy
15729-
DividesBy =
15730-
IsKnownToDivideBy(RewrittenLHS, DividesBy) ? DividesBy : nullptr;
15688+
const APInt &Multiple = SE.getConstantMultiple(RewrittenLHS);
15689+
if (!Multiple.isOne())
15690+
DividesBy = SE.getConstant(Multiple);
1573115691

1573215692
// Collect rewrites for LHS and its transitive operands based on the
1573315693
// condition.

llvm/test/Analysis/ScalarEvolution/trip-count-minmax.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ define void @umin(i32 noundef %a, i32 noundef %b) {
6161
; CHECK-NEXT: Loop %for.body: backedge-taken count is (-1 + ((2 * %a) umin (4 * %b)))
6262
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 2147483646
6363
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (-1 + ((2 * %a) umin (4 * %b)))
64-
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
64+
; CHECK-NEXT: Loop %for.body: Trip multiple is 2
6565
;
6666
; void umin(unsigned a, unsigned b) {
6767
; a *= 2;
@@ -157,7 +157,7 @@ define void @smin(i32 noundef %a, i32 noundef %b) {
157157
; CHECK-NEXT: Loop %for.body: backedge-taken count is (-1 + ((2 * %a)<nsw> smin (4 * %b)<nsw>))
158158
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 2147483646
159159
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (-1 + ((2 * %a)<nsw> smin (4 * %b)<nsw>))
160-
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
160+
; CHECK-NEXT: Loop %for.body: Trip multiple is 2
161161
;
162162
; void smin(signed a, signed b) {
163163
; a *= 2;

llvm/test/Transforms/LoopVectorize/single_early_exit.ll

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -594,19 +594,50 @@ define i64 @loop_guards_needed_to_prove_deref_multiple(i32 %x, i1 %c, ptr derefe
594594
; CHECK-NEXT: call void @llvm.assume(i1 [[PRE_2]])
595595
; CHECK-NEXT: [[N:%.*]] = add i32 [[SEL]], -1
596596
; CHECK-NEXT: [[N_EXT:%.*]] = zext i32 [[N]] to i64
597+
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[SEL]], -2
598+
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64
599+
; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 2
600+
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 4
601+
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
602+
; CHECK: vector.ph:
603+
; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP2]], 4
604+
; CHECK-NEXT: [[IV_NEXT:%.*]] = sub i64 [[TMP2]], [[N_MOD_VF]]
597605
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
606+
; CHECK: vector.body:
607+
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[LOOP_HEADER]] ]
608+
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[INDEX]]
609+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP3]], align 1
610+
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
611+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
612+
; CHECK-NEXT: [[TMP5:%.*]] = freeze <4 x i1> [[TMP4]]
613+
; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP5]])
614+
; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[IV_NEXT]]
615+
; CHECK-NEXT: [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
616+
; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_SPLIT:%.*]], label [[LOOP_HEADER]], !llvm.loop [[LOOP11:![0-9]+]]
617+
; CHECK: middle.split:
618+
; CHECK-NEXT: br i1 [[TMP6]], label [[VECTOR_EARLY_EXIT:%.*]], label [[LOOP_LATCH:%.*]]
619+
; CHECK: middle.block:
620+
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[IV_NEXT]]
621+
; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT_LOOPEXIT:%.*]], label [[SCALAR_PH]]
622+
; CHECK: vector.early.exit:
623+
; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP4]], i1 true)
624+
; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[INDEX]], [[TMP9]]
625+
; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]
626+
; CHECK: scalar.ph:
627+
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT]], [[LOOP_LATCH]] ], [ 0, [[PH]] ]
628+
; CHECK-NEXT: br label [[LOOP_HEADER1:%.*]]
598629
; CHECK: loop.header:
599-
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[PH]] ]
600-
; CHECK-NEXT: [[GEP_SRC_I:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[IV]]
630+
; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[IV_NEXT1:%.*]], [[LOOP_LATCH1:%.*]] ], [ [[IV]], [[SCALAR_PH]] ]
631+
; CHECK-NEXT: [[GEP_SRC_I:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[IV1]]
601632
; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[GEP_SRC_I]], align 1
602633
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[L]], 0
603-
; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_LATCH]]
634+
; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_LOOPEXIT]], label [[LOOP_LATCH1]]
604635
; CHECK: loop.latch:
605-
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
606-
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], [[N_EXT]]
607-
; CHECK-NEXT: br i1 [[EC]], label [[EXIT_LOOPEXIT]], label [[LOOP_HEADER]]
636+
; CHECK-NEXT: [[IV_NEXT1]] = add i64 [[IV1]], 1
637+
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV1]], [[N_EXT]]
638+
; CHECK-NEXT: br i1 [[EC]], label [[EXIT_LOOPEXIT]], label [[LOOP_HEADER1]], !llvm.loop [[LOOP12:![0-9]+]]
608639
; CHECK: exit.loopexit:
609-
; CHECK-NEXT: [[RES_PH:%.*]] = phi i64 [ [[IV]], [[LOOP_HEADER]] ], [ 0, [[LOOP_LATCH]] ]
640+
; CHECK-NEXT: [[RES_PH:%.*]] = phi i64 [ [[IV1]], [[LOOP_HEADER1]] ], [ 0, [[LOOP_LATCH1]] ], [ 0, [[LOOP_LATCH]] ], [ [[TMP10]], [[VECTOR_EARLY_EXIT]] ]
610641
; CHECK-NEXT: br label [[EXIT]]
611642
; CHECK: exit:
612643
; CHECK-NEXT: [[RES:%.*]] = phi i64 [ -1, [[ENTRY:%.*]] ], [ -2, [[THEN]] ], [ [[RES_PH]], [[EXIT_LOOPEXIT]] ]
@@ -653,11 +684,4 @@ exit:
653684
; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]}
654685
; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]}
655686
; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]}
656-
; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META1]]}
657-
; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]]}
658-
; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META1]]}
659-
; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META1]], [[META2]]}
660-
; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[META2]], [[META1]]}
661-
; CHECK: [[LOOP12]] = distinct !{[[LOOP12]], [[META1]], [[META2]]}
662-
; CHECK: [[LOOP13]] = distinct !{[[LOOP13]], [[META2]], [[META1]]}
663687
;.

0 commit comments

Comments
 (0)