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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221325 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2014-11-05 00:59:59 +00:00
parent 4cd064b8e8
commit 49c14f54b2
2 changed files with 45 additions and 11 deletions

View File

@ -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;

View File

@ -330,3 +330,17 @@ define i1 @exact_lshr_ne_noexactlog(i8 %a) {
%cmp = icmp ne i8 %shr, 30
ret i1 %cmp
}
; CHECK-LABEL: @exact_lshr_lowbit
; CHECK-NEXT: ret i32 7
define i32 @exact_lshr_lowbit(i32 %shiftval) {
%shr = lshr exact i32 7, %shiftval
ret i32 %shr
}
; CHECK-LABEL: @exact_ashr_lowbit
; CHECK-NEXT: ret i32 7
define i32 @exact_ashr_lowbit(i32 %shiftval) {
%shr = ashr exact i32 7, %shiftval
ret i32 %shr
}