Chromium Code Reviews| 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 set_previous(NULL); | 600 set_previous(NULL); |
| 601 set_next(NULL); | 601 set_next(NULL); |
| 602 } | 602 } |
| 603 | 603 |
| 604 | 604 |
| 605 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) | 605 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) |
| 606 : comparison_(comparison), | 606 : comparison_(comparison), |
| 607 is_checked_(is_checked), | 607 is_checked_(is_checked), |
| 608 constrained_type_(NULL), | 608 constrained_type_(NULL), |
| 609 constant_target_(NULL) { | 609 constant_target_(NULL) { |
| 610 ASSERT(comparison->env() == NULL); | |
| 610 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { | 611 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { |
| 611 comparison->InputAt(i)->set_instruction(this); | 612 comparison->InputAt(i)->set_instruction(this); |
| 612 } | 613 } |
| 613 } | 614 } |
| 614 | 615 |
| 615 | 616 |
| 616 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { | 617 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { |
| 617 comparison()->RawSetInputAt(i, value); | 618 comparison()->RawSetInputAt(i, value); |
| 618 } | 619 } |
| 619 | 620 |
| 620 | 621 |
| 621 // A misleadingly named function for use in template functions that replace | 622 // A misleadingly named function for use in template functions that replace |
| 622 // both definitions with definitions and branch comparisons with | 623 // both definitions with definitions and branch comparisons with |
| 623 // comparisons. In the branch case, leave the branch intact and replace its | 624 // comparisons. In the branch case, leave the branch intact and replace its |
| 624 // comparison with a new comparison not currently in the graph. | 625 // comparison with a new comparison not currently in the graph. |
| 625 void BranchInstr::ReplaceWith(ComparisonInstr* other, | 626 void BranchInstr::ReplaceWith(ComparisonInstr* other, |
| 626 ForwardInstructionIterator* ignored) { | 627 ForwardInstructionIterator* ignored) { |
| 627 SetComparison(other); | 628 SetComparison(other); |
| 628 } | 629 } |
| 629 | 630 |
| 630 | 631 |
| 631 void BranchInstr::SetComparison(ComparisonInstr* comp) { | 632 void BranchInstr::SetComparison(ComparisonInstr* comp) { |
| 632 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { | 633 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { |
| 633 Value* input = comp->InputAt(i); | 634 Value* input = comp->InputAt(i); |
| 634 input->definition()->AddInputUse(input); | 635 input->definition()->AddInputUse(input); |
| 635 input->set_instruction(this); | 636 input->set_instruction(this); |
| 636 } | 637 } |
| 637 // There should be no need to copy or unuse an environment. | 638 // There should be no need to copy or unuse an environment. |
| 638 ASSERT(comparison()->env() == NULL); | 639 ASSERT(comparison()->env() == NULL); |
| 640 ASSERT(comp->env() == NULL); | |
| 639 // Remove the current comparison's input uses. | 641 // Remove the current comparison's input uses. |
|
srdjan
2013/04/15 20:27:27
Would be probable more readable if CompareInstr* w
Vyacheslav Egorov (Google)
2013/04/16 11:51:16
I think instr is somewhat confusing as well. I ren
| |
| 640 comparison()->UnuseAllInputs(); | 642 comparison()->UnuseAllInputs(); |
| 641 ASSERT(!comp->HasUses()); | 643 ASSERT(!comp->HasUses()); |
| 642 comparison_ = comp; | 644 comparison_ = comp; |
| 643 } | 645 } |
| 644 | 646 |
| 645 | 647 |
| 646 // ==== Postorder graph traversal. | 648 // ==== Postorder graph traversal. |
| 647 static bool IsMarked(BlockEntryInstr* block, | 649 static bool IsMarked(BlockEntryInstr* block, |
| 648 GrowableArray<BlockEntryInstr*>* preorder) { | 650 GrowableArray<BlockEntryInstr*>* preorder) { |
| 649 // Detect that a block has been visited as part of the current | 651 // Detect that a block has been visited as part of the current |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1226 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); | 1228 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); |
| 1227 // It is ok to insert instructions before the current during | 1229 // It is ok to insert instructions before the current during |
| 1228 // forward iteration. | 1230 // forward iteration. |
| 1229 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue); | 1231 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue); |
| 1230 instantiator_type_arguments()->BindTo(null_constant); | 1232 instantiator_type_arguments()->BindTo(null_constant); |
| 1231 } | 1233 } |
| 1232 return this; | 1234 return this; |
| 1233 } | 1235 } |
| 1234 | 1236 |
| 1235 | 1237 |
| 1238 static bool RecognizeTestPattern(Value* left, Value* right) { | |
|
srdjan
2013/04/15 20:27:27
Add comment what pattern is being recognized.
Vyacheslav Egorov (Google)
2013/04/16 11:51:16
Done.
| |
| 1239 if (!right->BindsToConstant()) { | |
| 1240 return false; | |
| 1241 } | |
| 1242 | |
| 1243 const Object& value = right->BoundConstant(); | |
| 1244 if (!value.IsSmi() || (Smi::Cast(value).Value() != 0)) { | |
| 1245 return false; | |
| 1246 } | |
| 1247 | |
| 1248 Definition* left_defn = left->definition(); | |
| 1249 return left_defn->IsBinarySmiOp() && | |
| 1250 (left_defn->AsBinarySmiOp()->op_kind() == Token::kBIT_AND) && | |
| 1251 left_defn->HasOnlyUse(left); | |
| 1252 } | |
| 1253 | |
| 1254 | |
| 1236 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1255 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1237 // Only handle strict-compares. | 1256 // Only handle strict-compares. |
| 1238 if (comparison()->IsStrictCompare()) { | 1257 if (comparison()->IsStrictCompare()) { |
| 1239 Definition* replacement = comparison()->Canonicalize(optimizer); | 1258 Definition* replacement = comparison()->Canonicalize(optimizer); |
| 1240 if ((replacement == comparison()) || (replacement == NULL)) { | 1259 if ((replacement == comparison()) || (replacement == NULL)) { |
| 1241 return this; | 1260 return this; |
| 1242 } | 1261 } |
| 1243 ComparisonInstr* comp = replacement->AsComparison(); | 1262 ComparisonInstr* comp = replacement->AsComparison(); |
| 1244 if ((comp == NULL) || comp->CanDeoptimize()) { | 1263 if ((comp == NULL) || comp->CanDeoptimize()) { |
| 1245 return this; | 1264 return this; |
| 1246 } | 1265 } |
| 1247 | 1266 |
| 1248 // Check that comparison is not serving as a pending deoptimization target | 1267 // Check that comparison is not serving as a pending deoptimization target |
| 1249 // for conversions. | 1268 // for conversions. |
| 1250 for (intptr_t i = 0; i < comp->InputCount(); i++) { | 1269 for (intptr_t i = 0; i < comp->InputCount(); i++) { |
| 1251 if (comp->RequiredInputRepresentation(i) != | 1270 if (comp->RequiredInputRepresentation(i) != |
| 1252 comp->InputAt(i)->definition()->representation()) { | 1271 comp->InputAt(i)->definition()->representation()) { |
| 1253 return this; | 1272 return this; |
| 1254 } | 1273 } |
| 1255 } | 1274 } |
| 1256 | 1275 |
| 1257 // Replace the comparison if the replacement is used at this branch, | 1276 // Replace the comparison if the replacement is used at this branch, |
| 1258 // and has exactly one use. | 1277 // and has exactly one use. |
| 1259 Value* use = comp->input_use_list(); | 1278 Value* use = comp->input_use_list(); |
| 1260 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { | 1279 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { |
| 1261 RemoveEnvironment(); | 1280 RemoveEnvironment(); |
| 1262 InheritDeoptTarget(comp); | 1281 InheritDeoptTarget(comp); |
| 1263 | 1282 |
| 1283 comp->RemoveEnvironment(); | |
| 1264 comp->RemoveFromGraph(); | 1284 comp->RemoveFromGraph(); |
| 1265 SetComparison(comp); | 1285 SetComparison(comp); |
| 1266 if (FLAG_trace_optimization) { | 1286 if (FLAG_trace_optimization) { |
| 1267 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); | 1287 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); |
| 1268 } | 1288 } |
| 1269 // Clear the comparison's temp index and ssa temp index since the | 1289 // Clear the comparison's temp index and ssa temp index since the |
| 1270 // value of the comparison is not used outside the branch anymore. | 1290 // value of the comparison is not used outside the branch anymore. |
| 1271 ASSERT(comp->input_use_list() == NULL); | 1291 ASSERT(comp->input_use_list() == NULL); |
| 1272 comp->ClearSSATempIndex(); | 1292 comp->ClearSSATempIndex(); |
| 1273 comp->ClearTempIndex(); | 1293 comp->ClearTempIndex(); |
| 1274 } | 1294 } |
| 1295 } else if (comparison()->IsSmiEquality()) { | |
| 1296 BinarySmiOpInstr* bit_and = NULL; | |
| 1297 if (RecognizeTestPattern(comparison()->left(), comparison()->right())) { | |
| 1298 bit_and = comparison()->left()->definition()->AsBinarySmiOp(); | |
| 1299 } else if (RecognizeTestPattern(comparison()->right(), | |
| 1300 comparison()->left())) { | |
| 1301 bit_and = comparison()->right()->definition()->AsBinarySmiOp(); | |
| 1302 } | |
| 1303 | |
| 1304 if (bit_and != NULL) { | |
| 1305 TestSmiInstr* test = new TestSmiInstr(comparison()->kind(), | |
| 1306 bit_and->left()->Copy(), | |
| 1307 bit_and->right()->Copy()); | |
| 1308 ASSERT(!CanDeoptimize()); | |
| 1309 InheritDeoptTarget(bit_and); | |
| 1310 RemoveEnvironment(); | |
| 1311 SetComparison(test); | |
| 1312 bit_and->RemoveFromGraph(); | |
| 1313 } | |
| 1275 } | 1314 } |
| 1276 return this; | 1315 return this; |
| 1277 } | 1316 } |
| 1278 | 1317 |
| 1279 | 1318 |
| 1280 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1319 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1281 if (!right()->BindsToConstant()) { | 1320 if (!right()->BindsToConstant()) { |
| 1282 return this; | 1321 return this; |
| 1283 } | 1322 } |
| 1284 const Object& right_constant = right()->BoundConstant(); | 1323 const Object& right_constant = right()->BoundConstant(); |
| (...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2388 default: | 2427 default: |
| 2389 UNREACHABLE(); | 2428 UNREACHABLE(); |
| 2390 } | 2429 } |
| 2391 return kPowRuntimeEntry; | 2430 return kPowRuntimeEntry; |
| 2392 } | 2431 } |
| 2393 | 2432 |
| 2394 | 2433 |
| 2395 #undef __ | 2434 #undef __ |
| 2396 | 2435 |
| 2397 } // namespace dart | 2436 } // namespace dart |
| OLD | NEW |