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

Side by Side Diff: vm/flow_graph_builder.cc

Issue 10665022: Make IL instructions a doubly-linked list within basic blocks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: use_ssa flag off by default Created 8 years, 6 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
« no previous file with comments | « no previous file | vm/intermediate_language.h » ('j') | vm/intermediate_language.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "vm/ast_printer.h" 7 #include "vm/ast_printer.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/code_descriptors.h" 9 #include "vm/code_descriptors.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 } 66 }
67 if (is_empty()) { 67 if (is_empty()) {
68 entry_ = exit_ = instruction; 68 entry_ = exit_ = instruction;
69 } else { 69 } else {
70 exit()->SetSuccessor(instruction); 70 exit()->SetSuccessor(instruction);
71 exit_ = instruction; 71 exit_ = instruction;
72 } 72 }
73 } 73 }
74 74
75 75
76 // Appends a graph fragment to a block entry instruction and returns the exit
77 // of the resulting graph fragment.
78 static Instruction* AppendFragment(BlockEntryInstr* entry,
79 const EffectGraphVisitor& fragment) {
80 if (fragment.is_empty()) return entry;
81 entry->SetSuccessor(fragment.entry());
82 return fragment.exit();
83 }
srdjan 2012/06/25 15:57:16 I like it a lot that we factor out the knowledge o
84
85
76 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, 86 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment,
77 const EffectGraphVisitor& true_fragment, 87 const EffectGraphVisitor& true_fragment,
78 const EffectGraphVisitor& false_fragment) { 88 const EffectGraphVisitor& false_fragment) {
79 // We have: a test graph fragment with zero, one, or two available exits; 89 // We have: a test graph fragment with zero, one, or two available exits;
80 // and a pair of effect graph fragments with zero or one available exits. 90 // and a pair of effect graph fragments with zero or one available exits.
81 // We want to append the branch and (if necessary) a join node to this 91 // We want to append the branch and (if necessary) a join node to this
82 // graph fragment. 92 // graph fragment.
83 ASSERT(is_open()); 93 ASSERT(is_open());
84 94
85 // 1. Connect the test to this graph. 95 // 1. Connect the test to this graph.
86 Append(test_fragment); 96 Append(test_fragment);
87 97
88 // 2. Connect the true and false bodies to the test and record their exits 98 // 2. Connect the true and false bodies to the test and record their exits
89 // (if any). 99 // (if any).
90 Instruction* true_exit = NULL;
91 Instruction* false_exit = NULL;
92 TargetEntryInstr* true_entry = new TargetEntryInstr(); 100 TargetEntryInstr* true_entry = new TargetEntryInstr();
93 *test_fragment.true_successor_address() = true_entry; 101 *test_fragment.true_successor_address() = true_entry;
94 true_entry->SetSuccessor(true_fragment.entry()); 102 Instruction* true_exit = AppendFragment(true_entry, true_fragment);
95 true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit();
96 103
97 TargetEntryInstr* false_entry = new TargetEntryInstr(); 104 TargetEntryInstr* false_entry = new TargetEntryInstr();
98 *test_fragment.false_successor_address() = false_entry; 105 *test_fragment.false_successor_address() = false_entry;
99 false_entry->SetSuccessor(false_fragment.entry()); 106 Instruction* false_exit = AppendFragment(false_entry, false_fragment);
100 false_exit = false_fragment.is_empty() ? false_entry : false_fragment.exit();
101 107
102 // 3. Add a join or select one (or neither) of the arms as exit. 108 // 3. Add a join or select one (or neither) of the arms as exit.
103 if (true_exit == NULL) { 109 if (true_exit == NULL) {
104 exit_ = false_exit; // May be NULL. 110 exit_ = false_exit; // May be NULL.
105 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); 111 if (false_exit != NULL) temp_index_ = false_fragment.temp_index();
106 } else if (false_exit == NULL) { 112 } else if (false_exit == NULL) {
107 exit_ = true_exit; 113 exit_ = true_exit;
108 temp_index_ = true_fragment.temp_index(); 114 temp_index_ = true_fragment.temp_index();
109 } else { 115 } else {
110 exit_ = new JoinEntryInstr(); 116 exit_ = new JoinEntryInstr();
111 true_exit->SetSuccessor(exit_); 117 true_exit->SetSuccessor(exit_);
112 false_exit->SetSuccessor(exit_); 118 false_exit->SetSuccessor(exit_);
113 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); 119 ASSERT(true_fragment.temp_index() == false_fragment.temp_index());
114 temp_index_ = true_fragment.temp_index(); 120 temp_index_ = true_fragment.temp_index();
115 } 121 }
116 } 122 }
117 123
118 124
119 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, 125 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment,
120 const EffectGraphVisitor& body_fragment) { 126 const EffectGraphVisitor& body_fragment) {
121 // We have: a test graph fragment with zero, one, or two available exits; 127 // We have: a test graph fragment with zero, one, or two available exits;
122 // and an effect graph fragment with zero or one available exits. We want 128 // and an effect graph fragment with zero or one available exits. We want
123 // to append the 'while loop' consisting of the test graph fragment as 129 // to append the 'while loop' consisting of the test graph fragment as
124 // condition and the effect graph fragment as body. 130 // condition and the effect graph fragment as body.
125 ASSERT(is_open()); 131 ASSERT(is_open());
126 132
127 // 1. Connect the body to the test if it is reachable, and if so record 133 // 1. Connect the body to the test if it is reachable, and if so record
128 // its exit (if any). 134 // its exit (if any).
129 Instruction* body_exit = NULL;
130 TargetEntryInstr* body_entry = new TargetEntryInstr(); 135 TargetEntryInstr* body_entry = new TargetEntryInstr();
131 *test_fragment.true_successor_address() = body_entry; 136 *test_fragment.true_successor_address() = body_entry;
132 body_entry->SetSuccessor(body_fragment.entry()); 137 Instruction* body_exit = AppendFragment(body_entry, body_fragment);
133 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit();
134 138
135 // 2. Connect the test to this graph, including the body if reachable and 139 // 2. Connect the test to this graph, including the body if reachable and
136 // using a fresh join node if the body is reachable and has an open exit. 140 // using a fresh join node if the body is reachable and has an open exit.
137 if (body_exit == NULL) { 141 if (body_exit == NULL) {
138 Append(test_fragment); 142 Append(test_fragment);
139 } else { 143 } else {
140 JoinEntryInstr* join = new JoinEntryInstr(); 144 JoinEntryInstr* join = new JoinEntryInstr();
141 AddInstruction(join); 145 AddInstruction(join);
142 join->SetSuccessor(test_fragment.entry()); 146 join->SetSuccessor(test_fragment.entry());
143 body_exit->SetSuccessor(join); 147 body_exit->SetSuccessor(join);
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after
1118 1122
1119 TestGraphVisitor for_test(owner(), 1123 TestGraphVisitor for_test(owner(),
1120 temp_index(), 1124 temp_index(),
1121 node->condition()->token_pos()); 1125 node->condition()->token_pos());
1122 node->condition()->Visit(&for_test); 1126 node->condition()->Visit(&for_test);
1123 ASSERT(is_open()); 1127 ASSERT(is_open());
1124 1128
1125 // Tie do-while loop (test is after the body). 1129 // Tie do-while loop (test is after the body).
1126 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); 1130 JoinEntryInstr* body_entry_join = new JoinEntryInstr();
1127 AddInstruction(body_entry_join); 1131 AddInstruction(body_entry_join);
1128 body_entry_join->SetSuccessor(for_body.entry()); 1132 Instruction* body_exit = AppendFragment(body_entry_join, for_body);
1129 Instruction* body_exit =
1130 for_body.is_empty() ? body_entry_join : for_body.exit();
1131 1133
1132 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { 1134 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) {
1133 BlockEntryInstr* test_entry = NULL; 1135 BlockEntryInstr* test_entry = NULL;
1134 if (node->label()->join_for_continue() == NULL) { 1136 if (node->label()->join_for_continue() == NULL) {
1135 test_entry = new TargetEntryInstr(); 1137 test_entry = new TargetEntryInstr();
1136 } else { 1138 } else {
1137 test_entry = node->label()->join_for_continue(); 1139 test_entry = node->label()->join_for_continue();
1138 } 1140 }
1139 test_entry->SetSuccessor(for_test.entry()); 1141 test_entry->SetSuccessor(for_test.entry());
1140 if (body_exit != NULL) { 1142 if (body_exit != NULL) {
(...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after
2342 &preorder_block_entries_, 2344 &preorder_block_entries_,
2343 &postorder_block_entries_, 2345 &postorder_block_entries_,
2344 &parent, 2346 &parent,
2345 &assigned_vars, 2347 &assigned_vars,
2346 variable_count); 2348 variable_count);
2347 // Number blocks in reverse postorder. 2349 // Number blocks in reverse postorder.
2348 intptr_t block_count = postorder_block_entries_.length(); 2350 intptr_t block_count = postorder_block_entries_.length();
2349 for (intptr_t i = 0; i < block_count; ++i) { 2351 for (intptr_t i = 0; i < block_count; ++i) {
2350 postorder_block_entries_[i]->set_block_id(block_count - i - 1); 2352 postorder_block_entries_[i]->set_block_id(block_count - i - 1);
2351 } 2353 }
2352 if (for_optimized && FLAG_use_ssa) { 2354 if (for_optimized) {
2353 GrowableArray<BitVector*> dominance_frontier; 2355 // Link instructions backwards for optimized compilation.
2354 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); 2356 for (intptr_t i = 0; i < block_count; ++i) {
2355 InsertPhis(preorder_block_entries_, 2357 Instruction* prev = postorder_block_entries_[i];
2356 assigned_vars, 2358 Instruction* current = prev->StraightLineSuccessor();
2357 variable_count, 2359 while (current != NULL && !current->IsBlockEntry()) {
2358 dominance_frontier); 2360 current->SetPrevious(prev);
2359 Rename(variable_count); 2361 prev = current;
2362 current = current->StraightLineSuccessor();
2363 }
2364 }
2365
2366 // Construct SSA form.
2367 if (FLAG_use_ssa) {
2368 GrowableArray<BitVector*> dominance_frontier;
2369 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier);
2370 InsertPhis(preorder_block_entries_,
2371 assigned_vars,
2372 variable_count,
2373 dominance_frontier);
2374 Rename(variable_count);
2375 }
2360 } 2376 }
2361 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { 2377 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) {
2362 intptr_t length = postorder_block_entries_.length(); 2378 intptr_t length = postorder_block_entries_.length();
2363 GrowableArray<BlockEntryInstr*> reverse_postorder(length); 2379 GrowableArray<BlockEntryInstr*> reverse_postorder(length);
2364 for (intptr_t i = length - 1; i >= 0; --i) { 2380 for (intptr_t i = length - 1; i >= 0; --i) {
2365 reverse_postorder.Add(postorder_block_entries_[i]); 2381 reverse_postorder.Add(postorder_block_entries_[i]);
2366 } 2382 }
2367 if (FLAG_print_flow_graph) { 2383 if (FLAG_print_flow_graph) {
2368 // Print flow graph to stdout. 2384 // Print flow graph to stdout.
2369 FlowGraphPrinter printer(function, reverse_postorder); 2385 FlowGraphPrinter printer(function, reverse_postorder);
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
2611 if (phi != NULL) { 2627 if (phi != NULL) {
2612 (*env)[i] = new UseVal(phi); 2628 (*env)[i] = new UseVal(phi);
2613 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. 2629 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp.
2614 } 2630 }
2615 } 2631 }
2616 } 2632 }
2617 } 2633 }
2618 2634
2619 // 2. Process normal instructions. 2635 // 2. Process normal instructions.
2620 Instruction* current = block_entry->StraightLineSuccessor(); 2636 Instruction* current = block_entry->StraightLineSuccessor();
2621 Instruction* prev = block_entry;
2622 while ((current != NULL) && !current->IsBlockEntry()) { 2637 while ((current != NULL) && !current->IsBlockEntry()) {
2623 // 2a. Handle uses of LoadLocal / StoreLocal 2638 // 2a. Handle uses of LoadLocal / StoreLocal
2624 // For each use of a LoadLocal or StoreLocal: Replace it with the value 2639 // For each use of a LoadLocal or StoreLocal: Replace it with the value
2625 // from the environment. 2640 // from the environment.
2626 for (intptr_t i = 0; i < current->InputCount(); ++i) { 2641 for (intptr_t i = 0; i < current->InputCount(); ++i) {
2627 Value* v = current->InputAt(i); 2642 Value* v = current->InputAt(i);
2628 if (v->IsUse() && 2643 if (v->IsUse() &&
2629 v->AsUse()->definition()->IsBind() && 2644 v->AsUse()->definition()->IsBind() &&
2630 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { 2645 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) {
2631 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); 2646 Computation* comp = v->AsUse()->definition()->AsBind()->computation();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2667 if (current->IsDo() && 2682 if (current->IsDo() &&
2668 current->AsDo()->computation()->IsStoreLocal()) { 2683 current->AsDo()->computation()->IsStoreLocal()) {
2669 store = current->AsDo()->computation()->AsStoreLocal(); 2684 store = current->AsDo()->computation()->AsStoreLocal();
2670 } else if (current->IsBind() && 2685 } else if (current->IsBind() &&
2671 current->AsBind()->computation()->IsStoreLocal()) { 2686 current->AsBind()->computation()->IsStoreLocal()) {
2672 store = current->AsBind()->computation()->AsStoreLocal(); 2687 store = current->AsBind()->computation()->AsStoreLocal();
2673 } 2688 }
2674 2689
2675 if (load != NULL) { 2690 if (load != NULL) {
2676 // Remove instruction. 2691 // Remove instruction.
2677 prev->SetSuccessor(current->StraightLineSuccessor()); 2692 current->RemoveFromGraph();
2678 } else if (store != NULL) { 2693 } else if (store != NULL) {
2679 // Remove instruction and update renaming environment. 2694 // Remove instruction and update renaming environment.
2680 prev->SetSuccessor(current->StraightLineSuccessor()); 2695 current->RemoveFromGraph();
2681 (*env)[store->local().BitIndexIn(var_count)] = store->value(); 2696 (*env)[store->local().BitIndexIn(var_count)] = store->value();
2682 } else { 2697 } else if (current->IsBind()) {
2683 // Assign new SSA temporary. 2698 // Assign new SSA temporary.
2684 if (current->IsBind()) { 2699 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++);
2685 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++);
2686 }
2687 // Update previous only if no instruction was removed from the graph.
2688 prev = current;
2689 } 2700 }
2690 current = current->StraightLineSuccessor(); 2701 current = current->StraightLineSuccessor();
2691 } 2702 }
2692 2703
2693 // 3. Process dominated blocks. 2704 // 3. Process dominated blocks.
2694 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { 2705 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
2695 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; 2706 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
2696 ZoneGrowableArray<Value*>* new_env = 2707 ZoneGrowableArray<Value*>* new_env =
2697 new ZoneGrowableArray<Value*>(var_count); 2708 new ZoneGrowableArray<Value*>(var_count);
2698 new_env->AddArray(*env); 2709 new_env->AddArray(*env);
(...skipping 30 matching lines...) Expand all
2729 char* chars = reinterpret_cast<char*>( 2740 char* chars = reinterpret_cast<char*>(
2730 Isolate::Current()->current_zone()->Allocate(len)); 2741 Isolate::Current()->current_zone()->Allocate(len));
2731 OS::SNPrint(chars, len, kFormat, function_name, reason); 2742 OS::SNPrint(chars, len, kFormat, function_name, reason);
2732 const Error& error = Error::Handle( 2743 const Error& error = Error::Handle(
2733 LanguageError::New(String::Handle(String::New(chars)))); 2744 LanguageError::New(String::Handle(String::New(chars))));
2734 Isolate::Current()->long_jump_base()->Jump(1, error); 2745 Isolate::Current()->long_jump_base()->Jump(1, error);
2735 } 2746 }
2736 2747
2737 2748
2738 } // namespace dart 2749 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | vm/intermediate_language.h » ('j') | vm/intermediate_language.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698