[PATCH] D43759: [SCEV] Smarter logic in computeConstantDifference

Max Kazantsev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 26 03:05:43 PST 2018


mkazantsev created this revision.
mkazantsev added reviewers: sanjoy, apilipenko, anna, reames.

Current implementation of `computeConstantDifference` is limited to handling a bunch
of particular cases in order to prevent SCEV from making too complex transforms and
keep it fast. This code basically duplicates logic of `getAddExpr` in some limited variant.

This patch proposes an alternative way of restraining SCEV from making complex transforms.
Instead of duplication of logic, we can simply call `getMinusSCEV` with `Depth` parameter close
to its limit value. Currently I set it to `MaxArithDepth - 1` because it is sufficient to handle a
typical case `LHS = {X + C1,+,step}, RHS = {X + C2,+,step}` which is not handled by existing
implementation. I intentionally prefer making it via limiting depth and not via making one more
code duplication to handle this case.

As a result of this change, SCEV is now able to prove non-negativity of the indvar in
decrementing loop with signed latch condition and widen this condition.


https://reviews.llvm.org/D43759

Files:
  lib/Analysis/ScalarEvolution.cpp
  test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll


Index: test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll
===================================================================
--- test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll
+++ test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll
@@ -101,3 +101,34 @@
 return:         ; preds = %bb
   ret void
 }
+
+define void @promote_latch_condition_decrementing_loop_01(i32* %p, i32* %a) {
+
+; CHECK-LABEL: @promote_latch_condition_decrementing_loop_01(
+; CHECK-NOT:     trunc
+
+entry:
+  %len = load i32, i32* %p, align 4, !range !0
+  %len.minus.1 = add nsw i32 %len, -1
+  %zero_check = icmp eq i32 %len, 0
+  br i1 %zero_check, label %loopexit, label %preheader
+
+preheader:
+  br label %loop
+
+loopexit:
+  ret void
+
+loop:
+  %iv = phi i32 [ %iv.next, %loop ], [ %len.minus.1, %preheader ]
+  ; CHECK: %indvars.iv = phi i64
+  %iv.wide = zext i32 %iv to i64
+  %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide
+  store atomic i32 0, i32* %el unordered, align 4
+  %iv.next = add nsw i32 %iv, -1
+  ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1
+  %loopcond = icmp slt i32 %iv, 1
+  br i1 %loopcond, label %loopexit, label %loop
+}
+
+!0 = !{i32 0, i32 2147483647}
Index: lib/Analysis/ScalarEvolution.cpp
===================================================================
--- lib/Analysis/ScalarEvolution.cpp
+++ lib/Analysis/ScalarEvolution.cpp
@@ -9369,10 +9369,7 @@
 
 Optional<APInt> ScalarEvolution::computeConstantDifference(const SCEV *More,
                                                            const SCEV *Less) {
-  // We avoid subtracting expressions here because this function is usually
-  // fairly deep in the call stack (i.e. is called many times).
-
-  if (isa<SCEVAddRecExpr>(Less) && isa<SCEVAddRecExpr>(More)) {
+  while (isa<SCEVAddRecExpr>(Less) && isa<SCEVAddRecExpr>(More)) {
     const auto *LAR = cast<SCEVAddRecExpr>(Less);
     const auto *MAR = cast<SCEVAddRecExpr>(More);
 
@@ -9393,24 +9390,11 @@
     // fall through
   }
 
-  if (isa<SCEVConstant>(Less) && isa<SCEVConstant>(More)) {
-    const auto &M = cast<SCEVConstant>(More)->getAPInt();
-    const auto &L = cast<SCEVConstant>(Less)->getAPInt();
-    return M - L;
-  }
-
-  const SCEV *L, *R;
-  SCEV::NoWrapFlags Flags;
-  if (splitBinaryAdd(Less, L, R, Flags))
-    if (const auto *LC = dyn_cast<SCEVConstant>(L))
-      if (R == More)
-        return -(LC->getAPInt());
-
-  if (splitBinaryAdd(More, L, R, Flags))
-    if (const auto *LC = dyn_cast<SCEVConstant>(L))
-      if (R == Less)
-        return LC->getAPInt();
-
+  // We limit recursion depth here because this function is usually
+  // fairly deep in the call stack (i.e. is called many times).
+  if (auto *Difference = dyn_cast<SCEVConstant>(
+          getMinusSCEV(More, Less, SCEV::FlagAnyWrap, MaxArithDepth - 1)))
+    return Difference->getAPInt();
   return None;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D43759.135879.patch
Type: text/x-patch
Size: 2894 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180226/4c56e9b0/attachment.bin>


More information about the llvm-commits mailing list