[llvm] r212981 - InstSimplify: Correct sdiv x / -1

David Majnemer david.majnemer at gmail.com
Mon Jul 14 13:59:57 PDT 2014


I forgot to give thanks to Richard Smith for finding this bug!

On Mon, Jul 14, 2014 at 1:38 PM, David Majnemer
<david.majnemer at gmail.com> wrote:
> Author: majnemer
> Date: Mon Jul 14 15:38:45 2014
> New Revision: 212981
>
> URL: http://llvm.org/viewvc/llvm-project?rev=212981&view=rev
> Log:
> 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.
>
> Modified:
>     llvm/trunk/lib/Analysis/InstructionSimplify.cpp
>     llvm/trunk/test/Transforms/InstSimplify/compare.ll
>
> Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=212981&r1=212980&r2=212981&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
> +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Mon Jul 14 15:38:45 2014
> @@ -1958,20 +1958,22 @@ static Value *SimplifyICmpInst(unsigned
>          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)))) {
>
> Modified: llvm/trunk/test/Transforms/InstSimplify/compare.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/compare.ll?rev=212981&r1=212980&r2=212981&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstSimplify/compare.ll (original)
> +++ llvm/trunk/test/Transforms/InstSimplify/compare.ll Mon Jul 14 15:38:45 2014
> @@ -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]]
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list