LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 20186 - Instcombine turns -(x/INT_MIN) to x/INT_MIN
Summary: Instcombine turns -(x/INT_MIN) to x/INT_MIN
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Transformation Utilities (show other bugs)
Version: trunk
Hardware: All All
: P normal
Assignee: David Majnemer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-01 16:10 PDT by David Menendez
Modified: 2014-07-02 01:08 PDT (History)
6 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description David Menendez 2014-07-01 16:10:04 PDT
The transformation of -(X/C) to X/(-C) is invalid if C == INT_MIN.

Specifically, if I have

define i32 @foo(i32 %x) #0 {
entry:
%div = sdiv i32 %x, -2147483648
%sub = sub nsw i32 0, %div
ret i32 %sub
}

then opt -instcombine will produce

define i32 @foo(i32 %x) #0 {
entry:
%sub = sdiv i32 %x, -2147483648
ret i32 %sub
}


You can observe this with the following test case:

#include <stdio.h>
#include <limits.h>

int foo(int x)
{
return -(x/INT_MIN);
}

int main (void)
{
printf ("%d\n", foo(INT_MIN));
}

This will print -1 or 1, depending on the optimization level.

This appears to be the relevant code:

InstCombineAddSub.cpp:1556
   // 0 - (X sdiv C)  -> (X sdiv -C)
   if (match(Op1, m_SDiv(m_Value(X), m_Constant(C))) &&
       match(Op0, m_Zero()))
     return BinaryOperator::CreateSDiv(X, ConstantExpr::getNeg(C));
Comment 1 John Regehr 2014-07-01 16:14:01 PDT
I checked this against a recent LLVM on x86-64 and believe it is a real bug.
Comment 2 Richard Smith 2014-07-01 20:50:42 PDT
We should transform X/INT_MIN to X==INT_MIN instead.
Comment 3 David Majnemer 2014-07-02 01:08:24 PDT
Fixed in r212164.