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

Dan Gohman gohman at apple.com
Tue Feb 17 16:52:01 PST 2009


Author: djg
Date: Tue Feb 17 18:52:00 2009
New Revision: 64866

URL: http://llvm.org/viewvc/llvm-project?rev=64866&view=rev
Log:
Fix a corner case in the new indvars promotion logic: if there
are multiple IV's in a loop, some of them may under go signed
or unsigned wrapping even if the IV that's used in the loop
exit condition doesn't. Restrict sign-extension-elimination
and zero-extension-elimination to only those that operate on
the original loop-controlling IV.

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

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=64866&r1=64865&r2=64866&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Feb 17 18:52:00 2009
@@ -463,21 +463,24 @@
 }
 
 /// TestOrigIVForWrap - Analyze the original induction variable
-/// in the loop to determine whether it would ever undergo signed
-/// or unsigned overflow.
+/// that controls the loop's iteration to determine whether it
+/// would ever undergo signed or unsigned overflow.
+///
+/// In addition to setting the NoSignedWrap and NoUnsignedWrap
+/// variables, return the PHI for this induction variable.
 ///
 /// TODO: This duplicates a fair amount of ScalarEvolution logic.
 /// Perhaps this can be merged with ScalarEvolution::getIterationCount
 /// and/or ScalarEvolution::get{Sign,Zero}ExtendExpr.
 ///
-static void TestOrigIVForWrap(const Loop *L,
-                              const BranchInst *BI,
-                              const Instruction *OrigCond,
-                              bool &NoSignedWrap,
-                              bool &NoUnsignedWrap) {
+static const PHINode *TestOrigIVForWrap(const Loop *L,
+                                        const BranchInst *BI,
+                                        const Instruction *OrigCond,
+                                        bool &NoSignedWrap,
+                                        bool &NoUnsignedWrap) {
   // Verify that the loop is sane and find the exit condition.
   const ICmpInst *Cmp = dyn_cast<ICmpInst>(OrigCond);
-  if (!Cmp) return;
+  if (!Cmp) return 0;
 
   const Value *CmpLHS = Cmp->getOperand(0);
   const Value *CmpRHS = Cmp->getOperand(1);
@@ -530,7 +533,7 @@
   }
   // For now, analyze only LT loops for signed overflow.
   if (Pred != ICmpInst::ICMP_SLT && Pred != ICmpInst::ICMP_ULT)
-    return;
+    return 0;
 
   bool isSigned = Pred == ICmpInst::ICMP_SLT;
 
@@ -543,7 +546,7 @@
       if (!isa<ConstantInt>(CmpRHS) ||
           !cast<ConstantInt>(CmpRHS)->getValue()
             .isSignedIntN(IncrVal->getType()->getPrimitiveSizeInBits()))
-        return;
+        return 0;
       IncrVal = SI->getOperand(0);
     }
   } else {
@@ -551,7 +554,7 @@
       if (!isa<ConstantInt>(CmpRHS) ||
           !cast<ConstantInt>(CmpRHS)->getValue()
             .isIntN(IncrVal->getType()->getPrimitiveSizeInBits()))
-        return;
+        return 0;
       IncrVal = ZI->getOperand(0);
     }
   }
@@ -562,26 +565,26 @@
       IncrOp->getOpcode() != Instruction::Add ||
       !isa<ConstantInt>(IncrOp->getOperand(1)) ||
       !cast<ConstantInt>(IncrOp->getOperand(1))->equalsInt(1))
-    return;
+    return 0;
 
   // Make sure the PHI looks like a normal IV.
   const PHINode *PN = dyn_cast<PHINode>(IncrOp->getOperand(0));
   if (!PN || PN->getNumIncomingValues() != 2)
-    return;
+    return 0;
   unsigned IncomingEdge = L->contains(PN->getIncomingBlock(0));
   unsigned BackEdge = !IncomingEdge;
   if (!L->contains(PN->getIncomingBlock(BackEdge)) ||
       PN->getIncomingValue(BackEdge) != IncrOp)
