| 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/base/bits.h" | 5 #include "src/base/bits.h" |
| 6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 if (cont->IsBranch()) { | 226 if (cont->IsBranch()) { |
| 227 inputs[input_count++] = g.Label(cont->true_block()); | 227 inputs[input_count++] = g.Label(cont->true_block()); |
| 228 inputs[input_count++] = g.Label(cont->false_block()); | 228 inputs[input_count++] = g.Label(cont->false_block()); |
| 229 } | 229 } |
| 230 | 230 |
| 231 outputs[output_count++] = g.DefineAsRegister(node); | 231 outputs[output_count++] = g.DefineAsRegister(node); |
| 232 if (cont->IsSet()) { | 232 if (cont->IsSet()) { |
| 233 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 233 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 234 } | 234 } |
| 235 | 235 |
| 236 DCHECK_NE(0u, input_count); | 236 DCHECK_NE(0, input_count); |
| 237 DCHECK_NE(0u, output_count); | 237 DCHECK_NE(0, output_count); |
| 238 DCHECK_GE(arraysize(inputs), input_count); | 238 DCHECK_GE(arraysize(inputs), input_count); |
| 239 DCHECK_GE(arraysize(outputs), output_count); | 239 DCHECK_GE(arraysize(outputs), output_count); |
| 240 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 240 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
| 241 | 241 |
| 242 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 242 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
| 243 outputs, input_count, inputs); | 243 outputs, input_count, inputs); |
| 244 if (cont->IsBranch()) instr->MarkAsControl(); | 244 if (cont->IsBranch()) instr->MarkAsControl(); |
| 245 } | 245 } |
| 246 | 246 |
| 247 | 247 |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 return; | 441 return; |
| 442 } | 442 } |
| 443 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), | 443 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), |
| 444 g.DefineAsRegister(node), g.UseRegister(left), | 444 g.DefineAsRegister(node), g.UseRegister(left), |
| 445 g.UseRegister(right)); | 445 g.UseRegister(right)); |
| 446 } | 446 } |
| 447 | 447 |
| 448 | 448 |
| 449 void EmitUbfx(InstructionSelector* selector, Node* node, Node* left, | 449 void EmitUbfx(InstructionSelector* selector, Node* node, Node* left, |
| 450 uint32_t lsb, uint32_t width) { | 450 uint32_t lsb, uint32_t width) { |
| 451 DCHECK_LE(1u, width); | 451 DCHECK_LE(1, width); |
| 452 DCHECK_LE(width, 32u - lsb); | 452 DCHECK_LE(width, 32 - lsb); |
| 453 ArmOperandGenerator g(selector); | 453 ArmOperandGenerator g(selector); |
| 454 selector->Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(left), | 454 selector->Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(left), |
| 455 g.TempImmediate(lsb), g.TempImmediate(width)); | 455 g.TempImmediate(lsb), g.TempImmediate(width)); |
| 456 } | 456 } |
| 457 | 457 |
| 458 } // namespace | 458 } // namespace |
| 459 | 459 |
| 460 | 460 |
| 461 void InstructionSelector::VisitWord32And(Node* node) { | 461 void InstructionSelector::VisitWord32And(Node* node) { |
| 462 ArmOperandGenerator g(this); | 462 ArmOperandGenerator g(this); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 474 EmitBic(this, node, m.left().node(), mright.left().node()); | 474 EmitBic(this, node, m.left().node(), mright.left().node()); |
| 475 return; | 475 return; |
| 476 } | 476 } |
| 477 } | 477 } |
| 478 if (m.right().HasValue()) { | 478 if (m.right().HasValue()) { |
| 479 uint32_t const value = m.right().Value(); | 479 uint32_t const value = m.right().Value(); |
| 480 uint32_t width = base::bits::CountPopulation32(value); | 480 uint32_t width = base::bits::CountPopulation32(value); |
| 481 uint32_t msb = base::bits::CountLeadingZeros32(value); | 481 uint32_t msb = base::bits::CountLeadingZeros32(value); |
| 482 // Try to interpret this AND as UBFX. | 482 // Try to interpret this AND as UBFX. |
| 483 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { | 483 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { |
| 484 DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value)); | 484 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); |
| 485 if (m.left().IsWord32Shr()) { | 485 if (m.left().IsWord32Shr()) { |
| 486 Int32BinopMatcher mleft(m.left().node()); | 486 Int32BinopMatcher mleft(m.left().node()); |
| 487 if (mleft.right().IsInRange(0, 31)) { | 487 if (mleft.right().IsInRange(0, 31)) { |
| 488 // UBFX cannot extract bits past the register size, however since | 488 // UBFX cannot extract bits past the register size, however since |
| 489 // shifting the original value would have introduced some zeros we can | 489 // shifting the original value would have introduced some zeros we can |
| 490 // still use UBFX with a smaller mask and the remaining bits will be | 490 // still use UBFX with a smaller mask and the remaining bits will be |
| 491 // zeros. | 491 // zeros. |
| 492 uint32_t const lsb = mleft.right().Value(); | 492 uint32_t const lsb = mleft.right().Value(); |
| 493 return EmitUbfx(this, node, mleft.left().node(), lsb, | 493 return EmitUbfx(this, node, mleft.left().node(), lsb, |
| 494 std::min(width, 32 - lsb)); | 494 std::min(width, 32 - lsb)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 return; | 543 return; |
| 544 } | 544 } |
| 545 Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), | 545 Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), |
| 546 g.DefineAsRegister(node), g.UseRegister(m.left().node())); | 546 g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
| 547 return; | 547 return; |
| 548 } | 548 } |
| 549 VisitBinop(this, node, kArmEor, kArmEor); | 549 VisitBinop(this, node, kArmEor, kArmEor); |
| 550 } | 550 } |
| 551 | 551 |
| 552 | 552 |
| 553 namespace { | |
| 554 | |
| 555 template <typename TryMatchShift> | 553 template <typename TryMatchShift> |
| 556 void VisitShift(InstructionSelector* selector, Node* node, | 554 static inline void VisitShift(InstructionSelector* selector, Node* node, |
| 557 TryMatchShift try_match_shift, FlagsContinuation* cont) { | 555 TryMatchShift try_match_shift, |
| 556 FlagsContinuation* cont) { |
| 558 ArmOperandGenerator g(selector); | 557 ArmOperandGenerator g(selector); |
| 559 InstructionCode opcode = kArmMov; | 558 InstructionCode opcode = kArmMov; |
| 560 InstructionOperand* inputs[4]; | 559 InstructionOperand* inputs[4]; |
| 561 size_t input_count = 2; | 560 size_t input_count = 2; |
| 562 InstructionOperand* outputs[2]; | 561 InstructionOperand* outputs[2]; |
| 563 size_t output_count = 0; | 562 size_t output_count = 0; |
| 564 | 563 |
| 565 CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1])); | 564 CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1])); |
| 566 | 565 |
| 567 if (cont->IsBranch()) { | 566 if (cont->IsBranch()) { |
| 568 inputs[input_count++] = g.Label(cont->true_block()); | 567 inputs[input_count++] = g.Label(cont->true_block()); |
| 569 inputs[input_count++] = g.Label(cont->false_block()); | 568 inputs[input_count++] = g.Label(cont->false_block()); |
| 570 } | 569 } |
| 571 | 570 |
| 572 outputs[output_count++] = g.DefineAsRegister(node); | 571 outputs[output_count++] = g.DefineAsRegister(node); |
| 573 if (cont->IsSet()) { | 572 if (cont->IsSet()) { |
| 574 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 573 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 575 } | 574 } |
| 576 | 575 |
| 577 DCHECK_NE(0u, input_count); | 576 DCHECK_NE(0, input_count); |
| 578 DCHECK_NE(0u, output_count); | 577 DCHECK_NE(0, output_count); |
| 579 DCHECK_GE(arraysize(inputs), input_count); | 578 DCHECK_GE(arraysize(inputs), input_count); |
| 580 DCHECK_GE(arraysize(outputs), output_count); | 579 DCHECK_GE(arraysize(outputs), output_count); |
| 581 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 580 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
| 582 | 581 |
| 583 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 582 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
| 584 outputs, input_count, inputs); | 583 outputs, input_count, inputs); |
| 585 if (cont->IsBranch()) instr->MarkAsControl(); | 584 if (cont->IsBranch()) instr->MarkAsControl(); |
| 586 } | 585 } |
| 587 | 586 |
| 588 | 587 |
| 589 template <typename TryMatchShift> | 588 template <typename TryMatchShift> |
| 590 void VisitShift(InstructionSelector* selector, Node* node, | 589 static inline void VisitShift(InstructionSelector* selector, Node* node, |
| 591 TryMatchShift try_match_shift) { | 590 TryMatchShift try_match_shift) { |
| 592 FlagsContinuation cont; | 591 FlagsContinuation cont; |
| 593 VisitShift(selector, node, try_match_shift, &cont); | 592 VisitShift(selector, node, try_match_shift, &cont); |
| 594 } | 593 } |
| 595 | 594 |
| 596 } // namespace | |
| 597 | |
| 598 | 595 |
| 599 void InstructionSelector::VisitWord32Shl(Node* node) { | 596 void InstructionSelector::VisitWord32Shl(Node* node) { |
| 600 VisitShift(this, node, TryMatchLSL); | 597 VisitShift(this, node, TryMatchLSL); |
| 601 } | 598 } |
| 602 | 599 |
| 603 | 600 |
| 604 void InstructionSelector::VisitWord32Shr(Node* node) { | 601 void InstructionSelector::VisitWord32Shr(Node* node) { |
| 605 ArmOperandGenerator g(this); | 602 ArmOperandGenerator g(this); |
| 606 Int32BinopMatcher m(node); | 603 Int32BinopMatcher m(node); |
| 607 if (IsSupported(ARMv7) && m.left().IsWord32And() && | 604 if (IsSupported(ARMv7) && m.left().IsWord32And() && |
| 608 m.right().IsInRange(0, 31)) { | 605 m.right().IsInRange(0, 31)) { |
| 609 uint32_t lsb = m.right().Value(); | 606 int32_t lsb = m.right().Value(); |
| 610 Int32BinopMatcher mleft(m.left().node()); | 607 Int32BinopMatcher mleft(m.left().node()); |
| 611 if (mleft.right().HasValue()) { | 608 if (mleft.right().HasValue()) { |
| 612 uint32_t value = (mleft.right().Value() >> lsb) << lsb; | 609 uint32_t value = (mleft.right().Value() >> lsb) << lsb; |
| 613 uint32_t width = base::bits::CountPopulation32(value); | 610 uint32_t width = base::bits::CountPopulation32(value); |
| 614 uint32_t msb = base::bits::CountLeadingZeros32(value); | 611 uint32_t msb = base::bits::CountLeadingZeros32(value); |
| 615 if (msb + width + lsb == 32) { | 612 if (msb + width + lsb == 32) { |
| 616 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); | 613 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); |
| 617 return EmitUbfx(this, node, mleft.left().node(), lsb, width); | 614 return EmitUbfx(this, node, mleft.left().node(), lsb, width); |
| 618 } | 615 } |
| 619 } | 616 } |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 } | 1116 } |
| 1120 | 1117 |
| 1121 if (cont->IsBranch()) { | 1118 if (cont->IsBranch()) { |
| 1122 inputs[input_count++] = g.Label(cont->true_block()); | 1119 inputs[input_count++] = g.Label(cont->true_block()); |
| 1123 inputs[input_count++] = g.Label(cont->false_block()); | 1120 inputs[input_count++] = g.Label(cont->false_block()); |
| 1124 } else { | 1121 } else { |
| 1125 DCHECK(cont->IsSet()); | 1122 DCHECK(cont->IsSet()); |
| 1126 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 1123 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 1127 } | 1124 } |
| 1128 | 1125 |
| 1129 DCHECK_NE(0u, input_count); | 1126 DCHECK_NE(0, input_count); |
| 1130 DCHECK_GE(arraysize(inputs), input_count); | 1127 DCHECK_GE(arraysize(inputs), input_count); |
| 1131 DCHECK_GE(arraysize(outputs), output_count); | 1128 DCHECK_GE(arraysize(outputs), output_count); |
| 1132 | 1129 |
| 1133 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 1130 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
| 1134 outputs, input_count, inputs); | 1131 outputs, input_count, inputs); |
| 1135 if (cont->IsBranch()) instr->MarkAsControl(); | 1132 if (cont->IsBranch()) instr->MarkAsControl(); |
| 1136 } | 1133 } |
| 1137 | 1134 |
| 1138 | 1135 |
| 1139 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1136 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 MachineOperatorBuilder::kFloat64Ceil | | 1336 MachineOperatorBuilder::kFloat64Ceil | |
| 1340 MachineOperatorBuilder::kFloat64RoundTruncate | | 1337 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1341 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1338 MachineOperatorBuilder::kFloat64RoundTiesAway; |
| 1342 } | 1339 } |
| 1343 return flags; | 1340 return flags; |
| 1344 } | 1341 } |
| 1345 | 1342 |
| 1346 } // namespace compiler | 1343 } // namespace compiler |
| 1347 } // namespace internal | 1344 } // namespace internal |
| 1348 } // namespace v8 | 1345 } // namespace v8 |
| OLD | NEW |