forked from OSchip/llvm-project
[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:
parent
a4ba5f9951
commit
4d980515d2
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Reference in New Issue