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

Unified Diff: lib/compiler/implementation/ssa/value_range_analyzer.dart

Issue 10986085: Deal with more conditional expressions in the value range analyzer. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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
Index: lib/compiler/implementation/ssa/value_range_analyzer.dart
===================================================================
--- lib/compiler/implementation/ssa/value_range_analyzer.dart (revision 13020)
+++ lib/compiler/implementation/ssa/value_range_analyzer.dart (working copy)
@@ -298,10 +298,22 @@
return other.lower == lower && other.upper == upper;
}
- bool isLessThan(Range other) {
+ bool operator <(Range other) {
return upper != other.lower && upper.min(other.lower) == upper;
}
+ bool operator >(Range other) {
+ return lower != other.upper && lower.max(other.upper) == lower;
+ }
+
+ bool operator <=(Range other) {
+ return upper.min(other.lower) == upper;
+ }
+
+ bool operator >=(Range other) {
+ return lower.max(other.upper) == lower;
+ }
+
bool isNegative() => upper.isNegative();
bool isPositive() => lower.isPositive();
@@ -435,7 +447,7 @@
if (indexRange.isPositive() && belowLength) {
check.block.rewrite(check, check.index);
check.block.remove(check);
- } else if (indexRange.isNegative() || lengthRange.isLessThan(indexRange)) {
+ } else if (indexRange.isNegative() || lengthRange < indexRange) {
check.staticChecks = HBoundsCheck.ALWAYS_FALSE;
// The check is always false, and whatever instruction it
// dominates is dead code.
@@ -471,24 +483,39 @@
return indexRange;
}
- Range visitLess(HLess less) {
- HInstruction right = less.right;
- HInstruction left = less.left;
+ Range visitRelational(HRelation relational) {
+ HInstruction right = relational.right;
+ HInstruction left = relational.left;
if (!left.isInteger(types)) return const Range.unbound();
if (!right.isInteger(types)) return const Range.unbound();
- if (ranges[left].isLessThan(ranges[right])) {
- less.block.rewrite(less, graph.addConstantBool(true, constantSystem));
- less.block.remove(less);
- return const Range.unbound();
+ Operation operation = relational.operation(constantSystem);
+ Range rightRange = ranges[relational.right];
+ Range leftRange = ranges[relational.left];
+
+ if (relational is HEquals || relational is HIdentity) {
+ handleEqualityCheck(relational);
+ } else if (operation.apply(leftRange, rightRange)) {
+ relational.block.rewrite(
+ relational, graph.addConstantBool(true, constantSystem));
+ relational.block.remove(relational);
+ } else if (reverseOperation(operation).apply(leftRange, rightRange)) {
+ relational.block.rewrite(
+ relational, graph.addConstantBool(false, constantSystem));
+ relational.block.remove(relational);
}
- if (ranges[right].isLessThan(ranges[left])) {
- less.block.rewrite(less, graph.addConstantBool(false, constantSystem));
- less.block.remove(less);
- return const Range.unbound();
- }
return const Range.unbound();
}
+ void handleEqualityCheck(HRelational node) {
+ Range right = ranges[node.right];
+ Range left = ranges[node.left];
+ if (left.lower == left.upper && left == right) {
Søren Gjesse 2012/10/02 08:07:20 Maybe have an isSingleValue on Range and express t
ngeoffray 2012/10/04 08:51:08 Done.
+ node.block.rewrite(
+ node, graph.addConstantBool(true, constantSystem));
+ node.block.remove(node);
+ }
+ }
+
Range handleBinaryOperation(HBinaryArithmetic instruction) {
if (!instruction.isInteger(types)) return const Range.unbound();
return instruction.operation(constantSystem).apply(
@@ -550,31 +577,85 @@
return newInstruction;
}
+ static Operation reverseOperation(BinaryOperation operation) {
+ if (operation == const LessOperation()) {
+ return const GreaterEqualOperation();
+ } else if (operation == const LessEqualOperation()) {
+ return const GreaterOperation();
+ } else if (operation == const GreaterOperation()) {
+ return const LessEqualOperation();
+ } else if (operation == const GreaterEqualOperation()) {
+ return const LessOperation();
+ } else {
+ return null;
+ }
+ }
+
+ static Range computeNewRange(BinaryOperation operation, Range range) {
+ if (operation == const LessOperation()) {
+ return new Range(const MinIntValue(), range.upper - const IntValue(1));
+ } else if (operation == const LessEqualOperation()) {
+ return new Range(const MinIntValue(), range.upper);
+ } else if (operation == const GreaterOperation()) {
+ return new Range(range.lower + const IntValue(1), const MaxIntValue());
+ } else if (operation == const GreaterEqualOperation()) {
+ return new Range(range.lower, const MaxIntValue());
+ } else {
+ return const Range.unbound();
+ }
+ }
+
Range visitConditionalBranch(HConditionalBranch branch) {
var condition = branch.condition;
- // TODO(ngeoffray): Handle more condition kinds.
- if (condition is !HLess) return const Range.unbound();
+ // TODO(ngeoffray): Handle complex conditions.
+ if (condition is !HRelational) return const Range.unbound();
+ if (condition is HEquals) return const Range.unbound();
+ if (condition is HIdentity) return const Range.unbound();
HInstruction right = condition.right;
HInstruction left = condition.left;
if (!left.isInteger(types)) return const Range.unbound();
if (!right.isInteger(types)) return const Range.unbound();
- // Update the true branch to use a narrower range for [left].
- // TODO(ngeoffray): Also do it for [right].
- HInstruction instruction =
- createRangeConversion(branch.trueBranch.first, left);
- Range range = new Range(
- const MinIntValue(), ranges[right].upper - const IntValue(1));
- range = range.intersection(ranges[left]);
- ranges[instruction] = range;
+ Range rightRange = ranges[right];
+ Range leftRange = ranges[left];
+ Operation operation = condition.operation(constantSystem);
+ Operation reverse = reverseOperation(operation);
+ // Update the true branch to use narrower ranges for [left] and
+ // [right].
+ Range range = computeNewRange(operation, rightRange);
Søren Gjesse 2012/10/02 08:07:20 Wouldn't it be better to include the intersection
ngeoffray 2012/10/02 16:03:09 Not sure I understand that comment. Could you expa
Søren Gjesse 2012/10/02 16:26:56 What I ment was to change Range range = compute
ngeoffray 2012/10/04 08:51:08 Done.
+ range = range.intersection(leftRange);
+ if (leftRange != range) {
+ HInstruction instruction =
+ createRangeConversion(branch.trueBranch.first, left);
+ ranges[instruction] = range;
+ }
- // Update the false branch to use a narrower range for [left].
- // TODO(ngeoffray): Also do it for [right].
- instruction = createRangeConversion(branch.falseBranch.first, left);
- range = new Range(ranges[right].lower, const MaxIntValue());
- range = range.intersection(ranges[left]);
- ranges[instruction] = range;
+ range = computeNewRange(reverse, leftRange);
+ range = range.intersection(rightRange);
+ if (rightRange != range) {
+ HInstruction instruction =
+ createRangeConversion(branch.trueBranch.first, right);
+ ranges[instruction] = range;
+ }
+ // Update the false branch to use narrower ranges for [left] and
+ // [right].
+ range = computeNewRange(reverse, rightRange);
+ range = range.intersection(leftRange);
+ if (leftRange != range) {
+ HInstruction instruction =
+ createRangeConversion(branch.falseBranch.first, left);
+ ranges[instruction] = range;
+ }
+
+ range = computeNewRange(operation, leftRange);
+ range = range.intersection(rightRange);
+ if (rightRange != range) {
+ HInstruction instruction =
+ createRangeConversion(branch.falseBranch.first, right);
+ ranges[instruction] = range;
+ }
+
return const Range.unbound();
}

Powered by Google App Engine
This is Rietveld 408576698