<!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>[192121] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/192121">192121</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-11-06 15:34:31 -0800 (Fri, 06 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>B3 and Air should simplify CFGs
https://bugs.webkit.org/show_bug.cgi?id=150960

Reviewed by Geoffrey Garen.

This adds CFG simplification to both B3 and Air.

In B3, the simplification is done inside the B3::reduceStrength() fixpoint because we expect
that it will help to reveal more optimization opportunities. This is going to be particularly
true when we add Phi elimination.

In Air, the simplification is its own phase. We expect it to produce most of its benefits once
we have coalescing. Then, CFG simplification in Air will unbreak critial edges.

* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbortReason.h:
* assembler/MacroAssembler.h:
(JSC::MacroAssembler::oops): Reveal this as a method so that we can have an Oops instruction.
* b3/B3BasicBlock.h:
(JSC::B3::BasicBlock::predecessor):
(JSC::B3::BasicBlock::predecessors):
(JSC::B3::BasicBlock::containsPredecessor):
* b3/B3BasicBlockUtils.h: Bunch of fixes for blocks being killed.
(JSC::B3::replacePredecessor):
(JSC::B3::resetReachability):
* b3/B3ReduceStrength.cpp: Implement B3 CFG simplification.
* b3/B3ReduceStrength.h:
* b3/air/AirBasicBlock.h:
(JSC::B3::Air::BasicBlock::resize):
(JSC::B3::Air::BasicBlock::insts):
(JSC::B3::Air::BasicBlock::appendInst):
(JSC::B3::Air::BasicBlock::containsPredecessor):
* b3/air/AirGenerate.cpp:
(JSC::B3::Air::generate):
* b3/air/AirInst.cpp:
(JSC::B3::Air::Inst::hasArgEffects):
(JSC::B3::Air::Inst::dump):
* b3/air/AirInst.h:
* b3/air/AirLiveness.h:
(JSC::B3::Air::Liveness::Liveness): Fix for when blocks were killed.
* b3/air/AirOpcode.opcodes:
* b3/air/AirSimplifyCFG.cpp: Added.
(JSC::B3::Air::simplifyCFG):
* b3/air/AirSimplifyCFG.h: 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="#trunkSourceJavaScriptCoreassemblerAbortReasonh">trunk/Source/JavaScriptCore/assembler/AbortReason.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/MacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3BasicBlockh">trunk/Source/JavaScriptCore/b3/B3BasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3BasicBlockUtilsh">trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp">trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ReduceStrengthh">trunk/Source/JavaScriptCore/b3/B3ReduceStrength.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirBasicBlockh">trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirGeneratecpp">trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInstcpp">trunk/Source/JavaScriptCore/b3/air/AirInst.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInsth">trunk/Source/JavaScriptCore/b3/air/AirInst.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>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirSimplifyCFGcpp">trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirSimplifyCFGh">trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2015-11-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        B3 and Air should simplify CFGs
+        https://bugs.webkit.org/show_bug.cgi?id=150960
+
+        Reviewed by Geoffrey Garen.
+
+        This adds CFG simplification to both B3 and Air.
+
+        In B3, the simplification is done inside the B3::reduceStrength() fixpoint because we expect
+        that it will help to reveal more optimization opportunities. This is going to be particularly
+        true when we add Phi elimination.
+
+        In Air, the simplification is its own phase. We expect it to produce most of its benefits once
+        we have coalescing. Then, CFG simplification in Air will unbreak critial edges.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/AbortReason.h:
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::oops): Reveal this as a method so that we can have an Oops instruction.
+        * b3/B3BasicBlock.h:
+        (JSC::B3::BasicBlock::predecessor):
+        (JSC::B3::BasicBlock::predecessors):
+        (JSC::B3::BasicBlock::containsPredecessor):
+        * b3/B3BasicBlockUtils.h: Bunch of fixes for blocks being killed.
+        (JSC::B3::replacePredecessor):
+        (JSC::B3::resetReachability):
+        * b3/B3ReduceStrength.cpp: Implement B3 CFG simplification.
+        * b3/B3ReduceStrength.h:
+        * b3/air/AirBasicBlock.h:
+        (JSC::B3::Air::BasicBlock::resize):
+        (JSC::B3::Air::BasicBlock::insts):
+        (JSC::B3::Air::BasicBlock::appendInst):
+        (JSC::B3::Air::BasicBlock::containsPredecessor):
+        * b3/air/AirGenerate.cpp:
+        (JSC::B3::Air::generate):
+        * b3/air/AirInst.cpp:
+        (JSC::B3::Air::Inst::hasArgEffects):
+        (JSC::B3::Air::Inst::dump):
+        * b3/air/AirInst.h:
+        * b3/air/AirLiveness.h:
+        (JSC::B3::Air::Liveness::Liveness): Fix for when blocks were killed.
+        * b3/air/AirOpcode.opcodes:
+        * b3/air/AirSimplifyCFG.cpp: Added.
+        (JSC::B3::Air::simplifyCFG):
+        * b3/air/AirSimplifyCFG.h: Added.
+
</ins><span class="cx"> 2015-11-05  Nikos Andronikos  &lt;nikos.andronikos-webkit@cisra.canon.com.au&gt;
</span><span class="cx"> 
</span><span class="cx">         Add runtime and compile time flags for enabling Web Animations API and model.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -280,12 +280,14 @@
</span><span class="cx">                 0F300B7C18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */; };
</span><span class="cx">                 0F32BD101BB34F190093A57F /* HeapHelperPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */; };
</span><span class="cx">                 0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */; };
</span><del>-                0F338DF91BE96AA80013C88F /* B3CCallValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338DF71BE96AA80013C88F /* B3CCallValue.cpp */; };
-                0F338DFA1BE96AA80013C88F /* B3CCallValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338DF81BE96AA80013C88F /* B3CCallValue.h */; };
</del><span class="cx">                 0F338DF11BE93AD10013C88F /* B3StackmapValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338DEF1BE93AD10013C88F /* B3StackmapValue.cpp */; };
</span><span class="cx">                 0F338DF21BE93AD10013C88F /* B3StackmapValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338DF01BE93AD10013C88F /* B3StackmapValue.h */; };
</span><span class="cx">                 0F338DF51BE93D550013C88F /* B3ConstrainedValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338DF31BE93D550013C88F /* B3ConstrainedValue.cpp */; };
</span><span class="cx">                 0F338DF61BE93D550013C88F /* B3ConstrainedValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338DF41BE93D550013C88F /* B3ConstrainedValue.h */; };
</span><ins>+                0F338DF91BE96AA80013C88F /* B3CCallValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338DF71BE96AA80013C88F /* B3CCallValue.cpp */; };
+                0F338DFA1BE96AA80013C88F /* B3CCallValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338DF81BE96AA80013C88F /* B3CCallValue.h */; };
+                0F338DFD1BED51270013C88F /* AirSimplifyCFG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */; };
+                0F338DFE1BED51270013C88F /* AirSimplifyCFG.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338DFC1BED51270013C88F /* AirSimplifyCFG.h */; };
</ins><span class="cx">                 0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; };
</span><span class="cx">                 0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; };
</span><span class="cx">                 0F38B01117CF078000B144D3 /* LLIntEntrypoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */; };
</span><span class="lines">@@ -2303,12 +2305,14 @@
</span><span class="cx">                 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntegerCheckCombiningPhase.h; path = dfg/DFGIntegerCheckCombiningPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapHelperPool.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapHelperPool.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0F338DF71BE96AA80013C88F /* B3CCallValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3CCallValue.cpp; path = b3/B3CCallValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                0F338DF81BE96AA80013C88F /* B3CCallValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3CCallValue.h; path = b3/B3CCallValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 0F338DEF1BE93AD10013C88F /* B3StackmapValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3StackmapValue.cpp; path = b3/B3StackmapValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F338DF01BE93AD10013C88F /* B3StackmapValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3StackmapValue.h; path = b3/B3StackmapValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F338DF31BE93D550013C88F /* B3ConstrainedValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ConstrainedValue.cpp; path = b3/B3ConstrainedValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F338DF41BE93D550013C88F /* B3ConstrainedValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ConstrainedValue.h; path = b3/B3ConstrainedValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F338DF71BE96AA80013C88F /* B3CCallValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3CCallValue.cpp; path = b3/B3CCallValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F338DF81BE96AA80013C88F /* B3CCallValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3CCallValue.h; path = b3/B3CCallValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirSimplifyCFG.cpp; path = b3/air/AirSimplifyCFG.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F338DFC1BED51270013C88F /* AirSimplifyCFG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirSimplifyCFG.h; path = b3/air/AirSimplifyCFG.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoint.cpp; path = llint/LLIntEntrypoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4524,6 +4528,8 @@
</span><span class="cx">                                 0FEC85611BDACDC70080FF74 /* AirRegisterPriority.h */,
</span><span class="cx">                                 0F45703A1BE45F0A0062A629 /* AirReportUsedRegisters.cpp */,
</span><span class="cx">                                 0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */,
</span><ins>+                                0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */,
+                                0F338DFC1BED51270013C88F /* AirSimplifyCFG.h */,
</ins><span class="cx">                                 0FEC85621BDACDC70080FF74 /* AirSpecial.cpp */,
</span><span class="cx">                                 0FEC85631BDACDC70080FF74 /* AirSpecial.h */,
</span><span class="cx">                                 0FEC85641BDACDC70080FF74 /* AirSpillEverything.cpp */,
</span><span class="lines">@@ -6767,6 +6773,7 @@
</span><span class="cx">                                 0FBDB9AD1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h in Headers */,
</span><span class="cx">                                 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */,
</span><span class="cx">                                 0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */,
</span><ins>+                                0F338DFE1BED51270013C88F /* AirSimplifyCFG.h in Headers */,
</ins><span class="cx">                                 0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */,
</span><span class="cx">                                 0F9D36951AE9CC33000D4DFB /* DFGCleanUpPhase.h in Headers */,
</span><span class="cx">                                 A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */,
</span><span class="lines">@@ -8486,6 +8493,7 @@
</span><span class="cx">                                 147F39CE107EC37600427A48 /* Identifier.cpp in Sources */,
</span><span class="cx">                                 A5FD0075189B038C00633231 /* IdentifiersFactory.cpp in Sources */,
</span><span class="cx">                                 C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */,
</span><ins>+                                0F338DFD1BED51270013C88F /* AirSimplifyCFG.cpp in Sources */,
</ins><span class="cx">                                 0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */,
</span><span class="cx">                                 0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
</span><span class="cx">                                 0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbortReasonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbortReason.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbortReason.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/assembler/AbortReason.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx">     AHTagTypeNumberNotInPlace                         = 130,
</span><span class="cx">     AHTypeInfoInlineTypeFlagsAreValid                 = 140,
</span><span class="cx">     AHTypeInfoIsValid                                 = 150,
</span><ins>+    B3Oops                                            = 155,
</ins><span class="cx">     DFGBailedAtTopOfBlock                             = 161,
</span><span class="cx">     DFGBailedAtEndOfNode                              = 162,
</span><span class="cx">     DFGBasicStorageAllocatorZeroSize                  = 170,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssembler.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssembler.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -472,6 +472,11 @@
</span><span class="cx">         return condition;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void oops()
+    {
+        abortWithReason(B3Oops);
+    }
+
</ins><span class="cx">     static const unsigned BlindingModulus = 64;
</span><span class="cx">     bool shouldConsiderBlinding()
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BasicBlock.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BasicBlock.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/B3BasicBlock.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -88,6 +88,7 @@
</span><span class="cx">     BasicBlock*&amp; predecessor(unsigned index) { return m_predecessors[index]; }
</span><span class="cx">     const PredecessorList&amp; predecessors() const { return m_predecessors; }
</span><span class="cx">     PredecessorList&amp; predecessors() { return m_predecessors; }
</span><ins>+    bool containsPredecessor(BasicBlock* block) { return m_predecessors.contains(block); }
</ins><span class="cx"> 
</span><span class="cx">     bool addPredecessor(BasicBlock*);
</span><span class="cx">     bool removePredecessor(BasicBlock*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BasicBlockUtilsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/B3BasicBlockUtils.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -64,14 +64,11 @@
</span><span class="cx"> template&lt;typename BasicBlock&gt;
</span><span class="cx"> bool replacePredecessor(BasicBlock* block, BasicBlock* from, BasicBlock* to)
</span><span class="cx"> {
</span><del>-    auto&amp; predecessors = block-&gt;predecessors();
-    for (unsigned i = 0; i &lt; predecessors.size(); ++i) {
-        if (predecessors[i] == from) {
-            predecessors[i] = to;
-            return true;
-        }
-    }
-    return false;
</del><ins>+    bool changed = false;
+    // We do it this way because 'to' may already be a predecessor of 'block'.
+    changed |= removePredecessor(block, from);
+    changed |= addPredecessor(block, to);
+    return changed;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // This recomputes predecessors and removes blocks that aren't reachable.
</span><span class="lines">@@ -80,8 +77,10 @@
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;BasicBlock&gt;&gt;&amp; blocks, const DeleteFunctor&amp; deleteFunctor)
</span><span class="cx"> {
</span><span class="cx">     // Clear all predecessor lists first.
</span><del>-    for (auto&amp; block : blocks)
-        block-&gt;predecessors().resize(0);
</del><ins>+    for (auto&amp; block : blocks) {
+        if (block)
+            block-&gt;predecessors().resize(0);
+    }
</ins><span class="cx"> 
</span><span class="cx">     GraphNodeWorklist&lt;BasicBlock*, IndexSet&lt;BasicBlock&gt;&gt; worklist;
</span><span class="cx">     worklist.push(blocks[0].get());
</span><span class="lines">@@ -93,6 +92,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 1; i &lt; blocks.size(); ++i) {
</span><ins>+        if (!blocks[i])
+            continue;
</ins><span class="cx">         if (blocks[i]-&gt;predecessors().isEmpty()) {
</span><span class="cx">             deleteFunctor(blocks[i].get());
</span><span class="cx">             blocks[i] = nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp        2015-11-06 23:34:31 UTC (rev 192121)
</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;B3BasicBlockInlines.h&quot;
</ins><span class="cx"> #include &quot;B3ControlValue.h&quot;
</span><span class="cx"> #include &quot;B3IndexSet.h&quot;
</span><span class="cx"> #include &quot;B3InsertionSetInlines.h&quot;
</span><span class="lines">@@ -90,13 +91,17 @@
</span><span class="cx">     bool run()
</span><span class="cx">     {
</span><span class="cx">         bool result = false;
</span><ins>+        bool first = true;
</ins><span class="cx">         unsigned index = 0;
</span><span class="cx">         do {
</span><span class="cx">             m_changed = false;
</span><span class="cx">             m_changedCFG = false;
</span><ins>+            ++index;
</ins><span class="cx"> 
</span><del>-            if (verbose) {
-                dataLog(&quot;Reduce strength IR before iteration #&quot;, ++index, &quot;\n&quot;);
</del><ins>+            if (first)
+                first = false;
+            else if (verbose) {
+                dataLog(&quot;B3 after iteration #&quot;, index - 1, &quot; of reduceStrength:\n&quot;);
</ins><span class="cx">                 dataLog(m_proc);
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -108,6 +113,8 @@
</span><span class="cx">                 m_insertionSet.execute(m_block);
</span><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            simplifyCFG();
+
</ins><span class="cx">             if (m_changedCFG) {
</span><span class="cx">                 m_proc.resetReachability();
</span><span class="cx">                 m_changed = true;
</span><span class="lines">@@ -545,6 +552,7 @@
</span><span class="cx">             // Turn this: Branch(0, then, else)
</span><span class="cx">             // Into this: Jump(else)
</span><span class="cx">             if (triState == FalseTriState) {
</span><ins>+                branch-&gt;taken().block()-&gt;removePredecessor(m_block);
</ins><span class="cx">                 branch-&gt;convertToJump(branch-&gt;notTaken());
</span><span class="cx">                 m_changedCFG = true;
</span><span class="cx">                 break;
</span><span class="lines">@@ -553,6 +561,7 @@
</span><span class="cx">             // Turn this: Branch(not 0, then, else)
</span><span class="cx">             // Into this: Jump(then)
</span><span class="cx">             if (triState == TrueTriState) {
</span><ins>+                branch-&gt;notTaken().block()-&gt;removePredecessor(m_block);
</ins><span class="cx">                 branch-&gt;convertToJump(branch-&gt;taken());
</span><span class="cx">                 m_changedCFG = true;
</span><span class="cx">                 break;
</span><span class="lines">@@ -620,6 +629,118 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void simplifyCFG()
+    {
+        // We have three easy simplification rules:
+        //
+        // 1) If a successor is a block that just jumps to another block, then jump directly to
+        //    that block.
+        //
+        // 2) If all successors are the same and the operation has no effects, then use a jump
+        //    instead.
+        //
+        // 3) If you jump to a block that is not you and has one predecessor, then merge.
+        //
+        // Note that because of the first rule, this phase may introduce critical edges. That's fine.
+        // If you need broken critical edges, then you have to break them yourself.
+
+        // Note that this relies on predecessors being at least conservatively correct. It's fine for
+        // predecessors to mention a block that isn't actually a predecessor. It's *not* fine for a
+        // predecessor to be omitted. We assert as much in the loop. In practice, we precisely preserve
+        // predecessors during strength reduction since that minimizes the total number of fixpoint
+        // iterations needed to kill a lot of code.
+
+        for (BasicBlock* block : m_proc) {
+            checkPredecessorValidity();
+
+            // We don't care about blocks that don't have successors.
+            if (!block-&gt;numSuccessors())
+                continue;
+
+            // First check if any of the successors of this block can be forwarded over.
+            for (BasicBlock*&amp; successor : block-&gt;successorBlocks()) {
+                if (successor != block
+                    &amp;&amp; successor-&gt;size() == 1
+                    &amp;&amp; successor-&gt;last()-&gt;opcode() == Jump) {
+                    BasicBlock* newSuccessor = successor-&gt;successorBlock(0);
+                    if (newSuccessor != successor) {
+                        newSuccessor-&gt;replacePredecessor(successor, block);
+                        successor = newSuccessor;
+                        m_changedCFG = true;
+                    }
+                }
+            }
+
+            // Now check if the block's terminal can be replaced with a jump.
+            if (block-&gt;numSuccessors() &gt; 1) {
+                // The terminal must not have weird effects.
+                Effects effects = block-&gt;last()-&gt;effects();
+                effects.terminal = false;
+                if (!effects.mustExecute()) {
+                    // All of the successors must be the same.
+                    bool allSame = true;
+                    FrequentedBlock firstSuccessor = block-&gt;successor(0);
+                    for (unsigned i = 1; i &lt; block-&gt;numSuccessors(); ++i) {
+                        if (block-&gt;successorBlock(i) != firstSuccessor.block()) {
+                            allSame = false;
+                            break;
+                        }
+                    }
+                    if (allSame) {
+                        block-&gt;last()-&gt;as&lt;ControlValue&gt;()-&gt;convertToJump(firstSuccessor);
+                        m_changedCFG = true;
+                    }
+                }
+            }
+
+            // Finally handle jumps to a block with one predecessor.
+            if (block-&gt;numSuccessors() == 1) {
+                BasicBlock* successor = block-&gt;successorBlock(0);
+                if (successor != block &amp;&amp; successor-&gt;numPredecessors() == 1) {
+                    RELEASE_ASSERT(successor-&gt;predecessor(0) == block);
+                    
+                    // We can merge the two blocks, because the predecessor only jumps to the successor
+                    // and the successor is only reachable from the predecessor.
+                    
+                    // Remove the terminal.
+                    Value* value = block-&gt;values().takeLast();
+                    Origin jumpOrigin = value-&gt;origin();
+                    RELEASE_ASSERT(value-&gt;as&lt;ControlValue&gt;());
+                    m_proc.deleteValue(value);
+                    
+                    // Append the full contents of the successor to the predecessor.
+                    block-&gt;values().appendVector(successor-&gt;values());
+                    
+                    // Make sure that the successor has nothing left in it. Make sure that the block
+                    // has a terminal so that nobody chokes when they look at it.
+                    successor-&gt;values().resize(0);
+                    successor-&gt;appendNew&lt;ControlValue&gt;(m_proc, Oops, jumpOrigin);
+                    
+                    // Ensure that predecessors of block's new successors know what's up.
+                    for (BasicBlock* newSuccessor : block-&gt;successorBlocks())
+                        newSuccessor-&gt;replacePredecessor(successor, block);
+                    m_changedCFG = true;
+                }
+            }
+        }
+
+        if (m_changedCFG &amp;&amp; verbose) {
+            dataLog(&quot;B3 after simplifyCFG:\n&quot;);
+            dataLog(m_proc);
+        }
+    }
+
+    void checkPredecessorValidity()
+    {
+        if (!shouldValidateIRAtEachPhase())
+            return;
+
+        for (BasicBlock* block : m_proc) {
+            for (BasicBlock* successor : block-&gt;successorBlocks())
+                RELEASE_ASSERT(successor-&gt;containsPredecessor(block));
+        }
+    }
+
</ins><span class="cx">     void killDeadCode()
</span><span class="cx">     {
</span><span class="cx">         GraphNodeWorklist&lt;Value*, IndexSet&lt;Value&gt;&gt; worklist;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ReduceStrengthh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ReduceStrength.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ReduceStrength.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/B3ReduceStrength.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -32,8 +32,8 @@
</span><span class="cx"> 
</span><span class="cx"> class Procedure;
</span><span class="cx"> 
</span><del>-// Does strength reduction, constant folding, and canonicalization. In the future we may also have it
-// do CSE.
</del><ins>+// Does strength reduction, constant folding, canonicalization, CFG simplification, and DCE. In the
+// future we may also have it do CSE.
</ins><span class="cx"> 
</span><span class="cx"> bool reduceStrength(Procedure&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirBasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -65,6 +65,9 @@
</span><span class="cx"> 
</span><span class="cx">     void resize(unsigned size) { m_insts.resize(size); }
</span><span class="cx"> 
</span><ins>+    const InstList&amp; insts() const { return m_insts; }
+    InstList&amp; insts() { return m_insts; }
+
</ins><span class="cx">     template&lt;typename Inst&gt;
</span><span class="cx">     void appendInst(Inst&amp;&amp; inst)
</span><span class="cx">     {
</span><span class="lines">@@ -105,6 +108,7 @@
</span><span class="cx">     bool addPredecessor(BasicBlock*);
</span><span class="cx">     bool removePredecessor(BasicBlock*);
</span><span class="cx">     bool replacePredecessor(BasicBlock* from, BasicBlock* to);
</span><ins>+    bool containsPredecessor(BasicBlock* predecessor) const { return m_predecessors.contains(predecessor); }
</ins><span class="cx"> 
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     void deepDump(PrintStream&amp;) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirGeneratecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/air/AirGenerate.cpp        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;AirGenerationContext.h&quot;
</span><span class="cx"> #include &quot;AirHandleCalleeSaves.h&quot;
</span><span class="cx"> #include &quot;AirReportUsedRegisters.h&quot;
</span><ins>+#include &quot;AirSimplifyCFG.h&quot;
</ins><span class="cx"> #include &quot;AirSpillEverything.h&quot;
</span><span class="cx"> #include &quot;AirValidate.h&quot;
</span><span class="cx"> #include &quot;B3Common.h&quot;
</span><span class="lines">@@ -79,6 +80,10 @@
</span><span class="cx">     // shouldn't have to worry about this very much.
</span><span class="cx">     allocateStack(code);
</span><span class="cx"> 
</span><ins>+    // If we coalesced moves then we can unbreak critical edges. This is the main reason for this
+    // phase.
+    simplifyCFG(code);
+
</ins><span class="cx">     // FIXME: We should really have a code layout optimization here.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=150478
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInstcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInst.cpp (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInst.cpp        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/air/AirInst.cpp        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -28,11 +28,23 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;AirInstInlines.h&quot;
</ins><span class="cx"> #include &quot;B3Value.h&quot;
</span><span class="cx"> #include &lt;wtf/ListDump.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span><ins>+bool Inst::hasArgEffects()
+{
+    bool result = false;
+    forEachArg(
+        [&amp;] (Arg&amp;, Arg::Role role, Arg::Type) {
+            if (Arg::isDef(role))
+                result = true;
+        });
+    return result;
+}
+
</ins><span class="cx"> void Inst::dump(PrintStream&amp; out) const
</span><span class="cx"> {
</span><span class="cx">     out.print(opcode, &quot; &quot;, listDump(args));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInsth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInst.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInst.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/air/AirInst.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -151,6 +151,9 @@
</span><span class="cx">     // implied by the second argument.
</span><span class="cx">     bool hasNonArgEffects();
</span><span class="cx"> 
</span><ins>+    // Tells you if this operation has arg effects.
+    bool hasArgEffects();
+
</ins><span class="cx">     // Generate some code for this instruction. This is, like, literally our backend. If this is the
</span><span class="cx">     // terminal, it returns the jump that needs to be linked for the &quot;then&quot; case, with the &quot;else&quot;
</span><span class="cx">     // case being fall-through. This function is auto-generated by opcode_generator.rb.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLiveness.h (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -57,6 +57,8 @@
</span><span class="cx"> 
</span><span class="cx">             for (size_t blockIndex = code.size(); blockIndex--;) {
</span><span class="cx">                 BasicBlock* block = code.at(blockIndex);
</span><ins>+                if (!block)
+                    continue;
</ins><span class="cx">                 LocalCalc localCalc(*this, block);
</span><span class="cx">                 for (size_t instIndex = block-&gt;size(); instIndex--;)
</span><span class="cx">                     localCalc.execute(block-&gt;at(instIndex));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (192120 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-11-06 23:20:12 UTC (rev 192120)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -294,7 +294,7 @@
</span><span class="cx"> 
</span><span class="cx"> Ret /terminal
</span><span class="cx"> 
</span><del>-Breakpoint /effects
</del><ins>+Oops /terminal
</ins><span class="cx"> 
</span><span class="cx"> # Air allows for exotic behavior. A Patch's behavior is determined entirely by the Special operand,
</span><span class="cx"> # which must be the first operand.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirSimplifyCFGcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp (0 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -0,0 +1,169 @@
</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;AirSimplifyCFG.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirCode.h&quot;
+#include &quot;AirInstInlines.h&quot;
+#include &quot;AirPhaseScope.h&quot;
+
+namespace JSC { namespace B3 { namespace Air {
+
+bool simplifyCFG(Code&amp; code)
+{
+    const bool verbose = false;
+    
+    PhaseScope phaseScope(code, &quot;simplifyCFG&quot;);
+    
+    // We have three easy simplification rules:
+    //
+    // 1) If a successor is a block that just jumps to another block, then jump directly to
+    //    that block.
+    //
+    // 2) If all successors are the same and the operation has no effects, then use a jump
+    //    instead.
+    //
+    // 3) If you jump to a block that is not you and has one predecessor, then merge.
+    //
+    // Note that because of the first rule, this phase may introduce critical edges. That's fine.
+    // If you need broken critical edges, then you have to break them yourself.
+
+    bool result = false;
+    for (;;) {
+        if (verbose) {
+            dataLog(&quot;Air before an iteration of simplifyCFG:\n&quot;);
+            dataLog(code);
+        }
+        
+        bool changed = false;
+        for (BasicBlock* block : code) {
+            // We rely on predecessors being conservatively correct. Verify this here.
+            if (shouldValidateIRAtEachPhase()) {
+                for (BasicBlock* block : code) {
+                    for (BasicBlock* successor : block-&gt;successorBlocks())
+                        RELEASE_ASSERT(successor-&gt;containsPredecessor(block));
+                }
+            }
+
+            // We don't care about blocks that don't have successors.
+            if (!block-&gt;numSuccessors())
+                continue;
+
+            // First check if any of the successors of this block can be forwarded over.
+            for (BasicBlock*&amp; successor : block-&gt;successorBlocks()) {
+                if (successor != block
+                    &amp;&amp; successor-&gt;size() == 1
+                    &amp;&amp; successor-&gt;last().opcode == Jump) {
+                    BasicBlock* newSuccessor = successor-&gt;successorBlock(0);
+                    if (newSuccessor != successor) {
+                        if (verbose) {
+                            dataLog(
+                                &quot;Replacing &quot;, pointerDump(block), &quot;-&gt;&quot;, pointerDump(successor),
+                                &quot; with &quot;, pointerDump(block), &quot;-&gt;&quot;, pointerDump(newSuccessor), &quot;\n&quot;);
+                        }
+                        newSuccessor-&gt;replacePredecessor(successor, block);
+                        successor = newSuccessor;
+                        changed = true;
+                    }
+                }
+            }
+
+            // Now check if the block's terminal can be replaced with a jump.
+            if (block-&gt;numSuccessors() &gt; 1) {
+                // The terminal must not have weird effects.
+                if (!block-&gt;last().hasArgEffects()
+                    &amp;&amp; !block-&gt;last().hasNonArgNonControlEffects()) {
+                    // All of the successors must be the same.
+                    bool allSame = true;
+                    BasicBlock* firstSuccessor = block-&gt;successorBlock(0);
+                    for (unsigned i = 1; i &lt; block-&gt;numSuccessors(); ++i) {
+                        if (block-&gt;successorBlock(i) != firstSuccessor) {
+                            allSame = false;
+                            break;
+                        }
+                    }
+                    if (allSame) {
+                        if (verbose)
+                            dataLog(&quot;Changing &quot;, pointerDump(block), &quot;'s terminal to a Jump.\n&quot;);
+                        block-&gt;last() = Inst(Jump, block-&gt;last().origin);
+                        block-&gt;successors().resize(1);
+                        changed = true;
+                    }
+                }
+            }
+
+            // Finally handle jumps to a block with one predecessor.
+            if (block-&gt;numSuccessors() == 1) {
+                BasicBlock* successor = block-&gt;successorBlock(0);
+                if (successor != block &amp;&amp; successor-&gt;numPredecessors() == 1) {
+                    RELEASE_ASSERT(successor-&gt;predecessor(0) == block);
+
+                    // We can merge the two blocks because the predecessor only jumps to the successor
+                    // and the successor is only reachable from the predecessor.
+
+                    // Remove the terminal.
+                    Value* origin = block-&gt;insts().takeLast().origin;
+
+                    // Append the full contents of the successor to the predecessor.
+                    block-&gt;insts().reserveCapacity(block-&gt;size() + successor-&gt;size());
+                    for (Inst&amp; inst : *successor)
+                        block-&gt;appendInst(WTF::move(inst));
+
+                    // Make sure that our successors are the successor's successors.
+                    block-&gt;successors() = WTF::move(successor-&gt;successors());
+
+                    // Make sure that the successor has nothing left in it except an oops.
+                    successor-&gt;resize(1);
+                    successor-&gt;last() = Inst(Oops, origin);
+                    successor-&gt;successors().clear();
+
+                    // Ensure that the predecessors of block's new successors know what's up.
+                    for (BasicBlock* newSuccessor : block-&gt;successorBlocks())
+                        newSuccessor-&gt;replacePredecessor(successor, block);
+
+                    if (verbose)
+                        dataLog(&quot;Merged &quot;, pointerDump(block), &quot;-&gt;&quot;, pointerDump(successor), &quot;\n&quot;);
+                    changed = true;
+                }
+            }
+        }
+
+        if (!changed)
+            break;
+        result = true;
+        code.resetReachability();
+    }
+
+    return result;
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirSimplifyCFGh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.h (0 => 192121)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirSimplifyCFG.h        2015-11-06 23:34:31 UTC (rev 192121)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef AirSimplifyCFG_h
+#define AirSimplifyCFG_h
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 { namespace Air {
+
+class Code;
+
+// Simplifies the control flow graph by removing jump-only blocks and merging jumps.
+
+bool simplifyCFG(Code&amp;);
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
+#endif // AirSimplifyCFG_h
+
</ins></span></pre>
</div>
</div>

</body>
</html>