Fixed numeric relations on HPhi instances.
authormmassi@chromium.org <mmassi@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 21 Feb 2013 10:22:31 +0000 (10:22 +0000)
committermmassi@chromium.org <mmassi@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 21 Feb 2013 10:22:31 +0000 (10:22 +0000)
Review URL: https://codereview.chromium.org/12301027

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

src/arm/lithium-arm.cc
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/ia32/lithium-ia32.cc
src/mips/lithium-mips.cc
src/x64/lithium-x64.cc

index 208ca21..c7b4382 100644 (file)
@@ -1690,6 +1690,12 @@ LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+    HInductionVariableAnnotation* instr) {
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
   LOperand* value = UseRegisterOrConstantAtStart(instr->index());
   LOperand* length = UseRegister(instr->length());
index 2d4b82b..52eada4 100644 (file)
@@ -843,6 +843,27 @@ void HNumericConstraint::PrintDataTo(StringStream* stream) {
 }
 
 
+HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph(
+    HPhi* phi,
+    NumericRelation relation,
+    int operand_index) {
+  HInductionVariableAnnotation* result =
+      new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation,
+                                                             operand_index);
+  result->InsertAfter(phi->block()->first());
+  return result;
+}
+
+
+void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) {
+  stream->Add("(");
+  RedefinedOperand()->PrintNameTo(stream);
+  stream->Add(" %s ", relation().Mnemonic());
+  induction_base()->PrintNameTo(stream);
+  stream->Add(")");
+}
+
+
 void HDummyUse::PrintDataTo(StringStream* stream) {
   value()->PrintNameTo(stream);
 }
@@ -1554,15 +1575,14 @@ Range* HMod::InferRange(Zone* zone) {
 
 void HPhi::AddInformativeDefinitions() {
   if (OperandCount() == 2) {
+    // If one of the operands is an OSR block give up (this cannot be an
+    // induction variable).
+    if (OperandAt(0)->block()->is_osr_entry() ||
+        OperandAt(1)->block()->is_osr_entry()) return;
+
     for (int operand_index = 0; operand_index < 2; operand_index++) {
       int other_operand_index = (operand_index + 1) % 2;
 
-      // Add an idef that "discards" the OSR entry block branch.
-      if (OperandAt(operand_index)->block()->is_osr_entry()) {
-        HNumericConstraint::AddToGraph(
-            this, NumericRelation::Eq(), OperandAt(other_operand_index));
-      }
-
       static NumericRelation relations[] = {
         NumericRelation::Ge(),
         NumericRelation::Le()
@@ -1574,9 +1594,9 @@ void HPhi::AddInformativeDefinitions() {
       for (int relation_index = 0; relation_index < 2; relation_index++) {
         if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index],
                                                      this)) {
-          HNumericConstraint::AddToGraph(this,
-                                         relations[relation_index],
-                                         OperandAt(other_operand_index));
+          HInductionVariableAnnotation::AddToGraph(this,
+                                                   relations[relation_index],
+                                                   other_operand_index);
         }
       }
     }
@@ -1584,6 +1604,26 @@ void HPhi::AddInformativeDefinitions() {
 }
 
 
+bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) {
+  if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
+
+  SetFlag(kNumericConstraintEvaluationInProgress);
+  bool result = true;
+  for (int i = 0; i < OperandCount(); i++) {
+    // Skip OSR entry blocks
+    if (OperandAt(i)->block()->is_osr_entry()) continue;
+
+    if (!OperandAt(i)->IsRelationTrue(relation, other)) {
+      result = false;
+      break;
+    }
+  }
+  ClearFlag(kNumericConstraintEvaluationInProgress);
+
+  return result;
+}
+
+
 Range* HMathMinMax::InferRange(Zone* zone) {
   if (representation().IsInteger32()) {
     Range* a = left()->range();
index 64910c8..2d763d5 100644 (file)
@@ -119,6 +119,7 @@ class LChunkBuilder;
   V(Goto)                                      \
   V(HasCachedArrayIndexAndBranch)              \
   V(HasInstanceTypeAndBranch)                  \
+  V(InductionVariableAnnotation)               \
   V(In)                                        \
   V(InstanceOf)                                \
   V(InstanceOfKnownGlobal)                     \
@@ -704,6 +705,9 @@ class HValue: public ZoneObject {
     // HGraph::ComputeSafeUint32Operations is responsible for setting this
     // flag.
     kUint32,
+    // If a phi is involved in the evaluation of a numeric constraint the
+    // recursion can cause an endless cycle: we use this flag to exit the loop.
+    kNumericConstraintEvaluationInProgress,
     // This flag is set to true after the SetupInformativeDefinitions() pass
     // has processed this instruction.
     kIDefsProcessingDone,
@@ -2955,6 +2959,8 @@ class HPhi: public HValue {
     inputs_[index] = value;
   }
 
+  virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other);
+
  private:
   ZoneList<HValue*> inputs_;
   int merged_index_;
@@ -2967,6 +2973,52 @@ class HPhi: public HValue {
 };
 
 
+class HInductionVariableAnnotation : public HUnaryOperation {
+ public:
+  static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
+                                                  NumericRelation relation,
+                                                  int operand_index);
+
+  NumericRelation relation() { return relation_; }
+  HValue* induction_base() { return phi_->OperandAt(operand_index_); }
+
+  virtual int RedefinedOperandIndex() { return 0; }
+  virtual bool IsPurelyInformativeDefinition() { return true; }
+  virtual Representation RequiredInputRepresentation(int index) {
+    return representation();
+  }
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  virtual bool IsRelationTrueInternal(NumericRelation other_relation,
+                                      HValue* other_related_value) {
+    if (induction_base() == other_related_value) {
+      return relation().Implies(other_relation);
+    } else {
+      return false;
+    }
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation)
+
+ private:
+  HInductionVariableAnnotation(HPhi* phi,
+                               NumericRelation relation,
+                               int operand_index)
+      : HUnaryOperation(phi),
+    phi_(phi), relation_(relation), operand_index_(operand_index) {
+    set_representation(phi->representation());
+  }
+
+  // We need to store the phi both here and in the instruction operand because
+  // the operand can change if a new idef of the phi is added between the phi
+  // and this instruction (inserting an idef updates every use).
+  HPhi* phi_;
+  NumericRelation relation_;
+  int operand_index_;
+};
+
+
 class HArgumentsObject: public HTemplateInstruction<0> {
  public:
   HArgumentsObject() {
index a25c154..5d539ed 100644 (file)
@@ -1717,6 +1717,12 @@ LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+    HInductionVariableAnnotation* instr) {
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
   return AssignEnvironment(new(zone()) LBoundsCheck(
       UseRegisterOrConstantAtStart(instr->index()),
index 863457e..a6d7f1d 100644 (file)
@@ -1595,6 +1595,12 @@ LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+    HInductionVariableAnnotation* instr) {
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
   LOperand* value = UseRegisterOrConstantAtStart(instr->index());
   LOperand* length = UseRegister(instr->length());
index 4194ad6..57de0c8 100644 (file)
@@ -1641,6 +1641,12 @@ LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
+    HInductionVariableAnnotation* instr) {
+  return NULL;
+}
+
+
 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
   LOperand* value = UseRegisterOrConstantAtStart(instr->index());
   LOperand* length = Use(instr->length());