From: David Majnemer Date: Fri, 4 Jul 2014 00:23:39 +0000 (+0000) Subject: InstSimplify: Fix a bug when INT_MIN is in a sdiv X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=00428878bb65cbf2c5620bccda19706cec24c6b9;p=oota-llvm.git InstSimplify: Fix a bug when INT_MIN is in a sdiv When INT_MIN is the numerator in a sdiv, we would not properly handle overflow when calculating the bounds of possible values; abs(INT_MIN) is not a meaningful number. Instead, check and handle INT_MIN by reasoning that the largest value is INT_MIN/-2 and the smallest value is INT_MIN. This fixes PR20199. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212307 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 31263bb7de8..bd42af15da3 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -1948,9 +1948,15 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (!CI2->isZero()) Upper = NegOne.udiv(CI2->getValue()) + 1; } else if (match(LHS, m_SDiv(m_ConstantInt(CI2), m_Value()))) { - // 'sdiv CI2, x' produces [-|CI2|, |CI2|]. - Upper = CI2->getValue().abs() + 1; - Lower = (-Upper) + 1; + if (CI2->isMinSignedValue()) { + // 'sdiv INT_MIN, x' produces [INT_MIN, INT_MIN / -2]. + Lower = CI2->getValue(); + Upper = Lower.lshr(1) + 1; + } else { + // 'sdiv CI2, x' produces [-|CI2|, |CI2|]. + Upper = CI2->getValue().abs() + 1; + 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); diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll index 89fd6362d78..7d0cd9c5878 100644 --- a/test/Transforms/InstSimplify/compare.ll +++ b/test/Transforms/InstSimplify/compare.ll @@ -902,3 +902,14 @@ define i1 @icmp_ne_const(i32 %a) nounwind { ; CHECK-LABEL: @icmp_ne_const ; CHECK-NEXT: ret i1 true } + +define i1 @icmp_sdiv_int_min(i32 %a) { + %div = sdiv i32 -2147483648, %a + %cmp = icmp ne i32 %div, -1073741824 + ret i1 %cmp + +; CHECK-LABEL: @icmp_sdiv_int_min +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 -2147483648, %a +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[DIV]], -1073741824 +; CHECK-NEXT: ret i1 [[CMP]] +}