From 3b8a61dcf3b4162bb2cbb92b7fc7a1918f73ac39 Mon Sep 17 00:00:00 2001 From: "mmassi@chromium.org" Date: Fri, 1 Feb 2013 10:16:16 +0000 Subject: [PATCH] Base iDef update code. Review URL: https://codereview.chromium.org/12079042 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13575 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/flag-definitions.h | 1 + src/hydrogen-instructions.cc | 48 ++++++++++++++++++++++++++++++++++++ src/hydrogen-instructions.h | 48 +++++++++++++++++++++++++++++++++--- src/hydrogen.cc | 38 +++++++++++++++++++++++++++- src/hydrogen.h | 4 ++- 5 files changed, 134 insertions(+), 5 deletions(-) diff --git a/src/flag-definitions.h b/src/flag-definitions.h index ca9bf1de52..4c74f69006 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -205,6 +205,7 @@ DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true, "deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining") DEFINE_bool(use_osr, true, "use on-stack replacement") +DEFINE_bool(idefs, false, "use informative definitions") DEFINE_bool(array_bounds_checks_elimination, true, "perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, true, diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 4f8af2b0c0..4163b50045 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -364,6 +364,54 @@ HType HType::TypeFromValue(Handle value) { } +bool HValue::Dominates(HValue* dominator, HValue* dominated) { + if (dominator->block() != dominated->block()) { + // If they are in different blocks we can use the dominance relation + // between the blocks. + return dominator->block()->Dominates(dominated->block()); + } else { + // Otherwise we must see which instruction comes first, considering + // that phis always precede regular instructions. + if (dominator->IsInstruction()) { + if (dominated->IsInstruction()) { + for (HInstruction* next = HInstruction::cast(dominator)->next(); + next != NULL; + next = next->next()) { + if (next == dominated) return true; + } + return false; + } else if (dominated->IsPhi()) { + return false; + } else { + UNREACHABLE(); + } + } else if (dominator->IsPhi()) { + if (dominated->IsInstruction()) { + return true; + } else { + // We cannot compare which phi comes first. + UNREACHABLE(); + } + } else { + UNREACHABLE(); + } + return false; + } +} + + +bool HValue::TestDominanceUsingProcessedFlag(HValue* dominator, + HValue* dominated) { + if (dominator->block() != dominated->block()) { + return dominator->block()->Dominates(dominated->block()); + } else { + // If both arguments are in the same block we check if "dominator" has + // already been processed or if it is a phi: if yes it dominates the other. + return dominator->CheckFlag(kIDefsProcessingDone) || dominator->IsPhi(); + } +} + + bool HValue::IsDefinedAfter(HBasicBlock* other) const { return block()->block_id() > other->block_id(); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 2d57537596..3aa15e375a 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -579,7 +579,10 @@ class HValue: public ZoneObject { // HGraph::ComputeSafeUint32Operations is responsible for setting this // flag. kUint32, - kLastFlag = kUint32 + // This flag is set to true after the SetupInformativeDefinitions() pass + // has processed this instruction. + kIDefsProcessingDone, + kLastFlag = kIDefsProcessingDone }; STATIC_ASSERT(kLastFlag < kBitsPerInt); @@ -687,8 +690,8 @@ class HValue: public ZoneObject { return RedefinedOperandIndex() != kNoRedefinedOperand; } HValue* RedefinedOperand() { - ASSERT(IsInformativeDefinition()); - return OperandAt(RedefinedOperandIndex()); + return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex()) + : NULL; } // This method must always return the original HValue SSA definition @@ -698,6 +701,15 @@ class HValue: public ZoneObject { : this; } + virtual void AddInformativeDefinitions() {} + + void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() { + UpdateRedefinedUsesInner(); + } + void UpdateRedefinedUses() { + UpdateRedefinedUsesInner(); + } + bool IsDefinedAfter(HBasicBlock* other) const; // Operands. @@ -856,6 +868,36 @@ class HValue: public ZoneObject { representation_ = r; } + // Signature of a function testing if a HValue properly dominates another. + typedef bool (*DominanceTest)(HValue*, HValue*); + + // Simple implementation of DominanceTest implemented walking the chain + // of Hinstructions (used in UpdateRedefinedUsesInner). + static bool Dominates(HValue* dominator, HValue* dominated); + + // A fast implementation of DominanceTest that works only for the + // "current" instruction in the SetupInformativeDefinitions() phase. + // During that phase we use a flag to mark processed instructions, and by + // checking the flag we can quickly test if an instruction comes before or + // after the "current" one. + static bool TestDominanceUsingProcessedFlag(HValue* dominator, + HValue* dominated); + + // If we are redefining an operand, update all its dominated uses (the + // function that checks if a use is dominated is the template argument). + template + void UpdateRedefinedUsesInner() { + HValue* input = RedefinedOperand(); + if (input != NULL) { + for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) { + HValue* use = uses.value(); + if (TestDominance(this, use)) { + use->SetOperandAt(uses.index(), this); + } + } + } + } + static GVNFlagSet AllDependsOnFlagSet() { GVNFlagSet result; // Create changes mask. diff --git a/src/hydrogen.cc b/src/hydrogen.cc index e567e1cdb1..f62a2835fc 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -3587,7 +3587,10 @@ bool HGraph::Optimize(SmartArrayPointer* bailout_reason) { HStackCheckEliminator sce(this); sce.Process(); - if (FLAG_array_bounds_checks_elimination) EliminateRedundantBoundsChecks(); + if (FLAG_idefs) SetupInformativeDefinitions(); + if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { + EliminateRedundantBoundsChecks(); + } if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); if (FLAG_dead_code_elimination) DeadCodeElimination(); @@ -3597,6 +3600,39 @@ bool HGraph::Optimize(SmartArrayPointer* bailout_reason) { } +void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { + for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { + HPhi* phi = block->phis()->at(phi_index); + phi->AddInformativeDefinitions(); + // We do not support phis that "redefine just one operand". + ASSERT(!phi->IsInformativeDefinition()); + } + + for (HInstruction* i = block->first(); i != NULL; i = i->next()) { + i->AddInformativeDefinitions(); + i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions(); + } +} + + +// This method is recursive, so if its stack frame is large it could +// cause a stack overflow. +// To keep the individual stack frames small we do the actual work inside +// SetupInformativeDefinitionsInBlock(); +void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) { + SetupInformativeDefinitionsInBlock(block); + for (int i = 0; i < block->dominated_blocks()->length(); ++i) { + SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i)); + } +} + + +void HGraph::SetupInformativeDefinitions() { + HPhase phase("H_Setup informative definitions", this); + SetupInformativeDefinitionsRecursively(entry_block()); +} + + // We try to "factor up" HBoundsCheck instructions towards the root of the // dominator tree. // For now we handle checks where the index is like "exp + int32value". diff --git a/src/hydrogen.h b/src/hydrogen.h index 7417fdd2de..2593325cc0 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -269,7 +269,7 @@ class HGraph: public ZoneObject { void Canonicalize(); void OrderBlocks(); void AssignDominators(); - void ReplaceCheckedValues(); + void SetupInformativeDefinitions(); void EliminateRedundantBoundsChecks(); void DehoistSimpleArrayIndexComputations(); void DeadCodeElimination(); @@ -398,6 +398,8 @@ class HGraph: public ZoneObject { void InferTypes(ZoneList* worklist); void InitializeInferredTypes(int from_inclusive, int to_inclusive); void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor); + void SetupInformativeDefinitionsInBlock(HBasicBlock* block); + void SetupInformativeDefinitionsRecursively(HBasicBlock* block); void EliminateRedundantBoundsChecks(HBasicBlock* bb, BoundsCheckTable* table); Isolate* isolate_;