1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

InstSimplify: Improve handling of ashr/lshr

Summary:
Analyze the range of values produced by ashr/lshr cst, %V when it is
being used in an icmp.

Reviewers: nicholas

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D3774

llvm-svn: 209000
This commit is contained in:
David Majnemer 2014-05-16 17:14:03 +00:00
parent 186633e0f8
commit ef2cb1fc63
2 changed files with 61 additions and 1 deletions

View File

@ -2001,7 +2001,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
// Many binary operators with constant RHS have easy to compute constant
// range. Use them to check whether the comparison is a tautology.
uint32_t Width = CI->getBitWidth();
unsigned Width = CI->getBitWidth();
APInt Lower = APInt(Width, 0);
APInt Upper = APInt(Width, 0);
ConstantInt *CI2;
@ -2038,6 +2038,13 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
APInt NegOne = APInt::getAllOnesValue(Width);
if (CI2->getValue().ult(Width))
Upper = NegOne.lshr(CI2->getValue()) + 1;
} else if (match(LHS, m_LShr(m_ConstantInt(CI2), m_Value()))) {
// 'lshr CI2, x' produces [CI2 >> (Width-1), CI2].
unsigned ShiftAmount = Width - 1;
if (!CI2->isZero() && cast<BinaryOperator>(LHS)->isExact())
ShiftAmount = CI2->getValue().countTrailingZeros();
Lower = CI2->getValue().lshr(ShiftAmount);
Upper = CI2->getValue() + 1;
} else if (match(LHS, m_AShr(m_Value(), m_ConstantInt(CI2)))) {
// 'ashr x, CI2' produces [INT_MIN >> CI2, INT_MAX >> CI2].
APInt IntMin = APInt::getSignedMinValue(Width);
@ -2046,6 +2053,19 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
Lower = IntMin.ashr(CI2->getValue());
Upper = IntMax.ashr(CI2->getValue()) + 1;
}
} else if (match(LHS, m_AShr(m_ConstantInt(CI2), m_Value()))) {
unsigned ShiftAmount = Width - 1;
if (!CI2->isZero() && cast<BinaryOperator>(LHS)->isExact())
ShiftAmount = CI2->getValue().countTrailingZeros();
if (CI2->isNegative()) {
// 'ashr CI2, x' produces [CI2, CI2 >> (Width-1)]
Lower = CI2->getValue();
Upper = CI2->getValue().ashr(ShiftAmount) + 1;
} else {
// 'ashr CI2, x' produces [CI2 >> (Width-1), CI2]
Lower = CI2->getValue().ashr(ShiftAmount);
Upper = CI2->getValue() + 1;
}
} else if (match(LHS, m_Or(m_Value(), m_ConstantInt(CI2)))) {
// 'or x, CI2' produces [CI2, UINT_MAX].
Lower = CI2->getValue();

View File

@ -826,3 +826,43 @@ define i1 @compare_dividend(i32 %a) {
; CHECK-LABEL: @compare_dividend
; CHECK-NEXT: ret i1 false
}
define i1 @lshr_ugt_false(i32 %a) {
%shr = lshr i32 1, %a
%cmp = icmp ugt i32 %shr, 1
ret i1 %cmp
; CHECK-LABEL: @lshr_ugt_false
; CHECK-NEXT: ret i1 false
}
define i1 @exact_lshr_ugt_false(i32 %a) {
%shr = lshr exact i32 30, %a
%cmp = icmp ult i32 %shr, 15
ret i1 %cmp
; CHECK-LABEL: @exact_lshr_ugt_false
; CHECK-NEXT: ret i1 false
}
define i1 @lshr_sgt_false(i32 %a) {
%shr = lshr i32 1, %a
%cmp = icmp sgt i32 %shr, 1
ret i1 %cmp
; CHECK-LABEL: @lshr_sgt_false
; CHECK-NEXT: ret i1 false
}
define i1 @ashr_sgt_false(i32 %a) {
%shr = ashr i32 -30, %a
%cmp = icmp sgt i32 %shr, -1
ret i1 %cmp
; CHECK-LABEL: @ashr_sgt_false
; CHECK-NEXT: ret i1 false
}
define i1 @exact_ashr_sgt_false(i32 %a) {
%shr = ashr exact i32 -30, %a
%cmp = icmp sgt i32 %shr, -15
ret i1 %cmp
; CHECK-LABEL: @exact_ashr_sgt_false
; CHECK-NEXT: ret i1 false
}