OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/factory.h" | 7 #include "src/factory.h" |
8 #include "src/interpreter/bytecode-label.h" | 8 #include "src/interpreter/bytecode-label.h" |
9 #include "src/interpreter/bytecode-peephole-optimizer.h" | 9 #include "src/interpreter/bytecode-peephole-optimizer.h" |
10 #include "src/interpreter/constant-array-builder.h" | 10 #include "src/interpreter/constant-array-builder.h" |
11 #include "src/objects-inl.h" | 11 #include "src/objects-inl.h" |
12 #include "src/objects.h" | 12 #include "src/objects.h" |
13 #include "test/unittests/test-utils.h" | 13 #include "test/unittests/test-utils.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 namespace interpreter { | 17 namespace interpreter { |
18 | 18 |
19 class BytecodePeepholeOptimizerTest : public BytecodePipelineStage, | 19 class BytecodePeepholeOptimizerTest : public BytecodePipelineStage, |
20 public TestWithIsolateAndZone { | 20 public TestWithIsolateAndZone { |
21 public: | 21 public: |
22 BytecodePeepholeOptimizerTest() | 22 BytecodePeepholeOptimizerTest() |
23 : constant_array_builder_(isolate(), zone()), | 23 : constant_array_builder_(isolate(), zone()), |
24 peephole_optimizer_(&constant_array_builder_, this) {} | 24 peephole_optimizer_(&constant_array_builder_, this) {} |
25 ~BytecodePeepholeOptimizerTest() override {} | 25 ~BytecodePeepholeOptimizerTest() override {} |
26 | 26 |
| 27 void Reset() { |
| 28 last_written_.set_bytecode(Bytecode::kIllegal); |
| 29 write_count_ = 0; |
| 30 } |
| 31 |
27 void Write(BytecodeNode* node) override { | 32 void Write(BytecodeNode* node) override { |
28 write_count_++; | 33 write_count_++; |
29 last_written_.Clone(node); | 34 last_written_.Clone(node); |
30 } | 35 } |
31 | 36 |
32 void WriteJump(BytecodeNode* node, BytecodeLabel* label) override { | 37 void WriteJump(BytecodeNode* node, BytecodeLabel* label) override { |
33 write_count_++; | 38 write_count_++; |
34 last_written_.Clone(node); | 39 last_written_.Clone(node); |
35 } | 40 } |
36 | 41 |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 CHECK_EQ(last_written().operand(i), operands[i]); | 487 CHECK_EQ(last_written().operand(i), operands[i]); |
483 } | 488 } |
484 optimizer()->Write(&third); | 489 optimizer()->Write(&third); |
485 CHECK_EQ(write_count(), 2); | 490 CHECK_EQ(write_count(), 2); |
486 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); | 491 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); |
487 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); | 492 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); |
488 Flush(); | 493 Flush(); |
489 CHECK_EQ(last_written().bytecode(), third.bytecode()); | 494 CHECK_EQ(last_written().bytecode(), third.bytecode()); |
490 } | 495 } |
491 | 496 |
| 497 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaSmiWithBinaryOp) { |
| 498 Bytecode operator_replacement_pairs[][2] = { |
| 499 {Bytecode::kAdd, Bytecode::kAddSmi}, |
| 500 {Bytecode::kSub, Bytecode::kSubSmi}, |
| 501 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, |
| 502 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, |
| 503 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, |
| 504 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; |
| 505 |
| 506 for (auto operator_replacement : operator_replacement_pairs) { |
| 507 uint32_t imm_operand = 17; |
| 508 BytecodeNode first(Bytecode::kLdaSmi, imm_operand); |
| 509 first.source_info().Clone({3, true}); |
| 510 uint32_t reg_operand = Register(0).ToOperand(); |
| 511 BytecodeNode second(operator_replacement[0], reg_operand); |
| 512 optimizer()->Write(&first); |
| 513 optimizer()->Write(&second); |
| 514 Flush(); |
| 515 CHECK_EQ(write_count(), 1); |
| 516 CHECK_EQ(last_written().bytecode(), operator_replacement[1]); |
| 517 CHECK_EQ(last_written().operand_count(), 2); |
| 518 CHECK_EQ(last_written().operand(0), imm_operand); |
| 519 CHECK_EQ(last_written().operand(1), reg_operand); |
| 520 CHECK_EQ(last_written().source_info(), first.source_info()); |
| 521 Reset(); |
| 522 } |
| 523 } |
| 524 |
| 525 TEST_F(BytecodePeepholeOptimizerTest, NotMergingLdaSmiWithBinaryOp) { |
| 526 Bytecode operator_replacement_pairs[][2] = { |
| 527 {Bytecode::kAdd, Bytecode::kAddSmi}, |
| 528 {Bytecode::kSub, Bytecode::kSubSmi}, |
| 529 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, |
| 530 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, |
| 531 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, |
| 532 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; |
| 533 |
| 534 for (auto operator_replacement : operator_replacement_pairs) { |
| 535 uint32_t imm_operand = 17; |
| 536 BytecodeNode first(Bytecode::kLdaSmi, imm_operand); |
| 537 first.source_info().Clone({3, true}); |
| 538 uint32_t reg_operand = Register(0).ToOperand(); |
| 539 BytecodeNode second(operator_replacement[0], reg_operand); |
| 540 second.source_info().Clone({4, true}); |
| 541 optimizer()->Write(&first); |
| 542 optimizer()->Write(&second); |
| 543 CHECK_EQ(last_written(), first); |
| 544 Flush(); |
| 545 CHECK_EQ(last_written(), second); |
| 546 Reset(); |
| 547 } |
| 548 } |
| 549 |
| 550 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaZeroWithBinaryOp) { |
| 551 Bytecode operator_replacement_pairs[][2] = { |
| 552 {Bytecode::kAdd, Bytecode::kAddSmi}, |
| 553 {Bytecode::kSub, Bytecode::kSubSmi}, |
| 554 {Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi}, |
| 555 {Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi}, |
| 556 {Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi}, |
| 557 {Bytecode::kShiftRight, Bytecode::kShiftRightSmi}}; |
| 558 |
| 559 for (auto operator_replacement : operator_replacement_pairs) { |
| 560 BytecodeNode first(Bytecode::kLdaZero); |
| 561 uint32_t reg_operand = Register(0).ToOperand(); |
| 562 BytecodeNode second(operator_replacement[0], reg_operand); |
| 563 optimizer()->Write(&first); |
| 564 optimizer()->Write(&second); |
| 565 Flush(); |
| 566 CHECK_EQ(write_count(), 1); |
| 567 CHECK_EQ(last_written().bytecode(), operator_replacement[1]); |
| 568 CHECK_EQ(last_written().operand_count(), 2); |
| 569 CHECK_EQ(last_written().operand(0), 0); |
| 570 CHECK_EQ(last_written().operand(1), reg_operand); |
| 571 Reset(); |
| 572 } |
| 573 } |
| 574 |
492 } // namespace interpreter | 575 } // namespace interpreter |
493 } // namespace internal | 576 } // namespace internal |
494 } // namespace v8 | 577 } // namespace v8 |
OLD | NEW |