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

Side by Side Diff: runtime/vm/intermediate_language.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/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 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 482
470 483
471 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { 484 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const {
472 for (intptr_t i = 0; i < predecessors_.length(); ++i) { 485 for (intptr_t i = 0; i < predecessors_.length(); ++i) {
473 if (predecessors_[i] == pred) return i; 486 if (predecessors_[i] == pred) return i;
474 } 487 }
475 return -1; 488 return -1;
476 } 489 }
477 490
478 491
492 void JoinEntryInstr::EliminateUnreachablePhiInputs() {
493 if (phis_ == NULL || phis_->is_empty()) return;
494
495 // Loop over the predecessors, reorganize phi inputs.
496 // TODO(kmillikin): Replace phis that have a single remaining input with
497 // the input. This requires being a bit careful about use lists.
498 intptr_t input_count = predecessors_.length();
499 for (intptr_t new_idx = 0; new_idx < input_count; ++new_idx) {
500 BlockEntryInstr* pred = predecessors_[new_idx];
501 // Linear search for the old predecessor index. We can't directly
502 // compare block entries, because unreachable code elimination has
503 // replaced some targets with joins.
504 intptr_t old_idx = 0;
505 for (; old_idx < stale_predecessors_.length(); ++old_idx) {
506 if (stale_predecessors_[old_idx]->next() == pred->next()) break;
507 }
508 ASSERT(old_idx < stale_predecessors_.length());
509 // If the index has changed, adjust all phi inputs.
510 if (old_idx != new_idx) {
511 ASSERT(new_idx < old_idx);
512 // Swap each phi's inputs so the input at new_idx is correct.
513 // Preserve the previous value in case it is from a reachable
514 // predecessor.
515 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) {
516 PhiInstr* phi = (*phis_)[phi_idx];
517 if (phi == NULL) continue;
518 Value* temp = phi->InputAt(new_idx);
519 phi->SetInputAt(new_idx, phi->InputAt(old_idx));
520 phi->SetInputAt(old_idx, temp);
521 }
522 // The old input at new_idx is now found at old_idx. It may be a
523 // reachable predecessor so swap the old predecessors too.
524 BlockEntryInstr* temp = stale_predecessors_[new_idx];
525 stale_predecessors_[new_idx] = stale_predecessors_[old_idx];
526 stale_predecessors_[old_idx] = temp;
527 }
528 }
529 // Now truncate each phi if necessary.
530 if (input_count < stale_predecessors_.length()) {
531 for (intptr_t phi_idx = 0; phi_idx < phis_->length(); ++phi_idx) {
532 PhiInstr* phi = (*phis_)[phi_idx];
533 if (phi == NULL) continue;
534 phi->inputs_.TruncateTo(input_count);
535 }
536 }
537 }
538
539
479 // ==== Recording assigned variables. 540 // ==== Recording assigned variables.
480 void Definition::RecordAssignedVars(BitVector* assigned_vars, 541 void Definition::RecordAssignedVars(BitVector* assigned_vars,
481 intptr_t fixed_parameter_count) { 542 intptr_t fixed_parameter_count) {
482 // Nothing to do for the base class. 543 // Nothing to do for the base class.
483 } 544 }
484 545
485 546
486 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, 547 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars,
487 intptr_t fixed_parameter_count) { 548 intptr_t fixed_parameter_count) {
488 if (!local().is_captured()) { 549 if (!local().is_captured()) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 return propagated_cid(); 639 return propagated_cid();
579 } 640 }
580 641
581 642
582 intptr_t ParameterInstr::GetPropagatedCid() { 643 intptr_t ParameterInstr::GetPropagatedCid() {
583 return propagated_cid(); 644 return propagated_cid();
584 } 645 }
585 646
586 647
587 // ==== Postorder graph traversal. 648 // ==== Postorder graph traversal.
649 static bool IsMarked(BlockEntryInstr* block,
650 GrowableArray<BlockEntryInstr*>* preorder) {
651 // Detect that a block has been visited as part of the current
652 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block
653 // will be 'marked' by (1) having a preorder number in the range of the
654 // preorder array and (2) being in the preorder array at that index.
655 intptr_t i = block->preorder_number();
656 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block);
657 }
658
659
588 void GraphEntryInstr::DiscoverBlocks( 660 void GraphEntryInstr::DiscoverBlocks(
589 BlockEntryInstr* current_block, 661 BlockEntryInstr* current_block,
590 GrowableArray<BlockEntryInstr*>* preorder, 662 GrowableArray<BlockEntryInstr*>* preorder,
591 GrowableArray<BlockEntryInstr*>* postorder, 663 GrowableArray<BlockEntryInstr*>* postorder,
592 GrowableArray<intptr_t>* parent, 664 GrowableArray<intptr_t>* parent,
593 GrowableArray<BitVector*>* assigned_vars, 665 GrowableArray<BitVector*>* assigned_vars,
594 intptr_t variable_count, 666 intptr_t variable_count,
595 intptr_t fixed_parameter_count) { 667 intptr_t fixed_parameter_count) {
596 // We only visit this block once, first of all blocks. 668 // We only visit this block once, first of all blocks.
597 ASSERT(preorder_number() == -1); 669 ASSERT(!IsMarked(this, preorder));
598 ASSERT(current_block == NULL); 670 ASSERT(current_block == NULL);
599 ASSERT(preorder->is_empty()); 671 ASSERT(preorder->is_empty());
600 ASSERT(postorder->is_empty()); 672 ASSERT(postorder->is_empty());
601 ASSERT(parent->is_empty()); 673 ASSERT(parent->is_empty());
602 674
603 // This node has no parent, indicated by -1. The preorder number is 0. 675 // This node has no parent, indicated by -1. The preorder number is 0.
604 parent->Add(-1); 676 parent->Add(-1);
605 set_preorder_number(0); 677 set_preorder_number(0);
606 preorder->Add(this); 678 preorder->Add(this);
607 BitVector* vars = 679 BitVector* vars =
(...skipping 27 matching lines...) Expand all
635 GrowableArray<BlockEntryInstr*>* preorder, 707 GrowableArray<BlockEntryInstr*>* preorder,
636 GrowableArray<BlockEntryInstr*>* postorder, 708 GrowableArray<BlockEntryInstr*>* postorder,
637 GrowableArray<intptr_t>* parent, 709 GrowableArray<intptr_t>* parent,
638 GrowableArray<BitVector*>* assigned_vars, 710 GrowableArray<BitVector*>* assigned_vars,
639 intptr_t variable_count, 711 intptr_t variable_count,
640 intptr_t fixed_parameter_count) { 712 intptr_t fixed_parameter_count) {
641 // We have already visited the graph entry, so we can assume current_block 713 // We have already visited the graph entry, so we can assume current_block
642 // is non-null and preorder array is non-empty. 714 // is non-null and preorder array is non-empty.
643 ASSERT(current_block != NULL); 715 ASSERT(current_block != NULL);
644 ASSERT(!preorder->is_empty()); 716 ASSERT(!preorder->is_empty());
717 // Blocks with a single predecessor cannot have been reached before.
718 ASSERT(!IsTargetEntry() || !IsMarked(this, preorder));
645 719
646 // 1. Record control-flow-graph basic-block predecessors. 720 // 1. If the block has already been reached, add current_block as a
721 // basic-block predecessor and we are done.
722 if (IsMarked(this, preorder)) {
723 AddPredecessor(current_block);
724 return;
725 }
726
727 // 2. Otherwise, clear the predecessors which might have been computed on
728 // some earlier call to DiscoverBlocks and record this predecessor. For
729 // joins save the original predecessors, if any, so we can garbage collect
730 // phi inputs from unreachable predecessors without recomputing SSA.
731 ClearPredecessors();
647 AddPredecessor(current_block); 732 AddPredecessor(current_block);
648 733
649 // 2. If the block has already been reached by the traversal, we are
650 // done. Blocks with a single predecessor cannot have been reached
651 // before.
652 ASSERT(!IsTargetEntry() || (preorder_number() == -1));
653 if (preorder_number() >= 0) return;
654
655 // 3. The current block is the spanning-tree parent. 734 // 3. The current block is the spanning-tree parent.
656 parent->Add(current_block->preorder_number()); 735 parent->Add(current_block->preorder_number());
657 736
658 // 4. Assign preorder number and add the block entry to the list. 737 // 4. Assign preorder number and add the block entry to the list.
659 // Allocate an empty set of assigned variables for the block. 738 // Allocate an empty set of assigned variables for the block.
660 set_preorder_number(preorder->length()); 739 set_preorder_number(preorder->length());
661 preorder->Add(this); 740 preorder->Add(this);
662 BitVector* vars = 741 BitVector* vars =
663 (variable_count == 0) ? NULL : new BitVector(variable_count); 742 (variable_count == 0) ? NULL : new BitVector(variable_count);
664 assigned_vars->Add(vars); 743 assigned_vars->Add(vars);
(...skipping 1090 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 value->set_use_index(use_index++); 1834 value->set_use_index(use_index++);
1756 value->AddToEnvUseList(); 1835 value->AddToEnvUseList();
1757 } 1836 }
1758 instr->env()->outer_ = copy; 1837 instr->env()->outer_ = copy;
1759 } 1838 }
1760 1839
1761 1840
1762 #undef __ 1841 #undef __
1763 1842
1764 } // namespace dart 1843 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698