| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1213 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. | 1213 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. |
| 1214 needs_store_barrier = kNoStoreBarrier; | 1214 needs_store_barrier = kNoStoreBarrier; |
| 1215 Instruction* check = | 1215 Instruction* check = |
| 1216 GetCheckClass(stored_value, value_check, call->deopt_id()); | 1216 GetCheckClass(stored_value, value_check, call->deopt_id()); |
| 1217 cursor = flow_graph()->AppendTo(cursor, | 1217 cursor = flow_graph()->AppendTo(cursor, |
| 1218 check, | 1218 check, |
| 1219 call->env(), | 1219 call->env(), |
| 1220 Definition::kEffect); | 1220 Definition::kEffect); |
| 1221 } | 1221 } |
| 1222 | 1222 |
| 1223 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1224 stored_value = |
| 1225 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); |
| 1226 cursor = flow_graph()->AppendTo(cursor, |
| 1227 stored_value, |
| 1228 NULL, |
| 1229 Definition::kValue); |
| 1230 } |
| 1231 |
| 1223 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1232 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 1224 *last = new StoreIndexedInstr(new Value(array), | 1233 *last = new StoreIndexedInstr(new Value(array), |
| 1225 new Value(index), | 1234 new Value(index), |
| 1226 new Value(stored_value), | 1235 new Value(stored_value), |
| 1227 needs_store_barrier, | 1236 needs_store_barrier, |
| 1228 index_scale, | 1237 index_scale, |
| 1229 array_cid, | 1238 array_cid, |
| 1230 call->deopt_id()); | 1239 call->deopt_id()); |
| 1231 flow_graph()->AppendTo(cursor, | 1240 flow_graph()->AppendTo(cursor, |
| 1232 *last, | 1241 *last, |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1509 call->deopt_id() : Isolate::kNoDeoptId; | 1518 call->deopt_id() : Isolate::kNoDeoptId; |
| 1510 } | 1519 } |
| 1511 | 1520 |
| 1512 // Array load and return. | 1521 // Array load and return. |
| 1513 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 1522 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 1514 *last = new LoadIndexedInstr(new Value(array), | 1523 *last = new LoadIndexedInstr(new Value(array), |
| 1515 new Value(index), | 1524 new Value(index), |
| 1516 index_scale, | 1525 index_scale, |
| 1517 array_cid, | 1526 array_cid, |
| 1518 deopt_id); | 1527 deopt_id); |
| 1519 flow_graph()->AppendTo(cursor, | 1528 cursor = flow_graph()->AppendTo( |
| 1520 *last, | 1529 cursor, |
| 1521 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1530 *last, |
| 1522 Definition::kValue); | 1531 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 1532 Definition::kValue); |
| 1533 |
| 1534 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 1535 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 1536 flow_graph()->AppendTo(cursor, |
| 1537 *last, |
| 1538 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 1539 Definition::kValue); |
| 1540 } |
| 1523 return true; | 1541 return true; |
| 1524 } | 1542 } |
| 1525 | 1543 |
| 1526 | 1544 |
| 1527 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 1545 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
| 1528 // Check for monomorphic IC data. | 1546 // Check for monomorphic IC data. |
| 1529 if (!call->HasICData()) return false; | 1547 if (!call->HasICData()) return false; |
| 1530 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); | 1548 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); |
| 1531 if (ic_data.NumberOfChecks() != 1) return false; | 1549 if (ic_data.NumberOfChecks() != 1) return false; |
| 1532 ASSERT(ic_data.HasOneTarget()); | 1550 ASSERT(ic_data.HasOneTarget()); |
| (...skipping 1625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3158 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 3176 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
| 3159 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? | 3177 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? |
| 3160 call->deopt_id() : Isolate::kNoDeoptId; | 3178 call->deopt_id() : Isolate::kNoDeoptId; |
| 3161 } | 3179 } |
| 3162 | 3180 |
| 3163 *last = new LoadIndexedInstr(new Value(array), | 3181 *last = new LoadIndexedInstr(new Value(array), |
| 3164 new Value(index), | 3182 new Value(index), |
| 3165 1, | 3183 1, |
| 3166 view_cid, | 3184 view_cid, |
| 3167 deopt_id); | 3185 deopt_id); |
| 3168 flow_graph()->AppendTo(cursor, | 3186 cursor = flow_graph()->AppendTo( |
| 3169 *last, | 3187 cursor, |
| 3170 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 3188 *last, |
| 3171 Definition::kValue); | 3189 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 3190 Definition::kValue); |
| 3191 |
| 3192 if (view_cid == kTypedDataFloat32ArrayCid) { |
| 3193 *last = new FloatToDoubleInstr(new Value(*last), deopt_id); |
| 3194 flow_graph()->AppendTo(cursor, |
| 3195 *last, |
| 3196 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 3197 Definition::kValue); |
| 3198 } |
| 3172 return true; | 3199 return true; |
| 3173 } | 3200 } |
| 3174 | 3201 |
| 3175 | 3202 |
| 3176 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, | 3203 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target, |
| 3177 Instruction* call, | 3204 Instruction* call, |
| 3178 Definition* receiver, | 3205 Definition* receiver, |
| 3179 intptr_t array_cid, | 3206 intptr_t array_cid, |
| 3180 intptr_t view_cid, | 3207 intptr_t view_cid, |
| 3181 const ICData& ic_data, | 3208 const ICData& ic_data, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3272 default: | 3299 default: |
| 3273 // Array cids are already checked in the caller. | 3300 // Array cids are already checked in the caller. |
| 3274 UNREACHABLE(); | 3301 UNREACHABLE(); |
| 3275 } | 3302 } |
| 3276 | 3303 |
| 3277 Definition* stored_value = call->ArgumentAt(2); | 3304 Definition* stored_value = call->ArgumentAt(2); |
| 3278 if (!value_check.IsNull()) { | 3305 if (!value_check.IsNull()) { |
| 3279 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), | 3306 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), |
| 3280 call); | 3307 call); |
| 3281 } | 3308 } |
| 3309 |
| 3310 if (view_cid == kTypedDataFloat32ArrayCid) { |
| 3311 stored_value = |
| 3312 new DoubleToFloatInstr(new Value(stored_value), call->deopt_id()); |
| 3313 cursor = flow_graph()->AppendTo(cursor, |
| 3314 stored_value, |
| 3315 NULL, |
| 3316 Definition::kValue); |
| 3317 } |
| 3318 |
| 3282 StoreBarrierType needs_store_barrier = kNoStoreBarrier; | 3319 StoreBarrierType needs_store_barrier = kNoStoreBarrier; |
| 3283 *last = new StoreIndexedInstr(new Value(array), | 3320 *last = new StoreIndexedInstr(new Value(array), |
| 3284 new Value(index), | 3321 new Value(index), |
| 3285 new Value(stored_value), | 3322 new Value(stored_value), |
| 3286 needs_store_barrier, | 3323 needs_store_barrier, |
| 3287 1, // Index scale | 3324 1, // Index scale |
| 3288 view_cid, | 3325 view_cid, |
| 3289 call->deopt_id()); | 3326 call->deopt_id()); |
| 3290 | 3327 |
| 3291 flow_graph()->AppendTo(cursor, | 3328 flow_graph()->AppendTo(cursor, |
| (...skipping 1964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5256 if (comma) { | 5293 if (comma) { |
| 5257 OS::Print(", "); | 5294 OS::Print(", "); |
| 5258 } | 5295 } |
| 5259 OS::Print("%s", places_[it.Current()]->ToCString()); | 5296 OS::Print("%s", places_[it.Current()]->ToCString()); |
| 5260 comma = true; | 5297 comma = true; |
| 5261 } | 5298 } |
| 5262 } | 5299 } |
| 5263 | 5300 |
| 5264 const PhiPlaceMoves* phi_moves() const { return phi_moves_; } | 5301 const PhiPlaceMoves* phi_moves() const { return phi_moves_; } |
| 5265 | 5302 |
| 5266 // Returns true if the result of AllocateObject can be aliased by some | 5303 // Returns true if the result of an allocation instruction can be aliased by |
| 5267 // other SSA variable and false otherwise. Currently simply checks if | 5304 // some other SSA variable and false otherwise. Currently simply checks if |
| 5268 // this value is stored in a field, escapes to another function or | 5305 // this value is stored in a field, escapes to another function or |
| 5269 // participates in a phi. | 5306 // participates in a phi. |
| 5270 static bool CanBeAliased(AllocateObjectInstr* alloc) { | 5307 static bool CanBeAliased(AllocateObjectInstr* alloc) { |
| 5271 if (alloc->identity() == AllocateObjectInstr::kUnknown) { | 5308 if (alloc->identity() == AllocateObjectInstr::kUnknown) { |
| 5272 bool escapes = false; | 5309 bool escapes = false; |
| 5273 for (Value* use = alloc->input_use_list(); | 5310 for (Value* use = alloc->input_use_list(); |
| 5274 use != NULL; | 5311 use != NULL; |
| 5275 use = use->next_use()) { | 5312 use = use->next_use()) { |
| 5276 Instruction* instr = use->instruction(); | 5313 Instruction* instr = use->instruction(); |
| 5277 if (instr->IsPushArgument() || | 5314 if (instr->IsPushArgument() || |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5718 gen->RemoveAll(killed); | 5755 gen->RemoveAll(killed); |
| 5719 } | 5756 } |
| 5720 | 5757 |
| 5721 // Only forward stores to normal arrays, float64, and simd arrays | 5758 // Only forward stores to normal arrays, float64, and simd arrays |
| 5722 // to loads because other array stores (intXX/uintXX/float32) | 5759 // to loads because other array stores (intXX/uintXX/float32) |
| 5723 // may implicitly convert the value stored. | 5760 // may implicitly convert the value stored. |
| 5724 StoreIndexedInstr* array_store = instr->AsStoreIndexed(); | 5761 StoreIndexedInstr* array_store = instr->AsStoreIndexed(); |
| 5725 if ((array_store == NULL) || | 5762 if ((array_store == NULL) || |
| 5726 (array_store->class_id() == kArrayCid) || | 5763 (array_store->class_id() == kArrayCid) || |
| 5727 (array_store->class_id() == kTypedDataFloat64ArrayCid) || | 5764 (array_store->class_id() == kTypedDataFloat64ArrayCid) || |
| 5765 (array_store->class_id() == kTypedDataFloat32ArrayCid) || |
| 5728 (array_store->class_id() == kTypedDataFloat32x4ArrayCid)) { | 5766 (array_store->class_id() == kTypedDataFloat32x4ArrayCid)) { |
| 5729 bool is_load = false; | 5767 bool is_load = false; |
| 5730 Place store_place(instr, &is_load); | 5768 Place store_place(instr, &is_load); |
| 5731 ASSERT(!is_load); | 5769 ASSERT(!is_load); |
| 5732 Place* place = map_->Lookup(&store_place); | 5770 Place* place = map_->Lookup(&store_place); |
| 5733 if (place != NULL) { | 5771 if (place != NULL) { |
| 5734 // Store has a corresponding numbered place that might have a | 5772 // Store has a corresponding numbered place that might have a |
| 5735 // load. Try forwarding stored value to it. | 5773 // load. Try forwarding stored value to it. |
| 5736 gen->Add(place->id()); | 5774 gen->Add(place->id()); |
| 5737 if (out_values == NULL) out_values = CreateBlockOutValues(); | 5775 if (out_values == NULL) out_values = CreateBlockOutValues(); |
| (...skipping 1695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7433 SetValue(instr, non_constant_); | 7471 SetValue(instr, non_constant_); |
| 7434 } | 7472 } |
| 7435 | 7473 |
| 7436 | 7474 |
| 7437 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { | 7475 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { |
| 7438 // TODO(kmillikin): Handle conversion. | 7476 // TODO(kmillikin): Handle conversion. |
| 7439 SetValue(instr, non_constant_); | 7477 SetValue(instr, non_constant_); |
| 7440 } | 7478 } |
| 7441 | 7479 |
| 7442 | 7480 |
| 7481 void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) { |
| 7482 // TODO(kmillikin): Handle conversion. |
| 7483 SetValue(instr, non_constant_); |
| 7484 } |
| 7485 |
| 7486 |
| 7487 void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) { |
| 7488 // TODO(kmillikin): Handle conversion. |
| 7489 SetValue(instr, non_constant_); |
| 7490 } |
| 7491 |
| 7492 |
| 7443 void ConstantPropagator::VisitInvokeMathCFunction( | 7493 void ConstantPropagator::VisitInvokeMathCFunction( |
| 7444 InvokeMathCFunctionInstr* instr) { | 7494 InvokeMathCFunctionInstr* instr) { |
| 7445 // TODO(kmillikin): Handle conversion. | 7495 // TODO(kmillikin): Handle conversion. |
| 7446 SetValue(instr, non_constant_); | 7496 SetValue(instr, non_constant_); |
| 7447 } | 7497 } |
| 7448 | 7498 |
| 7449 | 7499 |
| 7450 void ConstantPropagator::VisitMergedMath(MergedMathInstr* instr) { | 7500 void ConstantPropagator::VisitMergedMath(MergedMathInstr* instr) { |
| 7451 // TODO(srdjan): Handle merged instruction. | 7501 // TODO(srdjan): Handle merged instruction. |
| 7452 SetValue(instr, non_constant_); | 7502 SetValue(instr, non_constant_); |
| (...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8510 } | 8560 } |
| 8511 | 8561 |
| 8512 // Insert materializations at environment uses. | 8562 // Insert materializations at environment uses. |
| 8513 for (intptr_t i = 0; i < exits.length(); i++) { | 8563 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8514 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8564 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8515 } | 8565 } |
| 8516 } | 8566 } |
| 8517 | 8567 |
| 8518 | 8568 |
| 8519 } // namespace dart | 8569 } // namespace dart |
| OLD | NEW |