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
78     // control uses will be relaxed assuming {node} cannot throw.
79     virtual void ReplaceWithValue(Node* node, Node* value, Node* effect,
80                                   Node* control) = 0;
81   };
82 
AdvancedReducer(Editor * editor)83   explicit AdvancedReducer(Editor* editor) : editor_(editor) {}
84 
85  protected:
86   // Helper functions for subclasses to produce reductions for a node.
Replace(Node * node)87   static Reduction Replace(Node* node) { return Reducer::Replace(node); }
88 
89   // Helper functions for subclasses to edit the graph.
Replace(Node * node,Node * replacement)90   void Replace(Node* node, Node* replacement) {
91     DCHECK_NOT_NULL(editor_);
92     editor_->Replace(node, replacement);
93   }
Revisit(Node * node)94   void Revisit(Node* node) {
95     DCHECK_NOT_NULL(editor_);
96     editor_->Revisit(node);
97   }
98   void ReplaceWithValue(Node* node, Node* value, Node* effect = nullptr,
99                         Node* control = nullptr) {
100     DCHECK_NOT_NULL(editor_);
101     editor_->ReplaceWithValue(node, value, effect, control);
102   }
103 
104   // Relax the effects of {node} by immediately replacing effect and control
105   // uses of {node} with the effect and control input to {node}.
106   // TODO(turbofan): replace the effect input to {node} with {graph->start()}.
RelaxEffectsAndControls(Node * node)107   void RelaxEffectsAndControls(Node* node) {
108     ReplaceWithValue(node, node, nullptr, nullptr);
109   }
110 
111   // Relax the control uses of {node} by immediately replacing them with the
112   // control input to {node}.
RelaxControls(Node * node)113   void RelaxControls(Node* node) {
114     ReplaceWithValue(node, node, node, nullptr);
115   }
116 
117  private:
118   Editor* const editor_;
119 };
120 
121 
122 // Performs an iterative reduction of a node graph.
123 class GraphReducer : public AdvancedReducer::Editor {
124  public:
125   GraphReducer(Zone* zone, Graph* graph, Node* dead = nullptr);
126   ~GraphReducer();
127 
graph()128   Graph* graph() const { return graph_; }
129 
130   void AddReducer(Reducer* reducer);
131 
132   // Reduce a single node.
133   void ReduceNode(Node* const);
134   // Reduce the whole graph.
135   void ReduceGraph();
136 
137  private:
138   enum class State : uint8_t;
139   struct NodeState {
140     Node* node;
141     int input_index;
142   };
143 
144   // Reduce a single node.
145   Reduction Reduce(Node* const);
146   // Reduce the node on top of the stack.
147   void ReduceTop();
148 
149   // Replace {node} with {replacement}.
150   void Replace(Node* node, Node* replacement) final;
151 
152   // Replace value uses of {node} with {value} and effect uses of {node} with
153   // {effect}. If {effect == nullptr}, then use the effect input to {node}. All
154   // control uses will be relaxed assuming {node} cannot throw.
155   void ReplaceWithValue(Node* node, Node* value, Node* effect,
156                         Node* control) final;
157 
158   // Replace all uses of {node} with {replacement} if the id of {replacement} is
159   // less than or equal to {max_id}. Otherwise, replace all uses of {node} whose
160   // id is less than or equal to {max_id} with the {replacement}.
161   void Replace(Node* node, Node* replacement, NodeId max_id);
162 
163   // Node stack operations.
164   void Pop();
165   void Push(Node* node);
166 
167   // Revisit queue operations.
168   bool Recurse(Node* node);
169   void Revisit(Node* node) final;
170 
171   Graph* const graph_;
172   Node* const dead_;
173   NodeMarker<State> state_;
174   ZoneVector<Reducer*> reducers_;
175   ZoneStack<Node*> revisit_;
176   ZoneStack<NodeState> stack_;
177 
178   DISALLOW_COPY_AND_ASSIGN(GraphReducer);
179 };
180 
181 }  // namespace compiler
182 }  // namespace internal
183 }  // namespace v8
184 
185 #endif  // V8_COMPILER_GRAPH_REDUCER_H_
186