Index: dart/runtime/vm/flow_graph_range_analysis.cc |
=================================================================== |
--- dart/runtime/vm/flow_graph_range_analysis.cc (revision 44047) |
+++ dart/runtime/vm/flow_graph_range_analysis.cc (working copy) |
@@ -2540,12 +2540,22 @@ |
((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; |
} |
@@ -2585,6 +2595,17 @@ |
} |
+// 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, |