From af9180fd0409431ce1a05f69212483a4d1c5c6c0 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 14 Jul 2014 20:38:45 +0000 Subject: [PATCH] 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 --- llvm/lib/Analysis/InstructionSimplify.cpp | 24 +++++++++++++----------- llvm/test/Transforms/InstSimplify/compare.ll | 11 +++++++++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 1054c79..fd7a4de 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -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)))) { diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll index d329b7b..1a9f82e 100644 --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -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]] +} -- 2.7.4