[llvm] 1ff313f - [SCEV] Always constant fold mul expression operands

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 25 10:54:44 PDT 2020


Author: Nikita Popov
Date: 2020-10-25T18:50:06+01:00
New Revision: 1ff313f0989009f8a080418e93fe510ec66e8999

URL: https://github.com/llvm/llvm-project/commit/1ff313f0989009f8a080418e93fe510ec66e8999
DIFF: https://github.com/llvm/llvm-project/commit/1ff313f0989009f8a080418e93fe510ec66e8999.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/lib/Analysis/ScalarEvolution.cpp
    llvm/test/Analysis/ScalarEvolution/limit-depth.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 92f9949188a1..bce06acdf2e7 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -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

diff  --git a/llvm/test/Analysis/ScalarEvolution/limit-depth.ll b/llvm/test/Analysis/ScalarEvolution/limit-depth.ll
index 8837b305e7ac..84035c3e9a46 100644
--- a/llvm/test/Analysis/ScalarEvolution/limit-depth.ll
+++ b/llvm/test/Analysis/ScalarEvolution/limit-depth.ll
@@ -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


        


More information about the llvm-commits mailing list