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.


Reply via email to