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 #include "src/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 if (cont->IsBranch()) { | 208 if (cont->IsBranch()) { |
209 inputs[input_count++] = g.Label(cont->true_block()); | 209 inputs[input_count++] = g.Label(cont->true_block()); |
210 inputs[input_count++] = g.Label(cont->false_block()); | 210 inputs[input_count++] = g.Label(cont->false_block()); |
211 } | 211 } |
212 | 212 |
213 outputs[output_count++] = g.DefineAsRegister(node); | 213 outputs[output_count++] = g.DefineAsRegister(node); |
214 if (cont->IsSet()) { | 214 if (cont->IsSet()) { |
215 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 215 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
216 } | 216 } |
217 | 217 |
218 DCHECK_NE(0, input_count); | 218 DCHECK_NE(0u, input_count); |
219 DCHECK_NE(0, output_count); | 219 DCHECK_NE(0u, output_count); |
220 DCHECK_GE(arraysize(inputs), input_count); | 220 DCHECK_GE(arraysize(inputs), input_count); |
221 DCHECK_GE(arraysize(outputs), output_count); | 221 DCHECK_GE(arraysize(outputs), output_count); |
222 | 222 |
223 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 223 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
224 outputs, input_count, inputs); | 224 outputs, input_count, inputs); |
225 if (cont->IsBranch()) instr->MarkAsControl(); | 225 if (cont->IsBranch()) instr->MarkAsControl(); |
226 } | 226 } |
227 | 227 |
228 | 228 |
229 // Shared routine for multiple binary operations. | 229 // Shared routine for multiple binary operations. |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 void InstructionSelector::VisitWord32And(Node* node) { | 500 void InstructionSelector::VisitWord32And(Node* node) { |
501 Arm64OperandGenerator g(this); | 501 Arm64OperandGenerator g(this); |
502 Int32BinopMatcher m(node); | 502 Int32BinopMatcher m(node); |
503 if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) && | 503 if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) && |
504 m.right().HasValue()) { | 504 m.right().HasValue()) { |
505 uint32_t mask = m.right().Value(); | 505 uint32_t mask = m.right().Value(); |
506 uint32_t mask_width = base::bits::CountPopulation32(mask); | 506 uint32_t mask_width = base::bits::CountPopulation32(mask); |
507 uint32_t mask_msb = base::bits::CountLeadingZeros32(mask); | 507 uint32_t mask_msb = base::bits::CountLeadingZeros32(mask); |
508 if ((mask_width != 0) && (mask_msb + mask_width == 32)) { | 508 if ((mask_width != 0) && (mask_msb + mask_width == 32)) { |
509 // The mask must be contiguous, and occupy the least-significant bits. | 509 // The mask must be contiguous, and occupy the least-significant bits. |
510 DCHECK_EQ(0, base::bits::CountTrailingZeros32(mask)); | 510 DCHECK_EQ(0u, base::bits::CountTrailingZeros32(mask)); |
511 | 511 |
512 // Select Ubfx for And(Shr(x, imm), mask) where the mask is in the least | 512 // Select Ubfx for And(Shr(x, imm), mask) where the mask is in the least |
513 // significant bits. | 513 // significant bits. |
514 Int32BinopMatcher mleft(m.left().node()); | 514 Int32BinopMatcher mleft(m.left().node()); |
515 if (mleft.right().IsInRange(0, 31)) { | 515 if (mleft.right().IsInRange(0, 31)) { |
516 // Ubfx cannot extract bits past the register size, however since | 516 // Ubfx cannot extract bits past the register size, however since |
517 // shifting the original value would have introduced some zeros we can | 517 // shifting the original value would have introduced some zeros we can |
518 // still use ubfx with a smaller mask and the remaining bits will be | 518 // still use ubfx with a smaller mask and the remaining bits will be |
519 // zeros. | 519 // zeros. |
520 uint32_t lsb = mleft.right().Value(); | 520 uint32_t lsb = mleft.right().Value(); |
(...skipping 16 matching lines...) Expand all Loading... |
537 void InstructionSelector::VisitWord64And(Node* node) { | 537 void InstructionSelector::VisitWord64And(Node* node) { |
538 Arm64OperandGenerator g(this); | 538 Arm64OperandGenerator g(this); |
539 Int64BinopMatcher m(node); | 539 Int64BinopMatcher m(node); |
540 if (m.left().IsWord64Shr() && CanCover(node, m.left().node()) && | 540 if (m.left().IsWord64Shr() && CanCover(node, m.left().node()) && |
541 m.right().HasValue()) { | 541 m.right().HasValue()) { |
542 uint64_t mask = m.right().Value(); | 542 uint64_t mask = m.right().Value(); |
543 uint64_t mask_width = base::bits::CountPopulation64(mask); | 543 uint64_t mask_width = base::bits::CountPopulation64(mask); |
544 uint64_t mask_msb = base::bits::CountLeadingZeros64(mask); | 544 uint64_t mask_msb = base::bits::CountLeadingZeros64(mask); |
545 if ((mask_width != 0) && (mask_msb + mask_width == 64)) { | 545 if ((mask_width != 0) && (mask_msb + mask_width == 64)) { |
546 // The mask must be contiguous, and occupy the least-significant bits. | 546 // The mask must be contiguous, and occupy the least-significant bits. |
547 DCHECK_EQ(0, base::bits::CountTrailingZeros64(mask)); | 547 DCHECK_EQ(0u, base::bits::CountTrailingZeros64(mask)); |
548 | 548 |
549 // Select Ubfx for And(Shr(x, imm), mask) where the mask is in the least | 549 // Select Ubfx for And(Shr(x, imm), mask) where the mask is in the least |
550 // significant bits. | 550 // significant bits. |
551 Int64BinopMatcher mleft(m.left().node()); | 551 Int64BinopMatcher mleft(m.left().node()); |
552 if (mleft.right().IsInRange(0, 63)) { | 552 if (mleft.right().IsInRange(0, 63)) { |
553 // Ubfx cannot extract bits past the register size, however since | 553 // Ubfx cannot extract bits past the register size, however since |
554 // shifting the original value would have introduced some zeros we can | 554 // shifting the original value would have introduced some zeros we can |
555 // still use ubfx with a smaller mask and the remaining bits will be | 555 // still use ubfx with a smaller mask and the remaining bits will be |
556 // zeros. | 556 // zeros. |
557 uint64_t lsb = mleft.right().Value(); | 557 uint64_t lsb = mleft.right().Value(); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 return; | 621 return; |
622 } | 622 } |
623 VisitRRO(this, kArm64Lsl, node, kShift64Imm); | 623 VisitRRO(this, kArm64Lsl, node, kShift64Imm); |
624 } | 624 } |
625 | 625 |
626 | 626 |
627 void InstructionSelector::VisitWord32Shr(Node* node) { | 627 void InstructionSelector::VisitWord32Shr(Node* node) { |
628 Arm64OperandGenerator g(this); | 628 Arm64OperandGenerator g(this); |
629 Int32BinopMatcher m(node); | 629 Int32BinopMatcher m(node); |
630 if (m.left().IsWord32And() && m.right().IsInRange(0, 31)) { | 630 if (m.left().IsWord32And() && m.right().IsInRange(0, 31)) { |
631 int32_t lsb = m.right().Value(); | 631 uint32_t lsb = m.right().Value(); |
632 Int32BinopMatcher mleft(m.left().node()); | 632 Int32BinopMatcher mleft(m.left().node()); |
633 if (mleft.right().HasValue()) { | 633 if (mleft.right().HasValue()) { |
634 uint32_t mask = (mleft.right().Value() >> lsb) << lsb; | 634 uint32_t mask = (mleft.right().Value() >> lsb) << lsb; |
635 uint32_t mask_width = base::bits::CountPopulation32(mask); | 635 uint32_t mask_width = base::bits::CountPopulation32(mask); |
636 uint32_t mask_msb = base::bits::CountLeadingZeros32(mask); | 636 uint32_t mask_msb = base::bits::CountLeadingZeros32(mask); |
637 // Select Ubfx for Shr(And(x, mask), imm) where the result of the mask is | 637 // Select Ubfx for Shr(And(x, mask), imm) where the result of the mask is |
638 // shifted into the least-significant bits. | 638 // shifted into the least-significant bits. |
639 if ((mask_msb + mask_width + lsb) == 32) { | 639 if ((mask_msb + mask_width + lsb) == 32) { |
640 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(mask)); | 640 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(mask)); |
641 Emit(kArm64Ubfx32, g.DefineAsRegister(node), | 641 Emit(kArm64Ubfx32, g.DefineAsRegister(node), |
642 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), | 642 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), |
643 g.TempImmediate(mask_width)); | 643 g.TempImmediate(mask_width)); |
644 return; | 644 return; |
645 } | 645 } |
646 } | 646 } |
647 } | 647 } |
648 VisitRRO(this, kArm64Lsr32, node, kShift32Imm); | 648 VisitRRO(this, kArm64Lsr32, node, kShift32Imm); |
649 } | 649 } |
650 | 650 |
651 | 651 |
652 void InstructionSelector::VisitWord64Shr(Node* node) { | 652 void InstructionSelector::VisitWord64Shr(Node* node) { |
653 Arm64OperandGenerator g(this); | 653 Arm64OperandGenerator g(this); |
654 Int64BinopMatcher m(node); | 654 Int64BinopMatcher m(node); |
655 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { | 655 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { |
656 int64_t lsb = m.right().Value(); | 656 uint64_t lsb = m.right().Value(); |
657 Int64BinopMatcher mleft(m.left().node()); | 657 Int64BinopMatcher mleft(m.left().node()); |
658 if (mleft.right().HasValue()) { | 658 if (mleft.right().HasValue()) { |
659 // Select Ubfx for Shr(And(x, mask), imm) where the result of the mask is | 659 // Select Ubfx for Shr(And(x, mask), imm) where the result of the mask is |
660 // shifted into the least-significant bits. | 660 // shifted into the least-significant bits. |
661 uint64_t mask = (mleft.right().Value() >> lsb) << lsb; | 661 uint64_t mask = (mleft.right().Value() >> lsb) << lsb; |
662 uint64_t mask_width = base::bits::CountPopulation64(mask); | 662 uint64_t mask_width = base::bits::CountPopulation64(mask); |
663 uint64_t mask_msb = base::bits::CountLeadingZeros64(mask); | 663 uint64_t mask_msb = base::bits::CountLeadingZeros64(mask); |
664 if ((mask_msb + mask_width + lsb) == 64) { | 664 if ((mask_msb + mask_width + lsb) == 64) { |
665 DCHECK_EQ(lsb, base::bits::CountTrailingZeros64(mask)); | 665 DCHECK_EQ(lsb, base::bits::CountTrailingZeros64(mask)); |
666 Emit(kArm64Ubfx, g.DefineAsRegister(node), | 666 Emit(kArm64Ubfx, g.DefineAsRegister(node), |
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1527 MachineOperatorBuilder::kFloat64RoundTruncate | | 1527 MachineOperatorBuilder::kFloat64RoundTruncate | |
1528 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1528 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1529 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1529 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1530 MachineOperatorBuilder::kInt32DivIsSafe | | 1530 MachineOperatorBuilder::kInt32DivIsSafe | |
1531 MachineOperatorBuilder::kUint32DivIsSafe; | 1531 MachineOperatorBuilder::kUint32DivIsSafe; |
1532 } | 1532 } |
1533 | 1533 |
1534 } // namespace compiler | 1534 } // namespace compiler |
1535 } // namespace internal | 1535 } // namespace internal |
1536 } // namespace v8 | 1536 } // namespace v8 |
OLD | NEW |