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