Commit 3b8a61dc authored by mmassi@chromium.org's avatar mmassi@chromium.org

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
parent bc166169
...@@ -205,6 +205,7 @@ DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing") ...@@ -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(deoptimize_uncommon_cases, true, "deoptimize uncommon cases")
DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining") DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining")
DEFINE_bool(use_osr, true, "use on-stack replacement") DEFINE_bool(use_osr, true, "use on-stack replacement")
DEFINE_bool(idefs, false, "use informative definitions")
DEFINE_bool(array_bounds_checks_elimination, true, DEFINE_bool(array_bounds_checks_elimination, true,
"perform array bounds checks elimination") "perform array bounds checks elimination")
DEFINE_bool(array_index_dehoisting, true, DEFINE_bool(array_index_dehoisting, true,
......
...@@ -364,6 +364,54 @@ HType HType::TypeFromValue(Handle<Object> value) { ...@@ -364,6 +364,54 @@ HType HType::TypeFromValue(Handle<Object> 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 { bool HValue::IsDefinedAfter(HBasicBlock* other) const {
return block()->block_id() > other->block_id(); return block()->block_id() > other->block_id();
} }
......
...@@ -579,7 +579,10 @@ class HValue: public ZoneObject { ...@@ -579,7 +579,10 @@ class HValue: public ZoneObject {
// HGraph::ComputeSafeUint32Operations is responsible for setting this // HGraph::ComputeSafeUint32Operations is responsible for setting this
// flag. // flag.
kUint32, kUint32,
kLastFlag = kUint32 // This flag is set to true after the SetupInformativeDefinitions() pass
// has processed this instruction.
kIDefsProcessingDone,
kLastFlag = kIDefsProcessingDone
}; };
STATIC_ASSERT(kLastFlag < kBitsPerInt); STATIC_ASSERT(kLastFlag < kBitsPerInt);
...@@ -687,8 +690,8 @@ class HValue: public ZoneObject { ...@@ -687,8 +690,8 @@ class HValue: public ZoneObject {
return RedefinedOperandIndex() != kNoRedefinedOperand; return RedefinedOperandIndex() != kNoRedefinedOperand;
} }
HValue* RedefinedOperand() { HValue* RedefinedOperand() {
ASSERT(IsInformativeDefinition()); return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex())
return OperandAt(RedefinedOperandIndex()); : NULL;
} }
// This method must always return the original HValue SSA definition // This method must always return the original HValue SSA definition
...@@ -698,6 +701,15 @@ class HValue: public ZoneObject { ...@@ -698,6 +701,15 @@ class HValue: public ZoneObject {
: this; : this;
} }
virtual void AddInformativeDefinitions() {}
void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() {
UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>();
}
void UpdateRedefinedUses() {
UpdateRedefinedUsesInner<Dominates>();
}
bool IsDefinedAfter(HBasicBlock* other) const; bool IsDefinedAfter(HBasicBlock* other) const;
// Operands. // Operands.
...@@ -856,6 +868,36 @@ class HValue: public ZoneObject { ...@@ -856,6 +868,36 @@ class HValue: public ZoneObject {
representation_ = r; 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<DominanceTest TestDominance>
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() { static GVNFlagSet AllDependsOnFlagSet() {
GVNFlagSet result; GVNFlagSet result;
// Create changes mask. // Create changes mask.
......
...@@ -3587,7 +3587,10 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { ...@@ -3587,7 +3587,10 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
HStackCheckEliminator sce(this); HStackCheckEliminator sce(this);
sce.Process(); 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_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
if (FLAG_dead_code_elimination) DeadCodeElimination(); if (FLAG_dead_code_elimination) DeadCodeElimination();
...@@ -3597,6 +3600,39 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { ...@@ -3597,6 +3600,39 @@ bool HGraph::Optimize(SmartArrayPointer<char>* 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 // We try to "factor up" HBoundsCheck instructions towards the root of the
// dominator tree. // dominator tree.
// For now we handle checks where the index is like "exp + int32value". // For now we handle checks where the index is like "exp + int32value".
......
...@@ -269,7 +269,7 @@ class HGraph: public ZoneObject { ...@@ -269,7 +269,7 @@ class HGraph: public ZoneObject {
void Canonicalize(); void Canonicalize();
void OrderBlocks(); void OrderBlocks();
void AssignDominators(); void AssignDominators();
void ReplaceCheckedValues(); void SetupInformativeDefinitions();
void EliminateRedundantBoundsChecks(); void EliminateRedundantBoundsChecks();
void DehoistSimpleArrayIndexComputations(); void DehoistSimpleArrayIndexComputations();
void DeadCodeElimination(); void DeadCodeElimination();
...@@ -398,6 +398,8 @@ class HGraph: public ZoneObject { ...@@ -398,6 +398,8 @@ class HGraph: public ZoneObject {
void InferTypes(ZoneList<HValue*>* worklist); void InferTypes(ZoneList<HValue*>* worklist);
void InitializeInferredTypes(int from_inclusive, int to_inclusive); void InitializeInferredTypes(int from_inclusive, int to_inclusive);
void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor); void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
void SetupInformativeDefinitionsInBlock(HBasicBlock* block);
void SetupInformativeDefinitionsRecursively(HBasicBlock* block);
void EliminateRedundantBoundsChecks(HBasicBlock* bb, BoundsCheckTable* table); void EliminateRedundantBoundsChecks(HBasicBlock* bb, BoundsCheckTable* table);
Isolate* isolate_; Isolate* isolate_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment