Index: runtime/vm/flow_graph_optimizer.cc |
=================================================================== |
--- runtime/vm/flow_graph_optimizer.cc (revision 10885) |
+++ runtime/vm/flow_graph_optimizer.cc (working copy) |
@@ -5,6 +5,7 @@ |
#include "vm/flow_graph_optimizer.h" |
#include "vm/flow_graph_builder.h" |
+#include "vm/hash_map.h" |
#include "vm/il_printer.h" |
#include "vm/object_store.h" |
#include "vm/parser.h" |
@@ -81,9 +82,9 @@ |
static bool ClassIdIsOneOf(intptr_t class_id, |
- GrowableArray<intptr_t>* class_ids) { |
- for (intptr_t i = 0; i < class_ids->length(); i++) { |
- if ((*class_ids)[i] == class_id) { |
+ const GrowableArray<intptr_t>& class_ids) { |
+ for (intptr_t i = 0; i < class_ids.length(); i++) { |
+ if (class_ids[i] == class_id) { |
return true; |
} |
} |
@@ -93,8 +94,8 @@ |
static bool ICDataHasOnlyReceiverArgumentClassIds( |
const ICData& ic_data, |
- GrowableArray<intptr_t>* receiver_class_ids, |
- GrowableArray<intptr_t>* argument_class_ids) { |
+ const GrowableArray<intptr_t>& receiver_class_ids, |
+ const GrowableArray<intptr_t>& argument_class_ids) { |
if (ic_data.num_args_tested() != 2) return false; |
Function& target = Function::Handle(); |
@@ -125,10 +126,10 @@ |
// Returns false if the ICData contains anything other than the 4 combinations |
// of Mint and Smi for the receiver and argument classes. |
static bool HasTwoMintOrSmi(const ICData& ic_data) { |
- GrowableArray<intptr_t> class_ids; |
+ GrowableArray<intptr_t> class_ids(2); |
class_ids.Add(kSmiCid); |
class_ids.Add(kMintCid); |
- return ICDataHasOnlyReceiverArgumentClassIds(ic_data, &class_ids, &class_ids); |
+ return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
} |
@@ -363,9 +364,35 @@ |
String::Handle(Field::NameFromGetter(comp->function_name())); |
const Field& field = Field::Handle(GetField(class_ids[0], field_name)); |
ASSERT(!field.IsNull()); |
- LoadInstanceFieldComp* load = new LoadInstanceFieldComp( |
- field, comp->ArgumentAt(0)->value(), comp); |
- load->set_ic_data(comp->ic_data()); |
+ |
+ LoadInstanceFieldComp* load; |
+ if (!use_ssa_) { |
+ load = new LoadInstanceFieldComp(field, |
+ comp->ArgumentAt(0)->value(), |
+ comp, |
+ true); // Can deoptimize. |
+ // TODO(fschneider): Remove the boolean parameter can_deoptimize once |
+ // the non-SSA optimizer is removed. |
+ load->set_ic_data(comp->ic_data()); |
+ } else { |
+ // TODO(fschneider): Avoid generating redundant checks by checking the |
+ // result-cid of the value. |
+ CheckClassComp* check = |
+ new CheckClassComp(comp->ArgumentAt(0)->value(), comp); |
+ const ICData& unary_checks = |
+ ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
+ check->set_ic_data(&unary_checks); |
+ BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); |
+ ASSERT(instr->env() != NULL); // Always the case with SSA. |
+ check_instr->set_env( |
+ new Environment(instr->env()->values(), |
+ instr->env()->fixed_parameter_count())); |
+ check_instr->InsertBefore(instr); |
+ load = new LoadInstanceFieldComp(field, |
+ comp->ArgumentAt(0)->value(), |
+ NULL, |
+ false); // Can not deoptimize. |
+ } |
instr->set_computation(load); |
RemovePushArguments(comp); |
return true; |
@@ -489,7 +516,7 @@ |
const intptr_t kMaxChecks = 4; |
if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { |
PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); |
- ICData& unary_checks = |
+ const ICData& unary_checks = |
ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
call->set_ic_data(&unary_checks); |
instr->set_computation(call); |
@@ -868,4 +895,31 @@ |
} |
} |
+ |
+void LocalCSE::Optimize() { |
+ for (intptr_t i = 0; i < blocks_.length(); ++i) { |
+ BlockEntryInstr* entry = blocks_[i]; |
+ DirectChainedHashMap<BindInstr*> map; |
+ ASSERT(map.IsEmpty()); |
+ for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
+ BindInstr* instr = it.Current()->AsBind(); |
+ if (instr == NULL || instr->computation()->HasSideEffect()) continue; |
+ BindInstr* result = map.Lookup(instr); |
+ if (result == NULL) { |
+ map.Insert(instr); |
+ continue; |
+ } |
+ // Replace current with lookup result. |
+ instr->ReplaceUsesWith(result); |
+ it.RemoveCurrentFromGraph(); |
+ if (FLAG_trace_optimization) { |
+ OS::Print("Replacing v%d with v%d\n", |
+ instr->ssa_temp_index(), |
+ result->ssa_temp_index()); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
} // namespace dart |