11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_LOOP_VARIABLE_OPTIMIZER_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_LOOP_VARIABLE_OPTIMIZER_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/compiler/functional-list.h"
91cb0ef41Sopenharmony_ci#include "src/compiler/node-aux-data.h"
101cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_cinamespace compiler {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciclass CommonOperatorBuilder;
171cb0ef41Sopenharmony_ciclass Graph;
181cb0ef41Sopenharmony_ciclass Node;
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciclass InductionVariable : public ZoneObject {
211cb0ef41Sopenharmony_ci public:
221cb0ef41Sopenharmony_ci  Node* phi() const { return phi_; }
231cb0ef41Sopenharmony_ci  Node* effect_phi() const { return effect_phi_; }
241cb0ef41Sopenharmony_ci  Node* arith() const { return arith_; }
251cb0ef41Sopenharmony_ci  Node* increment() const { return increment_; }
261cb0ef41Sopenharmony_ci  Node* init_value() const { return init_value_; }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  enum ConstraintKind { kStrict, kNonStrict };
291cb0ef41Sopenharmony_ci  enum ArithmeticType { kAddition, kSubtraction };
301cb0ef41Sopenharmony_ci  struct Bound {
311cb0ef41Sopenharmony_ci    Bound(Node* bound, ConstraintKind kind) : bound(bound), kind(kind) {}
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci    Node* bound;
341cb0ef41Sopenharmony_ci    ConstraintKind kind;
351cb0ef41Sopenharmony_ci  };
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  const ZoneVector<Bound>& lower_bounds() { return lower_bounds_; }
381cb0ef41Sopenharmony_ci  const ZoneVector<Bound>& upper_bounds() { return upper_bounds_; }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  ArithmeticType Type() { return arithmeticType_; }
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci private:
431cb0ef41Sopenharmony_ci  friend class LoopVariableOptimizer;
441cb0ef41Sopenharmony_ci  friend Zone;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  InductionVariable(Node* phi, Node* effect_phi, Node* arith, Node* increment,
471cb0ef41Sopenharmony_ci                    Node* init_value, Zone* zone, ArithmeticType arithmeticType)
481cb0ef41Sopenharmony_ci      : phi_(phi),
491cb0ef41Sopenharmony_ci        effect_phi_(effect_phi),
501cb0ef41Sopenharmony_ci        arith_(arith),
511cb0ef41Sopenharmony_ci        increment_(increment),
521cb0ef41Sopenharmony_ci        init_value_(init_value),
531cb0ef41Sopenharmony_ci        lower_bounds_(zone),
541cb0ef41Sopenharmony_ci        upper_bounds_(zone),
551cb0ef41Sopenharmony_ci        arithmeticType_(arithmeticType) {}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  void AddUpperBound(Node* bound, ConstraintKind kind);
581cb0ef41Sopenharmony_ci  void AddLowerBound(Node* bound, ConstraintKind kind);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  Node* phi_;
611cb0ef41Sopenharmony_ci  Node* effect_phi_;
621cb0ef41Sopenharmony_ci  Node* arith_;
631cb0ef41Sopenharmony_ci  Node* increment_;
641cb0ef41Sopenharmony_ci  Node* init_value_;
651cb0ef41Sopenharmony_ci  ZoneVector<Bound> lower_bounds_;
661cb0ef41Sopenharmony_ci  ZoneVector<Bound> upper_bounds_;
671cb0ef41Sopenharmony_ci  ArithmeticType arithmeticType_;
681cb0ef41Sopenharmony_ci};
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciclass LoopVariableOptimizer {
711cb0ef41Sopenharmony_ci public:
721cb0ef41Sopenharmony_ci  void Run();
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  LoopVariableOptimizer(Graph* graph, CommonOperatorBuilder* common,
751cb0ef41Sopenharmony_ci                        Zone* zone);
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  const ZoneMap<int, InductionVariable*>& induction_variables() {
781cb0ef41Sopenharmony_ci    return induction_vars_;
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  void ChangeToInductionVariablePhis();
821cb0ef41Sopenharmony_ci  void ChangeToPhisAndInsertGuards();
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci private:
851cb0ef41Sopenharmony_ci  const int kAssumedLoopEntryIndex = 0;
861cb0ef41Sopenharmony_ci  const int kFirstBackedge = 1;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  struct Constraint {
891cb0ef41Sopenharmony_ci    Node* left;
901cb0ef41Sopenharmony_ci    InductionVariable::ConstraintKind kind;
911cb0ef41Sopenharmony_ci    Node* right;
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    bool operator!=(const Constraint& other) const {
941cb0ef41Sopenharmony_ci      return left != other.left || kind != other.kind || right != other.right;
951cb0ef41Sopenharmony_ci    }
961cb0ef41Sopenharmony_ci  };
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  using VariableLimits = FunctionalList<Constraint>;
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  void VisitBackedge(Node* from, Node* loop);
1011cb0ef41Sopenharmony_ci  void VisitNode(Node* node);
1021cb0ef41Sopenharmony_ci  void VisitMerge(Node* node);
1031cb0ef41Sopenharmony_ci  void VisitLoop(Node* node);
1041cb0ef41Sopenharmony_ci  void VisitIf(Node* node, bool polarity);
1051cb0ef41Sopenharmony_ci  void VisitStart(Node* node);
1061cb0ef41Sopenharmony_ci  void VisitLoopExit(Node* node);
1071cb0ef41Sopenharmony_ci  void VisitOtherControl(Node* node);
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  void AddCmpToLimits(VariableLimits* limits, Node* node,
1101cb0ef41Sopenharmony_ci                      InductionVariable::ConstraintKind kind, bool polarity);
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  void TakeConditionsFromFirstControl(Node* node);
1131cb0ef41Sopenharmony_ci  const InductionVariable* FindInductionVariable(Node* node);
1141cb0ef41Sopenharmony_ci  InductionVariable* TryGetInductionVariable(Node* phi);
1151cb0ef41Sopenharmony_ci  void DetectInductionVariables(Node* loop);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  Graph* graph() { return graph_; }
1181cb0ef41Sopenharmony_ci  CommonOperatorBuilder* common() { return common_; }
1191cb0ef41Sopenharmony_ci  Zone* zone() { return zone_; }
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci  Graph* graph_;
1221cb0ef41Sopenharmony_ci  CommonOperatorBuilder* common_;
1231cb0ef41Sopenharmony_ci  Zone* zone_;
1241cb0ef41Sopenharmony_ci  NodeAuxData<VariableLimits> limits_;
1251cb0ef41Sopenharmony_ci  NodeAuxData<bool> reduced_;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  ZoneMap<int, InductionVariable*> induction_vars_;
1281cb0ef41Sopenharmony_ci};
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci}  // namespace compiler
1311cb0ef41Sopenharmony_ci}  // namespace internal
1321cb0ef41Sopenharmony_ci}  // namespace v8
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_LOOP_VARIABLE_OPTIMIZER_H_
135