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

Unified Diff: vm/flow_graph_builder.cc

Issue 10544206: Second step for computing SSA: renaming. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: 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 side-by-side diff with in-line comments
Download patch
Index: vm/flow_graph_builder.cc
===================================================================
--- vm/flow_graph_builder.cc (revision 8786)
+++ vm/flow_graph_builder.cc (working copy)
@@ -35,7 +35,8 @@
context_level_(0),
last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
try_index_(CatchClauseNode::kInvalidTryIndex),
- graph_entry_(NULL) { }
+ graph_entry_(NULL),
+ current_ssa_temp_index_(0) { }
void FlowGraphBuilder::AddCatchEntry(TargetEntryInstr* entry) {
@@ -2348,7 +2349,7 @@
assigned_vars,
variable_count,
dominance_frontier);
- // TODO(fschneider): Perform SSA renaming.
+ Rename(variable_count);
}
if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) {
intptr_t length = postorder_block_entries_.length();
@@ -2554,6 +2555,164 @@
}
+void FlowGraphBuilder::Rename(intptr_t var_count) {
+ // Initialize start environment:
+ // All locals are initialized with #null.
+ // TODO(fschneider): Support paramters. All parameters are initially located
srdjan 2012/06/18 18:04:38 parameters
Florian Schneider 2012/06/19 11:26:40 Done.
+ // on the stack.
+ ZoneGrowableArray<Value*>* start_env =
+ new ZoneGrowableArray<Value*>(var_count);
+ if (parsed_function().function().num_fixed_parameters() > 0) {
+ Bailout("Fixed parameter support in SSA");
+ }
+ if (parsed_function().copied_parameter_count()) {
+ Bailout("Copied parameter support in SSA");
+ }
+ Value* null_value = new ConstantVal(Object::ZoneHandle());
+ ASSERT(var_count == parsed_function().stack_local_count());
srdjan 2012/06/18 18:04:38 Why don't you use stack_local_count instead of pas
Florian Schneider 2012/06/19 11:26:40 Yes, in one of the next CLs it will change to: va
+ for (intptr_t i = 0; i < var_count; i++) {
+ start_env->Add(null_value);
+ }
+ graph_entry_->set_start_env(start_env);
+
+ BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
+ ASSERT(normal_entry != NULL); // Graph entry is empty.
srdjan 2012/06/18 18:04:38 Maybe change comment to: "Must have entry" or simi
Florian Schneider 2012/06/19 11:26:40 Done.
+ ZoneGrowableArray<Value*>* env = new ZoneGrowableArray<Value*>(var_count);
+ env->AddArray(*start_env);
+ RenameRecursive(normal_entry, env, var_count);
+}
+
+
+static intptr_t WhichPred(BlockEntryInstr* predecessor,
+ JoinEntryInstr* join_block) {
+ for (intptr_t i = 0; i < join_block->PredecessorCount(); ++i) {
+ if (join_block->PredecessorAt(i) == predecessor) return i;
+ }
+ UNREACHABLE();
+ return -1;
+}
+
+
+void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry,
+ ZoneGrowableArray<Value*>* env,
+ intptr_t var_count) {
+ // Iterate over instructions.
+ // 1. Handle phis first.
+ if (block_entry->IsJoinEntry()) {
+ JoinEntryInstr* join = block_entry->AsJoinEntry();
+ if (join->phis() != NULL) {
srdjan 2012/06/18 18:04:38 ASSERT(join->phis() != NULL) ?
Florian Schneider 2012/06/19 11:26:40 Right now I lazily allocate the phis() array when
+ for (intptr_t i = 0; i < join->phis()->length(); ++i) {
+ PhiInstr* phi = (*join->phis())[i];
+ if (phi != NULL) {
+ (*env)[i] = new UseVal(phi);
+ phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp.
+ }
+ }
+ }
+ }
+
+ // 2. Handle normal instructions.
+ Instruction* current = block_entry->StraightLineSuccessor();
+ Instruction* prev = block_entry;
+ while (current != NULL && !current->IsBlockEntry()) {
srdjan 2012/06/18 18:04:38 add parenthesis
Florian Schneider 2012/06/19 11:26:40 Done.
+ // 2a. Handle LoadLocal and StoreLocal.
+ LoadLocalComp* load = NULL;
+ if (current->IsDo() &&
+ current->AsDo()->computation()->IsLoadLocal()) {
+ load = current->AsDo()->computation()->AsLoadLocal();
srdjan 2012/06/18 18:04:38 A LoadLocal in a Do has no side effect and can be
Florian Schneider 2012/06/19 11:26:40 Yes. I remove it from the graph below, but better
+ } else if (current->IsBind() &&
+ current->AsBind()->computation()->IsLoadLocal()) {
+ load = current->AsBind()->computation()->AsLoadLocal();
+ }
+ StoreLocalComp* store = NULL;
+ if (current->IsDo() &&
+ current->AsDo()->computation()->IsStoreLocal()) {
+ store = current->AsDo()->computation()->AsStoreLocal();
+ } else if (current->IsBind() &&
+ current->AsBind()->computation()->IsStoreLocal()) {
+ store = current->AsBind()->computation()->AsStoreLocal();
+ }
+
+ if (load != NULL || store != NULL) {
srdjan 2012/06/18 18:04:38 Add parenthesis
Florian Schneider 2012/06/19 11:26:40 Done.
+ // Remove instruction with LoadLocal or StoreLocal.
+ prev->SetSuccessor(current->StraightLineSuccessor());
+ // Update renaming environment for StoreLocal.
+ if (store != NULL) {
+ (*env)[store->local().BitIndexIn(var_count)] = store->value();
+ }
+ } else {
+ // Assign new SSA temporary.
+ if (current->IsBind()) {
+ current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++);
+ }
+ }
+
+ // 2b. Handle uses of LoadLocal / StoreLocal
+ for (intptr_t i = 0; i < current->InputCount(); ++i) {
+ // For each use of a LoadLocal/StoreLocal: Replace it with the definition
+ // from the enviroment.
srdjan 2012/06/18 18:04:38 environment
Florian Schneider 2012/06/19 11:26:40 Done.
+ Value* v = current->InputAt(i);
+ if (v->IsUse() &&
+ v->AsUse()->definition()->IsBind() &&
+ v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) {
+ Computation* comp = v->AsUse()->definition()->AsBind()->computation();
+ intptr_t index = comp->AsLoadLocal()->local().BitIndexIn(var_count);
+ Value* new_value = (*env)[index];
+ // Make a copy if it is a UseVal.
+ if (new_value->IsUse()) {
+ new_value = new UseVal(new_value->AsUse()->definition());
+ }
+ current->SetInputAt(i, new_value);
+ }
+ if (v->IsUse() &&
+ v->AsUse()->definition()->IsBind() &&
+ v->AsUse()->definition()->AsBind()->computation()->IsStoreLocal()) {
+ // For each use of a LoadLocal: Replace LoadLocal with the definition
+ // from the enviroment.
+ Computation* comp = v->AsUse()->definition()->AsBind()->computation();
+ intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(var_count);
+ Value* new_value = (*env)[index];
+ // Make a copy if it is a UseVal.
+ if (new_value->IsUse()) {
+ new_value = new UseVal(new_value->AsUse()->definition());
+ }
+ current->SetInputAt(i, new_value);
+ }
+ }
+
+ // Update previous only if no instruction was removed from the graph.
+ if (load == NULL && store == NULL) {
srdjan 2012/06/18 18:04:38 parenthesis
Florian Schneider 2012/06/19 11:26:40 Done.
+ prev = current;
+ }
+ current = current->StraightLineSuccessor();
+ }
+
+ // 3. Process dominated blocks.
+ for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
+ BlockEntryInstr* block = block_entry->dominated_blocks()[i];
+ ZoneGrowableArray<Value*>* new_env =
+ new ZoneGrowableArray<Value*>(var_count);
+ new_env->AddArray(*env);
+ RenameRecursive(block, new_env, var_count);
+ }
+
+ // 4. Process successor block. We have edge-split form, so that only blocks
+ // with one successor can have a join block as successor.
+ if (block_entry->last_instruction()->SuccessorCount() == 1 &&
srdjan 2012/06/18 18:04:38 ditto
Florian Schneider 2012/06/19 11:26:40 Done.
+ block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
+ JoinEntryInstr* successor =
+ block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
+ intptr_t pred_index = WhichPred(block_entry, successor);
+ if (successor->phis() != NULL) {
+ for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
+ PhiInstr* phi = (*successor->phis())[i];
+ if (phi != NULL) phi->SetInputAt(pred_index, (*env)[i]);
+ }
+ }
+ }
+}
+
+
void FlowGraphBuilder::Bailout(const char* reason) {
const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
const char* function_name = parsed_function_.function().ToCString();

Powered by Google App Engine
This is Rietveld 408576698