• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_GRAPH_REDUCER_H_
6 #define V8_COMPILER_GRAPH_REDUCER_H_
7 
8 #include "src/compiler/node-marker.h"
9 #include "src/zone-containers.h"
10 
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14 
15 // Forward declarations.
16 class Graph;
17 class Node;
18 
19 
20 // NodeIds are identifying numbers for nodes that can be used to index auxiliary
21 // out-of-line data associated with each node.
22 typedef uint32_t NodeId;
23 
24 
25 // Represents the result of trying to reduce a node in the graph.
26 class Reduction final {
27  public:
replacement_(replacement)28   explicit Reduction(Node* replacement = nullptr) : replacement_(replacement) {}
29 
replacement()30   Node* replacement() const { return replacement_; }
Changed()31   bool Changed() const { return replacement() != nullptr; }
32 
33  private:
34   Node* replacement_;
35 };
36 
37 
38 // A reducer can reduce or simplify a given node based on its operator and
39 // inputs. This class functions as an extension point for the graph reducer for
40 // language-specific reductions (e.g. reduction based on types or constant
41 // folding of low-level operators) can be integrated into the graph reduction
42 // phase.
43 class Reducer {
44  public:
~Reducer()45   virtual ~Reducer() {}
46 
47   // Try to reduce a node if possible.
48   virtual Reduction Reduce(Node* node) = 0;
49 
50   // Invoked by the {GraphReducer} when all nodes are done.  Can be used to
51   // do additional reductions at the end, which in turn can cause a new round
52   // of reductions.
53   virtual void Finalize();
54 
55   // Helper functions for subclasses to produce reductions for a node.
NoChange()56   static Reduction NoChange() { return Reduction(); }
Replace(Node * node)57   static Reduction Replace(Node* node) { return Reduction(node); }
Changed(Node * node)58   static Reduction Changed(Node* node) { return Reduction(node); }
59 };
60 
61 
62 // An advanced reducer can also edit the graphs by changing and replacing nodes
63 // other than the one currently being reduced.
64 class AdvancedReducer : public Reducer {
65  public:
66   // Observe the actions of this reducer.
67   class Editor {
68    public:
~Editor()69     virtual ~Editor() {}
70 
71     // Replace {node} with {replacement}.
72     virtual void Replace(Node* node, Node* replacement) = 0;
73     // Revisit the {node} again later.
74     virtual void Revisit(Node* node) = 0;
75     // Replace value uses of {node} with {value} and effect uses of {node} with
76     // {effect}. If {effect == nullptr}, then use the effect input to {node}.
77     // All control uses will be relaxed assuming {node} cannot throw.
78     virtual void ReplaceWithValue(Node* node, Node* value, Node* effect,
79                                   Node* control) = 0;
80   };
81 
AdvancedReducer(Editor * editor)82   explicit AdvancedReducer(Editor* editor) : editor_(editor) {}
83 
84  protected:
85   // Helper functions for subclasses to produce reductions for a node.
Replace(Node * node)86   static Reduction Replace(Node* node) { return Reducer::Replace(node); }
87 
88   // Helper functions for subclasses to edit the graph.
Replace(Node * node,Node * replacement)89   void Replace(Node* node, Node* replacement) {
90     DCHECK_NOT_NULL(editor_);
91     editor_->Replace(node, replacement);
92   }
Revisit(Node * node)93   void Revisit(Node* node) {
94     DCHECK_NOT_NULL(editor_);
95     editor_->Revisit(node);
96   }
97   void ReplaceWithValue(Node* node, Node* value, Node* effect = nullptr,
98                         Node* control = nullptr) {
99     DCHECK_NOT_NULL(editor_);
100     editor_->ReplaceWithValue(node, value, effect, control);
101   }
102 
103   // Relax the effects of {node} by immediately replacing effect and control
104   // uses of {node} with the effect and control input to {node}.
105   // TODO(turbofan): replace the effect input to {node} with {graph->start()}.
RelaxEffectsAndControls(Node * node)106   void RelaxEffectsAndControls(Node* node) {
107     ReplaceWithValue(node, node, nullptr, nullptr);
108   }
109 
110   // Relax the control uses of {node} by immediately replacing them with the
111   // control input to {node}.
RelaxControls(Node * node)112   void RelaxControls(Node* node) {
113     ReplaceWithValue(node, node, node, nullptr);
114   }
115 
116  private:
117   Editor* const editor_;
118 };
119 
120 
121 // Performs an iterative reduction of a node graph.
122 class GraphReducer : public AdvancedReducer::Editor {
123  public:
124   GraphReducer(Zone* zone, Graph* graph, Node* dead = nullptr);
125   ~GraphReducer();
126 
graph()127   Graph* graph() const { return graph_; }
128 
129   void AddReducer(Reducer* reducer);
130 
131   // Reduce a single node.
132   void ReduceNode(Node* const);
133   // Reduce the whole graph.
134   void ReduceGraph();
135 
136  private:
137   enum class State : uint8_t;
138   struct NodeState {
139     Node* node;
140     int input_index;
141   };
142 
143   // Reduce a single node.
144   Reduction Reduce(Node* const);
145   // Reduce the node on top of the stack.
146   void ReduceTop();
147 
148   // Replace {node} with {replacement}.
149   void Replace(Node* node, Node* replacement) final;
150 
151   // Replace value uses of {node} with {value} and effect uses of {node} with
152   // {effect}. If {effect == nullptr}, then use the effect input to {node}. All
153   // control uses will be relaxed assuming {node} cannot throw.
154   void ReplaceWithValue(Node* node, Node* value, Node* effect,
155                         Node* control) final;
156 
157   // Replace all uses of {node} with {replacement} if the id of {replacement} is
158   // less than or equal to {max_id}. Otherwise, replace all uses of {node} whose
159   // id is less than or equal to {max_id} with the {replacement}.
160   void Replace(Node* node, Node* replacement, NodeId max_id);
161 
162   // Node stack operations.
163   void Pop();
164   void Push(Node* node);
165 
166   // Revisit queue operations.
167   bool Recurse(Node* node);
168   void Revisit(Node* node) final;
169 
170   Graph* const graph_;
171   Node* const dead_;
172   NodeMarker<State> state_;
173   ZoneVector<Reducer*> reducers_;
174   ZoneStack<Node*> revisit_;
175   ZoneStack<NodeState> stack_;
176 
177   DISALLOW_COPY_AND_ASSIGN(GraphReducer);
178 };
179 
180 }  // namespace compiler
181 }  // namespace internal
182 }  // namespace v8
183 
184 #endif  // V8_COMPILER_GRAPH_REDUCER_H_
185