| 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 <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "src/compiler/node.h" | 10 #include "src/compiler/node.h" |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher; | 164 typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher; |
| 165 typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher; | 165 typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher; |
| 166 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher; | 166 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher; |
| 167 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher; | 167 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher; |
| 168 typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher; | 168 typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher; |
| 169 typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; | 169 typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; |
| 170 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; | 170 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; |
| 171 typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; | 171 typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; |
| 172 | 172 |
| 173 | 173 |
| 174 template <class BinopMatcher, IrOpcode::Value kMulOpcode, |
| 175 IrOpcode::Value kShiftOpcode> |
| 176 struct ScaleMatcher { |
| 177 explicit ScaleMatcher(Node* node, bool allow_power_of_two_plus_one = false) |
| 178 : scale_(-1), power_of_two_plus_one_(false) { |
| 179 if (node->InputCount() < 2) return; |
| 180 BinopMatcher m(node); |
| 181 if (node->opcode() == kShiftOpcode) { |
| 182 if (m.right().HasValue()) { |
| 183 typename BinopMatcher::RightMatcher::ValueType value = |
| 184 m.right().Value(); |
| 185 if (value >= 0 && value <= 3) { |
| 186 scale_ = static_cast<int>(value); |
| 187 } |
| 188 } |
| 189 } else if (node->opcode() == kMulOpcode) { |
| 190 if (m.right().HasValue()) { |
| 191 typename BinopMatcher::RightMatcher::ValueType value = |
| 192 m.right().Value(); |
| 193 if (value == 1) { |
| 194 scale_ = 0; |
| 195 } else if (value == 2) { |
| 196 scale_ = 1; |
| 197 } else if (value == 4) { |
| 198 scale_ = 2; |
| 199 } else if (value == 8) { |
| 200 scale_ = 3; |
| 201 } else if (allow_power_of_two_plus_one) { |
| 202 if (value == 3) { |
| 203 scale_ = 1; |
| 204 power_of_two_plus_one_ = true; |
| 205 } else if (value == 5) { |
| 206 scale_ = 2; |
| 207 power_of_two_plus_one_ = true; |
| 208 } else if (value == 9) { |
| 209 scale_ = 3; |
| 210 power_of_two_plus_one_ = true; |
| 211 } |
| 212 } |
| 213 } |
| 214 } |
| 215 } |
| 216 |
| 217 bool matches() const { return scale_ != -1; } |
| 218 int scale() const { return scale_; } |
| 219 bool power_of_two_plus_one() const { return power_of_two_plus_one_; } |
| 220 |
| 221 private: |
| 222 int scale_; |
| 223 bool power_of_two_plus_one_; |
| 224 }; |
| 225 |
| 226 typedef ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul, |
| 227 IrOpcode::kWord32Shl> Int32ScaleMatcher; |
| 228 typedef ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul, |
| 229 IrOpcode::kWord64Shl> Int64ScaleMatcher; |
| 230 |
| 231 |
| 174 template <class BinopMatcher, IrOpcode::Value kAddOpcode, | 232 template <class BinopMatcher, IrOpcode::Value kAddOpcode, |
| 175 IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode> | 233 IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode> |
| 176 struct AddMatcher : public BinopMatcher { | 234 struct AddMatcher : public BinopMatcher { |
| 177 static const IrOpcode::Value kOpcode = kAddOpcode; | 235 static const IrOpcode::Value kOpcode = kAddOpcode; |
| 236 typedef ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode> Matcher; |
| 178 | 237 |
| 179 explicit AddMatcher(Node* node) : BinopMatcher(node), scale_exponent_(-1) { | 238 explicit AddMatcher(Node* node) |
| 180 if (this->HasProperty(Operator::kCommutative)) PutScaledInputOnLeft(); | 239 : BinopMatcher(node), scale_(-1), power_of_two_plus_one_(false) { |
| 181 } | 240 Matcher left_matcher(this->left().node(), true); |
| 241 if (left_matcher.matches()) { |
| 242 scale_ = left_matcher.scale(); |
| 243 power_of_two_plus_one_ = left_matcher.power_of_two_plus_one(); |
| 244 return; |
| 245 } |
| 182 | 246 |
| 183 bool HasScaledInput() const { return scale_exponent_ != -1; } | 247 if (!this->HasProperty(Operator::kCommutative)) { |
| 184 Node* ScaledInput() const { | 248 return; |
| 185 DCHECK(HasScaledInput()); | 249 } |
| 186 return this->left().node()->InputAt(0); | |
| 187 } | |
| 188 int ScaleExponent() const { | |
| 189 DCHECK(HasScaledInput()); | |
| 190 return scale_exponent_; | |
| 191 } | |
| 192 | 250 |
| 193 private: | 251 Matcher right_matcher(this->right().node(), true); |
| 194 int GetInputScaleExponent(Node* node) const { | 252 if (right_matcher.matches()) { |
| 195 if (node->opcode() == kShiftOpcode) { | 253 scale_ = right_matcher.scale(); |
| 196 BinopMatcher m(node); | 254 power_of_two_plus_one_ = right_matcher.power_of_two_plus_one(); |
| 197 if (m.right().HasValue()) { | 255 this->SwapInputs(); |
| 198 typename BinopMatcher::RightMatcher::ValueType value = | 256 return; |
| 199 m.right().Value(); | |
| 200 if (value >= 0 && value <= 3) { | |
| 201 return static_cast<int>(value); | |
| 202 } | |
| 203 } | |
| 204 } else if (node->opcode() == kMulOpcode) { | |
| 205 BinopMatcher m(node); | |
| 206 if (m.right().HasValue()) { | |
| 207 typename BinopMatcher::RightMatcher::ValueType value = | |
| 208 m.right().Value(); | |
| 209 if (value == 1) { | |
| 210 return 0; | |
| 211 } else if (value == 2) { | |
| 212 return 1; | |
| 213 } else if (value == 4) { | |
| 214 return 2; | |
| 215 } else if (value == 8) { | |
| 216 return 3; | |
| 217 } | |
| 218 } | |
| 219 } | 257 } |
| 220 return -1; | |
| 221 } | |
| 222 | 258 |
| 223 void PutScaledInputOnLeft() { | 259 if (this->right().opcode() == kAddOpcode && |
| 224 scale_exponent_ = GetInputScaleExponent(this->right().node()); | 260 this->left().opcode() != kAddOpcode) { |
| 225 if (scale_exponent_ >= 0) { | 261 this->SwapInputs(); |
| 226 int left_scale_exponent = GetInputScaleExponent(this->left().node()); | |
| 227 if (left_scale_exponent == -1) { | |
| 228 this->SwapInputs(); | |
| 229 } else { | |
| 230 scale_exponent_ = left_scale_exponent; | |
| 231 } | |
| 232 } else { | |
| 233 scale_exponent_ = GetInputScaleExponent(this->left().node()); | |
| 234 if (scale_exponent_ == -1) { | |
| 235 if (this->right().opcode() == kAddOpcode && | |
| 236 this->left().opcode() != kAddOpcode) { | |
| 237 this->SwapInputs(); | |
| 238 } | |
| 239 } | |
| 240 } | 262 } |
| 241 } | 263 } |
| 242 | 264 |
| 243 int scale_exponent_; | 265 bool HasIndexInput() const { return scale_ != -1; } |
| 266 Node* IndexInput() const { |
| 267 DCHECK(HasIndexInput()); |
| 268 return this->left().node()->InputAt(0); |
| 269 } |
| 270 int scale() const { |
| 271 DCHECK(HasIndexInput()); |
| 272 return scale_; |
| 273 } |
| 274 bool power_of_two_plus_one() const { return power_of_two_plus_one_; } |
| 275 |
| 276 private: |
| 277 int scale_; |
| 278 bool power_of_two_plus_one_; |
| 244 }; | 279 }; |
| 245 | 280 |
| 246 typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Mul, | 281 typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Mul, |
| 247 IrOpcode::kWord32Shl> Int32AddMatcher; | 282 IrOpcode::kWord32Shl> Int32AddMatcher; |
| 248 typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Mul, | 283 typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Mul, |
| 249 IrOpcode::kWord64Shl> Int64AddMatcher; | 284 IrOpcode::kWord64Shl> Int64AddMatcher; |
| 250 | 285 |
| 286 |
| 251 template <class AddMatcher> | 287 template <class AddMatcher> |
| 252 struct ScaledWithOffsetMatcher { | 288 struct BaseWithIndexAndDisplacementMatcher { |
| 253 explicit ScaledWithOffsetMatcher(Node* node) | 289 explicit BaseWithIndexAndDisplacementMatcher(Node* node) |
| 254 : matches_(false), | 290 : matches_(false), |
| 255 scaled_(NULL), | 291 index_(NULL), |
| 256 scale_exponent_(0), | 292 scale_(0), |
| 257 offset_(NULL), | 293 base_(NULL), |
| 258 constant_(NULL) { | 294 displacement_(NULL) { |
| 259 // The ScaledWithOffsetMatcher canonicalizes the order of constants and | 295 // The BaseWithIndexAndDisplacementMatcher canonicalizes the order of |
| 260 // scale factors that are used as inputs, so instead of enumerating all | 296 // displacements and scale factors that are used as inputs, so instead of |
| 261 // possible patterns by brute force, checking for node clusters using the | 297 // enumerating all possible patterns by brute force, checking for node |
| 262 // following templates in the following order suffices to find all of the | 298 // clusters using the following templates in the following order suffices to |
| 263 // interesting cases (S = scaled input, O = offset input, C = constant | 299 // find all of the interesting cases (S = index * scale, B = base input, D = |
| 264 // input): | 300 // displacement input): |
| 265 // (S + (O + C)) | 301 // (S + (B + D)) |
| 266 // (S + (O + O)) | 302 // (S + (B + B)) |
| 267 // (S + C) | 303 // (S + D) |
| 268 // (S + O) | 304 // (S + B) |
| 269 // ((S + C) + O) | 305 // ((S + D) + B) |
| 270 // ((S + O) + C) | 306 // ((S + B) + D) |
| 271 // ((O + C) + O) | 307 // ((B + D) + B) |
| 272 // ((O + O) + C) | 308 // ((B + B) + D) |
| 273 // (O + C) | 309 // (B + D) |
| 274 // (O + O) | 310 // (B + B) |
| 275 if (node->InputCount() < 2) return; | 311 if (node->InputCount() < 2) return; |
| 276 AddMatcher base_matcher(node); | 312 AddMatcher m(node); |
| 277 Node* left = base_matcher.left().node(); | 313 Node* left = m.left().node(); |
| 278 Node* right = base_matcher.right().node(); | 314 Node* right = m.right().node(); |
| 279 if (base_matcher.HasScaledInput() && left->OwnedBy(node)) { | 315 Node* displacement = NULL; |
| 280 scaled_ = base_matcher.ScaledInput(); | 316 Node* base = NULL; |
| 281 scale_exponent_ = base_matcher.ScaleExponent(); | 317 Node* index = NULL; |
| 318 Node* scale_expression = NULL; |
| 319 bool power_of_two_plus_one = false; |
| 320 int scale = 0; |
| 321 if (m.HasIndexInput() && left->OwnedBy(node)) { |
| 322 index = m.IndexInput(); |
| 323 scale = m.scale(); |
| 324 scale_expression = left; |
| 325 power_of_two_plus_one = m.power_of_two_plus_one(); |
| 282 if (right->opcode() == AddMatcher::kOpcode && right->OwnedBy(node)) { | 326 if (right->opcode() == AddMatcher::kOpcode && right->OwnedBy(node)) { |
| 283 AddMatcher right_matcher(right); | 327 AddMatcher right_matcher(right); |
| 284 if (right_matcher.right().HasValue()) { | 328 if (right_matcher.right().HasValue()) { |
| 285 // (S + (O + C)) | 329 // (S + (B + D)) |
| 286 offset_ = right_matcher.left().node(); | 330 base = right_matcher.left().node(); |
| 287 constant_ = right_matcher.right().node(); | 331 displacement = right_matcher.right().node(); |
| 288 } else { | 332 } else { |
| 289 // (S + (O + O)) | 333 // (S + (B + B)) |
| 290 offset_ = right; | 334 base = right; |
| 291 } | 335 } |
| 292 } else if (base_matcher.right().HasValue()) { | 336 } else if (m.right().HasValue()) { |
| 293 // (S + C) | 337 // (S + D) |
| 294 constant_ = right; | 338 displacement = right; |
| 295 } else { | 339 } else { |
| 296 // (S + O) | 340 // (S + B) |
| 297 offset_ = right; | 341 base = right; |
| 298 } | 342 } |
| 299 } else { | 343 } else { |
| 300 if (left->opcode() == AddMatcher::kOpcode && left->OwnedBy(node)) { | 344 if (left->opcode() == AddMatcher::kOpcode && left->OwnedBy(node)) { |
| 301 AddMatcher left_matcher(left); | 345 AddMatcher left_matcher(left); |
| 302 Node* left_left = left_matcher.left().node(); | 346 Node* left_left = left_matcher.left().node(); |
| 303 Node* left_right = left_matcher.right().node(); | 347 Node* left_right = left_matcher.right().node(); |
| 304 if (left_matcher.HasScaledInput() && left_left->OwnedBy(left)) { | 348 if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) { |
| 305 if (left_matcher.right().HasValue()) { | 349 if (left_matcher.right().HasValue()) { |
| 306 // ((S + C) + O) | 350 // ((S + D) + B) |
| 307 scaled_ = left_matcher.ScaledInput(); | 351 index = left_matcher.IndexInput(); |
| 308 scale_exponent_ = left_matcher.ScaleExponent(); | 352 scale = left_matcher.scale(); |
| 309 constant_ = left_right; | 353 scale_expression = left_left; |
| 310 offset_ = right; | 354 power_of_two_plus_one = left_matcher.power_of_two_plus_one(); |
| 311 } else if (base_matcher.right().HasValue()) { | 355 displacement = left_right; |
| 312 // ((S + O) + C) | 356 base = right; |
| 313 scaled_ = left_matcher.ScaledInput(); | 357 } else if (m.right().HasValue()) { |
| 314 scale_exponent_ = left_matcher.ScaleExponent(); | 358 // ((S + B) + D) |
| 315 offset_ = left_right; | 359 index = left_matcher.IndexInput(); |
| 316 constant_ = right; | 360 scale = left_matcher.scale(); |
| 361 scale_expression = left_left; |
| 362 power_of_two_plus_one = left_matcher.power_of_two_plus_one(); |
| 363 base = left_right; |
| 364 displacement = right; |
| 317 } else { | 365 } else { |
| 318 // (O + O) | 366 // (B + B) |
| 319 scaled_ = left; | 367 index = left; |
| 320 offset_ = right; | 368 base = right; |
| 321 } | 369 } |
| 322 } else { | 370 } else { |
| 323 if (left_matcher.right().HasValue()) { | 371 if (left_matcher.right().HasValue()) { |
| 324 // ((O + C) + O) | 372 // ((B + D) + B) |
| 325 scaled_ = left_left; | 373 index = left_left; |
| 326 constant_ = left_right; | 374 displacement = left_right; |
| 327 offset_ = right; | 375 base = right; |
| 328 } else if (base_matcher.right().HasValue()) { | 376 } else if (m.right().HasValue()) { |
| 329 // ((O + O) + C) | 377 // ((B + B) + D) |
| 330 scaled_ = left_left; | 378 index = left_left; |
| 331 offset_ = left_right; | 379 base = left_right; |
| 332 constant_ = right; | 380 displacement = right; |
| 333 } else { | 381 } else { |
| 334 // (O + O) | 382 // (B + B) |
| 335 scaled_ = left; | 383 index = left; |
| 336 offset_ = right; | 384 base = right; |
| 337 } | 385 } |
| 338 } | 386 } |
| 339 } else { | 387 } else { |
| 340 if (base_matcher.right().HasValue()) { | 388 if (m.right().HasValue()) { |
| 341 // (O + C) | 389 // (B + D) |
| 342 offset_ = left; | 390 base = left; |
| 343 constant_ = right; | 391 displacement = right; |
| 344 } else { | 392 } else { |
| 345 // (O + O) | 393 // (B + B) |
| 346 offset_ = left; | 394 base = left; |
| 347 scaled_ = right; | 395 index = right; |
| 348 } | 396 } |
| 349 } | 397 } |
| 350 } | 398 } |
| 351 int64_t value = 0; | 399 int64_t value = 0; |
| 352 if (constant_ != NULL) { | 400 if (displacement != NULL) { |
| 353 switch (constant_->opcode()) { | 401 switch (displacement->opcode()) { |
| 354 case IrOpcode::kInt32Constant: { | 402 case IrOpcode::kInt32Constant: { |
| 355 value = OpParameter<int32_t>(constant_); | 403 value = OpParameter<int32_t>(displacement); |
| 356 break; | 404 break; |
| 357 } | 405 } |
| 358 case IrOpcode::kInt64Constant: { | 406 case IrOpcode::kInt64Constant: { |
| 359 value = OpParameter<int64_t>(constant_); | 407 value = OpParameter<int64_t>(displacement); |
| 360 break; | 408 break; |
| 361 } | 409 } |
| 362 default: | 410 default: |
| 363 UNREACHABLE(); | 411 UNREACHABLE(); |
| 364 break; | 412 break; |
| 365 } | 413 } |
| 366 if (value == 0) { | 414 if (value == 0) { |
| 367 constant_ = NULL; | 415 displacement = NULL; |
| 368 } | 416 } |
| 369 } | 417 } |
| 418 if (power_of_two_plus_one) { |
| 419 if (base != NULL) { |
| 420 // If the scale requires explicitly using the index as the base, but a |
| 421 // base is already part of the match, then the (1 << N + 1) scale factor |
| 422 // can't be folded into the match and the entire index * scale |
| 423 // calculation must be computed separately. |
| 424 index = scale_expression; |
| 425 scale = 0; |
| 426 } else { |
| 427 base = index; |
| 428 } |
| 429 } |
| 430 base_ = base; |
| 431 displacement_ = displacement; |
| 432 index_ = index; |
| 433 scale_ = scale; |
| 370 matches_ = true; | 434 matches_ = true; |
| 371 } | 435 } |
| 372 | 436 |
| 373 bool matches() const { return matches_; } | 437 bool matches() const { return matches_; } |
| 374 Node* scaled() const { return scaled_; } | 438 Node* index() const { return index_; } |
| 375 int scale_exponent() const { return scale_exponent_; } | 439 int scale() const { return scale_; } |
| 376 Node* offset() const { return offset_; } | 440 Node* base() const { return base_; } |
| 377 Node* constant() const { return constant_; } | 441 Node* displacement() const { return displacement_; } |
| 378 | 442 |
| 379 private: | 443 private: |
| 380 bool matches_; | 444 bool matches_; |
| 381 | 445 |
| 382 protected: | 446 protected: |
| 383 Node* scaled_; | 447 Node* index_; |
| 384 int scale_exponent_; | 448 int scale_; |
| 385 Node* offset_; | 449 Node* base_; |
| 386 Node* constant_; | 450 Node* displacement_; |
| 387 }; | 451 }; |
| 388 | 452 |
| 389 typedef ScaledWithOffsetMatcher<Int32AddMatcher> ScaledWithOffset32Matcher; | 453 typedef BaseWithIndexAndDisplacementMatcher<Int32AddMatcher> |
| 390 typedef ScaledWithOffsetMatcher<Int64AddMatcher> ScaledWithOffset64Matcher; | 454 BaseWithIndexAndDisplacement32Matcher; |
| 455 typedef BaseWithIndexAndDisplacementMatcher<Int64AddMatcher> |
| 456 BaseWithIndexAndDisplacement64Matcher; |
| 391 | 457 |
| 392 } // namespace compiler | 458 } // namespace compiler |
| 393 } // namespace internal | 459 } // namespace internal |
| 394 } // namespace v8 | 460 } // namespace v8 |
| 395 | 461 |
| 396 #endif // V8_COMPILER_NODE_MATCHERS_H_ | 462 #endif // V8_COMPILER_NODE_MATCHERS_H_ |
| OLD | NEW |