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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 11568011: Implement store to load forwarding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index ff3c49e9baad0051ee510ab8316afb8321b872f6..40a36f8a6b4428f559284525b86c24e44a417899 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -2829,10 +2829,105 @@ static bool IsInterferingStore(Instruction* instr,
}
+static Definition* GetStoredValue(Instruction* instr) {
+ if (instr->IsStoreIndexed()) {
+ return instr->AsStoreIndexed()->value()->definition();
+ }
+
+ StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField();
+ if (store_instance_field != NULL) {
+ return store_instance_field->value()->definition();
+ }
+
+ StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField();
+ if (store_vm_field != NULL) {
+ return store_vm_field->value()->definition();
+ }
+
+ UNREACHABLE(); // Should only be called for supported store instructions.
+ return NULL;
+}
+
+
+// KeyValueTrait used for numbering of loads. Allows to lookup loads
+// corresponding to stores.
+class LoadKeyValueTrait {
+ public:
+ typedef Definition* Value;
+ typedef Definition* Key;
+ typedef Definition* Pair;
+
+ static Key KeyOf(Pair kv) {
+ return kv;
+ }
+
+ static Value ValueOf(Pair kv) {
+ return kv;
+ }
+
+ static inline intptr_t Hashcode(Key key) {
+ intptr_t object = 0;
+ intptr_t location = 0;
+
+ if (key->IsLoadIndexed()) {
+ LoadIndexedInstr* load_indexed = key->AsLoadIndexed();
+ object = load_indexed->array()->definition()->ssa_temp_index();
+ location = load_indexed->index()->definition()->ssa_temp_index();
+ } else if (key->IsStoreIndexed()) {
+ StoreIndexedInstr* store_indexed = key->AsStoreIndexed();
+ object = store_indexed->array()->definition()->ssa_temp_index();
+ location = store_indexed->index()->definition()->ssa_temp_index();
+ } else if (key->IsLoadField()) {
+ LoadFieldInstr* load_field = key->AsLoadField();
+ object = load_field->value()->definition()->ssa_temp_index();
+ location = load_field->offset_in_bytes();
+ } else if (key->IsStoreInstanceField()) {
+ StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField();
+ object = store_field->instance()->definition()->ssa_temp_index();
+ location = store_field->field().Offset();
+ } else if (key->IsStoreVMField()) {
+ StoreVMFieldInstr* store_field = key->AsStoreVMField();
+ object = store_field->dest()->definition()->ssa_temp_index();
+ location = store_field->offset_in_bytes();
+ }
+
+ return object * 31 + location;
+ }
+
+ static inline bool IsKeyEqual(Pair kv, Key key) {
+ if (kv->Equals(key)) return true;
+
+ if (kv->IsLoadIndexed()) {
+ if (key->IsStoreIndexed()) {
+ LoadIndexedInstr* load_indexed = kv->AsLoadIndexed();
+ StoreIndexedInstr* store_indexed = key->AsStoreIndexed();
+ return load_indexed->array()->Equals(store_indexed->array()) &&
+ load_indexed->index()->Equals(store_indexed->index());
+ }
+ return false;
+ }
+
+ ASSERT(kv->IsLoadField());
+ LoadFieldInstr* load_field = kv->AsLoadField();
+ if (key->IsStoreVMField()) {
+ StoreVMFieldInstr* store_field = key->AsStoreVMField();
+ return load_field->value()->Equals(store_field->dest()) &&
+ (load_field->offset_in_bytes() == store_field->offset_in_bytes());
+ } else if (key->IsStoreInstanceField()) {
+ StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField();
+ return load_field->value()->Equals(store_field->instance()) &&
+ (load_field->offset_in_bytes() == store_field->field().Offset());
+ }
+
+ return false;
+ }
+};
+
+
static intptr_t NumberLoadExpressions(
FlowGraph* graph,
+ DirectChainedHashMap<LoadKeyValueTrait>* map,
GrowableArray<BitVector*>* kill_by_offs) {
- DirectChainedHashMap<PointerKeyValueTrait<Definition> > map;
intptr_t expr_id = 0;
// Loads representing different expression ids will be collected and
@@ -2850,9 +2945,9 @@ static intptr_t NumberLoadExpressions(
if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
continue;
}
- Definition* result = map.Lookup(defn);
+ Definition* result = map->Lookup(defn);
if (result == NULL) {
- map.Insert(defn);
+ map->Insert(defn);
defn->set_expr_id(expr_id++);
loads.Add(defn);
} else {
@@ -2876,7 +2971,6 @@ static intptr_t NumberLoadExpressions(
(*kill_by_offs)[offset_in_words]->Add(defn->expr_id());
}
-
return expr_id;
}
@@ -2885,8 +2979,10 @@ class LoadOptimizer : public ValueObject {
public:
LoadOptimizer(FlowGraph* graph,
intptr_t max_expr_id,
+ DirectChainedHashMap<LoadKeyValueTrait>* map,
const GrowableArray<BitVector*>& kill_by_offset)
: graph_(graph),
+ map_(map),
max_expr_id_(max_expr_id),
kill_by_offset_(kill_by_offset),
in_(graph_->preorder().length()),
@@ -2952,6 +3048,15 @@ class LoadOptimizer : public ValueObject {
// because only those values that are in the GEN set
// will ever be used.
gen->RemoveAll(kill_by_offset_[offset_in_words]);
+
+ Definition* load = map_->Lookup(instr->AsDefinition());
+ if (load != NULL) {
+ // Store has a corresponding numbered load. Try forwarding
+ // stored value to it.
+ gen->Add(load->expr_id());
+ if (out_values == NULL) out_values = CreateBlockOutValues();
+ (*out_values)[load->expr_id()] = GetStoredValue(instr);
+ }
}
ASSERT(instr->IsDefinition() &&
!IsLoadEliminationCandidate(instr->AsDefinition()));
@@ -3274,6 +3379,7 @@ class LoadOptimizer : public ValueObject {
}
FlowGraph* graph_;
+ DirectChainedHashMap<LoadKeyValueTrait>* map_;
const intptr_t max_expr_id_;
// Mapping between field offsets in words and expression ids of loads from
@@ -3311,9 +3417,11 @@ bool DominatorBasedCSE::Optimize(FlowGraph* graph) {
bool changed = false;
if (FLAG_load_cse) {
GrowableArray<BitVector*> kill_by_offs(10);
- const intptr_t max_expr_id = NumberLoadExpressions(graph, &kill_by_offs);
+ DirectChainedHashMap<LoadKeyValueTrait> map;
+ const intptr_t max_expr_id =
+ NumberLoadExpressions(graph, &map, &kill_by_offs);
if (max_expr_id > 0) {
- LoadOptimizer load_optimizer(graph, max_expr_id, kill_by_offs);
+ LoadOptimizer load_optimizer(graph, max_expr_id, &map, kill_by_offs);
load_optimizer.Optimize();
}
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698