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

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

Issue 2273943002: VM: More refactoring of recognized methods inlining. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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 | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/intermediate_language.h » ('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_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/aot_optimizer.h" 7 #include "vm/aot_optimizer.h"
8 #include "vm/block_scheduler.h" 8 #include "vm/block_scheduler.h"
9 #include "vm/branch_optimizer.h" 9 #include "vm/branch_optimizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 2334 matching lines...) Expand 10 before | Expand all | Expand 10 after
2345 FlowGraph::kEffect); 2345 FlowGraph::kEffect);
2346 return true; 2346 return true;
2347 } 2347 }
2348 2348
2349 2349
2350 static bool InlineDoubleOp(FlowGraph* flow_graph, 2350 static bool InlineDoubleOp(FlowGraph* flow_graph,
2351 Token::Kind op_kind, 2351 Token::Kind op_kind,
2352 Instruction* call, 2352 Instruction* call,
2353 TargetEntryInstr** entry, 2353 TargetEntryInstr** entry,
2354 Definition** last) { 2354 Definition** last) {
2355 if (!CanUnboxDouble()) {
2356 return false;
2357 }
2355 Definition* left = call->ArgumentAt(0); 2358 Definition* left = call->ArgumentAt(0);
2356 Definition* right = call->ArgumentAt(1); 2359 Definition* right = call->ArgumentAt(1);
2357 2360
2358 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), 2361 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
2359 call->GetBlock()->try_index()); 2362 call->GetBlock()->try_index());
2360 (*entry)->InheritDeoptTarget(Z, call); 2363 (*entry)->InheritDeoptTarget(Z, call);
2361 // Arguments are checked. No need for class check. 2364 // Arguments are checked. No need for class check.
2362 BinaryDoubleOpInstr* double_bin_op = 2365 BinaryDoubleOpInstr* double_bin_op =
2363 new(Z) BinaryDoubleOpInstr(op_kind, 2366 new(Z) BinaryDoubleOpInstr(op_kind,
2364 new(Z) Value(left), 2367 new(Z) Value(left),
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2414 new(Z) Value(value), 2417 new(Z) Value(value),
2415 store_barrier_type, 2418 store_barrier_type,
2416 call->token_pos()); 2419 call->token_pos());
2417 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect); 2420 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect);
2418 *last = store; 2421 *last = store;
2419 2422
2420 return true; 2423 return true;
2421 } 2424 }
2422 2425
2423 2426
2424 static intptr_t PrepareInlineByteArrayBaseOp( 2427 static void PrepareInlineByteArrayBaseOp(
2425 FlowGraph* flow_graph, 2428 FlowGraph* flow_graph,
2426 Instruction* call, 2429 Instruction* call,
2427 intptr_t array_cid, 2430 intptr_t array_cid,
2428 intptr_t view_cid, 2431 intptr_t view_cid,
2429 Definition** array, 2432 Definition** array,
2430 Definition* byte_index, 2433 Definition* byte_index,
2431 Instruction** cursor) { 2434 Instruction** cursor) {
2432 LoadFieldInstr* length = 2435 LoadFieldInstr* length =
2433 new(Z) LoadFieldInstr( 2436 new(Z) LoadFieldInstr(
2434 new(Z) Value(*array), 2437 new(Z) Value(*array),
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2492 if (RawObject::IsExternalTypedDataClassId(array_cid)) { 2495 if (RawObject::IsExternalTypedDataClassId(array_cid)) {
2493 LoadUntaggedInstr* elements = 2496 LoadUntaggedInstr* elements =
2494 new(Z) LoadUntaggedInstr(new(Z) Value(*array), 2497 new(Z) LoadUntaggedInstr(new(Z) Value(*array),
2495 ExternalTypedData::data_offset()); 2498 ExternalTypedData::data_offset());
2496 *cursor = flow_graph->AppendTo(*cursor, 2499 *cursor = flow_graph->AppendTo(*cursor,
2497 elements, 2500 elements,
2498 NULL, 2501 NULL,
2499 FlowGraph::kValue); 2502 FlowGraph::kValue);
2500 *array = elements; 2503 *array = elements;
2501 } 2504 }
2502 return array_cid;
2503 } 2505 }
2504 2506
2505 2507
2506 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, 2508 static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph,
2507 Instruction* call, 2509 Instruction* call,
2508 Definition* receiver, 2510 Definition* receiver,
2509 intptr_t array_cid, 2511 intptr_t array_cid,
2510 intptr_t view_cid, 2512 intptr_t view_cid,
2511 TargetEntryInstr** entry, 2513 TargetEntryInstr** entry,
2512 Definition** last) { 2514 Definition** last) {
2513 ASSERT(array_cid != kIllegalCid); 2515 ASSERT(array_cid != kIllegalCid);
2514 Definition* array = receiver; 2516 Definition* array = receiver;
2515 Definition* index = call->ArgumentAt(1); 2517 Definition* index = call->ArgumentAt(1);
2516 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), 2518 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
2517 call->GetBlock()->try_index()); 2519 call->GetBlock()->try_index());
2518 (*entry)->InheritDeoptTarget(Z, call); 2520 (*entry)->InheritDeoptTarget(Z, call);
2519 Instruction* cursor = *entry; 2521 Instruction* cursor = *entry;
2520 2522
2521 array_cid = PrepareInlineByteArrayBaseOp(flow_graph, 2523 PrepareInlineByteArrayBaseOp(flow_graph,
2522 call, 2524 call,
2523 array_cid, 2525 array_cid,
2524 view_cid, 2526 view_cid,
2525 &array, 2527 &array,
2526 index, 2528 index,
2527 &cursor); 2529 &cursor);
2528 2530
2529 intptr_t deopt_id = Thread::kNoDeoptId; 2531 intptr_t deopt_id = Thread::kNoDeoptId;
2530 if ((array_cid == kTypedDataInt32ArrayCid) || 2532 if ((array_cid == kTypedDataInt32ArrayCid) ||
2531 (array_cid == kTypedDataUint32ArrayCid)) { 2533 (array_cid == kTypedDataUint32ArrayCid)) {
2532 // Deoptimization may be needed if result does not always fit in a Smi. 2534 // Deoptimization may be needed if result does not always fit in a Smi.
2533 deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id(); 2535 deopt_id = (kSmiBits >= 32) ? Thread::kNoDeoptId : call->deopt_id();
2534 } 2536 }
2535 2537
2536 *last = new(Z) LoadIndexedInstr(new(Z) Value(array), 2538 *last = new(Z) LoadIndexedInstr(new(Z) Value(array),
2537 new(Z) Value(index), 2539 new(Z) Value(index),
(...skipping 27 matching lines...) Expand all
2565 TargetEntryInstr** entry, 2567 TargetEntryInstr** entry,
2566 Definition** last) { 2568 Definition** last) {
2567 ASSERT(array_cid != kIllegalCid); 2569 ASSERT(array_cid != kIllegalCid);
2568 Definition* array = receiver; 2570 Definition* array = receiver;
2569 Definition* index = call->ArgumentAt(1); 2571 Definition* index = call->ArgumentAt(1);
2570 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), 2572 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
2571 call->GetBlock()->try_index()); 2573 call->GetBlock()->try_index());
2572 (*entry)->InheritDeoptTarget(Z, call); 2574 (*entry)->InheritDeoptTarget(Z, call);
2573 Instruction* cursor = *entry; 2575 Instruction* cursor = *entry;
2574 2576
2575 array_cid = PrepareInlineByteArrayBaseOp(flow_graph, 2577 PrepareInlineByteArrayBaseOp(flow_graph,
2576 call, 2578 call,
2577 array_cid, 2579 array_cid,
2578 view_cid, 2580 view_cid,
2579 &array, 2581 &array,
2580 index, 2582 index,
2581 &cursor); 2583 &cursor);
2582 2584
2583 // Extract the instance call so we can use the function_name in the stored 2585 // Extract the instance call so we can use the function_name in the stored
2584 // value check ICData. 2586 // value check ICData.
2585 InstanceCallInstr* i_call = NULL; 2587 InstanceCallInstr* i_call = NULL;
2586 if (call->IsPolymorphicInstanceCall()) { 2588 if (call->IsPolymorphicInstanceCall()) {
2587 i_call = call->AsPolymorphicInstanceCall()->instance_call(); 2589 i_call = call->AsPolymorphicInstanceCall()->instance_call();
2588 } else { 2590 } else {
2589 ASSERT(call->IsInstanceCall()); 2591 ASSERT(call->IsInstanceCall());
2590 i_call = call->AsInstanceCall(); 2592 i_call = call->AsInstanceCall();
2591 } 2593 }
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
2867 flow_graph->InsertBefore(call, check, call->env(), FlowGraph::kEffect); 2869 flow_graph->InsertBefore(call, check, call->env(), FlowGraph::kEffect);
2868 } 2870 }
2869 2871
2870 // Remove the original push arguments. 2872 // Remove the original push arguments.
2871 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 2873 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2872 PushArgumentInstr* push = call->PushArgumentAt(i); 2874 PushArgumentInstr* push = call->PushArgumentAt(i);
2873 push->ReplaceUsesWith(push->value()->definition()); 2875 push->ReplaceUsesWith(push->value()->definition());
2874 push->RemoveFromGraph(); 2876 push->RemoveFromGraph();
2875 } 2877 }
2876 // Replace all uses of this definition with the result. 2878 // Replace all uses of this definition with the result.
2877 call->ReplaceUsesWith(last); 2879 if (call->HasUses()) {
2880 call->ReplaceUsesWith(last);
2881 }
2878 // Finally insert the sequence other definition in place of this one in the 2882 // Finally insert the sequence other definition in place of this one in the
2879 // graph. 2883 // graph.
2880 call->previous()->LinkTo(entry->next()); 2884 if (entry->next() != NULL) {
2885 call->previous()->LinkTo(entry->next());
2886 }
2881 entry->UnuseAllInputs(); // Entry block is not in the graph. 2887 entry->UnuseAllInputs(); // Entry block is not in the graph.
2882 last->LinkTo(call); 2888 if (last != NULL) {
2889 last->LinkTo(call);
2890 }
2883 // Remove through the iterator. 2891 // Remove through the iterator.
2884 ASSERT(iterator->Current() == call); 2892 ASSERT(iterator->Current() == call);
2885 iterator->RemoveCurrentFromGraph(); 2893 iterator->RemoveCurrentFromGraph();
2886 call->set_previous(NULL); 2894 call->set_previous(NULL);
2887 call->set_next(NULL); 2895 call->set_next(NULL);
2888 return true; 2896 return true;
2889 } 2897 }
2890 return false; 2898 return false;
2891 } 2899 }
2892 2900
(...skipping 12 matching lines...) Expand all
2905 call->token_pos(), 2913 call->token_pos(),
2906 *call->ic_data(), 2914 *call->ic_data(),
2907 &entry, &last)) { 2915 &entry, &last)) {
2908 // Remove the original push arguments. 2916 // Remove the original push arguments.
2909 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 2917 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2910 PushArgumentInstr* push = call->PushArgumentAt(i); 2918 PushArgumentInstr* push = call->PushArgumentAt(i);
2911 push->ReplaceUsesWith(push->value()->definition()); 2919 push->ReplaceUsesWith(push->value()->definition());
2912 push->RemoveFromGraph(); 2920 push->RemoveFromGraph();
2913 } 2921 }
2914 // Replace all uses of this definition with the result. 2922 // Replace all uses of this definition with the result.
2915 call->ReplaceUsesWith(last); 2923 if (call->HasUses()) {
2924 call->ReplaceUsesWith(last);
2925 }
2916 // Finally insert the sequence other definition in place of this one in the 2926 // Finally insert the sequence other definition in place of this one in the
2917 // graph. 2927 // graph.
2918 call->previous()->LinkTo(entry->next()); 2928 if (entry->next() != NULL) {
2929 call->previous()->LinkTo(entry->next());
2930 }
2919 entry->UnuseAllInputs(); // Entry block is not in the graph. 2931 entry->UnuseAllInputs(); // Entry block is not in the graph.
2920 last->LinkTo(call); 2932 if (last != NULL) {
2933 last->LinkTo(call);
2934 }
2921 // Remove through the iterator. 2935 // Remove through the iterator.
2922 ASSERT(iterator->Current() == call); 2936 ASSERT(iterator->Current() == call);
2923 iterator->RemoveCurrentFromGraph(); 2937 iterator->RemoveCurrentFromGraph();
2924 call->set_previous(NULL); 2938 call->set_previous(NULL);
2925 call->set_next(NULL); 2939 call->set_next(NULL);
2926 return true; 2940 return true;
2927 } 2941 }
2928 return false; 2942 return false;
2929 } 2943 }
2930 2944
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
3320 return false; 3334 return false;
3321 } 3335 }
3322 flow_graph->AppendTo(cursor, *last, 3336 flow_graph->AppendTo(cursor, *last,
3323 call->deopt_id() != Thread::kNoDeoptId ? 3337 call->deopt_id() != Thread::kNoDeoptId ?
3324 call->env() : NULL, 3338 call->env() : NULL,
3325 FlowGraph::kValue); 3339 FlowGraph::kValue);
3326 return true; 3340 return true;
3327 } 3341 }
3328 3342
3329 3343
3344 static bool InlineMathCFunction(FlowGraph* flow_graph,
3345 Instruction* call,
3346 MethodRecognizer::Kind kind,
3347 TargetEntryInstr** entry,
3348 Definition** last) {
3349 if (!CanUnboxDouble()) {
3350 return false;
3351 }
3352 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
3353 call->GetBlock()->try_index());
3354 (*entry)->InheritDeoptTarget(Z, call);
3355 Instruction* cursor = *entry;
3356
3357 switch (kind) {
3358 case MethodRecognizer::kMathSqrt: {
3359 *last = new(Z) MathUnaryInstr(MathUnaryInstr::kSqrt,
3360 new(Z) Value(call->ArgumentAt(0)),
3361 call->deopt_id());
3362 break;
3363 }
3364 default: {
3365 ZoneGrowableArray<Value*>* args =
3366 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
3367 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
3368 args->Add(new(Z) Value(call->ArgumentAt(i)));
3369 }
3370 *last = new(Z) InvokeMathCFunctionInstr(args,
3371 call->deopt_id(),
3372 kind,
3373 call->token_pos());
3374 break;
3375 }
3376 }
3377 flow_graph->AppendTo(cursor, *last,
3378 call->deopt_id() != Thread::kNoDeoptId ?
3379 call->env() : NULL,
3380 FlowGraph::kValue);
3381 return true;
3382 }
3383
3384
3330 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph, 3385 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
3331 intptr_t receiver_cid, 3386 intptr_t receiver_cid,
3332 const Function& target, 3387 const Function& target,
3333 Instruction* call, 3388 Definition* call,
3334 Definition* receiver, 3389 Definition* receiver,
3335 TokenPosition token_pos, 3390 TokenPosition token_pos,
3336 const ICData& ic_data, 3391 const ICData& ic_data,
3337 TargetEntryInstr** entry, 3392 TargetEntryInstr** entry,
3338 Definition** last) { 3393 Definition** last) {
3339 ICData& value_check = ICData::ZoneHandle(Z); 3394 ICData& value_check = ICData::ZoneHandle(Z);
3340 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); 3395 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
3341 switch (kind) { 3396 switch (kind) {
3342 // Recognized [] operators. 3397 // Recognized [] operators.
3343 case MethodRecognizer::kImmutableArrayGetIndexed: 3398 case MethodRecognizer::kImmutableArrayGetIndexed:
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
3646 case MethodRecognizer::kFloat32x4FromFloat64x2: 3701 case MethodRecognizer::kFloat32x4FromFloat64x2:
3647 case MethodRecognizer::kFloat64x2Constructor: 3702 case MethodRecognizer::kFloat64x2Constructor:
3648 case MethodRecognizer::kFloat64x2Zero: 3703 case MethodRecognizer::kFloat64x2Zero:
3649 case MethodRecognizer::kFloat64x2Splat: 3704 case MethodRecognizer::kFloat64x2Splat:
3650 case MethodRecognizer::kFloat64x2FromFloat32x4: 3705 case MethodRecognizer::kFloat64x2FromFloat32x4:
3651 case MethodRecognizer::kInt32x4BoolConstructor: 3706 case MethodRecognizer::kInt32x4BoolConstructor:
3652 case MethodRecognizer::kInt32x4Constructor: 3707 case MethodRecognizer::kInt32x4Constructor:
3653 case MethodRecognizer::kInt32x4FromFloat32x4Bits: 3708 case MethodRecognizer::kInt32x4FromFloat32x4Bits:
3654 return InlineSimdConstructor(flow_graph, call, kind, entry, last); 3709 return InlineSimdConstructor(flow_graph, call, kind, entry, last);
3655 3710
3711 case MethodRecognizer::kMathSqrt:
3712 case MethodRecognizer::kMathDoublePow:
3713 case MethodRecognizer::kMathSin:
3714 case MethodRecognizer::kMathCos:
3715 case MethodRecognizer::kMathTan:
3716 case MethodRecognizer::kMathAsin:
3717 case MethodRecognizer::kMathAcos:
3718 case MethodRecognizer::kMathAtan:
3719 case MethodRecognizer::kMathAtan2:
3720 return InlineMathCFunction(flow_graph, call, kind, entry, last);
3721
3722 case MethodRecognizer::kObjectConstructor: {
3723 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
3724 call->GetBlock()->try_index());
3725 (*entry)->InheritDeoptTarget(Z, call);
3726 ASSERT(!call->HasUses());
3727 *last = NULL; // Empty body.
3728 return true;
3729 }
3730
3731 case MethodRecognizer::kObjectArrayAllocate: {
3732 Value* num_elements = new(Z) Value(call->ArgumentAt(1));
3733 if (num_elements->BindsToConstant() &&
3734 num_elements->BoundConstant().IsSmi()) {
3735 intptr_t length =
3736 Smi::Cast(num_elements->BoundConstant()).Value();
3737 if (length >= 0 && length <= Array::kMaxElements) {
3738 Value* type = new(Z) Value(call->ArgumentAt(0));
3739 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
3740 call->GetBlock()->try_index());
3741 (*entry)->InheritDeoptTarget(Z, call);
3742 *last =
3743 new(Z) CreateArrayInstr(call->token_pos(), type, num_elements);
3744 flow_graph->AppendTo(*entry, *last,
3745 call->deopt_id() != Thread::kNoDeoptId ?
3746 call->env() : NULL,
3747 FlowGraph::kValue);
3748 return true;
3749 }
3750 }
3751 return false;
3752 }
3753
3754 case MethodRecognizer::kOneByteStringSetAt: {
3755 // This is an internal method, no need to check argument types nor
3756 // range.
3757 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(),
3758 call->GetBlock()->try_index());
3759 (*entry)->InheritDeoptTarget(Z, call);
3760 Definition* str = call->ArgumentAt(0);
3761 Definition* index = call->ArgumentAt(1);
3762 Definition* value = call->ArgumentAt(2);
3763 *last = new(Z) StoreIndexedInstr(
3764 new(Z) Value(str),
3765 new(Z) Value(index),
3766 new(Z) Value(value),
3767 kNoStoreBarrier,
3768 1, // Index scale
3769 kOneByteStringCid,
3770 call->deopt_id(),
3771 call->token_pos());
3772 flow_graph->AppendTo(*entry,
3773 *last,
3774 call->deopt_id() != Thread::kNoDeoptId ?
3775 call->env() : NULL,
3776 FlowGraph::kEffect);
3777 return true;
3778 }
3779
3656 default: 3780 default:
3657 return false; 3781 return false;
3658 } 3782 }
3659 } 3783 }
3660 3784
3661 3785
3662 } // namespace dart 3786 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698