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