Improve representation inference
authorvegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 8 Jun 2012 09:21:23 +0000 (09:21 +0000)
committervegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 8 Jun 2012 09:21:23 +0000 (09:21 +0000)
- Extend HValue interface to allow splitting observed input representation (comming from type feedback) from required input representation (dictated by instruction itself). Currently all instructions except for bitwise binary operations have this representations match. For bitwise binary operations hydrogen builder unconditionaly forces Integer32 representation for those operations that have Double type feedback. Thus causing representation inference to incorrectly count such uses as Integer32 instead of Double. This change also prepares for more fine grained type feedback for inputs of binary operations.

- For phies that are not convertable to Integer32 discard direct and indirect use count of Integer32 type to avoid propagation of these uses to connected phies.

R=jkummerow@chromium.org
BUG=v8:2096

Review URL: https://chromiumcodereview.appspot.com/10540049

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

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

index 57a1862..734cd2e 100644 (file)
@@ -1298,14 +1298,33 @@ void HPhi::InitRealUses(int phi_id) {
   for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
     HValue* value = it.value();
     if (!value->IsPhi()) {
-      Representation rep = value->RequiredInputRepresentation(it.index());
+      Representation rep = value->ObservedInputRepresentation(it.index());
       non_phi_uses_[rep.kind()] += value->LoopWeight();
+      if (FLAG_trace_representation) {
+        PrintF("%d %s is used by %d %s as %s\n",
+               this->id(),
+               this->Mnemonic(),
+               value->id(),
+               value->Mnemonic(),
+               rep.Mnemonic());
+      }
     }
   }
 }
 
 
 void HPhi::AddNonPhiUsesFrom(HPhi* other) {
+  if (FLAG_trace_representation) {
+    PrintF("adding to %d %s uses of %d %s: i%d d%d t%d\n",
+           this->id(),
+           this->Mnemonic(),
+           other->id(),
+           other->Mnemonic(),
+           other->non_phi_uses_[Representation::kInteger32],
+           other->non_phi_uses_[Representation::kDouble],
+           other->non_phi_uses_[Representation::kTagged]);
+  }
+
   for (int i = 0; i < Representation::kNumRepresentations; i++) {
     indirect_uses_[i] += other->non_phi_uses_[i];
   }
@@ -1319,6 +1338,12 @@ void HPhi::AddIndirectUsesTo(int* dest) {
 }
 
 
+void HPhi::ResetInteger32Uses() {
+  non_phi_uses_[Representation::kInteger32] = 0;
+  indirect_uses_[Representation::kInteger32] = 0;
+}
+
+
 void HSimulate::PrintDataTo(StringStream* stream) {
   stream->Add("id=%d", ast_id());
   if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
index 0f6cb6e..ca4f318 100644 (file)
@@ -720,6 +720,11 @@ class HValue: public ZoneObject {
     return representation();
   }
 
+  // Type feedback access.
+  virtual Representation ObservedInputRepresentation(int index) {
+    return RequiredInputRepresentation(index);
+  }
+
   // This gives the instruction an opportunity to replace itself with an
   // instruction that does the same in some better way.  To replace an
   // instruction with a new one, first add the new instruction to the graph,
@@ -2402,11 +2407,15 @@ class HPhi: public HValue {
 
   bool AllOperandsConvertibleToInteger() {
     for (int i = 0; i < OperandCount(); ++i) {
-      if (!OperandAt(i)->IsConvertibleToInteger()) return false;
+      if (!OperandAt(i)->IsConvertibleToInteger()) {
+        return false;
+      }
     }
     return true;
   }
 
+  void ResetInteger32Uses();
+
  protected:
   virtual void DeleteFromGraph();
   virtual void InternalSetOperandAt(int index, HValue* value) {
@@ -2556,6 +2565,7 @@ class HBinaryOperation: public HTemplateInstruction<3> {
     if (IsCommutative() && left()->IsConstant()) return right();
     return left();
   }
+
   HValue* MostConstantOperand() {
     if (IsCommutative() && left()->IsConstant()) return left();
     return right();
@@ -2721,6 +2731,9 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
     set_representation(Representation::Tagged());
     SetFlag(kFlexibleRepresentation);
     SetAllSideEffects();
+    observed_input_representation_[0] = Representation::Tagged();
+    observed_input_representation_[1] = Representation::None();
+    observed_input_representation_[2] = Representation::None();
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -2740,7 +2753,19 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
 
   virtual HType CalculateInferredType();
 
+  virtual Representation ObservedInputRepresentation(int index) {
+    return observed_input_representation_[index];
+  }
+
+  void InitializeObservedInputRepresentation(Representation r) {
+    observed_input_representation_[1] = r;
+    observed_input_representation_[2] = r;
+  }
+
   DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
+
+ private:
+  Representation observed_input_representation_[3];
 };
 
 
index e2fbfb5..173d622 100644 (file)
@@ -2140,8 +2140,16 @@ Representation HInferRepresentation::TryChange(HValue* value) {
 
   for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
     HValue* use = it.value();
-    Representation rep = use->RequiredInputRepresentation(it.index());
+    Representation rep = use->ObservedInputRepresentation(it.index());
     if (rep.IsNone()) continue;
+    if (FLAG_trace_representation) {
+      PrintF("%d %s is used by %d %s as %s\n",
+             value->id(),
+             value->Mnemonic(),
+             use->id(),
+             use->Mnemonic(),
+             rep.Mnemonic());
+    }
     if (use->IsPhi()) HPhi::cast(use)->AddIndirectUsesTo(&use_count[0]);
     use_count[rep.kind()] += use->LoopWeight();
   }
@@ -2205,21 +2213,34 @@ void HInferRepresentation::Analyze() {
     }
   }
 
-  // (3) Use the phi reachability information from step 2 to
-  //     (a) sum up the non-phi use counts of all connected phis.
-  //     (b) push information about values which can't be converted to integer
-  //         without deoptimization through the phi use-def chains, avoiding
-  //         unnecessary deoptimizations later.
+  // (3a) Use the phi reachability information from step 2 to
+  // push information about values which can't be converted to integer
+  // without deoptimization through the phi use-def chains, avoiding
+  // unnecessary deoptimizations later.
   for (int i = 0; i < phi_count; ++i) {
     HPhi* phi = phi_list->at(i);
     bool cti = phi->AllOperandsConvertibleToInteger();
+    if (cti) continue;
+
+    for (BitVector::Iterator it(connected_phis.at(i));
+         !it.Done();
+         it.Advance()) {
+      HPhi* phi = phi_list->at(it.Current());
+      phi->set_is_convertible_to_integer(false);
+      phi->ResetInteger32Uses();
+    }
+  }
+
+  // (3b) Use the phi reachability information from step 2 to
+  // sum up the non-phi use counts of all connected phis.
+  for (int i = 0; i < phi_count; ++i) {
+    HPhi* phi = phi_list->at(i);
     for (BitVector::Iterator it(connected_phis.at(i));
          !it.Done();
          it.Advance()) {
       int index = it.Current();
-      HPhi* it_use = phi_list->at(it.Current());
-      if (index != i) phi->AddNonPhiUsesFrom(it_use);  // Don't count twice!
-      if (!cti) it_use->set_is_convertible_to_integer(false);
+      HPhi* it_use = phi_list->at(index);
+      if (index != i) phi->AddNonPhiUsesFrom(it_use);  // Don't count twice.
     }
   }
 
@@ -7503,8 +7524,10 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
   }
   Representation rep = ToRepresentation(info);
   // We only generate either int32 or generic tagged bitwise operations.
-  if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
-    rep = Representation::Integer32();
+  if (instr->IsBitwiseBinaryOperation()) {
+    HBitwiseBinaryOperation::cast(instr)->
+         InitializeObservedInputRepresentation(rep);
+    if (rep.IsDouble()) rep = Representation::Integer32();
   }
   TraceRepresentation(expr->op(), info, instr, rep);
   instr->AssumeRepresentation(rep);