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