Index: runtime/vm/flow_graph_optimizer.cc |
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc |
index 0b03b864ddc093de6ef773d446f12fc0c23bf32a..eacca8dab807427dbad9cd3b47c56d8b3e824adc 100644 |
--- a/runtime/vm/flow_graph_optimizer.cc |
+++ b/runtime/vm/flow_graph_optimizer.cc |
@@ -20,6 +20,7 @@ DECLARE_FLAG(bool, enable_type_checks); |
DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
DECLARE_FLAG(bool, trace_type_check_elimination); |
DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
+DEFINE_FLAG(bool, use_unboxed_doubles, true, "Try unboxing double values."); |
void FlowGraphOptimizer::ApplyICData() { |
VisitBlocks(); |
@@ -249,6 +250,34 @@ bool FlowGraphOptimizer::TryReplaceWithArrayOp(BindInstr* instr, |
} |
+Value* FlowGraphOptimizer::InsertBefore(Instruction* instr, |
+ Computation* comp, |
+ Environment* env) { |
+ BindInstr* bind = new BindInstr(BindInstr::kUsed, comp); |
+ bind->set_env(env->Clone()); |
Florian Schneider
2012/08/24 11:09:28
Use Environment::Copy?
Vyacheslav Egorov (Google)
2012/08/24 13:23:01
Done.
|
+ bind->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); |
+ |
+ bind->InsertBefore(instr); |
+ |
+ return new UseVal(bind); |
+} |
+ |
+ |
+BindInstr* FlowGraphOptimizer::InsertAfter(Instruction* instr, |
+ Computation* comp) { |
+ BindInstr* bind = new BindInstr(BindInstr::kUsed, comp); |
+ bind->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); |
+ |
+ Instruction* next = instr->next(); |
+ instr->set_next(bind); |
+ bind->set_previous(instr); |
+ bind->set_next(next); |
+ next->set_previous(bind); |
+ |
+ return bind; |
+} |
+ |
+ |
bool FlowGraphOptimizer::TryReplaceWithBinaryOp(BindInstr* instr, |
InstanceCallComp* comp, |
Token::Kind op_kind) { |
@@ -300,9 +329,36 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(BindInstr* instr, |
ASSERT(comp->ArgumentCount() == 2); |
if (operands_type == kDoubleCid) { |
- BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); |
- double_bin_op->set_ic_data(comp->ic_data()); |
- instr->set_computation(double_bin_op); |
+ if (FLAG_use_unboxed_doubles) { |
+ Value* left = comp->ArgumentAt(0)->value(); |
+ Value* right = comp->ArgumentAt(1)->value(); |
+ |
+ CheckEitherNonSmiComp* check = |
+ new CheckEitherNonSmiComp(left, right, comp); |
+ BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check); |
+ check_instr->set_env(instr->env()); |
+ check_instr->InsertBefore(instr); |
+ |
+ Value* unbox_left = |
+ InsertBefore(instr, new UnboxDoubleComp(left, comp), instr->env()); |
Florian Schneider
2012/08/24 11:09:28
Since left and right are used multiple times now,
Vyacheslav Egorov (Google)
2012/08/24 13:23:01
Done.
|
+ Value* unbox_right = |
+ InsertBefore(instr, new UnboxDoubleComp(right, comp), instr->env()); |
+ UnboxedDoubleBinaryOpComp* double_bin_op = |
+ new UnboxedDoubleBinaryOpComp(op_kind, comp, unbox_left, unbox_right); |
+ double_bin_op->set_ic_data(comp->ic_data()); |
+ instr->set_computation(double_bin_op); |
+ if (instr->is_used()) { |
+ UseVal* use_val = new UseVal(instr); |
+ BindInstr* bind = InsertAfter(instr, new BoxDoubleComp(use_val, comp)); |
+ instr->ReplaceUsesWith(bind); |
+ use_val->SetDefinition(instr); |
+ } |
+ RemovePushArguments(comp); |
+ } else { |
+ BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); |
+ double_bin_op->set_ic_data(comp->ic_data()); |
+ instr->set_computation(double_bin_op); |
+ } |
} else if (operands_type == kMintCid) { |
Value* left = comp->ArgumentAt(0)->value(); |
Value* right = comp->ArgumentAt(1)->value(); |