-    return;
+    return 0;
   if (!L->contains(TrueBB))
-    return;
+    return 0;
 
   // For now, only analyze loops with a constant start value, so that
   // we can easily determine if the start value is not a maximum value
   // which would wrap on the first iteration.
   const Value *InitialVal = PN->getIncomingValue(IncomingEdge);
   if (!isa<ConstantInt>(InitialVal))
-    return;
+    return 0;
 
   // The original induction variable will start at some non-max value,
   // it counts up by one, and the loop iterates only while it remans
@@ -592,6 +595,7 @@
   else if (!isSigned &&
            !cast<ConstantInt>(InitialVal)->getValue().isMaxValue())
     NoUnsignedWrap = true;
+  return PN;
 }
 
 bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
@@ -675,13 +679,15 @@
   // using it.  We can currently only handle loops with a single exit.
   bool NoSignedWrap = false;
   bool NoUnsignedWrap = false;
+  const PHINode *OrigControllingPHI = 0;
   if (!isa<SCEVCouldNotCompute>(IterationCount) && ExitingBlock)
     // Can't rewrite non-branch yet.
     if (BranchInst *BI = dyn_cast<BranchInst>(ExitingBlock->getTerminator())) {
       if (Instruction *OrigCond = dyn_cast<Instruction>(BI->getCondition())) {
         // Determine if the OrigIV will ever undergo overflow.
-        TestOrigIVForWrap(L, BI, OrigCond,
-                          NoSignedWrap, NoUnsignedWrap);
+        OrigControllingPHI =
+          TestOrigIVForWrap(L, BI, OrigCond,
+                            NoSignedWrap, NoUnsignedWrap);
 
         // We'll be replacing the original condition, so it'll be dead.
         DeadInsts.insert(OrigCond);
@@ -722,7 +728,7 @@
     /// If the new canonical induction variable is wider than the original,
     /// and the original has uses that are casts to wider types, see if the
     /// truncate and extend can be omitted.
-    if (PN->getType() != LargestType)
+    if (PN == OrigControllingPHI && PN->getType() != LargestType)
       for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
            UI != UE; ++UI) {
         if (isa<SExtInst>(UI) && NoSignedWrap) {

Added: 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=64866&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll Tue Feb 17 18:52:00 2009
@@ -0,0 +1,38 @@
+; RUN: llvm-as < %s | opt -indvars | llvm-dis > %t
+; RUN: grep sext %t | count 1
+; RUN: grep phi %t | count 1
+; RUN: grep {phi i64} %t
+
+; Indvars should insert a 64-bit induction variable to eliminate the
+; sext for the addressing, however it shouldn't eliminate the sext
+; on the other phi, since that value undergoes signed wrapping.
+
+define void @foo(i32* nocapture %d, i32 %n) nounwind {
+entry:
+	%0 = icmp sgt i32 %n, 0		; <i1> [#uses=1]
+	br i1 %0, label %bb.nph, label %return
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+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]
+	%1 = sext i8 %p.01 to i32		; <i32> [#uses=1]
+	%2 = sext i32 %i.02 to i64		; <i64> [#uses=1]
+	%3 = getelementptr i32* %d, i64 %2		; <i32*> [#uses=1]
+	store i32 %1, i32* %3, align 4
+	%4 = add i8 %p.01, 1		; <i8> [#uses=1]
+	%5 = add i32 %i.02, 1		; <i32> [#uses=2]
+	br label %bb1
+
+bb1:		; preds = %bb
+	%6 = icmp slt i32 %5, %n		; <i1> [#uses=1]
+	br i1 %6, label %bb, label %bb1.return_crit_edge
+
+bb1.return_crit_edge:		; preds = %bb1
+	br label %return
+
+return:		; preds = %bb1.return_crit_edge, %entry
+	ret void
+}





More information about the llvm-commits mailing list