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

Unified Diff: runtime/vm/flow_graph.cc

Issue 10879036: Compute the def-use list on-demand by walking the dominator tree. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Unneeded include. Created 8 years, 4 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
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_allocator.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph.cc
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index a8b3076e0d08dce663998aa5dabb4d7d130bf98b..30cc3563a6c709ef08ec105414e9e53f916f9c2a 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -64,6 +64,146 @@ void FlowGraph::DiscoverBlocks() {
}
+#ifdef DEBUG
+// Helper class to check consistency of the use list construction. Clears all
+// use-list data in one pass which is then used for assertions when building the
+// use lists.
+class DefUseCleanup : public FlowGraphVisitor {
Kevin Millikin (Google) 2012/08/24 08:53:05 While it's a noun, this isn't a very tangible name
+ public:
+ explicit DefUseCleanup(FlowGraph* flow_graph)
+ : FlowGraphVisitor(flow_graph->preorder()) { }
+ void CleanupInstruction(Instruction* instr) {
Kevin Millikin (Google) 2012/08/24 08:53:05 I like "ResetInstruction" slightly better. Cleanu
+ JoinEntryInstr* join = instr->AsJoinEntry();
+ if (join != NULL && join->phis() != NULL) {
+ for (intptr_t i = 0; i < join->phis()->length(); ++i) {
+ PhiInstr* phi = (*join->phis())[i];
+ if (phi != NULL) CleanupInstruction(phi);
+ }
+ }
+ Definition* defn = instr->AsDefinition();
+ if (defn != NULL) {
+ defn->set_input_use_list(NULL);
+ defn->set_env_use_list(NULL);
+ }
+ for (intptr_t i = 0; i < instr->InputCount(); ++i) {
+ UseVal* use = instr->InputAt(i)->AsUse();
+ if (use == NULL) continue;
+ use->set_instruction(NULL);
Kevin Millikin (Google) 2012/08/24 08:53:05 Here you could just use a virtual Reset function o
+ use->set_use_index(-1);
+ use->set_next_use(NULL);
+ }
+ if (instr->env() != NULL) {
+ for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
+ UseVal* use = instr->env()->values()[i]->AsUse();
+ if (use == NULL) continue;
+ use->set_instruction(NULL);
+ use->set_use_index(-1);
+ use->set_next_use(NULL);
+ }
+ }
+ }
+#define DEFINE_VISIT(type) \
+ virtual void Visit##type(type##Instr* instr) { CleanupInstruction(instr); }
+ FOR_EACH_INSTRUCTION(DEFINE_VISIT)
+#undef DEFINE_VISIT
+};
+#endif // DEBUG
+
+
+static void ClearUseLists(Definition* defn) {
+ ASSERT(defn != NULL);
+ ASSERT(defn->input_use_list() == NULL);
+ ASSERT(defn->env_use_list() == NULL);
+ defn->set_input_use_list(NULL);
+ defn->set_env_use_list(NULL);
+}
+
+
+static void RecordInputUses(Instruction* instr) {
+ ASSERT(instr != NULL);
+ for (intptr_t i = 0; i < instr->InputCount(); ++i) {
+ UseVal* use = instr->InputAt(i)->AsUse();
+ if (use == NULL) continue;
+ ASSERT(use->instruction() == NULL);
+ ASSERT(use->use_index() == -1);
+ ASSERT(use->next_use() == NULL);
+ use->set_instruction(instr);
+ use->set_use_index(i);
+ use->AddToInputUseList();
+ }
+}
+
+
+static void RecordEnvUses(Instruction* instr) {
+ ASSERT(instr != NULL);
+ if (instr->env() == NULL) return;
+ for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
+ UseVal* use = instr->env()->values()[i]->AsUse();
+ if (use == NULL) continue;
+ ASSERT(use->instruction() == NULL);
+ ASSERT(use->use_index() == -1);
+ ASSERT(use->next_use() == NULL);
+ use->set_instruction(instr);
+ use->set_use_index(i);
+ use->AddToEnvUseList();
+ }
+}
+
+
+static void ComputeUseListsRecursive(BlockEntryInstr* block) {
+ // Clear phi definitions.
+ JoinEntryInstr* join = block->AsJoinEntry();
+ if (join != NULL && join->phis() != NULL) {
+ for (intptr_t i = 0; i < join->phis()->length(); ++i) {
+ PhiInstr* phi = (*join->phis())[i];
+ if (phi != NULL) ClearUseLists(phi);
+ }
+ }
+ // Compute uses on normal instructions.
+ for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
+ Instruction* instr = it.Current();
+ if (instr->IsDefinition()) ClearUseLists(instr->AsDefinition());
+ RecordInputUses(instr);
+ RecordEnvUses(instr);
+ }
+ // Compute recursively on dominated blocks.
+ for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
+ ComputeUseListsRecursive(block->dominated_blocks()[i]);
+ }
+ // Add phi uses on successor edges.
+ if (block->last_instruction()->SuccessorCount() == 1 &&
+ block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
+ JoinEntryInstr* join =
+ block->last_instruction()->SuccessorAt(0)->AsJoinEntry();
+ intptr_t pred_index = join->IndexOfPredecessor(block);
+ ASSERT(pred_index >= 0);
+ if (join->phis() != NULL) {
+ for (intptr_t i = 0; i < join->phis()->length(); ++i) {
+ PhiInstr* phi = (*join->phis())[i];
+ if (phi == NULL) continue;
+ UseVal* use = phi->InputAt(pred_index)->AsUse();
+ if (use == NULL) continue;
+ ASSERT(use->instruction() == NULL);
+ ASSERT(use->use_index() == -1);
+ ASSERT(use->next_use() == NULL);
+ use->set_instruction(phi);
+ use->set_use_index(pred_index);
+ use->AddToInputUseList();
+ }
+ }
+ }
+}
+
+
+void FlowGraph::ComputeUseLists() {
+#ifdef DEBUG
+ DefUseCleanup cleanup(this);
+ cleanup.VisitBlocks();
+#endif // DEBUG
+ ComputeUseListsRecursive(graph_entry_);
+}
+
+
void FlowGraph::ComputeSSA() {
GrowableArray<BitVector*> dominance_frontier;
ComputeDominators(&preorder_, &parent_, &dominance_frontier);
@@ -342,11 +482,7 @@ void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
if ((as_bind != NULL) &&
(as_bind->computation()->IsLoadLocal() ||
as_bind->computation()->IsStoreLocal())) {
- // Assert exactly one use.
- ASSERT(as_bind->use_list() == v);
- ASSERT(as_bind->use_list()->next_use() == NULL);
- // Remove the use, its definition and copy the environment value.
- v->RemoveFromUseList();
+ // Remove the load/store from the graph.
as_bind->RemoveFromGraph();
// Assert we are not referencing nulls in the initial environment.
ASSERT(input_defn->ssa_temp_index() != -1);
@@ -387,9 +523,6 @@ void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
}
// Update expression stack or remove from graph.
if (bind->is_used()) {
- // Assert exactly one use.
- ASSERT(bind->use_list() != NULL);
- ASSERT(bind->use_list()->next_use() == NULL);
env->Add((*env)[index]);
// We remove load/store instructions when we find their use in 2a.
} else {
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698