<div dir="ltr">Note that this leads to an opt regression for us, leading to test results like 'expected: -1, actual: -1'. I don't have a small repro yet.</div><br><div class="gmail_quote"><div dir="ltr">On Fri, Sep 18, 2015 at 2:22 PM Sanjoy Das via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: sanjoy<br>
Date: Fri Sep 18 16:21:02 2015<br>
New Revision: 248045<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=248045&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=248045&view=rev</a><br>
Log:<br>
[IndVars] Widen more comparisons for non-negative induction vars<br>
<br>
Summary:<br>
If an induction variable is provably non-negative, its sign extension is<br>
equal to its zero extension.  This means narrow uses like<br>
<br>
  icmp slt iNarrow %indvar, %rhs<br>
<br>
can be widened into<br>
<br>
  icmp slt iWide zext(%indvar), sext(%rhs)<br>
<br>
Reviewers: atrick, mcrosier, hfinkel<br>
<br>
Subscribers: hfinkel, reames, llvm-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D12745" rel="noreferrer" target="_blank">http://reviews.llvm.org/D12745</a><br>
<br>
Modified:<br>
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<br>
    llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=248045&r1=248044&r2=248045&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=248045&r1=248044&r2=248045&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Fri Sep 18 16:21:02 2015<br>
@@ -849,6 +849,11 @@ class WidenIV {<br>
   Type *WideType;<br>
   bool IsSigned;<br>
<br>
+  // True if the narrow induction variable is never negative.  Tracking this<br>
+  // information lets us use a sign extension instead of a zero extension or<br>
+  // vice versa, when profitable and legal.<br>
+  bool NeverNegative;<br>
+<br>
   // Context<br>
   LoopInfo        *LI;<br>
   Loop            *L;<br>
@@ -871,6 +876,7 @@ public:<br>
     OrigPhi(WI.NarrowIV),<br>
     WideType(WI.WidestNativeType),<br>
     IsSigned(WI.IsSigned),<br>
+    NeverNegative(false),<br>
     LI(LInfo),<br>
     L(LI->getLoopFor(OrigPhi->getParent())),<br>
     SE(SEv),<br>
@@ -1082,8 +1088,22 @@ bool WidenIV::WidenLoopCompare(NarrowIVD<br>
   if (!Cmp)<br>
     return false;<br>
<br>
-  // Sign of IV user and compare must match.<br>
-  if (IsSigned != CmpInst::isSigned(Cmp->getPredicate()))<br>
+  // We can legally widen the comparison in the following two cases:<br>
+  //<br>
+  //  - The signedness of the IV extension and comparison match<br>
+  //<br>
+  //  - The narrow IV is always positive (and thus its sign extension is equal<br>
+  //    to its zero extension).  For instance, let's say we're zero extending<br>
+  //    %narrow for the following use<br>
+  //<br>
+  //      icmp slt i32 %narrow, %val   ... (A)<br>
+  //<br>
+  //    and %narrow is always positive.  Then<br>
+  //<br>
+  //      (A) == icmp slt i32 sext(%narrow), sext(%val)<br>
+  //          == icmp slt i32 zext(%narrow), sext(%val)<br>
+<br>
+  if (!(NeverNegative || IsSigned == Cmp->isSigned()))<br>
     return false;<br>
<br>
   Value *Op = Cmp->getOperand(Cmp->getOperand(0) == DU.NarrowDef ? 1 : 0);<br>
@@ -1097,7 +1117,7 @@ bool WidenIV::WidenLoopCompare(NarrowIVD<br>
<br>
   // Widen the other operand of the compare, if necessary.<br>
   if (CastWidth < IVWidth) {<br>
-    Value *ExtOp = getExtend(Op, WideType, IsSigned, Cmp);<br>
+    Value *ExtOp = getExtend(Op, WideType, Cmp->isSigned(), Cmp);<br>
     DU.NarrowUse->replaceUsesOfWith(Op, ExtOp);<br>
   }<br>
   return true;<br>
@@ -1247,6 +1267,9 @@ PHINode *WidenIV::CreateWideIV(SCEVExpan<br>
   if (!AddRec)<br>
     return nullptr;<br>
<br>
+  NeverNegative = SE->isKnownPredicate(ICmpInst::ICMP_SGE, AddRec,<br>
+                                       SE->getConstant(AddRec->getType(), 0));<br>
+<br>
   // Widen the induction variable expression.<br>
   const SCEV *WideIVExpr = IsSigned ?<br>
     SE->getSignExtendExpr(AddRec, WideType) :<br>
<br>
Modified: llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll?rev=248045&r1=248044&r2=248045&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll?rev=248045&r1=248044&r2=248045&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll (original)<br>
+++ llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll Fri Sep 18 16:21:02 2015<br>
@@ -193,3 +193,131 @@ for.body:<br>
 for.end:<br>
   ret i32 %sum.0<br>
 }<br>
+<br>
+define i32 @test6(i32* %a, i32 %b) {<br>
+; CHECK-LABEL: @test6(<br>
+; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64<br>
+; CHECK: for.cond:<br>
+; CHECK: icmp sle i64 %indvars.iv, [[B_SEXT]]<br>
+<br>
+entry:<br>
+  br label %for.cond<br>
+<br>
+for.cond:<br>
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]<br>
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]<br>
+  %cmp = icmp sle i32 %i.0, %b<br>
+  br i1 %cmp, label %for.body, label %for.end<br>
+<br>
+for.body:<br>
+  %idxprom = zext i32 %i.0 to i64<br>
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom<br>
+  %0 = load i32, i32* %arrayidx, align 4<br>
+  %add = add nsw i32 %sum.0, %0<br>
+  %inc = add nsw i32 %i.0, 1<br>
+  br label %for.cond<br>
+<br>
+for.end:<br>
+  ret i32 %sum.0<br>
+}<br>
+<br>
+define i32 @test7(i32* %a, i32 %b) {<br>
+; CHECK-LABEL: @test7(<br>
+; CHECK: [[B_ZEXT:%[a-z0-9]+]] = zext i32 %b to i64<br>
+; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64<br>
+; CHECK: for.cond:<br>
+; CHECK: icmp ule i64 %indvars.iv, [[B_ZEXT]]<br>
+; CHECK: for.body:<br>
+; CHECK: icmp sle i64 %indvars.iv, [[B_SEXT]]<br>
+<br>
+entry:<br>
+  br label %for.cond<br>
+<br>
+for.cond:<br>
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]<br>
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]<br>
+  %cmp = icmp ule i32 %i.0, %b<br>
+  br i1 %cmp, label %for.body, label %for.end<br>
+<br>
+for.body:<br>
+  %idxprom = sext i32 %i.0 to i64<br>
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom<br>
+  %0 = load i32, i32* %arrayidx, align 4<br>
+  %add = add nsw i32 %sum.0, %0<br>
+  %inc = add nsw i32 %i.0, 1<br>
+  %cmp2 = icmp sle i32 %i.0, %b<br>
+  br i1 %cmp2, label %for.cond, label %for.end<br>
+<br>
+for.end:<br>
+  ret i32 %sum.0<br>
+}<br>
+<br>
+define i32 @test8(i32* %a, i32 %b, i32 %init) {<br>
+; CHECK-LABEL: @test8(<br>
+; CHECK: [[INIT_SEXT:%[a-z0-9]+]] = sext i32 %init to i64<br>
+; CHECK: [[B_ZEXT:%[a-z0-9]+]] = zext i32 %b to i64<br>
+; CHECK: for.cond:<br>
+;     Note: %indvars.iv is the sign extension of %i.0<br>
+; CHECK: %indvars.iv = phi i64 [ [[INIT_SEXT]], %for.cond.preheader ], [ %indvars.iv.next, %for.body ]<br>
+; CHECK: icmp ule i64 %indvars.iv, [[B_ZEXT]]<br>
+<br>
+entry:<br>
+  %e = icmp sgt i32 %init, 0<br>
+  br i1 %e, label %for.cond, label %leave<br>
+<br>
+for.cond:<br>
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]<br>
+  %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]<br>
+  %cmp = icmp ule i32 %i.0, %b<br>
+  br i1 %cmp, label %for.body, label %for.end<br>
+<br>
+for.body:<br>
+  %idxprom = sext i32 %i.0 to i64<br>
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom<br>
+  %0 = load i32, i32* %arrayidx, align 4<br>
+  %add = add nsw i32 %sum.0, %0<br>
+  %inc = add nsw i32 %i.0, 1<br>
+  %cmp2 = icmp slt i32 0, %inc<br>
+  br i1 %cmp2, label %for.cond, label %for.end<br>
+<br>
+for.end:<br>
+  ret i32 %sum.0<br>
+<br>
+leave:<br>
+  ret i32 0<br>
+}<br>
+<br>
+define i32 @test9(i32* %a, i32 %b, i32 %init) {<br>
+; CHECK-LABEL: @test9(<br>
+; CHECK: [[INIT_ZEXT:%[a-z0-9]+]] = zext i32 %init to i64<br>
+; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64<br>
+; CHECK: for.cond:<br>
+;     Note: %indvars.iv is the zero extension of %i.0<br>
+; CHECK: %indvars.iv = phi i64 [ [[INIT_ZEXT]], %for.cond.preheader ], [ %indvars.iv.next, %for.body ]<br>
+; CHECK: icmp slt i64 %indvars.iv, [[B_SEXT]]<br>
+<br>
+entry:<br>
+  %e = icmp sgt i32 %init, 0<br>
+  br i1 %e, label %for.cond, label %leave<br>
+<br>
+for.cond:<br>
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]<br>
+  %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]<br>
+  %cmp = icmp slt i32 %i.0, %b<br>
+  br i1 %cmp, label %for.body, label %for.end<br>
+<br>
+for.body:<br>
+  %idxprom = zext i32 %i.0 to i64<br>
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom<br>
+  %0 = load i32, i32* %arrayidx, align 4<br>
+  %add = add nsw i32 %sum.0, %0<br>
+  %inc = add nsw i32 %i.0, 1<br>
+  %cmp2 = icmp slt i32 0, %inc<br>
+  br i1 %cmp2, label %for.cond, label %for.end<br>
+<br>
+for.end:<br>
+  ret i32 %sum.0<br>
+<br>
+leave:<br>
+  ret i32 0<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>