[llvm] r338115 - [SimplifyIndVar] Canonicalize comparisons to unsigned while eliminating truncs
Max Kazantsev via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 27 02:43:39 PDT 2018
Author: mkazantsev
Date: Fri Jul 27 02:43:39 2018
New Revision: 338115
URL: http://llvm.org/viewvc/llvm-project?rev=338115&view=rev
Log:
[SimplifyIndVar] Canonicalize comparisons to unsigned while eliminating truncs
This is a follow-up for the patch rL335020. When we replace compares against
trunc with compares against wide IV, we can also replace signed predicates with
unsigned where it is legal.
Reviewed By: reames
Differential Revision: https://reviews.llvm.org/D48763
Modified:
llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=338115&r1=338114&r2=338115&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Fri Jul 27 02:43:39 2018
@@ -555,6 +555,24 @@ bool SimplifyIndvar::eliminateTrunc(Trun
return false;
}
+ auto CanUseZExt = [&](ICmpInst *ICI) {
+ // Unsigned comparison can be widened as unsigned.
+ if (ICI->isUnsigned())
+ return true;
+ // Is it profitable to do zext?
+ if (!DoesZExtCollapse)
+ return false;
+ // For equality, we can safely zext both parts.
+ if (ICI->isEquality())
+ return true;
+ // Otherwise we can only use zext when comparing two non-negative or two
+ // negative values. But in practice, we will never pass DoesZExtCollapse
+ // check for a negative value, because zext(trunc(x)) is non-negative. So
+ // it only make sense to check for non-negativity here.
+ const SCEV *SCEVOP1 = SE->getSCEV(ICI->getOperand(0));
+ const SCEV *SCEVOP2 = SE->getSCEV(ICI->getOperand(1));
+ return SE->isKnownNonNegative(SCEVOP1) && SE->isKnownNonNegative(SCEVOP2);
+ };
// Replace all comparisons against trunc with comparisons against IV.
for (auto *ICI : ICmpUsers) {
auto *Op1 = ICI->getOperand(1);
@@ -565,17 +583,20 @@ bool SimplifyIndvar::eliminateTrunc(Trun
// then prefer zext as a more canonical form.
// TODO: If we see a signed comparison which can be turned into unsigned,
// we can do it here for canonicalization purposes.
- if (ICI->isUnsigned() || (ICI->isEquality() && DoesZExtCollapse)) {
+ ICmpInst::Predicate Pred = ICI->getPredicate();
+ if (CanUseZExt(ICI)) {
assert(DoesZExtCollapse && "Unprofitable zext?");
Ext = new ZExtInst(Op1, IVTy, "zext", ICI);
+ Pred = ICmpInst::getUnsignedPredicate(Pred);
} else {
assert(DoesSExtCollapse && "Unprofitable sext?");
Ext = new SExtInst(Op1, IVTy, "sext", ICI);
+ assert(Pred == ICmpInst::getSignedPredicate(Pred) && "Must be signed!");
}
bool Changed;
L->makeLoopInvariant(Ext, Changed);
(void)Changed;
- ICmpInst *NewICI = new ICmpInst(ICI, ICI->getPredicate(), IV, Ext);
+ ICmpInst *NewICI = new ICmpInst(ICI, Pred, IV, Ext);
ICI->replaceAllUsesWith(NewICI);
DeadInsts.emplace_back(ICI);
}
Modified: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll?rev=338115&r1=338114&r2=338115&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll Fri Jul 27 02:43:39 2018
@@ -531,3 +531,34 @@ bb6:
bb7: ; preds = %bb6
ret void
}
+
+; Show that we can turn signed comparison to unsigned and use zext while
+; comparing non-negative values.
+define void @test_12(i32* %p) {
+; CHECK-LABEL: @test_12(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[N:%.*]] = load i32, i32* [[P:%.*]], !range !0
+; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[N]] to i64
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV_NEXT]], [[ZEXT]]
+; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %n = load i32, i32* %p, !range !0
+ br label %loop
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %iv.next = add i64 %iv, 1
+ %narrow.iv = trunc i64 %iv.next to i32
+ %cmp = icmp slt i32 %narrow.iv, %n
+ br i1 %cmp, label %loop, label %exit
+exit:
+ ret void
+}
+
+!0 = !{i32 0, i32 1000}
More information about the llvm-commits
mailing list