Skip to content

Commit

Permalink
Generalize icmp matching in IndVars' eliminateTrunc
Browse files Browse the repository at this point in the history
We were only matching RHS being a loop invariant value, not the inverse. Since there's nothing which appears to canonicalize loop invariant values to RHS, this means we missed cases.

Differential Revision: https://reviews.llvm.org/D63112

llvm-svn: 363108
  • Loading branch information
preames committed Jun 11, 2019
1 parent c06943b commit 082cd30
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 14 deletions.
29 changes: 15 additions & 14 deletions llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
Expand Up @@ -521,20 +521,19 @@ bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
if (isa<Instruction>(U) &&
!DT->isReachableFromEntry(cast<Instruction>(U)->getParent()))
continue;
if (ICmpInst *ICI = dyn_cast<ICmpInst>(U)) {
if (ICI->getOperand(0) == TI && L->isLoopInvariant(ICI->getOperand(1))) {
assert(L->contains(ICI->getParent()) && "LCSSA form broken?");
// If we cannot get rid of trunc, bail.
if (ICI->isSigned() && !DoesSExtCollapse)
return false;
if (ICI->isUnsigned() && !DoesZExtCollapse)
return false;
// For equality, either signed or unsigned works.
ICmpUsers.push_back(ICI);
} else
return false;
} else
ICmpInst *ICI = dyn_cast<ICmpInst>(U);
if (!ICI) return false;
assert(L->contains(ICI->getParent()) && "LCSSA form broken?");
if (!(ICI->getOperand(0) == TI && L->isLoopInvariant(ICI->getOperand(1))) &&
!(ICI->getOperand(1) == TI && L->isLoopInvariant(ICI->getOperand(0))))
return false;
// If we cannot get rid of trunc, bail.
if (ICI->isSigned() && !DoesSExtCollapse)
return false;
if (ICI->isUnsigned() && !DoesZExtCollapse)
return false;
// For equality, either signed or unsigned works.
ICmpUsers.push_back(ICI);
}

auto CanUseZExt = [&](ICmpInst *ICI) {
Expand All @@ -557,7 +556,8 @@ bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
};
// Replace all comparisons against trunc with comparisons against IV.
for (auto *ICI : ICmpUsers) {
auto *Op1 = ICI->getOperand(1);
bool IsSwapped = L->isLoopInvariant(ICI->getOperand(0));
auto *Op1 = IsSwapped ? ICI->getOperand(0) : ICI->getOperand(1);
Instruction *Ext = nullptr;
// For signed/unsigned predicate, replace the old comparison with comparison
// of immediate IV against sext/zext of the invariant argument. If we can
Expand All @@ -566,6 +566,7 @@ bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
// TODO: If we see a signed comparison which can be turned into unsigned,
// we can do it here for canonicalization purposes.
ICmpInst::Predicate Pred = ICI->getPredicate();
if (IsSwapped) Pred = ICmpInst::getSwappedPredicate(Pred);
if (CanUseZExt(ICI)) {
assert(DoesZExtCollapse && "Unprofitable zext?");
Ext = new ZExtInst(Op1, IVTy, "zext", ICI);
Expand Down
104 changes: 104 additions & 0 deletions llvm/test/Transforms/IndVarSimplify/eliminate-trunc.ll
Expand Up @@ -561,4 +561,108 @@ exit:
ret void
}

define void @test_13a(i32 %n) {
;
; CHECK-LABEL: @test_13a(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 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]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw nuw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ne i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}

define void @test_13b(i32 %n) {
;
; CHECK-LABEL: @test_13b(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 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]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw nuw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp ugt i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}

define void @test_13c(i32 %n) {
;
; CHECK-LABEL: @test_13c(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 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]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw nuw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp sgt i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}

define void @test_13d(i32 %n) {
;
; CHECK-LABEL: @test_13d(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SEXT:%.*]] = sext i32 1024 to i64
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -20, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 2
; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]]
; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%iv = phi i64 [ -20, %entry ], [ %iv.next, %loop ]
%iv.next = add nsw i64 %iv, 2
%narrow.iv = trunc i64 %iv to i32
%cmp = icmp sgt i32 1024, %narrow.iv
br i1 %cmp, label %loop, label %exit
exit:
ret void
}

!0 = !{i32 0, i32 1000}

0 comments on commit 082cd30

Please sign in to comment.