source: webkit/trunk/Source/JavaScriptCore/dfg/DFGLoopPreHeaderCreationPhase.cpp

Last change on this file was 261895, checked in by Ross Kirsling, 5 years ago

REGRESSION(r261755): Win/Linux non-unified builds have hundreds of link failures
https://bugs.webkit.org/show_bug.cgi?id=212111

Unreviewed build fix.

  • API/:
  • bindings/:
  • bytecode/:
  • bytecompiler/NodesCodegen.cpp:
  • debugger/:
  • dfg/:
  • heap/:
  • inspector/:
  • interpreter/:
  • jit/:
  • llint/LLIntEntrypoint.cpp:
  • parser/:
  • profiler/:
  • runtime/:

Restore *Inlines.h includes for >300 files,
but try to preserve the spirit of the original patch by pruning redundancies along the way.

File size: 8.5 KB
Line 
1/*
2 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "DFGLoopPreHeaderCreationPhase.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGBasicBlockInlines.h"
32#include "DFGBlockInsertionSet.h"
33#include "DFGDominators.h"
34#include "DFGGraph.h"
35#include "DFGNaturalLoops.h"
36#include "DFGPhase.h"
37#include "JSCJSValueInlines.h"
38
39namespace JSC { namespace DFG {
40
41BasicBlock* createPreHeader(Graph& graph, BlockInsertionSet& insertionSet, BasicBlock* block)
42{
43 ASSERT_WITH_MESSAGE(!graph.isRoot(block), "A CFG root should not be in a loop");
44
45 // FIXME: If we run this utility on SSA IR, then we may end up with a bizarre arrangement of
46 // Upsilons and Phis, like:
47 //
48 // BB#1:
49 // Upsilon(@a, ^p)
50 // Jump(#3)
51 //
52 // BB#2:
53 // Upsilon(@b, ^p)
54 // Jump(#3)
55 //
56 // BB#3:
57 // Jump(#4)
58 //
59 // BB#4:
60 // p: Phi()
61 //
62 // Notice how the Upsilons are not in the predecessor of the Phi anymore. It's not clear if this
63 // would be bad. Probably not, but it's weird anyway. We should add a validation rule, and we
64 // should implement a Upsilon/Phi canonicalization that handles this by calling into the
65 // SSACalculator and treating the Upsilons as Defs and rebuilding the Phis from scratch.
66 //
67 // https://bugs.webkit.org/show_bug.cgi?id=148587
68
69 // Determine a good frequency for the pre-header. It's definitely not the frequency of the loop body.
70 // Instead, we use the max of the frequencies of the loop body's non-loop predecessors.
71 float frequency = 0;
72 for (BasicBlock* predecessor : block->predecessors) {
73 ASSERT(graph.m_form != SSA);
74 if (graph.m_cpsDominators->dominates(block, predecessor))
75 continue;
76 frequency = std::max(frequency, predecessor->executionCount);
77 }
78 BasicBlock* preHeader = insertionSet.insertBefore(block, frequency);
79
80 // FIXME: It would be great if we put some effort into enabling exitOK at this origin, if it
81 // happens to be unset. It might not be set because the loop header (i.e. "block") has Phis in it.
82 // Phis have to have exitOK=false. There are a few ways to try to set exitOK:
83 //
84 // - Regenerate an exit origin by proving that we are at an exit origin boundary. If all of the
85 // predecessors' terminals have different exit origins than the exit origin of head of block,
86 // then we can leverage the assumption that exit origin boundaries can always exit. We could
87 // extend this further, and say that we will set exitOK even if a predecessor's terminal has the
88 // same exit origin, but so long it hadn't done anything that clobbers exit since the start of
89 // the origin.
90 //
91 // - Analyze the Phi's and MovHint's at the head of block. If prior to the ExitOK there are only
92 // Phi's and MovHint's, we could "roll them back" by proving that for each of the MovHints, the
93 // referenced Phi has a child that dominates the pre-header, and that child is the node that is
94 // OSR-available at the local being MovHinted.
95 //
96 // Note that there are some obviously wrong ways to try to set exitOK. For example, we cannot
97 // simply use the origin of our predecessors, since in bytecode that could be *any* kind of
98 // instruction. It may not even be a control flow construct, if we had lowered some non-control
99 // bytecode operation into DFG IR that has control flow. Hence, we really do need to try to use the
100 // origin of the head of the loop header.
101 //
102 // https://bugs.webkit.org/show_bug.cgi?id=148586
103 preHeader->appendNode(
104 graph, SpecNone, Jump, block->at(0)->origin, OpInfo(block));
105
106 for (unsigned predecessorIndex = 0; predecessorIndex < block->predecessors.size(); predecessorIndex++) {
107 BasicBlock* predecessor = block->predecessors[predecessorIndex];
108 if (graph.m_cpsDominators->dominates(block, predecessor))
109 continue;
110 block->predecessors[predecessorIndex--] = block->predecessors.last();
111 block->predecessors.removeLast();
112 for (unsigned successorIndex = predecessor->numSuccessors(); successorIndex--;) {
113 BasicBlock*& successor = predecessor->successor(successorIndex);
114 if (successor != block)
115 continue;
116 successor = preHeader;
117 preHeader->predecessors.append(predecessor);
118 }
119 }
120
121 block->predecessors.append(preHeader);
122 return preHeader;
123}
124
125class LoopPreHeaderCreationPhase : public Phase {
126public:
127 LoopPreHeaderCreationPhase(Graph& graph)
128 : Phase(graph, "loop pre-header creation")
129 , m_insertionSet(graph)
130 {
131 }
132
133 bool run()
134 {
135 m_graph.ensureCPSDominators();
136 m_graph.ensureCPSNaturalLoops();
137
138 for (unsigned loopIndex = m_graph.m_cpsNaturalLoops->numLoops(); loopIndex--;) {
139 const CPSNaturalLoop& loop = m_graph.m_cpsNaturalLoops->loop(loopIndex);
140 BasicBlock* existingPreHeader = nullptr;
141 bool needsNewPreHeader = false;
142 for (unsigned predecessorIndex = loop.header().node()->predecessors.size(); predecessorIndex--;) {
143 BasicBlock* predecessor = loop.header().node()->predecessors[predecessorIndex];
144 if (m_graph.m_cpsDominators->dominates(loop.header().node(), predecessor))
145 continue;
146 if (!existingPreHeader) {
147 existingPreHeader = predecessor;
148 continue;
149 }
150 // We won't have duplicate entries in the predecessors list.
151 DFG_ASSERT(m_graph, nullptr, existingPreHeader != predecessor);
152 needsNewPreHeader = true;
153 break;
154 }
155
156 // This phase should only be run on a DFG where unreachable blocks have been pruned.
157 // We also don't allow loops back to root. This means that every loop header has got
158 // to have a pre-header.
159 DFG_ASSERT(m_graph, nullptr, existingPreHeader);
160
161 // We are looking at the predecessors of a loop header. A loop header has to have
162 // some predecessor other than the pre-header. We must have broken critical edges
163 // because that is the DFG SSA convention. Therefore, each predecessor of the loop
164 // header must have only one successor.
165 DFG_ASSERT(m_graph, nullptr, existingPreHeader->terminal()->op() == Jump, existingPreHeader->terminal()->op());
166
167 // A pre-header is most useful if it's possible to exit from its terminal. Hence
168 // if the terminal of the existing pre-header doesn't allow for exit, but the first
169 // origin of the loop header does, then we should create a new pre-header.
170 if (!needsNewPreHeader && loop.header().node()->at(0)->origin.exitOK
171 && !existingPreHeader->terminal()->origin.exitOK)
172 needsNewPreHeader = true;
173
174 if (!needsNewPreHeader)
175 continue;
176
177 createPreHeader(m_graph, m_insertionSet, loop.header().node());
178 }
179
180 return m_insertionSet.execute();
181 }
182
183 BlockInsertionSet m_insertionSet;
184};
185
186bool performLoopPreHeaderCreation(Graph& graph)
187{
188 return runPhase<LoopPreHeaderCreationPhase>(graph);
189}
190
191} } // namespace JSC::DFG
192
193#endif // ENABLE(DFG_JIT)
194
195
Note: See TracBrowser for help on using the repository browser.