| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 #ifndef VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 5 #ifndef VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
| 6 #define VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 6 #define VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
| 7 | 7 |
| 8 #include "vm/flow_graph.h" | 8 #include "vm/flow_graph.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 | 10 |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 | 483 |
| 484 class RangeUtils : public AllStatic { | 484 class RangeUtils : public AllStatic { |
| 485 public: | 485 public: |
| 486 static bool Fits(Range* range, RangeBoundary::RangeSize size) { | 486 static bool Fits(Range* range, RangeBoundary::RangeSize size) { |
| 487 return !Range::IsUnknown(range) && range->Fits(size); | 487 return !Range::IsUnknown(range) && range->Fits(size); |
| 488 } | 488 } |
| 489 | 489 |
| 490 static bool IsWithin(Range* range, int64_t min, int64_t max) { | 490 static bool IsWithin(Range* range, int64_t min, int64_t max) { |
| 491 return !Range::IsUnknown(range) && range->IsWithin(min, max); | 491 return !Range::IsUnknown(range) && range->IsWithin(min, max); |
| 492 } | 492 } |
| 493 |
| 494 static bool IsPositive(Range* range) { |
| 495 return !Range::IsUnknown(range) && range->IsPositive(); |
| 496 } |
| 493 }; | 497 }; |
| 494 | 498 |
| 495 | 499 |
| 496 // Range analysis for integer values. | 500 // Range analysis for integer values. |
| 497 class RangeAnalysis : public ValueObject { | 501 class RangeAnalysis : public ValueObject { |
| 498 public: | 502 public: |
| 499 explicit RangeAnalysis(FlowGraph* flow_graph) | 503 explicit RangeAnalysis(FlowGraph* flow_graph) |
| 500 : flow_graph_(flow_graph), | 504 : flow_graph_(flow_graph), |
| 501 smi_range_(Range::Full(RangeBoundary::kRangeBoundarySmi)) { } | 505 smi_range_(Range::Full(RangeBoundary::kRangeBoundarySmi)) { } |
| 502 | 506 |
| 503 // Infer ranges for all values and remove overflow checks from binary smi | 507 // Infer ranges for all values and remove overflow checks from binary smi |
| 504 // operations when proven redundant. | 508 // operations when proven redundant. |
| 505 void Analyze(); | 509 void Analyze(); |
| 506 | 510 |
| 507 // Helper that should be used to access ranges of inputs during range | 511 // Helper that should be used to access ranges of inputs during range |
| 508 // inference. | 512 // inference. |
| 509 // Returns meaningful results for uses of non-smi definitions that have smi | 513 // Returns meaningful results for uses of non-smi definitions that have smi |
| 510 // as a reaching type. | 514 // as a reaching type. |
| 511 const Range* GetSmiRange(Value* value) const; | 515 const Range* GetSmiRange(Value* value) const; |
| 512 | 516 |
| 517 static bool IsIntegerDefinition(Definition* defn) { |
| 518 return (defn->Type()->ToCid() == kSmiCid) || |
| 519 defn->IsMintDefinition() || |
| 520 defn->IsInt32Definition(); |
| 521 } |
| 522 |
| 523 void AssignRangesRecursively(Definition* defn); |
| 524 |
| 513 private: | 525 private: |
| 514 enum JoinOperator { | 526 enum JoinOperator { |
| 515 NONE, | 527 NONE, |
| 516 WIDEN, | 528 WIDEN, |
| 517 NARROW | 529 NARROW |
| 518 }; | 530 }; |
| 519 static char OpPrefix(JoinOperator op); | 531 static char OpPrefix(JoinOperator op); |
| 520 | 532 |
| 521 // Collect all values that were proven to be smi in smi_values_ array and all | 533 // Collect all values that were proven to be smi in smi_values_ array and all |
| 522 // CheckSmi instructions in smi_check_ array. | 534 // CheckSmi instructions in smi_check_ array. |
| 523 void CollectValues(); | 535 void CollectValues(); |
| 524 | 536 |
| 525 // Iterate over smi values and constrain them at branch successors. | 537 // Iterate over smi values and constrain them at branch successors. |
| 526 // Additionally constraint values after CheckSmi instructions. | 538 // Additionally constraint values after CheckSmi instructions. |
| 527 void InsertConstraints(); | 539 void InsertConstraints(); |
| 528 | 540 |
| 529 // Iterate over uses of the given definition and discover branches that | 541 // Iterate over uses of the given definition and discover branches that |
| 530 // constrain it. Insert appropriate Constraint instructions at true | 542 // constrain it. Insert appropriate Constraint instructions at true |
| 531 // and false successor and rename all dominated uses to refer to a | 543 // and false successor and rename all dominated uses to refer to a |
| 532 // Constraint instead of this definition. | 544 // Constraint instead of this definition. |
| 533 void InsertConstraintsFor(Definition* defn); | 545 void InsertConstraintsFor(Definition* defn); |
| 534 | 546 |
| 535 // Create a constraint for defn, insert it after given instruction and | 547 // Create a constraint for defn, insert it after given instruction and |
| 536 // rename all uses that are dominated by it. | 548 // rename all uses that are dominated by it. |
| 537 ConstraintInstr* InsertConstraintFor(Value* use, | 549 ConstraintInstr* InsertConstraintFor(Value* use, |
| 538 Definition* defn, | 550 Definition* defn, |
| 539 Range* constraint, | 551 Range* constraint, |
| 540 Instruction* after); | 552 Instruction* after); |
| 541 | 553 |
| 542 void ConstrainValueAfterBranch(Value* use, Definition* defn); | 554 bool ConstrainValueAfterBranch(Value* use, Definition* defn); |
| 543 void ConstrainValueAfterCheckArrayBound(Value* use, Definition* defn); | 555 void ConstrainValueAfterCheckArrayBound(Value* use, Definition* defn); |
| 544 | 556 |
| 545 // Replace uses of the definition def that are dominated by instruction dom | 557 // Replace uses of the definition def that are dominated by instruction dom |
| 546 // with uses of other definition. | 558 // with uses of other definition. |
| 547 void RenameDominatedUses(Definition* def, | 559 void RenameDominatedUses(Definition* def, |
| 548 Instruction* dom, | 560 Instruction* dom, |
| 549 Definition* other); | 561 Definition* other); |
| 550 | 562 |
| 551 | 563 |
| 552 // Infer ranges for integer (smi or mint) definitions. | 564 // Infer ranges for integer (smi or mint) definitions. |
| 553 void InferRanges(); | 565 void InferRanges(); |
| 554 | 566 |
| 555 // Collect integer definition in the reverse postorder. | 567 // Collect integer definition in the reverse postorder. |
| 556 void CollectDefinitions(BlockEntryInstr* block, BitVector* set); | 568 void CollectDefinitions(BitVector* set); |
| 557 | 569 |
| 558 // Recompute ranges of all definitions until they stop changing. | 570 // Recompute ranges of all definitions until they stop changing. |
| 559 // Apply the given JoinOperator when computing Phi ranges. | 571 // Apply the given JoinOperator when computing Phi ranges. |
| 560 void Iterate(JoinOperator op, intptr_t max_iterations); | 572 void Iterate(JoinOperator op, intptr_t max_iterations); |
| 561 bool InferRange(JoinOperator op, Definition* defn, intptr_t iteration); | 573 bool InferRange(JoinOperator op, Definition* defn, intptr_t iteration); |
| 562 | 574 |
| 563 // Based on computed ranges find and eliminate redundant CheckArrayBound | 575 // Based on computed ranges find and eliminate redundant CheckArrayBound |
| 564 // instructions. | 576 // instructions. |
| 565 void EliminateRedundantBoundsChecks(); | 577 void EliminateRedundantBoundsChecks(); |
| 566 | 578 |
| 567 // Find unsatisfiable constraints and mark corresponding blocks unreachable. | 579 // Find unsatisfiable constraints and mark corresponding blocks unreachable. |
| 568 void MarkUnreachableBlocks(); | 580 void MarkUnreachableBlocks(); |
| 569 | 581 |
| 570 // Convert mint operations that stay within int32 range into Int32 operations. | 582 // Convert mint operations that stay within int32 range into Int32 operations. |
| 571 void NarrowMintToInt32(); | 583 void NarrowMintToInt32(); |
| 572 | 584 |
| 585 void DiscoverSimpleInductionVariables(); |
| 586 |
| 573 // Remove artificial Constraint instructions and replace them with actual | 587 // Remove artificial Constraint instructions and replace them with actual |
| 574 // unconstrained definitions. | 588 // unconstrained definitions. |
| 575 void RemoveConstraints(); | 589 void RemoveConstraints(); |
| 576 | 590 |
| 577 Range* ConstraintSmiRange(Token::Kind op, Definition* boundary); | 591 Range* ConstraintSmiRange(Token::Kind op, Definition* boundary); |
| 578 | 592 |
| 579 Isolate* isolate() const { return flow_graph_->isolate(); } | 593 Isolate* isolate() const { return flow_graph_->isolate(); } |
| 580 | 594 |
| 581 FlowGraph* flow_graph_; | 595 FlowGraph* flow_graph_; |
| 582 | 596 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 BitVector* selected_uint32_defs_; | 644 BitVector* selected_uint32_defs_; |
| 631 | 645 |
| 632 FlowGraph* flow_graph_; | 646 FlowGraph* flow_graph_; |
| 633 Isolate* isolate_; | 647 Isolate* isolate_; |
| 634 }; | 648 }; |
| 635 | 649 |
| 636 | 650 |
| 637 } // namespace dart | 651 } // namespace dart |
| 638 | 652 |
| 639 #endif // VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 653 #endif // VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
| OLD | NEW |