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

Unified Diff: runtime/vm/flow_graph.cc

Issue 14021016: Track side-effect free paths in the graph to allow CSE and LICM for instructions that depend on som… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 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_optimizer.h » ('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 167e443edf90e0092ab3126a8634e6493807ee70..34ca6932d6aad8b34e57e39fe44fab42b493ba5d 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -28,7 +28,8 @@ FlowGraph::FlowGraph(const FlowGraphBuilder& builder,
graph_entry_(graph_entry),
preorder_(),
postorder_(),
- reverse_postorder_() {
+ reverse_postorder_(),
+ block_effects_(NULL) {
DiscoverBlocks();
}
@@ -99,6 +100,9 @@ void FlowGraph::DiscoverBlocks() {
for (intptr_t i = 0; i < block_count; ++i) {
reverse_postorder_.Add(postorder_[block_count - i - 1]);
}
+
+ // Block effects are using postorder numbering. Discard computed information.
+ block_effects_ = NULL;
}
@@ -923,4 +927,114 @@ intptr_t FlowGraph::InstructionCount() const {
return size;
}
+
+void FlowGraph::ComputeBlockEffects() {
+ block_effects_ = new BlockEffects(this);
+}
+
+
+BlockEffects::BlockEffects(FlowGraph* flow_graph)
+ : available_at_(flow_graph->postorder().length()) {
+ // We are tracking a single effect.
+ ASSERT(EffectSet::kLastEffect == 1);
+
+ const intptr_t block_count = flow_graph->postorder().length();
+
+ // Set of blocks that contain side-effects.
+ BitVector* kill = new BitVector(block_count);
+
+ // Per block available-after sets. Block A is available after the block B if
+ // and only if A is either equal to B or A is available at B and B contains no
+ // side-effects. Initially we consider all blocks available after all other
+ // blocks.
+ GrowableArray<BitVector*> available_after(block_count);
+
+ // Discover all blocks with side-effects.
+ for (BlockIterator it = flow_graph->postorder_iterator();
+ !it.Done();
+ it.Advance()) {
+ available_at_.Add(NULL);
+ available_after.Add(NULL);
+
+ BlockEntryInstr* block = it.Current();
+ for (ForwardInstructionIterator it(block);
+ !it.Done();
+ it.Advance()) {
+ if (!it.Current()->Effects().IsNone()) {
+ kill->Add(block->postorder_number());
+ break;
+ }
+ }
+ }
+
+ BitVector* temp = new BitVector(block_count);
+
+ // Recompute available-at based on predecessors' available-after until the fix
+ // point is reached.
+ bool changed;
+ do {
+ changed = false;
+
+ for (BlockIterator it = flow_graph->reverse_postorder_iterator();
+ !it.Done();
+ it.Advance()) {
+ BlockEntryInstr* block = it.Current();
+ const intptr_t block_num = block->postorder_number();
+
+ if (block->IsGraphEntry()) {
+ temp->Clear(); // Nothing is live-in into graph entry.
+ } else {
+ // Available-at is an intersection of all predecessors' available-after
+ // sets.
+ temp->SetAll();
+ for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
+ const intptr_t pred = block->PredecessorAt(i)->postorder_number();
+ if (available_after[pred] != NULL) {
+ temp->Intersect(available_after[pred]);
+ }
+ }
+ }
+
+ BitVector* current = available_at_[block_num];
+ if ((current == NULL) || !current->Equals(*temp)) {
+ // Available-at changed: update it and recompute available-after.
+ if (available_at_[block_num] == NULL) {
+ current = available_at_[block_num] = new BitVector(block_count);
+ available_after[block_num] = new BitVector(block_count);
+ // Block is always available after itself.
+ available_after[block_num]->Add(block_num);
+ }
+ current->CopyFrom(temp);
+ if (!kill->Contains(block_num)) {
+ available_after[block_num]->CopyFrom(temp);
+ // Block is always available after itself.
+ available_after[block_num]->Add(block_num);
+ }
+ changed = true;
+ }
+ }
+ } while (changed);
+}
+
+
+bool BlockEffects::IsAvailableAt(Instruction* instr,
+ BlockEntryInstr* block) const {
+ return (instr->Dependencies().IsNone()) ||
+ IsSideEffectFreePath(instr->GetBlock(), block);
+}
+
+
+bool BlockEffects::CanBeMovedTo(Instruction* instr,
+ BlockEntryInstr* block) const {
+ return (instr->Dependencies().IsNone()) ||
+ IsSideEffectFreePath(block, instr->GetBlock());
+}
+
+
+bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from,
+ BlockEntryInstr* to) const {
+ return available_at_[to->postorder_number()]->Contains(
+ from->postorder_number());
+}
+
} // namespace dart
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_optimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698