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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10914314: Simple redundant load elimination. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 12420)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -21,6 +21,7 @@
DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
DECLARE_FLAG(bool, trace_type_check_elimination);
DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
+DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
void FlowGraphOptimizer::ApplyICData() {
VisitBlocks();
@@ -1546,13 +1547,209 @@
}
-void DominatorBasedCSE::Optimize(BlockEntryInstr* graph_entry) {
- ASSERT(graph_entry->IsGraphEntry());
+static intptr_t NumberLoadExpressions(FlowGraph* graph) {
DirectChainedHashMap<Definition*> map;
- OptimizeRecursive(graph_entry, &map);
+ intptr_t expr_id = 0;
+ for (BlockIterator it = graph->reverse_postorder_iterator();
+ !it.Done();
+ it.Advance()) {
+ BlockEntryInstr* block = it.Current();
+ for (ForwardInstructionIterator instr_it(block);
+ !instr_it.Done();
+ instr_it.Advance()) {
+ Definition* defn = instr_it.Current()->AsDefinition();
+ if ((defn == NULL) ||
+ !defn->IsLoadField() ||
+ !defn->AffectedBySideEffect()) {
+ // TODO(fschneider): Extend to other load instructions.
+ continue;
+ }
+ Definition* result = map.Lookup(defn);
+ if (result == NULL) {
+ map.Insert(defn);
+ defn->set_expr_id(expr_id++);
+ } else {
+ defn->set_expr_id(result->expr_id());
+ }
+ }
+ }
+ return expr_id;
}
+static void ComputeAvailableLoads(
+ FlowGraph* graph,
+ intptr_t max_expr_id,
+ const GrowableArray<BitVector*>& avail_in) {
+ // Initialize gen-, kill-, out-sets.
+ intptr_t num_blocks = graph->preorder().length();
+ GrowableArray<BitVector*> avail_out(num_blocks);
+ GrowableArray<BitVector*> avail_gen(num_blocks);
+ GrowableArray<BitVector*> avail_kill(num_blocks);
+ for (intptr_t i = 0; i < num_blocks; i++) {
+ avail_out.Add(new BitVector(max_expr_id));
+ avail_gen.Add(new BitVector(max_expr_id));
+ avail_kill.Add(new BitVector(max_expr_id));
+ }
+
+ for (BlockIterator block_it = graph->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ BlockEntryInstr* block = block_it.Current();
+ intptr_t preorder_number = block->preorder_number();
+ for (BackwardInstructionIterator instr_it(block);
+ !instr_it.Done();
+ instr_it.Advance()) {
+ Instruction* instr = instr_it.Current();
+ if (instr->HasSideEffect()) {
+ avail_kill[preorder_number]->SetAll();
+ break;
+ }
+ Definition* defn = instr_it.Current()->AsDefinition();
+ if ((defn == NULL) ||
+ !defn->IsLoadField() ||
+ !defn->AffectedBySideEffect()) {
+ // TODO(fschneider): Extend to other load instructions.
+ continue;
+ }
+ avail_gen[preorder_number]->Add(defn->expr_id());
+ }
+ avail_out[preorder_number]->CopyFrom(avail_gen[preorder_number]);
+ }
+
+ BitVector* temp = new BitVector(avail_in[0]->length());
+
+ bool changed = true;
+ while (changed) {
+ changed = false;
+
+ for (BlockIterator block_it = graph->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ BlockEntryInstr* block = block_it.Current();
+ BitVector* block_in = avail_in[block->preorder_number()];
+ BitVector* block_out = avail_out[block->preorder_number()];
+ BitVector* block_kill = avail_kill[block->preorder_number()];
+ BitVector* block_gen = avail_gen[block->preorder_number()];
+
+ if (FLAG_trace_optimization) {
+ OS::Print("B%"Pd"", block->block_id());
+ block_in->Print();
+ block_out->Print();
+ OS::Print("\n");
+ }
+
+ // Compute block_in as the intersection of all out(p) where p
+ // is a predecessor of the current block.
+ if (block->IsGraphEntry()) {
+ temp->Clear();
+ } else {
+ temp->SetAll();
+ ASSERT(block->PredecessorCount() > 0);
+ for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
+ BlockEntryInstr* pred = block->PredecessorAt(i);
+ BitVector* pred_out = avail_out[pred->preorder_number()];
+ temp->Intersect(*pred_out);
+ }
+ }
+ if (!temp->Equals(*block_in)) {
+ block_in->CopyFrom(temp);
+ if (block_out->KillAndAdd(block_kill, block_gen)) changed = true;
+ }
+ }
+ }
+}
+
+
+static void OptimizeLoads(
+ BlockEntryInstr* block,
+ GrowableArray<Definition*>* definitions,
+ const GrowableArray<BitVector*>& avail_in) {
+ // TODO(fschneider): Factor out code shared with the existing CSE pass.
+
+ // Delete loads that are killed (not available) at the entry.
+ intptr_t pre_num = block->preorder_number();
+ ASSERT(avail_in[pre_num]->length() == definitions->length());
+ for (intptr_t i = 0; i < avail_in[pre_num]->length(); i++) {
+ if (!avail_in[pre_num]->Contains(i)) {
+ (*definitions)[i] = NULL;
+ }
+ }
+
+ for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
+ Instruction* instr = it.Current();
+ if (instr->HasSideEffect()) {
+ // Handle local side effects by clearing current definitions.
+ for (intptr_t i = 0; i < definitions->length(); i++) {
+ (*definitions)[i] = NULL;
+ }
+ continue;
+ }
+ Definition* defn = instr->AsDefinition();
+ if ((defn == NULL) ||
+ !defn->IsLoadField() ||
+ !defn->AffectedBySideEffect()) {
+ // Immutable loads are handled in normal CSE.
+ // TODO(fschneider): Extend to other load instructions.
+ continue;
+ }
+ Definition* result = (*definitions)[defn->expr_id()];
+ if (result == NULL) {
+ (*definitions)[defn->expr_id()] = defn;
+ continue;
+ }
+
+ // Replace current with lookup result.
+ defn->ReplaceUsesWith(result);
+ it.RemoveCurrentFromGraph();
+ if (FLAG_trace_optimization) {
+ OS::Print("Replacing load v%"Pd" with v%"Pd"\n",
+ defn->ssa_temp_index(),
+ result->ssa_temp_index());
+ }
+ }
+
+ // Process children in the dominator tree recursively.
+ intptr_t num_children = block->dominated_blocks().length();
+ for (intptr_t i = 0; i < num_children; ++i) {
+ BlockEntryInstr* child = block->dominated_blocks()[i];
+ if (i < num_children - 1) {
+ GrowableArray<Definition*> child_defs(definitions->length());
+ child_defs.AddArray(*definitions);
+ OptimizeLoads(child, &child_defs, avail_in);
+ } else {
+ OptimizeLoads(child, definitions, avail_in);
+ }
+ }
+}
+
+
+void DominatorBasedCSE::Optimize(FlowGraph* graph) {
+ if (FLAG_load_cse) {
+ intptr_t max_expr_id = NumberLoadExpressions(graph);
+ if (max_expr_id > 0) {
+ intptr_t num_blocks = graph->preorder().length();
+ GrowableArray<BitVector*> avail_in(num_blocks);
+ for (intptr_t i = 0; i < num_blocks; i++) {
+ avail_in.Add(new BitVector(max_expr_id));
+ }
+
+ ComputeAvailableLoads(graph, max_expr_id, avail_in);
+
+ GrowableArray<Definition*> definitions(max_expr_id);
+ for (intptr_t j = 0; j < max_expr_id ; j++) {
+ definitions.Add(NULL);
+ }
+
+ OptimizeLoads(graph->graph_entry(), &definitions, avail_in);
+ }
+ }
+
+ DirectChainedHashMap<Definition*> map;
+ OptimizeRecursive(graph->graph_entry(), &map);
+}
+
+
void DominatorBasedCSE::OptimizeRecursive(
BlockEntryInstr* block,
DirectChainedHashMap<Definition*>* map) {
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698