<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[194802] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/194802">194802</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-01-08 16:01:55 -0800 (Fri, 08 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>B3 needs Neg()
https://bugs.webkit.org/show_bug.cgi?id=152925

Reviewed by Mark Lam.

Previously we said that negation should be represented as Sub(0, x). That's wrong, since
for floats, Sub(0, 0) == 0 while Neg(0) == -0.

One way to solve this would be to say that anyone trying to say Neg(x) where x is a float
should instead say BitXor(x, -0). That's actually correct, but I think that it would be odd
to use bitops to represent floating point operations. Whatever cuteness this would have
bought us would be outweighed by the annoyance of having to write code that matches
Sub(0, x) for integer negation and BitXor(x, -0) for double negation. For example, this
would mean strictly more code for anyone implementing a Neg(Neg(x))=&gt;x strength reduction.
Also, I suspect that the omission of Neg would cause others to make the mistake of using
Sub to represent floating point negation.

So, this introduces a proper Neg() opcode to B3. It's now the canonical way of saying
negation for both ints and floats. For ints, we canonicalize Sub(0, x) to Neg(x). For
floats, we lower it to BitXor(x, -0) on x86.

This reduces the number of failures from 13 to 12.

* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::andFloat):
(JSC::MacroAssemblerX86Common::xorDouble):
(JSC::MacroAssemblerX86Common::xorFloat):
(JSC::MacroAssemblerX86Common::convertInt32ToDouble):
* b3/B3LowerMacrosAfterOptimizations.cpp:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/air/AirOpcode.opcodes:
* ftl/FTLB3Output.cpp:
(JSC::FTL::Output::lockedStackSlot):
(JSC::FTL::Output::neg):
(JSC::FTL::Output::bitNot):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::chillDiv):
(JSC::FTL::Output::mod):
(JSC::FTL::Output::chillMod):
(JSC::FTL::Output::doubleAdd):
(JSC::FTL::Output::doubleSub):
(JSC::FTL::Output::doubleMul):
(JSC::FTL::Output::doubleDiv):
(JSC::FTL::Output::doubleMod):
(JSC::FTL::Output::doubleNeg):
(JSC::FTL::Output::bitAnd):
(JSC::FTL::Output::bitOr):
(JSC::FTL::Output::neg): Deleted.
* tests/stress/ftl-negate-zero.js: Added. This was already covered by op_negate but since
it's such a glaring bug, I thought having a test for it specifically would be good.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerMacrosAfterOptimizationscpp">trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerToAircpp">trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Opcodecpp">trunk/Source/JavaScriptCore/b3/B3Opcode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Opcodeh">trunk/Source/JavaScriptCore/b3/B3Opcode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp">trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Validatecpp">trunk/Source/JavaScriptCore/b3/B3Validate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Valuecpp">trunk/Source/JavaScriptCore/b3/B3Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOpcodeopcodes">trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputcpp">trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputh">trunk/Source/JavaScriptCore/ftl/FTLB3Output.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlnegatezerojs">trunk/Source/JavaScriptCore/tests/stress/ftl-negate-zero.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1,5 +1,68 @@
</span><span class="cx"> 2016-01-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        B3 needs Neg()
+        https://bugs.webkit.org/show_bug.cgi?id=152925
+
+        Reviewed by Mark Lam.
+
+        Previously we said that negation should be represented as Sub(0, x). That's wrong, since
+        for floats, Sub(0, 0) == 0 while Neg(0) == -0.
+
+        One way to solve this would be to say that anyone trying to say Neg(x) where x is a float
+        should instead say BitXor(x, -0). That's actually correct, but I think that it would be odd
+        to use bitops to represent floating point operations. Whatever cuteness this would have
+        bought us would be outweighed by the annoyance of having to write code that matches
+        Sub(0, x) for integer negation and BitXor(x, -0) for double negation. For example, this
+        would mean strictly more code for anyone implementing a Neg(Neg(x))=&gt;x strength reduction.
+        Also, I suspect that the omission of Neg would cause others to make the mistake of using
+        Sub to represent floating point negation.
+
+        So, this introduces a proper Neg() opcode to B3. It's now the canonical way of saying
+        negation for both ints and floats. For ints, we canonicalize Sub(0, x) to Neg(x). For
+        floats, we lower it to BitXor(x, -0) on x86.
+
+        This reduces the number of failures from 13 to 12.
+
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::andFloat):
+        (JSC::MacroAssemblerX86Common::xorDouble):
+        (JSC::MacroAssemblerX86Common::xorFloat):
+        (JSC::MacroAssemblerX86Common::convertInt32ToDouble):
+        * b3/B3LowerMacrosAfterOptimizations.cpp:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/air/AirOpcode.opcodes:
+        * ftl/FTLB3Output.cpp:
+        (JSC::FTL::Output::lockedStackSlot):
+        (JSC::FTL::Output::neg):
+        (JSC::FTL::Output::bitNot):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::chillDiv):
+        (JSC::FTL::Output::mod):
+        (JSC::FTL::Output::chillMod):
+        (JSC::FTL::Output::doubleAdd):
+        (JSC::FTL::Output::doubleSub):
+        (JSC::FTL::Output::doubleMul):
+        (JSC::FTL::Output::doubleDiv):
+        (JSC::FTL::Output::doubleMod):
+        (JSC::FTL::Output::doubleNeg):
+        (JSC::FTL::Output::bitAnd):
+        (JSC::FTL::Output::bitOr):
+        (JSC::FTL::Output::neg): Deleted.
+        * tests/stress/ftl-negate-zero.js: Added. This was already covered by op_negate but since
+        it's such a glaring bug, I thought having a test for it specifically would be good.
+
+2016-01-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         FTL B3 compile() doesn't clear exception handlers before we add FTL-specific ones
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=152922
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2014-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2014-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -1082,6 +1082,16 @@
</span><span class="cx">         m_assembler.andps_rr(src, dst);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void xorDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.xorps_rr(src, dst);
+    }
+
+    void xorFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.xorps_rr(src, dst);
+    }
+
</ins><span class="cx">     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerMacrosAfterOptimizationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -108,6 +108,27 @@
</span><span class="cx">                 m_value-&gt;replaceWithIdentity(result);
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+            case Neg: {
+                if (!isFloat(m_value-&gt;type()))
+                    break;
+                
+                // X86 is odd in that it requires this.
+                if (!isX86())
+                    break;
+
+                Value* mask = nullptr;
+                if (m_value-&gt;type() == Double)
+                    mask = m_insertionSet.insert&lt;ConstDoubleValue&gt;(m_index, m_origin, -0.0);
+                else {
+                    RELEASE_ASSERT(m_value-&gt;type() == Float);
+                    mask = m_insertionSet.insert&lt;ConstFloatValue&gt;(m_index, m_origin, -0.0f);
+                }
+
+                Value* result = m_insertionSet.insert&lt;Value&gt;(
+                    m_index, BitXor, m_origin, m_value-&gt;child(0), mask);
+                m_value-&gt;replaceWithIdentity(result);
+                break;
+            }
</ins><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1612,13 +1612,15 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Sub: {
</span><del>-            if (m_value-&gt;child(0)-&gt;isInt(0))
-                appendUnOp&lt;Neg32, Neg64&gt;(m_value-&gt;child(1));
-            else
-                appendBinOp&lt;Sub32, Sub64, SubDouble, SubFloat&gt;(m_value-&gt;child(0), m_value-&gt;child(1));
</del><ins>+            appendBinOp&lt;Sub32, Sub64, SubDouble, SubFloat&gt;(m_value-&gt;child(0), m_value-&gt;child(1));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case Neg: {
+            appendUnOp&lt;Neg32, Neg64, NegateDouble, Air::Oops&gt;(m_value-&gt;child(0));
+            return;
+        }
+
</ins><span class="cx">         case Mul: {
</span><span class="cx">             appendBinOp&lt;Mul32, Mul64, MulDouble, MulFloat, Commutative&gt;(
</span><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="lines">@@ -1682,7 +1684,7 @@
</span><span class="cx">                 appendUnOp&lt;Not32, Not64&gt;(m_value-&gt;child(0));
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><del>-            appendBinOp&lt;Xor32, Xor64, Commutative&gt;(
</del><ins>+            appendBinOp&lt;Xor32, Xor64, XorDouble, XorFloat, Commutative&gt;(
</ins><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="cx">             return;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Opcodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Opcode.cpp (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -119,6 +119,9 @@
</span><span class="cx">     case Mod:
</span><span class="cx">         out.print(&quot;Mod&quot;);
</span><span class="cx">         return;
</span><ins>+    case Neg:
+        out.print(&quot;Neg&quot;);
+        return;
</ins><span class="cx">     case ChillDiv:
</span><span class="cx">         out.print(&quot;ChillDiv&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Opcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Opcode.h (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.h        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.h        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -73,6 +73,11 @@
</span><span class="cx">     Div, // All bets are off as to what will happen when you execute this for -2^31/-1 and x/0.
</span><span class="cx">     Mod, // All bets are off as to what will happen when you execute this for -2^31%-1 and x%0.
</span><span class="cx"> 
</span><ins>+    // Polymorphic negation. Note that we only need this for floating point, since integer negation
+    // is exactly like Sub(0, x). But that's not true for floating point. Sub(0, 0) is 0, while
+    // Neg(0) is -0. Also, we canonicalize Sub(0, x) into Neg(x) in case of integers.
+    Neg,
+
</ins><span class="cx">     // Integer math.
</span><span class="cx">     ChillDiv, // doesn't trap ever, behaves like JS (x/y)|0.
</span><span class="cx">     ChillMod, // doesn't trap ever, behaves like JS (x%y)|0.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -213,19 +213,44 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            // Turn this: Sub(value, constant)
-            // Into this: Add(value, -constant)
</del><span class="cx">             if (isInt(m_value-&gt;type())) {
</span><ins>+                // Turn this: Sub(value, constant)
+                // Into this: Add(value, -constant)
</ins><span class="cx">                 if (Value* negatedConstant = m_value-&gt;child(1)-&gt;negConstant(m_proc)) {
</span><span class="cx">                     m_insertionSet.insertValue(m_index, negatedConstant);
</span><span class="cx">                     replaceWithNew&lt;Value&gt;(
</span><span class="cx">                         Add, m_value-&gt;origin(), m_value-&gt;child(0), negatedConstant);
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><ins>+                
+                // Turn this: Sub(0, value)
+                // Into this: Neg(value)
+                if (m_value-&gt;child(0)-&gt;isInt(0)) {
+                    replaceWithNew&lt;Value&gt;(Neg, m_value-&gt;origin(), m_value-&gt;child(1));
+                    break;
+                }
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             break;
</span><span class="cx"> 
</span><ins>+        case Neg:
+            // Turn this: Neg(constant)
+            // Into this: -constant
+            if (Value* constant = m_value-&gt;child(0)-&gt;negConstant(m_proc)) {
+                replaceWithNewValue(constant);
+                break;
+            }
+            
+            // Turn this: Neg(Neg(value))
+            // Into this: value
+            if (m_value-&gt;child(0)-&gt;opcode() == Neg) {
+                m_value-&gt;replaceWithIdentity(m_value-&gt;child(0)-&gt;child(0));
+                m_changed = true;
+                break;
+            }
+            
+            break;
+
</ins><span class="cx">         case Mul:
</span><span class="cx">             handleCommutativity();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Validatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Validate.cpp (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -169,15 +169,20 @@
</span><span class="cx">             case Div:
</span><span class="cx">             case Mod:
</span><span class="cx">             case BitAnd:
</span><ins>+            case BitXor:
</ins><span class="cx">                 VALIDATE(value-&gt;numChildren() == 2, (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() == value-&gt;child(0)-&gt;type(), (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() == value-&gt;child(1)-&gt;type(), (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() != Void, (&quot;At &quot;, *value));
</span><span class="cx">                 break;
</span><ins>+            case Neg:
+                VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
+                VALIDATE(value-&gt;type() == value-&gt;child(0)-&gt;type(), (&quot;At &quot;, *value));
+                VALIDATE(value-&gt;type() != Void, (&quot;At &quot;, *value));
+                break;
</ins><span class="cx">             case ChillDiv:
</span><span class="cx">             case ChillMod:
</span><span class="cx">             case BitOr:
</span><del>-            case BitXor:
</del><span class="cx">                 VALIDATE(value-&gt;numChildren() == 2, (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() == value-&gt;child(0)-&gt;type(), (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() == value-&gt;child(1)-&gt;type(), (&quot;At &quot;, *value));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.cpp (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.cpp        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/B3Value.cpp        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -365,6 +365,7 @@
</span><span class="cx">     case Add:
</span><span class="cx">     case Sub:
</span><span class="cx">     case Mul:
</span><ins>+    case Neg:
</ins><span class="cx">     case ChillDiv:
</span><span class="cx">     case ChillMod:
</span><span class="cx">     case BitAnd:
</span><span class="lines">@@ -468,6 +469,7 @@
</span><span class="cx">     case DoubleToFloat:
</span><span class="cx">     case Check:
</span><span class="cx">     case BitwiseCast:
</span><ins>+    case Neg:
</ins><span class="cx">         return ValueKey(opcode(), type(), child(0));
</span><span class="cx">     case Add:
</span><span class="cx">     case Sub:
</span><span class="lines">@@ -553,6 +555,7 @@
</span><span class="cx">     case Mul:
</span><span class="cx">     case Div:
</span><span class="cx">     case Mod:
</span><ins>+    case Neg:
</ins><span class="cx">     case ChillDiv:
</span><span class="cx">     case ChillMod:
</span><span class="cx">     case BitAnd:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -177,6 +177,9 @@
</span><span class="cx"> 64: Neg64 UD:G:64
</span><span class="cx">     Tmp
</span><span class="cx"> 
</span><ins>+arm64: NegateDouble U:F:64, D:F:64
+    Tmp, Tmp
+
</ins><span class="cx"> Mul32 U:G:32, UZD:G:32
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     x86: Addr, Tmp
</span><span class="lines">@@ -253,6 +256,12 @@
</span><span class="cx"> x86: AndFloat U:F:32, UD:F:32
</span><span class="cx">     Tmp, Tmp
</span><span class="cx"> 
</span><ins>+x86: XorDouble U:F:64, UD:F:64
+    Tmp, Tmp
+
+x86: XorFloat U:F:32, UD:F:32
+    Tmp, Tmp
+
</ins><span class="cx"> arm64: Lshift32 U:G:32, U:G:32, ZD:G:32
</span><span class="cx">     Tmp, Tmp, Tmp
</span><span class="cx">     Tmp, Imm, Tmp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -67,6 +67,11 @@
</span><span class="cx">     return m_block-&gt;appendNew&lt;StackSlotValue&gt;(m_proc, origin(), bytes, StackSlotKind::Locked);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+LValue Output::neg(LValue value)
+{
+    return m_block-&gt;appendNew&lt;Value&gt;(m_proc, B3::Neg, origin(), value);
+}
+
</ins><span class="cx"> LValue Output::bitNot(LValue value)
</span><span class="cx"> {
</span><span class="cx">     return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::BitXor, origin(),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.h (194801 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2016-01-08 23:50:28 UTC (rev 194801)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -130,21 +130,14 @@
</span><span class="cx">     LValue chillDiv(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::ChillDiv, origin(), left, right); }
</span><span class="cx">     LValue mod(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Mod, origin(), left, right); }
</span><span class="cx">     LValue chillMod(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::ChillMod, origin(), left, right); }
</span><del>-    LValue neg(LValue value)
-    {
-        LValue zero = m_block-&gt;appendIntConstant(m_proc, origin(), value-&gt;type(), 0);
-        return sub(zero, value);
-    }
</del><ins>+    LValue neg(LValue);
</ins><span class="cx"> 
</span><span class="cx">     LValue doubleAdd(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Add, origin(), left, right); }
</span><span class="cx">     LValue doubleSub(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Sub, origin(), left, right); }
</span><span class="cx">     LValue doubleMul(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Mul, origin(), left, right); }
</span><span class="cx">     LValue doubleDiv(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Div, origin(), left, right); }
</span><span class="cx">     LValue doubleMod(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Mod, origin(), left, right); }
</span><del>-    LValue doubleNeg(LValue value)
-    {
-        return sub(doubleZero, value);
-    }
</del><ins>+    LValue doubleNeg(LValue value) { return neg(value); }
</ins><span class="cx"> 
</span><span class="cx">     LValue bitAnd(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::BitAnd, origin(), left, right); }
</span><span class="cx">     LValue bitOr(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::BitOr, origin(), left, right); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlnegatezerojs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-negate-zero.js (0 => 194802)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-negate-zero.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-negate-zero.js        2016-01-09 00:01:55 UTC (rev 194802)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+function foo(x) {
+    return -x;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(0);
+    if (1 / result != &quot;-Infinity&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>