Revision: 13543
Author:   [email protected]
Date:     Tue Jan 29 07:46:34 2013
Log:      Foundation for the use of informative definitions in Crankshaft.

Review URL: https://codereview.chromium.org/12090021
http://code.google.com/p/v8/source/detail?r=13543

Modified:
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/code-stubs-hydrogen.cc
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 29 07:28:05 2013 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 29 07:46:34 2013
@@ -501,8 +501,6 @@

 int LCodeGen::ToInteger32(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
-  ASSERT(constant->HasInteger32Value());
   return constant->Integer32Value();
 }

=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon Jan 28 05:24:41 2013 +++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Jan 29 07:46:34 2013
@@ -35,7 +35,6 @@
 namespace internal {


-// TODO(svenpanne) Merge with OptimizingCompiler::OptimizeGraph().
 static LChunk* OptimizeGraph(HGraph* graph) {
   AssertNoAllocation no_gc;
   NoHandleAllocation no_handles;
@@ -129,7 +128,8 @@

   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
       GetParameter(0), GetParameter(1), NULL, NULL,
-      casted_stub()->is_js_array(), casted_stub()->elements_kind(), false);
+      casted_stub()->is_js_array(), casted_stub()->elements_kind(),
+      false, Representation::Tagged());
   AddInstruction(load);

   HReturn* ret = new(zone) HReturn(load, context());
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Thu Jan 24 09:54:30 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Jan 29 07:46:34 2013
@@ -772,6 +772,28 @@
   stream->Add(" ");
   length()->PrintNameTo(stream);
 }
+
+
+void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
+  ASSERT(CheckFlag(kFlexibleRepresentation));
+  Representation r;
+  if (key_mode_ == DONT_ALLOW_SMI_KEY ||
+      !length()->representation().IsTagged()) {
+    r = Representation::Integer32();
+  } else if (index()->representation().IsTagged() ||
+      (index()->IsConstant() &&
+       HConstant::cast(index())->HasInteger32Value() &&
+       Smi::IsValid(HConstant::cast(index())->Integer32Value()))) {
+ // If the index is tagged, or a constant that holds a Smi, allow the length + // to be tagged, since it is usually already tagged from loading it out of + // the length field of a JSArray. This allows for direct comparison without
+    // untagging.
+    r = Representation::Tagged();
+  } else {
+    r = Representation::Integer32();
+  }
+  UpdateRepresentation(r, h_infer, "boundscheck");
+}


 void HCallConstantFunction::PrintDataTo(StringStream* stream) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Thu Jan 24 09:54:30 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Tue Jan 29 07:46:34 2013
@@ -672,6 +672,31 @@
     visited->Add(id());
     return NULL;
   }
+
+  // There are HInstructions that do not really change a value, they
+  // only add pieces of information to it (like bounds checks, map checks,
+  // smi checks...).
+  // We call these instructions "informative definitions", or "iDef".
+  // One of the iDef operands is special because it is the value that is
+  // "transferred" to the output, we call it the "redefined operand".
+ // If an HValue is an iDef it must override RedefinedOperandIndex() so that
+  // it does not return kNoRedefinedOperand;
+  static const int kNoRedefinedOperand = -1;
+  virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
+  bool IsInformativeDefinition() {
+    return RedefinedOperandIndex() != kNoRedefinedOperand;
+  }
+  HValue* RedefinedOperand() {
+    ASSERT(IsInformativeDefinition());
+    return OperandAt(RedefinedOperandIndex());
+  }
+
+  // This method must always return the original HValue SSA definition
+  // (regardless of any iDef of this value).
+  HValue* ActualValue() {
+    return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
+                                     : this;
+  }

   bool IsDefinedAfter(HBasicBlock* other) const;

@@ -3020,43 +3045,37 @@
 class HBoundsCheck: public HTemplateInstruction<2> {
  public:
   HBoundsCheck(HValue* index, HValue* length,
-               BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY)
+               BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY,
+               Representation r = Representation::None())
       : key_mode_(key_mode) {
     SetOperandAt(0, index);
     SetOperandAt(1, length);
-    set_representation(Representation::Integer32());
+    if (r.IsNone()) {
+      // In the normal compilation pipeline the representation is flexible
+      // (see comment to RequiredInputRepresentation).
+      SetFlag(kFlexibleRepresentation);
+    } else {
+      // When compiling stubs we want to set the representation explicitly
+ // so the compilation pipeline can skip the HInferRepresentation phase.
+      set_representation(r);
+    }
     SetFlag(kUseGVN);
   }

   virtual Representation RequiredInputRepresentation(int arg_index) {
-    if (key_mode_ == DONT_ALLOW_SMI_KEY ||
-        !length()->representation().IsTagged()) {
-      return Representation::Integer32();
-    }
-    // If the index is tagged and isn't constant, then allow the length
- // to be tagged, since it is usually already tagged from loading it out of - // the length field of a JSArray. This allows for direct comparison without
-    // untagging.
-    if (index()->representation().IsTagged() && !index()->IsConstant()) {
-      return Representation::Tagged();
-    }
-    // Also allow the length to be tagged if the index is constant, because
-    // it can be tagged to allow direct comparison.
-    if (index()->IsConstant() &&
-        index()->representation().IsInteger32() &&
-        arg_index == 1) {
-      return Representation::Tagged();
-    }
-    return Representation::Integer32();
+    return representation();
   }
   virtual Representation observed_input_representation(int index) {
     return Representation::Integer32();
   }

   virtual void PrintDataTo(StringStream* stream);
