<div dir="ltr"><div>I doubt this sort of code shows up often in the wild but sure, why not. X/INT_MIN now canonicalizes to an icmp instead of an sdiv (as of r212167).</div><div><br></div><div>We now generate the following x86:</div>
<div><div><span class="" style="white-space:pre"> </span>cmpl<span class="" style="white-space:pre">      </span>$-2147483648, %edi</div><div><span class="" style="white-space:pre"> </span>sete<span class="" style="white-space:pre">      </span>%al</div>
<div><span class="" style="white-space:pre">    </span>movzbl<span class="" style="white-space:pre">    </span>%al, %eax<br><br></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jul 1, 2014 at 11:28 PM, Sean Silva <span dir="ltr"><<a href="mailto:chisophugis@gmail.com" target="_blank">chisophugis@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Did you see Stephen Canon's reply in "[LLVMdev] Probable error in InstCombine" about an alternative instcombine for this case? Quoted here for convenience:<div>
<br></div><div><div style="font-family:arial,sans-serif;font-size:13px">
<br><span style="font-family:arial;font-size:small">On Tue, Jul 1, 2014 at 4:59 PM, Stephen Canon </span><span dir="ltr" style="font-family:arial;font-size:small"><<a href="mailto:scanon@apple.com" target="_blank">scanon@apple.com</a>></span><span style="font-family:arial;font-size:small"> wrote:</span><br style="font-family:arial;font-size:small">

<blockquote class="gmail_quote" style="font-family:arial;font-size:small;margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">

<div>Worth noting that if C is INTTYPE_MIN, (X/C) is equivalent to (X == INTTYPE_MIN), and CMP + SETcc/CMOV is generally cheaper than integer division.</div><div><br></div><div>– Steve</div></div></blockquote><span class="HOEnZb"><font color="#888888"><div>
<br></div>
<div>-- Sean Silva </div></font></span></div></div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jul 2, 2014 at 12:07 AM, David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: majnemer<br>
Date: Wed Jul  2 01:07:09 2014<br>
New Revision: 212164<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=212164&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=212164&view=rev</a><br>
Log:<br>
InstCombine: Don't turn -(x/INT_MIN) -> x/INT_MIN<br>
<br>
It is not safe to negate the smallest signed integer, doing so yields<br>
the same number back.<br>
<br>
This fixes PR20186.<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/IR/Constant.h<br>
    llvm/trunk/lib/IR/Constants.cpp<br>
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp<br>
    llvm/trunk/test/Transforms/InstCombine/sub.ll<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Constant.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constant.h?rev=212164&r1=212163&r2=212164&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Constant.h?rev=212164&r1=212163&r2=212164&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/include/llvm/IR/Constant.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Constant.h Wed Jul  2 01:07:09 2014<br>
@@ -64,6 +64,9 @@ public:<br>
   /// Return true if the value is negative zero or null value.<br>
   bool isZeroValue() const;<br>
<br>
+  /// \brief Return true if the value is the smallest signed value.<br>
+  bool isMinSignedValue() const;<br>
+<br>
   /// canTrap - Return true if evaluation of this constant could trap.  This is<br>
   /// true for things like constant expressions that could divide by zero.<br>
   bool canTrap() const;<br>
<br>
Modified: llvm/trunk/lib/IR/Constants.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=212164&r1=212163&r2=212164&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=212164&r1=212163&r2=212164&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/IR/Constants.cpp (original)<br>
+++ llvm/trunk/lib/IR/Constants.cpp Wed Jul  2 01:07:09 2014<br>
@@ -107,6 +107,28 @@ bool Constant::isAllOnesValue() const {<br>
   return false;<br>
 }<br>
<br>
+bool Constant::isMinSignedValue() const {<br>
+  // Check for INT_MIN integers<br>
+  if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))<br>
+    return CI->isMinValue(/*isSigned=*/true);<br>
+<br>
+  // Check for FP which are bitcasted from INT_MIN integers<br>
+  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))<br>
+    return CFP->getValueAPF().bitcastToAPInt().isMinSignedValue();<br>
+<br>
+  // Check for constant vectors which are splats of INT_MIN values.<br>
+  if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))<br>
+    if (Constant *Splat = CV->getSplatValue())<br>
+      return Splat->isMinSignedValue();<br>
+<br>
+  // Check for constant vectors which are splats of INT_MIN values.<br>
+  if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this))<br>
+    if (Constant *Splat = CV->getSplatValue())<br>
+      return Splat->isMinSignedValue();<br>
+<br>
+  return false;<br>
+}<br>
+<br>
 // Constructor to create a '0' constant of arbitrary type...<br>
 Constant *Constant::getNullValue(Type *Ty) {<br>
   switch (Ty->getTypeID()) {<br>
<br>
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=212164&r1=212163&r2=212164&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp?rev=212164&r1=212163&r2=212164&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Wed Jul  2 01:07:09 2014<br>
@@ -1553,9 +1553,9 @@ Instruction *InstCombiner::visitSub(Bina<br>
       return BinaryOperator::CreateAnd(Op0,<br>
                                   Builder->CreateNot(Y, Y->getName() + ".not"));<br>
<br>
-    // 0 - (X sdiv C)  -> (X sdiv -C)<br>
-    if (match(Op1, m_SDiv(m_Value(X), m_Constant(C))) &&<br>
-        match(Op0, m_Zero()))<br>
+    // 0 - (X sdiv C)  -> (X sdiv -C)  provided the negation doesn't overflow.<br>
+    if (match(Op1, m_SDiv(m_Value(X), m_Constant(C))) && match(Op0, m_Zero()) &&<br>
+        !C->isMinSignedValue())<br>
       return BinaryOperator::CreateSDiv(X, ConstantExpr::getNeg(C));<br>
<br>
     // 0 - (X << Y)  -> (-X << Y)   when X is freely negatable.<br>
<br>
Modified: llvm/trunk/test/Transforms/InstCombine/sub.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sub.ll?rev=212164&r1=212163&r2=212164&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sub.ll?rev=212164&r1=212163&r2=212164&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/test/Transforms/InstCombine/sub.ll (original)<br>
+++ llvm/trunk/test/Transforms/InstCombine/sub.ll Wed Jul  2 01:07:09 2014<br>
@@ -444,3 +444,22 @@ define <2 x i64> @test36(<2 x i64> %A) {<br>
 ; CHECK-NEXT: %sub = mul <2 x i64> %A, <i64 7, i64 15><br>
 ; CHECK-NEXT: ret <2 x i64> %sub<br>
 }<br>
+<br>
+define <2 x i64> @test37(<2 x i64> %A) {<br>
+  %shl = shl <2 x i64> %A, <i64 3, i64 4><br>
+  %sub = sub <2 x i64> %shl, %A<br>
+  ret <2 x i64> %sub<br>
+; CHECK-LABEL: @test37(<br>
+; CHECK-NEXT: %sub = mul <2 x i64> %A, <i64 7, i64 15><br>
+; CHECK-NEXT: ret <2 x i64> %sub<br>
+}<br>
+<br>
+define i32 @test38(i32 %A) {<br>
+  %div = sdiv i32 %A, -<a href="tel:2147483648" value="+12147483648" target="_blank">2147483648</a><br>
+  %sub = sub nsw i32 0, %div<br>
+  ret i32 %sub<br>
+; CHECK-LABEL: @test38(<br>
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %A, -<a href="tel:2147483648" value="+12147483648" target="_blank">2147483648</a><br>
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[DIV]]<br>
+; CHECK-NEXT: ret i32 [[SUB]]<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>