[llvm-commits] [llvm] r157701 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h lib/Analysis/ScalarEvolution.cpp test/Transforms/IndVarSimplify/ult-sub-to-eq.ll

Benjamin Kramer benny.kra at googlemail.com
Wed May 30 11:32:23 PDT 2012


Author: d0k
Date: Wed May 30 13:32:23 2012
New Revision: 157701

URL: http://llvm.org/viewvc/llvm-project?rev=157701&view=rev
Log:
Teach SCEV's icmp simplification logic that a-b == 0 is equivalent to a == b.

This also required making recursive simplifications until
nothing changes or a hard limit (currently 3) is hit.

With the simplification in place indvars can canonicalize
loops of the form
for (unsigned i = 0; i < a-b; ++i)
into
for (unsigned i = 0; i != a-b; ++i)
which used to fail because SCEV created a weird umax expr
for the backedge taken count.

Added:
    llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll
Modified:
    llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp

Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=157701&r1=157700&r2=157701&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Wed May 30 13:32:23 2012
@@ -837,7 +837,8 @@
     ///
     bool SimplifyICmpOperands(ICmpInst::Predicate &Pred,
                               const SCEV *&LHS,
-                              const SCEV *&RHS);
+                              const SCEV *&RHS,
+                              unsigned Depth = 0);
 
     /// getLoopDisposition - Return the "disposition" of the given SCEV with
     /// respect to the given loop.

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=157701&r1=157700&r2=157701&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Wed May 30 13:32:23 2012
@@ -5605,9 +5605,14 @@
 /// predicate Pred. Return true iff any changes were made.
 ///
 bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred,
-                                           const SCEV *&LHS, const SCEV *&RHS) {
+                                           const SCEV *&LHS, const SCEV *&RHS,
+                                           unsigned Depth) {
   bool Changed = false;
 
+  // If we hit the max recursion limit bail out.
+  if (Depth >= 3)
+    return false;
+
   // Canonicalize a constant to the right side.
   if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
     // Check for both operands constant.
@@ -5645,6 +5650,15 @@
     default: llvm_unreachable("Unexpected ICmpInst::Predicate value!");
     case ICmpInst::ICMP_EQ:
     case ICmpInst::ICMP_NE:
+      // Fold ((-1) * %a) + %b == 0 (equivalent to %b-%a == 0) into %a == %b.
+      if (!RA)
+        if (const SCEVAddExpr *AE = dyn_cast<SCEVAddExpr>(LHS))
+          if (const SCEVMulExpr *ME = dyn_cast<SCEVMulExpr>(AE->getOperand(0)))
+            if (ME->getOperand(0)->isAllOnesValue()) {
+              RHS = AE->getOperand(1);
+              LHS = ME->getOperand(1);
+              Changed = true;
+            }
       break;
     case ICmpInst::ICMP_UGE:
       if ((RA - 1).isMinValue()) {
@@ -5846,6 +5860,11 @@
 
   // TODO: More simplifications are possible here.
 
+  // Recursively simplify until we either hit a recursion limit or nothing
+  // changes.
+  if (Changed)
+    return SimplifyICmpOperands(Pred, LHS, RHS, Depth+1);
+
   return Changed;
 
 trivially_true:

Added: llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll?rev=157701&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll Wed May 30 13:32:23 2012
@@ -0,0 +1,42 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+define void @test1(float* nocapture %autoc, float* nocapture %data, float %d, i32 %data_len, i32 %sample) nounwind {
+entry:
+  %sub = sub i32 %data_len, %sample
+  %cmp4 = icmp eq i32 %data_len, %sample
+  br i1 %cmp4, label %for.end, label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
+  %0 = trunc i64 %indvars.iv to i32
+  %add = add i32 %0, %sample
+  %idxprom = zext i32 %add to i64
+  %arrayidx = getelementptr inbounds float* %data, i64 %idxprom
+  %1 = load float* %arrayidx, align 4
+  %mul = fmul float %1, %d
+  %arrayidx2 = getelementptr inbounds float* %autoc, i64 %indvars.iv
+  %2 = load float* %arrayidx2, align 4
+  %add3 = fadd float %2, %mul
+  store float %add3, float* %arrayidx2, align 4
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %3 = trunc i64 %indvars.iv.next to i32
+  %cmp = icmp ult i32 %3, %sub
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body, %entry
+  ret void
+
+; CHECK: @test1
+
+; First check that we move the sub into the preheader, it doesn't have to be
+; executed if %cmp4 == false
+; CHECK: for.body.preheader:
+; CHECK: sub i32 %data_len, %sample
+; CHECK: br label %for.body
+
+; Second, check that we turn the IV test into an eq.
+; CHECK: %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+; CHECK: %exitcond = icmp ne i32 %lftr.wideiv, %0
+; CHECK: br i1 %exitcond, label %for.body, label %for.end.loopexit
+}
+





More information about the llvm-commits mailing list