diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-02-13 22:24:37 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-02-13 22:24:37 +0000 |
commit | 7558d860af88bde4b860d9f66fd0281a331db345 (patch) | |
tree | 527c3c11d3199e193dca4ff61893ea5d6093eac9 /llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | |
parent | b42495468250e7887b3273100299190a70fab9ce (diff) | |
download | bcm5719-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.cpp | 38 |
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. |