Reviewers: Michael Starzinger,
Description:
Improve range analysis for modulo operations.
Please review this at https://codereview.chromium.org/15952004/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/hydrogen-instructions.h
M src/hydrogen-instructions.cc
M src/utils.h
Index: src/hydrogen-instructions.cc
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index
e362b95c60a81c0722e4a221e57ebd052271ada2..5cf4f8d62bc597ee77445545af7477d4930f3c04
100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1811,8 +1811,19 @@ Range* HMod::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
Range* b = right()->range();
- Range* result = new(zone) Range();
- if (a->CanBeMinusZero() || a->CanBeNegative()) {
+
+ // The magnitude of the modulus is bounded by the right operand.
+ int32_t positive_bound = -Min(NegAbs(b->lower()), NegAbs(b->upper()))
- 1;
+
+ // The result of the modulo operation has the sign of its left operand.
+ bool left_can_be_negative = a->CanBeMinusZero() || a->CanBeNegative();
+ Range* result = new(zone) Range(left_can_be_negative ?
-positive_bound : 0,
+ a->CanBePositive() ? positive_bound :
0);
+
+ // The result is bounded by its left operand, too.
+ result->Intersect(a);
+
+ if (left_can_be_negative) {
result->set_can_be_minus_zero(true);
}
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index
e3cb9fdbc5b4f3d23cc205f8d72d99bb52547259..4018bcb7a6aedf2feb649ff2cc47943715f53ef2
100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -263,6 +263,7 @@ class Range: public ZoneObject {
bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
bool CanBeNegative() const { return lower_ < 0; }
+ bool CanBePositive() const { return upper_ > 0; }
bool Includes(int value) const { return lower_ <= value && upper_ >=
value; }
bool IsMostGeneric() const {
return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
Index: src/utils.h
diff --git a/src/utils.h b/src/utils.h
index
93cded18bcd2f9c07dc9c29ec567bbc565bb3520..b16730b8c46d750c1e264ad07713868c2b32d804
100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -232,6 +232,13 @@ T Min(T a, T b) {
}
+// Returns the negative absolute value of its argument.
+template <typename T>
+T NegAbs(T a) {
+ return a < 0 ? a : -a;
+}
+
+
inline int StrLength(const char* string) {
size_t length = strlen(string);
ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.