Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: runtime/vm/flow_graph.cc

Issue 10949020: Reapply "Initial implementation of sparse conditional constant propagation." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase to HEAD. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph.h" 5 #include "vm/flow_graph.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 16 matching lines...) Expand all
27 preorder_(), 27 preorder_(),
28 postorder_(), 28 postorder_(),
29 reverse_postorder_(), 29 reverse_postorder_(),
30 exits_(NULL) { 30 exits_(NULL) {
31 DiscoverBlocks(); 31 DiscoverBlocks();
32 } 32 }
33 33
34 34
35 void FlowGraph::DiscoverBlocks() { 35 void FlowGraph::DiscoverBlocks() {
36 // Initialize state. 36 // Initialize state.
37 preorder_.TruncateTo(0); 37 preorder_.Clear();
38 postorder_.TruncateTo(0); 38 postorder_.Clear();
39 reverse_postorder_.TruncateTo(0); 39 reverse_postorder_.Clear();
40 parent_.TruncateTo(0); 40 parent_.Clear();
41 assigned_vars_.TruncateTo(0); 41 assigned_vars_.Clear();
42 // Perform a depth-first traversal of the graph to build preorder and 42 // Perform a depth-first traversal of the graph to build preorder and
43 // postorder block orders. 43 // postorder block orders.
44 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor. 44 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor.
45 &preorder_, 45 &preorder_,
46 &postorder_, 46 &postorder_,
47 &parent_, 47 &parent_,
48 &assigned_vars_, 48 &assigned_vars_,
49 variable_count(), 49 variable_count(),
50 num_non_copied_params()); 50 num_non_copied_params());
51 // Number blocks in reverse postorder. 51 // Number blocks in reverse postorder.
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 ValidateUseListsInInstruction(it.Current()); 183 ValidateUseListsInInstruction(it.Current());
184 } 184 }
185 } 185 }
186 return true; // Return true so we can ASSERT validation. 186 return true; // Return true so we can ASSERT validation.
187 } 187 }
188 #endif // DEBUG 188 #endif // DEBUG
189 189
190 190
191 static void ClearUseLists(Definition* defn) { 191 static void ClearUseLists(Definition* defn) {
192 ASSERT(defn != NULL); 192 ASSERT(defn != NULL);
193 DEBUG_ASSERT(defn->input_use_list() == NULL); 193 ASSERT(defn->input_use_list() == NULL);
194 DEBUG_ASSERT(defn->env_use_list() == NULL); 194 ASSERT(defn->env_use_list() == NULL);
195 defn->set_input_use_list(NULL); 195 defn->set_input_use_list(NULL);
196 defn->set_env_use_list(NULL); 196 defn->set_env_use_list(NULL);
197 } 197 }
198 198
199 199
200 static void RecordInputUses(Instruction* instr) { 200 static void RecordInputUses(Instruction* instr) {
201 ASSERT(instr != NULL); 201 ASSERT(instr != NULL);
202 for (intptr_t i = 0; i < instr->InputCount(); ++i) { 202 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
203 Value* use = instr->InputAt(i); 203 Value* use = instr->InputAt(i);
204 DEBUG_ASSERT(use->instruction() == NULL); 204 ASSERT(use->instruction() == NULL);
205 DEBUG_ASSERT(use->use_index() == -1); 205 ASSERT(use->use_index() == -1);
206 DEBUG_ASSERT(use->next_use() == NULL); 206 ASSERT(use->next_use() == NULL);
207 DEBUG_ASSERT(0 == MembershipCount(use, 207 DEBUG_ASSERT(0 == MembershipCount(use,
208 use->definition()->input_use_list())); 208 use->definition()->input_use_list()));
209 use->set_instruction(instr); 209 use->set_instruction(instr);
210 use->set_use_index(i); 210 use->set_use_index(i);
211 use->AddToInputUseList(); 211 use->AddToInputUseList();
212 } 212 }
213 } 213 }
214 214
215 215
216 static void RecordEnvUses(Instruction* instr) { 216 static void RecordEnvUses(Instruction* instr) {
217 ASSERT(instr != NULL); 217 ASSERT(instr != NULL);
218 if (instr->env() == NULL) return; 218 if (instr->env() == NULL) return;
219 intptr_t use_index = 0; 219 intptr_t use_index = 0;
220 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 220 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
221 Value* use = it.CurrentValue(); 221 Value* use = it.CurrentValue();
222 DEBUG_ASSERT(use->instruction() == NULL); 222 ASSERT(use->instruction() == NULL);
223 DEBUG_ASSERT(use->use_index() == -1); 223 ASSERT(use->use_index() == -1);
224 DEBUG_ASSERT(use->next_use() == NULL); 224 ASSERT(use->next_use() == NULL);
225 DEBUG_ASSERT(0 == MembershipCount(use, use->definition()->env_use_list())); 225 DEBUG_ASSERT(0 == MembershipCount(use, use->definition()->env_use_list()));
226 use->set_instruction(instr); 226 use->set_instruction(instr);
227 use->set_use_index(use_index++); 227 use->set_use_index(use_index++);
228 use->AddToEnvUseList(); 228 use->AddToEnvUseList();
229 } 229 }
230 } 230 }
231 231
232 232
233 static void ComputeUseListsRecursive(BlockEntryInstr* block) { 233 static void ComputeUseListsRecursive(BlockEntryInstr* block) {
234 // Clear phi definitions. 234 // Clear phi definitions.
(...skipping 20 matching lines...) Expand all
255 block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 255 block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
256 JoinEntryInstr* join = 256 JoinEntryInstr* join =
257 block->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 257 block->last_instruction()->SuccessorAt(0)->AsJoinEntry();
258 intptr_t pred_index = join->IndexOfPredecessor(block); 258 intptr_t pred_index = join->IndexOfPredecessor(block);
259 ASSERT(pred_index >= 0); 259 ASSERT(pred_index >= 0);
260 if (join->phis() != NULL) { 260 if (join->phis() != NULL) {
261 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 261 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
262 PhiInstr* phi = (*join->phis())[i]; 262 PhiInstr* phi = (*join->phis())[i];
263 if (phi == NULL) continue; 263 if (phi == NULL) continue;
264 Value* use = phi->InputAt(pred_index); 264 Value* use = phi->InputAt(pred_index);
265 DEBUG_ASSERT(use->instruction() == NULL); 265 ASSERT(use->instruction() == NULL);
266 DEBUG_ASSERT(use->use_index() == -1); 266 ASSERT(use->use_index() == -1);
267 DEBUG_ASSERT(use->next_use() == NULL); 267 ASSERT(use->next_use() == NULL);
268 DEBUG_ASSERT(0 == MembershipCount(use, 268 DEBUG_ASSERT(0 == MembershipCount(use,
269 use->definition()->input_use_list())); 269 use->definition()->input_use_list()));
270 use->set_instruction(phi); 270 use->set_instruction(phi);
271 use->set_use_index(pred_index); 271 use->set_use_index(pred_index);
272 use->AddToInputUseList(); 272 use->AddToInputUseList();
273 } 273 }
274 } 274 }
275 } 275 }
276 } 276 }
277 277
278 278
279 void FlowGraph::ComputeUseLists() { 279 void FlowGraph::ComputeUseLists() {
280 DEBUG_ASSERT(ResetUseLists()); 280 DEBUG_ASSERT(ResetUseLists());
281 // Clear initial definitions. 281 // Clear initial definitions.
282 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { 282 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) {
283 ClearUseLists((*graph_entry_->initial_definitions())[i]); 283 ClearUseLists((*graph_entry_->initial_definitions())[i]);
284 } 284 }
285 ComputeUseListsRecursive(graph_entry_); 285 ComputeUseListsRecursive(graph_entry_);
286 DEBUG_ASSERT(ValidateUseLists()); 286 DEBUG_ASSERT(ValidateUseLists());
287 } 287 }
288 288
289 289
290 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number) { 290 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number) {
291 current_ssa_temp_index_ = next_virtual_register_number; 291 current_ssa_temp_index_ = next_virtual_register_number;
292 GrowableArray<BitVector*> dominance_frontier; 292 GrowableArray<BitVector*> dominance_frontier;
293 ComputeDominators(&preorder_, &parent_, &dominance_frontier); 293 ComputeDominators(&dominance_frontier);
294 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 294 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
295 GrowableArray<PhiInstr*> live_phis; 295 GrowableArray<PhiInstr*> live_phis;
296 // Rename uses to reference inserted phis where appropriate. 296 // Rename uses to reference inserted phis where appropriate.
297 // Collect phis that reach a non-environment use. 297 // Collect phis that reach a non-environment use.
298 Rename(&live_phis); 298 Rename(&live_phis);
299 // Propagate alive mark transitively from alive phis. 299 // Propagate alive mark transitively from alive phis.
300 MarkLivePhis(&live_phis); 300 MarkLivePhis(&live_phis);
301 } 301 }
302 302
303 303
304 // Compute immediate dominators and the dominance frontier for each basic 304 // Compute immediate dominators and the dominance frontier for each basic
305 // block. As a side effect of the algorithm, sets the immediate dominator 305 // block. As a side effect of the algorithm, sets the immediate dominator
306 // of each basic block. 306 // of each basic block.
307 // 307 //
308 // preorder: an input list of basic block entries in preorder. The
309 // algorithm relies on the block ordering.
310 //
311 // parent: an input parameter encoding a depth-first spanning tree of
312 // the control flow graph. The array maps the preorder block
313 // number of a block to the preorder block number of its spanning
314 // tree parent.
315 //
316 // dominance_frontier: an output parameter encoding the dominance frontier. 308 // dominance_frontier: an output parameter encoding the dominance frontier.
317 // The array maps the preorder block number of a block to the set of 309 // The array maps the preorder block number of a block to the set of
318 // (preorder block numbers of) blocks in the dominance frontier. 310 // (preorder block numbers of) blocks in the dominance frontier.
319 void FlowGraph::ComputeDominators( 311 void FlowGraph::ComputeDominators(
320 GrowableArray<BlockEntryInstr*>* preorder,
321 GrowableArray<intptr_t>* parent,
322 GrowableArray<BitVector*>* dominance_frontier) { 312 GrowableArray<BitVector*>* dominance_frontier) {
323 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass 313 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
324 // version of the Lengauer-Tarjan algorithm (LT is normally three passes) 314 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
325 // that eliminates a pass by using nearest-common ancestor (NCA) to 315 // that eliminates a pass by using nearest-common ancestor (NCA) to
326 // compute immediate dominators from semidominators. It also removes a 316 // compute immediate dominators from semidominators. It also removes a
327 // level of indirection in the link-eval forest data structure. 317 // level of indirection in the link-eval forest data structure.
328 // 318 //
329 // The algorithm is described in Georgiadis, Tarjan, and Werneck's 319 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
330 // "Finding Dominators in Practice". 320 // "Finding Dominators in Practice".
331 // See http://www.cs.princeton.edu/~rwerneck/dominators/ . 321 // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
332 322
333 // All arrays are maps between preorder basic-block numbers. 323 // All arrays are maps between preorder basic-block numbers.
334 intptr_t size = parent->length(); 324 intptr_t size = parent_.length();
335 GrowableArray<intptr_t> idom(size); // Immediate dominator. 325 GrowableArray<intptr_t> idom(size); // Immediate dominator.
336 GrowableArray<intptr_t> semi(size); // Semidominator. 326 GrowableArray<intptr_t> semi(size); // Semidominator.
337 GrowableArray<intptr_t> label(size); // Label for link-eval forest. 327 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
338 328
339 // 1. First pass: compute semidominators as in Lengauer-Tarjan. 329 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
340 // Semidominators are computed from a depth-first spanning tree and are an 330 // Semidominators are computed from a depth-first spanning tree and are an
341 // approximation of immediate dominators. 331 // approximation of immediate dominators.
342 332
343 // Use a link-eval data structure with path compression. Implement path 333 // Use a link-eval data structure with path compression. Implement path
344 // compression in place by mutating the parent array. Each block has a 334 // compression in place by mutating the parent array. Each block has a
345 // label, which is the minimum block number on the compressed path. 335 // label, which is the minimum block number on the compressed path.
346 336
347 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the 337 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
348 // dominance frontier output array. 338 // dominance frontier output array.
349 for (intptr_t i = 0; i < size; ++i) { 339 for (intptr_t i = 0; i < size; ++i) {
350 idom.Add((*parent)[i]); 340 idom.Add(parent_[i]);
351 semi.Add(i); 341 semi.Add(i);
352 label.Add(i); 342 label.Add(i);
353 dominance_frontier->Add(new BitVector(size)); 343 dominance_frontier->Add(new BitVector(size));
354 } 344 }
355 345
356 // Loop over the blocks in reverse preorder (not including the graph 346 // Loop over the blocks in reverse preorder (not including the graph
357 // entry). 347 // entry). Clear the dominated blocks in the graph entry in case
348 // ComputeDominators is used to recompute them.
349 preorder_[0]->ClearDominatedBlocks();
358 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) { 350 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
359 // Loop over the predecessors. 351 // Loop over the predecessors.
360 BlockEntryInstr* block = (*preorder)[block_index]; 352 BlockEntryInstr* block = preorder_[block_index];
353 // Clear the immediately dominated blocks in case ComputeDominators is
354 // used to recompute them.
355 block->ClearDominatedBlocks();
361 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { 356 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
362 BlockEntryInstr* pred = block->PredecessorAt(i); 357 BlockEntryInstr* pred = block->PredecessorAt(i);
363 ASSERT(pred != NULL); 358 ASSERT(pred != NULL);
364 359
365 // Look for the semidominator by ascending the semidominator path 360 // Look for the semidominator by ascending the semidominator path
366 // starting from pred. 361 // starting from pred.
367 intptr_t pred_index = pred->preorder_number(); 362 intptr_t pred_index = pred->preorder_number();
368 intptr_t best = pred_index; 363 intptr_t best = pred_index;
369 if (pred_index > block_index) { 364 if (pred_index > block_index) {
370 CompressPath(block_index, pred_index, parent, &label); 365 CompressPath(block_index, pred_index, &parent_, &label);
371 best = label[pred_index]; 366 best = label[pred_index];
372 } 367 }
373 368
374 // Update the semidominator if we've found a better one. 369 // Update the semidominator if we've found a better one.
375 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]); 370 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
376 } 371 }
377 372
378 // Now use label for the semidominator. 373 // Now use label for the semidominator.
379 label[block_index] = semi[block_index]; 374 label[block_index] = semi[block_index];
380 } 375 }
381 376
382 // 2. Compute the immediate dominators as the nearest common ancestor of 377 // 2. Compute the immediate dominators as the nearest common ancestor of
383 // spanning tree parent and semidominator, for all blocks except the entry. 378 // spanning tree parent and semidominator, for all blocks except the entry.
384 for (intptr_t block_index = 1; block_index < size; ++block_index) { 379 for (intptr_t block_index = 1; block_index < size; ++block_index) {
385 intptr_t dom_index = idom[block_index]; 380 intptr_t dom_index = idom[block_index];
386 while (dom_index > semi[block_index]) { 381 while (dom_index > semi[block_index]) {
387 dom_index = idom[dom_index]; 382 dom_index = idom[dom_index];
388 } 383 }
389 idom[block_index] = dom_index; 384 idom[block_index] = dom_index;
390 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]); 385 preorder_[block_index]->set_dominator(preorder_[dom_index]);
391 (*preorder)[dom_index]->AddDominatedBlock((*preorder)[block_index]); 386 preorder_[dom_index]->AddDominatedBlock(preorder_[block_index]);
392 } 387 }
393 388
394 // 3. Now compute the dominance frontier for all blocks. This is 389 // 3. Now compute the dominance frontier for all blocks. This is
395 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is 390 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is
396 // attributed to a paper by Ferrante et al. There is no bookkeeping 391 // attributed to a paper by Ferrante et al. There is no bookkeeping
397 // required to avoid adding a block twice to the same block's dominance 392 // required to avoid adding a block twice to the same block's dominance
398 // frontier because we use a set to represent the dominance frontier. 393 // frontier because we use a set to represent the dominance frontier.
399 for (intptr_t block_index = 0; block_index < size; ++block_index) { 394 for (intptr_t block_index = 0; block_index < size; ++block_index) {
400 BlockEntryInstr* block = (*preorder)[block_index]; 395 BlockEntryInstr* block = preorder_[block_index];
401 intptr_t count = block->PredecessorCount(); 396 intptr_t count = block->PredecessorCount();
402 if (count <= 1) continue; 397 if (count <= 1) continue;
403 for (intptr_t i = 0; i < count; ++i) { 398 for (intptr_t i = 0; i < count; ++i) {
404 BlockEntryInstr* runner = block->PredecessorAt(i); 399 BlockEntryInstr* runner = block->PredecessorAt(i);
405 while (runner != block->dominator()) { 400 while (runner != block->dominator()) {
406 (*dominance_frontier)[runner->preorder_number()]->Add(block_index); 401 (*dominance_frontier)[runner->preorder_number()]->Add(block_index);
407 runner = runner->dominator(); 402 runner = runner->dominator();
408 } 403 }
409 } 404 }
410 } 405 }
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 // TODO(zerny): Support multiple exits. 790 // TODO(zerny): Support multiple exits.
796 UNREACHABLE(); 791 UNREACHABLE();
797 } 792 }
798 793
799 // TODO(zerny): Adjust pre/post orders. 794 // TODO(zerny): Adjust pre/post orders.
800 // TODO(zerny): Update dominator tree. 795 // TODO(zerny): Update dominator tree.
801 } 796 }
802 797
803 798
804 } // namespace dart 799 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698