<!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>[207164] 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/207164">207164</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-10-11 13:51:53 -0700 (Tue, 11 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Air should be able to replace constant materializations with adds
https://bugs.webkit.org/show_bug.cgi?id=162749

Reviewed by Yusuke Suzuki.
        
We have a lot of defenses against emitting code that materializes huge contants. But if we do
end up with such code in the backend, it's better to convert those materializations into add
instructions by checking if other registers are known to contain nearby constants. That's
what this patch does.

* b3/air/AirFixObviousSpills.cpp:
* b3/testb3.cpp:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirFixObviousSpillscpp">trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (207163 => 207164)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-11 20:37:51 UTC (rev 207163)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-11 20:51:53 UTC (rev 207164)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2016-10-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air should be able to replace constant materializations with adds
+        https://bugs.webkit.org/show_bug.cgi?id=162749
+
+        Reviewed by Yusuke Suzuki.
+        
+        We have a lot of defenses against emitting code that materializes huge contants. But if we do
+        end up with such code in the backend, it's better to convert those materializations into add
+        instructions by checking if other registers are known to contain nearby constants. That's
+        what this patch does.
+
+        * b3/air/AirFixObviousSpills.cpp:
+        * b3/testb3.cpp:
+
</ins><span class="cx"> 2016-10-11  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         B3-&gt;Air lowering needs the same defenses in effectiveAddr() that it has in tryAppendLea()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirFixObviousSpillscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp (207163 => 207164)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp        2016-10-11 20:37:51 UTC (rev 207163)
+++ trunk/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp        2016-10-11 20:51:53 UTC (rev 207164)
</span><span class="lines">@@ -191,6 +191,42 @@
</span><span class="cx"> 
</span><span class="cx">         if (verbose)
</span><span class="cx">             dataLog(&quot;Fixing inst &quot;, inst, &quot;: &quot;, m_state, &quot;\n&quot;);
</span><ins>+        
+        // First handle some special instructions.
+        switch (inst.kind.opcode) {
+        case Move: {
+            if (inst.args[0].isBigImm() &amp;&amp; inst.args[1].isReg()
+                &amp;&amp; isValidForm(Add64, Arg::Imm, Arg::Tmp, Arg::Tmp)) {
+                // BigImm materializations are super expensive on both x86 and ARM. Let's try to
+                // materialize this bad boy using math instead. Note that we use unsigned math here
+                // since it's more deterministic.
+                uint64_t myValue = inst.args[0].value();
+                Reg myDest = inst.args[1].reg();
+                for (const RegConst&amp; regConst : m_state.regConst) {
+                    uint64_t otherValue = regConst.constant;
+                    
+                    // Let's try add. That's the only thing that works on all platforms, since it's
+                    // the only cheap arithmetic op that x86 does in three operands. Long term, we
+                    // should add fancier materializations here for ARM if the BigImm is yuge.
+                    uint64_t delta = myValue - otherValue;
+                    
+                    if (Arg::isValidImmForm(delta)) {
+                        inst.kind = Add64;
+                        inst.args.resize(3);
+                        inst.args[0] = Arg::imm(delta);
+                        inst.args[1] = Tmp(regConst.reg);
+                        inst.args[2] = Tmp(myDest);
+                        return;
+                    }
+                }
+                return;
+            }
+            break;
+        }
+            
+        default:
+            break;
+        }
</ins><span class="cx"> 
</span><span class="cx">         // Create a copy in case we invalidate the instruction. That doesn't happen often.
</span><span class="cx">         Inst instCopy = inst;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (207163 => 207164)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2016-10-11 20:37:51 UTC (rev 207163)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2016-10-11 20:51:53 UTC (rev 207164)
</span><span class="lines">@@ -13705,6 +13705,30 @@
</span><span class="cx">         CHECK_EQ(invoke&lt;int32_t&gt;(*code, ptr - (static_cast&lt;intptr_t&gt;(1) &lt;&lt; static_cast&lt;intptr_t&gt;(32)) * i, i), 12341234);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testOptimizeMaterialization()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root-&gt;appendNew&lt;CCallValue&gt;(
+        proc, Void, Origin(),
+        root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), 0x123423453456llu),
+        root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), 0x123423453456llu + 35));
+    root-&gt;appendNew&lt;Value&gt;(proc, Return, Origin());
+    
+    auto code = compile(proc);
+    bool found = false;
+    for (Air::BasicBlock* block : proc.code()) {
+        for (Air::Inst&amp; inst : *block) {
+            if (inst.kind.opcode != Air::Add64)
+                continue;
+            if (inst.args[0] != Air::Arg::imm(35))
+                continue;
+            found = true;
+        }
+    }
+    CHECK(found);
+}
+
</ins><span class="cx"> // Make sure the compiler does not try to optimize anything out.
</span><span class="cx"> NEVER_INLINE double zero()
</span><span class="cx"> {
</span><span class="lines">@@ -15143,6 +15167,7 @@
</span><span class="cx">     RUN(testAddShl65());
</span><span class="cx">     RUN(testLoadBaseIndexShift2());
</span><span class="cx">     RUN(testLoadBaseIndexShift32());
</span><ins>+    RUN(testOptimizeMaterialization());
</ins><span class="cx">     
</span><span class="cx">     if (isX86()) {
</span><span class="cx">         RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp));
</span></span></pre>
</div>
</div>

</body>
</html>