Index: src/compiler/operation-typer.cc |
diff --git a/src/compiler/operation-typer.cc b/src/compiler/operation-typer.cc |
index c189d5c854eb69beeb7088c67dc6bdad43736d91..c8367d197b77625ab89a40369ce8b3fbb68ba389 100644 |
--- a/src/compiler/operation-typer.cc |
+++ b/src/compiler/operation-typer.cc |
@@ -204,36 +204,6 @@ Type* OperationTyper::SubtractRanger(RangeType* lhs, RangeType* rhs) { |
// [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN |
} |
-Type* OperationTyper::ModulusRanger(RangeType* lhs, RangeType* rhs) { |
- double lmin = lhs->Min(); |
- double lmax = lhs->Max(); |
- double rmin = rhs->Min(); |
- double rmax = rhs->Max(); |
- |
- double labs = std::max(std::abs(lmin), std::abs(lmax)); |
- double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1; |
- double abs = std::min(labs, rabs); |
- bool maybe_minus_zero = false; |
- double omin = 0; |
- double omax = 0; |
- if (lmin >= 0) { // {lhs} positive. |
- omin = 0; |
- omax = abs; |
- } else if (lmax <= 0) { // {lhs} negative. |
- omin = 0 - abs; |
- omax = 0; |
- maybe_minus_zero = true; |
- } else { |
- omin = 0 - abs; |
- omax = abs; |
- maybe_minus_zero = true; |
- } |
- |
- Type* result = Type::Range(omin, omax, zone()); |
- if (maybe_minus_zero) result = Type::Union(result, Type::MinusZero(), zone()); |
- return result; |
-} |
- |
Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { |
double results[4]; |
double lmin = lhs->AsRange()->Min(); |
@@ -373,24 +343,67 @@ Type* OperationTyper::NumberModulus(Type* lhs, Type* rhs) { |
DCHECK(lhs->Is(Type::Number())); |
DCHECK(rhs->Is(Type::Number())); |
- if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
- return Type::None(); |
- } |
+ // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or |
+ // {lhs} is not finite, or the {rhs} is a zero value. |
+ bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
+ lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY; |
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
- |
- if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
- lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { |
- // Result maybe NaN. |
- return Type::Number(); |
+ // Deal with -0 inputs, only the signbit of {lhs} matters for the result. |
+ bool maybe_minuszero = false; |
+ if (lhs->Maybe(Type::MinusZero())) { |
+ maybe_minuszero = true; |
+ lhs = Type::Union(lhs, cache_.kSingletonZero, zone()); |
} |
- |
- lhs = Rangify(lhs); |
- rhs = Rangify(rhs); |
- if (lhs->IsRange() && rhs->IsRange()) { |
- return ModulusRanger(lhs->AsRange(), rhs->AsRange()); |
+ if (rhs->Maybe(Type::MinusZero())) { |
+ rhs = Type::Union(rhs, cache_.kSingletonZero, zone()); |
+ } |
+ |
+ // Rule out NaN and -0, and check what we can do with the remaining type info. |
+ Type* type = Type::None(); |
+ lhs = Type::Intersect(lhs, Type::PlainNumber(), zone()); |
+ rhs = Type::Intersect(rhs, Type::PlainNumber(), zone()); |
+ |
+ // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited, |
+ // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}. |
+ if (lhs->IsInhabited() && !rhs->Is(cache_.kSingletonZero)) { |
+ // Determine the bounds of {lhs} and {rhs}. |
+ double const lmin = lhs->Min(); |
+ double const lmax = lhs->Max(); |
+ double const rmin = rhs->Min(); |
+ double const rmax = rhs->Max(); |
+ |
+ // The sign of the result is the sign of the {lhs}. |
+ if (lmin < 0.0) maybe_minuszero = true; |
+ |
+ // For integer inputs {lhs} and {rhs} we can infer a precise type. |
+ if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) { |
+ double labs = std::max(std::abs(lmin), std::abs(lmax)); |
+ double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1; |
+ double abs = std::min(labs, rabs); |
+ double min = 0.0, max = 0.0; |
+ if (lmin >= 0.0) { |
+ // {lhs} positive. |
+ min = 0.0; |
+ max = abs; |
+ } else if (lmax <= 0.0) { |
+ // {lhs} negative. |
+ min = 0.0 - abs; |
+ max = 0.0; |
+ } else { |
+ // {lhs} positive or negative. |
+ min = 0.0 - abs; |
+ max = abs; |
+ } |
+ type = Type::Range(min, max, zone()); |
+ } else { |
+ type = Type::PlainNumber(); |
+ } |
} |
- return Type::OrderedNumber(); |
+ |
+ // Take into account the -0 and NaN information computed earlier. |
+ if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); |
+ if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); |
+ return type; |
} |
Type* OperationTyper::NumberAbs(Type* type) { |