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 // TODO(turbofan): Move ExternalReference out of assembler.h | 10 // TODO(turbofan): Move ExternalReference out of assembler.h |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 private: | 311 private: |
312 int scale_; | 312 int scale_; |
313 bool power_of_two_plus_one_; | 313 bool power_of_two_plus_one_; |
314 }; | 314 }; |
315 | 315 |
316 typedef ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul, | 316 typedef ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul, |
317 IrOpcode::kWord32Shl> Int32ScaleMatcher; | 317 IrOpcode::kWord32Shl> Int32ScaleMatcher; |
318 typedef ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul, | 318 typedef ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul, |
319 IrOpcode::kWord64Shl> Int64ScaleMatcher; | 319 IrOpcode::kWord64Shl> Int64ScaleMatcher; |
320 | 320 |
321 | 321 template <class BinopMatcher, IrOpcode::Value AddOpcode, |
322 template <class BinopMatcher, IrOpcode::Value kAddOpcode, | 322 IrOpcode::Value SubOpcode, IrOpcode::Value kMulOpcode, |
323 IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode> | 323 IrOpcode::Value kShiftOpcode> |
324 struct AddMatcher : public BinopMatcher { | 324 struct AddMatcher : public BinopMatcher { |
325 static const IrOpcode::Value kOpcode = kAddOpcode; | 325 static const IrOpcode::Value kAddOpcode = AddOpcode; |
| 326 static const IrOpcode::Value kSubOpcode = SubOpcode; |
326 typedef ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode> Matcher; | 327 typedef ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode> Matcher; |
327 | 328 |
328 AddMatcher(Node* node, bool allow_input_swap) | 329 AddMatcher(Node* node, bool allow_input_swap) |
329 : BinopMatcher(node, allow_input_swap), | 330 : BinopMatcher(node, allow_input_swap), |
330 scale_(-1), | 331 scale_(-1), |
331 power_of_two_plus_one_(false) { | 332 power_of_two_plus_one_(false) { |
332 Initialize(node, allow_input_swap); | 333 Initialize(node, allow_input_swap); |
333 } | 334 } |
334 explicit AddMatcher(Node* node) | 335 explicit AddMatcher(Node* node) |
335 : BinopMatcher(node, node->op()->HasProperty(Operator::kCommutative)), | 336 : BinopMatcher(node, node->op()->HasProperty(Operator::kCommutative)), |
(...skipping 30 matching lines...) Expand all Loading... |
366 if (right_matcher.matches()) { | 367 if (right_matcher.matches()) { |
367 scale_ = right_matcher.scale(); | 368 scale_ = right_matcher.scale(); |
368 power_of_two_plus_one_ = right_matcher.power_of_two_plus_one(); | 369 power_of_two_plus_one_ = right_matcher.power_of_two_plus_one(); |
369 this->SwapInputs(); | 370 this->SwapInputs(); |
370 return; | 371 return; |
371 } | 372 } |
372 | 373 |
373 if (this->right().opcode() == kAddOpcode && | 374 if (this->right().opcode() == kAddOpcode && |
374 this->left().opcode() != kAddOpcode) { | 375 this->left().opcode() != kAddOpcode) { |
375 this->SwapInputs(); | 376 this->SwapInputs(); |
| 377 } else if (this->right().opcode() == kSubOpcode && |
| 378 this->left().opcode() != kSubOpcode) { |
| 379 this->SwapInputs(); |
376 } | 380 } |
377 } | 381 } |
378 | 382 |
379 int scale_; | 383 int scale_; |
380 bool power_of_two_plus_one_; | 384 bool power_of_two_plus_one_; |
381 }; | 385 }; |
382 | 386 |
383 typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Mul, | 387 typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Sub, |
384 IrOpcode::kWord32Shl> Int32AddMatcher; | 388 IrOpcode::kInt32Mul, IrOpcode::kWord32Shl> |
385 typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Mul, | 389 Int32AddMatcher; |
386 IrOpcode::kWord64Shl> Int64AddMatcher; | 390 typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Sub, |
| 391 IrOpcode::kInt64Mul, IrOpcode::kWord64Shl> |
| 392 Int64AddMatcher; |
387 | 393 |
| 394 enum DisplacementMode { kPositiveDisplacement, kNegativeDisplacement }; |
388 | 395 |
389 template <class AddMatcher> | 396 template <class AddMatcher> |
390 struct BaseWithIndexAndDisplacementMatcher { | 397 struct BaseWithIndexAndDisplacementMatcher { |
391 BaseWithIndexAndDisplacementMatcher(Node* node, bool allow_input_swap) | 398 BaseWithIndexAndDisplacementMatcher(Node* node, bool allow_input_swap) |
392 : matches_(false), | 399 : matches_(false), |
393 index_(nullptr), | 400 index_(nullptr), |
394 scale_(0), | 401 scale_(0), |
395 base_(nullptr), | 402 base_(nullptr), |
396 displacement_(nullptr) { | 403 displacement_(nullptr), |
| 404 displacement_mode_(kPositiveDisplacement) { |
397 Initialize(node, allow_input_swap); | 405 Initialize(node, allow_input_swap); |
398 } | 406 } |
399 | 407 |
400 explicit BaseWithIndexAndDisplacementMatcher(Node* node) | 408 explicit BaseWithIndexAndDisplacementMatcher(Node* node) |
401 : matches_(false), | 409 : matches_(false), |
402 index_(nullptr), | 410 index_(nullptr), |
403 scale_(0), | 411 scale_(0), |
404 base_(nullptr), | 412 base_(nullptr), |
405 displacement_(nullptr) { | 413 displacement_(nullptr), |
| 414 displacement_mode_(kPositiveDisplacement) { |
406 Initialize(node, node->op()->HasProperty(Operator::kCommutative)); | 415 Initialize(node, node->op()->HasProperty(Operator::kCommutative)); |
407 } | 416 } |
408 | 417 |
409 bool matches() const { return matches_; } | 418 bool matches() const { return matches_; } |
410 Node* index() const { return index_; } | 419 Node* index() const { return index_; } |
411 int scale() const { return scale_; } | 420 int scale() const { return scale_; } |
412 Node* base() const { return base_; } | 421 Node* base() const { return base_; } |
413 Node* displacement() const { return displacement_; } | 422 Node* displacement() const { return displacement_; } |
| 423 DisplacementMode displacement_mode() const { return displacement_mode_; } |
414 | 424 |
415 private: | 425 private: |
416 bool matches_; | 426 bool matches_; |
417 Node* index_; | 427 Node* index_; |
418 int scale_; | 428 int scale_; |
419 Node* base_; | 429 Node* base_; |
420 Node* displacement_; | 430 Node* displacement_; |
| 431 DisplacementMode displacement_mode_; |
421 | 432 |
422 void Initialize(Node* node, bool allow_input_swap) { | 433 void Initialize(Node* node, bool allow_input_swap) { |
423 // The BaseWithIndexAndDisplacementMatcher canonicalizes the order of | 434 // The BaseWithIndexAndDisplacementMatcher canonicalizes the order of |
424 // displacements and scale factors that are used as inputs, so instead of | 435 // displacements and scale factors that are used as inputs, so instead of |
425 // enumerating all possible patterns by brute force, checking for node | 436 // enumerating all possible patterns by brute force, checking for node |
426 // clusters using the following templates in the following order suffices to | 437 // clusters using the following templates in the following order suffices to |
427 // find all of the interesting cases (S = index * scale, B = base input, D = | 438 // find all of the interesting cases (S = index * scale, B = base input, D = |
428 // displacement input): | 439 // displacement input): |
429 // (S + (B + D)) | 440 // (S + (B + D)) |
430 // (S + (B + B)) | 441 // (S + (B + B)) |
431 // (S + D) | 442 // (S + D) |
432 // (S + B) | 443 // (S + B) |
433 // ((S + D) + B) | 444 // ((S + D) + B) |
434 // ((S + B) + D) | 445 // ((S + B) + D) |
435 // ((B + D) + B) | 446 // ((B + D) + B) |
436 // ((B + B) + D) | 447 // ((B + B) + D) |
437 // (B + D) | 448 // (B + D) |
438 // (B + B) | 449 // (B + B) |
439 if (node->InputCount() < 2) return; | 450 if (node->InputCount() < 2) return; |
440 AddMatcher m(node, allow_input_swap); | 451 AddMatcher m(node, allow_input_swap); |
441 Node* left = m.left().node(); | 452 Node* left = m.left().node(); |
442 Node* right = m.right().node(); | 453 Node* right = m.right().node(); |
443 Node* displacement = nullptr; | 454 Node* displacement = nullptr; |
444 Node* base = nullptr; | 455 Node* base = nullptr; |
445 Node* index = nullptr; | 456 Node* index = nullptr; |
446 Node* scale_expression = nullptr; | 457 Node* scale_expression = nullptr; |
447 bool power_of_two_plus_one = false; | 458 bool power_of_two_plus_one = false; |
| 459 DisplacementMode displacement_mode = kPositiveDisplacement; |
448 int scale = 0; | 460 int scale = 0; |
449 if (m.HasIndexInput() && left->OwnedBy(node)) { | 461 if (m.HasIndexInput() && left->OwnedBy(node)) { |
450 index = m.IndexInput(); | 462 index = m.IndexInput(); |
451 scale = m.scale(); | 463 scale = m.scale(); |
452 scale_expression = left; | 464 scale_expression = left; |
453 power_of_two_plus_one = m.power_of_two_plus_one(); | 465 power_of_two_plus_one = m.power_of_two_plus_one(); |
454 if (right->opcode() == AddMatcher::kOpcode && right->OwnedBy(node)) { | 466 bool match_found = false; |
| 467 if (right->opcode() == AddMatcher::kSubOpcode && right->OwnedBy(node)) { |
455 AddMatcher right_matcher(right); | 468 AddMatcher right_matcher(right); |
456 if (right_matcher.right().HasValue()) { | 469 if (right_matcher.right().HasValue()) { |
457 // (S + (B + D)) | 470 // (S + (B - D)) |
458 base = right_matcher.left().node(); | 471 base = right_matcher.left().node(); |
459 displacement = right_matcher.right().node(); | 472 displacement = right_matcher.right().node(); |
| 473 displacement_mode = kNegativeDisplacement; |
| 474 match_found = true; |
| 475 } |
| 476 } |
| 477 if (!match_found) { |
| 478 if (right->opcode() == AddMatcher::kAddOpcode && right->OwnedBy(node)) { |
| 479 AddMatcher right_matcher(right); |
| 480 if (right_matcher.right().HasValue()) { |
| 481 // (S + (B + D)) |
| 482 base = right_matcher.left().node(); |
| 483 displacement = right_matcher.right().node(); |
| 484 } else { |
| 485 // (S + (B + B)) |
| 486 base = right; |
| 487 } |
| 488 } else if (m.right().HasValue()) { |
| 489 // (S + D) |
| 490 displacement = right; |
460 } else { | 491 } else { |
461 // (S + (B + B)) | 492 // (S + B) |
462 base = right; | 493 base = right; |
463 } | 494 } |
464 } else if (m.right().HasValue()) { | |
465 // (S + D) | |
466 displacement = right; | |
467 } else { | |
468 // (S + B) | |
469 base = right; | |
470 } | 495 } |
471 } else { | 496 } else { |
472 if (left->opcode() == AddMatcher::kOpcode && left->OwnedBy(node)) { | 497 bool match_found = false; |
| 498 if (left->opcode() == AddMatcher::kSubOpcode && left->OwnedBy(node)) { |
473 AddMatcher left_matcher(left); | 499 AddMatcher left_matcher(left); |
474 Node* left_left = left_matcher.left().node(); | 500 Node* left_left = left_matcher.left().node(); |
475 Node* left_right = left_matcher.right().node(); | 501 Node* left_right = left_matcher.right().node(); |
476 if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) { | 502 if (left_matcher.right().HasValue()) { |
477 if (left_matcher.right().HasValue()) { | 503 if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) { |
478 // ((S + D) + B) | 504 // ((S - D) + B) |
479 index = left_matcher.IndexInput(); | 505 index = left_matcher.IndexInput(); |
480 scale = left_matcher.scale(); | 506 scale = left_matcher.scale(); |
481 scale_expression = left_left; | 507 scale_expression = left_left; |
482 power_of_two_plus_one = left_matcher.power_of_two_plus_one(); | 508 power_of_two_plus_one = left_matcher.power_of_two_plus_one(); |
483 displacement = left_right; | 509 displacement = left_right; |
| 510 displacement_mode = kNegativeDisplacement; |
484 base = right; | 511 base = right; |
485 } else if (m.right().HasValue()) { | 512 } else { |
486 // ((S + B) + D) | 513 // ((B - D) + B) |
487 index = left_matcher.IndexInput(); | 514 index = left_left; |
488 scale = left_matcher.scale(); | 515 displacement = left_right; |
489 scale_expression = left_left; | 516 displacement_mode = kNegativeDisplacement; |
490 power_of_two_plus_one = left_matcher.power_of_two_plus_one(); | 517 base = right; |
491 base = left_right; | 518 } |
| 519 match_found = true; |
| 520 } |
| 521 } |
| 522 if (!match_found) { |
| 523 if (left->opcode() == AddMatcher::kAddOpcode && left->OwnedBy(node)) { |
| 524 AddMatcher left_matcher(left); |
| 525 Node* left_left = left_matcher.left().node(); |
| 526 Node* left_right = left_matcher.right().node(); |
| 527 if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) { |
| 528 if (left_matcher.right().HasValue()) { |
| 529 // ((S + D) + B) |
| 530 index = left_matcher.IndexInput(); |
| 531 scale = left_matcher.scale(); |
| 532 scale_expression = left_left; |
| 533 power_of_two_plus_one = left_matcher.power_of_two_plus_one(); |
| 534 displacement = left_right; |
| 535 base = right; |
| 536 } else if (m.right().HasValue()) { |
| 537 // ((S + B) + D) |
| 538 index = left_matcher.IndexInput(); |
| 539 scale = left_matcher.scale(); |
| 540 scale_expression = left_left; |
| 541 power_of_two_plus_one = left_matcher.power_of_two_plus_one(); |
| 542 base = left_right; |
| 543 displacement = right; |
| 544 } else { |
| 545 // (B + B) |
| 546 index = left; |
| 547 base = right; |
| 548 } |
| 549 } else { |
| 550 if (left_matcher.right().HasValue()) { |
| 551 // ((B + D) + B) |
| 552 index = left_left; |
| 553 displacement = left_right; |
| 554 base = right; |
| 555 } else if (m.right().HasValue()) { |
| 556 // ((B + B) + D) |
| 557 index = left_left; |
| 558 base = left_right; |
| 559 displacement = right; |
| 560 } else { |
| 561 // (B + B) |
| 562 index = left; |
| 563 base = right; |
| 564 } |
| 565 } |
| 566 } else { |
| 567 if (m.right().HasValue()) { |
| 568 // (B + D) |
| 569 base = left; |
492 displacement = right; | 570 displacement = right; |
493 } else { | 571 } else { |
494 // (B + B) | 572 // (B + B) |
495 index = left; | 573 base = left; |
496 base = right; | 574 index = right; |
497 } | 575 } |
498 } else { | |
499 if (left_matcher.right().HasValue()) { | |
500 // ((B + D) + B) | |
501 index = left_left; | |
502 displacement = left_right; | |
503 base = right; | |
504 } else if (m.right().HasValue()) { | |
505 // ((B + B) + D) | |
506 index = left_left; | |
507 base = left_right; | |
508 displacement = right; | |
509 } else { | |
510 // (B + B) | |
511 index = left; | |
512 base = right; | |
513 } | |
514 } | |
515 } else { | |
516 if (m.right().HasValue()) { | |
517 // (B + D) | |
518 base = left; | |
519 displacement = right; | |
520 } else { | |
521 // (B + B) | |
522 base = left; | |
523 index = right; | |
524 } | 576 } |
525 } | 577 } |
526 } | 578 } |
527 int64_t value = 0; | 579 int64_t value = 0; |
528 if (displacement != nullptr) { | 580 if (displacement != nullptr) { |
529 switch (displacement->opcode()) { | 581 switch (displacement->opcode()) { |
530 case IrOpcode::kInt32Constant: { | 582 case IrOpcode::kInt32Constant: { |
531 value = OpParameter<int32_t>(displacement); | 583 value = OpParameter<int32_t>(displacement); |
532 break; | 584 break; |
533 } | 585 } |
(...skipping 16 matching lines...) Expand all Loading... |
550 // can't be folded into the match and the entire index * scale | 602 // can't be folded into the match and the entire index * scale |
551 // calculation must be computed separately. | 603 // calculation must be computed separately. |
552 index = scale_expression; | 604 index = scale_expression; |
553 scale = 0; | 605 scale = 0; |
554 } else { | 606 } else { |
555 base = index; | 607 base = index; |
556 } | 608 } |
557 } | 609 } |
558 base_ = base; | 610 base_ = base; |
559 displacement_ = displacement; | 611 displacement_ = displacement; |
| 612 displacement_mode_ = displacement_mode; |
560 index_ = index; | 613 index_ = index; |
561 scale_ = scale; | 614 scale_ = scale; |
562 matches_ = true; | 615 matches_ = true; |
563 } | 616 } |
564 }; | 617 }; |
565 | 618 |
566 typedef BaseWithIndexAndDisplacementMatcher<Int32AddMatcher> | 619 typedef BaseWithIndexAndDisplacementMatcher<Int32AddMatcher> |
567 BaseWithIndexAndDisplacement32Matcher; | 620 BaseWithIndexAndDisplacement32Matcher; |
568 typedef BaseWithIndexAndDisplacementMatcher<Int64AddMatcher> | 621 typedef BaseWithIndexAndDisplacementMatcher<Int64AddMatcher> |
569 BaseWithIndexAndDisplacement64Matcher; | 622 BaseWithIndexAndDisplacement64Matcher; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 Node* branch_; | 667 Node* branch_; |
615 Node* if_true_; | 668 Node* if_true_; |
616 Node* if_false_; | 669 Node* if_false_; |
617 }; | 670 }; |
618 | 671 |
619 } // namespace compiler | 672 } // namespace compiler |
620 } // namespace internal | 673 } // namespace internal |
621 } // namespace v8 | 674 } // namespace v8 |
622 | 675 |
623 #endif // V8_COMPILER_NODE_MATCHERS_H_ | 676 #endif // V8_COMPILER_NODE_MATCHERS_H_ |
OLD | NEW |