v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
loop-finder.cc
Go to the documentation of this file.
1// Copyright 2023 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
8
11 for (const Block& block : base::Reversed(input_graph_->blocks())) {
12 if (block.IsLoop()) {
13 LoopInfo info = VisitLoop(&block);
14 loop_header_info_.insert({&block, info});
15 }
16 }
17}
18
19// Update the `parent_loops_` of all of the blocks that are inside of the loop
20// that starts on `header`.
22 Block* backedge = header->LastPredecessor();
23 DCHECK(backedge->LastOperation(*input_graph_).Is<GotoOp>());
24 DCHECK_EQ(backedge->LastOperation(*input_graph_).Cast<GotoOp>().destination,
25 header);
26 DCHECK_GE(backedge->index().id(), header->index().id());
27
29 // The header is skipped by the while-loop below, so we initialize {info} with
30 // the `op_count` from {header}, and a `block_count` of 1 (= the header).
31 info.op_count = header->OpCountUpperBound();
32 info.start = header;
33 info.end = backedge;
34 info.block_count = 1;
35
36 queue_.clear();
37 queue_.push_back(backedge);
38 while (!queue_.empty()) {
39 const Block* curr = queue_.back();
40 queue_.pop_back();
41 if (curr == header) continue;
42 if (loop_headers_[curr->index()] != nullptr) {
43 const Block* curr_parent = loop_headers_[curr->index()];
44 if (curr_parent == header) {
45 // If {curr}'s parent is already marked as being {header}, then we've
46 // already visited {curr}.
47 continue;
48 } else {
49 // If {curr}'s parent is not {header}, then {curr} is part of an inner
50 // loop. We should continue the search on the loop header: the
51 // predecessors of {curr} will all be in this inner loop.
52 queue_.push_back(curr_parent);
53 info.has_inner_loops = true;
54 continue;
55 }
56 }
57 info.block_count++;
58 info.op_count += curr->OpCountUpperBound();
59 loop_headers_[curr->index()] = header;
60 const Block* pred_start = curr->LastPredecessor();
61 if (curr->IsLoop()) {
62 // Skipping the backedge of inner loops since we don't want to visit inner
63 // loops now (they should already have been visited).
64 DCHECK_NOT_NULL(pred_start);
65 pred_start = pred_start->NeighboringPredecessor();
66 info.has_inner_loops = true;
67 }
68 for (const Block* pred : NeighboringPredecessorIterable(pred_start)) {
69 queue_.push_back(pred);
70 }
71 }
72
73 return info;
74}
75
77 const Block* loop_header) {
78 DCHECK(!GetLoopInfo(loop_header).has_inner_loops);
80 body.insert(loop_header);
81
83 queue.push_back(loop_header->LastPredecessor());
84 while (!queue.empty()) {
85 const Block* curr = queue.back();
86 queue.pop_back();
87 if (body.find(curr) != body.end()) continue;
88 body.insert(curr);
89 for (const Block* pred = curr->LastPredecessor(); pred != nullptr;
90 pred = pred->NeighboringPredecessor()) {
91 if (pred == loop_header) continue;
92 queue.push_back(pred);
93 }
94 }
95
96 return body;
97}
98
99} // namespace v8::internal::compiler::turboshaft
void push_back(const T &value)
const Operation & LastOperation(const Graph &graph) const
Definition graph.h:1242
FixedBlockSidetable< const Block * > loop_headers_
LoopInfo GetLoopInfo(const Block *block) const
Definition loop-finder.h:74
ZoneUnorderedMap< const Block *, LoopInfo > loop_header_info_
LoopInfo VisitLoop(const Block *header)
ZoneSet< const Block *, BlockCmp > GetLoopBody(const Block *loop_header)
Handle< SharedFunctionInfo > info
RpoNumber block
auto Reversed(T &t)
Definition iterator.h:105
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485