<!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>[191865] trunk</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/191865">191865</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-11-01 15:37:03 -0800 (Sun, 01 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>B3::reduceStrength's DCE should be more agro and less wrong
https://bugs.webkit.org/show_bug.cgi?id=150748

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

First of all, our DCE had a bug where it would keep Upsilons after it deleted the Phis that
they referenced. But our B3 DCE was also not aggressive enough. It would not eliminate
cycles. It was also probably slower than it needed to be, since it would eliminate all
never-referenced things on each fixpoint.

This adds a presume-everyone-is-dead-and-find-live-things style DCE. This is very natural to
write, except for Upsilons. For everything but Upsilons, it's just a worklist algorithm. For
Upsilons, it's a fixpoint. It works fine in the end.

I kept finding bugs in this algorithm when I tested it against my &quot;Complex&quot; test that I was
writing as a compile time benchmark. So, I include that test in this change. I also include
the small lowering extensions that it needed - shifting and zero extending.

This change also adds an LLVM version of the Complex test. Though the LLVM version feels
more natural to write because LLVM has traditional Phi's rather than our quirky Phi's, in
the end LLVM ends up performing very badly - 10x to 20x worse than B3. Some of that gap will
close once we give B3 a register allocator, but still, that's pretty good news for our B3
strategy.

* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::lshift64):
(JSC::MacroAssemblerX86_64::rshift64):
* assembler/X86Assembler.h:
(JSC::X86Assembler::shlq_i8r):
(JSC::X86Assembler::shlq_CLr):
(JSC::X86Assembler::imull_rr):
* b3/B3BasicBlock.cpp:
(JSC::B3::BasicBlock::replacePredecessor):
(JSC::B3::BasicBlock::dump):
(JSC::B3::BasicBlock::removeNops): Deleted.
* b3/B3BasicBlock.h:
(JSC::B3::BasicBlock::frequency):
* b3/B3Common.cpp:
(JSC::B3::shouldSaveIRBeforePhase):
(JSC::B3::shouldMeasurePhaseTiming):
* b3/B3Common.h:
(JSC::B3::isRepresentableAsImpl):
* b3/B3Generate.cpp:
(JSC::B3::generate):
(JSC::B3::generateToAir):
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::tryAnd):
(JSC::B3::Air::LowerToAir::tryShl):
(JSC::B3::Air::LowerToAir::tryStoreAddLoad):
(JSC::B3::Air::LowerToAir::tryTrunc):
(JSC::B3::Air::LowerToAir::tryZExt32):
(JSC::B3::Air::LowerToAir::tryArgumentReg):
* b3/B3LoweringMatcher.patterns:
* b3/B3PhaseScope.cpp:
(JSC::B3::PhaseScope::PhaseScope):
* b3/B3PhaseScope.h:
* b3/B3ReduceStrength.cpp:
* b3/B3TimingScope.cpp: Added.
(JSC::B3::TimingScope::TimingScope):
(JSC::B3::TimingScope::~TimingScope):
* b3/B3TimingScope.h: Added.
* b3/B3Validate.cpp:
* b3/air/AirAllocateStack.cpp:
(JSC::B3::Air::allocateStack):
* b3/air/AirGenerate.cpp:
(JSC::B3::Air::generate):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach&lt;Arg&gt;::forEach):
(JSC::B3::Air::Inst::forEach):
(JSC::B3::Air::isLshift32Valid):
(JSC::B3::Air::isLshift64Valid):
* b3/air/AirLiveness.h:
(JSC::B3::Air::Liveness::isAlive):
(JSC::B3::Air::Liveness::Liveness):
(JSC::B3::Air::Liveness::LocalCalc::execute):
* b3/air/AirOpcode.opcodes:
* b3/air/AirPhaseScope.cpp:
(JSC::B3::Air::PhaseScope::PhaseScope):
* b3/air/AirPhaseScope.h:
* b3/testb3.cpp:
(JSC::B3::testBranchEqualFoldPtr):
(JSC::B3::testComplex):
(JSC::B3::run):
* runtime/Options.h:

Source/WTF:

* wtf/GraphNodeWorklist.h:
(WTF::GraphNodeWorklist::saw): This method is super useful.

Tools:

Add an LLVM version of testb3's &quot;testComplex&quot;.

