Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Unified Diff: src/compiler/typer.cc

Issue 2164263003: [turbofan] Induction variable bound analysis. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/typer.h ('k') | src/compiler/verifier.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/typer.cc
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index 98cf98ac337a6a1325452742970fc56eba1d3906..22f2788f1ad3f5c7204bdd78a2272d9af4ff4d28 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -10,6 +10,7 @@
#include "src/compiler/common-operator.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-operator.h"
+#include "src/compiler/loop-variable-optimizer.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
#include "src/compiler/operation-typer.h"
@@ -77,8 +78,10 @@ Typer::~Typer() {
class Typer::Visitor : public Reducer {
public:
- explicit Visitor(Typer* typer)
- : typer_(typer), weakened_nodes_(typer->zone()) {}
+ explicit Visitor(Typer* typer, LoopVariableOptimizer* induction_vars)
+ : typer_(typer),
+ induction_vars_(induction_vars),
+ weakened_nodes_(typer->zone()) {}
Reduction Reduce(Node* node) override {
if (node->op()->ValueOutputCount() == 0) return NoChange();
@@ -189,6 +192,7 @@ class Typer::Visitor : public Reducer {
private:
Typer* typer_;
+ LoopVariableOptimizer* induction_vars_;
ZoneSet<NodeId> weakened_nodes_;
#define DECLARE_METHOD(x) inline Type* Type##x(Node* node);
@@ -308,18 +312,23 @@ class Typer::Visitor : public Reducer {
}
};
+void Typer::Run() { Run(NodeVector(zone()), nullptr); }
-void Typer::Run() { Run(NodeVector(zone())); }
-
-
-void Typer::Run(const NodeVector& roots) {
- Visitor visitor(this);
+void Typer::Run(const NodeVector& roots,
+ LoopVariableOptimizer* induction_vars) {
+ if (induction_vars != nullptr) {
+ induction_vars->ChangeToInductionVariablePhis();
+ }
+ Visitor visitor(this, induction_vars);
GraphReducer graph_reducer(zone(), graph());
graph_reducer.AddReducer(&visitor);
for (Node* const root : roots) graph_reducer.ReduceNode(root);
graph_reducer.ReduceGraph();
-}
+ if (induction_vars != nullptr) {
+ induction_vars->ChangeFromInductionVariablePhis();
+ }
+}
void Typer::Decorator::Decorate(Node* node) {
if (node->op()->ValueOutputCount() > 0) {
@@ -327,7 +336,7 @@ void Typer::Decorator::Decorate(Node* node) {
// Other cases will generally require a proper fixpoint iteration with Run.
bool is_typed = NodeProperties::IsTyped(node);
if (is_typed || NodeProperties::AllValueInputsAreTyped(node)) {
- Visitor typing(typer_);
+ Visitor typing(typer_, nullptr);
Type* type = typing.TypeNode(node);
if (is_typed) {
type = Type::Intersect(type, NodeProperties::GetType(node),
@@ -736,7 +745,6 @@ Type* Typer::Visitor::TypeSelect(Node* node) {
return Type::Union(Operand(node, 1), Operand(node, 2), zone());
}
-
Type* Typer::Visitor::TypePhi(Node* node) {
int arity = node->op()->ValueInputCount();
Type* type = Operand(node, 0);
@@ -746,6 +754,89 @@ Type* Typer::Visitor::TypePhi(Node* node) {
return type;
}
+Type* Typer::Visitor::TypeInductionVariablePhi(Node* node) {
+ int arity = NodeProperties::GetControlInput(node)->op()->ControlInputCount();
+ DCHECK_EQ(IrOpcode::kLoop, NodeProperties::GetControlInput(node)->opcode());
+ DCHECK_EQ(2, NodeProperties::GetControlInput(node)->InputCount());
+
+ Type* initial_type = Operand(node, 0);
+ Type* increment_type = Operand(node, 2);
+
+ // We only handle integer induction variables (otherwise ranges
+ // do not apply and we cannot do anything).
+ if (!initial_type->Is(typer_->cache_.kInteger) ||
+ !increment_type->Is(typer_->cache_.kInteger)) {
+ // Fallback to normal phi typing.
+ Type* type = Operand(node, 0);
+ for (int i = 1; i < arity; ++i) {
+ type = Type::Union(type, Operand(node, i), zone());
+ }
+ return type;
+ }
+ // If we do not have enough type information for the initial value or
+ // the increment, just return the initial value's type.
+ if (!initial_type->IsInhabited() || !increment_type->IsInhabited()) {
+ return initial_type;
+ }
+
+ // Now process the bounds.
+ auto res = induction_vars_->induction_variables().find(node->id());
+ DCHECK(res != induction_vars_->induction_variables().end());
+ InductionVariable* induction_var = res->second;
+
+ double min = -V8_INFINITY;
+ double max = V8_INFINITY;
+ if (increment_type->Min() >= 0) {
+ min = initial_type->Min();
+ for (auto bound : induction_var->upper_bounds()) {
+ Type* bound_type = TypeOrNone(bound.bound);
+ // If the type is not an integer, just skip the bound.
+ if (!bound_type->Is(typer_->cache_.kInteger)) continue;
+ // If the type is not inhabited, then we can take the initial value.
+ if (!bound_type->IsInhabited()) {
+ max = initial_type->Max();
+ break;
+ }
+ double bound_max = bound_type->Max();
+ if (bound.kind == InductionVariable::kStrict) {
+ bound_max -= 1;
+ }
+ max = std::min(max, bound_max + increment_type->Max());
+ }
+ // The upper bound must be at least the initial value's upper bound.
+ max = std::max(max, initial_type->Max());
+ } else if (increment_type->Max() <= 0) {
+ max = initial_type->Max();
+ for (auto bound : induction_var->lower_bounds()) {
+ Type* bound_type = TypeOrNone(bound.bound);
+ // If the type is not an integer, just skip the bound.
+ if (!bound_type->Is(typer_->cache_.kInteger)) continue;
+ // If the type is not inhabited, then we can take the initial value.
+ if (!bound_type->IsInhabited()) {
+ min = initial_type->Min();
+ break;
+ }
+ double bound_min = bound_type->Min();
+ if (bound.kind == InductionVariable::kStrict) {
+ bound_min += 1;
+ }
+ min = std::max(min, bound_min + increment_type->Min());
+ }
+ // The lower bound must be at most the initial value's lower bound.
+ min = std::min(min, initial_type->Min());
+ } else {
+ // Shortcut: If the increment can be both positive and negative,
+ // the variable can go arbitrarily far, so just return integer.
+ return typer_->cache_.kInteger;
+ }
+ if (FLAG_trace_turbo_loop) {
+ OFStream os(stdout);
+ os << "Loop (" << NodeProperties::GetControlInput(node)->id()
+ << ") variable bounds for phi " << node->id() << ": (" << min << ", "
+ << max << ")\n";
+ }
+ return Type::Range(min, max, typer_->zone());
+}
Type* Typer::Visitor::TypeEffectPhi(Node* node) {
UNREACHABLE();
« no previous file with comments | « src/compiler/typer.h ('k') | src/compiler/verifier.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698