DEFINE_string(hydrogen_filter, "*", "optimization filter")
DEFINE_bool(use_range, true, "use hydrogen range analysis")
DEFINE_bool(use_gvn, true, "use hydrogen global value numbering")
+DEFINE_int(gvn_iterations, 3, "maximum number of GVN fix-point iterations")
DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing")
DEFINE_bool(use_inlining, true, "use function inlining")
DEFINE_bool(use_escape_analysis, true, "use hydrogen escape analysis")
zone());
loop_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
zone());
- }
+}
+
+
+void HGlobalValueNumberingPhase::Reset() {
+ block_side_effects_.Clear();
+ loop_side_effects_.Clear();
+ visited_on_paths_.Clear();
+ block_side_effects_.AddBlock(GVNFlagSet(), graph()->blocks()->length(),
+ zone());
+ loop_side_effects_.AddBlock(GVNFlagSet(), graph()->blocks()->length(),
+ zone());
+}
+
void HGlobalValueNumberingPhase::Analyze() {
removed_side_effects_ = false;
instr->Mnemonic(),
other->id(),
other->Mnemonic());
- instr->HandleSideEffectDominator(changes_flag, other);
+ if (instr->HandleSideEffectDominator(changes_flag, other)) {
+ removed_side_effects_ = true;
+ }
}
}
}
explicit HGlobalValueNumberingPhase(HGraph* graph);
void Run() {
- Analyze();
- // Trigger a second analysis pass to further eliminate duplicate values
- // that could only be discovered by removing side-effect-generating
- // instructions during the first pass.
- if (FLAG_smi_only_arrays && removed_side_effects_) {
+ int max_fixpoint_iteration_count = FLAG_gvn_iterations;
+ for (int i = 0; i < max_fixpoint_iteration_count; i++) {
Analyze();
- // TODO(danno): Turn this into a fixpoint iteration.
+ if (!removed_side_effects_) break;
+ Reset();
}
}
private:
+ void Reset();
void Analyze();
GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
HBasicBlock* dominator,
}
-void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
+bool HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) {
ASSERT(side_effect == kChangesMaps);
// TODO(mstarzinger): For now we specialize on HStoreNamedField, but once
// for which the map is known.
if (HasNoUses() && dominator->IsStoreNamedField()) {
HStoreNamedField* store = HStoreNamedField::cast(dominator);
- if (!store->has_transition() || store->object() != value()) return;
+ if (!store->has_transition() || store->object() != value()) return false;
HConstant* transition = HConstant::cast(store->transition());
if (map_set_.Contains(transition->GetUnique())) {
DeleteAndReplaceWith(NULL);
- return;
+ return true;
}
}
+ return false;
}
}
-void HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
+bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) {
ASSERT(side_effect == kChangesNewSpacePromotion);
Zone* zone = block()->zone();
- if (!FLAG_use_allocation_folding) return;
+ if (!FLAG_use_allocation_folding) return false;
// Try to fold allocations together with their dominating allocations.
if (!dominator->IsAllocate()) {
PrintF("#%d (%s) cannot fold into #%d (%s)\n",
id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
}
- return;
+ return false;
}
HAllocate* dominator_allocate = HAllocate::cast(dominator);
PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n",
id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
}
- return;
+ return false;
}
dominator_allocate = GetFoldableDominator(dominator_allocate);
if (dominator_allocate == NULL) {
- return;
+ return false;
}
ASSERT((IsNewSpaceAllocation() &&
id(), Mnemonic(), dominator_allocate->id(),
dominator_allocate->Mnemonic(), new_dominator_size);
}
- return;
+ return false;
}
HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore(
id(), Mnemonic(), dominator_allocate->id(),
dominator_allocate->Mnemonic());
}
+ return true;
}
// This function must be overridden for instructions which have the
// kTrackSideEffectDominators flag set, to track instructions that are
// dominating side effects.
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ // It returns true if it removed an instruction which had side effects.
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) {
UNREACHABLE();
+ return false;
}
// Check if this instruction has some reason that prevents elimination.
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
}
return Representation::Tagged();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE {
ASSERT(side_effect == kChangesNewSpacePromotion);
new_space_dominator_ = dominator;
+ return false;
}
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE {
ASSERT(side_effect == kChangesNewSpacePromotion);
new_space_dominator_ = dominator;
+ return false;
}
HValue* new_space_dominator() const { return new_space_dominator_; }