+  virtual void InferRepresentation(HInferRepresentation* h_infer);

   HValue* index() { return OperandAt(0); }
   HValue* length() { return OperandAt(1); }
+
+  virtual int RedefinedOperandIndex() { return 0; }

   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)

@@ -4433,6 +4452,11 @@
   virtual bool IsDehoisted() = 0;
   virtual void SetDehoisted(bool is_dehoisted) = 0;
   virtual ~ArrayInstructionInterface() { };
+
+  static Representation KeyedAccessIndexRequirement(Representation r) {
+    return r.IsInteger32() ? Representation::Integer32()
+                           : Representation::Tagged();
+  }
 };


@@ -4516,7 +4540,10 @@
       return is_external() ? Representation::External()
           : Representation::Tagged();
     }
-    if (index == 1) return Representation::Integer32();
+    if (index == 1) {
+      return ArrayInstructionInterface::KeyedAccessIndexRequirement(
+          OperandAt(1)->representation());
+    }
     return Representation::None();
   }

@@ -4731,7 +4758,8 @@
       return is_external() ? Representation::External()
                            : Representation::Tagged();
     } else if (index == 1) {
-      return Representation::Integer32();
+      return ArrayInstructionInterface::KeyedAccessIndexRequirement(
+          OperandAt(1)->representation());
     }

     ASSERT_EQ(index, 2);
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Fri Jan 25 08:55:00 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Tue Jan 29 07:46:34 2013
@@ -745,7 +745,8 @@
     HCheckMaps* mapcheck,
     bool is_js_array,
     ElementsKind elements_kind,
-    bool is_store) {
+    bool is_store,
+    Representation checked_index_representation) {
   Zone* zone = this->zone();
// No GVNFlag is necessary for ElementsKind if there is an explicit dependency // on a HElementsTransition instruction. The flag can also be removed if the
@@ -773,8 +774,8 @@
   HInstruction* checked_key = NULL;
   if (IsExternalArrayElementsKind(elements_kind)) {
     length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
-    checked_key = AddInstruction(new(zone) HBoundsCheck(key, length,
-                                                        ALLOW_SMI_KEY));
+    checked_key = AddInstruction(new(zone) HBoundsCheck(
+        key, length, ALLOW_SMI_KEY, checked_index_representation));
     HLoadExternalArrayPointer* external_elements =
         new(zone) HLoadExternalArrayPointer(elements);
     AddInstruction(external_elements);
@@ -791,8 +792,8 @@
   } else {
     length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
   }
-  checked_key = AddInstruction(new(zone) HBoundsCheck(key, length,
-                                                      ALLOW_SMI_KEY));
+  checked_key = AddInstruction(new(zone) HBoundsCheck(
+      key, length, ALLOW_SMI_KEY, checked_index_representation));
   return BuildFastElementAccess(elements, checked_key, val, mapcheck,
                                 elements_kind, is_store);
 }
@@ -3586,10 +3587,12 @@
   HStackCheckEliminator sce(this);
   sce.Process();

-  EliminateRedundantBoundsChecks();
-  DehoistSimpleArrayIndexComputations();
+ if (FLAG_array_bounds_checks_elimination) EliminateRedundantBoundsChecks();
+  if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
   if (FLAG_dead_code_elimination) DeadCodeElimination();

+  RestoreActualValues();
+
   return true;
 }

@@ -3727,6 +3730,7 @@
                                      new_check->index()->representation(),
                                      new_offset);
         if (!result) return false;
+        upper_check_->ReplaceAllUsesWith(upper_check_->index());
         upper_check_->SetOperandAt(0, added_upper_index_);
       }
     } else if (new_offset < lower_offset_) {
@@ -3742,6 +3746,7 @@
                                      new_check->index()->representation(),
                                      new_offset);
         if (!result) return false;
+        lower_check_->ReplaceAllUsesWith(lower_check_->index());
         lower_check_->SetOperandAt(0, added_lower_index_);
       }
     } else {
@@ -3749,7 +3754,7 @@
     }

     if (!keep_new_check) {
-      new_check->DeleteAndReplaceWith(NULL);
+      new_check->DeleteAndReplaceWith(new_check->ActualValue());
     }

     return true;
