[PATCH] D48763: [SimplifyIndVar] Canonicalize comparisons to unsigned while eliminating truncs
Max Kazantsev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 1 19:51:51 PDT 2018
mkazantsev updated this revision to Diff 153662.
mkazantsev marked 2 inline comments as done.
mkazantsev added a comment.
Added some comments, removed one unnecessary lambda.
https://reviews.llvm.org/D48763
Files:
lib/Transforms/Utils/SimplifyIndVar.cpp
test/Transforms/IndVarSimplify/eliminate-trunc.ll
Index: test/Transforms/IndVarSimplify/eliminate-trunc.ll
===================================================================
--- test/Transforms/IndVarSimplify/eliminate-trunc.ll
+++ test/Transforms/IndVarSimplify/eliminate-trunc.ll
@@ -531,3 +531,34 @@
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}
Index: lib/Transforms/Utils/SimplifyIndVar.cpp
===================================================================
--- lib/Transforms/Utils/SimplifyIndVar.cpp
+++ lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -555,6 +555,24 @@
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 @@
// 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);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D48763.153662.patch
Type: text/x-patch
Size: 3617 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180702/393934a0/attachment.bin>
More information about the llvm-commits
mailing list