summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2016-08-26 18:28:46 +0000
committerSanjay Patel <spatel@rotateright.com>2016-08-26 18:28:46 +0000
commit14e0e18d7663ed4b091f9dbe5042701e77700b76 (patch)
tree9ae19dddd592d3b7e8bb0a29a524a9ece5fc0eee /llvm/lib
parentfc670cf6d0cea44f3a5d96baaa4755c07b904987 (diff)
downloadbcm5719-llvm-14e0e18d7663ed4b091f9dbe5042701e77700b76.tar.gz
bcm5719-llvm-14e0e18d7663ed4b091f9dbe5042701e77700b76.zip
[InstCombine] add helper function for icmp (and (sh X, Y), C2), C1 ; NFC
Like other recent changes near here, the goal is to allow vector types for all of these folds. Splitting things up makes it easier to incrementally enhance the code and easier to read. llvm-svn: 279851
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp105
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineInternal.h4
2 files changed, 64 insertions, 45 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index db4c75cd1dc..b0802a32c9b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1389,65 +1389,29 @@ Instruction *InstCombiner::foldICmpXorConstant(ICmpInst &Cmp,
return nullptr;
}
-/// Fold icmp (and X, C2), C1.
-Instruction *InstCombiner::foldICmpAndConstConst(ICmpInst &Cmp,
- BinaryOperator *And,
- const APInt *C1) {
+/// Fold icmp (and (sh X, Y), C2), C1.
+Instruction *InstCombiner::foldICmpAndShift(ICmpInst &Cmp, BinaryOperator *And,
+ const APInt *C1) {
// FIXME: This check restricts all folds under here to scalar types.
ConstantInt *RHS = dyn_cast<ConstantInt>(Cmp.getOperand(1));
if (!RHS)
return nullptr;
+ // FIXME: This could be passed in as APInt.
auto *C2 = dyn_cast<ConstantInt>(And->getOperand(1));
if (!C2)
return nullptr;
- if (!And->hasOneUse() || !And->getOperand(0)->hasOneUse())
- return nullptr;
-
- // If the LHS is an AND of a truncating cast, we can widen the and/compare to
- // be the input width without changing the value produced, eliminating a cast.
- if (TruncInst *Cast = dyn_cast<TruncInst>(And->getOperand(0))) {
- // We can do this transformation if either the AND constant does not have
- // its sign bit set or if it is an equality comparison. Extending a
- // relational comparison when we're checking the sign bit would not work.
- if (Cmp.isEquality() || (!C2->isNegative() && C1->isNonNegative())) {
- Value *NewAnd = Builder->CreateAnd(
- Cast->getOperand(0), ConstantExpr::getZExt(C2, Cast->getSrcTy()));
- NewAnd->takeName(And);
- return new ICmpInst(Cmp.getPredicate(), NewAnd,
- ConstantExpr::getZExt(RHS, Cast->getSrcTy()));
- }
- }
-
- // If the LHS is an AND of a zext, and we have an equality compare, we can
- // shrink the and/compare to the smaller type, eliminating the cast.
- if (ZExtInst *Cast = dyn_cast<ZExtInst>(And->getOperand(0))) {
- IntegerType *Ty = cast<IntegerType>(Cast->getSrcTy());
- // Make sure we don't compare the upper bits, SimplifyDemandedBits
- // should fold the icmp to true/false in that case.
- if (Cmp.isEquality() && C1->getActiveBits() <= Ty->getBitWidth()) {
- Value *NewAnd = Builder->CreateAnd(Cast->getOperand(0),
- ConstantExpr::getTrunc(C2, Ty));
- NewAnd->takeName(And);
- return new ICmpInst(Cmp.getPredicate(), NewAnd,
- ConstantExpr::getTrunc(RHS, Ty));
- }
- }
-
// If this is: (X >> C3) & C2 != C1 (where any shift and any compare could
// exist), turn it into (X & (C2 << C3)) != (C1 << C3). This happens a LOT in
// code produced by the clang front-end, for bitfield access.
BinaryOperator *Shift = dyn_cast<BinaryOperator>(And->getOperand(0));
- if (Shift && !Shift->isShift())
- Shift = nullptr;
-
- ConstantInt *ShAmt;
- ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : nullptr;
+ if (!Shift || !Shift->isShift())
+ return nullptr;
// This seemingly simple opportunity to fold away a shift turns out to be
// rather complicated. See PR17827 for details.
- if (ShAmt) {
+ if (auto *ShAmt = dyn_cast<ConstantInt>(Shift->getOperand(1))) {
bool CanFold = false;
unsigned ShiftOpcode = Shift->getOpcode();
if (ShiftOpcode == Instruction::AShr) {
@@ -1513,7 +1477,7 @@ Instruction *InstCombiner::foldICmpAndConstConst(ICmpInst &Cmp,
// Turn ((X >> Y) & C2) == 0 into (X & (C2 << Y)) == 0. The latter is
// preferable because it allows the C2 << Y expression to be hoisted out of a
// loop if Y is invariant and X is not.
- if (Shift && Shift->hasOneUse() && *C1 == 0 && Cmp.isEquality() &&
+ if (Shift->hasOneUse() && *C1 == 0 && Cmp.isEquality() &&
!Shift->isArithmeticShift() && !isa<Constant>(Shift->getOperand(0))) {
// Compute C2 << Y.
Value *NS;
@@ -1532,6 +1496,59 @@ Instruction *InstCombiner::foldICmpAndConstConst(ICmpInst &Cmp,
return &Cmp;
}
+ return nullptr;
+}
+
+/// Fold icmp (and X, C2), C1.
+Instruction *InstCombiner::foldICmpAndConstConst(ICmpInst &Cmp,
+ BinaryOperator *And,
+ const APInt *C1) {
+ // FIXME: This check restricts all folds under here to scalar types.
+ ConstantInt *RHS = dyn_cast<ConstantInt>(Cmp.getOperand(1));
+ if (!RHS)
+ return nullptr;
+
+ // FIXME: Use m_APInt.
+ auto *C2 = dyn_cast<ConstantInt>(And->getOperand(1));
+ if (!C2)
+ return nullptr;
+
+ if (!And->hasOneUse() || !And->getOperand(0)->hasOneUse())
+ return nullptr;
+
+ // If the LHS is an AND of a truncating cast, we can widen the and/compare to
+ // be the input width without changing the value produced, eliminating a cast.
+ if (TruncInst *Cast = dyn_cast<TruncInst>(And->getOperand(0))) {
+ // We can do this transformation if either the AND constant does not have
+ // its sign bit set or if it is an equality comparison. Extending a
+ // relational comparison when we're checking the sign bit would not work.
+ if (Cmp.isEquality() || (!C2->isNegative() && C1->isNonNegative())) {
+ Value *NewAnd = Builder->CreateAnd(
+ Cast->getOperand(0), ConstantExpr::getZExt(C2, Cast->getSrcTy()));
+ NewAnd->takeName(And);
+ return new ICmpInst(Cmp.getPredicate(), NewAnd,
+ ConstantExpr::getZExt(RHS, Cast->getSrcTy()));
+ }
+ }
+
+ // If the LHS is an AND of a zext, and we have an equality compare, we can
+ // shrink the and/compare to the smaller type, eliminating the cast.
+ if (ZExtInst *Cast = dyn_cast<ZExtInst>(And->getOperand(0))) {
+ IntegerType *Ty = cast<IntegerType>(Cast->getSrcTy());
+ // Make sure we don't compare the upper bits, SimplifyDemandedBits
+ // should fold the icmp to true/false in that case.
+ if (Cmp.isEquality() && C1->getActiveBits() <= Ty->getBitWidth()) {
+ Value *NewAnd = Builder->CreateAnd(Cast->getOperand(0),
+ ConstantExpr::getTrunc(C2, Ty));
+ NewAnd->takeName(And);
+ return new ICmpInst(Cmp.getPredicate(), NewAnd,
+ ConstantExpr::getTrunc(RHS, Ty));
+ }
+ }
+
+ if (Instruction *I = foldICmpAndShift(Cmp, And, C1))
+ return I;
+
// (icmp pred (and (or (lshr A, B), A), 1), 0) -->
// (icmp pred (and A, (or (shl 1, B), 1), 0))
//
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 8619ac6fcf2..91d937c4a15 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -580,7 +580,9 @@ private:
Instruction *foldICmpAddConstant(ICmpInst &Cmp, BinaryOperator *Add,
const APInt *C);
Instruction *foldICmpAndConstConst(ICmpInst &Cmp, BinaryOperator *And,
- const APInt *C);
+ const APInt *C1);
+ Instruction *foldICmpAndShift(ICmpInst &Cmp, BinaryOperator *And,
+ const APInt *C1);
Instruction *foldICmpEqualityWithConstant(ICmpInst &ICI);
Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI);
OpenPOWER on IntegriCloud