[llvm-commits] [llvm] r134306 - in /llvm/trunk: lib/Transforms/Scalar/IndVarSimplify.cpp test/Transforms/IndVarSimplify/no-iv-rewrite.ll test/Transforms/IndVarSimplify/preserve-signed-wrap.ll

Andrew Trick atrick at apple.com
Fri Jul 1 19:34:25 PDT 2011


Author: atrick
Date: Fri Jul  1 21:34:25 2011
New Revision: 134306

URL: http://llvm.org/viewvc/llvm-project?rev=134306&view=rev
Log:
indvars -disable-iv-rewrite: bug fix involving weird geps and related cleanup.

Modified:
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
    llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=134306&r1=134305&r2=134306&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Fri Jul  1 21:34:25 2011
@@ -581,6 +581,7 @@
   SmallVectorImpl<WeakVH> &DeadInsts;
 
   SmallPtrSet<Instruction*,16> Widened;
+  SmallVector<std::pair<Use *, Instruction *>, 8> NarrowIVUsers;
 
 public:
   WidenIV(PHINode *PN, const WideIVInfo &WI, LoopInfo *LInfo,
@@ -607,10 +608,10 @@
                            Instruction *NarrowDef,
                            Instruction *WideDef);
 
-  const SCEVAddRecExpr *GetWideRecurrence(Instruction *NarrowUse);
-
   Instruction *WidenIVUse(Use &NarrowDefUse, Instruction *NarrowDef,
                           Instruction *WideDef);
+
+  void pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef);
 };
 } // anonymous namespace
 
@@ -669,26 +670,6 @@
   llvm_unreachable(0);
 }
 
-// GetWideRecurrence - Is this instruction potentially interesting from IVUsers'
-// perspective after widening it's type? In other words, can the extend be
-// safely hoisted out of the loop with SCEV reducing the value to a recurrence
-// on the same loop. If so, return the sign or zero extended
-// recurrence. Otherwise return NULL.
-const SCEVAddRecExpr *WidenIV::GetWideRecurrence(Instruction *NarrowUse) {
-  if (!SE->isSCEVable(NarrowUse->getType()))
-    return 0;
-
-  const SCEV *NarrowExpr = SE->getSCEV(NarrowUse);
-  const SCEV *WideExpr = IsSigned ?
-    SE->getSignExtendExpr(NarrowExpr, WideType) :
-    SE->getZeroExtendExpr(NarrowExpr, WideType);
-  const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(WideExpr);
-  if (!AddRec || AddRec->getLoop() != L)
-    return 0;
-
-  return AddRec;
-}
-
 /// HoistStep - Attempt to hoist an IV increment above a potential use.
 ///
 /// To successfully hoist, two criteria must be met:
@@ -729,15 +710,10 @@
                                  Instruction *WideDef) {
   Instruction *NarrowUse = cast<Instruction>(NarrowDefUse.getUser());
 
-  // To be consistent with IVUsers, stop traversing the def-use chain at
-  // inner-loop phis or post-loop phis.
+  // Stop traversing the def-use chain at inner-loop phis or post-loop phis.
   if (isa<PHINode>(NarrowUse) && LI->getLoopFor(NarrowUse->getParent()) != L)
     return 0;
 
-  // Handle data flow merges and bizarre phi cycles.
-  if (!Widened.insert(NarrowUse))
-    return 0;
-
   // Our raison d'etre! Eliminate sign and zero extension.
   if (IsSigned ? isa<SExtInst>(NarrowUse) : isa<ZExtInst>(NarrowUse)) {
     Value *NewDef = WideDef;
@@ -775,7 +751,26 @@
     // No further widening is needed. The deceased [sz]ext had done it for us.
     return 0;
   }
-  const SCEVAddRecExpr *WideAddRec = GetWideRecurrence(NarrowUse);
+
+  // Does this user itself evaluate to a recurrence after widening?
+  const SCEVAddRecExpr *WideAddRec = 0;
+  if (SE->isSCEVable(NarrowUse->getType())) {
+    const SCEV *NarrowExpr = SE->getSCEV(NarrowUse);
+    if (SE->getTypeSizeInBits(NarrowExpr->getType())
+        >= SE->getTypeSizeInBits(WideType)) {
+      // NarrowUse implicitly widens its operand. e.g. a gep with a narrow
+      // index. We have already extended the operand, so we're done.
+      return 0;
+    }
+    const SCEV *WideExpr = IsSigned ?
+      SE->getSignExtendExpr(NarrowExpr, WideType) :
+      SE->getZeroExtendExpr(NarrowExpr, WideType);
+
+    // Only widen past values that evaluate to a recurrence in the same loop.
+    const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(WideExpr);
+    if (AddRec && AddRec->getLoop() == L)
+      WideAddRec = AddRec;
+  }
   if (!WideAddRec) {
     // This user does not evaluate to a recurence after widening, so don't
     // follow it. Instead insert a Trunc to kill off the original use,
@@ -785,9 +780,10 @@
     NarrowUse->replaceUsesOfWith(NarrowDef, Trunc);
     return 0;
   }
-  // We assume that block terminators are not SCEVable.
+  // We assume that block terminators are not SCEVable. We wouldn't want to
+  // insert a Trunc after a terminator if there happens to be a critical edge.
   assert(NarrowUse != NarrowUse->getParent()->getTerminator() &&
-         "can't split terminators");
+         "SCEV is not expected to evaluate a block terminator");
 
   // Reuse the IV increment that SCEVExpander created as long as it dominates
   // NarrowUse.
