| 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/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| 11 #include "vm/hash_map.h" | 11 #include "vm/hash_map.h" |
| 12 #include "vm/il_printer.h" | 12 #include "vm/il_printer.h" |
| 13 #include "vm/intermediate_language.h" | 13 #include "vm/intermediate_language.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/parser.h" | 15 #include "vm/parser.h" |
| 16 #include "vm/resolver.h" | 16 #include "vm/resolver.h" |
| 17 #include "vm/scopes.h" | 17 #include "vm/scopes.h" |
| 18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 19 | 19 |
| 20 namespace dart { | 20 namespace dart { |
| 21 | 21 |
| 22 DECLARE_FLAG(bool, eliminate_type_checks); | |
| 23 DECLARE_FLAG(bool, enable_type_checks); | |
| 24 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); | |
| 25 DECLARE_FLAG(bool, trace_type_check_elimination); | |
| 26 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); | |
| 27 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); | |
| 28 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); | |
| 29 DEFINE_FLAG(bool, trace_constant_propagation, false, | |
| 30 "Print constant propagation and useless code elimination."); | |
| 31 DEFINE_FLAG(bool, array_bounds_check_elimination, true, | 22 DEFINE_FLAG(bool, array_bounds_check_elimination, true, |
| 32 "Eliminate redundant bounds checks."); | 23 "Eliminate redundant bounds checks."); |
| 24 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); |
| 33 DEFINE_FLAG(int, max_polymorphic_checks, 4, | 25 DEFINE_FLAG(int, max_polymorphic_checks, 4, |
| 34 "Maximum number of polymorphic check, otherwise it is megamorphic."); | 26 "Maximum number of polymorphic check, otherwise it is megamorphic."); |
| 35 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); | 27 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); |
| 28 DEFINE_FLAG(bool, trace_constant_propagation, false, |
| 29 "Print constant propagation and useless code elimination."); |
| 30 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
| 31 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); |
| 36 DEFINE_FLAG(bool, truncating_left_shift, true, | 32 DEFINE_FLAG(bool, truncating_left_shift, true, |
| 37 "Optimize left shift to truncate if possible"); | 33 "Optimize left shift to truncate if possible"); |
| 34 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
| 35 DECLARE_FLAG(bool, eliminate_type_checks); |
| 36 DECLARE_FLAG(bool, enable_type_checks); |
| 37 DECLARE_FLAG(bool, trace_type_check_elimination); |
| 38 |
| 38 | 39 |
| 39 | 40 |
| 40 void FlowGraphOptimizer::ApplyICData() { | 41 void FlowGraphOptimizer::ApplyICData() { |
| 41 VisitBlocks(); | 42 VisitBlocks(); |
| 42 } | 43 } |
| 43 | 44 |
| 44 | 45 |
| 45 // Attempts to convert an instance call (IC call) using propagated class-ids, | 46 // Attempts to convert an instance call (IC call) using propagated class-ids, |
| 46 // e.g., receiver class id. | 47 // e.g., receiver class id. |
| 47 void FlowGraphOptimizer::ApplyClassIds() { | 48 void FlowGraphOptimizer::ApplyClassIds() { |
| (...skipping 2292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2340 case Token::kLT: return Token::kGT; | 2341 case Token::kLT: return Token::kGT; |
| 2341 case Token::kGT: return Token::kLT; | 2342 case Token::kGT: return Token::kLT; |
| 2342 case Token::kLTE: return Token::kGTE; | 2343 case Token::kLTE: return Token::kGTE; |
| 2343 case Token::kGTE: return Token::kLTE; | 2344 case Token::kGTE: return Token::kLTE; |
| 2344 default: | 2345 default: |
| 2345 UNREACHABLE(); | 2346 UNREACHABLE(); |
| 2346 return Token::kILLEGAL; | 2347 return Token::kILLEGAL; |
| 2347 } | 2348 } |
| 2348 } | 2349 } |
| 2349 | 2350 |
| 2350 // For a comparison operation return an operation for the negated comparison: | |
| 2351 // !(a (op) b) === a (op') b | |
| 2352 static Token::Kind NegateComparison(Token::Kind op) { | |
| 2353 switch (op) { | |
| 2354 case Token::kEQ: return Token::kNE; | |
| 2355 case Token::kNE: return Token::kEQ; | |
| 2356 case Token::kLT: return Token::kGTE; | |
| 2357 case Token::kGT: return Token::kLTE; | |
| 2358 case Token::kLTE: return Token::kGT; | |
| 2359 case Token::kGTE: return Token::kLT; | |
| 2360 default: | |
| 2361 UNREACHABLE(); | |
| 2362 return Token::kILLEGAL; | |
| 2363 } | |
| 2364 } | |
| 2365 | |
| 2366 | 2351 |
| 2367 // Given a boundary (right operand) and a comparison operation return | 2352 // Given a boundary (right operand) and a comparison operation return |
| 2368 // a symbolic range constraint for the left operand of the comparison assuming | 2353 // a symbolic range constraint for the left operand of the comparison assuming |
| 2369 // that it evaluated to true. | 2354 // that it evaluated to true. |
| 2370 // For example for the comparison a < b symbol a is constrained with range | 2355 // For example for the comparison a < b symbol a is constrained with range |
| 2371 // [Smi::kMinValue, b - 1]. | 2356 // [Smi::kMinValue, b - 1]. |
| 2372 static Range* ConstraintRange(Token::Kind op, Definition* boundary) { | 2357 static Range* ConstraintRange(Token::Kind op, Definition* boundary) { |
| 2373 switch (op) { | 2358 switch (op) { |
| 2374 case Token::kEQ: | 2359 case Token::kEQ: |
| 2375 return new Range(RangeBoundary::FromDefinition(boundary), | 2360 return new Range(RangeBoundary::FromDefinition(boundary), |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2435 ConstraintRange(op_kind, boundary), | 2420 ConstraintRange(op_kind, boundary), |
| 2436 branch->true_successor()); | 2421 branch->true_successor()); |
| 2437 // Mark true_constraint an artificial use of boundary. This ensures | 2422 // Mark true_constraint an artificial use of boundary. This ensures |
| 2438 // that constraint's range is recalculated if boundary's range changes. | 2423 // that constraint's range is recalculated if boundary's range changes. |
| 2439 if (true_constraint != NULL) true_constraint->AddDependency(boundary); | 2424 if (true_constraint != NULL) true_constraint->AddDependency(boundary); |
| 2440 | 2425 |
| 2441 // Constrain definition with a negated condition at the false successor. | 2426 // Constrain definition with a negated condition at the false successor. |
| 2442 ConstraintInstr* false_constraint = | 2427 ConstraintInstr* false_constraint = |
| 2443 InsertConstraintFor( | 2428 InsertConstraintFor( |
| 2444 defn, | 2429 defn, |
| 2445 ConstraintRange(NegateComparison(op_kind), boundary), | 2430 ConstraintRange(Token::NegateComparison(op_kind), boundary), |
| 2446 branch->false_successor()); | 2431 branch->false_successor()); |
| 2447 // Mark false_constraint an artificial use of boundary. This ensures | 2432 // Mark false_constraint an artificial use of boundary. This ensures |
| 2448 // that constraint's range is recalculated if boundary's range changes. | 2433 // that constraint's range is recalculated if boundary's range changes. |
| 2449 if (false_constraint != NULL) false_constraint->AddDependency(boundary); | 2434 if (false_constraint != NULL) false_constraint->AddDependency(boundary); |
| 2450 } | 2435 } |
| 2451 } | 2436 } |
| 2452 | 2437 |
| 2453 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { | 2438 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { |
| 2454 for (Value* use = defn->input_use_list(); | 2439 for (Value* use = defn->input_use_list(); |
| 2455 use != NULL; | 2440 use != NULL; |
| (...skipping 2173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4629 if (changed) { | 4614 if (changed) { |
| 4630 // We may have changed the block order and the dominator tree. | 4615 // We may have changed the block order and the dominator tree. |
| 4631 flow_graph->DiscoverBlocks(); | 4616 flow_graph->DiscoverBlocks(); |
| 4632 GrowableArray<BitVector*> dominance_frontier; | 4617 GrowableArray<BitVector*> dominance_frontier; |
| 4633 flow_graph->ComputeDominators(&dominance_frontier); | 4618 flow_graph->ComputeDominators(&dominance_frontier); |
| 4634 } | 4619 } |
| 4635 } | 4620 } |
| 4636 | 4621 |
| 4637 | 4622 |
| 4638 } // namespace dart | 4623 } // namespace dart |
| OLD | NEW |