Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: runtime/vm/flow_graph_range_analysis.h

Issue 619903002: Generalize bounds checks. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698