@@ -800,8 +796,8 @@
     if (!WideUse)
       return 0;
   }
-  // GetWideRecurrence ensured that the narrow expression could be extended
-  // outside the loop without overflow. This suggests that the wide use
+  // Evaluation of WideAddRec ensured that the narrow expression could be
+  // extended outside the loop without overflow. This suggests that the wide use
   // evaluates to the same expression as the extended narrow use, but doesn't
   // absolutely guarantee it. Hence the following failsafe check. In rare cases
   // where it fails, we simply throw away the newly created wide use.
@@ -816,6 +812,21 @@
   return WideUse;
 }
 
+/// pushNarrowIVUsers - Add eligible users of NarrowDef to NarrowIVUsers.
+///
+void WidenIV::pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef) {
+  for (Value::use_iterator UI = NarrowDef->use_begin(),
+         UE = NarrowDef->use_end(); UI != UE; ++UI) {
+    Use &U = UI.getUse();
+
+    // Handle data flow merges and bizarre phi cycles.
+    if (!Widened.insert(cast<Instruction>(U.getUser())))
+      continue;
+
+    NarrowIVUsers.push_back(std::make_pair(&UI.getUse(), WideDef));
+  }
+}
+
 /// CreateWideIV - Process a single induction variable. First use the
 /// SCEVExpander to create a wide induction variable that evaluates to the same
 /// recurrence as the original narrow IV. Then use a worklist to forward
@@ -873,14 +884,11 @@
   ++NumWidened;
 
   // Traverse the def-use chain using a worklist starting at the original IV.
-  assert(Widened.empty() && "expect initial state" );
+  assert(Widened.empty() && NarrowIVUsers.empty() && "expect initial state" );
+
+  Widened.insert(OrigPhi);
+  pushNarrowIVUsers(OrigPhi, WidePhi);
 
-  // Each worklist entry has a Narrow def-use link and Wide def.
-  SmallVector<std::pair<Use *, Instruction *>, 8> NarrowIVUsers;
-  for (Value::use_iterator UI = OrigPhi->use_begin(),
-         UE = OrigPhi->use_end(); UI != UE; ++UI) {
-    NarrowIVUsers.push_back(std::make_pair(&UI.getUse(), WidePhi));
-  }
   while (!NarrowIVUsers.empty()) {
     Use *UsePtr;
     Instruction *WideDef;
@@ -893,12 +901,9 @@
     Instruction *WideUse = WidenIVUse(NarrowDefUse, NarrowDef, WideDef);
 
     // Follow all def-use edges from the previous narrow use.
-    if (WideUse) {
-      for (Value::use_iterator UI = NarrowDefUse.getUser()->use_begin(),
-             UE = NarrowDefUse.getUser()->use_end(); UI != UE; ++UI) {
-        NarrowIVUsers.push_back(std::make_pair(&UI.getUse(), WideUse));
-      }
-    }
+    if (WideUse)
+      pushNarrowIVUsers(cast<Instruction>(NarrowDefUse.getUser()), WideUse);
+
     // WidenIVUse may have removed the def-use edge.
     if (NarrowDef->use_empty())
       DeadInsts.push_back(NarrowDef);

Modified: llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll?rev=134306&r1=134305&r2=134306&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll Fri Jul  1 21:34:25 2011
@@ -246,3 +246,27 @@
   %result = and i64 %val, %t3
   ret i64 %result
 }
+
+; The i induction variable looks like a wrap-around, but it really is just
+; a simple affine IV.  Make sure that indvars simplifies through.
+define i32 @indirectRecurrence() nounwind {
+entry:
+  br label %loop
+
+; ReplaceLoopExitValue should fold the return value to constant 9.
+; CHECK: loop:
+; CHECK: phi i32
+; CHECK: ret i32 9
+loop:
+  %j.0 = phi i32 [ 1, %entry ], [ %j.next, %cond_true ]
+  %i.0 = phi i32 [ 0, %entry ], [ %j.0, %cond_true ]
+  %tmp = icmp ne i32 %j.0, 10
+  br i1 %tmp, label %cond_true, label %return
+
+cond_true:
+  %j.next = add i32 %j.0, 1
+  br label %loop
+
+return:
+  ret i32 %i.0
+}

Modified: llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll?rev=134306&r1=134305&r2=134306&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll Fri Jul  1 21:34:25 2011
@@ -1,7 +1,5 @@
-; RUN: opt < %s -indvars -S > %t
-; RUN: grep sext %t | count 1
-; RUN: grep phi %t | count 1
-; RUN: grep {phi i64} %t
+; RUN: opt < %s -indvars -S | FileCheck %s
+; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
 
 ; Indvars should insert a 64-bit induction variable to eliminate the
 ; sext for the addressing, however it shouldn't eliminate the sext
@@ -15,6 +13,10 @@
 bb.nph:		; preds = %entry
 	br label %bb
 
+; CHECK: bb:
+; CHECK: phi i64
+; CHECK: sext i8
+; CHECK-NOT: sext
 bb:		; preds = %bb1, %bb.nph
 	%i.02 = phi i32 [ %5, %bb1 ], [ 0, %bb.nph ]		; <i32> [#uses=2]
 	%p.01 = phi i8 [ %4, %bb1 ], [ -1, %bb.nph ]		; <i8> [#uses=2]





More information about the llvm-commits mailing list