Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 3a4d172f51db236758d2c4aaee21684b1ab2c867..57d2b56f9145fcd4c55eb1b995f221d98ad88696 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -1346,6 +1346,7 @@ class HGlobalValueNumberer BASE_EMBEDDED { |
explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) |
: graph_(graph), |
info_(info), |
+ removed_side_effects_(false), |
block_side_effects_(graph->blocks()->length()), |
loop_side_effects_(graph->blocks()->length()), |
visited_on_paths_(graph->zone(), graph->blocks()->length()) { |
@@ -1357,7 +1358,8 @@ class HGlobalValueNumberer BASE_EMBEDDED { |
ASSERT(!info_->isolate()->heap()->allow_allocation(true)); |
} |
- void Analyze(); |
+ // Returns true if values with side effects are removed. |
+ bool Analyze(); |
private: |
int CollectSideEffectsOnPathsToDominatedBlock(HBasicBlock* dominator, |
@@ -1377,6 +1379,7 @@ class HGlobalValueNumberer BASE_EMBEDDED { |
HGraph* graph_; |
CompilationInfo* info_; |
+ bool removed_side_effects_; |
// A map of block IDs to their side effects. |
ZoneList<int> block_side_effects_; |
@@ -1390,13 +1393,14 @@ class HGlobalValueNumberer BASE_EMBEDDED { |
}; |
-void HGlobalValueNumberer::Analyze() { |
+bool HGlobalValueNumberer::Analyze() { |
ComputeBlockSideEffects(); |
if (FLAG_loop_invariant_code_motion) { |
LoopInvariantCodeMotion(); |
} |
HValueMap* map = new(zone()) HValueMap(); |
AnalyzeBlock(graph_->entry_block(), map); |
+ return removed_side_effects_; |
} |
@@ -1530,11 +1534,12 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { |
HInstruction* next = instr->next(); |
int flags = instr->ChangesFlags(); |
if (flags != 0) { |
- ASSERT(!instr->CheckFlag(HValue::kUseGVN)); |
// Clear all instructions in the map that are affected by side effects. |
map->Kill(flags); |
TraceGVN("Instruction %d kills\n", instr->id()); |
- } else if (instr->CheckFlag(HValue::kUseGVN)) { |
+ } |
+ if (instr->CheckFlag(HValue::kUseGVN)) { |
+ ASSERT(!instr->HasObservableSideEffects()); |
HValue* other = map->Lookup(instr); |
if (other != NULL) { |
ASSERT(instr->Equals(other) && other->Equals(instr)); |
@@ -1543,6 +1548,7 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { |
instr->Mnemonic(), |
other->id(), |
other->Mnemonic()); |
+ if (instr->HasSideEffects()) removed_side_effects_ = true; |
instr->DeleteAndReplaceWith(other); |
} else { |
map->Add(instr); |
@@ -2108,12 +2114,12 @@ void TestContext::ReturnValue(HValue* value) { |
void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
ASSERT(!instr->IsControlInstruction()); |
owner()->AddInstruction(instr); |
- if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); |
+ if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); |
} |
void EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) { |
- ASSERT(!instr->HasSideEffects()); |
+ ASSERT(!instr->HasObservableSideEffects()); |
HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
instr->SetSuccessorAt(0, empty_true); |
@@ -2131,12 +2137,12 @@ void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
} |
owner()->AddInstruction(instr); |
owner()->Push(instr); |
- if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); |
+ if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); |
} |
void ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) { |
- ASSERT(!instr->HasSideEffects()); |
+ ASSERT(!instr->HasObservableSideEffects()); |
if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
return owner()->Bailout("bad value context for arguments object value"); |
} |
@@ -2161,7 +2167,7 @@ void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
builder->AddInstruction(instr); |
// We expect a simulate after every expression with side effects, though |
// this one isn't actually needed (and wouldn't work if it were targeted). |
- if (instr->HasSideEffects()) { |
+ if (instr->HasObservableSideEffects()) { |
builder->Push(instr); |
builder->AddSimulate(ast_id); |
builder->Pop(); |
@@ -2171,7 +2177,7 @@ void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) { |
- ASSERT(!instr->HasSideEffects()); |
+ ASSERT(!instr->HasObservableSideEffects()); |
HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
instr->SetSuccessorAt(0, empty_true); |
@@ -2373,7 +2379,13 @@ HGraph* HGraphBuilder::CreateGraph() { |
if (FLAG_use_gvn) { |
HPhase phase("Global value numbering", graph()); |
HGlobalValueNumberer gvn(graph(), info()); |
- gvn.Analyze(); |
+ bool removed_side_effects = gvn.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) { |
+ gvn.Analyze(); |
+ } |
} |
if (FLAG_use_range) { |
@@ -3546,7 +3558,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
// The HSimulate for the store should not see the stored value in |
// effect contexts (it is not materialized at expr->id() in the |
// unoptimized code). |
- if (instr->HasSideEffects()) { |
+ if (instr->HasObservableSideEffects()) { |
if (ast_context()->IsEffect()) { |
AddSimulate(expr->id()); |
} else { |
@@ -3619,7 +3631,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
Push(value); |
instr->set_position(expr->position()); |
AddInstruction(instr); |
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
+ if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
return ast_context()->ReturnValue(Pop()); |
} |
@@ -3640,7 +3652,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
instr->set_position(position); |
AddInstruction(instr); |
- if (instr->HasSideEffects()) AddSimulate(ast_id); |
+ if (instr->HasObservableSideEffects()) AddSimulate(ast_id); |
} else { |
HValue* context = environment()->LookupContext(); |
HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
@@ -3653,8 +3665,8 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
function_strict_mode_flag()); |
instr->set_position(position); |
AddInstruction(instr); |
- ASSERT(instr->HasSideEffects()); |
- if (instr->HasSideEffects()) AddSimulate(ast_id); |
+ ASSERT(instr->HasObservableSideEffects()); |
+ if (instr->HasObservableSideEffects()) AddSimulate(ast_id); |
} |
} |
@@ -3711,7 +3723,9 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
HStoreContextSlot* instr = |
new(zone()) HStoreContextSlot(context, var->index(), Top()); |
AddInstruction(instr); |
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
+ if (instr->HasObservableSideEffects()) { |
+ AddSimulate(expr->AssignmentId()); |
+ } |
break; |
} |
@@ -3737,7 +3751,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
load = BuildLoadNamedGeneric(obj, prop); |
} |
PushAndAdd(load); |
- if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); |
+ if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); |
CHECK_ALIVE(VisitForValue(expr->value())); |
HValue* right = Pop(); |
@@ -3745,14 +3759,14 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
HInstruction* instr = BuildBinaryOperation(operation, left, right); |
PushAndAdd(instr); |
- if (instr->HasSideEffects()) AddSimulate(operation->id()); |
+ if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); |
HInstruction* store = BuildStoreNamed(obj, instr, prop); |
AddInstruction(store); |
// Drop the simulated receiver and value. Return the value. |
Drop(2); |
Push(instr); |
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
+ if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
return ast_context()->ReturnValue(Pop()); |
} else { |
@@ -3777,7 +3791,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
HInstruction* instr = BuildBinaryOperation(operation, left, right); |
PushAndAdd(instr); |
- if (instr->HasSideEffects()) AddSimulate(operation->id()); |
+ if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); |
expr->RecordTypeFeedback(oracle()); |
HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), |
@@ -3875,7 +3889,9 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { |
HStoreContextSlot* instr = |
new(zone()) HStoreContextSlot(context, var->index(), Top()); |
AddInstruction(instr); |
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
+ if (instr->HasObservableSideEffects()) { |
+ AddSimulate(expr->AssignmentId()); |
+ } |
return ast_context()->ReturnValue(Pop()); |
} |
@@ -4148,7 +4164,7 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
if (num_untransitionable_maps == 1) { |
HInstruction* instr = AddInstruction(BuildMonomorphicElementAccess( |
object, key, val, untransitionable_map, is_store)); |
- *has_side_effects |= instr->HasSideEffects(); |
+ *has_side_effects |= instr->HasObservableSideEffects(); |
instr->set_position(position); |
return is_store ? NULL : instr; |
} |
@@ -4235,7 +4251,7 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
Push(access); |
} |
- *has_side_effects |= access->HasSideEffects(); |
+ *has_side_effects |= access->HasObservableSideEffects(); |
if (position != -1) { |
access->set_position(position); |
} |
@@ -4256,7 +4272,7 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
access = AddInstruction(BuildExternalArrayElementAccess( |
external_elements, checked_key, val, elements_kind, is_store)); |
} |
- *has_side_effects |= access->HasSideEffects(); |
+ *has_side_effects |= access->HasObservableSideEffects(); |
access->set_position(position); |
if (!is_store) { |
Push(access); |
@@ -4301,7 +4317,7 @@ HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj, |
} |
instr->set_position(position); |
AddInstruction(instr); |
- *has_side_effects = instr->HasSideEffects(); |
+ *has_side_effects = instr->HasObservableSideEffects(); |
return instr; |
} |
@@ -4900,7 +4916,7 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, |
AddInstruction(square_root); |
// MathPowHalf doesn't have side effects so there's no need for |
// an environment simulation here. |
- ASSERT(!square_root->HasSideEffects()); |
+ ASSERT(!square_root->HasObservableSideEffects()); |
result = new(zone()) HDiv(context, double_one, square_root); |
} else if (exponent == 2.0) { |
result = new(zone()) HMul(context, left, left); |
@@ -5484,7 +5500,9 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
HStoreContextSlot* instr = |
new(zone()) HStoreContextSlot(context, var->index(), after); |
AddInstruction(instr); |
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
+ if (instr->HasObservableSideEffects()) { |
+ AddSimulate(expr->AssignmentId()); |
+ } |
break; |
} |
@@ -5513,7 +5531,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
load = BuildLoadNamedGeneric(obj, prop); |
} |
PushAndAdd(load); |
- if (load->HasSideEffects()) AddSimulate(expr->CountId()); |
+ if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); |
after = BuildIncrement(returns_original_input, expr); |
input = Pop(); |
@@ -5526,7 +5544,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
// necessary. |
environment()->SetExpressionStackAt(0, after); |
if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
- if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
+ if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); |
} else { |
// Keyed property. |
@@ -6080,7 +6098,7 @@ void HGraphBuilder::HandleDeclaration(VariableProxy* proxy, |
HStoreContextSlot* store = |
new HStoreContextSlot(context, var->index(), value); |
AddInstruction(store); |
- if (store->HasSideEffects()) AddSimulate(proxy->id()); |
+ if (store->HasObservableSideEffects()) AddSimulate(proxy->id()); |
} else { |
environment()->Bind(var, value); |
} |