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(0, input_count); | 236 DCHECK_NE(0u, input_count); |
237 DCHECK_NE(0, output_count); | 237 DCHECK_NE(0u, 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(1, width); | 451 DCHECK_LE(1u, width); |
452 DCHECK_LE(width, 32 - lsb); | 452 DCHECK_LE(width, 32u - 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(0, base::bits::CountTrailingZeros32(value)); | 484 DCHECK_EQ(0u, 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 |
553 template <typename TryMatchShift> | 555 template <typename TryMatchShift> |
554 static inline void VisitShift(InstructionSelector* selector, Node* node, | 556 void VisitShift(InstructionSelector* selector, Node* node, |
555 TryMatchShift try_match_shift, | 557 TryMatchShift try_match_shift, FlagsContinuation* cont) { |
556 FlagsContinuation* cont) { | |
557 ArmOperandGenerator g(selector); | 558 ArmOperandGenerator g(selector); |
558 InstructionCode opcode = kArmMov; | 559 InstructionCode opcode = kArmMov; |
559 InstructionOperand* inputs[4]; | 560 InstructionOperand* inputs[4]; |
560 size_t input_count = 2; | 561 size_t input_count = 2; |
561 InstructionOperand* outputs[2]; | 562 InstructionOperand* outputs[2]; |
562 size_t output_count = 0; | 563 size_t output_count = 0; |
563 | 564 |
564 CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1])); | 565 CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1])); |
565 | 566 |
566 if (cont->IsBranch()) { | 567 if (cont->IsBranch()) { |
567 inputs[input_count++] = g.Label(cont->true_block()); | 568 inputs[input_count++] = g.Label(cont->true_block()); |
568 inputs[input_count++] = g.Label(cont->false_block()); | 569 inputs[input_count++] = g.Label(cont->false_block()); |
569 } | 570 } |
570 | 571 |
571 outputs[output_count++] = g.DefineAsRegister(node); | 572 outputs[output_count++] = g.DefineAsRegister(node); |
572 if (cont->IsSet()) { | 573 if (cont->IsSet()) { |
573 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 574 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
574 } | 575 } |
575 | 576 |
576 DCHECK_NE(0, input_count); | 577 DCHECK_NE(0u, input_count); |
577 DCHECK_NE(0, output_count); | 578 DCHECK_NE(0u, output_count); |
578 DCHECK_GE(arraysize(inputs), input_count); | 579 DCHECK_GE(arraysize(inputs), input_count); |
579 DCHECK_GE(arraysize(outputs), output_count); | 580 DCHECK_GE(arraysize(outputs), output_count); |
580 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 581 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
581 | 582 |
582 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 583 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
583 outputs, input_count, inputs); | 584 outputs, input_count, inputs); |
584 if (cont->IsBranch()) instr->MarkAsControl(); | 585 if (cont->IsBranch()) instr->MarkAsControl(); |
585 } | 586 } |
586 | 587 |
587 | 588 |
588 template <typename TryMatchShift> | 589 template <typename TryMatchShift> |
589 static inline void VisitShift(InstructionSelector* selector, Node* node, | 590 void VisitShift(InstructionSelector* selector, Node* node, |
590 TryMatchShift try_match_shift) { | 591 TryMatchShift try_match_shift) { |
591 FlagsContinuation cont; | 592 FlagsContinuation cont; |
592 VisitShift(selector, node, try_match_shift, &cont); | 593 VisitShift(selector, node, try_match_shift, &cont); |
593 } | 594 } |
594 | 595 |
| 596 } // namespace |
| 597 |
595 | 598 |
596 void InstructionSelector::VisitWord32Shl(Node* node) { | 599 void InstructionSelector::VisitWord32Shl(Node* node) { |
597 VisitShift(this, node, TryMatchLSL); | 600 VisitShift(this, node, TryMatchLSL); |
598 } | 601 } |
599 | 602 |
600 | 603 |
601 void InstructionSelector::VisitWord32Shr(Node* node) { | 604 void InstructionSelector::VisitWord32Shr(Node* node) { |
602 ArmOperandGenerator g(this); | 605 ArmOperandGenerator g(this); |
603 Int32BinopMatcher m(node); | 606 Int32BinopMatcher m(node); |
604 if (IsSupported(ARMv7) && m.left().IsWord32And() && | 607 if (IsSupported(ARMv7) && m.left().IsWord32And() && |
605 m.right().IsInRange(0, 31)) { | 608 m.right().IsInRange(0, 31)) { |
606 int32_t lsb = m.right().Value(); | 609 uint32_t lsb = m.right().Value(); |
607 Int32BinopMatcher mleft(m.left().node()); | 610 Int32BinopMatcher mleft(m.left().node()); |
608 if (mleft.right().HasValue()) { | 611 if (mleft.right().HasValue()) { |
609 uint32_t value = (mleft.right().Value() >> lsb) << lsb; | 612 uint32_t value = (mleft.right().Value() >> lsb) << lsb; |
610 uint32_t width = base::bits::CountPopulation32(value); | 613 uint32_t width = base::bits::CountPopulation32(value); |
611 uint32_t msb = base::bits::CountLeadingZeros32(value); | 614 uint32_t msb = base::bits::CountLeadingZeros32(value); |
612 if (msb + width + lsb == 32) { | 615 if (msb + width + lsb == 32) { |
613 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); | 616 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); |
614 return EmitUbfx(this, node, mleft.left().node(), lsb, width); | 617 return EmitUbfx(this, node, mleft.left().node(), lsb, width); |
615 } | 618 } |
616 } | 619 } |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 } | 1119 } |
1117 | 1120 |
1118 if (cont->IsBranch()) { | 1121 if (cont->IsBranch()) { |
1119 inputs[input_count++] = g.Label(cont->true_block()); | 1122 inputs[input_count++] = g.Label(cont->true_block()); |
1120 inputs[input_count++] = g.Label(cont->false_block()); | 1123 inputs[input_count++] = g.Label(cont->false_block()); |
1121 } else { | 1124 } else { |
1122 DCHECK(cont->IsSet()); | 1125 DCHECK(cont->IsSet()); |
1123 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 1126 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
1124 } | 1127 } |
1125 | 1128 |
1126 DCHECK_NE(0, input_count); | 1129 DCHECK_NE(0u, input_count); |
1127 DCHECK_GE(arraysize(inputs), input_count); | 1130 DCHECK_GE(arraysize(inputs), input_count); |
1128 DCHECK_GE(arraysize(outputs), output_count); | 1131 DCHECK_GE(arraysize(outputs), output_count); |
1129 | 1132 |
1130 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 1133 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
1131 outputs, input_count, inputs); | 1134 outputs, input_count, inputs); |
1132 if (cont->IsBranch()) instr->MarkAsControl(); | 1135 if (cont->IsBranch()) instr->MarkAsControl(); |
1133 } | 1136 } |
1134 | 1137 |
1135 | 1138 |
1136 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1139 void VisitWordCompare(InstructionSelector* selector, Node* node, |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 MachineOperatorBuilder::kFloat64Ceil | | 1339 MachineOperatorBuilder::kFloat64Ceil | |
1337 MachineOperatorBuilder::kFloat64RoundTruncate | | 1340 MachineOperatorBuilder::kFloat64RoundTruncate | |
1338 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1341 MachineOperatorBuilder::kFloat64RoundTiesAway; |
1339 } | 1342 } |
1340 return flags; | 1343 return flags; |
1341 } | 1344 } |
1342 | 1345 |
1343 } // namespace compiler | 1346 } // namespace compiler |
1344 } // namespace internal | 1347 } // namespace internal |
1345 } // namespace v8 | 1348 } // namespace v8 |
OLD | NEW |