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")
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,
......
......@@ -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 {
return block()->block_id() > other->block_id();
}
......
......@@ -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<TestDominanceUsingProcessedFlag>();
}
void UpdateRedefinedUses() {
UpdateRedefinedUsesInner<Dominates>();
}
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<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() {
GVNFlagSet result;
// Create changes mask.
......
......@@ -3587,7 +3587,10 @@ bool HGraph::Optimize(SmartArrayPointer<char>* 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<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
// dominator tree.
// For now we handle checks where the index is like "exp + int32value".
......
......@@ -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<HValue*>* 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_;
......
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