blob: 2ac60a6d1d3577e02bf2a77b77d2eb25e6a6c26b [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/compiler/node-marker.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/zone-containers.h"
10
11namespace v8 {
12namespace internal {
13namespace compiler {
14
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015// Forward declarations.
16class Graph;
17class 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.
22typedef uint32_t NodeId;
23
24
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025// Represents the result of trying to reduce a node in the graph.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026class Reduction final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 explicit Reduction(Node* replacement = nullptr) : replacement_(replacement) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029
30 Node* replacement() const { return replacement_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031 bool Changed() const { return replacement() != nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032
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.
43class Reducer {
44 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045 virtual ~Reducer() {}
46
47 // Try to reduce a node if possible.
48 virtual Reduction Reduce(Node* node) = 0;
49
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 // 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 // Helper functions for subclasses to produce reductions for a node.
56 static Reduction NoChange() { return Reduction(); }
57 static Reduction Replace(Node* node) { return Reduction(node); }
58 static Reduction Changed(Node* node) { return Reduction(node); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059};
60
61
62// An advanced reducer can also edit the graphs by changing and replacing nodes
63// other than the one currently being reduced.
64class AdvancedReducer : public Reducer {
65 public:
66 // Observe the actions of this reducer.
67 class Editor {
68 public:
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}.
Ben Murdoch61f157c2016-09-16 13:49:30 +010077 // All control uses will be relaxed assuming {node} cannot throw.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 virtual void ReplaceWithValue(Node* node, Node* value, Node* effect,
79 Node* control) = 0;
80 };
81
82 explicit AdvancedReducer(Editor* editor) : editor_(editor) {}
83
84 protected:
85 // Helper functions for subclasses to produce reductions for a node.
86 static Reduction Replace(Node* node) { return Reducer::Replace(node); }
87
88 // Helper functions for subclasses to edit the graph.
89 void Replace(Node* node, Node* replacement) {
90 DCHECK_NOT_NULL(editor_);
91 editor_->Replace(node, replacement);
92 }
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()}.
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}.
112 void RelaxControls(Node* node) {
113 ReplaceWithValue(node, node, node, nullptr);
114 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115
116 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 Editor* const editor_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118};
119
120
121// Performs an iterative reduction of a node graph.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122class GraphReducer : public AdvancedReducer::Editor {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 GraphReducer(Zone* zone, Graph* graph, Node* dead = nullptr);
125 ~GraphReducer();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126
127 Graph* graph() const { return graph_; }
128
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400129 void AddReducer(Reducer* reducer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130
131 // Reduce a single node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400132 void ReduceNode(Node* const);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 // Reduce the whole graph.
134 void ReduceGraph();
135
136 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148 // 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 // Node stack operations.
163 void Pop();
164 void Push(Node* node);
165
166 // Revisit queue operations.
167 bool Recurse(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 void Revisit(Node* node) final;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 Graph* const graph_;
171 Node* const dead_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400172 NodeMarker<State> state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 ZoneVector<Reducer*> reducers_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174 ZoneStack<Node*> revisit_;
175 ZoneStack<NodeState> stack_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176
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_