mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
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:
parent
4cd064b8e8
commit
49c14f54b2
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user