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