<!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>[191762] trunk/Source</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/191762">191762</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-10-29 16:42:04 -0700 (Thu, 29 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>StoreOpLoad pattern matching should check effects between the Store and Load
https://bugs.webkit.org/show_bug.cgi?id=150534

Reviewed by Geoffrey Garen.

If we turn:

    a = Load(addr)
    b = Add(a, 42)
    Store(b, addr)

Into:

    Add $42, (addr)

Then we must make sure that we didn't really have this to begin with:

    a = Load(addr)
    Store(666, addr)
    b = Add(a, 42)
    Store(b, addr)

That's because pattern matching doesn't care about control flow, and it finds the Load
just using data flow. This patch fleshes out B3's aliasing analysis, and makes it powerful
enough to broadly ask questions about whether such a code motion of the Load is legal.

* b3/B3Effects.cpp:
(JSC::B3::Effects::interferes):
(JSC::B3::Effects::dump):
* b3/B3Effects.h:
(JSC::B3::Effects::mustExecute):
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::run):
(JSC::B3::Air::LowerToAir::commitInternal):
(JSC::B3::Air::LowerToAir::crossesInterference):
(JSC::B3::Air::LowerToAir::effectiveAddr):
(JSC::B3::Air::LowerToAir::loadAddr):
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::addBlock):
(JSC::B3::Procedure::resetValueOwners):
(JSC::B3::Procedure::resetReachability):
* b3/B3Procedure.h:
* b3/B3Value.cpp:
(JSC::B3::Value::effects):
* b3/B3Value.h:
* b3/testb3.cpp:
(JSC::B3::testStoreAddLoad):
(JSC::B3::testStoreAddLoadInterference):
(JSC::B3::testStoreAddAndLoad):
(JSC::B3::testLoadOffsetUsingAdd):
(JSC::B3::testLoadOffsetUsingAddInterference):
(JSC::B3::testLoadOffsetUsingAddNotConstant):
(JSC::B3::run):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Effectscpp">trunk/Source/JavaScriptCore/b3/B3Effects.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Effectsh">trunk/Source/JavaScriptCore/b3/B3Effects.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3LowerToAircpp">trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedurecpp">trunk/Source/JavaScriptCore/b3/B3Procedure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedureh">trunk/Source/JavaScriptCore/b3/B3Procedure.h</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="#trunkSourceWTFwtfMathExtrash">trunk/Source/WTF/wtf/MathExtras.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2015-10-29  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        StoreOpLoad pattern matching should check effects between the Store and Load
+        https://bugs.webkit.org/show_bug.cgi?id=150534
+
+        Reviewed by Geoffrey Garen.
+
+        If we turn:
+
+            a = Load(addr)
+            b = Add(a, 42)
+            Store(b, addr)
+
+        Into:
+
+            Add $42, (addr)
+
+        Then we must make sure that we didn't really have this to begin with:
+
+            a = Load(addr)
+            Store(666, addr)
+            b = Add(a, 42)
+            Store(b, addr)
+
+        That's because pattern matching doesn't care about control flow, and it finds the Load
+        just using data flow. This patch fleshes out B3's aliasing analysis, and makes it powerful
+        enough to broadly ask questions about whether such a code motion of the Load is legal.
+
+        * b3/B3Effects.cpp:
+        (JSC::B3::Effects::interferes):
+        (JSC::B3::Effects::dump):
+        * b3/B3Effects.h:
+        (JSC::B3::Effects::mustExecute):
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::run):
+        (JSC::B3::Air::LowerToAir::commitInternal):
+        (JSC::B3::Air::LowerToAir::crossesInterference):
+        (JSC::B3::Air::LowerToAir::effectiveAddr):
+        (JSC::B3::Air::LowerToAir::loadAddr):
+        * b3/B3Procedure.cpp:
+        (JSC::B3::Procedure::addBlock):
+        (JSC::B3::Procedure::resetValueOwners):
+        (JSC::B3::Procedure::resetReachability):
+        * b3/B3Procedure.h:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::effects):
+        * b3/B3Value.h:
+        * b3/testb3.cpp:
+        (JSC::B3::testStoreAddLoad):
+        (JSC::B3::testStoreAddLoadInterference):
+        (JSC::B3::testStoreAddAndLoad):
+        (JSC::B3::testLoadOffsetUsingAdd):
+        (JSC::B3::testLoadOffsetUsingAddInterference):
+        (JSC::B3::testLoadOffsetUsingAddNotConstant):
+        (JSC::B3::run):
+
</ins><span class="cx"> 2015-10-29  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Modern IDB: deleteObjectStore support.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Effectscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Effects.cpp (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Effects.cpp        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/B3Effects.cpp        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -29,9 +29,53 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/CommaPrinter.h&gt;
</span><ins>+#include &lt;wtf/DataLog.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><ins>+namespace {
+
+// These helpers cascade in such a way that after the helper for terminal, we don't have to worry
+// about terminal again, since the terminal case considers all ways that a terminal may interfere
+// with something else. And after the exit sideways case, we don't have to worry about either
+// exitsSideways or terminal. And so on...
+
+bool interferesWithTerminal(const Effects&amp; terminal, const Effects&amp; other)
+{
+    if (!terminal.terminal)
+        return false;
+    return other.terminal || other.controlDependent || other.writesSSAState || other.writes;
+}
+
+bool interferesWithExitSideways(const Effects&amp; exitsSideways, const Effects&amp; other)
+{
+    if (!exitsSideways.exitsSideways)
+        return false;
+    return other.controlDependent || other.writes;
+}
+
+bool interferesWithWritesSSAState(const Effects&amp; writesSSAState, const Effects&amp; other)
+{
+    if (!writesSSAState.writesSSAState)
+        return false;
+    return other.writesSSAState || other.readsSSAState;
+}
+
+} // anonymous namespace
+
+bool Effects::interferes(const Effects&amp; other) const
+{
+    if (interferesWithTerminal(*this, other) || interferesWithTerminal(other, *this))
+        return true;
+    if (interferesWithExitSideways(*this, other) || interferesWithExitSideways(other, *this))
+        return true;
+    if (interferesWithWritesSSAState(*this, other) || interferesWithWritesSSAState(other, *this))
+        return true;
+    return writes.overlaps(other.writes)
+        || writes.overlaps(other.reads)
+        || reads.overlaps(other.writes);
+}
+
</ins><span class="cx"> void Effects::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     CommaPrinter comma(&quot;|&quot;);
</span><span class="lines">@@ -43,6 +87,8 @@
</span><span class="cx">         out.print(comma, &quot;ControlDependent&quot;);
</span><span class="cx">     if (writesSSAState)
</span><span class="cx">         out.print(comma, &quot;WritesSSAState&quot;);
</span><ins>+    if (readsSSAState)
+        out.print(comma, &quot;ReadsSSAState&quot;);
</ins><span class="cx">     if (writes)
</span><span class="cx">         out.print(comma, &quot;Writes:&quot;, writes);
</span><span class="cx">     if (reads)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Effectsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Effects.h (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Effects.h        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/B3Effects.h        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -49,6 +49,9 @@
</span><span class="cx">     // anyway.
</span><span class="cx">     bool writesSSAState { false };
</span><span class="cx"> 
</span><ins>+    // True if this reads from the SSA state. This is only used for Phi.
+    bool readsSSAState { false };
+
</ins><span class="cx">     HeapRange writes;
</span><span class="cx">     HeapRange reads;
</span><span class="cx"> 
</span><span class="lines">@@ -57,6 +60,10 @@
</span><span class="cx">         return terminal || exitsSideways || writesSSAState || writes;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Returns true if reordering instructions with these respective effects would change program
+    // behavior in an observable way.
+    bool interferes(const Effects&amp;) const;
+
</ins><span class="cx">     void dump(PrintStream&amp; out) const;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -74,15 +74,19 @@
</span><span class="cx">                 stackToStack.add(stackSlotValue, code.addStackSlot(stackSlotValue));
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        procedure.resetValueOwners(); // Used by crossesInterference().
+
</ins><span class="cx">         // Lower defs before uses on a global level. This is a good heuristic to lock down a
</span><span class="cx">         // hoisted address expression before we duplicate it back into the loop.
</span><span class="cx">         for (B3::BasicBlock* block : procedure.blocksInPreOrder()) {
</span><ins>+            currentBlock = block;
</ins><span class="cx">             // Reset some state.
</span><span class="cx">             insts.resize(0);
</span><span class="cx">             
</span><span class="cx">             // Process blocks in reverse order so we see uses before defs. That's what allows us
</span><span class="cx">             // to match patterns effectively.
</span><span class="cx">             for (unsigned i = block-&gt;size(); i--;) {
</span><ins>+                currentIndex = i;
</ins><span class="cx">                 currentValue = block-&gt;at(i);
</span><span class="cx">                 if (locked.contains(currentValue))
</span><span class="cx">                     continue;
</span><span class="lines">@@ -144,6 +148,29 @@
</span><span class="cx">         locked.add(value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool crossesInterference(Value* value)
+    {
+        // If it's in a foreign block, then be conservative. We could handle this if we were
+        // willing to do heavier analysis. For example, if we had liveness, then we could label
+        // values as &quot;crossing interference&quot; if they interfere with anything that they are live
+        // across. But, it's not clear how useful this would be.
+        if (value-&gt;owner != currentValue-&gt;owner)
+            return true;
+
+        Effects effects = value-&gt;effects();
+
+        for (unsigned i = currentIndex; i--;) {
+            Value* otherValue = currentBlock-&gt;at(i);
+            if (otherValue == value)
+                return false;
+            if (effects.interferes(otherValue-&gt;effects()))
+                return true;
+        }
+
+        ASSERT_NOT_REACHED();
+        return true;
+    }
+
</ins><span class="cx">     // This turns the given operand into an address.
</span><span class="cx">     Arg effectiveAddr(Value* address)
</span><span class="cx">     {
</span><span class="lines">@@ -179,11 +206,13 @@
</span><span class="cx"> 
</span><span class="cx">     Arg loadAddr(Value* loadValue)
</span><span class="cx">     {
</span><ins>+        if (loadValue-&gt;opcode() != Load)
+            return Arg();
</ins><span class="cx">         if (!canBeInternal(loadValue))
</span><span class="cx">             return Arg();
</span><del>-        if (loadValue-&gt;opcode() == Load)
-            return addr(loadValue);
-        return Arg();
</del><ins>+        if (crossesInterference(loadValue))
+            return Arg();
+        return addr(loadValue);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Arg imm(Value* value)
</span><span class="lines">@@ -289,11 +318,6 @@
</span><span class="cx">     template&lt;Air::Opcode opcode, Commutativity commutativity = NotCommutative&gt;
</span><span class="cx">     bool tryAppendStoreBinOp(Value* left, Value* right)
</span><span class="cx">     {
</span><del>-        // FIXME: This fails to check if there are any effects between the Load and the Store that
-        // could clobber the loaded value. We need to check such things because we are effectively
-        // sinking the load.
-        // https://bugs.webkit.org/show_bug.cgi?id=150534
-        
</del><span class="cx">         Arg storeAddr = addr(currentValue);
</span><span class="cx">         ASSERT(storeAddr);
</span><span class="cx"> 
</span><span class="lines">@@ -366,6 +390,8 @@
</span><span class="cx">     Vector&lt;Vector&lt;Inst, 4&gt;&gt; insts;
</span><span class="cx">     Vector&lt;Inst&gt; prologue;
</span><span class="cx"> 
</span><ins>+    B3::BasicBlock* currentBlock;
+    unsigned currentIndex;
</ins><span class="cx">     Value* currentValue;
</span><span class="cx"> 
</span><span class="cx">     // The address selector will match any pattern where the input operands are available as Tmps.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.cpp (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.cpp        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -52,6 +52,14 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Procedure::resetValueOwners()
+{
+    for (BasicBlock* block : *this) {
+        for (Value* value : *block)
+            value-&gt;owner = block;
+    }
+}
+
</ins><span class="cx"> void Procedure::resetReachability()
</span><span class="cx"> {
</span><span class="cx">     B3::resetReachability(m_blocks);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.h (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.h        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.h        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     template&lt;typename ValueType, typename... Arguments&gt;
</span><span class="cx">     ValueType* add(Arguments...);
</span><span class="cx"> 
</span><ins>+    void resetValueOwners();
</ins><span class="cx">     void resetReachability();
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void dump(PrintStream&amp;) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.cpp (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/B3Value.cpp        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -168,7 +168,6 @@
</span><span class="cx">     case Below:
</span><span class="cx">     case AboveEqual:
</span><span class="cx">     case BelowEqual:
</span><del>-    case Phi:
</del><span class="cx">         break;
</span><span class="cx">     case Div:
</span><span class="cx">         result.controlDependent = true;
</span><span class="lines">@@ -209,6 +208,9 @@
</span><span class="cx">     case Upsilon:
</span><span class="cx">         result.writesSSAState = true;
</span><span class="cx">         break;
</span><ins>+    case Phi:
+        result.readsSSAState = true;
+        break;
</ins><span class="cx">     case Jump:
</span><span class="cx">     case Branch:
</span><span class="cx">     case Switch:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.h (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.h        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/B3Value.h        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -197,7 +197,7 @@
</span><span class="cx">     AdjacencyList m_children;
</span><span class="cx"> 
</span><span class="cx"> public:
</span><del>-    BasicBlock* owner { nullptr }; // computed lazily.
</del><ins>+    BasicBlock* owner { nullptr }; // computed by Procedure::resetValueOwners().
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class DeepValueDump {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -235,6 +235,33 @@
</span><span class="cx">     CHECK(slot == 37 + amount);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testStoreAddLoadInterference(int amount)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    int slot = 37;
+    ConstPtrValue* slotPtr = root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;slot);
+    ArgumentRegValue* otherSlotPtr =
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* load = root-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, Origin(), slotPtr);
+    root-&gt;appendNew&lt;MemoryValue&gt;(
+        proc, Store, Origin(),
+        root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 666),
+        otherSlotPtr);
+    root-&gt;appendNew&lt;MemoryValue&gt;(
+        proc, Store, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Add, Origin(),
+            load, root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), amount)),
+        slotPtr);
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 0));
+
+    CHECK(!compileAndRun&lt;int&gt;(proc, &amp;slot));
+    CHECK(slot == 37 + amount);
+}
+
</ins><span class="cx"> void testStoreAddAndLoad(int amount, int mask)
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -331,6 +358,39 @@
</span><span class="cx">     CHECK(compileAndRun&lt;int&gt;(proc) == array[0] + array[1]);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testLoadOffsetUsingAddInterference()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    int array[] = { 1, 2 };
+    ConstPtrValue* arrayPtr = root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), array);
+    ArgumentRegValue* otherArrayPtr =
+        root-&gt;appendNew&lt;ArgumentRegValue&gt;(proc, Origin(), GPRInfo::argumentGPR0);
+    Const32Value* theNumberOfTheBeast = root-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 666);
+    MemoryValue* left = root-&gt;appendNew&lt;MemoryValue&gt;(
+        proc, Load, Int32, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Add, Origin(), arrayPtr,
+            root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), 0)));
+    MemoryValue* right = root-&gt;appendNew&lt;MemoryValue&gt;(
+        proc, Load, Int32, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Add, Origin(), arrayPtr,
+            root-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), sizeof(int))));
+    root-&gt;appendNew&lt;MemoryValue&gt;(
+        proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0);
+    root-&gt;appendNew&lt;MemoryValue&gt;(
+        proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, sizeof(int));
+    root-&gt;appendNew&lt;ControlValue&gt;(
+        proc, Return, Origin(),
+        root-&gt;appendNew&lt;Value&gt;(
+            proc, Add, Origin(), left, right));
+    
+    CHECK(compileAndRun&lt;int&gt;(proc, &amp;array[0]) == 1 + 2);
+    CHECK(array[0] == 666);
+    CHECK(array[1] == 666);
+}
+
</ins><span class="cx"> void testLoadOffsetUsingAddNotConstant()
</span><span class="cx"> {
</span><span class="cx">     Procedure proc;
</span><span class="lines">@@ -443,12 +503,14 @@
</span><span class="cx">     RUN(testTrunc((static_cast&lt;int64_t&gt;(1) &lt;&lt; 40) + 42));
</span><span class="cx">     RUN(testAdd1(45));
</span><span class="cx">     RUN(testStoreAddLoad(46));
</span><ins>+    RUN(testStoreAddLoadInterference(52));
</ins><span class="cx">     RUN(testStoreAddAndLoad(47, 0xffff));
</span><span class="cx">     RUN(testStoreAddAndLoad(470000, 0xffff));
</span><span class="cx">     RUN(testAdd1Uncommuted(48));
</span><span class="cx">     RUN(testLoadOffset());
</span><span class="cx">     RUN(testLoadOffsetNotConstant());
</span><span class="cx">     RUN(testLoadOffsetUsingAdd());
</span><ins>+    RUN(testLoadOffsetUsingAddInterference());
</ins><span class="cx">     RUN(testLoadOffsetUsingAddNotConstant());
</span><span class="cx">     RUN(testFramePointer());
</span><span class="cx">     RUN(testStackSlot());
</span></span></pre></div>
<a id="trunkSourceWTFwtfMathExtrash"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MathExtras.h (191761 => 191762)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MathExtras.h        2015-10-29 23:13:10 UTC (rev 191761)
+++ trunk/Source/WTF/wtf/MathExtras.h        2015-10-29 23:42:04 UTC (rev 191762)
</span><span class="lines">@@ -428,6 +428,13 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(leftMin &lt;= leftMax);
</span><span class="cx">     ASSERT(rightMin &lt;= rightMax);
</span><ins>+    
+    // Empty ranges interfere with nothing.
+    if (leftMin == leftMax)
+        return false;
+    if (rightMin == rightMax)
+        return false;
+    
</ins><span class="cx">     if (leftMin &lt;= rightMin &amp;&amp; leftMax &gt; rightMin)
</span><span class="cx">         return true;
</span><span class="cx">     if (rightMin &lt;= leftMin &amp;&amp; rightMax &gt; leftMin)
</span></span></pre>
</div>
</div>

</body>
</html>