v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
control-equivalence.cc
Go to the documentation of this file.
1// Copyright 2015 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
7
8#define TRACE(...) \
9 do { \
10 if (v8_flags.trace_turbo_ceq) PrintF(__VA_ARGS__); \
11 } while (false)
12
13namespace v8 {
14namespace internal {
15namespace compiler {
16
18 if (!Participates(exit) || GetClass(exit) == kInvalidClass) {
20 RunUndirectedDFS(exit);
21 }
22}
23
24
25// static
27
28
30 TRACE("CEQ: Pre-visit of #%d:%s\n", node->id(), node->op()->mnemonic());
31}
32
33
35 TRACE("CEQ: Mid-visit of #%d:%s\n", node->id(), node->op()->mnemonic());
36 BracketList& blist = GetBracketList(node);
37
38 // Remove brackets pointing to this node [line:19].
39 BracketListDelete(blist, node, direction);
40
41 // Potentially introduce artificial dependency from start to end.
42 if (blist.empty()) {
45 }
46
47 // Potentially start a new equivalence class [line:37].
48 BracketListTRACE(blist);
49 Bracket* recent = &blist.back();
50 if (recent->recent_size != blist.size()) {
51 recent->recent_size = blist.size();
52 recent->recent_class = NewClassNumber();
53 }
54
55 // Assign equivalence class to node.
56 SetClass(node, recent->recent_class);
57 TRACE(" Assigned class number is %zu\n", GetClass(node));
58}
59
60
61void ControlEquivalence::VisitPost(Node* node, Node* parent_node,
63 TRACE("CEQ: Post-visit of #%d:%s\n", node->id(), node->op()->mnemonic());
64 BracketList& blist = GetBracketList(node);
65
66 // Remove brackets pointing to this node [line:19].
67 BracketListDelete(blist, node, direction);
68
69 // Propagate bracket list up the DFS tree [line:13].
70 if (parent_node != nullptr) {
71 BracketList& parent_blist = GetBracketList(parent_node);
72 parent_blist.splice(parent_blist.end(), blist);
73 }
74}
75
76
79 TRACE("CEQ: Backedge from #%d:%s to #%d:%s\n", from->id(),
80 from->op()->mnemonic(), to->id(), to->op()->mnemonic());
81
82 // Push backedge onto the bracket list [line:25].
83 Bracket bracket = {direction, kInvalidClass, 0, from, to};
84 GetBracketList(from).push_back(bracket);
85}
86
87
90 DFSPush(stack, exit, nullptr, kInputDirection);
91 VisitPre(exit);
92
93 while (!stack.empty()) { // Undirected depth-first backwards traversal.
94 DFSStackEntry& entry = stack.top();
95 Node* node = entry.node;
96
97 if (entry.direction == kInputDirection) {
98 if (entry.input != node->input_edges().end()) {
99 Edge edge = *entry.input;
100 Node* input = edge.to();
101 ++(entry.input);
103 // Visit next control input.
104 if (!Participates(input)) continue;
105 if (GetData(input)->visited) continue;
106 if (GetData(input)->on_stack) {
107 // Found backedge if input is on stack.
108 if (input != entry.parent_node) {
109 VisitBackedge(node, input, kInputDirection);
110 }
111 } else {
112 // Push input onto stack.
113 DFSPush(stack, input, node, kInputDirection);
114 VisitPre(input);
115 }
116 }
117 continue;
118 }
119 if (entry.use != node->use_edges().end()) {
120 // Switch direction to uses.
121 entry.direction = kUseDirection;
123 continue;
124 }
125 }
126
127 if (entry.direction == kUseDirection) {
128 if (entry.use != node->use_edges().end()) {
129 Edge edge = *entry.use;
130 Node* use = edge.from();
131 ++(entry.use);
133 // Visit next control use.
134 if (!Participates(use)) continue;
135 if (GetData(use)->visited) continue;
136 if (GetData(use)->on_stack) {
137 // Found backedge if use is on stack.
138 if (use != entry.parent_node) {
139 VisitBackedge(node, use, kUseDirection);
140 }
141 } else {
142 // Push use onto stack.
143 DFSPush(stack, use, node, kUseDirection);
144 VisitPre(use);
145 }
146 }
147 continue;
148 }
149 if (entry.input != node->input_edges().end()) {
150 // Switch direction to inputs.
152 VisitMid(node, kUseDirection);
153 continue;
154 }
155 }
156
157 // Pop node from stack when done with all inputs and uses.
158 DCHECK(entry.input == node->input_edges().end());
159 DCHECK(entry.use == node->use_edges().end());
160 VisitPost(node, entry.parent_node, entry.direction);
161 DFSPop(stack, node);
162 }
163}
164
166 Node* node) {
167 if (!Participates(node)) {
168 AllocateData(node);
169 queue.push(node);
170 }
171}
172
173
175 ZoneQueue<Node*> queue(zone_);
177 while (!queue.empty()) { // Breadth-first backwards traversal.
178 Node* node = queue.front();
179 queue.pop();
180 int max = NodeProperties::PastControlIndex(node);
181 for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) {
182 DetermineParticipationEnqueue(queue, node->InputAt(i));
183 }
184 }
185}
186
187
189 DFSDirection dir) {
190 DCHECK(Participates(node));
191 DCHECK(!GetData(node)->visited);
192 GetData(node)->on_stack = true;
193 Node::InputEdges::iterator input = node->input_edges().begin();
194 Node::UseEdges::iterator use = node->use_edges().begin();
195 stack.push({dir, input, use, from, node});
196}
197
198
200 DCHECK_EQ(stack.top().node, node);
201 GetData(node)->on_stack = false;
202 GetData(node)->visited = true;
203 stack.pop();
204}
205
206
209 // TODO(turbofan): Optimize this to avoid linear search.
210 for (BracketList::iterator i = blist.begin(); i != blist.end(); /*nop*/) {
211 if (i->to == to && i->direction != direction) {
212 TRACE(" BList erased: {%d->%d}\n", i->from->id(), i->to->id());
213 i = blist.erase(i);
214 } else {
215 ++i;
216 }
217 }
218}
219
220
222 if (v8_flags.trace_turbo_ceq) {
223 TRACE(" BList: ");
224 for (Bracket bracket : blist) {
225 TRACE("{%d->%d} ", bracket.from->id(), bracket.to->id());
226 }
227 TRACE("\n");
228 }
229}
230
231#undef TRACE
232
233} // namespace compiler
234} // namespace internal
235} // namespace v8
void DFSPop(DFSStack &stack, Node *node)
void DetermineParticipationEnqueue(ZoneQueue< Node * > &queue, Node *node)
void DFSPush(DFSStack &stack, Node *node, Node *from, DFSDirection dir)
void BracketListDelete(BracketList &blist, Node *to, DFSDirection direction)
void VisitPost(Node *node, Node *parent_node, DFSDirection direction)
void VisitMid(Node *node, DFSDirection direction)
void VisitBackedge(Node *from, Node *to, DFSDirection direction)
Node * from() const
Definition node.h:425
Node * to() const
Definition node.h:426
ArrayReduceDirection direction
#define TRACE(...)
ZoneStack< RpoNumber > & stack
Point from
V8_EXPORT_PRIVATE FlagValues v8_flags
other heap size generate builtins concurrently on separate threads in mksnapshot track concurrent recompilation artificial compilation delay in ms max number of threads that concurrent Turbofan can use(0 for unbounded)") DEFINE_BOOL( stress_concurrent_inlining
#define STATIC_CONST_MEMBER_DEFINITION
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485