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 |