| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 call->deopt_id(), | 1355 call->deopt_id(), |
| 1356 call->env(), | 1356 call->env(), |
| 1357 call); | 1357 call); |
| 1358 cid = kSmiCid; | 1358 cid = kSmiCid; |
| 1359 } else { | 1359 } else { |
| 1360 // Shortcut for equality with null. | 1360 // Shortcut for equality with null. |
| 1361 ConstantInstr* right_const = right->AsConstant(); | 1361 ConstantInstr* right_const = right->AsConstant(); |
| 1362 ConstantInstr* left_const = left->AsConstant(); | 1362 ConstantInstr* left_const = left->AsConstant(); |
| 1363 if ((right_const != NULL && right_const->value().IsNull()) || | 1363 if ((right_const != NULL && right_const->value().IsNull()) || |
| 1364 (left_const != NULL && left_const->value().IsNull())) { | 1364 (left_const != NULL && left_const->value().IsNull())) { |
| 1365 StrictCompareInstr* comp = new StrictCompareInstr(call->token_pos(), | 1365 StrictCompareInstr* comp = |
| 1366 Token::kEQ_STRICT, | 1366 new StrictCompareInstr(call->token_pos(), |
| 1367 new Value(left), | 1367 Token::kEQ_STRICT, |
| 1368 new Value(right)); | 1368 new Value(left), |
| 1369 new Value(right), |
| 1370 false); // No number check. |
| 1369 ReplaceCall(call, comp); | 1371 ReplaceCall(call, comp); |
| 1370 return true; | 1372 return true; |
| 1371 } | 1373 } |
| 1372 return false; | 1374 return false; |
| 1373 } | 1375 } |
| 1374 } | 1376 } |
| 1375 ASSERT(cid != kIllegalCid); | 1377 ASSERT(cid != kIllegalCid); |
| 1376 EqualityCompareInstr* comp = new EqualityCompareInstr(call->token_pos(), | 1378 EqualityCompareInstr* comp = new EqualityCompareInstr(call->token_pos(), |
| 1377 op_kind, | 1379 op_kind, |
| 1378 new Value(left), | 1380 new Value(left), |
| (...skipping 4885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6264 } | 6266 } |
| 6265 | 6267 |
| 6266 | 6268 |
| 6267 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { | 6269 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { |
| 6268 // Instruction is eliminated when translating to SSA. | 6270 // Instruction is eliminated when translating to SSA. |
| 6269 UNREACHABLE(); | 6271 UNREACHABLE(); |
| 6270 } | 6272 } |
| 6271 | 6273 |
| 6272 | 6274 |
| 6273 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { | 6275 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { |
| 6274 ASSERT(Token::IsEqualityOperator(instr->kind())); | 6276 instr->comparison()->Accept(this); |
| 6275 | 6277 const Object& value = instr->comparison()->constant_value(); |
| 6276 const Object& left = instr->left()->definition()->constant_value(); | 6278 if (IsNonConstant(value)) { |
| 6277 const Object& right = instr->right()->definition()->constant_value(); | 6279 SetValue(instr, non_constant_); |
| 6278 | 6280 } else if (IsConstant(value)) { |
| 6279 if (IsNonConstant(left) || IsNonConstant(right)) { | 6281 ASSERT(!value.IsNull()); |
| 6280 // TODO(vegorov): incorporate nullability information into the lattice. | 6282 ASSERT(value.IsBool()); |
| 6281 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || | 6283 bool result = Bool::Cast(value).value(); |
| 6282 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { | 6284 SetValue(instr, |
| 6283 bool result = left.IsNull() ? instr->right()->Type()->IsNull() | 6285 Smi::Handle(Smi::New( |
| 6284 : instr->left()->Type()->IsNull(); | 6286 result ? instr->if_true() : instr->if_false()))); |
| 6285 if (instr->kind() == Token::kNE_STRICT || | |
| 6286 instr->kind() == Token::kNE) { | |
| 6287 result = !result; | |
| 6288 } | |
| 6289 SetValue(instr, Smi::Handle( | |
| 6290 Smi::New(result ? instr->if_true() : instr->if_false()))); | |
| 6291 } else { | |
| 6292 SetValue(instr, non_constant_); | |
| 6293 } | |
| 6294 } else if (IsConstant(left) && IsConstant(right)) { | |
| 6295 bool result = (left.raw() == right.raw()); | |
| 6296 if (instr->kind() == Token::kNE_STRICT || | |
| 6297 instr->kind() == Token::kNE) { | |
| 6298 result = !result; | |
| 6299 } | |
| 6300 SetValue(instr, Smi::Handle( | |
| 6301 Smi::New(result ? instr->if_true() : instr->if_false()))); | |
| 6302 } | 6287 } |
| 6303 } | 6288 } |
| 6304 | 6289 |
| 6305 | 6290 |
| 6306 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 6291 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
| 6307 const Object& left = instr->left()->definition()->constant_value(); | 6292 const Object& left = instr->left()->definition()->constant_value(); |
| 6308 const Object& right = instr->right()->definition()->constant_value(); | 6293 const Object& right = instr->right()->definition()->constant_value(); |
| 6309 | 6294 |
| 6310 if (instr->left()->definition() == instr->right()->definition()) { | 6295 if (instr->left()->definition() == instr->right()->definition()) { |
| 6311 // Fold x === x, and x !== x to true/false. | 6296 // Fold x === x, and x !== x to true/false. |
| (...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7355 new JoinEntryInstr(target->block_id(), target->try_index()); | 7340 new JoinEntryInstr(target->block_id(), target->try_index()); |
| 7356 join->InheritDeoptTarget(target); | 7341 join->InheritDeoptTarget(target); |
| 7357 join->LinkTo(target->next()); | 7342 join->LinkTo(target->next()); |
| 7358 join->set_last_instruction(target->last_instruction()); | 7343 join->set_last_instruction(target->last_instruction()); |
| 7359 target->UnuseAllInputs(); | 7344 target->UnuseAllInputs(); |
| 7360 return join; | 7345 return join; |
| 7361 } | 7346 } |
| 7362 | 7347 |
| 7363 | 7348 |
| 7364 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, | 7349 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, |
| 7365 Value* left, | 7350 Value* new_left, |
| 7366 Value* right) { | 7351 Value* new_right) { |
| 7367 ComparisonInstr* comparison = branch->comparison(); | 7352 ComparisonInstr* comparison = branch->comparison(); |
| 7368 ComparisonInstr* new_comparison = NULL; | 7353 ComparisonInstr* new_comparison = |
| 7369 if (comparison->IsStrictCompare()) { | 7354 comparison->CopyWithNewOperands(new_left, new_right); |
| 7370 new_comparison = new StrictCompareInstr(comparison->token_pos(), | |
| 7371 comparison->kind(), | |
| 7372 left, | |
| 7373 right); | |
| 7374 } else if (comparison->IsEqualityCompare()) { | |
| 7375 EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare(); | |
| 7376 EqualityCompareInstr* new_equality_compare = | |
| 7377 new EqualityCompareInstr(equality_compare->token_pos(), | |
| 7378 comparison->kind(), | |
| 7379 left, | |
| 7380 right, | |
| 7381 equality_compare->operation_cid(), | |
| 7382 equality_compare->deopt_id()); | |
| 7383 new_comparison = new_equality_compare; | |
| 7384 } else { | |
| 7385 ASSERT(comparison->IsRelationalOp()); | |
| 7386 RelationalOpInstr* relational_op = comparison->AsRelationalOp(); | |
| 7387 RelationalOpInstr* new_relational_op = | |
| 7388 new RelationalOpInstr(relational_op->token_pos(), | |
| 7389 comparison->kind(), | |
| 7390 left, | |
| 7391 right, | |
| 7392 relational_op->operation_cid(), | |
| 7393 relational_op->deopt_id()); | |
| 7394 new_comparison = new_relational_op; | |
| 7395 } | |
| 7396 return new BranchInstr(new_comparison, branch->is_checked()); | 7355 return new BranchInstr(new_comparison, branch->is_checked()); |
| 7397 } | 7356 } |
| 7398 | 7357 |
| 7399 | 7358 |
| 7400 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { | 7359 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { |
| 7401 // Optimize some branches that test the value of a phi. When it is safe | 7360 // Optimize some branches that test the value of a phi. When it is safe |
| 7402 // to do so, push the branch to each of the predecessor blocks. This is | 7361 // to do so, push the branch to each of the predecessor blocks. This is |
| 7403 // an optimization when (a) it can avoid materializing a boolean object at | 7362 // an optimization when (a) it can avoid materializing a boolean object at |
| 7404 // the phi only to test its value, and (b) it can expose opportunities for | 7363 // the phi only to test its value, and (b) it can expose opportunities for |
| 7405 // constant propagation and unreachable code elimination. This | 7364 // constant propagation and unreachable code elimination. This |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7597 BranchInstr* branch = pred->last_instruction()->AsBranch(); | 7556 BranchInstr* branch = pred->last_instruction()->AsBranch(); |
| 7598 ComparisonInstr* comparison = branch->comparison(); | 7557 ComparisonInstr* comparison = branch->comparison(); |
| 7599 | 7558 |
| 7600 // Check if the platform supports efficient branchless IfThenElseInstr | 7559 // Check if the platform supports efficient branchless IfThenElseInstr |
| 7601 // for the given combination of comparison and values flowing from | 7560 // for the given combination of comparison and values flowing from |
| 7602 // false and true paths. | 7561 // false and true paths. |
| 7603 if (IfThenElseInstr::Supports(comparison, v1, v2)) { | 7562 if (IfThenElseInstr::Supports(comparison, v1, v2)) { |
| 7604 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2; | 7563 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2; |
| 7605 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2; | 7564 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2; |
| 7606 | 7565 |
| 7566 ComparisonInstr* new_comparison = |
| 7567 comparison->CopyWithNewOperands(comparison->left()->Copy(), |
| 7568 comparison->right()->Copy()); |
| 7607 IfThenElseInstr* if_then_else = new IfThenElseInstr( | 7569 IfThenElseInstr* if_then_else = new IfThenElseInstr( |
| 7608 comparison->kind(), | 7570 new_comparison, |
| 7609 comparison->InputAt(0)->Copy(), | |
| 7610 comparison->InputAt(1)->Copy(), | |
| 7611 if_true->Copy(), | 7571 if_true->Copy(), |
| 7612 if_false->Copy()); | 7572 if_false->Copy()); |
| 7613 flow_graph->InsertBefore(branch, | 7573 flow_graph->InsertBefore(branch, |
| 7614 if_then_else, | 7574 if_then_else, |
| 7615 NULL, | 7575 NULL, |
| 7616 Definition::kValue); | 7576 Definition::kValue); |
| 7617 | 7577 |
| 7618 phi->ReplaceUsesWith(if_then_else); | 7578 phi->ReplaceUsesWith(if_then_else); |
| 7619 | 7579 |
| 7620 // Connect IfThenElseInstr to the first instruction in the merge block | 7580 // Connect IfThenElseInstr to the first instruction in the merge block |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7912 } | 7872 } |
| 7913 | 7873 |
| 7914 // Insert materializations at environment uses. | 7874 // Insert materializations at environment uses. |
| 7915 for (intptr_t i = 0; i < exits.length(); i++) { | 7875 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7916 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7876 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7917 } | 7877 } |
| 7918 } | 7878 } |
| 7919 | 7879 |
| 7920 | 7880 |
| 7921 } // namespace dart | 7881 } // namespace dart |
| OLD | NEW |