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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 1670113004: VM: Optimized calls to asin, acos, tan. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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 unified diff | Download patch
« no previous file with comments | « no previous file | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 4479 matching lines...) Expand 10 before | Expand all | Expand 10 after
4490 case MethodRecognizer::kMathCos: 4490 case MethodRecognizer::kMathCos:
4491 unary_kind = MathUnaryInstr::kCos; 4491 unary_kind = MathUnaryInstr::kCos;
4492 break; 4492 break;
4493 default: 4493 default:
4494 unary_kind = MathUnaryInstr::kIllegal; 4494 unary_kind = MathUnaryInstr::kIllegal;
4495 break; 4495 break;
4496 } 4496 }
4497 if (unary_kind != MathUnaryInstr::kIllegal) { 4497 if (unary_kind != MathUnaryInstr::kIllegal) {
4498 if (FLAG_precompilation) { 4498 if (FLAG_precompilation) {
4499 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well. 4499 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well.
4500 } else {
4501 MathUnaryInstr* math_unary =
4502 new(Z) MathUnaryInstr(unary_kind,
4503 new(Z) Value(call->ArgumentAt(0)),
4504 call->deopt_id());
4505 ReplaceCall(call, math_unary);
4506 }
4507 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) ||
4508 (recognized_kind == MethodRecognizer::kFloat32x4Splat) ||
4509 (recognized_kind == MethodRecognizer::kFloat32x4Constructor) ||
4510 (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) {
4511 TryInlineFloat32x4Constructor(call, recognized_kind);
4512 } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) ||
4513 (recognized_kind == MethodRecognizer::kFloat64x2Zero) ||
4514 (recognized_kind == MethodRecognizer::kFloat64x2Splat) ||
4515 (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) {
4516 TryInlineFloat64x2Constructor(call, recognized_kind);
4517 } else if ((recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) ||
4518 (recognized_kind == MethodRecognizer::kInt32x4Constructor)) {
4519 TryInlineInt32x4Constructor(call, recognized_kind);
4520 } else if (recognized_kind == MethodRecognizer::kObjectConstructor) {
4521 // Remove the original push arguments.
4522 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
4523 PushArgumentInstr* push = call->PushArgumentAt(i);
4524 push->ReplaceUsesWith(push->value()->definition());
4525 push->RemoveFromGraph();
4526 }
4527 // Manually replace call with global null constant. ReplaceCall can't
4528 // be used for definitions that are already in the graph.
4529 call->ReplaceUsesWith(flow_graph_->constant_null());
4530 ASSERT(current_iterator()->Current() == call);
4531 current_iterator()->RemoveCurrentFromGraph();;
4532 } else if ((recognized_kind == MethodRecognizer::kMathMin) ||
4533 (recognized_kind == MethodRecognizer::kMathMax)) {
4534 // We can handle only monomorphic min/max call sites with both arguments
4535 // being either doubles or smis.
4536 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4537 const ICData& ic_data = *call->ic_data();
4538 intptr_t result_cid = kIllegalCid;
4539 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) {
4540 result_cid = kDoubleCid;
4541 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
4542 result_cid = kSmiCid;
4543 }
4544 if (result_cid != kIllegalCid) {
4545 MathMinMaxInstr* min_max = new(Z) MathMinMaxInstr(
4546 recognized_kind,
4547 new(Z) Value(call->ArgumentAt(0)),
4548 new(Z) Value(call->ArgumentAt(1)),
4549 call->deopt_id(),
4550 result_cid);
4551 const ICData& unary_checks =
4552 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks());
4553 AddCheckClass(min_max->left()->definition(),
4554 unary_checks,
4555 call->deopt_id(),
4556 call->env(),
4557 call);
4558 AddCheckClass(min_max->right()->definition(),
4559 unary_checks,
4560 call->deopt_id(),
4561 call->env(),
4562 call);
4563 ReplaceCall(call, min_max);
4564 }
4565 }
4566 } else if ((recognized_kind == MethodRecognizer::kMathDoublePow) ||
4567 (recognized_kind == MethodRecognizer::kMathAtan) ||
4568 (recognized_kind == MethodRecognizer::kMathAtan2)) {
4569 if (FLAG_precompilation) {
4570 // No UnboxDouble instructons allowed.
4571 return; 4500 return;
4572 } 4501 }
4573 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble 4502 MathUnaryInstr* math_unary =
4574 // instructions contain type checks and conversions to double. 4503 new(Z) MathUnaryInstr(unary_kind,
4575 ZoneGrowableArray<Value*>* args = 4504 new(Z) Value(call->ArgumentAt(0)),
4576 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); 4505 call->deopt_id());
4577 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 4506 ReplaceCall(call, math_unary);
4578 args->Add(new(Z) Value(call->ArgumentAt(i))); 4507 return;
4508 }
4509 switch (recognized_kind) {
4510 case MethodRecognizer::kFloat32x4Zero:
4511 case MethodRecognizer::kFloat32x4Splat:
4512 case MethodRecognizer::kFloat32x4Constructor:
4513 case MethodRecognizer::kFloat32x4FromFloat64x2:
4514 TryInlineFloat32x4Constructor(call, recognized_kind);
4515 break;
4516 case MethodRecognizer::kFloat64x2Constructor:
4517 case MethodRecognizer::kFloat64x2Zero:
4518 case MethodRecognizer::kFloat64x2Splat:
4519 case MethodRecognizer::kFloat64x2FromFloat32x4:
4520 TryInlineFloat64x2Constructor(call, recognized_kind);
4521 break;
4522 case MethodRecognizer::kInt32x4BoolConstructor:
4523 case MethodRecognizer::kInt32x4Constructor:
4524 TryInlineInt32x4Constructor(call, recognized_kind);
4525 break;
4526 case MethodRecognizer::kObjectConstructor: {
4527 // Remove the original push arguments.
4528 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
4529 PushArgumentInstr* push = call->PushArgumentAt(i);
4530 push->ReplaceUsesWith(push->value()->definition());
4531 push->RemoveFromGraph();
4532 }
4533 // Manually replace call with global null constant. ReplaceCall can't
4534 // be used for definitions that are already in the graph.
4535 call->ReplaceUsesWith(flow_graph_->constant_null());
4536 ASSERT(current_iterator()->Current() == call);
4537 current_iterator()->RemoveCurrentFromGraph();
4538 break;
4579 } 4539 }
4580 InvokeMathCFunctionInstr* invoke = 4540 case MethodRecognizer::kMathMin:
4581 new(Z) InvokeMathCFunctionInstr(args, 4541 case MethodRecognizer::kMathMax: {
4582 call->deopt_id(), 4542 // We can handle only monomorphic min/max call sites with both arguments
4583 recognized_kind, 4543 // being either doubles or smis.
4584 call->token_pos()); 4544 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4585 ReplaceCall(call, invoke); 4545 const ICData& ic_data = *call->ic_data();
4586 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) { 4546 intptr_t result_cid = kIllegalCid;
4587 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { 4547 if (ICDataHasReceiverArgumentClassIds(ic_data,
4588 const ICData& ic_data = *call->ic_data(); 4548 kDoubleCid, kDoubleCid)) {
4589 if (CanUnboxDouble()) { 4549 result_cid = kDoubleCid;
4590 if (ArgIsAlways(kSmiCid, ic_data, 1)) { 4550 } else if (ICDataHasReceiverArgumentClassIds(ic_data,
4591 Definition* arg = call->ArgumentAt(1); 4551 kSmiCid, kSmiCid)) {
4592 AddCheckSmi(arg, call->deopt_id(), call->env(), call); 4552 result_cid = kSmiCid;
4593 ReplaceCall(call, 4553 }
4594 new(Z) SmiToDoubleInstr(new(Z) Value(arg), 4554 if (result_cid != kIllegalCid) {
4595 call->token_pos())); 4555 MathMinMaxInstr* min_max = new(Z) MathMinMaxInstr(
4596 } else if (ArgIsAlways(kMintCid, ic_data, 1) && 4556 recognized_kind,
4597 CanConvertUnboxedMintToDouble()) { 4557 new(Z) Value(call->ArgumentAt(0)),
4598 Definition* arg = call->ArgumentAt(1); 4558 new(Z) Value(call->ArgumentAt(1)),
4599 ReplaceCall(call, 4559 call->deopt_id(),
4600 new(Z) MintToDoubleInstr(new(Z) Value(arg), 4560 result_cid);
4601 call->deopt_id())); 4561 const ICData& unary_checks =
4562 ICData::ZoneHandle(Z, ic_data.AsUnaryClassChecks());
4563 AddCheckClass(min_max->left()->definition(),
4564 unary_checks,
4565 call->deopt_id(),
4566 call->env(),
4567 call);
4568 AddCheckClass(min_max->right()->definition(),
4569 unary_checks,
4570 call->deopt_id(),
4571 call->env(),
4572 call);
4573 ReplaceCall(call, min_max);
4574 }
4575 }
4576 break;
4577 }
4578 case MethodRecognizer::kMathDoublePow:
4579 case MethodRecognizer::kMathTan:
4580 case MethodRecognizer::kMathAsin:
4581 case MethodRecognizer::kMathAcos:
4582 case MethodRecognizer::kMathAtan:
4583 case MethodRecognizer::kMathAtan2: {
4584 if (FLAG_precompilation) {
4585 // No UnboxDouble instructons allowed.
4586 return;
4587 }
4588 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble
4589 // instructions contain type checks and conversions to double.
4590 ZoneGrowableArray<Value*>* args =
4591 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
4592 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
4593 args->Add(new(Z) Value(call->ArgumentAt(i)));
4594 }
4595 InvokeMathCFunctionInstr* invoke =
4596 new(Z) InvokeMathCFunctionInstr(args,
4597 call->deopt_id(),
4598 recognized_kind,
4599 call->token_pos());
4600 ReplaceCall(call, invoke);
4601 break;
4602 }
4603 case MethodRecognizer::kDoubleFromInteger: {
4604 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4605 const ICData& ic_data = *call->ic_data();
4606 if (CanUnboxDouble()) {
4607 if (ArgIsAlways(kSmiCid, ic_data, 1)) {
4608 Definition* arg = call->ArgumentAt(1);
4609 AddCheckSmi(arg, call->deopt_id(), call->env(), call);
4610 ReplaceCall(call,
4611 new(Z) SmiToDoubleInstr(new(Z) Value(arg),
4612 call->token_pos()));
4613 } else if (ArgIsAlways(kMintCid, ic_data, 1) &&
4614 CanConvertUnboxedMintToDouble()) {
4615 Definition* arg = call->ArgumentAt(1);
4616 ReplaceCall(call,
4617 new(Z) MintToDoubleInstr(new(Z) Value(arg),
4618 call->deopt_id()));
4619 }
4620 }
4621 }
4622 break;
4623 }
4624 default: {
4625 if (call->function().IsFactory()) {
4626 const Class& function_class =
4627 Class::Handle(Z, call->function().Owner());
4628 if ((function_class.library() == Library::CoreLibrary()) ||
4629 (function_class.library() == Library::TypedDataLibrary())) {
4630 intptr_t cid = FactoryRecognizer::ResultCid(call->function());
4631 switch (cid) {
4632 case kArrayCid: {
4633 Value* type = new(Z) Value(call->ArgumentAt(0));
4634 Value* num_elements = new(Z) Value(call->ArgumentAt(1));
4635 if (num_elements->BindsToConstant() &&
4636 num_elements->BoundConstant().IsSmi()) {
4637 intptr_t length =
4638 Smi::Cast(num_elements->BoundConstant()).Value();
4639 if (length >= 0 && length <= Array::kMaxElements) {
4640 CreateArrayInstr* create_array =
4641 new(Z) CreateArrayInstr(
4642 call->token_pos(), type, num_elements);
4643 ReplaceCall(call, create_array);
4644 }
4645 }
4646 }
4647 default:
4648 break;
4649 }
4602 } 4650 }
4603 } 4651 }
4604 } 4652 }
4605 } else if (call->function().IsFactory()) {
4606 const Class& function_class =
4607 Class::Handle(Z, call->function().Owner());
4608 if ((function_class.library() == Library::CoreLibrary()) ||
4609 (function_class.library() == Library::TypedDataLibrary())) {
4610 intptr_t cid = FactoryRecognizer::ResultCid(call->function());
4611 switch (cid) {
4612 case kArrayCid: {
4613 Value* type = new(Z) Value(call->ArgumentAt(0));
4614 Value* num_elements = new(Z) Value(call->ArgumentAt(1));
4615 if (num_elements->BindsToConstant() &&
4616 num_elements->BoundConstant().IsSmi()) {
4617 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
4618 if (length >= 0 && length <= Array::kMaxElements) {
4619 CreateArrayInstr* create_array =
4620 new(Z) CreateArrayInstr(
4621 call->token_pos(), type, num_elements);
4622 ReplaceCall(call, create_array);
4623 }
4624 }
4625 }
4626 default:
4627 break;
4628 }
4629 }
4630 } 4653 }
4631 } 4654 }
4632 4655
4633 4656
4634 void FlowGraphOptimizer::VisitStoreInstanceField( 4657 void FlowGraphOptimizer::VisitStoreInstanceField(
4635 StoreInstanceFieldInstr* instr) { 4658 StoreInstanceFieldInstr* instr) {
4636 if (instr->IsUnboxedStore()) { 4659 if (instr->IsUnboxedStore()) {
4637 ASSERT(instr->is_potential_unboxed_initialization_); 4660 ASSERT(instr->is_potential_unboxed_initialization_);
4638 // Determine if this field should be unboxed based on the usage of getter 4661 // Determine if this field should be unboxed based on the usage of getter
4639 // and setter functions: The heuristic requires that the setter has a 4662 // and setter functions: The heuristic requires that the setter has a
(...skipping 4208 matching lines...) Expand 10 before | Expand all | Expand 10 after
8848 8871
8849 // Insert materializations at environment uses. 8872 // Insert materializations at environment uses.
8850 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 8873 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
8851 CreateMaterializationAt( 8874 CreateMaterializationAt(
8852 exits_collector_.exits()[i], alloc, *slots); 8875 exits_collector_.exits()[i], alloc, *slots);
8853 } 8876 }
8854 } 8877 }
8855 8878
8856 8879
8857 } // namespace dart 8880 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698