| 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 |