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 |