Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10912094: Reapply "Remove classes Computation and BindInstr." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 6b1c0f526a44bfc554800aaba9d92b1b2fe2aa8b..140e314730b348232b2e400dec9da41cd2f3f305 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -31,19 +31,19 @@ void FlowGraphOptimizer::OptimizeComputations() {
BlockEntryInstr* entry = block_order_[i];
entry->Accept(this);
for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
- BindInstr* instr = it.Current()->AsBind();
- if (instr != NULL) {
- Definition* result = instr->computation()->TryReplace(instr);
- if (result != instr) {
+ Definition* defn = it.Current()->AsDefinition();
+ if (defn != NULL) {
+ Definition* result = defn->Canonicalize();
+ if (result != defn) {
if (result != NULL) {
- instr->ReplaceUsesWith(result);
+ defn->ReplaceUsesWith(result);
if (FLAG_trace_optimization) {
OS::Print("Replacing v%d with v%d\n",
- instr->ssa_temp_index(),
+ defn->ssa_temp_index(),
result->ssa_temp_index());
}
} else if (FLAG_trace_optimization) {
- OS::Print("Removing v%d.\n", instr->ssa_temp_index());
+ OS::Print("Removing v%d.\n", defn->ssa_temp_index());
}
it.RemoveCurrentFromGraph();
}
@@ -53,17 +53,17 @@ void FlowGraphOptimizer::OptimizeComputations() {
}
-static Computation* CreateConversion(Representation from,
- Representation to,
- Definition* def,
- Instruction* deopt_target) {
+static Definition* CreateConversion(Representation from,
+ Representation to,
+ Definition* def,
+ Instruction* deopt_target) {
if ((from == kUnboxedDouble) && (to == kTagged)) {
- return new BoxDoubleComp(new Value(def), NULL);
+ return new BoxDoubleInstr(new Value(def), NULL);
} else if ((from == kTagged) && (to == kUnboxedDouble)) {
const intptr_t deopt_id = (deopt_target != NULL) ?
deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid));
- return new UnboxDoubleComp(new Value(def), deopt_id);
+ return new UnboxDoubleInstr(new Value(def), deopt_id);
} else {
UNREACHABLE();
return NULL;
@@ -96,16 +96,15 @@ void FlowGraphOptimizer::InsertConversionsFor(Definition* def) {
deopt_target = instr;
}
- BindInstr* converted = InsertBefore(
- instr,
- CreateConversion(from_rep, to_rep, def, deopt_target),
- use->instruction()->env(),
- Definition::kValue);
-
+ Definition* converted =
+ CreateConversion(from_rep, to_rep, def, deopt_target);
+ InsertBefore(instr, converted, use->instruction()->env(),
+ Definition::kValue);
use->set_definition(converted);
}
}
+
void FlowGraphOptimizer::SelectRepresentations() {
// Convervatively unbox all phis that were proven to be of type Double.
for (intptr_t i = 0; i < block_order_.length(); ++i) {
@@ -264,10 +263,10 @@ static bool ShouldSpecializeForDouble(const ICData& ic_data) {
}
-static void RemovePushArguments(InstanceCallComp* comp) {
+static void RemovePushArguments(InstanceCallInstr* call) {
// Remove original push arguments.
- for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) {
- PushArgumentInstr* push = comp->ArgumentAt(i);
+ for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
+ PushArgumentInstr* push = call->ArgumentAt(i);
push->ReplaceUsesWith(push->value()->definition());
push->RemoveFromGraph();
}
@@ -290,10 +289,10 @@ static bool HasOneTarget(const ICData& ic_data) {
}
-static intptr_t ReceiverClassId(InstanceCallComp* comp) {
- if (!comp->HasICData()) return kIllegalCid;
+static intptr_t ReceiverClassId(InstanceCallInstr* call) {
+ if (!call->HasICData()) return kIllegalCid;
- const ICData& ic_data = *comp->ic_data();
+ const ICData& ic_data = *call->ic_data();
if (ic_data.NumberOfChecks() == 0) return kIllegalCid;
// TODO(vegorov): Add multiple receiver type support.
@@ -307,24 +306,22 @@ static intptr_t ReceiverClassId(InstanceCallComp* comp) {
}
-void FlowGraphOptimizer::AddCheckClass(BindInstr* instr,
- InstanceCallComp* comp,
+void FlowGraphOptimizer::AddCheckClass(InstanceCallInstr* call,
Value* value) {
// Type propagation has not run yet, we cannot eliminate the check.
const ICData& unary_checks =
- ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
- CheckClassComp* check = new CheckClassComp(value, comp, unary_checks);
- InsertBefore(instr, check, instr->env(), Definition::kEffect);
+ ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks());
+ CheckClassInstr* check = new CheckClassInstr(value, call, unary_checks);
+ InsertBefore(call, check, call->env(), Definition::kEffect);
}
-bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr,
- InstanceCallComp* comp,
+bool FlowGraphOptimizer::TryReplaceWithArrayOp(InstanceCallInstr* call,
Token::Kind op_kind) {
// TODO(fschneider): Optimize []= operator in checked mode as well.
if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false;
- const intptr_t class_id = ReceiverClassId(comp);
+ const intptr_t class_id = ReceiverClassId(call);
switch (class_id) {
case kImmutableArrayCid:
// Stores are only specialized for Array and GrowableObjectArray,
@@ -333,32 +330,32 @@ bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr,
// Fall through.
case kArrayCid:
case kGrowableObjectArrayCid: {
- Value* array = comp->ArgumentAt(0)->value();
- Value* index = comp->ArgumentAt(1)->value();
+ Value* array = call->ArgumentAt(0)->value();
+ Value* index = call->ArgumentAt(1)->value();
// Insert class check and index smi checks and attach a copy of the
// original environment because the operation can still deoptimize.
- AddCheckClass(instr, comp, array->Copy());
- InsertBefore(instr,
- new CheckSmiComp(index->Copy(), comp->deopt_id()),
- instr->env(),
+ AddCheckClass(call, array->Copy());
+ InsertBefore(call,
+ new CheckSmiInstr(index->Copy(), call->deopt_id()),
+ call->env(),
Definition::kEffect);
// Insert array bounds check.
- InsertBefore(instr,
- new CheckArrayBoundComp(array->Copy(),
- index->Copy(),
- class_id,
- comp),
- instr->env(),
+ InsertBefore(call,
+ new CheckArrayBoundInstr(array->Copy(),
+ index->Copy(),
+ class_id,
+ call),
+ call->env(),
Definition::kEffect);
- Computation* array_op = NULL;
+ Definition* array_op = NULL;
if (op_kind == Token::kINDEX) {
- array_op = new LoadIndexedComp(array, index, class_id);
+ array_op = new LoadIndexedInstr(array, index, class_id);
} else {
- Value* value = comp->ArgumentAt(2)->value();
- array_op = new StoreIndexedComp(array, index, value, class_id);
+ Value* value = call->ArgumentAt(2)->value();
+ array_op = new StoreIndexedInstr(array, index, value, class_id);
}
- instr->set_computation(array_op);
- RemovePushArguments(comp);
+ call->ReplaceWith(array_op, current_iterator());
+ RemovePushArguments(call);
return true;
}
default:
@@ -367,40 +364,35 @@ bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr,
}
-BindInstr* FlowGraphOptimizer::InsertBefore(Instruction* instr,
- Computation* comp,
- Environment* env,
- BindInstr::UseKind use_kind) {
- BindInstr* bind = new BindInstr(use_kind, comp);
- if (env != NULL) env->CopyTo(bind);
+void FlowGraphOptimizer::InsertBefore(Instruction* instr,
+ Definition* defn,
+ Environment* env,
+ Definition::UseKind use_kind) {
+ if (env != NULL) env->CopyTo(defn);
if (use_kind == Definition::kValue) {
- bind->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
+ defn->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
}
- bind->InsertBefore(instr);
- return bind;
+ defn->InsertBefore(instr);
}
-BindInstr* FlowGraphOptimizer::InsertAfter(Instruction* instr,
- Computation* comp,
- Environment* env,
- BindInstr::UseKind use_kind) {
- BindInstr* bind = new BindInstr(use_kind, comp);
- if (env != NULL) env->CopyTo(bind);
+void FlowGraphOptimizer::InsertAfter(Instruction* instr,
+ Definition* defn,
+ Environment* env,
+ Definition::UseKind use_kind) {
+ if (env != NULL) env->CopyTo(defn);
if (use_kind == Definition::kValue) {
- bind->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
+ defn->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
}
- bind->InsertAfter(instr);
- return bind;
+ defn->InsertAfter(instr);
}
-bool FlowGraphOptimizer::TryReplaceWithBinaryOp(BindInstr* instr,
- InstanceCallComp* comp,
+bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
Token::Kind op_kind) {
intptr_t operands_type = kIllegalCid;
- ASSERT(comp->HasICData());
- const ICData& ic_data = *comp->ic_data();
+ ASSERT(call->HasICData());
+ const ICData& ic_data = *call->ic_data();
switch (op_kind) {
case Token::kADD:
case Token::kSUB:
@@ -447,87 +439,82 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(BindInstr* instr,
UNREACHABLE();
};
- ASSERT(comp->ArgumentCount() == 2);
+ ASSERT(call->ArgumentCount() == 2);
if (operands_type == kDoubleCid) {
- Value* left = comp->ArgumentAt(0)->value();
- Value* right = comp->ArgumentAt(1)->value();
+ Value* left = call->ArgumentAt(0)->value();
+ Value* right = call->ArgumentAt(1)->value();
// Check that either left or right are not a smi. Result or a
// binary operation with two smis is a smi not a double.
- InsertBefore(instr,
- new CheckEitherNonSmiComp(left->Copy(),
- right->Copy(),
- comp),
- instr->env(),
+ InsertBefore(call,
+ new CheckEitherNonSmiInstr(left->Copy(),
+ right->Copy(),
+ call),
+ call->env(),
Definition::kEffect);
- UnboxedDoubleBinaryOpComp* double_bin_op =
- new UnboxedDoubleBinaryOpComp(op_kind,
- left->Copy(),
- right->Copy(),
- comp);
- instr->set_computation(double_bin_op);
-
- RemovePushArguments(comp);
+ UnboxedDoubleBinaryOpInstr* double_bin_op =
+ new UnboxedDoubleBinaryOpInstr(op_kind,
+ left->Copy(),
+ right->Copy(),
+ call);
+ call->ReplaceWith(double_bin_op, current_iterator());
+ RemovePushArguments(call);
} else if (operands_type == kMintCid) {
- Value* left = comp->ArgumentAt(0)->value();
- Value* right = comp->ArgumentAt(1)->value();
- BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind,
- comp,
- left,
- right);
- instr->set_computation(bin_op);
- RemovePushArguments(comp);
+ Value* left = call->ArgumentAt(0)->value();
+ Value* right = call->ArgumentAt(1)->value();
+ BinaryMintOpInstr* bin_op = new BinaryMintOpInstr(op_kind,
+ call,
+ left,
+ right);
+ call->ReplaceWith(bin_op, current_iterator());
+ RemovePushArguments(call);
} else {
ASSERT(operands_type == kSmiCid);
- Value* left = comp->ArgumentAt(0)->value();
- Value* right = comp->ArgumentAt(1)->value();
+ Value* left = call->ArgumentAt(0)->value();
+ Value* right = call->ArgumentAt(1)->value();
// Insert two smi checks and attach a copy of the original
// environment because the smi operation can still deoptimize.
- InsertBefore(instr,
- new CheckSmiComp(left->Copy(), comp->deopt_id()),
- instr->env(),
+ InsertBefore(call,
+ new CheckSmiInstr(left->Copy(), call->deopt_id()),
+ call->env(),
Definition::kEffect);
- InsertBefore(instr,
- new CheckSmiComp(right->Copy(), comp->deopt_id()),
- instr->env(),
+ InsertBefore(call,
+ new CheckSmiInstr(right->Copy(), call->deopt_id()),
+ call->env(),
Definition::kEffect);
- BinarySmiOpComp* bin_op = new BinarySmiOpComp(op_kind,
- comp,
- left,
- right);
- instr->set_computation(bin_op);
- RemovePushArguments(comp);
+ BinarySmiOpInstr* bin_op = new BinarySmiOpInstr(op_kind, call, left, right);
+ call->ReplaceWith(bin_op, current_iterator());
+ RemovePushArguments(call);
}
return true;
}
-bool FlowGraphOptimizer::TryReplaceWithUnaryOp(BindInstr* instr,
- InstanceCallComp* comp,
+bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
Token::Kind op_kind) {
- if (comp->ic_data()->NumberOfChecks() != 1) {
+ if (call->ic_data()->NumberOfChecks() != 1) {
// TODO(srdjan): Not yet supported.
return false;
}
- ASSERT(comp->ArgumentCount() == 1);
- Computation* unary_op = NULL;
- if (HasOneSmi(*comp->ic_data())) {
- Value* value = comp->ArgumentAt(0)->value();
- InsertBefore(instr,
- new CheckSmiComp(value->Copy(), comp->deopt_id()),
- instr->env(),
+ ASSERT(call->ArgumentCount() == 1);
+ Definition* unary_op = NULL;
+ if (HasOneSmi(*call->ic_data())) {
+ Value* value = call->ArgumentAt(0)->value();
+ InsertBefore(call,
+ new CheckSmiInstr(value->Copy(), call->deopt_id()),
+ call->env(),
Definition::kEffect);
- unary_op = new UnarySmiOpComp(op_kind,
- (op_kind == Token::kNEGATE) ? comp : NULL,
- value);
- } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) {
- unary_op = new NumberNegateComp(comp, comp->ArgumentAt(0)->value());
+ unary_op = new UnarySmiOpInstr(op_kind,
+ (op_kind == Token::kNEGATE) ? call : NULL,
+ value);
+ } else if (HasOneDouble(*call->ic_data()) && (op_kind == Token::kNEGATE)) {
+ unary_op = new NumberNegateInstr(call, call->ArgumentAt(0)->value());
}
if (unary_op == NULL) return false;
- instr->set_computation(unary_op);
- RemovePushArguments(comp);
+ call->ReplaceWith(unary_op, current_iterator());
+ RemovePushArguments(call);
return true;
}
@@ -548,10 +535,9 @@ static RawField* GetField(intptr_t class_id, const String& field_name) {
// Only unique implicit instance getters can be currently handled.
-bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr,
- InstanceCallComp* comp) {
- ASSERT(comp->HasICData());
- const ICData& ic_data = *comp->ic_data();
+bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
+ ASSERT(call->HasICData());
+ const ICData& ic_data = *call->ic_data();
if (ic_data.NumberOfChecks() == 0) {
// No type feedback collected.
return false;
@@ -568,18 +554,18 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr,
}
// Inline implicit instance getter.
const String& field_name =
- String::Handle(Field::NameFromGetter(comp->function_name()));
+ String::Handle(Field::NameFromGetter(call->function_name()));
const Field& field = Field::Handle(GetField(class_ids[0], field_name));
ASSERT(!field.IsNull());
- AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy());
+ AddCheckClass(call, call->ArgumentAt(0)->value()->Copy());
// Detach environment from the original instruction because it can't
// deoptimize.
- instr->set_env(NULL);
- LoadInstanceFieldComp* load =
- new LoadInstanceFieldComp(field, comp->ArgumentAt(0)->value());
- instr->set_computation(load);
- RemovePushArguments(comp);
+ call->set_env(NULL);
+ LoadInstanceFieldInstr* load =
+ new LoadInstanceFieldInstr(field, call->ArgumentAt(0)->value());
+ call->ReplaceWith(load, current_iterator());
+ RemovePushArguments(call);
return true;
}
@@ -608,15 +594,15 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr,
UNREACHABLE();
}
// Check receiver class.
- AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy());
+ AddCheckClass(call, call->ArgumentAt(0)->value()->Copy());
- LoadVMFieldComp* load = new LoadVMFieldComp(
- comp->ArgumentAt(0)->value(),
+ LoadVMFieldInstr* load = new LoadVMFieldInstr(
+ call->ArgumentAt(0)->value(),
length_offset,
Type::ZoneHandle(Type::SmiType()));
load->set_result_cid(kSmiCid);
- instr->set_computation(load);
- RemovePushArguments(comp);
+ call->ReplaceWith(load, current_iterator());
+ RemovePushArguments(call);
return true;
}
@@ -626,15 +612,15 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr,
return false;
}
// Check receiver class.
- AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy());
+ AddCheckClass(call, call->ArgumentAt(0)->value()->Copy());
- LoadVMFieldComp* load = new LoadVMFieldComp(
- comp->ArgumentAt(0)->value(),
+ LoadVMFieldInstr* load = new LoadVMFieldInstr(
+ call->ArgumentAt(0)->value(),
String::length_offset(),
Type::ZoneHandle(Type::SmiType()));
load->set_result_cid(kSmiCid);
- instr->set_computation(load);
- RemovePushArguments(comp);
+ call->ReplaceWith(load, current_iterator());
+ RemovePushArguments(call);
return true;
}
return false;
@@ -642,10 +628,9 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr,
// Inline only simple, frequently called core library methods.
-bool FlowGraphOptimizer::TryInlineInstanceMethod(BindInstr* instr,
- InstanceCallComp* comp) {
- ASSERT(comp->HasICData());
- const ICData& ic_data = *comp->ic_data();
+bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
+ ASSERT(call->HasICData());
+ const ICData& ic_data = *call->ic_data();
if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) {
// No type feedback collected.
return false;
@@ -658,16 +643,16 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(BindInstr* instr,
if ((recognized_kind == MethodRecognizer::kDoubleToDouble) &&
(class_ids[0] == kDoubleCid)) {
- DoubleToDoubleComp* d2d_comp =
- new DoubleToDoubleComp(comp->ArgumentAt(0)->value(), comp);
- instr->set_computation(d2d_comp);
- RemovePushArguments(comp);
+ DoubleToDoubleInstr* d2d_instr =
+ new DoubleToDoubleInstr(call->ArgumentAt(0)->value(), call);
+ call->ReplaceWith(d2d_instr, current_iterator());
+ RemovePushArguments(call);
return true;
}
if ((recognized_kind == MethodRecognizer::kIntegerToDouble) &&
(class_ids[0] == kSmiCid)) {
- SmiToDoubleComp* s2d_comp = new SmiToDoubleComp(comp);
- instr->set_computation(s2d_comp);
+ SmiToDoubleInstr* s2d_instr = new SmiToDoubleInstr(call);
+ call->ReplaceWith(s2d_instr, current_iterator());
// Pushed arguments are not removed because SmiToDouble is implemented
// as a call.
return true;
@@ -676,51 +661,49 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(BindInstr* instr,
}
-void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp,
- BindInstr* instr) {
- if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) {
- const Token::Kind op_kind = comp->token_kind();
+void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
+ if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) {
+ const Token::Kind op_kind = instr->token_kind();
if (Token::IsIndexOperator(op_kind) &&
- TryReplaceWithArrayOp(instr, comp, op_kind)) {
+ TryReplaceWithArrayOp(instr, op_kind)) {
return;
}
if (Token::IsBinaryToken(op_kind) &&
- TryReplaceWithBinaryOp(instr, comp, op_kind)) {
+ TryReplaceWithBinaryOp(instr, op_kind)) {
return;
}
if (Token::IsUnaryToken(op_kind) &&
- TryReplaceWithUnaryOp(instr, comp, op_kind)) {
+ TryReplaceWithUnaryOp(instr, op_kind)) {
return;
}
- if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, comp)) {
+ if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) {
return;
}
- if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr, comp)) {
+ if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr)) {
return;
}
- if (TryInlineInstanceMethod(instr, comp)) {
+ if (TryInlineInstanceMethod(instr)) {
return;
}
const intptr_t kMaxChecks = 4;
- if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) {
+ if (instr->ic_data()->NumberOfChecks() <= kMaxChecks) {
const ICData& unary_checks =
- ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
+ ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks());
bool call_with_checks;
- // TODO(srdjan): Add check class comp for mixed smi/non-smi.
+ // TODO(srdjan): Add check class instr for mixed smi/non-smi.
if (HasOneTarget(unary_checks) &&
(unary_checks.GetReceiverClassIdAt(0) != kSmiCid)) {
// Type propagation has not run yet, we cannot eliminate the check.
- AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy());
+ AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy());
// Call can still deoptimize, do not detach environment from instr.
call_with_checks = false;
} else {
call_with_checks = true;
}
- PolymorphicInstanceCallComp* call =
- new PolymorphicInstanceCallComp(comp,
- unary_checks,
- call_with_checks);
- instr->set_computation(call);
+ PolymorphicInstanceCallInstr* call =
+ new PolymorphicInstanceCallInstr(instr, unary_checks,
+ call_with_checks);
+ instr->ReplaceWith(call, current_iterator());
}
}
// An instance call without ICData should continue calling via IC calls
@@ -728,25 +711,23 @@ void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp,
}
-void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp,
- BindInstr* instr) {
+void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* instr) {
MethodRecognizer::Kind recognized_kind =
- MethodRecognizer::RecognizeKind(comp->function());
+ MethodRecognizer::RecognizeKind(instr->function());
if (recognized_kind == MethodRecognizer::kMathSqrt) {
- comp->set_recognized(MethodRecognizer::kMathSqrt);
+ instr->set_recognized(MethodRecognizer::kMathSqrt);
}
}
-bool FlowGraphOptimizer::TryInlineInstanceSetter(BindInstr* instr,
- InstanceCallComp* comp) {
+bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr) {
if (FLAG_enable_type_checks) {
// TODO(srdjan): Add assignable check node if --enable_type_checks.
return false;
}
- ASSERT(comp->HasICData());
- const ICData& ic_data = *comp->ic_data();
+ ASSERT(instr->HasICData());
+ const ICData& ic_data = *instr->ic_data();
if (ic_data.NumberOfChecks() == 0) {
// No type feedback collected.
return false;
@@ -765,20 +746,20 @@ bool FlowGraphOptimizer::TryInlineInstanceSetter(BindInstr* instr,
}
// Inline implicit instance setter.
const String& field_name =
- String::Handle(Field::NameFromSetter(comp->function_name()));
+ String::Handle(Field::NameFromSetter(instr->function_name()));
const Field& field = Field::Handle(GetField(class_id, field_name));
ASSERT(!field.IsNull());
- AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy());
+ AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy());
// Detach environment from the original instruction because it can't
// deoptimize.
instr->set_env(NULL);
- StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
+ StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
field,
- comp->ArgumentAt(0)->value(),
- comp->ArgumentAt(1)->value());
- instr->set_computation(store);
- RemovePushArguments(comp);
+ instr->ArgumentAt(0)->value(),
+ instr->ArgumentAt(1)->value());
+ instr->ReplaceWith(store, current_iterator());
+ RemovePushArguments(instr);
return true;
}
@@ -786,7 +767,7 @@ bool FlowGraphOptimizer::TryInlineInstanceSetter(BindInstr* instr,
// TODO(fschneider): Once we get rid of the distinction between Instruction
// and computation, this helper can go away.
static void HandleRelationalOp(FlowGraphOptimizer* optimizer,
- RelationalOpComp* comp,
+ RelationalOpInstr* comp,
Instruction* instr) {
if (!comp->HasICData()) return;
@@ -799,12 +780,12 @@ static void HandleRelationalOp(FlowGraphOptimizer* optimizer,
if (HasOnlyTwoSmi(ic_data)) {
optimizer->InsertBefore(
instr,
- new CheckSmiComp(comp->left()->Copy(), comp->deopt_id()),
+ new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
optimizer->InsertBefore(
instr,
- new CheckSmiComp(comp->right()->Copy(), comp->deopt_id()),
+ new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
comp->set_operands_class_id(kSmiCid);
@@ -815,9 +796,8 @@ static void HandleRelationalOp(FlowGraphOptimizer* optimizer,
}
}
-void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp,
- BindInstr* instr) {
- HandleRelationalOp(this, comp, instr);
+void FlowGraphOptimizer::VisitRelationalOp(RelationalOpInstr* instr) {
+ HandleRelationalOp(this, instr, instr);
}
@@ -825,16 +805,17 @@ void FlowGraphOptimizer::VisitRelationalOp(RelationalOpComp* comp,
// and computation, this helper can go away.
template <typename T>
static void HandleEqualityCompare(FlowGraphOptimizer* optimizer,
- EqualityCompareComp* comp,
- T instr) {
+ EqualityCompareInstr* comp,
+ T instr,
+ ForwardInstructionIterator* iterator) {
// If one of the inputs is null, no ICdata will be collected.
if (comp->left()->BindsToConstantNull() ||
comp->right()->BindsToConstantNull()) {
Token::Kind strict_kind = (comp->kind() == Token::kEQ) ?
Token::kEQ_STRICT : Token::kNE_STRICT;
- StrictCompareComp* strict_comp =
- new StrictCompareComp(strict_kind, comp->left(), comp->right());
- instr->set_computation(strict_comp);
+ StrictCompareInstr* strict_comp =
+ new StrictCompareInstr(strict_kind, comp->left(), comp->right());
+ instr->ReplaceWith(strict_comp, iterator);
return;
}
if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return;
@@ -847,12 +828,12 @@ static void HandleEqualityCompare(FlowGraphOptimizer* optimizer,
if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) {
optimizer->InsertBefore(
instr,
- new CheckSmiComp(comp->left()->Copy(), comp->deopt_id()),
+ new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
optimizer->InsertBefore(
instr,
- new CheckSmiComp(comp->right()->Copy(), comp->deopt_id()),
+ new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
comp->set_receiver_class_id(kSmiCid);
@@ -867,23 +848,18 @@ static void HandleEqualityCompare(FlowGraphOptimizer* optimizer,
}
-void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp,
- BindInstr* instr) {
- HandleEqualityCompare(this, comp, instr);
-}
-
-
-void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
- instr->computation()->Accept(this, instr);
+void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) {
+ HandleEqualityCompare(this, instr, instr, current_iterator());
}
void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) {
- ComparisonComp* comparison = instr->computation();
+ ComparisonInstr* comparison = instr->comparison();
if (comparison->IsRelationalOp()) {
HandleRelationalOp(this, comparison->AsRelationalOp(), instr);
} else if (comparison->IsEqualityCompare()) {
- HandleEqualityCompare(this, comparison->AsEqualityCompare(), instr);
+ HandleEqualityCompare(this, comparison->AsEqualityCompare(), instr,
+ current_iterator());
} else {
ASSERT(comparison->IsStrictCompare());
// Nothing to do.
@@ -891,19 +867,52 @@ void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) {
}
-void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp,
- BindInstr* instr) {
+void FlowGraphTypePropagator::VisitBlocks() {
+ ASSERT(current_iterator_ == NULL);
+ for (intptr_t i = 0; i < block_order_.length(); ++i) {
+ BlockEntryInstr* entry = block_order_[i];
+ entry->Accept(this);
+ ForwardInstructionIterator it(entry);
+ current_iterator_ = &it;
+ for (; !it.Done(); it.Advance()) {
+ Instruction* current = it.Current();
+ // No need to propagate the input types of the instruction, as long as
+ // PhiInstr's are handled as part of JoinEntryInstr.
+
+ // Visit the instruction and possibly eliminate type checks.
+ current->Accept(this);
+ // The instruction may have been removed from the graph.
+ Definition* defn = current->AsDefinition();
+ if ((defn != NULL) &&
+ !defn->IsPushArgument() &&
Kevin Millikin (Google) 2012/09/05 12:50:09 This line is added.
+ (defn->previous() != NULL)) {
+ // Cache the propagated computation type.
+ AbstractType& type = AbstractType::Handle(defn->CompileType());
+ still_changing_ = defn->SetPropagatedType(type) || still_changing_;
+
+ // Propagate class ids.
+ const intptr_t cid = defn->ResultCid();
+ still_changing_ = defn->SetPropagatedCid(cid) || still_changing_;
+ }
+ }
+ current_iterator_ = NULL;
+ }
+}
+
+
+void FlowGraphTypePropagator::VisitAssertAssignable(
+ AssertAssignableInstr* instr) {
if (FLAG_eliminate_type_checks &&
- !comp->is_eliminated() &&
- comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) {
+ !instr->is_eliminated() &&
+ instr->value()->CompileTypeIsMoreSpecificThan(instr->dst_type())) {
// TODO(regis): Remove is_eliminated_ field and support.
- comp->eliminate();
+ instr->eliminate();
- Value* use = comp->value();
+ Value* use = instr->value();
ASSERT(use != NULL);
Definition* result = use->definition();
ASSERT(result != NULL);
- // Replace uses and remove the current instructions via the iterator.
+ // Replace uses and remove the current instruction via the iterator.
instr->ReplaceUsesWith(result);
ASSERT(current_iterator()->Current() == instr);
current_iterator()->RemoveCurrentFromGraph();
@@ -915,18 +924,17 @@ void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp,
if (FLAG_trace_type_check_elimination) {
FlowGraphPrinter::PrintTypeCheck(parsed_function(),
- comp->token_pos(),
- comp->value(),
- comp->dst_type(),
- comp->dst_name(),
- comp->is_eliminated());
+ instr->token_pos(),
+ instr->value(),
+ instr->dst_type(),
+ instr->dst_name(),
+ instr->is_eliminated());
}
}
}
-void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp,
- BindInstr* instr) {
+void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
// TODO(regis): Propagate NullType as well and revise the comment and code
// below to also eliminate the test for non-null and non-constant value.
@@ -934,18 +942,18 @@ void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp,
// a constant time constant. Indeed, a variable of the proper compile time
// type (bool) may still hold null at run time and therefore fail the test.
if (FLAG_eliminate_type_checks &&
- !comp->is_eliminated() &&
- comp->value()->BindsToConstant() &&
- !comp->value()->BindsToConstantNull() &&
- comp->value()->CompileTypeIsMoreSpecificThan(
+ !instr->is_eliminated() &&
+ instr->value()->BindsToConstant() &&
+ !instr->value()->BindsToConstantNull() &&
+ instr->value()->CompileTypeIsMoreSpecificThan(
Type::Handle(Type::BoolType()))) {
// TODO(regis): Remove is_eliminated_ field and support.
- comp->eliminate();
+ instr->eliminate();
- Value* use = comp->value();
+ Value* use = instr->value();
Definition* result = use->definition();
ASSERT(result != NULL);
- // Replace uses and remove the current instructions via the iterator.
+ // Replace uses and remove the current instruction via the iterator.
instr->ReplaceUsesWith(result);
ASSERT(current_iterator()->Current() == instr);
current_iterator()->RemoveCurrentFromGraph();
@@ -958,18 +966,17 @@ void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp,
if (FLAG_trace_type_check_elimination) {
const String& name = String::Handle(Symbols::New("boolean expression"));
FlowGraphPrinter::PrintTypeCheck(parsed_function(),
- comp->token_pos(),
- comp->value(),
+ instr->token_pos(),
+ instr->value(),
Type::Handle(Type::BoolType()),
name,
- comp->is_eliminated());
+ instr->is_eliminated());
}
}
}
-void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfComp* comp,
- BindInstr* instr) {
+void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfInstr* instr) {
// TODO(regis): Propagate NullType as well and revise the comment and code
// below to also eliminate the test for non-null and non-constant value.
@@ -979,13 +986,13 @@ void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfComp* comp,
// We do not bother checking for Object destination type, since the graph
// builder did already.
if (FLAG_eliminate_type_checks &&
- comp->value()->BindsToConstant() &&
- !comp->value()->BindsToConstantNull() &&
- comp->value()->CompileTypeIsMoreSpecificThan(comp->type())) {
- Value* use = comp->value();
+ instr->value()->BindsToConstant() &&
+ !instr->value()->BindsToConstantNull() &&
+ instr->value()->CompileTypeIsMoreSpecificThan(instr->type())) {
+ Value* use = instr->value();
Definition* result = use->definition();
ASSERT(result != NULL);
- // Replace uses and remove the current instructions via the iterator.
+ // Replace uses and remove the current instruction via the iterator.
instr->ReplaceUsesWith(result);
ASSERT(current_iterator()->Current() == instr);
current_iterator()->RemoveCurrentFromGraph();
@@ -998,9 +1005,9 @@ void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfComp* comp,
if (FLAG_trace_type_check_elimination) {
const String& name = String::Handle(Symbols::New("InstanceOf"));
FlowGraphPrinter::PrintTypeCheck(parsed_function(),
- comp->token_pos(),
- comp->value(),
- comp->type(),
+ instr->token_pos(),
+ instr->value(),
+ instr->type(),
name,
/* eliminated = */ true);
}
@@ -1042,31 +1049,6 @@ void FlowGraphTypePropagator::VisitPushArgument(PushArgumentInstr* push) {
}
-void FlowGraphTypePropagator::VisitBind(BindInstr* bind) {
- // No need to propagate the input types of the bound computation, as long as
- // PhiInstr's are handled as part of JoinEntryInstr.
- // Visit computation and possibly eliminate type check.
- bind->computation()->Accept(this, bind);
- // The current bind may have been removed from the graph.
- if (current_iterator()->Current() == bind) {
- // Current bind was not removed.
- // Cache propagated computation type.
- AbstractType& computation_type =
- AbstractType::Handle(bind->computation()->CompileType());
- bool changed = bind->SetPropagatedType(computation_type);
- if (changed) {
- still_changing_ = true;
- }
- // Propagate class ids.
- const intptr_t cid = bind->computation()->ResultCid();
- changed = bind->SetPropagatedCid(cid);
- if (changed) {
- still_changing_ = true;
- }
- }
-}
-
-
void FlowGraphTypePropagator::VisitPhi(PhiInstr* phi) {
// We could set the propagated type of the phi to the least upper bound of its
// input propagated types. However, keeping all propagated types allows us to
@@ -1165,28 +1147,28 @@ void FlowGraphAnalyzer::Analyze() {
void DominatorBasedCSE::Optimize(BlockEntryInstr* graph_entry) {
ASSERT(graph_entry->IsGraphEntry());
- DirectChainedHashMap<BindInstr*> map;
+ DirectChainedHashMap<Definition*> map;
OptimizeRecursive(graph_entry, &map);
}
void DominatorBasedCSE::OptimizeRecursive(
BlockEntryInstr* block,
- DirectChainedHashMap<BindInstr*>* map) {
+ DirectChainedHashMap<Definition*>* map) {
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
- BindInstr* instr = it.Current()->AsBind();
- if (instr == NULL || instr->computation()->HasSideEffect()) continue;
- BindInstr* result = map->Lookup(instr);
+ Definition* defn = it.Current()->AsDefinition();
+ if ((defn == NULL) || defn->HasSideEffect()) continue;
+ Definition* result = map->Lookup(defn);
if (result == NULL) {
- map->Insert(instr);
+ map->Insert(defn);
continue;
}
// Replace current with lookup result.
- instr->ReplaceUsesWith(result);
+ defn->ReplaceUsesWith(result);
it.RemoveCurrentFromGraph();
if (FLAG_trace_optimization) {
OS::Print("Replacing v%d with v%d\n",
- instr->ssa_temp_index(),
+ defn->ssa_temp_index(),
result->ssa_temp_index());
}
}
@@ -1196,7 +1178,7 @@ void DominatorBasedCSE::OptimizeRecursive(
for (intptr_t i = 0; i < num_children; ++i) {
BlockEntryInstr* child = block->dominated_blocks()[i];
if (i < num_children - 1) {
- DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map.
+ DirectChainedHashMap<Definition*> child_map(*map); // Copy map.
OptimizeRecursive(child, &child_map);
} else {
OptimizeRecursive(child, map); // Reuse map for the last child.
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698