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

Unified Diff: src/hydrogen-check-elimination.cc

Issue 141653009: Check elimination improvement: propagation of state through phis is supported, CheckMap narrowing i… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review notes applied Created 6 years, 11 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 | « src/hydrogen.cc ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen-check-elimination.cc
diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
index cd002a1d5c80a5d9a76ee4eded2f889461958dc6..2d240b22690cb2b2aa46eb2f6a9d2aeeda8aa860 100644
--- a/src/hydrogen-check-elimination.cc
+++ b/src/hydrogen-check-elimination.cc
@@ -48,12 +48,12 @@ typedef UniqueSet<Map>* MapSet;
struct HCheckTableEntry {
HValue* object_; // The object being approximated. NULL => invalid entry.
- HValue* check_; // The last check instruction.
- MapSet maps_; // The set of known maps for the object.
+ HInstruction* check_; // The last check instruction.
+ MapSet maps_; // The set of known maps for the object.
};
-// The main datastructure used during check elimination, which stores a
+// The main data structure used during check elimination, which stores a
// set of known maps for each object.
class HCheckTable : public ZoneObject {
public:
@@ -130,6 +130,8 @@ class HCheckTable : public ZoneObject {
copy->cursor_ = cursor_;
copy->size_ = size_;
+ copy->InheritPhiOperands(succ, this, from_block, COPY, zone);
+
// Branch-sensitive analysis for certain comparisons may add more facts
// to the state for the successor on the true branch.
bool learned = false;
@@ -192,13 +194,19 @@ class HCheckTable : public ZoneObject {
size_ = 0;
cursor_ = 0;
} else {
+ InheritPhiOperands(succ, that, that_block, MERGE, zone);
titzer 2014/02/04 13:12:26 Why don't you process the phis after first merging
Igor Sheludko 2014/02/05 11:28:01 Good idea!
+
bool compact = false;
for (int i = 0; i < size_; i++) {
HCheckTableEntry* this_entry = &entries_[i];
titzer 2014/02/04 13:12:26 Using the above suggestion, you can simply retain
Igor Sheludko 2014/02/05 11:28:01 Done.
HCheckTableEntry* that_entry = that->Find(this_entry->object_);
+ // Keep those phis in the table that dominate succ block.
if (that_entry == NULL) {
- this_entry->object_ = NULL;
- compact = true;
+ if (!this_entry->object_->IsPhi() ||
+ !this_entry->object_->block()->EqualToOrDominates(succ)) {
+ this_entry->object_ = NULL;
+ compact = true;
+ }
} else {
this_entry->maps_ =
this_entry->maps_->Union(that_entry->maps_, phase_->zone());
@@ -219,6 +227,43 @@ class HCheckTable : public ZoneObject {
return this;
}
+ enum InheritPhiOperandsMode { COPY, MERGE };
+ void InheritPhiOperands(HBasicBlock* succ, HCheckTable* that,
+ HBasicBlock* that_block, InheritPhiOperandsMode mode,
+ Zone* zone) {
+ if (succ->predecessors()->length() == 1) return;
titzer 2014/02/04 13:12:26 I think you want to check succ->phis()->length() =
Igor Sheludko 2014/02/05 11:28:01 Done.
+
+ int pred_index = succ->PredecessorIndexOf(that_block);
+
+ for (int i = 0; i < that->size_; i++) {
+ HCheckTableEntry* that_entry = &that->entries_[i];
+ if (that_entry->object_ != NULL) {
+ HPhi* phi = NULL;
+ for (int phi_index = 0;
+ phi_index < succ->phis()->length();
+ ++phi_index) {
+ HPhi* tmp_phi = succ->phis()->at(phi_index);
+ if (tmp_phi->OperandAt(pred_index) == that_entry->object_) {
+ phi = tmp_phi;
+ break;
+ }
+ }
+
+ if (phi != NULL) {
+ // Found a |phi| with operand equal to |that_entry->object_|.
+ HCheckTableEntry* phi_entry = (mode == MERGE) ? Find(phi) : NULL;
+ if (phi_entry == NULL) {
+ // Create an entry for a phi in the table.
+ Insert(phi, NULL, that_entry->maps_);
+ } else {
+ phi_entry->maps_ =
+ phi_entry->maps_->Union(that_entry->maps_, phase_->zone());
+ }
+ }
+ }
+ }
+ }
+
void ReduceCheckMaps(HCheckMaps* instr) {
HValue* object = instr->value()->ActualValue();
HCheckTableEntry* entry = Find(object);
@@ -244,14 +289,42 @@ class HCheckTable : public ZoneObject {
}
return;
}
- i = i->Intersect(a, phase_->zone());
- if (i->size() == 0) {
+ MapSet intersection = i->Intersect(a, phase_->zone());
+ if (intersection->size() == 0) {
// Intersection is empty; probably megamorphic, which is likely to
// deopt anyway, so just leave things as they are.
INC_STAT(empty_);
} else {
- // TODO(titzer): replace the first check with a more strict check
- INC_STAT(narrowed_);
+ // Update set of maps in the entry.
+ entry->maps_ = intersection;
+ if (intersection->size() != i->size()) {
+ // Narrow set of maps in the second check maps instruction.
+ HGraph* graph = instr->block()->graph();
+ HCheckMaps* new_check_maps =
+ HCheckMaps::New(graph->zone(), NULL, instr->value(),
+ intersection, instr->typecheck());
+ if (entry->check_ != NULL &&
+ entry->check_->block() == instr->block()) {
+ // There is a check in the same block so replace it with a more
+ // strict check and eliminate the second check entirely.
+ new_check_maps->InsertBefore(entry->check_);
+ entry->check_->DeleteAndReplaceWith(new_check_maps);
+ TRACE(("Check #%d narrowed to #%d\n",
+ entry->check_->id(), new_check_maps->id()));
+
+ } else {
+ new_check_maps->InsertBefore(instr);
+ }
+ TRACE(("CheckMaps #%d for #%d narrowed to #%d:\n",
+ instr->id(), instr->value()->id(), new_check_maps->id()));
+ instr->DeleteAndReplaceWith(new_check_maps);
+ entry->check_ = new_check_maps;
+
+ if (FLAG_trace_check_elimination) {
+ Print();
+ }
+ INC_STAT(narrowed_);
+ }
}
} else {
// No entry; insert a new one.
« no previous file with comments | « src/hydrogen.cc ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698