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

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: 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
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, receiver_cid, entry, last);
1565 case MethodRecognizer::kDoubleSub:
1566 return InlineDoubleOp(Token::kSUB, call, receiver_cid, entry, last);
1567 case MethodRecognizer::kDoubleMul:
1568 return InlineDoubleOp(Token::kMUL, call, receiver_cid, entry, last);
1569 case MethodRecognizer::kDoubleDiv:
1570 return InlineDoubleOp(Token::kDIV, call, receiver_cid, 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 intptr_t cid, // Not used.
srdjan 2014/08/18 18:04:49 Why pass if not used?
Florian Schneider 2014/08/18 18:22:57 Done.
2800 TargetEntryInstr** entry,
2801 Definition** last) {
2802 Definition* left = call->ArgumentAt(0);
2803 Definition* right = call->ArgumentAt(1);
2804
2805 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(),
2806 call->GetBlock()->try_index());
2807 (*entry)->InheritDeoptTarget(I, call);
2808 // Arguments are checked. No need for class check.
2809 BinaryDoubleOpInstr* double_bin_op =
2810 new(I) BinaryDoubleOpInstr(op_kind,
2811 new(I) Value(left),
2812 new(I) Value(right),
2813 call->deopt_id(), call->token_pos());
2814 flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
2815 *last = double_bin_op;
2816
2817 return true;
2818 }
2819
2820
2793 void FlowGraphOptimizer::ReplaceWithMathCFunction( 2821 void FlowGraphOptimizer::ReplaceWithMathCFunction(
2794 InstanceCallInstr* call, 2822 InstanceCallInstr* call,
2795 MethodRecognizer::Kind recognized_kind) { 2823 MethodRecognizer::Kind recognized_kind) {
2796 AddReceiverCheck(call); 2824 AddReceiverCheck(call);
2797 ZoneGrowableArray<Value*>* args = 2825 ZoneGrowableArray<Value*>* args =
2798 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); 2826 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount());
2799 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 2827 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
2800 args->Add(new(I) Value(call->ArgumentAt(i))); 2828 args->Add(new(I) Value(call->ArgumentAt(i)));
2801 } 2829 }
2802 InvokeMathCFunctionInstr* invoke = 2830 InvokeMathCFunctionInstr* invoke =
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2953 if (!TargetCPUFeatures::double_truncate_round_supported()) { 2981 if (!TargetCPUFeatures::double_truncate_round_supported()) {
2954 ReplaceWithMathCFunction(call, recognized_kind); 2982 ReplaceWithMathCFunction(call, recognized_kind);
2955 } else { 2983 } else {
2956 AddReceiverCheck(call); 2984 AddReceiverCheck(call);
2957 DoubleToDoubleInstr* d2d_instr = 2985 DoubleToDoubleInstr* d2d_instr =
2958 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)), 2986 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)),
2959 recognized_kind, call->deopt_id()); 2987 recognized_kind, call->deopt_id());
2960 ReplaceCall(call, d2d_instr); 2988 ReplaceCall(call, d2d_instr);
2961 } 2989 }
2962 return true; 2990 return true;
2991 case MethodRecognizer::kDoubleAdd:
2992 case MethodRecognizer::kDoubleSub:
2993 case MethodRecognizer::kDoubleMul:
2994 case MethodRecognizer::kDoubleDiv:
2995 return TryReplaceInstanceCallWithInline(call);
2963 default: 2996 default:
2964 // Unsupported method. 2997 // Unsupported method.
2965 return false; 2998 return false;
2966 } 2999 }
2967 } 3000 }
2968 3001
2969 if (IsSupportedByteArrayViewCid(class_ids[0]) && 3002 if (IsSupportedByteArrayViewCid(class_ids[0]) &&
2970 (ic_data.NumberOfChecks() == 1)) { 3003 (ic_data.NumberOfChecks() == 1)) {
2971 // For elements that may not fit into a smi on all platforms, check if 3004 // 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. 3005 // 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(), 4368 call->deopt_id(),
4336 recognized_kind, 4369 recognized_kind,
4337 call->token_pos()); 4370 call->token_pos());
4338 ReplaceCall(call, invoke); 4371 ReplaceCall(call, invoke);
4339 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { 4372 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) {
4340 Value* type = new(I) Value(call->ArgumentAt(0)); 4373 Value* type = new(I) Value(call->ArgumentAt(0));
4341 Value* num_elements = new(I) Value(call->ArgumentAt(1)); 4374 Value* num_elements = new(I) Value(call->ArgumentAt(1));
4342 CreateArrayInstr* create_array = 4375 CreateArrayInstr* create_array =
4343 new(I) CreateArrayInstr(call->token_pos(), type, num_elements); 4376 new(I) CreateArrayInstr(call->token_pos(), type, num_elements);
4344 ReplaceCall(call, create_array); 4377 ReplaceCall(call, create_array);
4378 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) {
4379 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
4380 const ICData& ic_data = *call->ic_data();
4381 if (CanUnboxDouble() && ArgIsAlways(kSmiCid, ic_data, 0)) {
4382 Definition* arg = call->ArgumentAt(0);
4383 InsertBefore(call,
4384 new(I) CheckSmiInstr(
4385 new(I) Value(arg),
4386 call->deopt_id(),
4387 call->token_pos()),
4388 call->env(),
4389 FlowGraph::kEffect);
4390 ReplaceCall(call,
4391 new(I) SmiToDoubleInstr(new(I) Value(arg),
4392 call->token_pos()));
4393 }
4394 }
4345 } else if (call->function().IsFactory()) { 4395 } else if (call->function().IsFactory()) {
4346 const Class& function_class = 4396 const Class& function_class =
4347 Class::Handle(I, call->function().Owner()); 4397 Class::Handle(I, call->function().Owner());
4348 if ((function_class.library() == Library::CoreLibrary()) || 4398 if ((function_class.library() == Library::CoreLibrary()) ||
4349 (function_class.library() == Library::TypedDataLibrary())) { 4399 (function_class.library() == Library::TypedDataLibrary())) {
4350 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); 4400 intptr_t cid = FactoryRecognizer::ResultCid(call->function());
4351 switch (cid) { 4401 switch (cid) {
4352 case kArrayCid: { 4402 case kArrayCid: {
4353 Value* type = new(I) Value(call->ArgumentAt(0)); 4403 Value* type = new(I) Value(call->ArgumentAt(0));
4354 Value* num_elements = new(I) Value(call->ArgumentAt(1)); 4404 Value* num_elements = new(I) Value(call->ArgumentAt(1));
(...skipping 5187 matching lines...) Expand 10 before | Expand all | Expand 10 after
9542 9592
9543 // Insert materializations at environment uses. 9593 // Insert materializations at environment uses.
9544 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 9594 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
9545 CreateMaterializationAt( 9595 CreateMaterializationAt(
9546 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); 9596 exits_collector_.exits()[i], alloc, alloc->cls(), *slots);
9547 } 9597 }
9548 } 9598 }
9549 9599
9550 9600
9551 } // namespace dart 9601 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698