diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-11-05 00:59:59 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-11-05 00:59:59 +0000 |
commit | bf7550e7ecabb10e7a17e6d5067aa8c87810b46b (patch) | |
tree | 2f5168b432205c82ea2c9cecf095f9dfc2a8408b /llvm/lib/Analysis/InstructionSimplify.cpp | |
parent | 629680e499c5df3f8965bfbc5b6100261dce0f5a (diff) | |
download | bcm5719-llvm-bf7550e7ecabb10e7a17e6d5067aa8c87810b46b.tar.gz bcm5719-llvm-bf7550e7ecabb10e7a17e6d5067aa8c87810b46b.zip |
InstSimplify: Exact shifts of X by Y are X if X has the lsb set
Exact shifts may not shift out any non-zero bits. Use computeKnownBits
to determine when this occurs and just return the left hand side.
This fixes PR21477.
llvm-svn: 221325
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 831ff2f09b1..a1b5b462b77 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1328,6 +1328,32 @@ static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1, return nullptr; } +/// \brief Given operands for an Shl, LShr or AShr, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyRightShift(unsigned Opcode, Value *Op0, Value *Op1, + bool isExact, const Query &Q, + unsigned MaxRecurse) { + if (Value *V = SimplifyShift(Opcode, Op0, Op1, Q, MaxRecurse)) + return V; + + // X >> X -> 0 + if (Op0 == Op1) + return Constant::getNullValue(Op0->getType()); + + // The low bit cannot be shifted out of an exact shift if it is set. + if (isExact) { + unsigned BitWidth = Op0->getType()->getScalarSizeInBits(); + APInt Op0KnownZero(BitWidth, 0); + APInt Op0KnownOne(BitWidth, 0); + computeKnownBits(Op0, Op0KnownZero, Op0KnownOne, Q.DL, /*Depth=*/0, Q.AT, Q.CxtI, + Q.DT); + if (Op0KnownOne[0]) + return Op0; + } + + return nullptr; +} + /// SimplifyShlInst - Given operands for an Shl, see if we can /// fold the result. If not, this returns null. static Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, @@ -1358,12 +1384,9 @@ Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, /// fold the result. If not, this returns null. static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, const Query &Q, unsigned MaxRecurse) { - if (Value *V = SimplifyShift(Instruction::LShr, Op0, Op1, Q, MaxRecurse)) - return V; - - // X >> X -> 0 - if (Op0 == Op1) - return Constant::getNullValue(Op0->getType()); + if (Value *V = SimplifyRightShift(Instruction::LShr, Op0, Op1, isExact, Q, + MaxRecurse)) + return V; // undef >>l X -> 0 if (match(Op0, m_Undef())) @@ -1391,13 +1414,10 @@ Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, /// fold the result. If not, this returns null. static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, const Query &Q, unsigned MaxRecurse) { - if (Value *V = SimplifyShift(Instruction::AShr, Op0, Op1, Q, MaxRecurse)) + if (Value *V = SimplifyRightShift(Instruction::AShr, Op0, Op1, isExact, Q, + MaxRecurse)) return V; - // X >> X -> 0 - if (Op0 == Op1) - return Constant::getNullValue(Op0->getType()); - // all ones >>a X -> all ones if (match(Op0, m_AllOnes())) return Op0; |