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 |