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

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

Issue 484693003: Improve polymorphic inlining of int/int double/double operations. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased and addressed comments Created 6 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | 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/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 1542 matching lines...) Expand 10 before | Expand all | Expand 10 after
1553 if (!ShouldInlineSimd()) { 1553 if (!ShouldInlineSimd()) {
1554 return false; 1554 return false;
1555 } 1555 }
1556 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, 1556 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1557 kTypedDataInt32x4ArrayCid, 1557 kTypedDataInt32x4ArrayCid,
1558 ic_data, entry, last); 1558 ic_data, entry, last);
1559 case MethodRecognizer::kStringBaseCodeUnitAt: 1559 case MethodRecognizer::kStringBaseCodeUnitAt:
1560 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); 1560 return InlineStringCodeUnitAt(call, receiver_cid, entry, last);
1561 case MethodRecognizer::kStringBaseCharAt: 1561 case MethodRecognizer::kStringBaseCharAt:
1562 return InlineStringBaseCharAt(call, receiver_cid, entry, last); 1562 return InlineStringBaseCharAt(call, receiver_cid, entry, last);
1563 case MethodRecognizer::kDoubleAdd:
1564 return InlineDoubleOp(Token::kADD, call, entry, last);
1565 case MethodRecognizer::kDoubleSub:
1566 return InlineDoubleOp(Token::kSUB, call, entry, last);
1567 case MethodRecognizer::kDoubleMul:
1568 return InlineDoubleOp(Token::kMUL, call, entry, last);
1569 case MethodRecognizer::kDoubleDiv:
1570 return InlineDoubleOp(Token::kDIV, call, entry, last);
1563 default: 1571 default:
1564 return false; 1572 return false;
1565 } 1573 }
1566 } 1574 }
1567 1575
1568 1576
1569 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, 1577 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call,
1570 intptr_t array_cid, 1578 intptr_t array_cid,
1571 Definition** array, 1579 Definition** array,
1572 Definition* index, 1580 Definition* index,
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after
2329 // Reset value types if guarded_cid was used. 2337 // Reset value types if guarded_cid was used.
2330 for (Value::Iterator it(load->input_use_list()); 2338 for (Value::Iterator it(load->input_use_list());
2331 !it.Done(); 2339 !it.Done();
2332 it.Advance()) { 2340 it.Advance()) {
2333 it.Current()->SetReachingType(NULL); 2341 it.Current()->SetReachingType(NULL);
2334 } 2342 }
2335 } 2343 }
2336 } 2344 }
2337 2345
2338 2346
2339 LoadFieldInstr* FlowGraphOptimizer::BuildLoadStringLength(Definition* str) {
2340 // Treat length loads as mutable (i.e. affected by side effects) to avoid
2341 // hoisting them since we can't hoist the preceding class-check. This
2342 // is because of externalization of strings that affects their class-id.
2343 LoadFieldInstr* load = new(I) LoadFieldInstr(
2344 new(I) Value(str),
2345 String::length_offset(),
2346 Type::ZoneHandle(I, Type::SmiType()),
2347 str->token_pos());
2348 load->set_result_cid(kSmiCid);
2349 load->set_recognized_kind(MethodRecognizer::kStringBaseLength);
2350 return load;
2351 }
2352
2353
2354 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, 2347 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
2355 MethodRecognizer::Kind getter) { 2348 MethodRecognizer::Kind getter) {
2356 if (!ShouldInlineSimd()) { 2349 if (!ShouldInlineSimd()) {
2357 return false; 2350 return false;
2358 } 2351 }
2359 AddCheckClass(call->ArgumentAt(0), 2352 AddCheckClass(call->ArgumentAt(0),
2360 ICData::ZoneHandle( 2353 ICData::ZoneHandle(
2361 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2354 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
2362 call->deopt_id(), 2355 call->deopt_id(),
2363 call->env(), 2356 call->env(),
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
2704 2697
2705 cursor = flow_graph()->AppendTo(cursor, 2698 cursor = flow_graph()->AppendTo(cursor,
2706 new(I) CheckSmiInstr( 2699 new(I) CheckSmiInstr(
2707 new(I) Value(index), 2700 new(I) Value(index),
2708 call->deopt_id(), 2701 call->deopt_id(),
2709 call->token_pos()), 2702 call->token_pos()),
2710 call->env(), 2703 call->env(),
2711 FlowGraph::kEffect); 2704 FlowGraph::kEffect);
2712 2705
2713 // Load the length of the string. 2706 // Load the length of the string.
2714 LoadFieldInstr* length = BuildLoadStringLength(str); 2707 // Treat length loads as mutable (i.e. affected by side effects) to avoid
2708 // hoisting them since we can't hoist the preceding class-check. This
2709 // is because of externalization of strings that affects their class-id.
2710 LoadFieldInstr* length = new(I) LoadFieldInstr(
2711 new(I) Value(str),
2712 String::length_offset(),
2713 Type::ZoneHandle(I, Type::SmiType()),
2714 str->token_pos());
2715 length->set_result_cid(kSmiCid);
2716 length->set_recognized_kind(MethodRecognizer::kStringBaseLength);
2717
2715 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); 2718 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue);
2716 // Bounds check. 2719 // Bounds check.
2717 cursor = flow_graph()->AppendTo(cursor, 2720 cursor = flow_graph()->AppendTo(cursor,
2718 new(I) CheckArrayBoundInstr( 2721 new(I) CheckArrayBoundInstr(
2719 new(I) Value(length), 2722 new(I) Value(length),
2720 new(I) Value(index), 2723 new(I) Value(index),
2721 call->deopt_id()), 2724 call->deopt_id()),
2722 call->env(), 2725 call->env(),
2723 FlowGraph::kEffect); 2726 FlowGraph::kEffect);
2724 2727
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2783 StringFromCharCodeInstr* char_at = new(I) StringFromCharCodeInstr( 2786 StringFromCharCodeInstr* char_at = new(I) StringFromCharCodeInstr(
2784 new(I) Value(*last), cid); 2787 new(I) Value(*last), cid);
2785 2788
2786 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); 2789 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
2787 *last = char_at; 2790 *last = char_at;
2788 2791
2789 return true; 2792 return true;
2790 } 2793 }
2791 2794
2792 2795
2796 bool FlowGraphOptimizer::InlineDoubleOp(
2797 Token::Kind op_kind,
2798 Instruction* call,
2799 TargetEntryInstr** entry,
2800 Definition** last) {
2801 Definition* left = call->ArgumentAt(0);
2802 Definition* right = call->ArgumentAt(1);
2803
2804 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(),
2805 call->GetBlock()->try_index());
2806 (*entry)->InheritDeoptTarget(I, call);
2807 // Arguments are checked. No need for class check.
2808 BinaryDoubleOpInstr* double_bin_op =
2809 new(I) BinaryDoubleOpInstr(op_kind,
2810 new(I) Value(left),
2811 new(I) Value(right),
2812 call->deopt_id(), call->token_pos());
2813 flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
2814 *last = double_bin_op;
2815
2816 return true;
2817 }
2818
2819
2793 void FlowGraphOptimizer::ReplaceWithMathCFunction( 2820 void FlowGraphOptimizer::ReplaceWithMathCFunction(
2794 InstanceCallInstr* call, 2821 InstanceCallInstr* call,
2795 MethodRecognizer::Kind recognized_kind) { 2822 MethodRecognizer::Kind recognized_kind) {
2796 AddReceiverCheck(call); 2823 AddReceiverCheck(call);
2797 ZoneGrowableArray<Value*>* args = 2824 ZoneGrowableArray<Value*>* args =
2798 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); 2825 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount());
2799 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 2826 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
2800 args->Add(new(I) Value(call->ArgumentAt(i))); 2827 args->Add(new(I) Value(call->ArgumentAt(i)));
2801 } 2828 }
2802 InvokeMathCFunctionInstr* invoke = 2829 InvokeMathCFunctionInstr* invoke =
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2953 if (!TargetCPUFeatures::double_truncate_round_supported()) { 2980 if (!TargetCPUFeatures::double_truncate_round_supported()) {
2954 ReplaceWithMathCFunction(call, recognized_kind); 2981 ReplaceWithMathCFunction(call, recognized_kind);
2955 } else { 2982 } else {
2956 AddReceiverCheck(call); 2983 AddReceiverCheck(call);
2957 DoubleToDoubleInstr* d2d_instr = 2984 DoubleToDoubleInstr* d2d_instr =
2958 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)), 2985 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)),
2959 recognized_kind, call->deopt_id()); 2986 recognized_kind, call->deopt_id());
2960 ReplaceCall(call, d2d_instr); 2987 ReplaceCall(call, d2d_instr);
2961 } 2988 }
2962 return true; 2989 return true;
2990 case MethodRecognizer::kDoubleAdd:
2991 case MethodRecognizer::kDoubleSub:
2992 case MethodRecognizer::kDoubleMul:
2993 case MethodRecognizer::kDoubleDiv:
2994 return TryReplaceInstanceCallWithInline(call);
2963 default: 2995 default:
2964 // Unsupported method. 2996 // Unsupported method.
2965 return false; 2997 return false;
2966 } 2998 }
2967 } 2999 }
2968 3000
2969 if (IsSupportedByteArrayViewCid(class_ids[0]) && 3001 if (IsSupportedByteArrayViewCid(class_ids[0]) &&
2970 (ic_data.NumberOfChecks() == 1)) { 3002 (ic_data.NumberOfChecks() == 1)) {
2971 // For elements that may not fit into a smi on all platforms, check if 3003 // For elements that may not fit into a smi on all platforms, check if
2972 // elements fit into a smi or the platform supports unboxed mints. 3004 // elements fit into a smi or the platform supports unboxed mints.
(...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after
4335 call->deopt_id(), 4367 call->deopt_id(),
4336 recognized_kind, 4368 recognized_kind,
4337 call->token_pos()); 4369 call->token_pos());
4338 ReplaceCall(call, invoke); 4370 ReplaceCall(call, invoke);
4339 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { 4371 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) {
4340 Value* type = new(I) Value(call->ArgumentAt(0)); 4372 Value* type = new(I) Value(call->ArgumentAt(0));
4341 Value* num_elements = new(I) Value(call->ArgumentAt(1)); 4373 Value* num_elements = new(I) Value(call->ArgumentAt(1));
4342 CreateArrayInstr* create_array = 4374 CreateArrayInstr* create_array =
4343 new(I) CreateArrayInstr(call->token_pos(), type, num_elements); 4375 new(I) CreateArrayInstr(call->token_pos(), type, num_elements);
4344 ReplaceCall(call, create_array); 4376 ReplaceCall(call, create_array);
4377 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) {
4378 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4379 const ICData& ic_data = *call->ic_data();
4380 if (CanUnboxDouble() && ArgIsAlways(kSmiCid, ic_data, 0)) {
4381 Definition* arg = call->ArgumentAt(0);
4382 InsertBefore(call,
4383 new(I) CheckSmiInstr(
4384 new(I) Value(arg),
4385 call->deopt_id(),
4386 call->token_pos()),
4387 call->env(),
4388 FlowGraph::kEffect);
4389 ReplaceCall(call,
4390 new(I) SmiToDoubleInstr(new(I) Value(arg),
4391 call->token_pos()));
4392 }
4393 }
4345 } else if (call->function().IsFactory()) { 4394 } else if (call->function().IsFactory()) {
4346 const Class& function_class = 4395 const Class& function_class =
4347 Class::Handle(I, call->function().Owner()); 4396 Class::Handle(I, call->function().Owner());
4348 if ((function_class.library() == Library::CoreLibrary()) || 4397 if ((function_class.library() == Library::CoreLibrary()) ||
4349 (function_class.library() == Library::TypedDataLibrary())) { 4398 (function_class.library() == Library::TypedDataLibrary())) {
4350 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); 4399 intptr_t cid = FactoryRecognizer::ResultCid(call->function());
4351 switch (cid) { 4400 switch (cid) {
4352 case kArrayCid: { 4401 case kArrayCid: {
4353 Value* type = new(I) Value(call->ArgumentAt(0)); 4402 Value* type = new(I) Value(call->ArgumentAt(0));
4354 Value* num_elements = new(I) Value(call->ArgumentAt(1)); 4403 Value* num_elements = new(I) Value(call->ArgumentAt(1));
(...skipping 5192 matching lines...) Expand 10 before | Expand all | Expand 10 after
9547 9596
9548 // Insert materializations at environment uses. 9597 // Insert materializations at environment uses.
9549 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 9598 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
9550 CreateMaterializationAt( 9599 CreateMaterializationAt(
9551 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); 9600 exits_collector_.exits()[i], alloc, alloc->cls(), *slots);
9552 } 9601 }
9553 } 9602 }
9554 9603
9555 9604
9556 } // namespace dart 9605 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698