@@ -3885,10 +3890,6 @@
     if (!i->IsBoundsCheck()) continue;

     HBoundsCheck* check = HBoundsCheck::cast(i);
-    check->ReplaceAllUsesWith(check->index());
-
-    if (!FLAG_array_bounds_checks_elimination) continue;
-
     int32_t offset;
     BoundsCheckKey* key =
         BoundsCheckKey::Create(zone(), check, &offset);
@@ -3906,7 +3907,7 @@
                                                    NULL);
       *data_p = bb_data_list;
     } else if (data->OffsetIsCovered(offset)) {
-      check->DeleteAndReplaceWith(NULL);
+      check->DeleteAndReplaceWith(check->ActualValue());
     } else if (data->BasicBlock() != bb ||
                !data->CoverCheck(check, offset)) {
       // If the check is in the current BB we try to modify it by calling
@@ -3955,7 +3956,7 @@


 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
-  HValue* index = array_operation->GetKey();
+  HValue* index = array_operation->GetKey()->ActualValue();
   if (!index->representation().IsInteger32()) return;

   HConstant* constant;
@@ -4003,8 +4004,6 @@


 void HGraph::DehoistSimpleArrayIndexComputations() {
-  if (!FLAG_array_index_dehoisting) return;
-
   HPhase phase("H_Dehoist index computations", this);
   for (int i = 0; i < blocks()->length(); ++i) {
     for (HInstruction* instr = blocks()->at(i)->first();
@@ -4054,6 +4053,30 @@
     }
   }
 }
+
+
+void HGraph::RestoreActualValues() {
+  HPhase phase("H_Restore actual values", this);
+
+ for (int block_index = 0; block_index < blocks()->length(); block_index++) {
+    HBasicBlock* block = blocks()->at(block_index);
+
+#ifdef DEBUG
+    for (int i = 0; i < block->phis()->length(); i++) {
+      HPhi* phi = block->phis()->at(i);
+      ASSERT(phi->ActualValue() == phi);
+    }
+#endif
+
+    for (HInstruction* instruction = block->first();
+        instruction != NULL;
+        instruction = instruction->next()) {
+      if (instruction->ActualValue() != instruction) {
+        instruction->ReplaceAllUsesWith(instruction->ActualValue());
+      }
+    }
+  }
+}


 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) {
=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Wed Jan 23 05:52:00 2013
+++ /branches/bleeding_edge/src/hydrogen.h      Tue Jan 29 07:46:34 2013
@@ -273,6 +273,7 @@
   void EliminateRedundantBoundsChecks();
   void DehoistSimpleArrayIndexComputations();
   void DeadCodeElimination();
+  void RestoreActualValues();
   void PropagateDeoptimizingMark();
   void EliminateUnusedInstructions();

@@ -897,7 +898,8 @@
       HCheckMaps* mapcheck,
       bool is_js_array,
       ElementsKind elements_kind,
-      bool is_store);
+      bool is_store,
+ Representation checked_index_representation = Representation::None());

  private:
   HGraphBuilder();
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jan 29 07:28:05 2013 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jan 29 07:46:34 2013
@@ -502,8 +502,6 @@

 int LCodeGen::ToInteger32(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
-  ASSERT(constant->HasInteger32Value());
   return constant->Integer32Value();
 }

@@ -3207,13 +3205,6 @@
     uint32_t additional_index) {
   Register elements_pointer_reg = ToRegister(elements_pointer);
   int shift_size = ElementsKindToShiftSize(elements_kind);
-  // Even though the HLoad/StoreKeyed instructions force the input
- // representation for the key to be an integer, the input gets replaced during - // bound check elimination with the index argument to the bounds check, which
-  // can be tagged, so that case must be handled here, too.
-  if (key_representation.IsTagged() && (shift_size >= 1)) {
-    shift_size -= kSmiTagSize;
-  }
   if (key->IsConstantOperand()) {
     int constant_value = ToInteger32(LConstantOperand::cast(key));
     if (constant_value & 0xF0000000) {
@@ -3223,6 +3214,10 @@
                    ((constant_value + additional_index) << shift_size)
                        + offset);
   } else {
+    // Take the tag bit into account while computing the shift size.
+    if (key_representation.IsTagged() && (shift_size >= 1)) {
+      shift_size -= kSmiTagSize;
+    }
     ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
     return Operand(elements_pointer_reg,
                    ToRegister(key),
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Mon Jan 28 06:50:47 2013 +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Tue Jan 29 07:46:34 2013
@@ -490,8 +490,6 @@

 int LCodeGen::ToInteger32(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
-  ASSERT(constant->HasInteger32Value());
   return constant->Integer32Value();
 }

=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon Jan 28 06:50:47 2013 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Jan 29 07:46:34 2013
@@ -425,8 +425,6 @@

 int LCodeGen::ToInteger32(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
-  ASSERT(constant->HasInteger32Value());
   return constant->Integer32Value();
 }

--
--
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