| OLD | NEW |
| 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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 if (class_ids.length() > 1) { | 247 if (class_ids.length() > 1) { |
| 248 ic_data.AddCheck(class_ids, function); | 248 ic_data.AddCheck(class_ids, function); |
| 249 } else { | 249 } else { |
| 250 ASSERT(class_ids.length() == 1); | 250 ASSERT(class_ids.length() == 1); |
| 251 ic_data.AddReceiverCheck(class_ids[0], function); | 251 ic_data.AddReceiverCheck(class_ids[0], function); |
| 252 } | 252 } |
| 253 call->set_ic_data(&ic_data); | 253 call->set_ic_data(&ic_data); |
| 254 return true; | 254 return true; |
| 255 } | 255 } |
| 256 | 256 |
| 257 if (Compiler::always_optimize() && | 257 if (FLAG_precompilation && |
| 258 (isolate()->object_store()->unique_dynamic_targets() != Array::null())) { | 258 (isolate()->object_store()->unique_dynamic_targets() != Array::null())) { |
| 259 // Check if the target is unique. | 259 // Check if the target is unique. |
| 260 Function& target_function = Function::Handle(Z); | 260 Function& target_function = Function::Handle(Z); |
| 261 Precompiler::GetUniqueDynamicTarget( | 261 Precompiler::GetUniqueDynamicTarget( |
| 262 isolate(), call->function_name(), &target_function); | 262 isolate(), call->function_name(), &target_function); |
| 263 // Calls with named arguments must be resolved/checked at runtime. | 263 // Calls with named arguments must be resolved/checked at runtime. |
| 264 String& error_message = String::Handle(Z); | 264 String& error_message = String::Handle(Z); |
| 265 if (!target_function.IsNull() && | 265 if (!target_function.IsNull() && |
| 266 !target_function.HasOptionalNamedParameters() && | 266 !target_function.HasOptionalNamedParameters() && |
| 267 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, | 267 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, |
| (...skipping 2898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3166 return true; | 3166 return true; |
| 3167 } | 3167 } |
| 3168 } | 3168 } |
| 3169 return false; | 3169 return false; |
| 3170 } | 3170 } |
| 3171 | 3171 |
| 3172 | 3172 |
| 3173 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( | 3173 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( |
| 3174 StaticCallInstr* call, | 3174 StaticCallInstr* call, |
| 3175 MethodRecognizer::Kind recognized_kind) { | 3175 MethodRecognizer::Kind recognized_kind) { |
| 3176 if (Compiler::always_optimize()) { | 3176 if (FLAG_precompilation) { |
| 3177 // Cannot handle unboxed instructions. | 3177 // Cannot handle unboxed instructions. |
| 3178 return false; | 3178 return false; |
| 3179 } | 3179 } |
| 3180 if (!ShouldInlineSimd()) { | 3180 if (!ShouldInlineSimd()) { |
| 3181 return false; | 3181 return false; |
| 3182 } | 3182 } |
| 3183 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { | 3183 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { |
| 3184 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr(); | 3184 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr(); |
| 3185 ReplaceCall(call, zero); | 3185 ReplaceCall(call, zero); |
| 3186 return true; | 3186 return true; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3213 ReplaceCall(call, cast); | 3213 ReplaceCall(call, cast); |
| 3214 return true; | 3214 return true; |
| 3215 } | 3215 } |
| 3216 return false; | 3216 return false; |
| 3217 } | 3217 } |
| 3218 | 3218 |
| 3219 | 3219 |
| 3220 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( | 3220 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( |
| 3221 StaticCallInstr* call, | 3221 StaticCallInstr* call, |
| 3222 MethodRecognizer::Kind recognized_kind) { | 3222 MethodRecognizer::Kind recognized_kind) { |
| 3223 if (Compiler::always_optimize()) { | 3223 if (FLAG_precompilation) { |
| 3224 // Cannot handle unboxed instructions. | 3224 // Cannot handle unboxed instructions. |
| 3225 return false; | 3225 return false; |
| 3226 } | 3226 } |
| 3227 if (!ShouldInlineSimd()) { | 3227 if (!ShouldInlineSimd()) { |
| 3228 return false; | 3228 return false; |
| 3229 } | 3229 } |
| 3230 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { | 3230 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { |
| 3231 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr(); | 3231 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr(); |
| 3232 ReplaceCall(call, zero); | 3232 ReplaceCall(call, zero); |
| 3233 return true; | 3233 return true; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3252 ReplaceCall(call, cast); | 3252 ReplaceCall(call, cast); |
| 3253 return true; | 3253 return true; |
| 3254 } | 3254 } |
| 3255 return false; | 3255 return false; |
| 3256 } | 3256 } |
| 3257 | 3257 |
| 3258 | 3258 |
| 3259 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( | 3259 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( |
| 3260 StaticCallInstr* call, | 3260 StaticCallInstr* call, |
| 3261 MethodRecognizer::Kind recognized_kind) { | 3261 MethodRecognizer::Kind recognized_kind) { |
| 3262 if (Compiler::always_optimize()) { | 3262 if (FLAG_precompilation) { |
| 3263 // Cannot handle unboxed instructions. | 3263 // Cannot handle unboxed instructions. |
| 3264 return false; | 3264 return false; |
| 3265 } | 3265 } |
| 3266 if (!ShouldInlineSimd()) { | 3266 if (!ShouldInlineSimd()) { |
| 3267 return false; | 3267 return false; |
| 3268 } | 3268 } |
| 3269 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { | 3269 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { |
| 3270 Int32x4BoolConstructorInstr* con = | 3270 Int32x4BoolConstructorInstr* con = |
| 3271 new(Z) Int32x4BoolConstructorInstr( | 3271 new(Z) Int32x4BoolConstructorInstr( |
| 3272 new(Z) Value(call->ArgumentAt(1)), | 3272 new(Z) Value(call->ArgumentAt(1)), |
| (...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4356 /* with_checks = */ false); | 4356 /* with_checks = */ false); |
| 4357 instr->ReplaceWith(call, current_iterator()); | 4357 instr->ReplaceWith(call, current_iterator()); |
| 4358 return; | 4358 return; |
| 4359 } | 4359 } |
| 4360 } | 4360 } |
| 4361 | 4361 |
| 4362 | 4362 |
| 4363 // Tries to optimize instance call by replacing it with a faster instruction | 4363 // Tries to optimize instance call by replacing it with a faster instruction |
| 4364 // (e.g, binary op, field load, ..). | 4364 // (e.g, binary op, field load, ..). |
| 4365 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 4365 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 4366 if (Compiler::always_optimize()) { | 4366 if (FLAG_precompilation) { |
| 4367 InstanceCallNoopt(instr); | 4367 InstanceCallNoopt(instr); |
| 4368 return; | 4368 return; |
| 4369 } | 4369 } |
| 4370 | 4370 |
| 4371 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { | 4371 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { |
| 4372 return; | 4372 return; |
| 4373 } | 4373 } |
| 4374 const Token::Kind op_kind = instr->token_kind(); | 4374 const Token::Kind op_kind = instr->token_kind(); |
| 4375 | 4375 |
| 4376 // Type test is special as it always gets converted into inlined code. | 4376 // Type test is special as it always gets converted into inlined code. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4488 unary_kind = MathUnaryInstr::kSin; | 4488 unary_kind = MathUnaryInstr::kSin; |
| 4489 break; | 4489 break; |
| 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 (Compiler::always_optimize()) { | 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 { | 4500 } else { |
| 4501 MathUnaryInstr* math_unary = | 4501 MathUnaryInstr* math_unary = |
| 4502 new(Z) MathUnaryInstr(unary_kind, | 4502 new(Z) MathUnaryInstr(unary_kind, |
| 4503 new(Z) Value(call->ArgumentAt(0)), | 4503 new(Z) Value(call->ArgumentAt(0)), |
| 4504 call->deopt_id()); | 4504 call->deopt_id()); |
| 4505 ReplaceCall(call, math_unary); | 4505 ReplaceCall(call, math_unary); |
| 4506 } | 4506 } |
| 4507 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || | 4507 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || |
| 4508 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || | 4508 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4557 call); | 4557 call); |
| 4558 AddCheckClass(min_max->right()->definition(), | 4558 AddCheckClass(min_max->right()->definition(), |
| 4559 unary_checks, | 4559 unary_checks, |
| 4560 call->deopt_id(), | 4560 call->deopt_id(), |
| 4561 call->env(), | 4561 call->env(), |
| 4562 call); | 4562 call); |
| 4563 ReplaceCall(call, min_max); | 4563 ReplaceCall(call, min_max); |
| 4564 } | 4564 } |
| 4565 } | 4565 } |
| 4566 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { | 4566 } else if (recognized_kind == MethodRecognizer::kMathDoublePow) { |
| 4567 if (Compiler::always_optimize()) { | 4567 if (FLAG_precompilation) { |
| 4568 // No UnboxDouble instructons allowed. | 4568 // No UnboxDouble instructons allowed. |
| 4569 return; | 4569 return; |
| 4570 } | 4570 } |
| 4571 // We know that first argument is double, the second is num. | 4571 // We know that first argument is double, the second is num. |
| 4572 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble | 4572 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble |
| 4573 // instructions contain type checks and conversions to double. | 4573 // instructions contain type checks and conversions to double. |
| 4574 ZoneGrowableArray<Value*>* args = | 4574 ZoneGrowableArray<Value*>* args = |
| 4575 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); | 4575 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
| 4576 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 4576 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
| 4577 args->Add(new(Z) Value(call->ArgumentAt(i))); | 4577 args->Add(new(Z) Value(call->ArgumentAt(i))); |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5219 return IsLoadEliminationCandidate(instr) && | 5219 return IsLoadEliminationCandidate(instr) && |
| 5220 (sets != NULL) && | 5220 (sets != NULL) && |
| 5221 instr->HasPlaceId() && | 5221 instr->HasPlaceId() && |
| 5222 ((*sets)[loop_header_index] != NULL) && | 5222 ((*sets)[loop_header_index] != NULL) && |
| 5223 (*sets)[loop_header_index]->Contains(instr->place_id()); | 5223 (*sets)[loop_header_index]->Contains(instr->place_id()); |
| 5224 } | 5224 } |
| 5225 | 5225 |
| 5226 | 5226 |
| 5227 void LICM::OptimisticallySpecializeSmiPhis() { | 5227 void LICM::OptimisticallySpecializeSmiPhis() { |
| 5228 if (!flow_graph()->function().allows_hoisting_check_class() || | 5228 if (!flow_graph()->function().allows_hoisting_check_class() || |
| 5229 Compiler::always_optimize()) { | 5229 FLAG_precompilation) { |
| 5230 // Do not hoist any: Either deoptimized on a hoisted check, | 5230 // Do not hoist any: Either deoptimized on a hoisted check, |
| 5231 // or compiling precompiled code where we can't do optimistic | 5231 // or compiling precompiled code where we can't do optimistic |
| 5232 // hoisting of checks. | 5232 // hoisting of checks. |
| 5233 return; | 5233 return; |
| 5234 } | 5234 } |
| 5235 | 5235 |
| 5236 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 5236 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 5237 flow_graph()->LoopHeaders(); | 5237 flow_graph()->LoopHeaders(); |
| 5238 | 5238 |
| 5239 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 5239 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| (...skipping 3606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8846 | 8846 |
| 8847 // Insert materializations at environment uses. | 8847 // Insert materializations at environment uses. |
| 8848 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8848 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8849 CreateMaterializationAt( | 8849 CreateMaterializationAt( |
| 8850 exits_collector_.exits()[i], alloc, *slots); | 8850 exits_collector_.exits()[i], alloc, *slots); |
| 8851 } | 8851 } |
| 8852 } | 8852 } |
| 8853 | 8853 |
| 8854 | 8854 |
| 8855 } // namespace dart | 8855 } // namespace dart |
| OLD | NEW |