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

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

Issue 562203005: Inline toDouble calls on mints (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/assembler_ia32_test.cc ('k') | runtime/vm/flow_graph_type_propagator.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/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 static bool ShouldInlineSimd() { 56 static bool ShouldInlineSimd() {
57 return FlowGraphCompiler::SupportsUnboxedSimd128(); 57 return FlowGraphCompiler::SupportsUnboxedSimd128();
58 } 58 }
59 59
60 60
61 static bool CanUnboxDouble() { 61 static bool CanUnboxDouble() {
62 return FlowGraphCompiler::SupportsUnboxedDoubles(); 62 return FlowGraphCompiler::SupportsUnboxedDoubles();
63 } 63 }
64 64
65 65
66 static bool CanConvertUnboxedMintToDouble() {
67 #if defined(TARGET_ARCH_IA32)
68 return true;
69 #else
70 // ARM does not have a short instruction sequence for converting int64 to
71 // double.
72 // TODO(johnmccutchan): Investigate possibility on MIPS once
73 // mints are implemented there.
74 return false;
75 #endif
76 }
77
66 // Optimize instance calls using ICData. 78 // Optimize instance calls using ICData.
67 void FlowGraphOptimizer::ApplyICData() { 79 void FlowGraphOptimizer::ApplyICData() {
68 VisitBlocks(); 80 VisitBlocks();
69 } 81 }
70 82
71 83
72 // Optimize instance calls using cid. This is called after optimizer 84 // Optimize instance calls using cid. This is called after optimizer
73 // converted instance calls to instructions. Any remaining 85 // converted instance calls to instructions. Any remaining
74 // instance calls are either megamorphic calls, cannot be optimized or 86 // instance calls are either megamorphic calls, cannot be optimized or
75 // have no runtime type feedback collected. 87 // have no runtime type feedback collected.
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 642 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
631 converted = new UnboxInt32Instr(use->CopyWithType(), deopt_id); 643 converted = new UnboxInt32Instr(use->CopyWithType(), deopt_id);
632 } else if ((from == kUnboxedInt32) && (to == kTagged)) { 644 } else if ((from == kUnboxedInt32) && (to == kTagged)) {
633 converted = new BoxInt32Instr(use->CopyWithType()); 645 converted = new BoxInt32Instr(use->CopyWithType());
634 } else if ((from == kTagged) && (to == kUnboxedUint32)) { 646 } else if ((from == kTagged) && (to == kUnboxedUint32)) {
635 const intptr_t deopt_id = (deopt_target != NULL) ? 647 const intptr_t deopt_id = (deopt_target != NULL) ?
636 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 648 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
637 converted = new UnboxUint32Instr(use->CopyWithType(), deopt_id); 649 converted = new UnboxUint32Instr(use->CopyWithType(), deopt_id);
638 } else if (from == kUnboxedMint && to == kUnboxedDouble) { 650 } else if (from == kUnboxedMint && to == kUnboxedDouble) {
639 ASSERT(CanUnboxDouble()); 651 ASSERT(CanUnboxDouble());
640 // Convert by boxing/unboxing.
641 // TODO(fschneider): Implement direct unboxed mint-to-double conversion.
642 BoxIntegerInstr* boxed =
643 new(I) BoxIntegerInstr(use->CopyWithType());
644 use->BindTo(boxed);
645 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
646
647 const intptr_t deopt_id = (deopt_target != NULL) ? 652 const intptr_t deopt_id = (deopt_target != NULL) ?
648 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 653 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
649 converted = new(I) UnboxDoubleInstr(new(I) Value(boxed), deopt_id); 654 if (CanConvertUnboxedMintToDouble()) {
650 655 // Fast path.
656 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id);
657 } else {
658 // Slow path.
659 BoxIntegerInstr* boxed = new(I) BoxIntegerInstr(use->CopyWithType());
660 use->BindTo(boxed);
661 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
662 converted = new(I) UnboxDoubleInstr(new(I) Value(boxed), deopt_id);
663 }
651 } else if ((from == kUnboxedDouble) && (to == kTagged)) { 664 } else if ((from == kUnboxedDouble) && (to == kTagged)) {
652 ASSERT(CanUnboxDouble()); 665 ASSERT(CanUnboxDouble());
653 converted = new(I) BoxDoubleInstr(use->CopyWithType()); 666 converted = new(I) BoxDoubleInstr(use->CopyWithType());
654
655 } else if ((from == kTagged) && (to == kUnboxedDouble)) { 667 } else if ((from == kTagged) && (to == kUnboxedDouble)) {
656 ASSERT(CanUnboxDouble()); 668 ASSERT(CanUnboxDouble());
657 ASSERT((deopt_target != NULL) || 669 ASSERT((deopt_target != NULL) ||
658 (use->Type()->ToCid() == kDoubleCid)); 670 (use->Type()->ToCid() == kDoubleCid));
659 const intptr_t deopt_id = (deopt_target != NULL) ? 671 const intptr_t deopt_id = (deopt_target != NULL) ?
660 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 672 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
661 ConstantInstr* constant = use->definition()->AsConstant(); 673 ConstantInstr* constant = use->definition()->AsConstant();
662 if ((constant != NULL) && constant->value().IsSmi()) { 674 if ((constant != NULL) && constant->value().IsSmi()) {
663 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); 675 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue();
664 const Double& dbl_obj = 676 const Double& dbl_obj =
(...skipping 2379 matching lines...) Expand 10 before | Expand all | Expand 10 after
3044 call->deopt_id(), 3056 call->deopt_id(),
3045 call->token_pos()); 3057 call->token_pos());
3046 ReplaceCall(call, store_op); 3058 ReplaceCall(call, store_op);
3047 return true; 3059 return true;
3048 } 3060 }
3049 return false; 3061 return false;
3050 } 3062 }
3051 3063
3052 if (CanUnboxDouble() && 3064 if (CanUnboxDouble() &&
3053 (recognized_kind == MethodRecognizer::kIntegerToDouble) && 3065 (recognized_kind == MethodRecognizer::kIntegerToDouble) &&
3054 (ic_data.NumberOfChecks() == 1) && 3066 (ic_data.NumberOfChecks() == 1)) {
3055 (class_ids[0] == kSmiCid)) { 3067 if (class_ids[0] == kSmiCid) {
3056 AddReceiverCheck(call); 3068 AddReceiverCheck(call);
3057 ReplaceCall(call, 3069 ReplaceCall(call,
3058 new(I) SmiToDoubleInstr( 3070 new(I) SmiToDoubleInstr(
3059 new(I) Value(call->ArgumentAt(0)), 3071 new(I) Value(call->ArgumentAt(0)),
3060 call->token_pos())); 3072 call->token_pos()));
3061 return true; 3073 return true;
3074 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) {
3075 AddReceiverCheck(call);
3076 ReplaceCall(call,
3077 new(I) MintToDoubleInstr(new(I) Value(call->ArgumentAt(0)),
3078 call->deopt_id()));
3079 return true;
3080 }
3062 } 3081 }
3063 3082
3064 if (class_ids[0] == kDoubleCid) { 3083 if (class_ids[0] == kDoubleCid) {
3065 if (!CanUnboxDouble()) { 3084 if (!CanUnboxDouble()) {
3066 return false; 3085 return false;
3067 } 3086 }
3068 switch (recognized_kind) { 3087 switch (recognized_kind) {
3069 case MethodRecognizer::kDoubleToInteger: { 3088 case MethodRecognizer::kDoubleToInteger: {
3070 AddReceiverCheck(call); 3089 AddReceiverCheck(call);
3071 ASSERT(call->HasICData()); 3090 ASSERT(call->HasICData());
(...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after
4497 } 4516 }
4498 InvokeMathCFunctionInstr* invoke = 4517 InvokeMathCFunctionInstr* invoke =
4499 new(I) InvokeMathCFunctionInstr(args, 4518 new(I) InvokeMathCFunctionInstr(args,
4500 call->deopt_id(), 4519 call->deopt_id(),
4501 recognized_kind, 4520 recognized_kind,
4502 call->token_pos()); 4521 call->token_pos());
4503 ReplaceCall(call, invoke); 4522 ReplaceCall(call, invoke);
4504 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) { 4523 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) {
4505 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { 4524 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4506 const ICData& ic_data = *call->ic_data(); 4525 const ICData& ic_data = *call->ic_data();
4507 if (CanUnboxDouble() && ArgIsAlways(kSmiCid, ic_data, 0)) { 4526 if (CanUnboxDouble()) {
4508 Definition* arg = call->ArgumentAt(0); 4527 if (ArgIsAlways(kSmiCid, ic_data, 1)) {
4509 InsertBefore(call, 4528 Definition* arg = call->ArgumentAt(1);
4510 new(I) CheckSmiInstr( 4529 AddCheckSmi(arg, call->deopt_id(), call->env(), call);
4511 new(I) Value(arg), 4530 ReplaceCall(call,
4512 call->deopt_id(), 4531 new(I) SmiToDoubleInstr(new(I) Value(arg),
4513 call->token_pos()), 4532 call->token_pos()));
4514 call->env(), 4533 } else if (ArgIsAlways(kMintCid, ic_data, 1) &&
4515 FlowGraph::kEffect); 4534 CanConvertUnboxedMintToDouble()) {
4516 ReplaceCall(call, 4535 Definition* arg = call->ArgumentAt(1);
4517 new(I) SmiToDoubleInstr(new(I) Value(arg), 4536 ReplaceCall(call,
4518 call->token_pos())); 4537 new(I) MintToDoubleInstr(new(I) Value(arg),
4538 call->deopt_id()));
4539 }
4519 } 4540 }
4520 } 4541 }
4521 } else if (call->function().IsFactory()) { 4542 } else if (call->function().IsFactory()) {
4522 const Class& function_class = 4543 const Class& function_class =
4523 Class::Handle(I, call->function().Owner()); 4544 Class::Handle(I, call->function().Owner());
4524 if ((function_class.library() == Library::CoreLibrary()) || 4545 if ((function_class.library() == Library::CoreLibrary()) ||
4525 (function_class.library() == Library::TypedDataLibrary())) { 4546 (function_class.library() == Library::TypedDataLibrary())) {
4526 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); 4547 intptr_t cid = FactoryRecognizer::ResultCid(call->function());
4527 switch (cid) { 4548 switch (cid) {
4528 case kArrayCid: { 4549 case kArrayCid: {
(...skipping 3888 matching lines...) Expand 10 before | Expand all | Expand 10 after
8417 const Object& value = instr->value()->definition()->constant_value(); 8438 const Object& value = instr->value()->definition()->constant_value();
8418 if (IsConstant(value) && value.IsInteger()) { 8439 if (IsConstant(value) && value.IsInteger()) {
8419 SetValue(instr, Double::Handle(I, 8440 SetValue(instr, Double::Handle(I,
8420 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); 8441 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld)));
8421 } else if (IsNonConstant(value)) { 8442 } else if (IsNonConstant(value)) {
8422 SetValue(instr, non_constant_); 8443 SetValue(instr, non_constant_);
8423 } 8444 }
8424 } 8445 }
8425 8446
8426 8447
8448 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) {
8449 const Object& value = instr->value()->definition()->constant_value();
8450 if (IsConstant(value) && value.IsInteger()) {
8451 SetValue(instr, Double::Handle(I,
8452 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld)));
8453 } else if (IsNonConstant(value)) {
8454 SetValue(instr, non_constant_);
8455 }
8456 }
8457
8458
8427 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { 8459 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) {
8428 const Object& value = instr->value()->definition()->constant_value(); 8460 const Object& value = instr->value()->definition()->constant_value();
8429 if (IsConstant(value) && value.IsInteger()) { 8461 if (IsConstant(value) && value.IsInteger()) {
8430 SetValue(instr, Double::Handle(I, 8462 SetValue(instr, Double::Handle(I,
8431 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); 8463 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld)));
8432 } else if (IsNonConstant(value)) { 8464 } else if (IsNonConstant(value)) {
8433 SetValue(instr, non_constant_); 8465 SetValue(instr, non_constant_);
8434 } 8466 }
8435 } 8467 }
8436 8468
(...skipping 1647 matching lines...) Expand 10 before | Expand all | Expand 10 after
10084 10116
10085 // Insert materializations at environment uses. 10117 // Insert materializations at environment uses.
10086 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 10118 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
10087 CreateMaterializationAt( 10119 CreateMaterializationAt(
10088 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); 10120 exits_collector_.exits()[i], alloc, alloc->cls(), *slots);
10089 } 10121 }
10090 } 10122 }
10091 10123
10092 10124
10093 } // namespace dart 10125 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/assembler_ia32_test.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698