| 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 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| 11 namespace compiler { | 11 namespace compiler { |
| 12 | 12 |
| 13 // Adds Arm-specific methods for generating InstructionOperands. | 13 // Adds Arm-specific methods for generating InstructionOperands. |
| 14 class ArmOperandGenerator : public OperandGenerator { | 14 class ArmOperandGenerator : public OperandGenerator { |
| 15 public: | 15 public: |
| 16 explicit ArmOperandGenerator(InstructionSelector* selector) | 16 explicit ArmOperandGenerator(InstructionSelector* selector) |
| 17 : OperandGenerator(selector) {} | 17 : OperandGenerator(selector) {} |
| 18 | 18 |
| 19 InstructionOperand* UseOperand(Node* node, InstructionCode opcode) { | 19 InstructionOperand* UseOperand(Node* node, InstructionCode opcode) { |
| 20 if (CanBeImmediate(node, opcode)) { | 20 if (CanBeImmediate(node, opcode)) { |
| 21 return UseImmediate(node); | 21 return UseImmediate(node); |
| 22 } | 22 } |
| 23 return UseRegister(node); | 23 return UseRegister(node); |
| 24 } | 24 } |
| 25 | 25 |
| 26 bool CanBeImmediate(int32_t value) const { |
| 27 return Assembler::ImmediateFitsAddrMode1Instruction(value); |
| 28 } |
| 29 |
| 30 bool CanBeImmediate(uint32_t value) const { |
| 31 return CanBeImmediate(bit_cast<int32_t>(value)); |
| 32 } |
| 33 |
| 26 bool CanBeImmediate(Node* node, InstructionCode opcode) { | 34 bool CanBeImmediate(Node* node, InstructionCode opcode) { |
| 27 Int32Matcher m(node); | 35 Int32Matcher m(node); |
| 28 if (!m.HasValue()) return false; | 36 if (!m.HasValue()) return false; |
| 29 int32_t value = m.Value(); | 37 int32_t value = m.Value(); |
| 30 switch (ArchOpcodeField::decode(opcode)) { | 38 switch (ArchOpcodeField::decode(opcode)) { |
| 31 case kArmAnd: | 39 case kArmAnd: |
| 32 case kArmMov: | 40 case kArmMov: |
| 33 case kArmMvn: | 41 case kArmMvn: |
| 34 case kArmBic: | 42 case kArmBic: |
| 35 return ImmediateFitsAddrMode1Instruction(value) || | 43 return CanBeImmediate(value) || CanBeImmediate(~value); |
| 36 ImmediateFitsAddrMode1Instruction(~value); | |
| 37 | 44 |
| 38 case kArmAdd: | 45 case kArmAdd: |
| 39 case kArmSub: | 46 case kArmSub: |
| 40 case kArmCmp: | 47 case kArmCmp: |
| 41 case kArmCmn: | 48 case kArmCmn: |
| 42 return ImmediateFitsAddrMode1Instruction(value) || | 49 return CanBeImmediate(value) || CanBeImmediate(-value); |
| 43 ImmediateFitsAddrMode1Instruction(-value); | |
| 44 | 50 |
| 45 case kArmTst: | 51 case kArmTst: |
| 46 case kArmTeq: | 52 case kArmTeq: |
| 47 case kArmOrr: | 53 case kArmOrr: |
| 48 case kArmEor: | 54 case kArmEor: |
| 49 case kArmRsb: | 55 case kArmRsb: |
| 50 return ImmediateFitsAddrMode1Instruction(value); | 56 return CanBeImmediate(value); |
| 51 | 57 |
| 52 case kArmVldrF32: | 58 case kArmVldrF32: |
| 53 case kArmVstrF32: | 59 case kArmVstrF32: |
| 54 case kArmVldrF64: | 60 case kArmVldrF64: |
| 55 case kArmVstrF64: | 61 case kArmVstrF64: |
| 56 return value >= -1020 && value <= 1020 && (value % 4) == 0; | 62 return value >= -1020 && value <= 1020 && (value % 4) == 0; |
| 57 | 63 |
| 58 case kArmLdrb: | 64 case kArmLdrb: |
| 59 case kArmLdrsb: | 65 case kArmLdrsb: |
| 60 case kArmStrb: | 66 case kArmStrb: |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 case kArmVcvtF64S32: | 105 case kArmVcvtF64S32: |
| 100 case kArmVcvtF64U32: | 106 case kArmVcvtF64U32: |
| 101 case kArmVcvtS32F64: | 107 case kArmVcvtS32F64: |
| 102 case kArmVcvtU32F64: | 108 case kArmVcvtU32F64: |
| 103 case kArmPush: | 109 case kArmPush: |
| 104 return false; | 110 return false; |
| 105 } | 111 } |
| 106 UNREACHABLE(); | 112 UNREACHABLE(); |
| 107 return false; | 113 return false; |
| 108 } | 114 } |
| 109 | |
| 110 private: | |
| 111 bool ImmediateFitsAddrMode1Instruction(int32_t imm) const { | |
| 112 return Assembler::ImmediateFitsAddrMode1Instruction(imm); | |
| 113 } | |
| 114 }; | 115 }; |
| 115 | 116 |
| 116 | 117 |
| 117 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 118 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, |
| 118 Node* node) { | 119 Node* node) { |
| 119 ArmOperandGenerator g(selector); | 120 ArmOperandGenerator g(selector); |
| 120 selector->Emit(opcode, g.DefineAsRegister(node), | 121 selector->Emit(opcode, g.DefineAsRegister(node), |
| 121 g.UseRegister(node->InputAt(0)), | 122 g.UseRegister(node->InputAt(0)), |
| 122 g.UseRegister(node->InputAt(1))); | 123 g.UseRegister(node->InputAt(1))); |
| 123 } | 124 } |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 } | 411 } |
| 411 } | 412 } |
| 412 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) { | 413 if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) { |
| 413 Int32BinopMatcher mright(m.right().node()); | 414 Int32BinopMatcher mright(m.right().node()); |
| 414 if (mright.right().Is(-1)) { | 415 if (mright.right().Is(-1)) { |
| 415 EmitBic(this, node, m.left().node(), mright.left().node()); | 416 EmitBic(this, node, m.left().node(), mright.left().node()); |
| 416 return; | 417 return; |
| 417 } | 418 } |
| 418 } | 419 } |
| 419 if (IsSupported(ARMv7) && m.right().HasValue()) { | 420 if (IsSupported(ARMv7) && m.right().HasValue()) { |
| 420 uint32_t value = m.right().Value(); | 421 // Try to interpret this AND as UBFX. |
| 422 uint32_t const value = m.right().Value(); |
| 421 uint32_t width = base::bits::CountPopulation32(value); | 423 uint32_t width = base::bits::CountPopulation32(value); |
| 422 uint32_t msb = base::bits::CountLeadingZeros32(value); | 424 uint32_t msb = base::bits::CountLeadingZeros32(value); |
| 423 if (width != 0 && msb + width == 32) { | 425 if (width != 0 && msb + width == 32) { |
| 424 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); | 426 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); |
| 425 if (m.left().IsWord32Shr()) { | 427 if (m.left().IsWord32Shr()) { |
| 426 Int32BinopMatcher mleft(m.left().node()); | 428 Int32BinopMatcher mleft(m.left().node()); |
| 427 if (mleft.right().IsInRange(0, 31)) { | 429 if (mleft.right().IsInRange(0, 31)) { |
| 428 Emit(kArmUbfx, g.DefineAsRegister(node), | 430 Emit(kArmUbfx, g.DefineAsRegister(node), |
| 429 g.UseRegister(mleft.left().node()), | 431 g.UseRegister(mleft.left().node()), |
| 430 g.UseImmediate(mleft.right().node()), g.TempImmediate(width)); | 432 g.UseImmediate(mleft.right().node()), g.TempImmediate(width)); |
| 431 return; | 433 return; |
| 432 } | 434 } |
| 433 } | 435 } |
| 434 Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 436 Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 435 g.TempImmediate(0), g.TempImmediate(width)); | 437 g.TempImmediate(0), g.TempImmediate(width)); |
| 436 return; | 438 return; |
| 437 } | 439 } |
| 440 |
| 441 // Try to interpret this AND as BIC. |
| 442 if (g.CanBeImmediate(~value)) { |
| 443 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), |
| 444 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 445 g.TempImmediate(~value)); |
| 446 return; |
| 447 } |
| 448 |
| 438 // Try to interpret this AND as BFC. | 449 // Try to interpret this AND as BFC. |
| 439 width = 32 - width; | 450 width = 32 - width; |
| 440 msb = base::bits::CountLeadingZeros32(~value); | 451 msb = base::bits::CountLeadingZeros32(~value); |
| 441 uint32_t lsb = base::bits::CountTrailingZeros32(~value); | 452 uint32_t lsb = base::bits::CountTrailingZeros32(~value); |
| 442 if (msb + width + lsb == 32) { | 453 if (msb + width + lsb == 32) { |
| 443 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), | 454 Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), |
| 444 g.TempImmediate(lsb), g.TempImmediate(width)); | 455 g.TempImmediate(lsb), g.TempImmediate(width)); |
| 445 return; | 456 return; |
| 446 } | 457 } |
| 447 } | 458 } |
| (...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 | 1163 |
| 1153 | 1164 |
| 1154 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { | 1165 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
| 1155 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); | 1166 FlagsContinuation cont(kUnorderedLessThanOrEqual, node); |
| 1156 VisitFloat64Compare(this, node, &cont); | 1167 VisitFloat64Compare(this, node, &cont); |
| 1157 } | 1168 } |
| 1158 | 1169 |
| 1159 } // namespace compiler | 1170 } // namespace compiler |
| 1160 } // namespace internal | 1171 } // namespace internal |
| 1161 } // namespace v8 | 1172 } // namespace v8 |
| OLD | NEW |