| Index: runtime/vm/flow_graph_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
|
| index f22e386d6ceb6a8a7f31fef4b83d24f6b7ed63d0..322730fb4021d55227a9e53bb958eea69d7c31b0 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/flow_graph_optimizer.cc
|
| @@ -390,53 +390,104 @@ void FlowGraphOptimizer::InsertConversion(Representation from,
|
| }
|
|
|
|
|
| +void FlowGraphOptimizer::ConvertUse(Value* use, Representation from_rep) {
|
| + const Representation to_rep =
|
| + use->instruction()->RequiredInputRepresentation(use->use_index());
|
| + if (from_rep == to_rep || to_rep == kNoRepresentation) {
|
| + return;
|
| + }
|
| +
|
| + Instruction* insert_before;
|
| + Instruction* deopt_target;
|
| + PhiInstr* phi = use->instruction()->AsPhi();
|
| + if (phi != NULL) {
|
| + ASSERT(phi->is_alive());
|
| + // For phis conversions have to be inserted in the predecessor.
|
| + insert_before =
|
| + phi->block()->PredecessorAt(use->use_index())->last_instruction();
|
| + deopt_target = NULL;
|
| + } else {
|
| + deopt_target = insert_before = use->instruction();
|
| + }
|
| +
|
| + InsertConversion(from_rep, to_rep, use, insert_before, deopt_target);
|
| +}
|
| +
|
| void FlowGraphOptimizer::InsertConversionsFor(Definition* def) {
|
| const Representation from_rep = def->representation();
|
|
|
| for (Value::Iterator it(def->input_use_list());
|
| !it.Done();
|
| it.Advance()) {
|
| - Value* use = it.Current();
|
| - const Representation to_rep =
|
| - use->instruction()->RequiredInputRepresentation(use->use_index());
|
| - if (from_rep == to_rep || to_rep == kNoRepresentation) {
|
| - continue;
|
| - }
|
| + ConvertUse(it.Current(), from_rep);
|
| + }
|
| +}
|
|
|
| - Instruction* insert_before;
|
| - Instruction* deopt_target;
|
| - PhiInstr* phi = use->instruction()->AsPhi();
|
| - if (phi != NULL) {
|
| - ASSERT(phi->is_alive());
|
| - // For phis conversions have to be inserted in the predecessor.
|
| - insert_before =
|
| - phi->block()->PredecessorAt(use->use_index())->last_instruction();
|
| - deopt_target = NULL;
|
| - } else {
|
| - deopt_target = insert_before = use->instruction();
|
| +
|
| +// Returns true if phi's representation was changed.
|
| +static bool UnboxPhi(PhiInstr* phi) {
|
| + Representation current = phi->representation();
|
| + Representation unboxed = current;
|
| +
|
| + switch (phi->Type()->ToCid()) {
|
| + case kDoubleCid:
|
| + unboxed = kUnboxedDouble;
|
| + break;
|
| + case kFloat32x4Cid:
|
| + unboxed = kUnboxedFloat32x4;
|
| + break;
|
| + case kUint32x4Cid:
|
| + unboxed = kUnboxedUint32x4;
|
| + break;
|
| + }
|
| +
|
| + if (unboxed != current) {
|
| + phi->set_representation(unboxed);
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +
|
| +void FlowGraphOptimizer::UnboxPhis() {
|
| + GrowableArray<PhiInstr*> worklist(5);
|
| +
|
| + // Convervatively unbox all phis that were proven to be of Double,
|
| + // Float32x4, or Uint32x4 type.
|
| + for (intptr_t i = 0; i < block_order_.length(); ++i) {
|
| + JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
|
| + if (join_entry != NULL) {
|
| + for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
|
| + PhiInstr* phi = it.Current();
|
| + if (UnboxPhi(phi)) {
|
| + worklist.Add(phi);
|
| + }
|
| + }
|
| }
|
| + }
|
|
|
| - InsertConversion(from_rep, to_rep, use, insert_before, deopt_target);
|
| + while (!worklist.is_empty()) {
|
| + PhiInstr* phi = worklist.RemoveLast();
|
| + InsertConversionsFor(phi);
|
| +
|
| + for (intptr_t i = 0; i < phi->InputCount(); i++) {
|
| + ConvertUse(phi->InputAt(i),
|
| + phi->InputAt(i)->definition()->representation());
|
| + }
|
| }
|
| }
|
|
|
|
|
| void FlowGraphOptimizer::SelectRepresentations() {
|
| // Convervatively unbox all phis that were proven to be of Double,
|
| - // Float32x4, or Uint32x4.
|
| + // Float32x4, or Uint32x4 type.
|
| for (intptr_t i = 0; i < block_order_.length(); ++i) {
|
| JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
|
| if (join_entry != NULL) {
|
| for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
|
| PhiInstr* phi = it.Current();
|
| - ASSERT(phi != NULL);
|
| - if (phi->Type()->ToCid() == kDoubleCid) {
|
| - phi->set_representation(kUnboxedDouble);
|
| - } else if (phi->Type()->ToCid() == kFloat32x4Cid) {
|
| - phi->set_representation(kUnboxedFloat32x4);
|
| - } else if (phi->Type()->ToCid() == kUint32x4Cid) {
|
| - phi->set_representation(kUnboxedUint32x4);
|
| - }
|
| + UnboxPhi(phi);
|
| }
|
| }
|
| }
|
|
|