[SCEV] Always constant fold mul expression operands

Establish parity with the handling of add expressions, by always
constant folding mul expression operands before checking the depth
limit (this is a non-recursive simplification). The code was already
unconditionally constant folding the case where all operands were
constants, but was not folding multiple constant operands together
if there were also non-constant operands.

This requires picking out a different demonstration for depth-based
folding differences in the limit-depth.ll test.
This commit is contained in:
Nikita Popov 2020-10-25 18:46:27 +01:00
parent 22a5cde541
commit 1ff313f098
2 changed files with 25 additions and 14 deletions

View File

@ -2686,17 +2686,6 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
Flags = StrengthenNoWrapFlags(this, scMulExpr, Ops, Flags);
// Limit recursion calls depth, but fold all-constant expressions.
// `Ops` is sorted, so it's enough to check just last one.
if ((Depth > MaxArithDepth || hasHugeExpression(Ops)) &&
!isa<SCEVConstant>(Ops.back()))
return getOrCreateMulExpr(Ops, Flags);
if (SCEV *S = std::get<0>(findExistingSCEVInCache(scMulExpr, Ops))) {
static_cast<SCEVMulExpr *>(S)->setNoWrapFlags(Flags);
return S;
}
// If there are any constants, fold them together.
unsigned Idx = 0;
if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) {
@ -2724,6 +2713,15 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
return Ops[0];
}
// Limit recursion calls depth.
if (Depth > MaxArithDepth || hasHugeExpression(Ops))
return getOrCreateMulExpr(Ops, Flags);
if (SCEV *S = std::get<0>(findExistingSCEVInCache(scMulExpr, Ops))) {
static_cast<SCEVMulExpr *>(S)->setNoWrapFlags(Flags);
return S;
}
if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) {
if (Ops.size() == 2) {
// C1*(C2+V) -> C1*C2 + C1*V

View File

@ -24,10 +24,11 @@ define void @test_add(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
ret void
}
define void @test_mul(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
; CHECK-LABEL: @test_mul
; Constant factors still get folded together.
define void @test_mul_consts(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
; CHECK-LABEL: @test_mul_consts
; CHECK: %s2 = mul i32 %s1, %p3
; CHECK-NEXT: --> (2 * 3 * 4 * 5 * 6 * 7 * %a * %b * %c * %d * %e * %f)
; CHECK-NEXT: --> (5040 * %a * %b * %c * %d * %e * %f)
%tmp0 = mul i32 %a, 2
%tmp1 = mul i32 %b, 3
%tmp2 = mul i32 %c, 4
@ -44,6 +45,18 @@ define void @test_mul(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
ret void
}
; The outer *5 gets distributed because it is at depth=0, but the resulting
; nested multiply doesn't get flattened, because it is at depth=1.
define void @test_mul(i32 %a, i32 %b) {
; CHECK-LABEL: @test_mul
; CHECK: %tmp2 = mul i32 %tmp1, 5
; CHECK-NEXT: --> (20 + (5 * (3 * %a)))
%tmp0 = mul i32 %a, 3
%tmp1 = add i32 %tmp0, 4
%tmp2 = mul i32 %tmp1, 5
ret void
}
define void @test_sext(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
; CHECK-LABEL: @test_sext
; CHECK: %se2 = sext i64 %iv2.inc to i128