Turn range analysis into proper HPhase.
authorbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 4 Jul 2013 19:25:16 +0000 (19:25 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 4 Jul 2013 19:25:16 +0000 (19:25 +0000)
R=dslomov@chromium.org

Review URL: https://codereview.chromium.org/18491002

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

src/hydrogen-range-analysis.cc [new file with mode: 0644]
src/hydrogen-range-analysis.h [new file with mode: 0644]
src/hydrogen.cc
tools/gyp/v8.gyp

diff --git a/src/hydrogen-range-analysis.cc b/src/hydrogen-range-analysis.cc
new file mode 100644 (file)
index 0000000..0d4d970
--- /dev/null
@@ -0,0 +1,169 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-range-analysis.h"
+
+namespace v8 {
+namespace internal {
+
+
+void HRangeAnalysisPhase::TraceRange(const char* msg, ...) {
+  if (FLAG_trace_range) {
+    va_list arguments;
+    va_start(arguments, msg);
+    OS::VPrint(msg, arguments);
+    va_end(arguments);
+  }
+}
+
+
+void HRangeAnalysisPhase::Analyze(HBasicBlock* block) {
+  TraceRange("Analyzing block B%d\n", block->block_id());
+
+  int last_changed_range = changed_ranges_.length() - 1;
+
+  // Infer range based on control flow.
+  if (block->predecessors()->length() == 1) {
+    HBasicBlock* pred = block->predecessors()->first();
+    if (pred->end()->IsCompareIDAndBranch()) {
+      InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
+    }
+  }
+
+  // Process phi instructions.
+  for (int i = 0; i < block->phis()->length(); ++i) {
+    HPhi* phi = block->phis()->at(i);
+    InferRange(phi);
+  }
+
+  // Go through all instructions of the current block.
+  for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+    InferRange(it.Current());
+  }
+
+  // Continue analysis in all dominated blocks.
+  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
+    Analyze(block->dominated_blocks()->at(i));
+  }
+
+  RollBackTo(last_changed_range);
+}
+
+
+void HRangeAnalysisPhase::InferControlFlowRange(HCompareIDAndBranch* test,
+                                                HBasicBlock* dest) {
+  ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
+  if (test->representation().IsSmiOrInteger32()) {
+    Token::Value op = test->token();
+    if (test->SecondSuccessor() == dest) {
+      op = Token::NegateCompareOp(op);
+    }
+    Token::Value inverted_op = Token::ReverseCompareOp(op);
+    UpdateControlFlowRange(op, test->left(), test->right());
+    UpdateControlFlowRange(inverted_op, test->right(), test->left());
+  }
+}
+
+
+// We know that value [op] other. Use this information to update the range on
+// value.
+void HRangeAnalysisPhase::UpdateControlFlowRange(Token::Value op,
+                                                 HValue* value,
+                                                 HValue* other) {
+  Range temp_range;
+  Range* range = other->range() != NULL ? other->range() : &temp_range;
+  Range* new_range = NULL;
+
+  TraceRange("Control flow range infer %d %s %d\n",
+             value->id(),
+             Token::Name(op),
+             other->id());
+
+  if (op == Token::EQ || op == Token::EQ_STRICT) {
+    // The same range has to apply for value.
+    new_range = range->Copy(graph()->zone());
+  } else if (op == Token::LT || op == Token::LTE) {
+    new_range = range->CopyClearLower(graph()->zone());
+    if (op == Token::LT) {
+      new_range->AddConstant(-1);
+    }
+  } else if (op == Token::GT || op == Token::GTE) {
+    new_range = range->CopyClearUpper(graph()->zone());
+    if (op == Token::GT) {
+      new_range->AddConstant(1);
+    }
+  }
+
+  if (new_range != NULL && !new_range->IsMostGeneric()) {
+    AddRange(value, new_range);
+  }
+}
+
+
+void HRangeAnalysisPhase::InferRange(HValue* value) {
+  ASSERT(!value->HasRange());
+  if (!value->representation().IsNone()) {
+    value->ComputeInitialRange(graph()->zone());
+    Range* range = value->range();
+    TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
+               value->id(),
+               value->Mnemonic(),
+               range->lower(),
+               range->upper());
+  }
+}
+
+
+void HRangeAnalysisPhase::RollBackTo(int index) {
+  for (int i = index + 1; i < changed_ranges_.length(); ++i) {
+    changed_ranges_[i]->RemoveLastAddedRange();
+  }
+  changed_ranges_.Rewind(index + 1);
+}
+
+
+void HRangeAnalysisPhase::AddRange(HValue* value, Range* range) {
+  Range* original_range = value->range();
+  value->AddNewRange(range, graph()->zone());
+  changed_ranges_.Add(value, zone());
+  Range* new_range = value->range();
+  TraceRange("Updated range of %d set to [%d,%d]\n",
+             value->id(),
+             new_range->lower(),
+             new_range->upper());
+  if (original_range != NULL) {
+    TraceRange("Original range was [%d,%d]\n",
+               original_range->lower(),
+               original_range->upper());
+  }
+  TraceRange("New information was [%d,%d]\n",
+             range->lower(),
+             range->upper());
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/hydrogen-range-analysis.h b/src/hydrogen-range-analysis.h
new file mode 100644 (file)
index 0000000..52ce109
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_RANGE_ANALYSIS_H_
+#define V8_HYDROGEN_RANGE_ANALYSIS_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+class HRangeAnalysisPhase : public HPhase {
+ public:
+  explicit HRangeAnalysisPhase(HGraph* graph)
+      : HPhase("H_Range analysis", graph), changed_ranges_(16, zone()) { }
+
+  void Run() {
+    Analyze(graph()->entry_block());
+  }
+
+ private:
+  void TraceRange(const char* msg, ...);
+  void Analyze(HBasicBlock* block);
+  void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
+  void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
+  void InferRange(HValue* value);
+  void RollBackTo(int index);
+  void AddRange(HValue* value, Range* range);
+
+  ZoneList<HValue*> changed_ranges_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_RANGE_ANALYSIS_H_
index c5f4818..7679f93 100644 (file)
@@ -38,6 +38,7 @@
 #include "hydrogen-infer-representation.h"
 #include "hydrogen-gvn.h"
 #include "hydrogen-osr.h"
+#include "hydrogen-range-analysis.h"
 #include "hydrogen-uint32-analysis.h"
 #include "lithium-allocator.h"
 #include "parser.h"
@@ -2579,169 +2580,6 @@ void HGraph::InferTypes(ZoneList<HValue*>* worklist) {
 }
 
 
-class HRangeAnalysis BASE_EMBEDDED {
- public:
-  explicit HRangeAnalysis(HGraph* graph) :
-      graph_(graph), zone_(graph->zone()), changed_ranges_(16, zone_) { }
-
-  void Analyze();
-
- private:
-  void TraceRange(const char* msg, ...);
-  void Analyze(HBasicBlock* block);
-  void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
-  void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
-  void InferRange(HValue* value);
-  void RollBackTo(int index);
-  void AddRange(HValue* value, Range* range);
-
-  HGraph* graph_;
-  Zone* zone_;
-  ZoneList<HValue*> changed_ranges_;
-};
-
-
-void HRangeAnalysis::TraceRange(const char* msg, ...) {
-  if (FLAG_trace_range) {
-    va_list arguments;
-    va_start(arguments, msg);
-    OS::VPrint(msg, arguments);
-    va_end(arguments);
-  }
-}
-
-
-void HRangeAnalysis::Analyze() {
-  HPhase phase("H_Range analysis", graph_);
-  Analyze(graph_->entry_block());
-}
-
-
-void HRangeAnalysis::Analyze(HBasicBlock* block) {
-  TraceRange("Analyzing block B%d\n", block->block_id());
-
-  int last_changed_range = changed_ranges_.length() - 1;
-
-  // Infer range based on control flow.
-  if (block->predecessors()->length() == 1) {
-    HBasicBlock* pred = block->predecessors()->first();
-    if (pred->end()->IsCompareIDAndBranch()) {
-      InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
-    }
-  }
-
-  // Process phi instructions.
-  for (int i = 0; i < block->phis()->length(); ++i) {
-    HPhi* phi = block->phis()->at(i);
-    InferRange(phi);
-  }
-
-  // Go through all instructions of the current block.
-  for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
-    InferRange(it.Current());
-  }
-
-  // Continue analysis in all dominated blocks.
-  for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
-    Analyze(block->dominated_blocks()->at(i));
-  }
-
-  RollBackTo(last_changed_range);
-}
-
-
-void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
-                                           HBasicBlock* dest) {
-  ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
-  if (test->representation().IsSmiOrInteger32()) {
-    Token::Value op = test->token();
-    if (test->SecondSuccessor() == dest) {
-      op = Token::NegateCompareOp(op);
-    }
-    Token::Value inverted_op = Token::ReverseCompareOp(op);
-    UpdateControlFlowRange(op, test->left(), test->right());
-    UpdateControlFlowRange(inverted_op, test->right(), test->left());
-  }
-}
-
-
-// We know that value [op] other. Use this information to update the range on
-// value.
-void HRangeAnalysis::UpdateControlFlowRange(Token::Value op,
-                                            HValue* value,
-                                            HValue* other) {
-  Range temp_range;
-  Range* range = other->range() != NULL ? other->range() : &temp_range;
-  Range* new_range = NULL;
-
-  TraceRange("Control flow range infer %d %s %d\n",
-             value->id(),
-             Token::Name(op),
-             other->id());
-
-  if (op == Token::EQ || op == Token::EQ_STRICT) {
-    // The same range has to apply for value.
-    new_range = range->Copy(zone_);
-  } else if (op == Token::LT || op == Token::LTE) {
-    new_range = range->CopyClearLower(zone_);
-    if (op == Token::LT) {
-      new_range->AddConstant(-1);
-    }
-  } else if (op == Token::GT || op == Token::GTE) {
-    new_range = range->CopyClearUpper(zone_);
-    if (op == Token::GT) {
-      new_range->AddConstant(1);
-    }
-  }
-
-  if (new_range != NULL && !new_range->IsMostGeneric()) {
-    AddRange(value, new_range);
-  }
-}
-
-
-void HRangeAnalysis::InferRange(HValue* value) {
-  ASSERT(!value->HasRange());
-  if (!value->representation().IsNone()) {
-    value->ComputeInitialRange(zone_);
-    Range* range = value->range();
-    TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
-               value->id(),
-               value->Mnemonic(),
-               range->lower(),
-               range->upper());
-  }
-}
-
-
-void HRangeAnalysis::RollBackTo(int index) {
-  for (int i = index + 1; i < changed_ranges_.length(); ++i) {
-    changed_ranges_[i]->RemoveLastAddedRange();
-  }
-  changed_ranges_.Rewind(index + 1);
-}
-
-
-void HRangeAnalysis::AddRange(HValue* value, Range* range) {
-  Range* original_range = value->range();
-  value->AddNewRange(range, zone_);
-  changed_ranges_.Add(value, zone_);
-  Range* new_range = value->range();
-  TraceRange("Updated range of %d set to [%d,%d]\n",
-             value->id(),
-             new_range->lower(),
-             new_range->upper());
-  if (original_range != NULL) {
-    TraceRange("Original range was [%d,%d]\n",
-               original_range->lower(),
-               original_range->upper());
-  }
-  TraceRange("New information was [%d,%d]\n",
-             range->lower(),
-             range->upper());
-}
-
-
 class HStackCheckEliminator BASE_EMBEDDED {
  public:
   explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
@@ -3606,10 +3444,8 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
 
   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
 
-  if (FLAG_use_range) {
-    HRangeAnalysis range_analysis(this);
-    range_analysis.Analyze();
-  }
+  if (FLAG_use_range) Run<HRangeAnalysisPhase>();
+
   ComputeMinusZeroChecks();
 
   // Eliminate redundant stack checks on backwards branches.
index ab8f197..892e437 100644 (file)
         '../../src/hydrogen-gvn.h',
         '../../src/hydrogen-infer-representation.cc',
         '../../src/hydrogen-infer-representation.h',
+        '../../src/hydrogen-range-analysis.cc',
+        '../../src/hydrogen-range-analysis.h',
         '../../src/hydrogen-uint32-analysis.cc',
         '../../src/hydrogen-uint32-analysis.h',
         '../../src/hydrogen-osr.cc',