summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2013-06-28 23:42:03 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2013-06-28 23:42:03 +0000
commitb889e405eb558b773809226e1e64cdfdf9e0f331 (patch)
treee9b23a778aa8f2eb38464d19ca07621a58a8dacb /llvm/lib/Transforms
parentbb97db3df9906cad44164bffdc9da0cb7eab27c1 (diff)
downloadbcm5719-llvm-b889e405eb558b773809226e1e64cdfdf9e0f331.tar.gz
bcm5719-llvm-b889e405eb558b773809226e1e64cdfdf9e0f331.zip
InstCombine: Optimize (1 << X) Pred CstP2 to X Pred Log2(CstP2)
We may, after other optimizations, find ourselves with IR that looks like: %shl = shl i32 1, %y %cmp = icmp ult i32 %shl, 32 Instead, we should just compare the shift count: %cmp = icmp ult i32 %y, 5 llvm-svn: 185242
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp74
1 files changed, 72 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 617d8e7a5c1..2a87f8ab3be 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1319,10 +1319,80 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
}
case Instruction::Shl: { // (icmp pred (shl X, ShAmt), CI)
+ uint32_t TypeBits = RHSV.getBitWidth();
ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
- if (!ShAmt) break;
+ if (!ShAmt) {
+ Value *X;
+ // (1 << X) pred P2 -> X pred Log2(P2)
+ if (match(LHSI, m_Shl(m_One(), m_Value(X)))) {
+ bool RHSVIsPowerOf2 = RHSV.isPowerOf2();
+ ICmpInst::Predicate Pred = ICI.getPredicate();
+ if (ICI.isUnsigned()) {
+ if (!RHSVIsPowerOf2) {
+ // (1 << X) < 30 -> X <= 4
+ // (1 << X) <= 30 -> X <= 4
+ // (1 << X) >= 30 -> X > 4
+ // (1 << X) > 30 -> X > 4
+ if (Pred == ICmpInst::ICMP_ULT)
+ Pred = ICmpInst::ICMP_ULE;
+ else if (Pred == ICmpInst::ICMP_UGE)
+ Pred = ICmpInst::ICMP_UGT;
+ }
+ unsigned RHSLog2 = RHSV.logBase2();
+
+ // (1 << X) >= 2147483648 -> X >= 31 -> X == 31
+ // (1 << X) > 2147483648 -> X > 31 -> false
+ // (1 << X) <= 2147483648 -> X <= 31 -> true
+ // (1 << X) < 2147483648 -> X < 31 -> X != 31
+ if (RHSLog2 == TypeBits-1) {
+ if (Pred == ICmpInst::ICMP_UGE)
+ Pred = ICmpInst::ICMP_EQ;
+ else if (Pred == ICmpInst::ICMP_UGT)
+ return ReplaceInstUsesWith(ICI, Builder->getFalse());
+ else if (Pred == ICmpInst::ICMP_ULE)
+ return ReplaceInstUsesWith(ICI, Builder->getTrue());
+ else if (Pred == ICmpInst::ICMP_ULT)
+ Pred = ICmpInst::ICMP_NE;
+ }
- uint32_t TypeBits = RHSV.getBitWidth();
+ return new ICmpInst(Pred, X,
+ ConstantInt::get(RHS->getType(), RHSLog2));
+ } else if (ICI.isSigned()) {
+ if (RHSV.isAllOnesValue()) {
+ // (1 << X) <= -1 -> X == 31
+ if (Pred == ICmpInst::ICMP_SLE)
+ return new ICmpInst(ICmpInst::ICMP_EQ, X,
+ ConstantInt::get(RHS->getType(), TypeBits-1));
+
+ // (1 << X) > -1 -> X != 31
+ if (Pred == ICmpInst::ICMP_SGT)
+ return new ICmpInst(ICmpInst::ICMP_NE, X,
+ ConstantInt::get(RHS->getType(), TypeBits-1));
+ } else if (!RHSV) {
+ // (1 << X) < 0 -> X == 31
+ // (1 << X) <= 0 -> X == 31
+ if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE)
+ return new ICmpInst(ICmpInst::ICMP_EQ, X,
+ ConstantInt::get(RHS->getType(), TypeBits-1));
+
+ // (1 << X) >= 0 -> X != 31
+ // (1 << X) > 0 -> X != 31
+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE)
+ return new ICmpInst(ICmpInst::ICMP_NE, X,
+ ConstantInt::get(RHS->getType(), TypeBits-1));
+ }
+ } else if (ICI.isEquality()) {
+ if (RHSVIsPowerOf2)
+ return new ICmpInst(
+ Pred, X, ConstantInt::get(RHS->getType(), RHSV.logBase2()));
+
+ return ReplaceInstUsesWith(
+ ICI, Pred == ICmpInst::ICMP_EQ ? Builder->getFalse()
+ : Builder->getTrue());
+ }
+ }
+ break;
+ }
// Check that the shift amount is in range. If not, don't perform
// undefined shifts. When the shift is visited it will be
OpenPOWER on IntegriCloud