<!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>[193933] 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/193933">193933</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-12-10 16:31:51 -0800 (Thu, 10 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Add a Modulo operator to B3, and a chill variant
https://bugs.webkit.org/show_bug.cgi?id=152110

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2015-12-10
Reviewed by Geoffrey Garen.

It is basically refactoring the Div and ChillDiv
code to be used by both opcodes.

* b3/B3Common.h:
(JSC::B3::chillDiv):
(JSC::B3::chillMod):
* b3/B3Const32Value.cpp:
(JSC::B3::Const32Value::modConstant):
* b3/B3Const32Value.h:
* b3/B3Const64Value.cpp:
(JSC::B3::Const64Value::modConstant):
* b3/B3Const64Value.h:
* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::modConstant):
* b3/B3ConstDoubleValue.h:
* b3/B3LowerMacros.cpp:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
(JSC::B3::Air::LowerToAir::lowerX86Div):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::modConstant):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/testb3.cpp:
(JSC::B3::testModArgDouble):
(JSC::B3::testModArgsDouble):
(JSC::B3::testModArgImmDouble):
(JSC::B3::testModImmArgDouble):
(JSC::B3::testModImmsDouble):
(JSC::B3::testModArgFloat):
(JSC::B3::testModArgsFloat):
(JSC::B3::testModArgImmFloat):
(JSC::B3::testModImmArgFloat):
(JSC::B3::testModImmsFloat):
(JSC::B3::testModArg):
(JSC::B3::testModArgs):
(JSC::B3::testModImms):
(JSC::B3::testModArg32):
(JSC::B3::testModArgs32):
(JSC::B3::testModImms32):
(JSC::B3::testChillModArg):
(JSC::B3::testChillModArgs):
(JSC::B3::testChillModImms):
(JSC::B3::testChillModArg32):
(JSC::B3::testChillModArgs32):
(JSC::B3::testChillModImms32):
(JSC::B3::run):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::mod):
(JSC::FTL::Output::chillMod):
(JSC::FTL::Output::doubleMod):
(JSC::FTL::Output::rem): Deleted.
(JSC::FTL::Output::doubleRem): Deleted.
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithMod):
* ftl/FTLOutput.cpp:
(JSC::FTL::Output::chillMod):
* ftl/FTLOutput.h:
(JSC::FTL::Output::mod):
(JSC::FTL::Output::doubleMod):
(JSC::FTL::Output::rem): Deleted.
(JSC::FTL::Output::doubleRem): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Commonh">trunk/Source/JavaScriptCore/b3/B3Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const32Valuecpp">trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const32Valueh">trunk/Source/JavaScriptCore/b3/B3Const32Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const64Valuecpp">trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const64Valueh">trunk/Source/JavaScriptCore/b3/B3Const64Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstDoubleValuecpp">trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstDoubleValueh">trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerMacroscpp">trunk/Source/JavaScriptCore/b3/B3LowerMacros.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="#trunkSourceJavaScriptCoreb3B3Valueh">trunk/Source/JavaScriptCore/b3/B3Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputh">trunk/Source/JavaScriptCore/ftl/FTLB3Output.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputcpp">trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputh">trunk/Source/JavaScriptCore/ftl/FTLOutput.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -1,3 +1,80 @@
</span><ins>+2015-12-10  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Add a Modulo operator to B3, and a chill variant
+        https://bugs.webkit.org/show_bug.cgi?id=152110
+
+        Reviewed by Geoffrey Garen.
+
+        It is basically refactoring the Div and ChillDiv
+        code to be used by both opcodes.
+
+        * b3/B3Common.h:
+        (JSC::B3::chillDiv):
+        (JSC::B3::chillMod):
+        * b3/B3Const32Value.cpp:
+        (JSC::B3::Const32Value::modConstant):
+        * b3/B3Const32Value.h:
+        * b3/B3Const64Value.cpp:
+        (JSC::B3::Const64Value::modConstant):
+        * b3/B3Const64Value.h:
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::modConstant):
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3LowerMacros.cpp:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        (JSC::B3::Air::LowerToAir::lowerX86Div):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::modConstant):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/testb3.cpp:
+        (JSC::B3::testModArgDouble):
+        (JSC::B3::testModArgsDouble):
+        (JSC::B3::testModArgImmDouble):
+        (JSC::B3::testModImmArgDouble):
+        (JSC::B3::testModImmsDouble):
+        (JSC::B3::testModArgFloat):
+        (JSC::B3::testModArgsFloat):
+        (JSC::B3::testModArgImmFloat):
+        (JSC::B3::testModImmArgFloat):
+        (JSC::B3::testModImmsFloat):
+        (JSC::B3::testModArg):
+        (JSC::B3::testModArgs):
+        (JSC::B3::testModImms):
+        (JSC::B3::testModArg32):
+        (JSC::B3::testModArgs32):
+        (JSC::B3::testModImms32):
+        (JSC::B3::testChillModArg):
+        (JSC::B3::testChillModArgs):
+        (JSC::B3::testChillModImms):
+        (JSC::B3::testChillModArg32):
+        (JSC::B3::testChillModArgs32):
+        (JSC::B3::testChillModImms32):
+        (JSC::B3::run):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::mod):
+        (JSC::FTL::Output::chillMod):
+        (JSC::FTL::Output::doubleMod):
+        (JSC::FTL::Output::rem): Deleted.
+        (JSC::FTL::Output::doubleRem): Deleted.
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMod):
+        * ftl/FTLOutput.cpp:
+        (JSC::FTL::Output::chillMod):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::mod):
+        (JSC::FTL::Output::doubleMod):
+        (JSC::FTL::Output::rem): Deleted.
+        (JSC::FTL::Output::doubleRem): Deleted.
+
</ins><span class="cx"> 2015-12-10  Csaba Osztrogonác  &lt;ossy@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [B3] Add new files to the cmake build system
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Common.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Common.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Common.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -94,22 +94,24 @@
</span><span class="cx">     return isRepresentableAsImpl&lt;ResultType, double, int64_t&gt;(value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline int32_t chillDiv(int32_t num, int32_t den)
</del><ins>+template&lt;typename IntType&gt;
+static IntType chillDiv(IntType numerator, IntType denominator)
</ins><span class="cx"> {
</span><del>-    if (!den)
</del><ins>+    if (!denominator)
</ins><span class="cx">         return 0;
</span><del>-    if (den == -1 &amp;&amp; num == std::numeric_limits&lt;int32_t&gt;::min())
-        return num;
-    return num / den;
</del><ins>+    if (denominator == -1 &amp;&amp; numerator == std::numeric_limits&lt;IntType&gt;::min())
+        return std::numeric_limits&lt;IntType&gt;::min();
+    return numerator / denominator;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline int64_t chillDiv(int64_t num, int64_t den)
</del><ins>+template&lt;typename IntType&gt;
+static IntType chillMod(IntType numerator, IntType denominator)
</ins><span class="cx"> {
</span><del>-    if (!den)
</del><ins>+    if (!denominator)
</ins><span class="cx">         return 0;
</span><del>-    if (den == -1 &amp;&amp; num == std::numeric_limits&lt;int64_t&gt;::min())
-        return num;
-    return num / den;
</del><ins>+    if (denominator == -1 &amp;&amp; numerator == std::numeric_limits&lt;IntType&gt;::min())
+        return 0;
+    return numerator % denominator;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const32Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -112,6 +112,13 @@
</span><span class="cx">     return proc.add&lt;Const32Value&gt;(origin(), chillDiv(m_value, other-&gt;asInt32()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* Const32Value::modConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasInt32())
+        return nullptr;
+    return proc.add&lt;Const32Value&gt;(origin(), chillMod(m_value, other-&gt;asInt32()));
+}
+
</ins><span class="cx"> Value* Const32Value::bitAndConstant(Procedure&amp; proc, const Value* other) const
</span><span class="cx"> {
</span><span class="cx">     if (!other-&gt;hasInt32())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const32Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const32Value.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const32Value.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Const32Value.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx">     Value* checkMulConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* checkNegConstant(Procedure&amp;) const override;
</span><span class="cx">     Value* divConstant(Procedure&amp;, const Value* other) const override;
</span><ins>+    Value* modConstant(Procedure&amp;, const Value* other) const override;
</ins><span class="cx">     Value* bitAndConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* bitOrConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* bitXorConstant(Procedure&amp;, const Value* other) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const64Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -112,6 +112,13 @@
</span><span class="cx">     return proc.add&lt;Const64Value&gt;(origin(), chillDiv(m_value, other-&gt;asInt64()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* Const64Value::modConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasInt64())
+        return nullptr;
+    return proc.add&lt;Const64Value&gt;(origin(), chillMod(m_value, other-&gt;asInt64()));
+}
+
</ins><span class="cx"> Value* Const64Value::bitAndConstant(Procedure&amp; proc, const Value* other) const
</span><span class="cx"> {
</span><span class="cx">     if (!other-&gt;hasInt64())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const64Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const64Value.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const64Value.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Const64Value.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx">     Value* checkMulConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* checkNegConstant(Procedure&amp;) const override;
</span><span class="cx">     Value* divConstant(Procedure&amp;, const Value* other) const override;
</span><ins>+    Value* modConstant(Procedure&amp;, const Value* other) const override;
</ins><span class="cx">     Value* bitAndConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* bitOrConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* bitXorConstant(Procedure&amp;, const Value* other) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -91,6 +91,13 @@
</span><span class="cx">     return proc.add&lt;ConstDoubleValue&gt;(origin(), m_value / other-&gt;asDouble());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* ConstDoubleValue::modConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasDouble())
+        return nullptr;
+    return proc.add&lt;ConstDoubleValue&gt;(origin(), fmod(m_value, other-&gt;asDouble()));
+}
+
</ins><span class="cx"> TriState ConstDoubleValue::equalConstant(const Value* other) const
</span><span class="cx"> {
</span><span class="cx">     if (!other-&gt;hasDouble())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx">     Value* addConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* subConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* divConstant(Procedure&amp;, const Value* other) const override;
</span><ins>+    Value* modConstant(Procedure&amp;, const Value* other) const override;
</ins><span class="cx">     Value* mulConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* bitwiseCastConstant(Procedure&amp;) const override;
</span><span class="cx">     Value* doubleToFloatConstant(Procedure&amp;) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerMacroscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerMacros.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerMacros.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3LowerMacros.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3BasicBlockInlines.h&quot;
</span><span class="cx"> #include &quot;B3BlockInsertionSet.h&quot;
</span><ins>+#include &quot;B3CCallValue.h&quot;
+#include &quot;B3ConstPtrValue.h&quot;
</ins><span class="cx"> #include &quot;B3ControlValue.h&quot;
</span><span class="cx"> #include &quot;B3InsertionSetInlines.h&quot;
</span><span class="cx"> #include &quot;B3PhaseScope.h&quot;
</span><span class="lines">@@ -37,6 +39,7 @@
</span><span class="cx"> #include &quot;B3SwitchValue.h&quot;
</span><span class="cx"> #include &quot;B3UpsilonValue.h&quot;
</span><span class="cx"> #include &quot;B3ValueInlines.h&quot;
</span><ins>+#include &lt;cmath&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><span class="lines">@@ -72,105 +75,36 @@
</span><span class="cx">             m_value = m_block-&gt;at(m_index);
</span><span class="cx">             m_origin = m_value-&gt;origin();
</span><span class="cx">             switch (m_value-&gt;opcode()) {
</span><ins>+            case Mod: {
+                if (m_value-&gt;type() == Double) {
+                    Value* functionAddress = m_insertionSet.insert&lt;ConstPtrValue&gt;(m_index, m_origin, fmod);
+                    Value* result = m_insertionSet.insert&lt;CCallValue&gt;(m_index, Double, m_origin,
+                        Effects::none(),
+                        functionAddress,
+                        m_value-&gt;child(0),
+                        m_value-&gt;child(1));
+                    m_value-&gt;replaceWithIdentity(result);
+                } else if (m_value-&gt;type() == Float) {
+                    Value* numeratorAsDouble = m_insertionSet.insert&lt;Value&gt;(m_index, FloatToDouble, m_origin, m_value-&gt;child(0));
+                    Value* denominatorAsDouble = m_insertionSet.insert&lt;Value&gt;(m_index, FloatToDouble, m_origin, m_value-&gt;child(1));
+                    Value* functionAddress = m_insertionSet.insert&lt;ConstPtrValue&gt;(m_index, m_origin, fmod);
+                    Value* doubleMod = m_insertionSet.insert&lt;CCallValue&gt;(m_index, Double, m_origin,
+                        Effects::none(),
+                        functionAddress,
+                        numeratorAsDouble,
+                        denominatorAsDouble);
+                    Value* result = m_insertionSet.insert&lt;Value&gt;(m_index, DoubleToFloat, m_origin, doubleMod);
+                    m_value-&gt;replaceWithIdentity(result);
+                }
+                break;
+            }
</ins><span class="cx">             case ChillDiv: {
</span><del>-                // ARM supports this instruction natively.
-                if (isARM64())
-                    break;
</del><ins>+                makeDivisionChill(Div);
+                break;
+            }
</ins><span class="cx"> 
</span><del>-                m_changed = true;
-
-                // We implement &quot;res = ChillDiv(num, den)&quot; as follows:
-                //
-                //     if (den + 1 &lt;=_unsigned 1) {
-                //         if (!den) {
-                //             res = 0;
-                //             goto done;
-                //         }
-                //         if (num == -2147483648) {
-                //             res = num;
-                //             goto done;
-                //         }
-                //     }
-                //     res = num / dev;
-                // done:
-
-                Value* num = m_value-&gt;child(0);
-                Value* den = m_value-&gt;child(1);
-
-                Value* one =
-                    m_insertionSet.insertIntConstant(m_index, m_value, 1);
-                Value* isDenOK = m_insertionSet.insert&lt;Value&gt;(
-                    m_index, Above, m_origin,
-                    m_insertionSet.insert&lt;Value&gt;(m_index, Add, m_origin, den, one),
-                    one);
-
-                BasicBlock* before =
-                    m_blockInsertionSet.splitForward(m_block, m_index, &amp;m_insertionSet);
-
-                BasicBlock* normalDivCase = m_blockInsertionSet.insertBefore(m_block);
-                BasicBlock* shadyDenCase = m_blockInsertionSet.insertBefore(m_block);
-                BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
-                BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block);
-                BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block);
-
-                before-&gt;replaceLastWithNew&lt;ControlValue&gt;(
-                    m_proc, Branch, m_origin, isDenOK,
-                    FrequentedBlock(normalDivCase, FrequencyClass::Normal),
-                    FrequentedBlock(shadyDenCase, FrequencyClass::Rare));
-
-                UpsilonValue* normalResult = normalDivCase-&gt;appendNew&lt;UpsilonValue&gt;(
-                    m_proc, m_origin,
-                    normalDivCase-&gt;appendNew&lt;Value&gt;(m_proc, Div, m_origin, num, den));
-                normalDivCase-&gt;appendNew&lt;ControlValue&gt;(
-                    m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
-                shadyDenCase-&gt;appendNew&lt;ControlValue&gt;(
-                    m_proc, Branch, m_origin, den,
-                    FrequentedBlock(neg1DenCase, FrequencyClass::Normal),
-                    FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
-
-                UpsilonValue* zeroResult = zeroDenCase-&gt;appendNew&lt;UpsilonValue&gt;(
-                    m_proc, m_origin,
-                    zeroDenCase-&gt;appendIntConstant(m_proc, m_value, 0));
-                zeroDenCase-&gt;appendNew&lt;ControlValue&gt;(
-                    m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
-                int64_t badNumeratorConst;
-                switch (m_value-&gt;type()) {
-                case Int32:
-                    badNumeratorConst = std::numeric_limits&lt;int32_t&gt;::min();
-                    break;
-                case Int64:
-                    badNumeratorConst = std::numeric_limits&lt;int64_t&gt;::min();
-                    break;
-                default:
-                    ASSERT_NOT_REACHED();
-                    badNumeratorConst = 0;
-                }
-
-                Value* badNumerator =
-                    neg1DenCase-&gt;appendIntConstant(m_proc, m_value, badNumeratorConst);
-
-                neg1DenCase-&gt;appendNew&lt;ControlValue&gt;(
-                    m_proc, Branch, m_origin,
-                    neg1DenCase-&gt;appendNew&lt;Value&gt;(
-                        m_proc, Equal, m_origin, num, badNumerator),
-                    FrequentedBlock(intMinCase, FrequencyClass::Rare),
-                    FrequentedBlock(normalDivCase, FrequencyClass::Normal));
-
-                UpsilonValue* intMinResult = intMinCase-&gt;appendNew&lt;UpsilonValue&gt;(
-                    m_proc, m_origin, badNumerator);
-                intMinCase-&gt;appendNew&lt;ControlValue&gt;(
-                    m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
-                Value* phi = m_insertionSet.insert&lt;Value&gt;(
-                    m_index, Phi, m_value-&gt;type(), m_origin);
-                normalResult-&gt;setPhi(phi);
-                zeroResult-&gt;setPhi(phi);
-                intMinResult-&gt;setPhi(phi);
-
-                m_value-&gt;replaceWithIdentity(phi);
-                before-&gt;updatePredecessorsAfter();
</del><ins>+            case ChillMod: {
+                makeDivisionChill(Mod);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -199,6 +133,108 @@
</span><span class="cx">         m_insertionSet.execute(m_block);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void makeDivisionChill(Opcode nonChillOpcode)
+    {
+        ASSERT(nonChillOpcode == Div || nonChillOpcode == Mod);
+
+        // ARM supports this instruction natively.
+        if (isARM64())
+            return;
+
+        // We implement &quot;res = ChillDiv/ChillMod(num, den)&quot; as follows:
+        //
+        //     if (den + 1 &lt;=_unsigned 1) {
+        //         if (!den) {
+        //             res = 0;
+        //             goto done;
+        //         }
+        //         if (num == -2147483648) {
+        //             res = isDiv ? num : 0;
+        //             goto done;
+        //         }
+        //     }
+        //     res = num (/ or %) dev;
+        // done:
+        m_changed = true;
+
+        Value* num = m_value-&gt;child(0);
+        Value* den = m_value-&gt;child(1);
+
+        Value* one = m_insertionSet.insertIntConstant(m_index, m_value, 1);
+        Value* isDenOK = m_insertionSet.insert&lt;Value&gt;(
+            m_index, Above, m_origin,
+            m_insertionSet.insert&lt;Value&gt;(m_index, Add, m_origin, den, one),
+            one);
+
+        BasicBlock* before = m_blockInsertionSet.splitForward(m_block, m_index, &amp;m_insertionSet);
+
+        BasicBlock* normalDivCase = m_blockInsertionSet.insertBefore(m_block);
+        BasicBlock* shadyDenCase = m_blockInsertionSet.insertBefore(m_block);
+        BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
+        BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block);
+        BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block);
+
+        before-&gt;replaceLastWithNew&lt;ControlValue&gt;(
+            m_proc, Branch, m_origin, isDenOK,
+            FrequentedBlock(normalDivCase, FrequencyClass::Normal),
+            FrequentedBlock(shadyDenCase, FrequencyClass::Rare));
+
+        UpsilonValue* normalResult = normalDivCase-&gt;appendNew&lt;UpsilonValue&gt;(
+            m_proc, m_origin,
+            normalDivCase-&gt;appendNew&lt;Value&gt;(m_proc, nonChillOpcode, m_origin, num, den));
+        normalDivCase-&gt;appendNew&lt;ControlValue&gt;(
+            m_proc, Jump, m_origin, FrequentedBlock(m_block));
+
+        shadyDenCase-&gt;appendNew&lt;ControlValue&gt;(
+            m_proc, Branch, m_origin, den,
+            FrequentedBlock(neg1DenCase, FrequencyClass::Normal),
+            FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
+
+        UpsilonValue* zeroResult = zeroDenCase-&gt;appendNew&lt;UpsilonValue&gt;(
+            m_proc, m_origin,
+            zeroDenCase-&gt;appendIntConstant(m_proc, m_value, 0));
+        zeroDenCase-&gt;appendNew&lt;ControlValue&gt;(
+            m_proc, Jump, m_origin, FrequentedBlock(m_block));
+
+        int64_t badNumeratorConst = 0;
+        switch (m_value-&gt;type()) {
+        case Int32:
+            badNumeratorConst = std::numeric_limits&lt;int32_t&gt;::min();
+            break;
+        case Int64:
+            badNumeratorConst = std::numeric_limits&lt;int64_t&gt;::min();
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+            badNumeratorConst = 0;
+        }
+
+        Value* badNumerator =
+            neg1DenCase-&gt;appendIntConstant(m_proc, m_value, badNumeratorConst);
+
+        neg1DenCase-&gt;appendNew&lt;ControlValue&gt;(
+            m_proc, Branch, m_origin,
+            neg1DenCase-&gt;appendNew&lt;Value&gt;(
+                m_proc, Equal, m_origin, num, badNumerator),
+            FrequentedBlock(intMinCase, FrequencyClass::Rare),
+            FrequentedBlock(normalDivCase, FrequencyClass::Normal));
+
+        Value* intMinResult = nonChillOpcode == Div ? badNumerator : intMinCase-&gt;appendIntConstant(m_proc, m_value, 0);
+        UpsilonValue* intMinResultUpsilon = intMinCase-&gt;appendNew&lt;UpsilonValue&gt;(
+            m_proc, m_origin, intMinResult);
+        intMinCase-&gt;appendNew&lt;ControlValue&gt;(
+            m_proc, Jump, m_origin, FrequentedBlock(m_block));
+
+        Value* phi = m_insertionSet.insert&lt;Value&gt;(
+            m_index, Phi, m_value-&gt;type(), m_origin);
+        normalResult-&gt;setPhi(phi);
+        zeroResult-&gt;setPhi(phi);
+        intMinResultUpsilon-&gt;setPhi(phi);
+
+        m_value-&gt;replaceWithIdentity(phi);
+        before-&gt;updatePredecessorsAfter();
+    }
+
</ins><span class="cx">     void recursivelyBuildSwitch(
</span><span class="cx">         const Vector&lt;SwitchCase&gt;&amp; cases, unsigned start, bool hardStart, unsigned end,
</span><span class="cx">         BasicBlock* before)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -1441,29 +1441,8 @@
</span><span class="cx"> 
</span><span class="cx">         case Div: {
</span><span class="cx">             if (isInt(m_value-&gt;type())) {
</span><del>-                Tmp eax = Tmp(X86Registers::eax);
-                Tmp edx = Tmp(X86Registers::edx);
-
-                Air::Opcode convertToDoubleWord;
-                Air::Opcode div;
-                switch (m_value-&gt;type()) {
-                case Int32:
-                    convertToDoubleWord = X86ConvertToDoubleWord32;
-                    div = X86Div32;
-                    break;
-                case Int64:
-                    convertToDoubleWord = X86ConvertToQuadWord64;
-                    div = X86Div64;
-                    break;
-                default:
-                    RELEASE_ASSERT_NOT_REACHED();
-                    return;
-                }
-                
-                append(Move, tmp(m_value-&gt;child(0)), eax);
-                append(convertToDoubleWord, eax, edx);
-                append(div, eax, edx, tmp(m_value-&gt;child(1)));
-                append(Move, eax, tmp(m_value));
</del><ins>+                lowerX86Div();
+                append(Move, Tmp(X86Registers::eax), tmp(m_value));
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx">             ASSERT(isFloat(m_value-&gt;type()));
</span><span class="lines">@@ -1472,6 +1451,12 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case Mod: {
+            lowerX86Div();
+            append(Move, Tmp(X86Registers::edx), tmp(m_value));
+            return;
+        }
+
</ins><span class="cx">         case BitAnd: {
</span><span class="cx">             appendBinOp&lt;And32, And64, Commutative&gt;(
</span><span class="cx">                 m_value-&gt;child(0), m_value-&gt;child(1));
</span><span class="lines">@@ -1977,6 +1962,32 @@
</span><span class="cx">         dataLog(&quot;FATAL: could not lower &quot;, deepDump(m_value), &quot;\n&quot;);
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><ins>+
+    void lowerX86Div()
+    {
+        Tmp eax = Tmp(X86Registers::eax);
+        Tmp edx = Tmp(X86Registers::edx);
+
+        Air::Opcode convertToDoubleWord;
+        Air::Opcode div;
+        switch (m_value-&gt;type()) {
+        case Int32:
+            convertToDoubleWord = X86ConvertToDoubleWord32;
+            div = X86Div32;
+            break;
+        case Int64:
+            convertToDoubleWord = X86ConvertToQuadWord64;
+            div = X86Div64;
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+        
+        append(Move, tmp(m_value-&gt;child(0)), eax);
+        append(convertToDoubleWord, eax, edx);
+        append(div, eax, edx, tmp(m_value-&gt;child(1)));
+    }
</ins><span class="cx">     
</span><span class="cx">     IndexSet&lt;Value&gt; m_locked; // These are values that will have no Tmp in Air.
</span><span class="cx">     IndexMap&lt;Value, Tmp&gt; m_valueToTmp; // These are values that must have a Tmp in Air. We say that a Value* with a non-null Tmp is &quot;pinned&quot;.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Opcodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Opcode.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -116,11 +116,14 @@
</span><span class="cx">     case Div:
</span><span class="cx">         out.print(&quot;Div&quot;);
</span><span class="cx">         return;
</span><ins>+    case Mod:
+        out.print(&quot;Mod&quot;);
+        return;
</ins><span class="cx">     case ChillDiv:
</span><span class="cx">         out.print(&quot;ChillDiv&quot;);
</span><span class="cx">         return;
</span><del>-    case Mod:
-        out.print(&quot;Mod&quot;);
</del><ins>+    case ChillMod:
+        out.print(&quot;ChillMod&quot;);
</ins><span class="cx">         return;
</span><span class="cx">     case BitAnd:
</span><span class="cx">         out.print(&quot;BitAnd&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Opcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Opcode.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -71,10 +71,11 @@
</span><span class="cx">     Sub,
</span><span class="cx">     Mul,
</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><ins>+    Mod, // All bets are off as to what will happen when you execute this for -2^31%-1 and x%0.
</ins><span class="cx"> 
</span><span class="cx">     // Integer math.
</span><span class="cx">     ChillDiv, // doesn't trap ever, behaves like JS (x/y)|0.
</span><del>-    Mod,
</del><ins>+    ChillMod, // doesn't trap ever, behaves like JS (x%y)|0.
</ins><span class="cx">     BitAnd,
</span><span class="cx">     BitOr,
</span><span class="cx">     BitXor,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -291,6 +291,11 @@
</span><span class="cx">             replaceWithNewValue(m_value-&gt;child(0)-&gt;divConstant(m_proc, m_value-&gt;child(1)));
</span><span class="cx">             break;
</span><span class="cx"> 
</span><ins>+        case Mod:
+        case ChillMod:
+            replaceWithNewValue(m_value-&gt;child(0)-&gt;modConstant(m_proc, m_value-&gt;child(1)));
+            break;
+
</ins><span class="cx">         case BitAnd:
</span><span class="cx">             handleCommutativity();
</span><span class="cx"> 
</span><span class="lines">@@ -658,7 +663,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             // Turn this: Load(constant1, offset = constant2)
</span><del>-            // Into this: Laod(constant1 + constant2)
</del><ins>+            // Into this: Load(constant1 + constant2)
</ins><span class="cx">             //
</span><span class="cx">             // This is a fun canonicalization. It purely regresses naively generated code. We rely
</span><span class="cx">             // on constant materialization to be smart enough to materialize this constant the smart
</span><span class="lines">@@ -677,6 +682,18 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case CCall:
+            // Turn this: Call(fmod, constant1, constant2)
+            // Into this: fcall-constant(constant1, constant2)
+            if (m_value-&gt;type() == Double
+                &amp;&amp; m_value-&gt;numChildren() == 3
+                &amp;&amp; m_value-&gt;child(0)-&gt;isIntPtr(reinterpret_cast&lt;intptr_t&gt;(fmod))
+                &amp;&amp; m_value-&gt;child(1)-&gt;type() == Double
+                &amp;&amp; m_value-&gt;child(2)-&gt;type() == Double) {
+                replaceWithNewValue(m_value-&gt;child(1)-&gt;modConstant(m_proc, m_value-&gt;child(2)));
+            }
+            break;
+
</ins><span class="cx">         case Equal:
</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 (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -153,13 +153,14 @@
</span><span class="cx">             case Sub:
</span><span class="cx">             case Mul:
</span><span class="cx">             case Div:
</span><ins>+            case Mod:
</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><span class="cx">             case ChillDiv:
</span><del>-            case Mod:
</del><ins>+            case ChillMod:
</ins><span class="cx">             case BitAnd:
</span><span class="cx">             case BitOr:
</span><span class="cx">             case BitXor:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -164,6 +164,11 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* Value::modConstant(Procedure&amp;, const Value*) const
+{
+    return nullptr;
+}
+
</ins><span class="cx"> Value* Value::bitAndConstant(Procedure&amp;, const Value*) const
</span><span class="cx"> {
</span><span class="cx">     return nullptr;
</span><span class="lines">@@ -337,7 +342,7 @@
</span><span class="cx">     case Sub:
</span><span class="cx">     case Mul:
</span><span class="cx">     case ChillDiv:
</span><del>-    case Mod:
</del><ins>+    case ChillMod:
</ins><span class="cx">     case BitAnd:
</span><span class="cx">     case BitOr:
</span><span class="cx">     case BitXor:
</span><span class="lines">@@ -369,6 +374,7 @@
</span><span class="cx">     case Select:
</span><span class="cx">         break;
</span><span class="cx">     case Div:
</span><ins>+    case Mod:
</ins><span class="cx">         result.controlDependent = true;
</span><span class="cx">         break;
</span><span class="cx">     case Load8Z:
</span><span class="lines">@@ -436,8 +442,10 @@
</span><span class="cx">     case Add:
</span><span class="cx">     case Sub:
</span><span class="cx">     case Mul:
</span><ins>+    case Div:
+    case Mod:
</ins><span class="cx">     case ChillDiv:
</span><del>-    case Mod:
</del><ins>+    case ChillMod:
</ins><span class="cx">     case BitAnd:
</span><span class="cx">     case BitOr:
</span><span class="cx">     case BitXor:
</span><span class="lines">@@ -452,7 +460,6 @@
</span><span class="cx">     case Below:
</span><span class="cx">     case AboveEqual:
</span><span class="cx">     case BelowEqual:
</span><del>-    case Div:
</del><span class="cx">     case CheckAdd:
</span><span class="cx">     case CheckSub:
</span><span class="cx">     case CheckMul:
</span><span class="lines">@@ -514,8 +521,9 @@
</span><span class="cx">     case Sub:
</span><span class="cx">     case Mul:
</span><span class="cx">     case Div:
</span><ins>+    case Mod:
</ins><span class="cx">     case ChillDiv:
</span><del>-    case Mod:
</del><ins>+    case ChillMod:
</ins><span class="cx">     case BitAnd:
</span><span class="cx">     case BitOr:
</span><span class="cx">     case BitXor:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/B3Value.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -121,6 +121,7 @@
</span><span class="cx">     virtual Value* checkMulConstant(Procedure&amp;, const Value* other) const;
</span><span class="cx">     virtual Value* checkNegConstant(Procedure&amp;) const;
</span><span class="cx">     virtual Value* divConstant(Procedure&amp;, const Value* other) const; // This chooses ChillDiv semantics for integers.
</span><ins>+    virtual Value* modConstant(Procedure&amp;, const Value* other) const; // This chooses ChillMod semantics for integers.
</ins><span class="cx">     virtual Value* bitAndConstant(Procedure&amp;, const Value* other) const;
</span><span class="cx">     virtual Value* bitOrConstant(Procedure&amp;, const Value* other) const;
</span><span class="cx">     virtual Value* bitXorConstant(Procedure&amp;, const Value* other) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -1027,6 +1027,145 @@
</span><span class="cx">     CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc), bitwise_cast&lt;int32_t&gt;(a / b)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testModArgDouble(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* value = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), value, value));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a), fmod(a, a)));
+}
+
+void testModArgsDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* valueA = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* valueB = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR1);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), valueA, valueB));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a, b), fmod(a, b)));
+}
+
+void testModArgImmDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* valueA = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* valueB = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), b);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), valueA, valueB));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a), fmod(a, b)));
+}
+
+void testModImmArgDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* valueA = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), a);
+    Value* valueB = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), valueA, valueB));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, b), fmod(a, b)));
+}
+
+void testModImmsDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* valueA = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), a);
+    Value* valueB = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), b);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), valueA, valueB));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), fmod(a, b)));
+}
+
+void testModArgFloat(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), floatValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fmod(a, a)))));
+}
+
+void testModArgsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2int32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* floatValue1 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument1int32);
+    Value* floatValue2 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument2int32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), floatValue1, floatValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fmod(a, b)))));
+}
+
+void testModArgImmFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), floatValue, constValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fmod(a, b)))));
+}
+
+void testModImmArgFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* constValue = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), constValue, floatValue);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(b)), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fmod(a, b)))));
+}
+
+void testModImmsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* constValue1 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* constValue2 = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), constValue1, constValue2);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), result);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fmod(a, b)))));
+}
+
</ins><span class="cx"> void testDivArgFloatWithUselessDoubleConversion(float a)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -6300,6 +6439,190 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testModArg(int64_t value)
+{
+    if (!value)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), argument, argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(!compileAndRun&lt;int64_t&gt;(proc, value));
+}
+
+void testModArgs(int64_t numerator, int64_t denominator)
+{
+    if (!denominator)
+        return;
+    if (numerator == std::numeric_limits&lt;int64_t&gt;::min() &amp;&amp; denominator == -1)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argument2 = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int64_t&gt;(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testModImms(int64_t numerator, int64_t denominator)
+{
+    if (!denominator)
+        return;
+    if (numerator == std::numeric_limits&lt;int64_t&gt;::min() &amp;&amp; denominator == -1)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;Const64Value&gt;(proc, Origin(), numerator);
+    Value* argument2 = root-&gt;appendNew&lt;Const64Value&gt;(proc, Origin(), denominator);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int64_t&gt;(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testModArg32(int32_t value)
+{
+    if (!value)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), argument, argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(!compileAndRun&lt;int32_t&gt;(proc, value));
+}
+
+void testModArgs32(int32_t numerator, int32_t denominator)
+{
+    if (!denominator)
+        return;
+    if (numerator == std::numeric_limits&lt;int32_t&gt;::min() &amp;&amp; denominator == -1)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int32_t&gt;(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testModImms32(int32_t numerator, int32_t denominator)
+{
+    if (!denominator)
+        return;
+    if (numerator == std::numeric_limits&lt;int32_t&gt;::min() &amp;&amp; denominator == -1)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), numerator);
+    Value* argument2 = root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), denominator);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Mod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int32_t&gt;(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testChillModArg(int64_t value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, ChillMod, Origin(), argument, argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(!compileAndRun&lt;int64_t&gt;(proc, value));
+}
+
+void testChillModArgs(int64_t numerator, int64_t denominator)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argument2 = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, ChillMod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int64_t&gt;(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
+void testChillModImms(int64_t numerator, int64_t denominator)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;Const64Value&gt;(proc, Origin(), numerator);
+    Value* argument2 = root-&gt;appendNew&lt;Const64Value&gt;(proc, Origin(), denominator);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, ChillMod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int64_t&gt;(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
+void testChillModArg32(int32_t value)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, ChillMod, Origin(), argument, argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(!compileAndRun&lt;int32_t&gt;(proc, value));
+}
+
+void testChillModArgs32(int32_t numerator, int32_t denominator)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, ChillMod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int32_t&gt;(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
+void testChillModImms32(int32_t numerator, int32_t denominator)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* argument1 = root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), numerator);
+    Value* argument2 = root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), denominator);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, ChillMod, Origin(), argument1, argument2);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(compileAndRun&lt;int32_t&gt;(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
</ins><span class="cx"> void testSwitch(unsigned degree, unsigned gap = 1)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -7059,6 +7382,17 @@
</span><span class="cx">     RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</span><span class="cx">     RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</span><span class="cx"> 
</span><ins>+    RUN_UNARY(testModArgDouble, floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testModArgsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testModArgImmDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testModImmArgDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testModImmsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testModArgFloat, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testModArgsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testModArgImmFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testModImmArgFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testModImmsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+
</ins><span class="cx">     RUN(testSubArg(24));
</span><span class="cx">     RUN(testSubArgs(1, 1));
</span><span class="cx">     RUN(testSubArgs(1, 2));
</span><span class="lines">@@ -7633,6 +7967,19 @@
</span><span class="cx">     RUN(testChillDivTwice(4, 0, 6, 2, 3));
</span><span class="cx">     RUN(testChillDivTwice(4, 2, 6, 0, 2));
</span><span class="cx"> 
</span><ins>+    RUN_UNARY(testModArg, int64Operands());
+    RUN_BINARY(testModArgs, int64Operands(), int64Operands());
+    RUN_BINARY(testModImms, int64Operands(), int64Operands());
+    RUN_UNARY(testModArg32, int32Operands());
+    RUN_BINARY(testModArgs32, int32Operands(), int32Operands());
+    RUN_BINARY(testModImms32, int32Operands(), int32Operands());
+    RUN_UNARY(testChillModArg, int64Operands());
+    RUN_BINARY(testChillModArgs, int64Operands(), int64Operands());
+    RUN_BINARY(testChillModImms, int64Operands(), int64Operands());
+    RUN_UNARY(testChillModArg32, int32Operands());
+    RUN_BINARY(testChillModArgs32, int32Operands(), int32Operands());
+    RUN_BINARY(testChillModImms32, int32Operands(), int32Operands());
+
</ins><span class="cx">     RUN(testSwitch(0, 1));
</span><span class="cx">     RUN(testSwitch(1, 1));
</span><span class="cx">     RUN(testSwitch(2, 1));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -128,7 +128,8 @@
</span><span class="cx">     LValue mul(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 div(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 chillDiv(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::ChillDiv, origin(), left, right); }
</span><del>-    LValue rem(LValue left, LValue right) { CRASH(); }
</del><ins>+    LValue mod(LValue left, LValue right) { m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Mod, origin(), left, right); }
+    LValue chillMod(LValue left, LValue right) { m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::ChillMod, origin(), left, right); }
</ins><span class="cx">     LValue neg(LValue value)
</span><span class="cx">     {
</span><span class="cx">         LValue zero = m_block-&gt;appendIntConstant(m_proc, origin(), value-&gt;type(), 0);
</span><span class="lines">@@ -139,7 +140,7 @@
</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><del>-    LValue doubleRem(LValue left, LValue right) { return callWithoutSideEffects(B3::Double, fmod, left, right); }
</del><ins>+    LValue doubleMod(LValue left, LValue right) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Mod, origin(), left, right); }
</ins><span class="cx">     LValue doubleNeg(LValue value)
</span><span class="cx">     {
</span><span class="cx">         return sub(doubleZero, value);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -2025,89 +2025,53 @@
</span><span class="cx">         case Int32Use: {
</span><span class="cx">             LValue numerator = lowInt32(m_node-&gt;child1());
</span><span class="cx">             LValue denominator = lowInt32(m_node-&gt;child2());
</span><del>-            
-            LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, (&quot;ArithMod unsafe denominator&quot;));
-            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;ArithMod continuation&quot;));
-            LBasicBlock done = FTL_NEW_BLOCK(m_out, (&quot;ArithMod done&quot;));
-            
-            Vector&lt;ValueFromBlock, 3&gt; results;
-            
-            LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
-            
-            m_out.branch(
-                m_out.above(adjustedDenominator, m_out.int32One),
-                usually(continuation), rarely(unsafeDenominator));
-            
-            LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
-            
-            LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
-            
-            // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
-            // separate case for that. But it probably doesn't matter so much.
</del><ins>+
+            LValue remainder;
</ins><span class="cx">             if (shouldCheckOverflow(m_node-&gt;arithMode())) {
</span><ins>+                LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, (&quot;ArithMod unsafe denominator&quot;));
+                LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;ArithMod continuation&quot;));
+
+                LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
+                m_out.branch(
+                    m_out.above(adjustedDenominator, m_out.int32One),
+                    usually(continuation), rarely(unsafeDenominator));
+
+                LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
+                LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
</ins><span class="cx">                 LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
</span><span class="cx">                 speculate(Overflow, noValue(), 0, cond);
</span><span class="cx">                 m_out.jump(continuation);
</span><del>-            } else {
-                // This is the case where we convert the result to an int after we're done. So,
-                // if the denominator is zero, then the result should be result should be zero.
-                // If the denominator is not zero (i.e. it's -1 because we're guarded by the
-                // check above) and the numerator is -2^31 then the result should be -2^31.
-                
-                LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, (&quot;ArithMod modulo by zero&quot;));
-                LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, (&quot;ArithMod not modulo by zero&quot;));
-                LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, (&quot;ArithMod -2^31/-1&quot;));
-                
-                m_out.branch(
-                    m_out.isZero32(denominator), rarely(modByZero), usually(notModByZero));
-                
-                m_out.appendTo(modByZero, notModByZero);
-                results.append(m_out.anchor(m_out.int32Zero));
-                m_out.jump(done);
-                
-                m_out.appendTo(notModByZero, neg2ToThe31ByNeg1);
-                m_out.branch(
-                    m_out.equal(numerator, neg2ToThe31),
-                    rarely(neg2ToThe31ByNeg1), usually(continuation));
-                
-                m_out.appendTo(neg2ToThe31ByNeg1, continuation);
-                results.append(m_out.anchor(m_out.int32Zero));
-                m_out.jump(done);
-            }
-            
-            m_out.appendTo(continuation, done);
-            
-            LValue remainder = m_out.rem(numerator, denominator);
-            
</del><ins>+
+                m_out.appendTo(continuation, lastNext);
+                LValue result = m_out.mod(numerator, denominator);
+                remainder = result;
+            } else
+                remainder = m_out.chillMod(numerator, denominator);
+
</ins><span class="cx">             if (shouldCheckNegativeZero(m_node-&gt;arithMode())) {
</span><span class="cx">                 LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, (&quot;ArithMod negative numerator&quot;));
</span><span class="cx">                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, (&quot;ArithMod numerator continuation&quot;));
</span><del>-                
</del><ins>+
</ins><span class="cx">                 m_out.branch(
</span><span class="cx">                     m_out.lessThan(numerator, m_out.int32Zero),
</span><span class="cx">                     unsure(negativeNumerator), unsure(numeratorContinuation));
</span><del>-                
</del><ins>+
</ins><span class="cx">                 LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
</span><del>-                
</del><ins>+
</ins><span class="cx">                 speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
</span><del>-                
</del><ins>+
</ins><span class="cx">                 m_out.jump(numeratorContinuation);
</span><del>-                
</del><ins>+
</ins><span class="cx">                 m_out.appendTo(numeratorContinuation, innerLastNext);
</span><span class="cx">             }
</span><del>-            
-            results.append(m_out.anchor(remainder));
-            m_out.jump(done);
-            
-            m_out.appendTo(done, lastNext);
-            
-            setInt32(m_out.phi(m_out.int32, results));
</del><ins>+
+            setInt32(remainder);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case DoubleRepUse: {
</span><span class="cx">             setDouble(
</span><del>-                m_out.doubleRem(lowDouble(m_node-&gt;child1()), lowDouble(m_node-&gt;child2())));
</del><ins>+                m_out.doubleMod(lowDouble(m_node-&gt;child1()), lowDouble(m_node-&gt;child2())));
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -116,6 +116,47 @@
</span><span class="cx">     return phi(int32, results);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+LValue Output::chillMod(LValue numerator, LValue denominator)
+{
+    LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(*this, (&quot;ChillMod unsafe denominator&quot;));
+    LBasicBlock continuation = FTL_NEW_BLOCK(*this, (&quot;ChillMod continuation&quot;));
+    LBasicBlock done = FTL_NEW_BLOCK(*this, (&quot;ChillMod done&quot;));
+    LBasicBlock divByZero = FTL_NEW_BLOCK(*this, (&quot;ChillMod divide by zero&quot;));
+    LBasicBlock notDivByZero = FTL_NEW_BLOCK(*this, (&quot;ChillMod not divide by zero&quot;));
+    LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(*this, (&quot;ChillMod -2^31/-1&quot;));
+
+    LValue adjustedDenominator = add(denominator, int32One);
+    branch(
+        above(adjustedDenominator, int32One),
+        usually(continuation), rarely(unsafeDenominator));
+
+    Vector&lt;ValueFromBlock, 3&gt; results;
+    LBasicBlock lastNext = appendTo(unsafeDenominator, continuation);
+
+    LValue neg2ToThe31 = constInt32(-2147483647-1);
+    branch(isZero32(denominator), rarely(divByZero), usually(notDivByZero));
+
+    appendTo(divByZero, notDivByZero);
+    results.append(anchor(int32Zero));
+    jump(done);
+
+    appendTo(notDivByZero, neg2ToThe31ByNeg1);
+    branch(equal(numerator, neg2ToThe31),
+        rarely(neg2ToThe31ByNeg1), usually(continuation));
+
+    appendTo(neg2ToThe31ByNeg1, continuation);
+    results.append(anchor(int32Zero));
+    jump(done);
+
+    appendTo(continuation, done);
+    LValue result = mod(numerator, denominator);
+    results.append(anchor(result));
+    jump(done);
+
+    appendTo(done, lastNext);
+    return phi(int32, results);
+}
+
</ins><span class="cx"> LValue Output::sensibleDoubleToInt(LValue value)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(isX86());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.h (193932 => 193933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2015-12-11 00:31:51 UTC (rev 193933)
</span><span class="lines">@@ -126,14 +126,15 @@
</span><span class="cx">     LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
</span><span class="cx">     LValue div(LValue left, LValue right) { return buildDiv(m_builder, left, right); }
</span><span class="cx">     LValue chillDiv(LValue left, LValue right);
</span><del>-    LValue rem(LValue left, LValue right) { return buildRem(m_builder, left, right); }
</del><ins>+    LValue mod(LValue left, LValue right) { return buildRem(m_builder, left, right); }
+    LValue chillMod(LValue left, LValue right);
</ins><span class="cx">     LValue neg(LValue value) { return buildNeg(m_builder, value); }
</span><span class="cx"> 
</span><span class="cx">     LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
</span><span class="cx">     LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
</span><span class="cx">     LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
</span><span class="cx">     LValue doubleDiv(LValue left, LValue right) { return buildFDiv(m_builder, left, right); }
</span><del>-    LValue doubleRem(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
</del><ins>+    LValue doubleMod(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
</ins><span class="cx">     LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
</span><span class="cx"> 
</span><span class="cx">     LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }
</span></span></pre>
</div>
</div>

</body>
</html>