Insert representation changes before doing range analysis and fix a bug in Range...
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 23 Aug 2011 07:34:45 +0000 (07:34 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 23 Aug 2011 07:34:45 +0000 (07:34 +0000)
This improves our static type information by calculating the result type
of conversions (HChange) during range analysis. It allows e.g. to eliminate
the write barrier in the following example where it was not possible before:

function f(x) {
  var y = x + 1;
  if (y > 0 && y < 100) {
    a[0] = y;
  }
}

* Fix bug in Range::Copy. The minus-zero flags has to be preserved by default.
Review URL: http://codereview.chromium.org/7634022

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8994 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc

index ec5affd6cf7c5a5a7b44886f8f8dcc21b3eb69d3..176218616e2917ff93e86e8ed50013fb0cc4e053 100644 (file)
@@ -641,6 +641,7 @@ void HBoundsCheck::PrintDataTo(StringStream* stream) {
   length()->PrintNameTo(stream);
 }
 
+
 void HCallConstantFunction::PrintDataTo(StringStream* stream) {
   if (IsApplyFunction()) {
     stream->Add("optimized apply ");
@@ -875,6 +876,21 @@ Range* HValue::InferRange() {
 }
 
 
+Range* HChange::InferRange() {
+  Range* input_range = value()->range();
+  if (from().IsInteger32() &&
+      to().IsTagged() &&
+      input_range != NULL && input_range->IsInSmiRange()) {
+    set_type(HType::Smi());
+  }
+  Range* result = (input_range != NULL)
+      ? input_range->Copy()
+      : HValue::InferRange();
+  if (to().IsInteger32()) result->set_can_be_minus_zero(false);
+  return result;
+}
+
+
 Range* HConstant::InferRange() {
   if (has_int32_value_) {
     Range* result = new Range(int32_value_, int32_value_);
@@ -1220,6 +1236,7 @@ Range* HSar::InferRange() {
           ? left()->range()->Copy()
           : new Range();
       result->Sar(c->Integer32Value());
+      result->set_can_be_minus_zero(false);
       return result;
     }
   }
@@ -1243,6 +1260,7 @@ Range* HShr::InferRange() {
             ? left()->range()->Copy()
             : new Range();
         result->Sar(c->Integer32Value());
+        result->set_can_be_minus_zero(false);
         return result;
       }
     }
@@ -1259,6 +1277,7 @@ Range* HShl::InferRange() {
           ? left()->range()->Copy()
           : new Range();
       result->Shl(c->Integer32Value());
+      result->set_can_be_minus_zero(false);
       return result;
     }
   }
index 1c3d7b204be3c1b7e8800f849a9461b5480ef5a8..76007d764e6564db26abc9520ddf1b4100eaddf3 100644 (file)
@@ -227,14 +227,20 @@ class Range: public ZoneObject {
   Range* next() const { return next_; }
   Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
   Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
-  Range* Copy() const { return new Range(lower_, upper_); }
+  Range* Copy() const {
+    Range* result = new Range(lower_, upper_);
+    result->set_can_be_minus_zero(CanBeMinusZero());
+    return result;
+  }
   int32_t Mask() const;
   void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
   bool CanBeNegative() const { return lower_ < 0; }
   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
-  bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
+  bool IsMostGeneric() const {
+    return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
+  }
   bool IsInSmiRange() const {
     return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
   }
@@ -578,9 +584,9 @@ class HValue: public ZoneObject {
   virtual bool IsConvertibleToInteger() const { return true; }
 
   HType type() const { return type_; }
-  void set_type(HType type) {
-    ASSERT(HasNoUses());
-    type_ = type;
+  void set_type(HType new_type) {
+    ASSERT(new_type.IsSubtypeOf(type_));
+    type_ = new_type;
   }
 
   // An operation needs to override this function iff:
@@ -1100,10 +1106,6 @@ class HChange: public HUnaryOperation {
     set_representation(to);
     SetFlag(kUseGVN);
     if (is_truncating) SetFlag(kTruncatingToInt32);
-    if (from.IsInteger32() && to.IsTagged() && value->range() != NULL &&
-        value->range()->IsInSmiRange()) {
-      set_type(HType::Smi());
-    }
   }
 
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
@@ -1115,6 +1117,8 @@ class HChange: public HUnaryOperation {
     return from_;
   }
 
+  virtual Range* InferRange();
+
   virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(Change)
index 570987d4940d66ad2a0e073317e75b565a05a515..3a6849d2b4693a97aaacddd8d360a02ead9c8d35 100644 (file)
@@ -2325,15 +2325,15 @@ HGraph* HGraphBuilder::CreateGraph() {
   HInferRepresentation rep(graph());
   rep.Analyze();
 
+  graph()->MarkDeoptimizeOnUndefined();
+  graph()->InsertRepresentationChanges();
+
   if (FLAG_use_range) {
     HRangeAnalysis rangeAnalysis(graph());
     rangeAnalysis.Analyze();
   }
-
   graph()->InitializeInferredTypes();
   graph()->Canonicalize();
-  graph()->MarkDeoptimizeOnUndefined();
-  graph()->InsertRepresentationChanges();
   graph()->ComputeMinusZeroChecks();
 
   // Eliminate redundant stack checks on backwards branches.