mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
InstSimplify: Correct sdiv x / -1
Determining the bounds of x/ -1 would start off with us dividing it by INT_MIN. Suffice to say, this would not work very well. Instead, handle it upfront by checking for -1 and mapping it to the range: [INT_MIN + 1, INT_MAX. This means that the result of our division can be any value other than INT_MIN. llvm-svn: 212981
This commit is contained in:
parent
21e980408c
commit
6e615bab35
@ -1958,20 +1958,22 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
Lower = (-Upper) + 1;
|
||||
}
|
||||
} else if (match(LHS, m_SDiv(m_Value(), m_ConstantInt(CI2)))) {
|
||||
// 'sdiv x, CI2' produces [INT_MIN / CI2, INT_MAX / CI2].
|
||||
APInt IntMin = APInt::getSignedMinValue(Width);
|
||||
APInt IntMax = APInt::getSignedMaxValue(Width);
|
||||
APInt Val = CI2->getValue().abs();
|
||||
if (!Val.isMinValue()) {
|
||||
APInt Val = CI2->getValue();
|
||||
if (Val.isAllOnesValue()) {
|
||||
// 'sdiv x, -1' produces [INT_MIN + 1, INT_MAX]
|
||||
// where CI2 != -1 and CI2 != 0 and CI2 != 1
|
||||
Lower = IntMin + 1;
|
||||
Upper = IntMax + 1;
|
||||
} else if (Val.countLeadingZeros() < Width - 1) {
|
||||
// 'sdiv x, CI2' produces [INT_MIN / CI2, INT_MAX / CI2]
|
||||
// where CI2 != -1 and CI2 != 0 and CI2 != 1
|
||||
Lower = IntMin.sdiv(Val);
|
||||
APInt Rem;
|
||||
APInt::sdivrem(IntMax, Val, Upper, Rem);
|
||||
// We may need to round the result of the INT_MAX / CI2 calculation up
|
||||
// if we see that the division was not exact.
|
||||
if (Rem.isMinValue())
|
||||
Upper = Upper + 1;
|
||||
else
|
||||
Upper = Upper + 2;
|
||||
Upper = IntMax.sdiv(Val);
|
||||
if (Lower.sgt(Upper))
|
||||
std::swap(Lower, Upper);
|
||||
Upper = Upper + 1;
|
||||
assert(Upper != Lower && "Upper part of range has wrapped!");
|
||||
}
|
||||
} else if (match(LHS, m_LShr(m_Value(), m_ConstantInt(CI2)))) {
|
||||
|
@ -924,3 +924,14 @@ define i1 @icmp_sdiv_pr20288(i64 %a) {
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[DIV]], 1073741824
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
}
|
||||
|
||||
define i1 @icmp_sdiv_neg1(i64 %a) {
|
||||
%div = sdiv i64 %call, -1
|
||||
%cmp = icmp ne i64 %div, 1073741824
|
||||
ret i1 %cmp
|
||||
|
||||
; CHECK-LABEL: @icmp_sdiv_neg1
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv i64 %a, -1
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[DIV]], 1073741824
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user