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

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

Issue 10943007: Initial implementation of sparse conditional constant propagation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flow_graph_allocator.h" 9 #include "vm/flow_graph_allocator.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/flow_graph_optimizer.h"
12 #include "vm/locations.h" 13 #include "vm/locations.h"
13 #include "vm/object.h" 14 #include "vm/object.h"
14 #include "vm/object_store.h" 15 #include "vm/object_store.h"
15 #include "vm/os.h" 16 #include "vm/os.h"
16 #include "vm/scopes.h" 17 #include "vm/scopes.h"
17 #include "vm/stub_code.h" 18 #include "vm/stub_code.h"
18 #include "vm/symbols.h" 19 #include "vm/symbols.h"
19 20
20 namespace dart { 21 namespace dart {
21 22
22 DECLARE_FLAG(bool, enable_type_checks); 23 DECLARE_FLAG(bool, enable_type_checks);
23 24
24 25
26 Definition::Definition()
27 : temp_index_(-1),
28 ssa_temp_index_(-1),
29 propagated_type_(AbstractType::Handle()),
30 propagated_cid_(kIllegalCid),
31 input_use_list_(NULL),
32 env_use_list_(NULL),
33 use_kind_(kValue), // Phis and parameters rely on this default.
34 constant_value_(Object::ZoneHandle(ConstantPropagator::Unknown())) {
35 }
36
37
25 intptr_t Definition::Hashcode() const { 38 intptr_t Definition::Hashcode() const {
26 intptr_t result = tag(); 39 intptr_t result = tag();
27 for (intptr_t i = 0; i < InputCount(); ++i) { 40 for (intptr_t i = 0; i < InputCount(); ++i) {
28 Value* value = InputAt(i); 41 Value* value = InputAt(i);
29 intptr_t j = value->definition()->ssa_temp_index(); 42 intptr_t j = value->definition()->ssa_temp_index();
30 result = result * 31 + j; 43 result = result * 31 + j;
31 } 44 }
32 return result; 45 return result;
33 } 46 }
34 47
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 428
416 429
417 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { 430 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const {
418 for (intptr_t i = 0; i < predecessors_.length(); ++i) { 431 for (intptr_t i = 0; i < predecessors_.length(); ++i) {
419 if (predecessors_[i] == pred) return i; 432 if (predecessors_[i] == pred) return i;
420 } 433 }
421 return -1; 434 return -1;
422 } 435 }
423 436
424 437
438 void JoinEntryInstr::EliminateUnreachablePhiInputs() {
439 if (phis_ == NULL || phis_->is_empty()) return;
440
441 // Loop over the predecessors, reorganize phi inputs.
442 // TODO(kmillikin): Replace phis that have a single remaining input with
443 // the input. This requires being a bit careful about use lists.
444 intptr_t input_count = predecessors_.length();
445 for (intptr_t new_idx = 0; new_idx < input_count; ++new_idx) {
446 BlockEntryInstr* pred = predecessors_[new_idx];
447 // Linear search for the old predecessor index. We can't directly
448 // compare block entries, because unreachable code elimination has
449 // replaced some targets with joins.
450 intptr_t old_idx = 0;
451 for (; old_idx < stale_predecessors_.length(); ++old_idx) {
452 if (stale_predecessors_[old_idx]->next() == pred->next()) break;
453 }
454 ASSERT(old_idx < stale_predecessors_.length());
455 // If the index has changed, adjust all phi inputs.
456 if (old_idx != new_idx) {
457 ASSERT(new_idx < old_idx);
458 // Swap each phi's inputs so the input at new_idx is correct.
459 // Preserve the previous value in case it is from a reachable
460 // predecessor.
461 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) {
462 PhiInstr* phi = (*phis_)[phi_idx];
463 if (phi == NULL) continue;
464 Value* temp = phi->InputAt(new_idx);
465 phi->SetInputAt(new_idx, phi->InputAt(old_idx));
466 phi->SetInputAt(old_idx, temp);
467 }
468 // The old input at new_idx is now found at old_idx. It may be a
469 // reachable predecessor so swap the old predecessors too.
470 BlockEntryInstr* temp = stale_predecessors_[new_idx];
471 stale_predecessors_[new_idx] = stale_predecessors_[old_idx];
472 stale_predecessors_[old_idx] = temp;
473 }
474 }
475 // Now truncate each phi if necessary.
476 if (input_count < stale_predecessors_.length()) {
477 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) {
478 PhiInstr* phi = (*phis_)[phi_idx];
479 if (phi == NULL) continue;
480 phi->inputs_.TruncateTo(input_count);
481 }
482 }
483 }
484
485
425 // ==== Recording assigned variables. 486 // ==== Recording assigned variables.
426 void Definition::RecordAssignedVars(BitVector* assigned_vars, 487 void Definition::RecordAssignedVars(BitVector* assigned_vars,
427 intptr_t fixed_parameter_count) { 488 intptr_t fixed_parameter_count) {
428 // Nothing to do for the base class. 489 // Nothing to do for the base class.
429 } 490 }
430 491
431 492
432 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, 493 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars,
433 intptr_t fixed_parameter_count) { 494 intptr_t fixed_parameter_count) {
434 if (!local().is_captured()) { 495 if (!local().is_captured()) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 return propagated_cid(); 585 return propagated_cid();
525 } 586 }
526 587
527 588
528 intptr_t ParameterInstr::GetPropagatedCid() { 589 intptr_t ParameterInstr::GetPropagatedCid() {
529 return propagated_cid(); 590 return propagated_cid();
530 } 591 }
531 592
532 593
533 // ==== Postorder graph traversal. 594 // ==== Postorder graph traversal.
595 static bool IsMarked(BlockEntryInstr* block,
596 GrowableArray<BlockEntryInstr*>* preorder) {
597 // Detect that a block has been visited as part of the current
598 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block
599 // will be 'marked' by (1) having a preorder number in the range of the
600 // preorder array and (2) being in the preorder array at that index.
601 intptr_t i = block->preorder_number();
602 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block);
603 }
604
605
534 void GraphEntryInstr::DiscoverBlocks( 606 void GraphEntryInstr::DiscoverBlocks(
535 BlockEntryInstr* current_block, 607 BlockEntryInstr* current_block,
536 GrowableArray<BlockEntryInstr*>* preorder, 608 GrowableArray<BlockEntryInstr*>* preorder,
537 GrowableArray<BlockEntryInstr*>* postorder, 609 GrowableArray<BlockEntryInstr*>* postorder,
538 GrowableArray<intptr_t>* parent, 610 GrowableArray<intptr_t>* parent,
539 GrowableArray<BitVector*>* assigned_vars, 611 GrowableArray<BitVector*>* assigned_vars,
540 intptr_t variable_count, 612 intptr_t variable_count,
541 intptr_t fixed_parameter_count) { 613 intptr_t fixed_parameter_count) {
542 // We only visit this block once, first of all blocks. 614 // We only visit this block once, first of all blocks.
543 ASSERT(preorder_number() == -1); 615 ASSERT(!IsMarked(this, preorder));
544 ASSERT(current_block == NULL); 616 ASSERT(current_block == NULL);
545 ASSERT(preorder->is_empty()); 617 ASSERT(preorder->is_empty());
546 ASSERT(postorder->is_empty()); 618 ASSERT(postorder->is_empty());
547 ASSERT(parent->is_empty()); 619 ASSERT(parent->is_empty());
548 620
549 // This node has no parent, indicated by -1. The preorder number is 0. 621 // This node has no parent, indicated by -1. The preorder number is 0.
550 parent->Add(-1); 622 parent->Add(-1);
551 set_preorder_number(0); 623 set_preorder_number(0);
552 preorder->Add(this); 624 preorder->Add(this);
553 BitVector* vars = 625 BitVector* vars =
(...skipping 27 matching lines...) Expand all
581 GrowableArray<BlockEntryInstr*>* preorder, 653 GrowableArray<BlockEntryInstr*>* preorder,
582 GrowableArray<BlockEntryInstr*>* postorder, 654 GrowableArray<BlockEntryInstr*>* postorder,
583 GrowableArray<intptr_t>* parent, 655 GrowableArray<intptr_t>* parent,
584 GrowableArray<BitVector*>* assigned_vars, 656 GrowableArray<BitVector*>* assigned_vars,
585 intptr_t variable_count, 657 intptr_t variable_count,
586 intptr_t fixed_parameter_count) { 658 intptr_t fixed_parameter_count) {
587 // We have already visited the graph entry, so we can assume current_block 659 // We have already visited the graph entry, so we can assume current_block
588 // is non-null and preorder array is non-empty. 660 // is non-null and preorder array is non-empty.
589 ASSERT(current_block != NULL); 661 ASSERT(current_block != NULL);
590 ASSERT(!preorder->is_empty()); 662 ASSERT(!preorder->is_empty());
663 // Blocks with a single predecessor cannot have been reached before.
664 ASSERT(!IsTargetEntry() || !IsMarked(this, preorder));
591 665
592 // 1. Record control-flow-graph basic-block predecessors. 666 // 1. If the block has already been reached, add current_block as a
667 // basic-block predecessor and we are done.
668 if (IsMarked(this, preorder)) {
669 AddPredecessor(current_block);
670 return;
671 }
672
673 // 2. Otherwise, clear the predecessors which might have been computed on
674 // some earlier call to DiscoverBlocks and record this predecessor. For
675 // joins save the original predecessors, if any, so we can garbage collect
676 // phi inputs from unreachable predecessors without recomputing SSA.
677 ClearPredecessors();
593 AddPredecessor(current_block); 678 AddPredecessor(current_block);
594 679
595 // 2. If the block has already been reached by the traversal, we are
596 // done. Blocks with a single predecessor cannot have been reached
597 // before.
598 ASSERT(!IsTargetEntry() || (preorder_number() == -1));
599 if (preorder_number() >= 0) return;
600
601 // 3. The current block is the spanning-tree parent. 680 // 3. The current block is the spanning-tree parent.
602 parent->Add(current_block->preorder_number()); 681 parent->Add(current_block->preorder_number());
603 682
604 // 4. Assign preorder number and add the block entry to the list. 683 // 4. Assign preorder number and add the block entry to the list.
605 // Allocate an empty set of assigned variables for the block. 684 // Allocate an empty set of assigned variables for the block.
606 set_preorder_number(preorder->length()); 685 set_preorder_number(preorder->length());
607 preorder->Add(this); 686 preorder->Add(this);
608 BitVector* vars = 687 BitVector* vars =
609 (variable_count == 0) ? NULL : new BitVector(variable_count); 688 (variable_count == 0) ? NULL : new BitVector(variable_count);
610 assigned_vars->Add(vars); 689 assigned_vars->Add(vars);
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after
1692 value->set_use_index(use_index++); 1771 value->set_use_index(use_index++);
1693 value->AddToEnvUseList(); 1772 value->AddToEnvUseList();
1694 } 1773 }
1695 instr->set_env(copy); 1774 instr->set_env(copy);
1696 } 1775 }
1697 1776
1698 1777
1699 #undef __ 1778 #undef __
1700 1779
1701 } // namespace dart 1780 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698