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

Unified Diff: runtime/vm/flow_graph_range_analysis.cc

Issue 961443005: Fix Range::Mul for fully non-positive ranges. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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 | « runtime/vm/flow_graph_range_analysis.h ('k') | tests/language/vm/regress_22541_vm_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_range_analysis.cc
diff --git a/runtime/vm/flow_graph_range_analysis.cc b/runtime/vm/flow_graph_range_analysis.cc
index 738c294dc0246667e3ece60b14342e98f3ec3065..0a0ef94d4ee82d2ea33fe81e4cabfc7e4f06887c 100644
--- a/runtime/vm/flow_graph_range_analysis.cc
+++ b/runtime/vm/flow_graph_range_analysis.cc
@@ -2541,12 +2541,22 @@ void Range::Mul(const Range* left_range,
((left_max == 0) || (right_max <= kMaxInt64 / left_max))) {
// Product of left and right max values stays in 64 bit range.
const int64_t mul_max = left_max * right_max;
- const int64_t r_min =
- OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -mul_max;
- *result_min = RangeBoundary::FromConstant(r_min);
- const int64_t r_max =
- OnlyNegativeOrZero(*left_range, *right_range) ? 0 : mul_max;
- *result_max = RangeBoundary::FromConstant(r_max);
+ if (OnlyPositiveOrZero(*left_range, *right_range) ||
+ OnlyNegativeOrZero(*left_range, *right_range)) {
+ // If both ranges are of the same sign then the range of the result
+ // is positive and is between multiplications of absolute minimums
+ // and absolute maximums.
+ const int64_t mul_min =
+ ConstantAbsMin(left_range) * ConstantAbsMin(right_range);
+ *result_min = RangeBoundary::FromConstant(mul_min);
+ *result_max = RangeBoundary::FromConstant(mul_max);
+ } else {
+ // If ranges have mixed signs then use conservative approximation:
+ // absolute value of the result is less or equal to multiplication
+ // of absolute maximums.
+ *result_min = RangeBoundary::FromConstant(-mul_max);
+ *result_max = RangeBoundary::FromConstant(mul_max);
+ }
return;
}
@@ -2586,6 +2596,17 @@ int64_t Range::ConstantAbsMax(const Range* range) {
}
+// Return the minimum absolute value included in range.
+int64_t Range::ConstantAbsMin(const Range* range) {
+ if (range == NULL) {
+ return 0;
+ }
+ const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue());
+ const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue());
+ return Utils::Minimum(abs_min, abs_max);
+}
+
+
void Range::BinaryOp(const Token::Kind op,
const Range* left_range,
const Range* right_range,
« no previous file with comments | « runtime/vm/flow_graph_range_analysis.h ('k') | tests/language/vm/regress_22541_vm_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698