summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-02-13 22:24:37 +0000
committerSanjay Patel <spatel@rotateright.com>2018-02-13 22:24:37 +0000
commit7558d860af88bde4b860d9f66fd0281a331db345 (patch)
tree527c3c11d3199e193dca4ff61893ea5d6093eac9 /llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
parentb42495468250e7887b3273100299190a70fab9ce (diff)
downloadbcm5719-llvm-7558d860af88bde4b860d9f66fd0281a331db345.tar.gz
bcm5719-llvm-7558d860af88bde4b860d9f66fd0281a331db345.zip
[InstCombine] (lshr X, 31) * Y --> (ashr X, 31) & Y
This replaces the bit-tracking based fold that did the same thing, but it only worked for scalars and not directly. There is no evidence in existing regression tests that the greater power of bit-tracking was needed here, but we should be aware of this potential loss of optimization. llvm-svn: 325062
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp38
1 files changed, 13 insertions, 25 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 27f2a6dbc4e..f6907841016 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -340,37 +340,25 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
}
}
- Value *X;
// (bool X) * Y --> X ? Y : 0
+ // Y * (bool X) --> X ? Y : 0
+ Value *X;
if (match(Op0, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
return SelectInst::Create(X, Op1, ConstantInt::get(I.getType(), 0));
-
- // Y * (bool X) --> X ? Y : 0
if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
return SelectInst::Create(X, Op0, ConstantInt::get(I.getType(), 0));
- // If one of the operands of the multiply is a cast from a boolean value, then
- // we know the bool is either zero or one, so this is a 'masking' multiply.
- // X * Y (where Y is 0 or 1) -> X & (0-Y)
- if (!I.getType()->isVectorTy()) {
- // -2 is "-1 << 1" so it is all bits set except the low one.
- APInt Negative2(I.getType()->getPrimitiveSizeInBits(), (uint64_t)-2, true);
-
- Value *BoolCast = nullptr, *OtherOp = nullptr;
- if (MaskedValueIsZero(Op0, Negative2, 0, &I)) {
- BoolCast = Op0;
- OtherOp = Op1;
- } else if (MaskedValueIsZero(Op1, Negative2, 0, &I)) {
- BoolCast = Op1;
- OtherOp = Op0;
- }
-
- if (BoolCast) {
- Value *V = Builder.CreateSub(Constant::getNullValue(I.getType()),
- BoolCast);
- return BinaryOperator::CreateAnd(V, OtherOp);
- }
- }
+ // (lshr X, 31) * Y --> (ashr X, 31) & Y
+ // Y * (lshr X, 31) --> (ashr X, 31) & Y
+ // TODO: We are not checking one-use because the elimination of the multiply
+ // is better for analysis?
+ // TODO: Should we canonicalize to '(X < 0) ? Y : 0' instead? That would be
+ // more similar to what we're doing above.
+ const APInt *C;
+ if (match(Op0, m_LShr(m_Value(X), m_APInt(C))) && *C == C->getBitWidth() - 1)
+ return BinaryOperator::CreateAnd(Builder.CreateAShr(X, *C), Op1);
+ if (match(Op1, m_LShr(m_Value(X), m_APInt(C))) && *C == C->getBitWidth() - 1)
+ return BinaryOperator::CreateAnd(Builder.CreateAShr(X, *C), Op0);
// Check for (mul (sext x), y), see if we can merge this into an
// integer mul followed by a sext.
OpenPOWER on IntegriCloud