<!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>[194003] 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/194003">194003</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-12-11 22:10:07 -0800 (Fri, 11 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Add Floating Point Abs() to B3
https://bugs.webkit.org/show_bug.cgi?id=152176

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

This patch adds an Abs() operation for floating point.

On x86, Abs() is implemented by masking the top bit
of the floating point value. On ARM64, there is a builtin
abs opcode.

To account for those differences, B3 use &quot;Abs&quot; as
the cannonical operation. When we are about to lower
to Air, Abs is extended on x86 to get a clean handling
of the mask constants.

This patch has one cool thing related to FTL.
If you do:
   @1 = unboxDouble(@0)
   @2 = abs(@1)
   @3 = boxDouble(@2)

B3ReduceStrength completely eliminate the Double-Integer
conversion.

The strength reduction of Abs is aware that it can do a bit
mask over the bitcast used by unboxing.
If even works if you use floats by forcing fround: reduceDoubleToFloat()
elminiates the useless conversions, followed by ReduceStrength
that removes the switch from GP to FP.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::andDouble):
(JSC::MacroAssemblerX86Common::andFloat):
* assembler/X86Assembler.h:
(JSC::X86Assembler::andps_rr):
* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::bitAndConstant):
(JSC::B3::ConstDoubleValue::absConstant):
* b3/B3ConstDoubleValue.h:
* b3/B3ConstFloatValue.cpp:
(JSC::B3::ConstFloatValue::bitAndConstant):
(JSC::B3::ConstFloatValue::absConstant):
* b3/B3ConstFloatValue.h:
* b3/B3Generate.cpp:
(JSC::B3::generateToAir):
* b3/B3LowerMacrosAfterOptimizations.cpp: Added.
(JSC::B3::lowerMacrosAfterOptimizations):
* b3/B3LowerMacrosAfterOptimizations.h: Added.
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceDoubleToFloat.cpp:
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::absConstant):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::bitAndDouble):
(JSC::B3::testBitAndArgDouble):
(JSC::B3::testBitAndArgsDouble):
(JSC::B3::testBitAndArgImmDouble):
(JSC::B3::testBitAndImmsDouble):
(JSC::B3::bitAndFloat):
(JSC::B3::testBitAndArgFloat):
(JSC::B3::testBitAndArgsFloat):
(JSC::B3::testBitAndArgImmFloat):
(JSC::B3::testBitAndImmsFloat):
(JSC::B3::testBitAndArgsFloatWithUselessDoubleConversion):
(JSC::B3::testAbsArg):
(JSC::B3::testAbsImm):
(JSC::B3::testAbsMem):
(JSC::B3::testAbsAbsArg):
(JSC::B3::testAbsBitwiseCastArg):
(JSC::B3::testBitwiseCastAbsBitwiseCastArg):
(JSC::B3::testAbsArgWithUselessDoubleConversion):
(JSC::B3::testAbsArgWithEffectfulDoubleConversion):
(JSC::B3::run):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::doubleAbs):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerX86Assemblerh">trunk/Source/JavaScriptCore/assembler/X86Assembler.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="#trunkSourceJavaScriptCoreb3B3ConstFloatValuecpp">trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstFloatValueh">trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Generatecpp">trunk/Source/JavaScriptCore/b3/B3Generate.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="#trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloatcpp">trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp</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="#trunkSourceJavaScriptCoreb3airAirOpcodeopcodes">trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes</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>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerMacrosAfterOptimizationscpp">trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerMacrosAfterOptimizationsh">trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -114,6 +114,7 @@
</span><span class="cx">     b3/B3HeapRange.cpp
</span><span class="cx">     b3/B3InsertionSet.cpp
</span><span class="cx">     b3/B3LowerMacros.cpp
</span><ins>+    b3/B3LowerMacrosAfterOptimizations.cpp
</ins><span class="cx">     b3/B3LowerToAir.cpp
</span><span class="cx">     b3/B3MathExtras.cpp
</span><span class="cx">     b3/B3MemoryValue.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -1,3 +1,95 @@
</span><ins>+2015-12-11  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Add Floating Point Abs() to B3
+        https://bugs.webkit.org/show_bug.cgi?id=152176
+
+        Reviewed by Geoffrey Garen.
+
+        This patch adds an Abs() operation for floating point.
+
+        On x86, Abs() is implemented by masking the top bit
+        of the floating point value. On ARM64, there is a builtin
+        abs opcode.
+
+        To account for those differences, B3 use &quot;Abs&quot; as
+        the cannonical operation. When we are about to lower
+        to Air, Abs is extended on x86 to get a clean handling
+        of the mask constants.
+
+        This patch has one cool thing related to FTL.
+        If you do:
+           @1 = unboxDouble(@0)
+           @2 = abs(@1)
+           @3 = boxDouble(@2)
+
+        B3ReduceStrength completely eliminate the Double-Integer
+        conversion.
+
+        The strength reduction of Abs is aware that it can do a bit
+        mask over the bitcast used by unboxing.
+        If even works if you use floats by forcing fround: reduceDoubleToFloat()
+        elminiates the useless conversions, followed by ReduceStrength
+        that removes the switch from GP to FP.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::andDouble):
+        (JSC::MacroAssemblerX86Common::andFloat):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::andps_rr):
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::bitAndConstant):
+        (JSC::B3::ConstDoubleValue::absConstant):
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3ConstFloatValue.cpp:
+        (JSC::B3::ConstFloatValue::bitAndConstant):
+        (JSC::B3::ConstFloatValue::absConstant):
+        * b3/B3ConstFloatValue.h:
+        * b3/B3Generate.cpp:
+        (JSC::B3::generateToAir):
+        * b3/B3LowerMacrosAfterOptimizations.cpp: Added.
+        (JSC::B3::lowerMacrosAfterOptimizations):
+        * b3/B3LowerMacrosAfterOptimizations.h: Added.
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceDoubleToFloat.cpp:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::absConstant):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::bitAndDouble):
+        (JSC::B3::testBitAndArgDouble):
+        (JSC::B3::testBitAndArgsDouble):
+        (JSC::B3::testBitAndArgImmDouble):
+        (JSC::B3::testBitAndImmsDouble):
+        (JSC::B3::bitAndFloat):
+        (JSC::B3::testBitAndArgFloat):
+        (JSC::B3::testBitAndArgsFloat):
+        (JSC::B3::testBitAndArgImmFloat):
+        (JSC::B3::testBitAndImmsFloat):
+        (JSC::B3::testBitAndArgsFloatWithUselessDoubleConversion):
+        (JSC::B3::testAbsArg):
+        (JSC::B3::testAbsImm):
+        (JSC::B3::testAbsMem):
+        (JSC::B3::testAbsAbsArg):
+        (JSC::B3::testAbsBitwiseCastArg):
+        (JSC::B3::testBitwiseCastAbsBitwiseCastArg):
+        (JSC::B3::testAbsArgWithUselessDoubleConversion):
+        (JSC::B3::testAbsArgWithEffectfulDoubleConversion):
+        (JSC::B3::run):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::doubleAbs):
+
</ins><span class="cx"> 2015-12-11  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Removed some dead code, and simplified some code in the baseline JIT.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -1129,6 +1129,8 @@
</span><span class="cx">                 371D842D17C98B6E00ECF994 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 371D842C17C98B6E00ECF994 /* libz.dylib */; };
</span><span class="cx">                 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateConversion.h */; };
</span><span class="cx">                 41DEA1321B9F3163006D65DD /* BuiltinUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DEA1311B9F3154006D65DD /* BuiltinUtils.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                4319DA031C1BE40A001D260B /* B3LowerMacrosAfterOptimizations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4319DA011C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.cpp */; };
+                4319DA041C1BE40D001D260B /* B3LowerMacrosAfterOptimizations.h in Headers */ = {isa = PBXBuildFile; fileRef = 4319DA021C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.h */; };
</ins><span class="cx">                 4340A4841A9051AF00D73CCA /* MathCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4340A4821A9051AF00D73CCA /* MathCommon.cpp */; };
</span><span class="cx">                 4340A4851A9051AF00D73CCA /* MathCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 4340A4831A9051AF00D73CCA /* MathCommon.h */; };
</span><span class="cx">                 43422A621C158E6A00E2EB98 /* B3ConstFloatValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43422A601C15871B00E2EB98 /* B3ConstFloatValue.cpp */; };
</span><span class="lines">@@ -3207,6 +3209,8 @@
</span><span class="cx">                 2AF7382B18BBBF92008A5A37 /* StructureIDTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureIDTable.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 371D842C17C98B6E00ECF994 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = &quot;compiled.mach-o.dylib&quot;; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
</span><span class="cx">                 41DEA1311B9F3154006D65DD /* BuiltinUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinUtils.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                4319DA011C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3LowerMacrosAfterOptimizations.cpp; path = b3/B3LowerMacrosAfterOptimizations.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                4319DA021C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3LowerMacrosAfterOptimizations.h; path = b3/B3LowerMacrosAfterOptimizations.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 4340A4821A9051AF00D73CCA /* MathCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathCommon.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 4340A4831A9051AF00D73CCA /* MathCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathCommon.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 43422A601C15871B00E2EB98 /* B3ConstFloatValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ConstFloatValue.cpp; path = b3/B3ConstFloatValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4619,8 +4623,6 @@
</span><span class="cx">                                 0F338E011BF0276C0013C88F /* B3DataSection.cpp */,
</span><span class="cx">                                 0F338E021BF0276C0013C88F /* B3DataSection.h */,
</span><span class="cx">                                 0F33FCFA1C1625BE00323F67 /* B3Dominators.h */,
</span><del>-                                43422A641C16221E00E2EB98 /* B3ReduceDoubleToFloat.cpp */,
-                                43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */,
</del><span class="cx">                                 0FEC85C41BE16F5A0080FF74 /* B3Effects.cpp */,
</span><span class="cx">                                 0FEC85BE1BE167A00080FF74 /* B3Effects.h */,
</span><span class="cx">                                 0FEC84CB1BDACDAC0080FF74 /* B3FrequencyClass.cpp */,
</span><span class="lines">@@ -4638,6 +4640,8 @@
</span><span class="cx">                                 0FEC85B61BE1462F0080FF74 /* B3InsertionSetInlines.h */,
</span><span class="cx">                                 0F338E191BF286EA0013C88F /* B3LowerMacros.cpp */,
</span><span class="cx">                                 0F338E1A1BF286EA0013C88F /* B3LowerMacros.h */,
</span><ins>+                                4319DA011C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.cpp */,
+                                4319DA021C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.h */,
</ins><span class="cx">                                 0FEC84D31BDACDAC0080FF74 /* B3LowerToAir.cpp */,
</span><span class="cx">                                 0FEC84D41BDACDAC0080FF74 /* B3LowerToAir.h */,
</span><span class="cx">                                 43AB26C41C1A52F700D82AE6 /* B3MathExtras.cpp */,
</span><span class="lines">@@ -4664,6 +4668,8 @@
</span><span class="cx">                                 0FEC84E11BDACDAC0080FF74 /* B3Procedure.cpp */,
</span><span class="cx">                                 0FEC84E21BDACDAC0080FF74 /* B3Procedure.h */,
</span><span class="cx">                                 0FEC84E31BDACDAC0080FF74 /* B3ProcedureInlines.h */,
</span><ins>+                                43422A641C16221E00E2EB98 /* B3ReduceDoubleToFloat.cpp */,
+                                43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */,
</ins><span class="cx">                                 0FEC85B71BE1462F0080FF74 /* B3ReduceStrength.cpp */,
</span><span class="cx">                                 0FEC85B81BE1462F0080FF74 /* B3ReduceStrength.h */,
</span><span class="cx">                                 0F33FCF51C136E2500323F67 /* B3StackmapGenerationParams.cpp */,
</span><span class="lines">@@ -7730,6 +7736,7 @@
</span><span class="cx">                                 0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */,
</span><span class="cx">                                 FE3A06B21C10CB8900390FDD /* JITBitAndGenerator.h in Headers */,
</span><span class="cx">                                 0FD3E40E1B618B6600C80E1E /* PropertyCondition.h in Headers */,
</span><ins>+                                4319DA041C1BE40D001D260B /* B3LowerMacrosAfterOptimizations.h in Headers */,
</ins><span class="cx">                                 A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */,
</span><span class="cx">                                 BC95437D0EBA70FD0072B6D3 /* PropertyMapHashTable.h in Headers */,
</span><span class="cx">                                 86158AB3155C8B4000B45C9C /* PropertyName.h in Headers */,
</span><span class="lines">@@ -8788,6 +8795,7 @@
</span><span class="cx">                                 0F338DF11BE93AD10013C88F /* B3StackmapValue.cpp in Sources */,
</span><span class="cx">                                 0F25F1B3181635F300522F39 /* FTLSlowPathCallKey.cpp in Sources */,
</span><span class="cx">                                 0F9D339A1803ADB70073C2BC /* FTLStackMaps.cpp in Sources */,
</span><ins>+                                4319DA031C1BE40A001D260B /* B3LowerMacrosAfterOptimizations.cpp in Sources */,
</ins><span class="cx">                                 0FEA0A161706BB9000BB722C /* FTLState.cpp in Sources */,
</span><span class="cx">                                 0F235BE117178E1C00690C7F /* FTLThunks.cpp in Sources */,
</span><span class="cx">                                 0F6B1CC51862C47800845D97 /* FTLUnwindInfo.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -1013,6 +1013,17 @@
</span><span class="cx">         m_assembler.mulss_mr(src.offset, src.base, dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void andDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        // ANDPS is defined on 128bits and is shorter than ANDPD.
+        m_assembler.andps_rr(src, dst);
+    }
+
+    void andFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.andps_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="trunkSourceJavaScriptCoreassemblerX86Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/X86Assembler.h (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -273,6 +273,7 @@
</span><span class="cx">         OP2_DIVSD_VsdWsd    = 0x5E,
</span><span class="cx">         OP2_MOVMSKPD_VdEd   = 0x50,
</span><span class="cx">         OP2_SQRTSD_VsdWsd   = 0x51,
</span><ins>+        OP2_ANDPS_VpdWpd    = 0x54,
</ins><span class="cx">         OP2_ANDNPD_VpdWpd   = 0x55,
</span><span class="cx">         OP2_XORPD_VpdWpd    = 0x57,
</span><span class="cx">         OP2_MOVD_VdEd       = 0x6E,
</span><span class="lines">@@ -2283,6 +2284,11 @@
</span><span class="cx">         m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, base, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void andps_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_ANDPS_VpdWpd, (RegisterID)dst, (RegisterID)src);
+    }
+
</ins><span class="cx">     void xorps_rr(XMMRegisterID src, XMMRegisterID dst)
</span><span class="cx">     {
</span><span class="cx">         m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -69,6 +69,14 @@
</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::bitAndConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasDouble())
+        return nullptr;
+    double result = bitwise_cast&lt;double&gt;(bitwise_cast&lt;uint64_t&gt;(m_value) &amp; bitwise_cast&lt;uint64_t&gt;(other-&gt;asDouble()));
+    return proc.add&lt;ConstDoubleValue&gt;(origin(), result);
+}
+
</ins><span class="cx"> Value* ConstDoubleValue::bitwiseCastConstant(Procedure&amp; proc) const
</span><span class="cx"> {
</span><span class="cx">     return proc.add&lt;Const64Value&gt;(origin(), bitwise_cast&lt;int64_t&gt;(m_value));
</span><span class="lines">@@ -79,6 +87,11 @@
</span><span class="cx">     return proc.add&lt;ConstFloatValue&gt;(origin(), static_cast&lt;float&gt;(m_value));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* ConstDoubleValue::absConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstDoubleValue&gt;(origin(), fabs(m_value));
+}
+
</ins><span class="cx"> Value* ConstDoubleValue::sqrtConstant(Procedure&amp; proc) const
</span><span class="cx"> {
</span><span class="cx">     return proc.add&lt;ConstDoubleValue&gt;(origin(), sqrt(m_value));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -47,8 +47,10 @@
</span><span class="cx">     Value* divConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* modConstant(Procedure&amp;, const Value* other) const override;
</span><span class="cx">     Value* mulConstant(Procedure&amp;, const Value* other) const override;
</span><ins>+    Value* bitAndConstant(Procedure&amp;, const Value* other) const override;
</ins><span class="cx">     Value* bitwiseCastConstant(Procedure&amp;) const override;
</span><span class="cx">     Value* doubleToFloatConstant(Procedure&amp;) const override;
</span><ins>+    Value* absConstant(Procedure&amp;) const override;
</ins><span class="cx">     Value* sqrtConstant(Procedure&amp;) const override;
</span><span class="cx"> 
</span><span class="cx">     TriState equalConstant(const Value* other) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstFloatValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -69,6 +69,14 @@
</span><span class="cx">     return proc.add&lt;ConstFloatValue&gt;(origin(), m_value * other-&gt;asFloat());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* ConstFloatValue::bitAndConstant(Procedure&amp; proc, const Value* other) const
+{
+    if (!other-&gt;hasFloat())
+        return nullptr;
+    float result = bitwise_cast&lt;float&gt;(bitwise_cast&lt;uint32_t&gt;(m_value) &amp; bitwise_cast&lt;uint32_t&gt;(other-&gt;asFloat()));
+    return proc.add&lt;ConstFloatValue&gt;(origin(), result);
+}
+
</ins><span class="cx"> Value* ConstFloatValue::bitwiseCastConstant(Procedure&amp; proc) const
</span><span class="cx"> {
</span><span class="cx">     return proc.add&lt;Const32Value&gt;(origin(), bitwise_cast&lt;int32_t&gt;(m_value));
</span><span class="lines">@@ -79,6 +87,11 @@
</span><span class="cx">     return proc.add&lt;ConstDoubleValue&gt;(origin(), static_cast&lt;double&gt;(m_value));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* ConstFloatValue::absConstant(Procedure&amp; proc) const
+{
+    return proc.add&lt;ConstFloatValue&gt;(origin(), static_cast&lt;float&gt;(fabs(m_value)));
+}
+
</ins><span class="cx"> Value* ConstFloatValue::sqrtConstant(Procedure&amp; proc) const
</span><span class="cx"> {
</span><span class="cx">     return proc.add&lt;ConstFloatValue&gt;(origin(), static_cast&lt;float&gt;(sqrt(m_value)));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstFloatValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -46,8 +46,10 @@
</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><span class="cx">     Value* mulConstant(Procedure&amp;, const Value* other) const override;
</span><ins>+    Value* bitAndConstant(Procedure&amp;, const Value* other) const override;
</ins><span class="cx">     Value* bitwiseCastConstant(Procedure&amp;) const override;
</span><span class="cx">     Value* floatToDoubleConstant(Procedure&amp;) const override;
</span><ins>+    Value* absConstant(Procedure&amp;) const override;
</ins><span class="cx">     Value* sqrtConstant(Procedure&amp;) const override;
</span><span class="cx"> 
</span><span class="cx">     TriState equalConstant(const Value* other) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Generatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Generate.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><span class="cx"> #include &quot;B3Common.h&quot;
</span><span class="cx"> #include &quot;B3LowerMacros.h&quot;
</span><ins>+#include &quot;B3LowerMacrosAfterOptimizations.h&quot;
</ins><span class="cx"> #include &quot;B3LowerToAir.h&quot;
</span><span class="cx"> #include &quot;B3MoveConstants.h&quot;
</span><span class="cx"> #include &quot;B3Procedure.h&quot;
</span><span class="lines">@@ -82,6 +83,8 @@
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=150507
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    lowerMacrosAfterOptimizations(procedure);
+
</ins><span class="cx">     moveConstants(procedure);
</span><span class="cx"> 
</span><span class="cx">     if (shouldValidateIR())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerMacrosAfterOptimizationscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp (0 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -0,0 +1,125 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;B3LowerMacrosAfterOptimizations.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;B3BasicBlockInlines.h&quot;
+#include &quot;B3BlockInsertionSet.h&quot;
+#include &quot;B3ConstDoubleValue.h&quot;
+#include &quot;B3ConstFloatValue.h&quot;
+#include &quot;B3InsertionSetInlines.h&quot;
+#include &quot;B3PhaseScope.h&quot;
+
+namespace JSC { namespace B3 {
+
+namespace {
+
+class LowerMacros {
+public:
+    LowerMacros(Procedure&amp; proc)
+        : m_proc(proc)
+        , m_blockInsertionSet(proc)
+        , m_insertionSet(proc)
+    {
+    }
+
+    bool run()
+    {
+        for (BasicBlock* block : m_proc) {
+            m_block = block;
+            processCurrentBlock();
+        }
+        m_changed |= m_blockInsertionSet.execute();
+        if (m_changed) {
+            m_proc.resetReachability();
+            m_proc.invalidateCFG();
+        }
+        return m_changed;
+    }
+    
+private:
+    void processCurrentBlock()
+    {
+        for (m_index = 0; m_index &lt; m_block-&gt;size(); ++m_index) {
+            m_value = m_block-&gt;at(m_index);
+            m_origin = m_value-&gt;origin();
+            switch (m_value-&gt;opcode()) {
+            case Abs: {
+                // ARM supports this instruction natively.
+                if (isARM64())
+                    break;
+
+                Value* mask = nullptr;
+                if (m_value-&gt;type() == Double)
+                    mask = m_insertionSet.insert&lt;ConstDoubleValue&gt;(m_index, m_origin, bitwise_cast&lt;double&gt;(~(1l &lt;&lt; 63)));
+                else if (m_value-&gt;type() == Float)
+                    mask = m_insertionSet.insert&lt;ConstFloatValue&gt;(m_index, m_origin, bitwise_cast&lt;float&gt;(~(1 &lt;&lt; 31)));
+                else
+                    RELEASE_ASSERT_NOT_REACHED();
+                Value* result = m_insertionSet.insert&lt;Value&gt;(m_index, BitAnd, m_origin, m_value-&gt;child(0), mask);
+                m_value-&gt;replaceWithIdentity(result);
+                break;
+            }
+            default:
+                break;
+            }
+        }
+        m_insertionSet.execute(m_block);
+    }
+    
+    Procedure&amp; m_proc;
+    BlockInsertionSet m_blockInsertionSet;
+    InsertionSet m_insertionSet;
+    BasicBlock* m_block;
+    unsigned m_index;
+    Value* m_value;
+    Origin m_origin;
+    bool m_changed { false };
+};
+
+bool lowerMacrosImpl(Procedure&amp; proc)
+{
+    LowerMacros lowerMacros(proc);
+    return lowerMacros.run();
+}
+
+} // anonymous namespace
+
+bool lowerMacrosAfterOptimizations(Procedure&amp; proc)
+{
+    PhaseScope phaseScope(proc, &quot;lowerMacrosAfterOptimizations&quot;);
+    bool result = lowerMacrosImpl(proc);
+    if (shouldValidateIR())
+        RELEASE_ASSERT(!lowerMacrosImpl(proc));
+    return result;
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerMacrosAfterOptimizationsh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.h (0 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef B3LowerMacrosAfterOptimizations_h
+#define B3LowerMacrosAfterOptimizations_h
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 {
+
+class Procedure;
+
+// Lower certain high level opcodes to lower-level opcode to help code generation.
+
+bool lowerMacrosAfterOptimizations(Procedure&amp;);
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3LowerMacrosAfterOptimizations_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -1459,7 +1459,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case BitAnd: {
</span><del>-            appendBinOp&lt;And32, And64, Commutative&gt;(
</del><ins>+            appendBinOp&lt;And32, And64, AndDouble, AndFloat, 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 (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -146,6 +146,9 @@
</span><span class="cx">     case Clz:
</span><span class="cx">         out.print(&quot;Clz&quot;);
</span><span class="cx">         return;
</span><ins>+    case Abs:
+        out.print(&quot;Abs&quot;);
+        return;
</ins><span class="cx">     case Sqrt:
</span><span class="cx">         out.print(&quot;Sqrt&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 (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3Opcode.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -84,7 +84,8 @@
</span><span class="cx">     ZShr, // Logical Shift.
</span><span class="cx">     Clz, // Count leading zeros.
</span><span class="cx"> 
</span><del>-    // Double math.
</del><ins>+    // Floating point math.
+    Abs,
</ins><span class="cx">     Sqrt,
</span><span class="cx"> 
</span><span class="cx">     // Casts and such.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceDoubleToFloatcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx">             candidate-&gt;setType(Float);
</span><span class="cx">         }
</span><span class="cx">         break;
</span><ins>+    case Abs:
</ins><span class="cx">     case Sqrt:
</span><span class="cx">         if (candidate-&gt;child(0)-&gt;opcode() == FloatToDouble) {
</span><span class="cx">             candidate-&gt;child(0) = candidate-&gt;child(0)-&gt;child(0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -505,6 +505,39 @@
</span><span class="cx"> 
</span><span class="cx">             break;
</span><span class="cx"> 
</span><ins>+        case Abs:
+            // Turn this: Abs(constant)
+            // Into this: fabs&lt;value-&gt;type()&gt;(constant)
+            if (Value* constant = m_value-&gt;child(0)-&gt;absConstant(m_proc)) {
+                replaceWithNewValue(constant);
+                break;
+            }
+
+            // Turn this: Abs(Abs(value))
+            // Into this: Abs(value)
+            if (m_value-&gt;child(0)-&gt;opcode() == Abs) {
+                m_value-&gt;replaceWithIdentity(m_value-&gt;child(0));
+                break;
+            }
+
+            // Turn this: Abs(BitwiseCast(value))
+            // Into this: BitwiseCast(And(value, mask-top-bit))
+            if (m_value-&gt;child(0)-&gt;opcode() == BitwiseCast) {
+                Value* mask;
+                if (m_value-&gt;type() == Double)
+                    mask = m_insertionSet.insert&lt;Const64Value&gt;(m_index, m_value-&gt;origin(), ~(1l &lt;&lt; 63));
+                else
+                    mask = m_insertionSet.insert&lt;Const32Value&gt;(m_index, m_value-&gt;origin(), ~(1l &lt;&lt; 31));
+
+                Value* bitAnd = m_insertionSet.insert&lt;Value&gt;(m_index, BitAnd, m_value-&gt;origin(),
+                    m_value-&gt;child(0)-&gt;child(0),
+                    mask);
+                Value* cast = m_insertionSet.insert&lt;Value&gt;(m_index, BitwiseCast, m_value-&gt;origin(), bitAnd);
+                m_value-&gt;replaceWithIdentity(cast);
+                break;
+            }
+            break;
+
</ins><span class="cx">         case Sqrt:
</span><span class="cx">             // Turn this: Sqrt(constant)
</span><span class="cx">             // Into this: sqrt&lt;value-&gt;type()&gt;(constant)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Validatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Validate.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -154,6 +154,7 @@
</span><span class="cx">             case Mul:
</span><span class="cx">             case Div:
</span><span class="cx">             case Mod:
</span><ins>+            case BitAnd:
</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="lines">@@ -161,7 +162,6 @@
</span><span class="cx">                 break;
</span><span class="cx">             case ChillDiv:
</span><span class="cx">             case ChillMod:
</span><del>-            case BitAnd:
</del><span class="cx">             case BitOr:
</span><span class="cx">             case BitXor:
</span><span class="cx">                 VALIDATE(value-&gt;numChildren() == 2, (&quot;At &quot;, *value));
</span><span class="lines">@@ -209,6 +209,7 @@
</span><span class="cx">                 VALIDATE(value-&gt;child(0)-&gt;type() == Int64, (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(value-&gt;type() == Int32, (&quot;At &quot;, *value));
</span><span class="cx">                 break;
</span><ins>+            case Abs:
</ins><span class="cx">             case Sqrt:
</span><span class="cx">                 VALIDATE(value-&gt;numChildren() == 1, (&quot;At &quot;, *value));
</span><span class="cx">                 VALIDATE(isFloat(value-&gt;child(0)-&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 (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -221,6 +221,11 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Value* Value::absConstant(Procedure&amp;) const
+{
+    return nullptr;
+}
+
</ins><span class="cx"> Value* Value::sqrtConstant(Procedure&amp;) const
</span><span class="cx"> {
</span><span class="cx">     return nullptr;
</span><span class="lines">@@ -357,6 +362,7 @@
</span><span class="cx">     case SShr:
</span><span class="cx">     case ZShr:
</span><span class="cx">     case Clz:
</span><ins>+    case Abs:
</ins><span class="cx">     case Sqrt:
</span><span class="cx">     case BitwiseCast:
</span><span class="cx">     case SExt8:
</span><span class="lines">@@ -433,6 +439,7 @@
</span><span class="cx">     case FramePointer:
</span><span class="cx">         return ValueKey(opcode(), type());
</span><span class="cx">     case Identity:
</span><ins>+    case Abs:
</ins><span class="cx">     case Sqrt:
</span><span class="cx">     case SExt8:
</span><span class="cx">     case SExt16:
</span><span class="lines">@@ -539,6 +546,7 @@
</span><span class="cx">     case SShr:
</span><span class="cx">     case ZShr:
</span><span class="cx">     case Clz:
</span><ins>+    case Abs:
</ins><span class="cx">     case Sqrt:
</span><span class="cx">     case CheckAdd:
</span><span class="cx">     case CheckSub:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.h (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.h        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/B3Value.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -131,6 +131,7 @@
</span><span class="cx">     virtual Value* bitwiseCastConstant(Procedure&amp;) const;
</span><span class="cx">     virtual Value* doubleToFloatConstant(Procedure&amp;) const;
</span><span class="cx">     virtual Value* floatToDoubleConstant(Procedure&amp;) const;
</span><ins>+    virtual Value* absConstant(Procedure&amp;) const;
</ins><span class="cx">     virtual Value* sqrtConstant(Procedure&amp;) const;
</span><span class="cx"> 
</span><span class="cx">     virtual TriState equalConstant(const Value* other) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -170,6 +170,12 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><ins>+AndDouble U:F, UD:F
+    Tmp, Tmp
+
+AndFloat U:F, UD:F
+    Tmp, Tmp
+
</ins><span class="cx"> Lshift32 U:G, UD:G
</span><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -1942,6 +1942,140 @@
</span><span class="cx">     CHECK(compileAndRun&lt;int64_t&gt;(proc, a, b) == expected);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+double bitAndDouble(double a, double b)
+{
+    return bitwise_cast&lt;double&gt;(bitwise_cast&lt;uint64_t&gt;(a) &amp; bitwise_cast&lt;uint64_t&gt;(b));
+}
+
+void testBitAndArgDouble(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, BitAnd, Origin(), argument, argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a), bitAndDouble(a, a)));
+}
+
+void testBitAndArgsDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* argumentB = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR1);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, BitAnd, Origin(), argumentA, argumentB);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a, b), bitAndDouble(a, b)));
+}
+
+void testBitAndArgImmDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* argumentB = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, BitAnd, Origin(), argumentA, argumentB);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a, b), bitAndDouble(a, b)));
+}
+
+void testBitAndImmsDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), a);
+    Value* argumentB = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, BitAnd, Origin(), argumentA, argumentB);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), bitAndDouble(a, b)));
+}
+
+float bitAndFloat(float a, float b)
+{
+    return bitwise_cast&lt;float&gt;(bitwise_cast&lt;uint32_t&gt;(a) &amp; bitwise_cast&lt;uint32_t&gt;(b));
+}
+
+void testBitAndArgFloat(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(),
+        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, BitAnd, Origin(), argument, argument);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), bitAndFloat(a, a)));
+}
+
+void testBitAndArgsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0)));
+    Value* argumentB = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(),
+        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, BitAnd, Origin(), argumentA, argumentB);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitAndFloat(a, b)));
+}
+
+void testBitAndArgImmFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0)));
+    Value* argumentB = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, BitAnd, Origin(), argumentA, argumentB);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), bitAndFloat(a, b)));
+}
+
+void testBitAndImmsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* argumentB = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), b);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, BitAnd, Origin(), argumentA, argumentB);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc), bitAndFloat(a, b)));
+}
+
+void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0)));
+    Value* argumentB = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+            root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1)));
+    Value* argumentAasDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), argumentA);
+    Value* argumentBasDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), argumentB);
+    Value* doubleResult = root-&gt;appendNew&lt;Value&gt;(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), doubleResult);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), floatResult);
+
+    double doubleA = a;
+    double doubleB = b;
+    float expected = static_cast&lt;float&gt;(bitAndDouble(doubleA, doubleB));
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), bitwise_cast&lt;int32_t&gt;(b)), expected));
+}
+
</ins><span class="cx"> void testBitOrArgs(int64_t a, int64_t b)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -2897,6 +3031,202 @@
</span><span class="cx">     CHECK(compileAndRun&lt;unsigned&gt;(proc, &amp;a) == countLeadingZero(a));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testAbsArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Abs, Origin(),
+                root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0)));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a), fabs(a)));
+}
+
+void testAbsImm(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ConstDoubleValue&gt;(proc, Origin(), a);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argument));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc), fabs(a)));
+}
+
+void testAbsMem(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadDouble = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Double, Origin(), address);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), loadDouble));
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, &amp;a), fabs(a)));
+}
+
+void testAbsAbsArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* firstAbs = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), FPRInfo::argumentFPR0));
+    Value* secondAbs = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), firstAbs);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), secondAbs);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, a), fabs(a)));
+}
+
+void testAbsBitwiseCastArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt64 = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argumentAsDouble = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentAsInt64);
+    Value* absValue = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argumentAsDouble);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), absValue);
+
+    CHECK(isIdentical(compileAndRun&lt;double&gt;(proc, bitwise_cast&lt;int64_t&gt;(a)), fabs(a)));
+}
+
+void testBitwiseCastAbsBitwiseCastArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt64 = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argumentAsDouble = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentAsInt64);
+    Value* absValue = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argumentAsDouble);
+    Value* resultAsInt64 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), absValue);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), resultAsInt64);
+
+    int64_t expectedResult = bitwise_cast&lt;int64_t&gt;(fabs(a));
+    CHECK(isIdentical(compileAndRun&lt;int64_t&gt;(proc, bitwise_cast&lt;int64_t&gt;(a)), expectedResult));
+}
+
+void testAbsArg(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* argument = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argument);
+    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;(fabs(a)))));
+}
+
+void testAbsImm(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root-&gt;appendNew&lt;ConstFloatValue&gt;(proc, Origin(), a);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argument);
+    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;(fabs(a)))));
+}
+
+void testAbsMem(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadFloat = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Float, Origin(), address);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), loadFloat);
+    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, &amp;a), bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fabs(a)))));
+}
+
+void testAbsAbsArg(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* argument = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argument32);
+    Value* firstAbs = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argument);
+    Value* secondAbs = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), firstAbs);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), secondAbs);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), static_cast&lt;float&gt;(fabs(a))));
+}
+
+void testAbsBitwiseCastArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentAsfloat = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentAsInt32);
+    Value* absValue = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argumentAsfloat);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), absValue);
+
+    CHECK(isIdentical(compileAndRun&lt;float&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), static_cast&lt;float&gt;(fabs(a))));
+}
+
+void testBitwiseCastAbsBitwiseCastArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt32 = root-&gt;appendNew&lt;Value&gt;(proc, Trunc, Origin(),
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentAsfloat = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), argumentAsInt32);
+    Value* absValue = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), argumentAsfloat);
+    Value* resultAsInt64 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), absValue);
+
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), resultAsInt64);
+
+    int32_t expectedResult = bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fabs(a)));
+    CHECK(isIdentical(compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a)), expectedResult));
+}
+
+void testAbsArgWithUselessDoubleConversion(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* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    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;(fabs(a)))));
+}
+
+void testAbsArgWithEffectfulDoubleConversion(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* asDouble = root-&gt;appendNew&lt;Value&gt;(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root-&gt;appendNew&lt;Value&gt;(proc, Abs, Origin(), asDouble);
+    Value* floatResult = root-&gt;appendNew&lt;Value&gt;(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root-&gt;appendNew&lt;Value&gt;(proc, BitwiseCast, Origin(), floatResult);
+    Value* doubleAddress = root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR1);
+    root-&gt;appendNew&lt;MemoryValue&gt;(proc, Store, Origin(), result, doubleAddress);
+    root-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    int32_t resultValue = compileAndRun&lt;int32_t&gt;(proc, bitwise_cast&lt;int32_t&gt;(a), &amp;effect);
+    CHECK(isIdentical(resultValue, bitwise_cast&lt;int32_t&gt;(static_cast&lt;float&gt;(fabs(a)))));
+    CHECK(isIdentical(effect, fabs(a)));
+}
+
</ins><span class="cx"> void testSqrtArg(double a)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -7515,6 +7845,15 @@
</span><span class="cx">     RUN(testBitAndImmBitAndArgImm32(6, 1, 6));
</span><span class="cx">     RUN(testBitAndImmBitAndArgImm32(24, 0xffff, 7));
</span><span class="cx">     RUN_BINARY(testBitAndWithMaskReturnsBooleans, int64Operands(), int64Operands());
</span><ins>+    RUN_UNARY(testBitAndArgDouble, floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testBitAndArgsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testBitAndArgImmDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_BINARY(testBitAndImmsDouble, floatingPointOperands&lt;double&gt;(), floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testBitAndArgFloat, floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testBitAndArgsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testBitAndArgImmFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testBitAndImmsFloat, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
+    RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;(), floatingPointOperands&lt;float&gt;());
</ins><span class="cx"> 
</span><span class="cx">     RUN(testBitOrArgs(43, 43));
</span><span class="cx">     RUN(testBitOrArgs(43, 0));
</span><span class="lines">@@ -7746,6 +8085,21 @@
</span><span class="cx">     RUN_UNARY(testClzArg32, int32Operands());
</span><span class="cx">     RUN_UNARY(testClzMem32, int64Operands());
</span><span class="cx"> 
</span><ins>+    RUN_UNARY(testAbsArg, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testAbsImm, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testAbsMem, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testAbsAbsArg, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands&lt;double&gt;());
+    RUN_UNARY(testAbsArg, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testAbsImm, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testAbsMem, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testAbsAbsArg, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testAbsArgWithUselessDoubleConversion, floatingPointOperands&lt;float&gt;());
+    RUN_UNARY(testAbsArgWithEffectfulDoubleConversion, floatingPointOperands&lt;float&gt;());
+
</ins><span class="cx">     RUN_UNARY(testSqrtArg, floatingPointOperands&lt;double&gt;());
</span><span class="cx">     RUN_UNARY(testSqrtImm, floatingPointOperands&lt;double&gt;());
</span><span class="cx">     RUN_UNARY(testSqrtMem, floatingPointOperands&lt;double&gt;());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.h (194002 => 194003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-12 06:10:07 UTC (rev 194003)
</span><span class="lines">@@ -162,7 +162,7 @@
</span><span class="cx">     LValue addWithOverflow64(LValue left, LValue right) { CRASH(); }
</span><span class="cx">     LValue subWithOverflow64(LValue left, LValue right) { CRASH(); }
</span><span class="cx">     LValue mulWithOverflow64(LValue left, LValue right) { CRASH(); }
</span><del>-    LValue doubleAbs(LValue value) { CRASH(); }
</del><ins>+    LValue doubleAbs(LValue value) { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::Abs, origin(), value); }
</ins><span class="cx"> 
</span><span class="cx">     LValue doubleSin(LValue value) { return callWithoutSideEffects(B3::Double, sin, value); }
</span><span class="cx">     LValue doubleCos(LValue value) { return callWithoutSideEffects(B3::Double, cos, value); }
</span></span></pre>
</div>
</div>

</body>
</html>