Skip to content

Commit 70012fd

Browse files
authored
[SCEV] Fold (C1 * A /u C2) -> A /u (C2 /u C1), if C2 > C1. (#157656)
If C2 >u C1 and C1 >u 1, fold to A /u (C2 /u C1). Depends on #157555. Alive2 Proof: https://alive2.llvm.org/ce/z/BWvQYN PR: #157656
1 parent 0e8f9fc commit 70012fd

File tree

3 files changed

+15
-8
lines changed

3 files changed

+15
-8
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3217,18 +3217,26 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
32173217
}
32183218

32193219
// Try to fold (C1 * D /u C2) -> C1/C2 * D, if C1 and C2 are powers-of-2,
3220-
// D is a multiple of C2, and C1 is a multiple of C2.
3220+
// D is a multiple of C2, and C1 is a multiple of C2. If C2 is a multiple
3221+
// of C1, fold to (D /u (C2 /u C1)).
32213222
const SCEV *D;
32223223
APInt C1V = LHSC->getAPInt();
3223-
// (C1 * D /u C2) == -1 * -C1 * D /u C2 when C1 != INT_MIN.
3224-
if (C1V.isNegative() && !C1V.isMinSignedValue())
3224+
// (C1 * D /u C2) == -1 * -C1 * D /u C2 when C1 != INT_MIN. Don't treat -1
3225+
// as -1 * 1, as it won't enable additional folds.
3226+
if (C1V.isNegative() && !C1V.isMinSignedValue() && !C1V.isAllOnes())
32253227
C1V = C1V.abs();
32263228
const SCEVConstant *C2;
32273229
if (C1V.isPowerOf2() &&
32283230
match(Ops[1], m_scev_UDiv(m_SCEV(D), m_SCEVConstant(C2))) &&
3229-
C2->getAPInt().isPowerOf2() && C1V.uge(C2->getAPInt()) &&
3231+
C2->getAPInt().isPowerOf2() &&
32303232
C1V.logBase2() <= getMinTrailingZeros(D)) {
3231-
const SCEV *NewMul = getMulExpr(getUDivExpr(getConstant(C1V), C2), D);
3233+
const SCEV *NewMul;
3234+
if (C1V.uge(C2->getAPInt())) {
3235+
NewMul = getMulExpr(getUDivExpr(getConstant(C1V), C2), D);
3236+
} else {
3237+
assert(C1V.ugt(1) && "C1 <= 1 should have been folded earlier");
3238+
NewMul = getUDivExpr(D, getUDivExpr(C2, getConstant(C1V)));
3239+
}
32323240
return C1V == LHSC->getAPInt() ? NewMul : getNegativeSCEV(NewMul);
32333241
}
32343242
}

llvm/test/Analysis/ScalarEvolution/mul-udiv-folds.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ define void @udiv4_and_udiv2(i1 %c, ptr %A) {
2121
; CHECK-NEXT: %gep.8 = getelementptr i8, ptr %A, i64 %iv
2222
; CHECK-NEXT: --> {(((zext i32 %start to i64) /u 4) + %A),+,1}<%loop> U: full-set S: full-set Exits: (((zext i32 %start to i64) /u 2) + %A) LoopDispositions: { %loop: Computable }
2323
; CHECK-NEXT: %gep.16 = getelementptr i16, ptr %A, i64 %iv
24-
; CHECK-NEXT: --> {((2 * ((zext i32 %start to i64) /u 4))<nuw><nsw> + %A),+,2}<%loop> U: full-set S: full-set Exits: ((zext i32 %start to i64) + %A) LoopDispositions: { %loop: Computable }
24+
; CHECK-NEXT: --> {(((zext i32 %start to i64) /u 2) + %A),+,2}<%loop> U: full-set S: full-set Exits: ((zext i32 %start to i64) + %A) LoopDispositions: { %loop: Computable }
2525
; CHECK-NEXT: %gep.32 = getelementptr i32, ptr %A, i64 %iv
2626
; CHECK-NEXT: --> {((zext i32 %start to i64) + %A),+,4}<%loop> U: full-set S: full-set Exits: ((2 * (zext i32 %start to i64))<nuw><nsw> + %A) LoopDispositions: { %loop: Computable }
2727
; CHECK-NEXT: %gep.40 = getelementptr <{ i32, i8 }>, ptr %A, i64 %iv

llvm/test/Transforms/LoopStrengthReduce/duplicated-phis.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ define i64 @test_duplicated_phis(i64 noundef %N) {
1818
; CHECK: [[FOR_BODY_PREHEADER_NEW]]:
1919
; CHECK-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[MUL]], -4
2020
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[UNROLL_ITER]], -4
21-
; CHECK-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP4]], 2
22-
; CHECK-NEXT: [[TMP3:%.*]] = shl nuw nsw i64 [[TMP5]], 1
21+
; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP4]], 1
2322
; CHECK-NEXT: [[LSR_IV_NEXT:%.*]] = sub i64 -3, [[TMP3]]
2423
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
2524
; CHECK: [[FOR_BODY]]:

0 commit comments

Comments
 (0)