[IndVars] Fix a bug in r248045.
authorSanjoy Das <sanjoy@playingwithpointers.com>
Sun, 20 Sep 2015 01:52:18 +0000 (01:52 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Sun, 20 Sep 2015 01:52:18 +0000 (01:52 +0000)
Because -indvars widens induction variables through arithmetic,
`NeverNegative` cannot be a property of the `WidenIV` (a `WidenIV`
manages information for all transitive uses of an IV being widened,
including uses of `-1 * IV`).  Instead it must live on `NarrowIVDefUse`
which manages information for a specific def-use edge in the transitive
use list of an induction variable.

This change also adds a test case that demonstrates the problem with
r248045.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248107 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/IndVarSimplify.cpp
test/Transforms/IndVarSimplify/widen-loop-comp.ll

index c58c9978b82e411e39539a4600c5eaa29d556df6..72d957949495435dc0965cec0d670350072b3641 100644 (file)
@@ -832,10 +832,19 @@ struct NarrowIVDefUse {
   Instruction *NarrowUse;
   Instruction *WideDef;
 
-  NarrowIVDefUse(): NarrowDef(nullptr), NarrowUse(nullptr), WideDef(nullptr) {}
+  // True if the narrow def is never negative.  Tracking this information lets
+  // us use a sign extension instead of a zero extension or vice versa, when
+  // profitable and legal.
+  bool NeverNegative;
+
+  NarrowIVDefUse()
+      : NarrowDef(nullptr), NarrowUse(nullptr), WideDef(nullptr),
+        NeverNegative(false) {}
 
-  NarrowIVDefUse(Instruction *ND, Instruction *NU, Instruction *WD):
-    NarrowDef(ND), NarrowUse(NU), WideDef(WD) {}
+  NarrowIVDefUse(Instruction *ND, Instruction *NU, Instruction *WD,
+                 bool NeverNegative)
+      : NarrowDef(ND), NarrowUse(NU), WideDef(WD),
+        NeverNegative(NeverNegative) {}
 };
 
 /// WidenIV - The goal of this transform is to remove sign and zero extends
@@ -849,11 +858,6 @@ class WidenIV {
   Type *WideType;
   bool IsSigned;
 
-  // True if the narrow induction variable is never negative.  Tracking this
-  // information lets us use a sign extension instead of a zero extension or
-  // vice versa, when profitable and legal.
-  bool NeverNegative;
-
   // Context
   LoopInfo        *LI;
   Loop            *L;
@@ -876,7 +880,6 @@ public:
     OrigPhi(WI.NarrowIV),
     WideType(WI.WidestNativeType),
     IsSigned(WI.IsSigned),
-    NeverNegative(false),
     LI(LInfo),
     L(LI->getLoopFor(OrigPhi->getParent())),
     SE(SEv),
@@ -1103,7 +1106,7 @@ bool WidenIV::WidenLoopCompare(NarrowIVDefUse DU) {
   //      (A) == icmp slt i32 sext(%narrow), sext(%val)
   //          == icmp slt i32 zext(%narrow), sext(%val)
 
-  if (!(NeverNegative || IsSigned == Cmp->isSigned()))
+  if (!(DU.NeverNegative || IsSigned == Cmp->isSigned()))
     return false;
 
   Value *Op = Cmp->getOperand(Cmp->getOperand(0) == DU.NarrowDef ? 1 : 0);
@@ -1240,6 +1243,10 @@ Instruction *WidenIV::WidenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) {
 /// pushNarrowIVUsers - Add eligible users of NarrowDef to NarrowIVUsers.
 ///
 void WidenIV::pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef) {
+  const SCEV *NarrowSCEV = SE->getSCEV(NarrowDef);
+  bool NeverNegative =
+      SE->isKnownPredicate(ICmpInst::ICMP_SGE, NarrowSCEV,
+                           SE->getConstant(NarrowSCEV->getType(), 0));
   for (User *U : NarrowDef->users()) {
     Instruction *NarrowUser = cast<Instruction>(U);
 
@@ -1247,7 +1254,8 @@ void WidenIV::pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef) {
     if (!Widened.insert(NarrowUser).second)
       continue;
 
-    NarrowIVUsers.push_back(NarrowIVDefUse(NarrowDef, NarrowUser, WideDef));
+    NarrowIVUsers.push_back(
+        NarrowIVDefUse(NarrowDef, NarrowUser, WideDef, NeverNegative));
   }
 }
 
@@ -1267,9 +1275,6 @@ PHINode *WidenIV::CreateWideIV(SCEVExpander &Rewriter) {
   if (!AddRec)
     return nullptr;
 
-  NeverNegative = SE->isKnownPredicate(ICmpInst::ICMP_SGE, AddRec,
-                                       SE->getConstant(AddRec->getType(), 0));
-
   // Widen the induction variable expression.
   const SCEV *WideIVExpr = IsSigned ?
     SE->getSignExtendExpr(AddRec, WideType) :
index 5860bf2a8b3cd223f5fc07b4575296e1fc6dec1c..b87cd0550192ed4073e609dc8897335a78bab0ee 100644 (file)
@@ -321,3 +321,35 @@ for.end:
 leave:
   ret i32 0
 }
+
+declare void @consume.i64(i64)
+declare void @consume.i1(i1)
+
+define i32 @test10(i32 %v) {
+; CHECK-LABEL: @test10(
+ entry:
+; CHECK-NOT: zext
+  br label %loop
+
+ loop:
+; CHECK: loop:
+; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ]
+; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+; CHECK: [[MUL:%[a-z0-9]+]] = mul nsw i64 %indvars.iv, -1
+; CHECK: [[MUL_TRUNC:%[a-z0-9]+]] = trunc i64 [[MUL]] to i32
+; CHECK: [[CMP:%[a-z0-9]+]] = icmp eq i32 [[MUL_TRUNC]], %v
+; CHECK: call void @consume.i1(i1 [[CMP]])
+
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+  %i.inc = add i32 %i, 1
+  %iv = mul i32 %i, -1
+  %cmp = icmp eq i32 %iv, %v
+  call void @consume.i1(i1 %cmp)
+  %be.cond = icmp slt i32 %i.inc, 11
+  %ext = sext i32 %iv to i64
+  call void @consume.i64(i64 %ext)
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret i32 22
+}