[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

llvm-svn: 338115
This commit is contained in:
Max Kazantsev 2018-07-27 09:43:39 +00:00
parent a4ba5f9951
commit 4d980515d2
2 changed files with 54 additions and 2 deletions

View File

@ -555,6 +555,24 @@ bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
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(TruncInst *TI) {
// 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);
}

View File

@ -531,3 +531,34 @@ bb6: ; preds = %bb4, %bb1
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}