[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