<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>