* ReducedFTL/ComplexTest.cpp: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<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="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerX86Assemblerh">trunk/Source/JavaScriptCore/assembler/X86Assembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3BasicBlockcpp">trunk/Source/JavaScriptCore/b3/B3BasicBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3BasicBlockh">trunk/Source/JavaScriptCore/b3/B3BasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Commoncpp">trunk/Source/JavaScriptCore/b3/B3Common.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Commonh">trunk/Source/JavaScriptCore/b3/B3Common.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="#trunkSourceJavaScriptCoreb3B3LoweringMatcherpatterns">trunk/Source/JavaScriptCore/b3/B3LoweringMatcher.patterns</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3PhaseScopecpp">trunk/Source/JavaScriptCore/b3/B3PhaseScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3PhaseScopeh">trunk/Source/JavaScriptCore/b3/B3PhaseScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp">trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Validatecpp">trunk/Source/JavaScriptCore/b3/B3Validate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateStackcpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGeneratecpp">trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInstInlinesh">trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLivenessh">trunk/Source/JavaScriptCore/b3/air/AirLiveness.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOpcodeopcodes">trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirPhaseScopecpp">trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirPhaseScopeh">trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfGraphNodeWorklisth">trunk/Source/WTF/wtf/GraphNodeWorklist.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3B3TimingScopecpp">trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3TimingScopeh">trunk/Source/JavaScriptCore/b3/B3TimingScope.h</a></li>
<li><a href="#trunkToolsReducedFTLComplexTestcpp">trunk/Tools/ReducedFTL/ComplexTest.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -1,3 +1,91 @@
</span><ins>+2015-10-31  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        B3::reduceStrength's DCE should be more agro and less wrong
+        https://bugs.webkit.org/show_bug.cgi?id=150748
+
+        Reviewed by Geoffrey Garen.
+
+        First of all, our DCE had a bug where it would keep Upsilons after it deleted the Phis that
+        they referenced. But our B3 DCE was also not aggressive enough. It would not eliminate
+        cycles. It was also probably slower than it needed to be, since it would eliminate all
+        never-referenced things on each fixpoint.
+
+        This adds a presume-everyone-is-dead-and-find-live-things style DCE. This is very natural to
+        write, except for Upsilons. For everything but Upsilons, it's just a worklist algorithm. For
+        Upsilons, it's a fixpoint. It works fine in the end.
+
+        I kept finding bugs in this algorithm when I tested it against my &quot;Complex&quot; test that I was
+        writing as a compile time benchmark. So, I include that test in this change. I also include
+        the small lowering extensions that it needed - shifting and zero extending.
+
+        This change also adds an LLVM version of the Complex test. Though the LLVM version feels
+        more natural to write because LLVM has traditional Phi's rather than our quirky Phi's, in
+        the end LLVM ends up performing very badly - 10x to 20x worse than B3. Some of that gap will
+        close once we give B3 a register allocator, but still, that's pretty good news for our B3
+        strategy.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::lshift64):
+        (JSC::MacroAssemblerX86_64::rshift64):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::shlq_i8r):
+        (JSC::X86Assembler::shlq_CLr):
+        (JSC::X86Assembler::imull_rr):
+        * b3/B3BasicBlock.cpp:
+        (JSC::B3::BasicBlock::replacePredecessor):
+        (JSC::B3::BasicBlock::dump):
+        (JSC::B3::BasicBlock::removeNops): Deleted.
+        * b3/B3BasicBlock.h:
+        (JSC::B3::BasicBlock::frequency):
+        * b3/B3Common.cpp:
+        (JSC::B3::shouldSaveIRBeforePhase):
+        (JSC::B3::shouldMeasurePhaseTiming):
+        * b3/B3Common.h:
+        (JSC::B3::isRepresentableAsImpl):
+        * b3/B3Generate.cpp:
+        (JSC::B3::generate):
+        (JSC::B3::generateToAir):
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::tryAnd):
+        (JSC::B3::Air::LowerToAir::tryShl):
+        (JSC::B3::Air::LowerToAir::tryStoreAddLoad):
+        (JSC::B3::Air::LowerToAir::tryTrunc):
+        (JSC::B3::Air::LowerToAir::tryZExt32):
+        (JSC::B3::Air::LowerToAir::tryArgumentReg):
+        * b3/B3LoweringMatcher.patterns:
+        * b3/B3PhaseScope.cpp:
+        (JSC::B3::PhaseScope::PhaseScope):
+        * b3/B3PhaseScope.h:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3TimingScope.cpp: Added.
+        (JSC::B3::TimingScope::TimingScope):
+        (JSC::B3::TimingScope::~TimingScope):
+        * b3/B3TimingScope.h: Added.
+        * b3/B3Validate.cpp:
+        * b3/air/AirAllocateStack.cpp:
+        (JSC::B3::Air::allocateStack):
+        * b3/air/AirGenerate.cpp:
+        (JSC::B3::Air::generate):
+        * b3/air/AirInstInlines.h:
+        (JSC::B3::Air::ForEach&lt;Arg&gt;::forEach):
+        (JSC::B3::Air::Inst::forEach):
+        (JSC::B3::Air::isLshift32Valid):
+        (JSC::B3::Air::isLshift64Valid):
+        * b3/air/AirLiveness.h:
+        (JSC::B3::Air::Liveness::isAlive):
+        (JSC::B3::Air::Liveness::Liveness):
+        (JSC::B3::Air::Liveness::LocalCalc::execute):
+        * b3/air/AirOpcode.opcodes:
+        * b3/air/AirPhaseScope.cpp:
+        (JSC::B3::Air::PhaseScope::PhaseScope):
+        * b3/air/AirPhaseScope.h:
+        * b3/testb3.cpp:
+        (JSC::B3::testBranchEqualFoldPtr):
+        (JSC::B3::testComplex):
+        (JSC::B3::run):
+        * runtime/Options.h:
+
</ins><span class="cx"> 2015-11-01  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Add support for toStringTag
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -315,6 +315,8 @@
</span><span class="cx">                 0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */; };
</span><span class="cx">                 0F45703C1BE45F0A0062A629 /* AirReportUsedRegisters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F45703A1BE45F0A0062A629 /* AirReportUsedRegisters.cpp */; };
</span><span class="cx">                 0F45703D1BE45F0A0062A629 /* AirReportUsedRegisters.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */; };
</span><ins>+                0F4570401BE584CA0062A629 /* B3TimingScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F45703E1BE584CA0062A629 /* B3TimingScope.cpp */; };
+                0F4570411BE584CA0062A629 /* B3TimingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F45703F1BE584CA0062A629 /* B3TimingScope.h */; };
</ins><span class="cx">                 0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46808014BA572700BFE272 /* JITExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F46808314BA573100BFE272 /* JITExceptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F46807F14BA572700BFE272 /* JITExceptions.cpp */; };
</span><span class="cx">                 0F4680A314BA7F8D00BFE272 /* LLIntExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F46809E14BA7F8200BFE272 /* LLIntExceptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2333,6 +2335,8 @@
</span><span class="cx">                 0F4570371BE44C910062A629 /* AirEliminateDeadCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirEliminateDeadCode.h; path = b3/air/AirEliminateDeadCode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F45703A1BE45F0A0062A629 /* AirReportUsedRegisters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirReportUsedRegisters.cpp; path = b3/air/AirReportUsedRegisters.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirReportUsedRegisters.h; path = b3/air/AirReportUsedRegisters.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F45703E1BE584CA0062A629 /* B3TimingScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3TimingScope.cpp; path = b3/B3TimingScope.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F45703F1BE584CA0062A629 /* B3TimingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3TimingScope.h; path = b3/B3TimingScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F46807F14BA572700BFE272 /* JITExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITExceptions.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F46808014BA572700BFE272 /* JITExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITExceptions.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F46809D14BA7F8200BFE272 /* LLIntExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntExceptions.cpp; path = llint/LLIntExceptions.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4455,6 +4459,8 @@
</span><span class="cx">                                 0FEC84EE1BDACDAC0080FF74 /* B3SwitchCase.h */,
</span><span class="cx">                                 0FEC84EF1BDACDAC0080FF74 /* B3SwitchValue.cpp */,
</span><span class="cx">                                 0FEC84F01BDACDAC0080FF74 /* B3SwitchValue.h */,
</span><ins>+                                0F45703E1BE584CA0062A629 /* B3TimingScope.cpp */,
+                                0F45703F1BE584CA0062A629 /* B3TimingScope.h */,
</ins><span class="cx">                                 0FEC84F11BDACDAC0080FF74 /* B3Type.cpp */,
</span><span class="cx">                                 0FEC84F21BDACDAC0080FF74 /* B3Type.h */,
</span><span class="cx">                                 0FEC84F31BDACDAC0080FF74 /* B3UpsilonValue.cpp */,
</span><span class="lines">@@ -6608,6 +6614,7 @@
</span><span class="cx">                                 A7E5A3A81797432D00E893C0 /* CompilationResult.h in Headers */,
</span><span class="cx">                                 BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */,
</span><span class="cx">                                 996B731D1BDA08EF00331B84 /* JSGlobalObject.lut.h in Headers */,
</span><ins>+                                0F4570411BE584CA0062A629 /* B3TimingScope.h in Headers */,
</ins><span class="cx">                                 996B731F1BDA08EF00331B84 /* JSPromisePrototype.lut.h in Headers */,
</span><span class="cx">                                 0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */,
</span><span class="cx">                                 0FDB2CEA174896C7007B3C1B /* ConcurrentJITLock.h in Headers */,
</span><span class="lines">@@ -8575,6 +8582,7 @@
</span><span class="cx">                                 7C184E1A17BEDBD3007CB63A /* JSPromise.cpp in Sources */,
</span><span class="cx">                                 7C184E2217BEE240007CB63A /* JSPromiseConstructor.cpp in Sources */,
</span><span class="cx">                                 7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */,
</span><ins>+                                0F4570401BE584CA0062A629 /* B3TimingScope.cpp in Sources */,
</ins><span class="cx">                                 7C184E1E17BEE22E007CB63A /* JSPromisePrototype.cpp in Sources */,
</span><span class="cx">                                 2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */,
</span><span class="cx">                                 E3EF88741B66DF23003F26CB /* JSPropertyNameIterator.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -329,6 +329,20 @@
</span><span class="cx">         m_assembler.shlq_i8r(imm.m_value, dest);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void lshift64(RegisterID src, RegisterID dest)
+    {
+        ASSERT(src != dest);
+        
+        if (src == X86Registers::ecx)
+            m_assembler.shlq_CLr(dest);
+        else {
+            // Can only shift by ecx, so we do some swapping if we see anything else.
+            swap(src, X86Registers::ecx);
+            m_assembler.shlq_CLr(dest);
+            swap(src, X86Registers::ecx);
+        }
+    }
+    
</ins><span class="cx">     void rshift64(TrustedImm32 imm, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         m_assembler.sarq_i8r(imm.m_value, dest);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerX86Assemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/X86Assembler.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/assembler/X86Assembler.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -910,6 +910,11 @@
</span><span class="cx">             m_formatter.immediate8(imm);
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
+    void shlq_CLr(RegisterID dst)
+    {
+        m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
+    }
</ins><span class="cx"> #endif // CPU(X86_64)
</span><span class="cx"> 
</span><span class="cx">     void imull_rr(RegisterID src, RegisterID dst)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BasicBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BasicBlock.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BasicBlock.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3BasicBlock.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -67,20 +67,6 @@
</span><span class="cx">     return B3::replacePredecessor(this, from, to);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BasicBlock::removeNops(Procedure&amp; procedure)
-{
-    unsigned sourceIndex = 0;
-    unsigned targetIndex = 0;
-    while (sourceIndex &lt; size()) {
-        Value* value = m_values[sourceIndex++];
-        if (value-&gt;opcode() == Nop)
-            procedure.deleteValue(value);
-        else
-            m_values[targetIndex++] = value;
-    }
-    m_values.resize(targetIndex);
-}
-
</del><span class="cx"> void BasicBlock::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     out.print(dumpPrefix, m_index);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BasicBlock.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BasicBlock.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3BasicBlock.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -95,8 +95,6 @@
</span><span class="cx"> 
</span><span class="cx">     double frequency() const { return m_frequency; }
</span><span class="cx"> 
</span><del>-    void removeNops(Procedure&amp;);
-
</del><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     void deepDump(PrintStream&amp;) const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Commoncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Common.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Common.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3Common.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -59,6 +59,11 @@
</span><span class="cx">     return Options::verboseValidationFailure();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool shouldMeasurePhaseTiming()
+{
+    return Options::logB3PhaseTimes();
+}
+
</ins><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Common.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Common.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3Common.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> bool shouldValidateIR();
</span><span class="cx"> bool shouldValidateIRAtEachPhase();
</span><span class="cx"> bool shouldSaveIRBeforePhase();
</span><ins>+bool shouldMeasurePhaseTiming();
</ins><span class="cx"> 
</span><span class="cx"> template&lt;typename ResultType, typename InputType, typename BitsType&gt;
</span><span class="cx"> inline bool isRepresentableAsImpl(InputType originalValue)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Generatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Generate.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3Generate.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -35,12 +35,15 @@
</span><span class="cx"> #include &quot;B3LowerToAir.h&quot;
</span><span class="cx"> #include &quot;B3Procedure.h&quot;
</span><span class="cx"> #include &quot;B3ReduceStrength.h&quot;
</span><ins>+#include &quot;B3TimingScope.h&quot;
</ins><span class="cx"> #include &quot;B3Validate.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><span class="cx"> void generate(Procedure&amp; procedure, CCallHelpers&amp; jit)
</span><span class="cx"> {
</span><ins>+    TimingScope timingScope(&quot;generate&quot;);
+
</ins><span class="cx">     Air::Code code;
</span><span class="cx">     generateToAir(procedure, code);
</span><span class="cx">     Air::generate(code, jit);
</span><span class="lines">@@ -48,6 +51,8 @@
</span><span class="cx"> 
</span><span class="cx"> void generateToAir(Procedure&amp; procedure, Air::Code&amp; code)
</span><span class="cx"> {
</span><ins>+    TimingScope timingScope(&quot;generateToAir&quot;);
+    
</ins><span class="cx">     // We don't require the incoming IR to have predecessors computed.
</span><span class="cx">     procedure.resetReachability();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LowerToAircpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -585,6 +585,22 @@
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
+    bool tryShl(Value* value, Value* amount)
+    {
+        Air::Opcode opcode = value-&gt;type() == Int32 ? Lshift32 : Lshift64;
+
+        if (imm(amount)) {
+            append(Move, tmp(value), tmp(currentValue));
+            append(opcode, imm(amount), tmp(currentValue));
+            return true;
+        }
+
+        append(Move, tmp(value), tmp(currentValue));
+        append(Move, tmp(amount), Tmp(X86Registers::ecx));
+        append(opcode, Tmp(X86Registers::ecx), tmp(currentValue));
+        return true;
+    }
</ins><span class="cx">     
</span><span class="cx">     bool tryStoreAddLoad(Value* left, Value* right, Value*)
</span><span class="cx">     {
</span><span class="lines">@@ -650,6 +666,14 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool tryZExt32(Value* value)
+    {
+        // FIXME: This could just be a copy propagation rule, with caveats. ;-)
+        // https://bugs.webkit.org/show_bug.cgi?id=150775
+        append(Move32, tmp(value), tmp(currentValue));
+        return true;
+    }
+
</ins><span class="cx">     bool tryArgumentReg()
</span><span class="cx">     {
</span><span class="cx">         prologue.append(Inst(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3LoweringMatcherpatterns"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3LoweringMatcher.patterns (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3LoweringMatcher.patterns        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3LoweringMatcher.patterns        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -34,6 +34,8 @@
</span><span class="cx"> Sub = Sub(left, right)
</span><span class="cx"> And = BitAnd(left, right)
</span><span class="cx"> 
</span><ins>+Shl = Shl(value, amount)
+
</ins><span class="cx"> StoreAddLoad = Store(Add(left, right), address)
</span><span class="cx"> StoreSubLoad = Store(Add(left, right), address)
</span><span class="cx"> StoreAndLoad = Store(BitAnd(left, right), address)
</span><span class="lines">@@ -42,6 +44,8 @@
</span><span class="cx"> TruncArgumentReg = Trunc(argumentReg = ArgumentReg())
</span><span class="cx"> Trunc = Trunc(value)
</span><span class="cx"> 
</span><ins>+ZExt32 = ZExt32(value)
+
</ins><span class="cx"> ArgumentReg = ArgumentReg()
</span><span class="cx"> 
</span><span class="cx"> Const32 = Const32()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3PhaseScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3PhaseScope.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3PhaseScope.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3PhaseScope.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> PhaseScope::PhaseScope(Procedure&amp; procedure, const char* name)
</span><span class="cx">     : m_procedure(procedure)
</span><span class="cx">     , m_name(name)
</span><ins>+    , m_timingScope(name)
</ins><span class="cx"> {
</span><span class="cx">     if (shouldDumpIRAtEachPhase()) {
</span><span class="cx">         dataLog(&quot;B3 after &quot;, procedure.lastPhaseName(), &quot;, before &quot;, name, &quot;:\n&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3PhaseScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3PhaseScope.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3PhaseScope.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3PhaseScope.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3TimingScope.h&quot;
</ins><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -44,6 +45,7 @@
</span><span class="cx"> private:
</span><span class="cx">     Procedure&amp; m_procedure;
</span><span class="cx">     const char* m_name;
</span><ins>+    TimingScope m_timingScope;
</ins><span class="cx">     CString m_dumpBefore;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -29,12 +29,15 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3ControlValue.h&quot;
</span><ins>+#include &quot;B3IndexSet.h&quot;
</ins><span class="cx"> #include &quot;B3InsertionSetInlines.h&quot;
</span><span class="cx"> #include &quot;B3MemoryValue.h&quot;
</span><span class="cx"> #include &quot;B3PhaseScope.h&quot;
</span><span class="cx"> #include &quot;B3ProcedureInlines.h&quot;
</span><ins>+#include &quot;B3UpsilonValue.h&quot;
</ins><span class="cx"> #include &quot;B3UseCounts.h&quot;
</span><span class="cx"> #include &quot;B3ValueInlines.h&quot;
</span><ins>+#include &lt;wtf/GraphNodeWorklist.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><span class="lines">@@ -61,8 +64,6 @@
</span><span class="cx">                 for (m_index = 0; m_index &lt; block-&gt;size(); ++m_index)
</span><span class="cx">                     process();
</span><span class="cx">                 m_insertionSet.execute(m_block);
</span><del>-
-                block-&gt;removeNops(m_proc);
</del><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             if (m_changedCFG) {
</span><span class="lines">@@ -70,13 +71,7 @@
</span><span class="cx">                 m_changed = true;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            UseCounts useCounts(m_proc);
-            for (Value* value : m_proc.values()) {
-                if (!useCounts[value] &amp;&amp; !value-&gt;effects().mustExecute()) {
-                    value-&gt;replaceWithNop();
-                    m_changed = true;
-                }
-            }
</del><ins>+            killDeadCode();
</ins><span class="cx">             
</span><span class="cx">             result |= m_changed;
</span><span class="cx">         } while (m_changed);
</span><span class="lines">@@ -337,6 +332,64 @@
</span><span class="cx">         m_changed = true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void killDeadCode()
+    {
+        GraphNodeWorklist&lt;Value*, IndexSet&lt;Value&gt;&gt; worklist;
+        Vector&lt;UpsilonValue*, 64&gt; upsilons;
+        for (BasicBlock* block : m_proc) {
+            for (Value* value : *block) {
+                Effects effects = value-&gt;effects();
+                // We don't care about SSA Effects, since we model them more accurately than the
+                // effects() method does.
+                effects.writesSSAState = false;
+                effects.readsSSAState = false;
+                if (effects.mustExecute())
+                    worklist.push(value);
+                if (UpsilonValue* upsilon = value-&gt;as&lt;UpsilonValue&gt;())
+                    upsilons.append(upsilon);
+            }
+        }
+        for (;;) {
+            while (Value* value = worklist.pop()) {
+                for (Value* child : value-&gt;children())
+                    worklist.push(child);
+            }
+            
+            bool didPush = false;
+            for (size_t upsilonIndex = 0; upsilonIndex &lt; upsilons.size(); ++upsilonIndex) {
+                UpsilonValue* upsilon = upsilons[upsilonIndex];
+                if (worklist.saw(upsilon-&gt;phi())) {
+                    worklist.push(upsilon);
+                    upsilons[upsilonIndex--] = upsilons.last();
+                    upsilons.takeLast();
+                    didPush = true;
+                }
+            }
+            if (!didPush)
+                break;
+        }
+
+        for (BasicBlock* block : m_proc) {
+            size_t sourceIndex = 0;
+            size_t targetIndex = 0;
+            while (sourceIndex &lt; block-&gt;size()) {
+                Value* value = block-&gt;at(sourceIndex++);
+                if (worklist.saw(value))
+                    block-&gt;at(targetIndex++) = value;
+                else {
+                    m_proc.deleteValue(value);
+                    
+                    // It's not entirely clear if this is needed. I think it makes sense to have
+                    // this force a rerun of the fixpoint for now, since that will make it easier
+                    // to do peephole optimizations: removing dead code will make the peephole
+                    // easier to spot.
+                    m_changed = true;
+                }
+            }
+            block-&gt;values().resize(targetIndex);
+        }
+    }
+
</ins><span class="cx">     Procedure&amp; m_proc;
</span><span class="cx">     InsertionSet m_insertionSet;
</span><span class="cx">     BasicBlock* m_block;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3TimingScopecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp (0 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -0,0 +1,55 @@
</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;B3TimingScope.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;B3Common.h&quot;
+#include &lt;wtf/CurrentTime.h&gt;
+#include &lt;wtf/DataLog.h&gt;
+
+namespace JSC { namespace B3 {
+
+TimingScope::TimingScope(const char* name)
+    : m_name(name)
+{
+    if (shouldMeasurePhaseTiming())
+        m_before = monotonicallyIncreasingTimeMS();
+}
+
+TimingScope::~TimingScope()
+{
+    if (shouldMeasurePhaseTiming()) {
+        double after = monotonicallyIncreasingTimeMS();
+        dataLog(&quot;[B3] &quot;, m_name, &quot; took: &quot;, after - m_before, &quot; ms.\n&quot;);
+    }
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3TimingScopeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/B3TimingScope.h (0 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3TimingScope.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/B3TimingScope.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -0,0 +1,51 @@
</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 B3TimingScope_h
+#define B3TimingScope_h
+
+#if ENABLE(B3_JIT)
+
+#include &lt;wtf/Noncopyable.h&gt;
+
+namespace JSC { namespace B3 {
+
+class TimingScope {
+    WTF_MAKE_NONCOPYABLE(TimingScope);
+public:
+    TimingScope(const char* name);
+    ~TimingScope();
+
+private:
+    const char* m_name;
+    double m_before;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3TimingScope_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Validatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Validate.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/B3Validate.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -61,12 +61,12 @@
</span><span class="cx">     {
</span><span class="cx">         HashSet&lt;BasicBlock*&gt; blocks;
</span><span class="cx">         HashSet&lt;Value*&gt; valueInProc;
</span><del>-        HashSet&lt;Value*&gt; valueInBlock;
</del><ins>+        HashMap&lt;Value*, unsigned&gt; valueInBlock;
</ins><span class="cx"> 
</span><span class="cx">         for (BasicBlock* block : m_procedure) {
</span><span class="cx">             blocks.add(block);
</span><span class="cx">             for (Value* value : *block)
</span><del>-                valueInBlock.add(value);
</del><ins>+                valueInBlock.add(value, 0).iterator-&gt;value++;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         for (Value* value : m_procedure.values())
</span><span class="lines">@@ -74,8 +74,10 @@
</span><span class="cx"> 
</span><span class="cx">         for (Value* value : valueInProc)
</span><span class="cx">             VALIDATE(valueInBlock.contains(value), (&quot;At &quot;, *value));
</span><del>-        for (Value* value : valueInBlock)
-            VALIDATE(valueInProc.contains(value), (&quot;At &quot;, *value));
</del><ins>+        for (auto&amp; entry : valueInBlock) {
+            VALIDATE(valueInProc.contains(entry.key), (&quot;At &quot;, *entry.key));
+            VALIDATE(entry.value == 1, (&quot;At &quot;, *entry.key));
+        }
</ins><span class="cx"> 
</span><span class="cx">         for (Value* value : valueInProc) {
</span><span class="cx">             for (Value* child : value-&gt;children())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateStackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -41,11 +41,6 @@
</span><span class="cx"> 
</span><span class="cx"> const bool verbose = false;
</span><span class="cx"> 
</span><del>-bool argumentIsOnStack(const Arg&amp; arg)
-{
-    return arg.isStack() &amp;&amp; arg.stackSlot()-&gt;kind() == StackSlotKind::Anonymous;
-}
-
</del><span class="cx"> bool attemptAssignment(
</span><span class="cx">     StackSlot* slot, intptr_t offsetFromFP, const Vector&lt;StackSlot*&gt;&amp; otherSlots)
</span><span class="cx"> {
</span><span class="lines">@@ -141,34 +136,35 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Now we handle the anonymous slots.
</span><del>-    // FIXME: We should tell Liveness to only track StackSlots.
-    // https://bugs.webkit.org/show_bug.cgi?id=150751
-    Liveness&lt;Arg&gt; liveness(code);
</del><ins>+    Liveness&lt;StackSlot*&gt; liveness(code);
</ins><span class="cx">     IndexMap&lt;StackSlot, HashSet&lt;StackSlot*&gt;&gt; interference(code.stackSlots().size());
</span><span class="cx">     Vector&lt;StackSlot*&gt; slots;
</span><span class="cx"> 
</span><span class="cx">     for (BasicBlock* block : code) {
</span><del>-        Liveness&lt;Arg&gt;::LocalCalc localCalc(liveness, block);
</del><ins>+        Liveness&lt;StackSlot*&gt;::LocalCalc localCalc(liveness, block);
</ins><span class="cx"> 
</span><span class="cx">         auto interfere = [&amp;] (Inst&amp; inst) {
</span><span class="cx">             if (verbose)
</span><del>-                dataLog(&quot;Interfering: &quot;, listDump(localCalc.live()), &quot;\n&quot;);
</del><ins>+                dataLog(&quot;Interfering: &quot;, pointerListDump(localCalc.live()), &quot;\n&quot;);
</ins><span class="cx">             
</span><span class="cx">             // Form a clique of stack slots that interfere. First find the list of stack slots
</span><span class="cx">             // that are live right now.
</span><span class="cx">             slots.resize(0);
</span><del>-            for (Arg arg : localCalc.live()) {
-                if (argumentIsOnStack(arg))
-                    slots.append(arg.stackSlot());
</del><ins>+            for (StackSlot* slot : localCalc.live()) {
+                if (slot-&gt;kind() == StackSlotKind::Anonymous)
+                    slots.append(slot);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             // We mustn't mandate that the input code is optimal. Therefore, it may have dead stores
</span><span class="cx">             // to the stack. We need to treat these as interfering.
</span><span class="cx">             inst.forEachArg(
</span><span class="cx">                 [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type) {
</span><del>-                    if (Arg::isDef(role) &amp;&amp; argumentIsOnStack(arg)
-                        &amp;&amp; !localCalc.live().contains(arg))
-                        slots.append(arg.stackSlot());
</del><ins>+                    if (Arg::isDef(role) &amp;&amp; arg.isStack()) {
+                        StackSlot* slot = arg.stackSlot();
+                        if (slot-&gt;kind() == StackSlotKind::Anonymous
+                            &amp;&amp; !localCalc.live().contains(slot))
+                            slots.append(slot);
+                    }
</ins><span class="cx">                 });
</span><span class="cx">             
</span><span class="cx">             if (verbose)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGeneratecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -38,12 +38,15 @@
</span><span class="cx"> #include &quot;AirValidate.h&quot;
</span><span class="cx"> #include &quot;B3Common.h&quot;
</span><span class="cx"> #include &quot;B3IndexMap.h&quot;
</span><ins>+#include &quot;B3TimingScope.h&quot;
</ins><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><span class="cx"> void generate(Code&amp; code, CCallHelpers&amp; jit)
</span><span class="cx"> {
</span><ins>+    TimingScope timingScope(&quot;Air::generate&quot;);
+    
</ins><span class="cx">     // We don't expect the incoming code to have predecessors computed.
</span><span class="cx">     code.resetReachability();
</span><span class="cx">     
</span><span class="lines">@@ -91,6 +94,8 @@
</span><span class="cx">         dataLog(code);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    TimingScope codeGenTimingScope(&quot;Air::generate backend&quot;);
+
</ins><span class="cx">     // And now, we generate code.
</span><span class="cx">     jit.emitFunctionPrologue();
</span><span class="cx">     jit.addPtr(CCallHelpers::TrustedImm32(-code.frameSize()), MacroAssembler::stackPointerRegister);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInstInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -51,6 +51,20 @@
</span><span class="cx">         inst.forEachArg(functor);
</span><span class="cx">     }
</span><span class="cx"> };
</span><ins>+template&lt;&gt; struct ForEach&lt;StackSlot*&gt; {
+    template&lt;typename Functor&gt;
+    static void forEach(Inst&amp; inst, const Functor&amp; functor)
+    {
+        inst.forEachArg(
+            [&amp;] (Arg&amp; arg, Arg::Role role, Arg::Type type) {
+                if (!arg.isStack())
+                    return;
+                StackSlot* stackSlot = arg.stackSlot();
+                functor(stackSlot, role, type);
+                arg = Arg::stack(stackSlot);
+            });
+    }
+};
</ins><span class="cx"> 
</span><span class="cx"> template&lt;typename Thing, typename Functor&gt;
</span><span class="cx"> void Inst::forEach(const Functor&amp; functor)
</span><span class="lines">@@ -90,6 +104,11 @@
</span><span class="cx">     return isShiftValid(inst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool isLshift64Valid(const Inst&amp; inst)
+{
+    return isShiftValid(inst);
+}
+
</ins><span class="cx"> } } } // namespace JSC::B3::Air
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLiveness.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -39,6 +39,11 @@
</span><span class="cx"> template&lt;typename Thing&gt;
</span><span class="cx"> class Liveness {
</span><span class="cx"> public:
</span><ins>+    template&lt;typename T&gt;
+    static bool isAlive(const T&amp; thing) { return thing.isAlive(); }
+
+    static bool isAlive(StackSlot* slot) { return slot-&gt;kind() == StackSlotKind::Anonymous; }
+    
</ins><span class="cx">     Liveness(Code&amp; code)
</span><span class="cx">     {
</span><span class="cx">         m_liveAtHead.resize(code.size());
</span><span class="lines">@@ -94,24 +99,16 @@
</span><span class="cx">             // First handle def's.
</span><span class="cx">             inst.forEach&lt;Thing&gt;(
</span><span class="cx">                 [this] (Thing&amp; arg, Arg::Role role, Arg::Type) {
</span><del>-                    if (!arg.isAlive())
</del><ins>+                    if (!isAlive(arg))
</ins><span class="cx">                         return;
</span><span class="cx">                     if (Arg::isDef(role))
</span><span class="cx">                         m_live.remove(arg);
</span><span class="cx">                 });
</span><span class="cx"> 
</span><del>-            // Next handle clobbered registers.
-            if (inst.hasSpecial()) {
-                inst.extraClobberedRegs().forEach(
-                    [this] (Reg reg) {
-                        m_live.remove(Thing(Tmp(reg)));
-                    });
-            }
-            
</del><span class="cx">             // Finally handle use's.
</span><span class="cx">             inst.forEach&lt;Thing&gt;(
</span><span class="cx">                 [this] (Thing&amp; arg, Arg::Role role, Arg::Type) {
</span><del>-                    if (!arg.isAlive())
</del><ins>+                    if (!isAlive(arg))
</ins><span class="cx">                         return;
</span><span class="cx">                     if (Arg::isUse(role))
</span><span class="cx">                         m_live.add(arg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -107,6 +107,10 @@
</span><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><ins>+Lshift64 U:G, UD:G
+    Tmp*, Tmp
+    Imm, Tmp
+
</ins><span class="cx"> Mul32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirPhaseScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> PhaseScope::PhaseScope(Code&amp; code, const char* name)
</span><span class="cx">     : m_code(code)
</span><span class="cx">     , m_name(name)
</span><ins>+    , m_timingScope(name)
</ins><span class="cx"> {
</span><span class="cx">     if (shouldDumpIRAtEachPhase()) {
</span><span class="cx">         dataLog(&quot;Air after &quot;, code.lastPhaseName(), &quot;, before &quot;, name, &quot;:\n&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirPhaseScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/air/AirPhaseScope.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;B3TimingScope.h&quot;
</ins><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -44,6 +45,7 @@
</span><span class="cx"> private:
</span><span class="cx">     Code&amp; m_code;
</span><span class="cx">     const char* m_name;
</span><ins>+    TimingScope m_timingScope;
</ins><span class="cx">     CString m_dumpBefore;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -1066,6 +1066,141 @@
</span><span class="cx">     CHECK(compileAndRun&lt;int&gt;(proc) == !value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void testComplex(unsigned numVars, unsigned numConstructs)
+{
+    double before = monotonicallyIncreasingTimeMS();
+    
+    Procedure proc;
+    BasicBlock* current = proc.addBlock();
+
+    Const32Value* one = current-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 1);
+
+    Vector&lt;int32_t&gt; varSlots;
+    for (unsigned i = numVars; i--;)
+        varSlots.append(i);
+
+    Vector&lt;Value*&gt; vars;
+    for (int32_t&amp; varSlot : varSlots) {
+        Value* varSlotPtr = current-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), &amp;varSlot);
+        vars.append(current-&gt;appendNew&lt;MemoryValue&gt;(proc, Load, Int32, Origin(), varSlotPtr));
+    }
+
+    for (unsigned i = 0; i &lt; numConstructs; ++i) {
+        if (i &amp; 1) {
+            // Control flow diamond.
+            unsigned predicateVarIndex = (i &gt;&gt; 1) % numVars;
+            unsigned thenIncVarIndex = ((i &gt;&gt; 1) + 1) % numVars;
+            unsigned elseIncVarIndex = ((i &gt;&gt; 1) + 2) % numVars;
+
+            BasicBlock* thenBlock = proc.addBlock();
+            BasicBlock* elseBlock = proc.addBlock();
+            BasicBlock* continuation = proc.addBlock();
+
+            current-&gt;appendNew&lt;ControlValue&gt;(
+                proc, Branch, Origin(), vars[predicateVarIndex],
+                FrequentedBlock(thenBlock), FrequentedBlock(elseBlock));
+
+            UpsilonValue* thenThenResult = thenBlock-&gt;appendNew&lt;UpsilonValue&gt;(
+                proc, Origin(),
+                thenBlock-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), vars[thenIncVarIndex], one));
+            UpsilonValue* thenElseResult = thenBlock-&gt;appendNew&lt;UpsilonValue&gt;(
+                proc, Origin(), vars[elseIncVarIndex]);
+            thenBlock-&gt;appendNew&lt;ControlValue&gt;(proc, Jump, Origin(), FrequentedBlock(continuation));
+
+            UpsilonValue* elseElseResult = elseBlock-&gt;appendNew&lt;UpsilonValue&gt;(
+                proc, Origin(),
+                elseBlock-&gt;appendNew&lt;Value&gt;(proc, Add, Origin(), vars[elseIncVarIndex], one));
+            UpsilonValue* elseThenResult = elseBlock-&gt;appendNew&lt;UpsilonValue&gt;(
+                proc, Origin(), vars[thenIncVarIndex]);
+            elseBlock-&gt;appendNew&lt;ControlValue&gt;(proc, Jump, Origin(), FrequentedBlock(continuation));
+
+            Value* thenPhi = continuation-&gt;appendNew&lt;Value&gt;(proc, Phi, Int32, Origin());
+            thenThenResult-&gt;setPhi(thenPhi);
+            elseThenResult-&gt;setPhi(thenPhi);
+            vars[thenIncVarIndex] = thenPhi;
+            
+            Value* elsePhi = continuation-&gt;appendNew&lt;Value&gt;(proc, Phi, Int32, Origin());
+            thenElseResult-&gt;setPhi(elsePhi);
+            elseElseResult-&gt;setPhi(elsePhi);
+            vars[elseIncVarIndex] = thenPhi;
+            
+            current = continuation;
+        } else {
+            // Loop.
+
+            BasicBlock* loopEntry = proc.addBlock();
+            BasicBlock* loopReentry = proc.addBlock();
+            BasicBlock* loopBody = proc.addBlock();
+            BasicBlock* loopExit = proc.addBlock();
+            BasicBlock* loopSkip = proc.addBlock();
+            BasicBlock* continuation = proc.addBlock();
+            
+            Value* startIndex = vars[(i &gt;&gt; 1) % numVars];
+            Value* startSum = current-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 0);
+            current-&gt;appendNew&lt;ControlValue&gt;(
+                proc, Branch, Origin(), startIndex,
+                FrequentedBlock(loopEntry), FrequentedBlock(loopSkip));
+
+            UpsilonValue* startIndexForBody = loopEntry-&gt;appendNew&lt;UpsilonValue&gt;(
+                proc, Origin(), startIndex);
+            UpsilonValue* startSumForBody = loopEntry-&gt;appendNew&lt;UpsilonValue&gt;(
+                proc, Origin(), startSum);
+            loopEntry-&gt;appendNew&lt;ControlValue&gt;(proc, Jump, Origin(), FrequentedBlock(loopBody));
+
+            Value* bodyIndex = loopBody-&gt;appendNew&lt;Value&gt;(proc, Phi, Int32, Origin());
+            startIndexForBody-&gt;setPhi(bodyIndex);
+            Value* bodySum = loopBody-&gt;appendNew&lt;Value&gt;(proc, Phi, Int32, Origin());
+            startSumForBody-&gt;setPhi(bodySum);
+            Value* newBodyIndex = loopBody-&gt;appendNew&lt;Value&gt;(proc, Sub, Origin(), bodyIndex, one);
+            Value* newBodySum = loopBody-&gt;appendNew&lt;Value&gt;(
+                proc, Add, Origin(),
+                bodySum,
+                loopBody-&gt;appendNew&lt;MemoryValue&gt;(
+                    proc, Load, Int32, Origin(),
+                    loopBody-&gt;appendNew&lt;Value&gt;(
+                        proc, Add, Origin(),
+                        loopBody-&gt;appendNew&lt;ConstPtrValue&gt;(proc, Origin(), varSlots.data()),
+                        loopBody-&gt;appendNew&lt;Value&gt;(
+                            proc, Shl, Origin(),
+                            loopBody-&gt;appendNew&lt;Value&gt;(
+                                proc, ZExt32, Origin(),
+                                loopBody-&gt;appendNew&lt;Value&gt;(
+                                    proc, BitAnd, Origin(),
+                                    newBodyIndex,
+                                    loopBody-&gt;appendNew&lt;Const32Value&gt;(
+                                        proc, Origin(), numVars - 1))),
+                            loopBody-&gt;appendNew&lt;Const32Value&gt;(proc, Origin(), 2)))));
+            loopBody-&gt;appendNew&lt;ControlValue&gt;(
+                proc, Branch, Origin(), newBodyIndex,
+                FrequentedBlock(loopReentry), FrequentedBlock(loopExit));
+
+            loopReentry-&gt;appendNew&lt;UpsilonValue&gt;(proc, Origin(), newBodyIndex, bodyIndex);
+            loopReentry-&gt;appendNew&lt;UpsilonValue&gt;(proc, Origin(), newBodySum, bodySum);
+            loopReentry-&gt;appendNew&lt;ControlValue&gt;(proc, Jump, Origin(), FrequentedBlock(loopBody));
+
+            UpsilonValue* exitSum = loopExit-&gt;appendNew&lt;UpsilonValue&gt;(proc, Origin(), newBodySum);
+            loopExit-&gt;appendNew&lt;ControlValue&gt;(proc, Jump, Origin(), FrequentedBlock(continuation));
+
+            UpsilonValue* skipSum = loopSkip-&gt;appendNew&lt;UpsilonValue&gt;(proc, Origin(), startSum);
+            loopSkip-&gt;appendNew&lt;ControlValue&gt;(proc, Jump, Origin(), FrequentedBlock(continuation));
+
+            Value* finalSum = continuation-&gt;appendNew&lt;Value&gt;(proc, Phi, Int32, Origin());
+            exitSum-&gt;setPhi(finalSum);
+            skipSum-&gt;setPhi(finalSum);
+
+            current = continuation;
+            vars[((i &gt;&gt; 1) + 1) % numVars] = finalSum;
+        }
+    }
+
+    current-&gt;appendNew&lt;ControlValue&gt;(proc, Return, Origin(), vars[0]);
+
+    compile(proc);
+
+    double after = monotonicallyIncreasingTimeMS();
+    dataLog(&quot;    That took &quot;, after - before, &quot; ms.\n&quot;);
+}
+
</ins><span class="cx"> #define RUN(test) do {                          \
</span><span class="cx">         if (!shouldRun(#test))                  \
</span><span class="cx">             break;                              \
</span><span class="lines">@@ -1168,6 +1303,13 @@
</span><span class="cx">     RUN(testBranchEqualFoldPtr(42));
</span><span class="cx">     RUN(testBranchEqualFoldPtr(0));
</span><span class="cx"> 
</span><ins>+    RUN(testComplex(64, 128));
+    RUN(testComplex(64, 256));
+    RUN(testComplex(64, 384));
+    RUN(testComplex(4, 128));
+    RUN(testComplex(4, 256));
+    RUN(testComplex(4, 384));
+
</ins><span class="cx">     if (!didRun)
</span><span class="cx">         usage();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -337,6 +337,8 @@
</span><span class="cx">     v(unsigned, fireOSRExitFuzzAt, 0, nullptr) \
</span><span class="cx">     v(unsigned, fireOSRExitFuzzAtOrAfter, 0, nullptr) \
</span><span class="cx">     \
</span><ins>+    v(bool, logB3PhaseTimes, false, nullptr) \
+    \
</ins><span class="cx">     v(bool, useDollarVM, false, &quot;installs the $vm debugging tool in global objects&quot;) \
</span><span class="cx">     v(optionString, functionOverrides, nullptr, &quot;file with debugging overrides for function bodies&quot;) \
</span><span class="cx">     \
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/WTF/ChangeLog        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-10-31  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        B3::reduceStrength's DCE should be more agro and less wrong
+        https://bugs.webkit.org/show_bug.cgi?id=150748
+
+        Reviewed by Geoffrey Garen.
+
+        * wtf/GraphNodeWorklist.h:
+        (WTF::GraphNodeWorklist::saw): This method is super useful.
+
</ins><span class="cx"> 2015-11-01  Philip Chimento  &lt;philip.chimento@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Fix combinations of PLATFORM(GTK) and OS(DARWIN)
</span></span></pre></div>
<a id="trunkSourceWTFwtfGraphNodeWorklisth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/GraphNodeWorklist.h (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/GraphNodeWorklist.h        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Source/WTF/wtf/GraphNodeWorklist.h        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -54,6 +54,8 @@
</span><span class="cx">         return m_stack.takeLast();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool saw(Node node) { return m_seen.contains(node); }
+
</ins><span class="cx"> private:
</span><span class="cx">     Set m_seen;
</span><span class="cx">     Vector&lt;Node, 16&gt; m_stack;
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (191864 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2015-11-01 23:12:27 UTC (rev 191864)
+++ trunk/Tools/ChangeLog        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-10-31  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        B3::reduceStrength's DCE should be more agro and less wrong
+        https://bugs.webkit.org/show_bug.cgi?id=150748
+
+        Reviewed by Geoffrey Garen.
+
+        Add an LLVM version of testb3's &quot;testComplex&quot;.
+
+        * ReducedFTL/ComplexTest.cpp: Added.
+
</ins><span class="cx"> 2015-11-01  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r191831.
</span></span></pre></div>
<a id="trunkToolsReducedFTLComplexTestcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/ReducedFTL/ComplexTest.cpp (0 => 191865)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ReducedFTL/ComplexTest.cpp                                (rev 0)
+++ trunk/Tools/ReducedFTL/ComplexTest.cpp        2015-11-01 23:37:03 UTC (rev 191865)
</span><span class="lines">@@ -0,0 +1,247 @@
</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. 
+ */
+
+// Compile like so:
+// clang++ -O3 -o ComplexTest ComplexTest.cpp -std=c++14 `~/Downloads/clang+llvm-3.7.0-x86_64-apple-darwin/bin/llvm-config --cppflags --cxxflags --ldflags --libs` -lcurses -g -lz
+
+#include &lt;vector&gt;
+#include &lt;memory&gt;
+#include &lt;chrono&gt;
+
+#include &lt;sys/time.h&gt;
+
+#include &lt;llvm/Support/raw_ostream.h&gt;
+#include &lt;llvm/IR/LLVMContext.h&gt;
+#include &lt;llvm/IR/DataLayout.h&gt;
+#include &lt;llvm/IR/IRBuilder.h&gt;
+#include &lt;llvm/IR/Constants.h&gt;
+#include &lt;llvm/IR/Function.h&gt;
+#include &lt;llvm/IR/Instructions.h&gt;
+#include &lt;llvm/IR/Module.h&gt;
+#include &lt;llvm/IR/Verifier.h&gt;
+#include &lt;llvm/ExecutionEngine/ExecutionEngine.h&gt;
+#include &lt;llvm/Transforms/Utils/BasicBlockUtils.h&gt;
+#include &lt;llvm/Pass.h&gt;
+#include &lt;llvm/IR/LegacyPassManager.h&gt;
+#include &lt;llvm/Support/Host.h&gt;
+#include &lt;llvm/Analysis/Passes.h&gt;
+#include &lt;llvm/Transforms/Scalar.h&gt;
+#include &lt;llvm/Transforms/IPO.h&gt;
+#include &lt;llvm/Transforms/IPO/PassManagerBuilder.h&gt;
+#include &lt;llvm/ExecutionEngine/MCJIT.h&gt;
+#include &lt;llvm/Support/ErrorHandling.h&gt;
+#include &lt;llvm/Support/TargetSelect.h&gt;
+
+using namespace llvm;
+using namespace std;
+
+namespace {
+
+template&lt;typename ToType, typename FromType&gt;
+inline ToType bitwise_cast(FromType from)
+{
+    static_assert(sizeof(FromType) == sizeof(ToType), &quot;bitwise_cast size of FromType and ToType must be equal!&quot;);
+    union {
+        FromType from;
+        ToType to;
+    } u;
+    u.from = from;
+    return u.to;
+}
+
+double monotonicallyIncreasingTimeMS()
+{
+    return chrono::duration_cast&lt;chrono::microseconds&gt;(
+        chrono::steady_clock::now().time_since_epoch()).count() / 1000.;
+}
+
+void run(unsigned numVars, unsigned numConstructs)
+{
+    LLVMContext context;
+    Type* int32Ty = Type::getInt32Ty(context);
+    Module* module = new Module(&quot;complexModule&quot;, context);
+    Function* function = Function::Create(
+        FunctionType::get(int32Ty, false), GlobalValue::ExternalLinkage, &quot;complexFunction&quot;, module);
+
+    vector&lt;int32_t&gt; varSlots;
+    for (unsigned i = numVars; i--;)
+        varSlots.push_back(i);
+
+    BasicBlock* current = BasicBlock::Create(context, &quot;&quot;, function);
+    unique_ptr&lt;IRBuilder&lt;&gt;&gt; builder = make_unique&lt;IRBuilder&lt;&gt;&gt;(current);
+
+    vector&lt;Value*&gt; vars;
+    for (int32_t&amp; varSlot : varSlots) {
+        Value* ptr = builder-&gt;CreateIntToPtr(builder-&gt;getInt64(bitwise_cast&lt;intptr_t&gt;(&amp;varSlot)),
+                                            int32Ty-&gt;getPointerTo());
+        vars.push_back(builder-&gt;CreateLoad(ptr));
+    }
+
+    for (unsigned i = 0; i &lt; numConstructs; ++i) {
+        if (i &amp; 1) {
+            // Control flow diamond.
+            unsigned predicateVarIndex = (i &gt;&gt; 1) % numVars;
+            unsigned thenIncVarIndex = ((i &gt;&gt; 1) + 1) % numVars;
+            unsigned elseIncVarIndex = ((i &gt;&gt; 1) + 2) % numVars;
+
+            BasicBlock* thenBlock = BasicBlock::Create(context, &quot;&quot;, function);
+            BasicBlock* elseBlock = BasicBlock::Create(context, &quot;&quot;, function);
+            BasicBlock* continuation = BasicBlock::Create(context, &quot;&quot;, function);
+
+            builder-&gt;CreateCondBr(
+                builder-&gt;CreateICmpNE(vars[predicateVarIndex], builder-&gt;getInt32(0)),
+                thenBlock, elseBlock);
+
+            builder = make_unique&lt;IRBuilder&lt;&gt;&gt;(thenBlock);
+            Value* thenValue = builder-&gt;CreateAdd(vars[thenIncVarIndex], builder-&gt;getInt32(1));
+            builder-&gt;CreateBr(continuation);
+
+            builder = make_unique&lt;IRBuilder&lt;&gt;&gt;(elseBlock);
+            Value* elseValue = builder-&gt;CreateAdd(vars[elseIncVarIndex], builder-&gt;getInt32(1));
+            builder-&gt;CreateBr(continuation);
+
+            builder = make_unique&lt;IRBuilder&lt;&gt;&gt;(current = continuation);
+            PHINode* thenPhi = builder-&gt;CreatePHI(int32Ty, 2);
+            thenPhi-&gt;addIncoming(thenValue, thenBlock);
+            thenPhi-&gt;addIncoming(vars[thenIncVarIndex], elseBlock);
+            PHINode* elsePhi = builder-&gt;CreatePHI(int32Ty, 2);
+            elsePhi-&gt;addIncoming(elseValue, elseBlock);
+            elsePhi-&gt;addIncoming(vars[elseIncVarIndex], thenBlock);
+            
+            vars[thenIncVarIndex] = thenPhi;
+            vars[elseIncVarIndex] = elsePhi;
+        } else {
+            // Loop.
+
+            BasicBlock* loopBody = BasicBlock::Create(context, &quot;&quot;, function);
+            BasicBlock* continuation = BasicBlock::Create(context, &quot;&quot;, function);
+
+            Value* startIndex = vars[(i &gt;&gt; 1) % numVars];
+            Value* startSum = builder-&gt;getInt32(0);
+            builder-&gt;CreateCondBr(
+                builder-&gt;CreateICmpNE(startIndex, builder-&gt;getInt32(0)),
+                loopBody, continuation);
+
+            builder = make_unique&lt;IRBuilder&lt;&gt;&gt;(loopBody);
+            PHINode* bodyIndex = builder-&gt;CreatePHI(int32Ty, 2);
+            PHINode* bodySum = builder-&gt;CreatePHI(int32Ty, 2);
+            bodyIndex-&gt;addIncoming(startIndex, current);
+            bodySum-&gt;addIncoming(startSum, current);
+
+            Value* newBodyIndex = builder-&gt;CreateSub(bodyIndex, builder-&gt;getInt32(1));
+            Value* newBodySum = builder-&gt;CreateAdd(
+                bodySum,
+                builder-&gt;CreateLoad(
+                    builder-&gt;CreateIntToPtr(
+                        builder-&gt;CreateAdd(
+                            builder-&gt;getInt64(bitwise_cast&lt;intptr_t&gt;(&amp;varSlots[0])),
+                            builder-&gt;CreateShl(
+                                builder-&gt;CreateZExt(
+                                    builder-&gt;CreateAnd(
+                                        newBodyIndex,
+                                        builder-&gt;getInt32(numVars - 1)),
+                                    Type::getInt64Ty(context)),
+                                builder-&gt;getInt64(2))),
+                        int32Ty-&gt;getPointerTo())));
+            bodyIndex-&gt;addIncoming(newBodyIndex, loopBody);
+            bodySum-&gt;addIncoming(newBodySum, loopBody);
+            builder-&gt;CreateCondBr(
+                builder-&gt;CreateICmpNE(newBodyIndex, builder-&gt;getInt32(0)),
+                loopBody, continuation);
+
+            builder = make_unique&lt;IRBuilder&lt;&gt;&gt;(continuation);
+            PHINode* finalSum = builder-&gt;CreatePHI(int32Ty, 2);
+            finalSum-&gt;addIncoming(startSum, current);
+            finalSum-&gt;addIncoming(newBodySum, loopBody);
+            current = continuation;
+        }
+    }
+
+    builder-&gt;CreateRet(vars[0]);
+    builder = nullptr;
+
+    unique_ptr&lt;ExecutionEngine&gt; EE;
+    {
+        std::string errorMessage;
+        EngineBuilder builder((std::unique_ptr&lt;Module&gt;(module)));
+        builder.setMArch(&quot;&quot;);
+        builder.setMCPU(sys::getHostCPUName());
+        builder.setMAttrs(std::vector&lt;std::string&gt;());
+        builder.setRelocationModel(Reloc::Default);
+        builder.setCodeModel(CodeModel::JITDefault);
+        builder.setErrorStr(&amp;errorMessage);
+        builder.setEngineKind(EngineKind::JIT);
+
+        builder.setOptLevel(CodeGenOpt::Default);
+        
+        {
+            TargetOptions Options;
+            Options.FloatABIType = FloatABI::Default;
+
+            builder.setTargetOptions(Options);
+        }
+
+        EE = unique_ptr&lt;ExecutionEngine&gt;(builder.create());
+    }
+    
+    legacy::PassManager passManager;
+    //passManager.add(new DataLayout(*EE-&gt;getDataLayout()));
+    passManager.add(createPromoteMemoryToRegisterPass());
+    passManager.add(createConstantPropagationPass());
+    passManager.add(createInstructionCombiningPass());
+    passManager.add(createBasicAliasAnalysisPass());
+    passManager.add(createTypeBasedAliasAnalysisPass());
+    passManager.add(createGVNPass());
+    passManager.add(createCFGSimplificationPass());
+    passManager.run(*module);
+
+    EE-&gt;getFunctionAddress(function-&gt;getName());
+}
+
+} // anonymous namespace
+
+int main(int c, char** v)
+{
+    InitializeAllTargets();
+    InitializeAllTargetMCs();
+    InitializeAllAsmPrinters();
+    InitializeAllAsmParsers();
+    for (unsigned i = 1; i &lt;= 3; ++i) {
+        printf(&quot;Doing: run(4, %u)\n&quot;, i * 128);
+        double before = monotonicallyIncreasingTimeMS();
+        run(4, 128 * i);
+        double after = monotonicallyIncreasingTimeMS();
+        printf(&quot;That took %lf ms.\n&quot;, after - before);
+    }
+    for (unsigned i = 1; i &lt;= 3; ++i) {
+        printf(&quot;Doing: run(64, %u)\n&quot;, i * 128);
+        double before = monotonicallyIncreasingTimeMS();
+        run(64, 128 * i);
+        double after = monotonicallyIncreasingTimeMS();
+        printf(&quot;That took %lf ms.\n&quot;, after - before);
+    }
+    return 0;
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>