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));
I checked this against a recent LLVM on x86-64 and believe it is a real bug.
We should transform X/INT_MIN to X==INT_MIN instead.
Fixed in r212164.