OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_COMPILER_NODE_MATCHERS_H_ | 5 #ifndef V8_COMPILER_NODE_MATCHERS_H_ |
6 #define V8_COMPILER_NODE_MATCHERS_H_ | 6 #define V8_COMPILER_NODE_MATCHERS_H_ |
7 | 7 |
8 #include "src/compiler/node.h" | 8 #include "src/compiler/node.h" |
9 #include "src/compiler/operator.h" | 9 #include "src/compiler/operator.h" |
10 #include "src/unique.h" | 10 #include "src/unique.h" |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 : public ValueMatcher<Unique<T>, IrOpcode::kHeapConstant> { | 109 : public ValueMatcher<Unique<T>, IrOpcode::kHeapConstant> { |
110 explicit HeapObjectMatcher(Node* node) | 110 explicit HeapObjectMatcher(Node* node) |
111 : ValueMatcher<Unique<T>, IrOpcode::kHeapConstant>(node) {} | 111 : ValueMatcher<Unique<T>, IrOpcode::kHeapConstant>(node) {} |
112 }; | 112 }; |
113 | 113 |
114 | 114 |
115 // For shorter pattern matching code, this struct matches both the left and | 115 // For shorter pattern matching code, this struct matches both the left and |
116 // right hand sides of a binary operation and can put constants on the right | 116 // right hand sides of a binary operation and can put constants on the right |
117 // if they appear on the left hand side of a commutative operation. | 117 // if they appear on the left hand side of a commutative operation. |
118 template <typename Left, typename Right> | 118 template <typename Left, typename Right> |
119 struct BinopMatcher FINAL : public NodeMatcher { | 119 struct BinopMatcher : public NodeMatcher { |
120 explicit BinopMatcher(Node* node) | 120 explicit BinopMatcher(Node* node) |
121 : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { | 121 : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { |
122 if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); | 122 if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); |
123 } | 123 } |
124 | 124 |
125 const Left& left() const { return left_; } | 125 const Left& left() const { return left_; } |
126 const Right& right() const { return right_; } | 126 const Right& right() const { return right_; } |
127 | 127 |
128 bool IsFoldable() const { return left().HasValue() && right().HasValue(); } | 128 bool IsFoldable() const { return left().HasValue() && right().HasValue(); } |
129 bool LeftEqualsRight() const { return left().node() == right().node(); } | 129 bool LeftEqualsRight() const { return left().node() == right().node(); } |
130 | 130 |
131 protected: | |
132 void SwapInputs() { | |
133 std::swap(left_, right_); | |
134 node()->ReplaceInput(0, left().node()); | |
135 node()->ReplaceInput(1, right().node()); | |
136 } | |
137 | |
131 private: | 138 private: |
132 void PutConstantOnRight() { | 139 void PutConstantOnRight() { |
133 if (left().HasValue() && !right().HasValue()) { | 140 if (left().HasValue() && !right().HasValue()) { |
134 std::swap(left_, right_); | 141 SwapInputs(); |
135 node()->ReplaceInput(0, left().node()); | |
136 node()->ReplaceInput(1, right().node()); | |
137 } | 142 } |
138 } | 143 } |
139 | 144 |
140 Left left_; | 145 Left left_; |
141 Right right_; | 146 Right right_; |
142 }; | 147 }; |
143 | 148 |
144 typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher; | 149 typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher; |
145 typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher; | 150 typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher; |
146 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher; | 151 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher; |
147 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher; | 152 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher; |
148 typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher; | 153 typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher; |
149 typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; | 154 typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; |
150 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; | 155 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; |
151 typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; | 156 typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; |
152 | 157 |
158 struct Int32AddMatcher : public Int32BinopMatcher { | |
159 explicit Int32AddMatcher(Node* node) | |
160 : Int32BinopMatcher(node), has_scaled_input_(false), scale_factor_(-1) { | |
161 PutScaledInputOnLeft(); | |
162 if (HasScaledInput()) { | |
163 Int32BinopMatcher m(left().node()); | |
164 if (m.opcode() == IrOpcode::kWord32Shl) { | |
165 scale_factor_ = 1 << m.right().Value(); | |
166 } else { | |
167 DCHECK(m.opcode() == IrOpcode::kInt32Mul); | |
168 scale_factor_ = m.right().Value(); | |
169 } | |
170 } | |
171 } | |
172 | |
173 bool HasScaledInput() const { return has_scaled_input_; } | |
174 Node* ScaledInput() const { | |
175 DCHECK(HasScaledInput()); | |
176 return left().node()->InputAt(0); | |
177 } | |
178 int ScaleFactor() const { | |
179 DCHECK(HasScaledInput()); | |
180 return scale_factor_; | |
181 } | |
182 | |
183 private: | |
184 bool IsScaledInput(Node* node) const { | |
titzer
2014/11/06 11:47:06
You could also have this method return the scaled
danno
2014/11/06 23:34:07
Done.
| |
185 if (node->opcode() == IrOpcode::kWord32Shl) { | |
186 Int32BinopMatcher m(node->InputAt(1)); | |
187 if (m.right().HasValue()) { | |
188 int32_t value = m.right().Value(); | |
189 return (value == 0) || (value == 1) || (value == 2) || (value == 3); | |
190 } | |
191 } else if (node->opcode() == IrOpcode::kInt32Mul) { | |
192 Int32BinopMatcher m(node->InputAt(1)); | |
193 if (m.right().HasValue()) { | |
194 int32_t value = m.right().Value(); | |
195 return (value == 1) || (value == 2) || (value == 4) || (value == 8); | |
196 } | |
197 } | |
198 return false; | |
199 } | |
200 | |
201 void PutScaledInputOnLeft() { | |
202 if (IsScaledInput(right().node()) && !IsScaledInput(left().node())) { | |
203 SwapInputs(); | |
204 } | |
205 | |
206 if (IsScaledInput(left().node())) { | |
207 has_scaled_input_ = true; | |
208 } else { | |
209 if (right().opcode() == IrOpcode::kInt32Add && | |
210 left().opcode() != IrOpcode::kInt32Add) { | |
211 SwapInputs(); | |
212 } | |
213 } | |
214 } | |
215 | |
216 bool has_scaled_input_; | |
217 int scale_factor_; | |
218 }; | |
219 | |
220 struct ScaledWithOffsetMatcher { | |
221 explicit ScaledWithOffsetMatcher(Node* node) | |
222 : matches_(false), | |
223 scaled_(NULL), | |
224 scale_factor_(1), | |
225 offset_(NULL), | |
226 constant_(NULL) { | |
227 if (node->opcode() != IrOpcode::kInt32Add) return; | |
228 | |
229 // The Int32AddMatcher canonicalizes the order of constants and scale | |
230 // factors that are used as inputs, so instead of enumerating all possible | |
231 // patterns by brute force, checking for node clusters using the following | |
232 // templates in the following order suffices to find all of the interesting | |
233 // cases (S = scaled input, O = offset input, C = constant input): | |
234 // (S + (O + C)) | |
235 // (S + (O + O)) | |
236 // (S + C) | |
237 // (S + O) | |
238 // ((S + C) + O) | |
239 // ((S + O) + C) | |
240 // ((O + C) + O) | |
241 // ((O + O) + C) | |
242 // (O + C) | |
243 // (O + O) | |
244 Int32AddMatcher base_matcher(node); | |
245 Node* left = base_matcher.left().node(); | |
246 Node* right = base_matcher.right().node(); | |
247 if (base_matcher.HasScaledInput() && left->OwnedBy(node)) { | |
248 scaled_ = base_matcher.ScaledInput(); | |
249 scale_factor_ = base_matcher.ScaleFactor(); | |
250 if (right->opcode() == IrOpcode::kInt32Add && right->OwnedBy(node)) { | |
251 Int32AddMatcher right_matcher(right); | |
252 if (right_matcher.right().HasValue()) { | |
253 // (S + (O + C)) | |
254 offset_ = right_matcher.left().node(); | |
255 constant_ = right_matcher.right().node(); | |
256 } else { | |
257 // (S + (O + O)) | |
258 offset_ = right; | |
259 } | |
260 } else if (base_matcher.right().HasValue()) { | |
261 // (S + C) | |
262 constant_ = right; | |
263 } else { | |
264 // (S + O) | |
265 offset_ = right; | |
266 } | |
267 } else { | |
268 if (left->opcode() == IrOpcode::kInt32Add && left->OwnedBy(node)) { | |
269 Int32AddMatcher left_matcher(left); | |
270 Node* left_left = left_matcher.left().node(); | |
271 Node* left_right = left_matcher.right().node(); | |
272 if (left_matcher.HasScaledInput() && left_left->OwnedBy(left)) { | |
273 scaled_ = left_matcher.ScaledInput(); | |
274 scale_factor_ = left_matcher.ScaleFactor(); | |
275 if (left_matcher.right().HasValue()) { | |
276 // ((S + C) + O) | |
277 constant_ = left_right; | |
278 offset_ = right; | |
279 } else if (base_matcher.right().HasValue()) { | |
280 // ((S + O) + C) | |
281 offset_ = left_right; | |
282 constant_ = right; | |
283 } else { | |
284 // (O + O) | |
285 scaled_ = left; | |
286 offset_ = right; | |
287 } | |
288 } else { | |
289 if (left_matcher.right().HasValue()) { | |
290 // ((O + C) + O) | |
291 scaled_ = left_left; | |
292 constant_ = left_right; | |
293 offset_ = right; | |
294 } else if (base_matcher.right().HasValue()) { | |
295 // ((O + O) + C) | |
296 scaled_ = left_left; | |
297 offset_ = left_right; | |
298 constant_ = right; | |
299 } else { | |
300 // (O + O) | |
301 scaled_ = left; | |
302 offset_ = right; | |
303 } | |
304 } | |
305 } else { | |
306 if (base_matcher.right().HasValue()) { | |
307 // (O + C) | |
308 offset_ = left; | |
309 constant_ = right; | |
310 } else { | |
311 // (O + O) | |
312 offset_ = left; | |
313 scaled_ = right; | |
314 } | |
315 } | |
316 } | |
317 matches_ = true; | |
318 } | |
319 | |
320 bool Matches() const { return matches_; } | |
titzer
2014/11/06 11:47:06
Lower case for simple getters.
danno
2014/11/06 23:34:07
Done.
| |
321 Node* Scaled() const { return scaled_; } | |
322 int ScaleFactor() const { return scale_factor_; } | |
323 Node* Offset() const { return offset_; } | |
324 Node* Constant() const { return constant_; } | |
325 | |
326 private: | |
327 bool matches_; | |
328 | |
329 protected: | |
330 Node* scaled_; | |
331 int scale_factor_; | |
332 Node* offset_; | |
333 Node* constant_; | |
334 }; | |
335 | |
153 } // namespace compiler | 336 } // namespace compiler |
154 } // namespace internal | 337 } // namespace internal |
155 } // namespace v8 | 338 } // namespace v8 |
156 | 339 |
157 #endif // V8_COMPILER_NODE_MATCHERS_H_ | 340 #endif // V8_COMPILER_NODE_MATCHERS_H_ |
OLD | NEW |