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

Unified Diff: runtime/vm/flow_graph_range_analysis.h

Issue 477193002: Reland r39293. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/flow_graph_range_analysis.cc » ('j') | runtime/vm/flow_graph_range_analysis.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_range_analysis.h
diff --git a/runtime/vm/flow_graph_range_analysis.h b/runtime/vm/flow_graph_range_analysis.h
index f9ae03664a1851ce62094763615ae290a39b243f..135cca0fa5720087728b48db7fa6b9b01a0454cf 100644
--- a/runtime/vm/flow_graph_range_analysis.h
+++ b/runtime/vm/flow_graph_range_analysis.h
@@ -84,9 +84,33 @@ class RangeBoundary : public ValueObject {
return FromConstant(kMax);
}
- // Calculate the minimum of a and b within the given range.
- static RangeBoundary Min(RangeBoundary a, RangeBoundary b, RangeSize size);
- static RangeBoundary Max(RangeBoundary a, RangeBoundary b, RangeSize size);
+ // Given two boundaries a and b, select one of them as c so that
+ //
+ // inf {[a, ...) ^ [b, ...)} >= inf {c}
+ //
+ static RangeBoundary IntersectionMin(RangeBoundary a, RangeBoundary b);
+
+ // Given two boundaries a and b, select one of them as c so that
+ //
+ // sup {(..., a] ^ (..., b]} <= sup {c}
+ //
+ static RangeBoundary IntersectionMax(RangeBoundary a, RangeBoundary b);
+
+ // Given two boundaries a and b compute boundary c such that
+ //
+ // inf {[a, ...) U [b, ...)} >= inf {c}
+ //
+ // Try to select c such that it is as close to inf {[a, ...) U [b, ...)}
+ // as possible.
+ static RangeBoundary JoinMin(RangeBoundary a, RangeBoundary b);
+
+ // Given two boundaries a and b compute boundary c such that
+ //
+ // sup {(..., a] U (..., b]} <= sup {c}
+ //
+ // Try to select c such that it is as close to sup {(..., a] U (..., b]}
+ // as possible.
+ static RangeBoundary JoinMax(RangeBoundary a, RangeBoundary b);
// Returns true when this is a constant that is outside of Smi range.
bool OverflowedSmi() const {
@@ -119,7 +143,6 @@ class RangeBoundary : public ValueObject {
return *this;
}
-
bool IsSmiMinimumOrBelow() const {
return IsNegativeInfinity() ||
(IsConstant() && (ConstantValue() <= Smi::kMinValue));
@@ -222,6 +245,14 @@ class RangeBoundary : public ValueObject {
bool Equals(const RangeBoundary& other) const;
+ int64_t SmiUpperBound() const {
+ return UpperBound().Clamp(kRangeBoundarySmi).ConstantValue();
+ }
+
+ int64_t SmiLowerBound() const {
+ return LowerBound().Clamp(kRangeBoundarySmi).ConstantValue();
+ }
+
private:
RangeBoundary(Kind kind, int64_t value, int64_t offset)
: kind_(kind), value_(value), offset_(offset) { }
@@ -234,23 +265,59 @@ class RangeBoundary : public ValueObject {
class Range : public ZoneAllocated {
public:
- Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { }
+ Range() : min_(), max_() { }
+ Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) {
+ ASSERT(min_.IsUnknown() == max_.IsUnknown());
+ }
- static Range* Unknown() {
- return new Range(RangeBoundary::MinConstant(),
- RangeBoundary::MaxConstant());
+ Range(const Range& other)
+ : ZoneAllocated(),
+ min_(other.min_),
+ max_(other.max_) {
}
- static Range* UnknownSmi() {
- return new Range(RangeBoundary::MinSmi(),
- RangeBoundary::MaxSmi());
+ Range& operator=(const Range& other) {
+ min_ = other.min_;
+ max_ = other.max_;
+ return *this;
+ }
+
+ static bool IsUnknown(const Range* other) {
+ if (other == NULL) {
+ return true;
+ }
+ return other->min().IsUnknown();
+ }
+
+ static Range Full(RangeBoundary::RangeSize size) {
+ if (size == RangeBoundary::kRangeBoundarySmi) {
+ return Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi());
+ } else {
+ ASSERT(size == RangeBoundary::kRangeBoundaryInt64);
+ return Range(RangeBoundary::MinConstant(), RangeBoundary::MaxConstant());
+ }
}
void PrintTo(BufferFormatter* f) const;
static const char* ToCString(const Range* range);
+ bool Equals(const Range* other) {
+ ASSERT(min_.IsUnknown() == max_.IsUnknown());
+ if (other == NULL) {
+ return min_.IsUnknown();
+ }
+ return min_.Equals(other->min_) &&
+ max_.Equals(other->max_);
+ }
+
const RangeBoundary& min() const { return min_; }
const RangeBoundary& max() const { return max_; }
+ void set_min(const RangeBoundary& value) {
+ min_ = value;
+ }
+ void set_max(const RangeBoundary& value) {
+ max_ = value;
+ }
static RangeBoundary ConstantMinSmi(const Range* range) {
if (range == NULL) {
@@ -301,6 +368,11 @@ class Range : public ZoneAllocated {
return !min_.IsInfinity() && !max_.IsInfinity();
}
+ Range Intersect(const Range* other) const {
+ return Range(RangeBoundary::IntersectionMin(min(), other->min()),
+ RangeBoundary::IntersectionMax(max(), other->max()));
+ }
+
// Clamp this to be within size.
void Clamp(RangeBoundary::RangeSize size);
@@ -345,10 +417,11 @@ class Range : public ZoneAllocated {
// Return the maximum absolute value included in range.
static int64_t ConstantAbsMax(const Range* range);
- static Range* BinaryOp(const Token::Kind op,
- const Range* left_range,
- const Range* right_range,
- Definition* left_defn);
+ static void BinaryOp(const Token::Kind op,
+ const Range* left_range,
+ const Range* right_range,
+ Definition* left_defn,
+ Range* result);
private:
RangeBoundary min_;
@@ -361,13 +434,26 @@ class RangeAnalysis : public ValueObject {
public:
explicit RangeAnalysis(FlowGraph* flow_graph)
: flow_graph_(flow_graph),
- marked_defns_(NULL) { }
+ smi_range_(Range::Full(RangeBoundary::kRangeBoundarySmi)) { }
// Infer ranges for all values and remove overflow checks from binary smi
// operations when proven redundant.
void Analyze();
+ // Helper that should be used to access ranges of inputs during range
+ // inference.
+ // Returns meaningful results for uses of non-smi definitions that have smi
+ // as a reaching type.
+ const Range* GetRange(Value* value) const;
+
private:
+ enum JoinOperator {
+ NONE,
+ WIDEN,
+ NARROW
+ };
+ static char OpPrefix(JoinOperator op);
+
// Collect all values that were proven to be smi in smi_values_ array and all
// CheckSmi instructions in smi_check_ array.
void CollectValues();
@@ -384,14 +470,13 @@ class RangeAnalysis : public ValueObject {
// Create a constraint for defn, insert it after given instruction and
// rename all uses that are dominated by it.
- ConstraintInstr* InsertConstraintFor(Definition* defn,
+ ConstraintInstr* InsertConstraintFor(Value* use,
+ Definition* defn,
Range* constraint,
Instruction* after);
- void ConstrainValueAfterBranch(Definition* defn, Value* use);
- void ConstrainValueAfterCheckArrayBound(Definition* defn,
- CheckArrayBoundInstr* check,
- intptr_t use_index);
+ void ConstrainValueAfterBranch(Value* use, Definition* defn);
+ void ConstrainValueAfterCheckArrayBound(Value* use, Definition* defn);
// Replace uses of the definition def that are dominated by instruction dom
// with uses of other definition.
@@ -400,62 +485,50 @@ class RangeAnalysis : public ValueObject {
Definition* other);
- // Walk the dominator tree and infer ranges for smi values.
+ // Infer ranges for integer (smi or mint) definitions.
void InferRanges();
- void InferRangesRecursive(BlockEntryInstr* block);
-
- enum Direction {
- kUnknown,
- kPositive,
- kNegative,
- kBoth
- };
-
- Range* InferInductionVariableRange(JoinEntryInstr* loop_header,
- PhiInstr* var);
- void ResetWorklist();
- void MarkDefinition(Definition* defn);
+ // Collect integer definition in the reverse postorder.
+ void CollectDefinitions(BlockEntryInstr* block, BitVector* set);
- static Direction ToDirection(Value* val);
+ // Recompute ranges of all definitions until they stop changing.
+ // Apply the given JoinOperator when computing Phi ranges.
+ void Iterate(JoinOperator op, intptr_t max_iterations);
+ bool InferRange(JoinOperator op, Definition* defn, intptr_t iteration);
- static Direction Invert(Direction direction) {
- return (direction == kPositive) ? kNegative : kPositive;
- }
+ // Based on computed ranges find and eliminate redundant CheckArrayBound
+ // instructions.
+ void EliminateRedundantBoundsChecks();
- static void UpdateDirection(Direction* direction,
- Direction new_direction) {
- if (*direction != new_direction) {
- if (*direction != kUnknown) new_direction = kBoth;
- *direction = new_direction;
- }
- }
+ // Find unsatisfiable constraints and mark corresponding blocks unreachable.
+ void MarkUnreachableBlocks();
// Remove artificial Constraint instructions and replace them with actual
// unconstrained definitions.
void RemoveConstraints();
- Range* ConstraintRange(Token::Kind op, Definition* boundary);
+ Range* ConstraintSmiRange(Token::Kind op, Definition* boundary);
Isolate* isolate() const { return flow_graph_->isolate(); }
FlowGraph* flow_graph_;
+ // Range object representing full Smi range.
+ Range smi_range_;
+
// Value that are known to be smi or mint.
GrowableArray<Definition*> values_;
- // All CheckSmi instructions.
- GrowableArray<CheckSmiInstr*> smi_checks_;
+
+ // All CheckArrayBound instructions.
+ GrowableArray<CheckArrayBoundInstr*> bounds_checks_;
// All Constraints inserted during InsertConstraints phase. They are treated
// as smi values.
GrowableArray<ConstraintInstr*> constraints_;
- // Bitvector for a quick filtering of known smi or mint values.
- BitVector* definitions_;
-
- // Worklist for induction variables analysis.
- GrowableArray<Definition*> worklist_;
- BitVector* marked_defns_;
+ // List of integer (smi or mint) definitions including constraints sorted
+ // in the reverse postorder.
+ GrowableArray<Definition*> definitions_;
DISALLOW_COPY_AND_ASSIGN(RangeAnalysis);
};
« no previous file with comments | « no previous file | runtime/vm/flow_graph_range_analysis.cc » ('j') | runtime/vm/flow_graph_range_analysis.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698