diff options
author | Sanjay Patel <spatel@rotateright.com> | 2016-11-01 19:19:29 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2016-11-01 19:19:29 +0000 |
commit | c0339c77ef9372b85dc6b3fca8ce534fdac7341b (patch) | |
tree | 3f7ff52d796309ce682fca45e8e08345c280e942 /llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | |
parent | 654dc11b794c3196a446c479a9d4442cd0530d7a (diff) | |
download | bcm5719-llvm-c0339c77ef9372b85dc6b3fca8ce534fdac7341b.tar.gz bcm5719-llvm-c0339c77ef9372b85dc6b3fca8ce534fdac7341b.zip |
[InstCombine] Fold nuw left-shifts in `ugt`/`ule` comparisons.
This transforms
%a = shl nuw %x, c1
%b = icmp {ugt|ule} %a, c0
into
%b = icmp {ugt|ule} %x, (c0 >> c1)
z3:
(declare-const x (_ BitVec 64))
(declare-const c0 (_ BitVec 64))
(declare-const c1 (_ BitVec 64))
(push)
(assert (= x (bvlshr (bvshl x c1) c1))) ; nuw
(assert (not (= (bvugt (bvshl x c1) c0)
(bvugt x
(bvlshr c0 c1)))))
(check-sat)
(get-model)
(pop)
(push)
(assert (= x (bvlshr (bvshl x c1) c1))) ; nuw
(assert (not (= (bvule (bvshl x c1) c0)
(bvule x
(bvlshr c0 c1)))))
(check-sat)
(get-model)
(pop)
Patch by bryant!
Differential Revision: https://reviews.llvm.org/D25913
llvm-svn: 285729
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 652d2c7bef4..bacb9ba5d59 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1950,6 +1950,23 @@ Instruction *InstCombiner::foldICmpShlConstant(ICmpInst &Cmp, And, Constant::getNullValue(And->getType())); } + // When the shift is nuw and pred is >u or <=u, comparison only really happens + // in the pre-shifted bits. Since InstSimplify canoncalizes <=u into <u, the + // <=u case can be further converted to match <u (see below). + if (Shl->hasNoUnsignedWrap() && + (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULT)) { + // Derivation for the ult case: + // (X << S) <=u C is equiv to X <=u (C >> S) for all C + // (X << S) <u (C + 1) is equiv to X <u (C >> S) + 1 if C <u ~0u + // (X << S) <u C is equiv to X <u ((C - 1) >> S) + 1 if C >u 0 + assert((Pred != ICmpInst::ICMP_ULT || C->ugt(0)) && + "Encountered `ult 0` that should have been eliminated by " + "InstSimplify."); + APInt ShiftedC = Pred == ICmpInst::ICMP_ULT ? (*C - 1).lshr(*ShiftAmt) + 1 + : C->lshr(*ShiftAmt); + return new ICmpInst(Pred, X, ConstantInt::get(X->getType(), ShiftedC)); + } + // Transform (icmp pred iM (shl iM %v, N), C) // -> (icmp pred i(M-N) (trunc %v iM to i(M-N)), (trunc (C>>N)) // Transform the shl to a trunc if (trunc (C>>N)) has no loss and M-N. |