2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGNaturalLoops.h"
32 #include "JSCInlines.h"
33 #include <wtf/CommaPrinter.h>
35 namespace JSC
{ namespace DFG
{
37 void NaturalLoop::dump(PrintStream
& out
) const
39 out
.print("[Header: ", *header(), ", Body:");
40 for (unsigned i
= 0; i
< m_body
.size(); ++i
)
41 out
.print(" ", *m_body
[i
]);
45 NaturalLoops::NaturalLoops() { }
46 NaturalLoops::~NaturalLoops() { }
48 void NaturalLoops::compute(Graph
& graph
)
50 // Implement the classic dominator-based natural loop finder. The first
51 // step is to find all control flow edges A -> B where B dominates A.
52 // Then B is a loop header and A is a backward branching block. We will
53 // then accumulate, for each loop header, multiple backward branching
54 // blocks. Then we backwards graph search from the backward branching
55 // blocks to their loop headers, which gives us all of the blocks in the
58 static const bool verbose
= false;
60 graph
.m_dominators
.computeIfNecessary(graph
);
63 dataLog("Dominators:\n");
64 graph
.m_dominators
.dump(graph
, WTF::dataFile());
69 for (BlockIndex blockIndex
= graph
.numBlocks(); blockIndex
--;) {
70 BasicBlock
* block
= graph
.block(blockIndex
);
74 for (unsigned i
= block
->numSuccessors(); i
--;) {
75 BasicBlock
* successor
= block
->successor(i
);
76 if (!graph
.m_dominators
.dominates(successor
, block
))
79 for (unsigned j
= m_loops
.size(); j
--;) {
80 if (m_loops
[j
].header() == successor
) {
81 m_loops
[j
].addBlock(block
);
88 NaturalLoop
loop(successor
, m_loops
.size());
95 dataLog("After bootstrap: ", *this, "\n");
97 FastBitVector seenBlocks
;
98 Vector
<BasicBlock
*, 4> blockWorklist
;
99 seenBlocks
.resize(graph
.numBlocks());
101 for (unsigned i
= m_loops
.size(); i
--;) {
102 NaturalLoop
& loop
= m_loops
[i
];
104 seenBlocks
.clearAll();
105 ASSERT(blockWorklist
.isEmpty());
108 dataLog("Dealing with loop ", loop
, "\n");
110 for (unsigned j
= loop
.size(); j
--;) {
111 seenBlocks
.set(loop
[j
]->index
);
112 blockWorklist
.append(loop
[j
]);
115 while (!blockWorklist
.isEmpty()) {
116 BasicBlock
* block
= blockWorklist
.takeLast();
119 dataLog(" Dealing with ", *block
, "\n");
121 if (block
== loop
.header())
124 for (unsigned j
= block
->predecessors
.size(); j
--;) {
125 BasicBlock
* predecessor
= block
->predecessors
[j
];
126 if (seenBlocks
.get(predecessor
->index
))
129 loop
.addBlock(predecessor
);
130 blockWorklist
.append(predecessor
);
131 seenBlocks
.set(predecessor
->index
);
136 // Figure out reverse mapping from blocks to loops.
137 for (BlockIndex blockIndex
= graph
.numBlocks(); blockIndex
--;) {
138 BasicBlock
* block
= graph
.block(blockIndex
);
141 for (unsigned i
= BasicBlock::numberOfInnerMostLoopIndices
; i
--;)
142 block
->innerMostLoopIndices
[i
] = UINT_MAX
;
144 for (unsigned loopIndex
= m_loops
.size(); loopIndex
--;) {
145 NaturalLoop
& loop
= m_loops
[loopIndex
];
147 for (unsigned blockIndexInLoop
= loop
.size(); blockIndexInLoop
--;) {
148 BasicBlock
* block
= loop
[blockIndexInLoop
];
150 for (unsigned i
= 0; i
< BasicBlock::numberOfInnerMostLoopIndices
; ++i
) {
151 unsigned thisIndex
= block
->innerMostLoopIndices
[i
];
152 if (thisIndex
== UINT_MAX
|| loop
.size() < m_loops
[thisIndex
].size()) {
153 insertIntoBoundedVector(
154 block
->innerMostLoopIndices
, BasicBlock::numberOfInnerMostLoopIndices
,
162 // Now each block knows its inner-most loop and its next-to-inner-most loop. Use
163 // this to figure out loop parenting.
164 for (unsigned i
= m_loops
.size(); i
--;) {
165 NaturalLoop
& loop
= m_loops
[i
];
166 RELEASE_ASSERT(loop
.header()->innerMostLoopIndices
[0] == i
);
168 loop
.m_outerLoopIndex
= loop
.header()->innerMostLoopIndices
[1];
171 if (validationEnabled()) {
172 // Do some self-verification that we've done some of this correctly.
174 for (BlockIndex blockIndex
= graph
.numBlocks(); blockIndex
--;) {
175 BasicBlock
* block
= graph
.block(blockIndex
);
179 Vector
<const NaturalLoop
*> simpleLoopsOf
;
181 for (unsigned i
= m_loops
.size(); i
--;) {
182 if (m_loops
[i
].contains(block
))
183 simpleLoopsOf
.append(&m_loops
[i
]);
186 Vector
<const NaturalLoop
*> fancyLoopsOf
= loopsOf(block
);
188 std::sort(simpleLoopsOf
.begin(), simpleLoopsOf
.end());
189 std::sort(fancyLoopsOf
.begin(), fancyLoopsOf
.end());
191 RELEASE_ASSERT(simpleLoopsOf
== fancyLoopsOf
);
196 dataLog("Results: ", *this, "\n");
199 Vector
<const NaturalLoop
*> NaturalLoops::loopsOf(BasicBlock
* block
) const
201 Vector
<const NaturalLoop
*> result
;
202 for (const NaturalLoop
* loop
= innerMostLoopOf(block
); loop
; loop
= innerMostOuterLoop(*loop
))
207 void NaturalLoops::dump(PrintStream
& out
) const
209 out
.print("NaturalLoops:{");
211 for (unsigned i
= 0; i
< m_loops
.size(); ++i
)
212 out
.print(comma
, m_loops
[i
]);
216 } } // namespace JSC::DFG
218 #endif // ENABLE(DFG_JIT)