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) { | |
20 if (CanBeImmediate(node, opcode)) { | |
21 return UseImmediate(node); | |
22 } | |
23 return UseRegister(node); | |
24 } | |
25 | |
26 bool CanBeImmediate(int32_t value) const { | 19 bool CanBeImmediate(int32_t value) const { |
27 return Assembler::ImmediateFitsAddrMode1Instruction(value); | 20 return Assembler::ImmediateFitsAddrMode1Instruction(value); |
28 } | 21 } |
29 | 22 |
30 bool CanBeImmediate(uint32_t value) const { | 23 bool CanBeImmediate(uint32_t value) const { |
31 return CanBeImmediate(bit_cast<int32_t>(value)); | 24 return CanBeImmediate(bit_cast<int32_t>(value)); |
32 } | 25 } |
33 | 26 |
34 bool CanBeImmediate(Node* node, InstructionCode opcode) { | 27 bool CanBeImmediate(Node* node, InstructionCode opcode) { |
35 Int32Matcher m(node); | 28 Int32Matcher m(node); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 case kArmLdr: | 60 case kArmLdr: |
68 case kArmStr: | 61 case kArmStr: |
69 case kArmStoreWriteBarrier: | 62 case kArmStoreWriteBarrier: |
70 return value >= -4095 && value <= 4095; | 63 return value >= -4095 && value <= 4095; |
71 | 64 |
72 case kArmLdrh: | 65 case kArmLdrh: |
73 case kArmLdrsh: | 66 case kArmLdrsh: |
74 case kArmStrh: | 67 case kArmStrh: |
75 return value >= -255 && value <= 255; | 68 return value >= -255 && value <= 255; |
76 | 69 |
77 case kArchCallCodeObject: | 70 default: |
78 case kArchCallJSFunction: | 71 break; |
79 case kArchJmp: | |
80 case kArchNop: | |
81 case kArchRet: | |
82 case kArchStackPointer: | |
83 case kArchTruncateDoubleToI: | |
84 case kArmMul: | |
85 case kArmMla: | |
86 case kArmMls: | |
87 case kArmSmmul: | |
88 case kArmSmmla: | |
89 case kArmUmull: | |
90 case kArmSdiv: | |
91 case kArmUdiv: | |
92 case kArmBfc: | |
93 case kArmUbfx: | |
94 case kArmSxtb: | |
95 case kArmSxth: | |
96 case kArmSxtab: | |
97 case kArmSxtah: | |
98 case kArmUxtb: | |
99 case kArmUxth: | |
100 case kArmUxtab: | |
101 case kArmUxtah: | |
102 case kArmVcmpF64: | |
103 case kArmVaddF64: | |
104 case kArmVsubF64: | |
105 case kArmVmulF64: | |
106 case kArmVmlaF64: | |
107 case kArmVmlsF64: | |
108 case kArmVdivF64: | |
109 case kArmVmodF64: | |
110 case kArmVnegF64: | |
111 case kArmVsqrtF64: | |
112 case kArmVfloorF64: | |
113 case kArmVceilF64: | |
114 case kArmVroundTruncateF64: | |
115 case kArmVroundTiesAwayF64: | |
116 case kArmVcvtF32F64: | |
117 case kArmVcvtF64F32: | |
118 case kArmVcvtF64S32: | |
119 case kArmVcvtF64U32: | |
120 case kArmVcvtS32F64: | |
121 case kArmVcvtU32F64: | |
122 case kArmPush: | |
123 return false; | |
124 } | 72 } |
125 UNREACHABLE(); | |
126 return false; | 73 return false; |
127 } | 74 } |
128 }; | 75 }; |
129 | 76 |
130 | 77 |
131 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 78 namespace { |
132 Node* node) { | 79 |
| 80 void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, |
| 81 Node* node) { |
133 ArmOperandGenerator g(selector); | 82 ArmOperandGenerator g(selector); |
134 selector->Emit(opcode, g.DefineAsRegister(node), | 83 selector->Emit(opcode, g.DefineAsRegister(node), |
135 g.UseRegister(node->InputAt(0))); | 84 g.UseRegister(node->InputAt(0))); |
136 } | 85 } |
137 | 86 |
138 | 87 |
139 static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 88 void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, |
140 Node* node) { | 89 Node* node) { |
141 ArmOperandGenerator g(selector); | 90 ArmOperandGenerator g(selector); |
142 selector->Emit(opcode, g.DefineAsRegister(node), | 91 selector->Emit(opcode, g.DefineAsRegister(node), |
143 g.UseRegister(node->InputAt(0)), | 92 g.UseRegister(node->InputAt(0)), |
144 g.UseRegister(node->InputAt(1))); | 93 g.UseRegister(node->InputAt(1))); |
145 } | 94 } |
146 | 95 |
147 | 96 |
148 static bool TryMatchROR(InstructionSelector* selector, | 97 template <IrOpcode::Value kOpcode, int kImmMin, int kImmMax, |
149 InstructionCode* opcode_return, Node* node, | 98 AddressingMode kImmMode, AddressingMode kRegMode> |
150 InstructionOperand** value_return, | 99 bool TryMatchShift(InstructionSelector* selector, |
151 InstructionOperand** shift_return) { | 100 InstructionCode* opcode_return, Node* node, |
| 101 InstructionOperand** value_return, |
| 102 InstructionOperand** shift_return) { |
152 ArmOperandGenerator g(selector); | 103 ArmOperandGenerator g(selector); |
153 if (node->opcode() != IrOpcode::kWord32Ror) return false; | 104 if (node->opcode() == kOpcode) { |
154 Int32BinopMatcher m(node); | 105 Int32BinopMatcher m(node); |
155 *value_return = g.UseRegister(m.left().node()); | 106 *value_return = g.UseRegister(m.left().node()); |
156 if (m.right().IsInRange(1, 31)) { | 107 if (m.right().IsInRange(kImmMin, kImmMax)) { |
157 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_I); | 108 *opcode_return |= AddressingModeField::encode(kImmMode); |
158 *shift_return = g.UseImmediate(m.right().node()); | 109 *shift_return = g.UseImmediate(m.right().node()); |
159 } else { | 110 } else { |
160 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ROR_R); | 111 *opcode_return |= AddressingModeField::encode(kRegMode); |
161 *shift_return = g.UseRegister(m.right().node()); | 112 *shift_return = g.UseRegister(m.right().node()); |
| 113 } |
| 114 return true; |
162 } | 115 } |
163 return true; | 116 return false; |
164 } | 117 } |
165 | 118 |
166 | 119 |
167 static inline bool TryMatchASR(InstructionSelector* selector, | 120 bool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return, |
168 InstructionCode* opcode_return, Node* node, | 121 Node* node, InstructionOperand** value_return, |
169 InstructionOperand** value_return, | 122 InstructionOperand** shift_return) { |
170 InstructionOperand** shift_return) { | 123 return TryMatchShift<IrOpcode::kWord32Ror, 1, 31, kMode_Operand2_R_ROR_I, |
171 ArmOperandGenerator g(selector); | 124 kMode_Operand2_R_ROR_R>(selector, opcode_return, node, |
172 if (node->opcode() != IrOpcode::kWord32Sar) return false; | 125 value_return, shift_return); |
173 Int32BinopMatcher m(node); | |
174 *value_return = g.UseRegister(m.left().node()); | |
175 if (m.right().IsInRange(1, 32)) { | |
176 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_I); | |
177 *shift_return = g.UseImmediate(m.right().node()); | |
178 } else { | |
179 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_ASR_R); | |
180 *shift_return = g.UseRegister(m.right().node()); | |
181 } | |
182 return true; | |
183 } | 126 } |
184 | 127 |
185 | 128 |
186 static inline bool TryMatchLSL(InstructionSelector* selector, | 129 bool TryMatchASR(InstructionSelector* selector, InstructionCode* opcode_return, |
187 InstructionCode* opcode_return, Node* node, | 130 Node* node, InstructionOperand** value_return, |
188 InstructionOperand** value_return, | 131 InstructionOperand** shift_return) { |
189 InstructionOperand** shift_return) { | 132 return TryMatchShift<IrOpcode::kWord32Sar, 1, 32, kMode_Operand2_R_ASR_I, |
190 ArmOperandGenerator g(selector); | 133 kMode_Operand2_R_ASR_R>(selector, opcode_return, node, |
191 if (node->opcode() != IrOpcode::kWord32Shl) return false; | 134 value_return, shift_return); |
192 Int32BinopMatcher m(node); | |
193 *value_return = g.UseRegister(m.left().node()); | |
194 if (m.right().IsInRange(0, 31)) { | |
195 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_I); | |
196 *shift_return = g.UseImmediate(m.right().node()); | |
197 } else { | |
198 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSL_R); | |
199 *shift_return = g.UseRegister(m.right().node()); | |
200 } | |
201 return true; | |
202 } | 135 } |
203 | 136 |
204 | 137 |
205 static inline bool TryMatchLSR(InstructionSelector* selector, | 138 bool TryMatchLSL(InstructionSelector* selector, InstructionCode* opcode_return, |
206 InstructionCode* opcode_return, Node* node, | 139 Node* node, InstructionOperand** value_return, |
207 InstructionOperand** value_return, | 140 InstructionOperand** shift_return) { |
208 InstructionOperand** shift_return) { | 141 return TryMatchShift<IrOpcode::kWord32Shl, 0, 31, kMode_Operand2_R_LSL_I, |
209 ArmOperandGenerator g(selector); | 142 kMode_Operand2_R_LSL_R>(selector, opcode_return, node, |
210 if (node->opcode() != IrOpcode::kWord32Shr) return false; | 143 value_return, shift_return); |
211 Int32BinopMatcher m(node); | |
212 *value_return = g.UseRegister(m.left().node()); | |
213 if (m.right().IsInRange(1, 32)) { | |
214 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_I); | |
215 *shift_return = g.UseImmediate(m.right().node()); | |
216 } else { | |
217 *opcode_return |= AddressingModeField::encode(kMode_Operand2_R_LSR_R); | |
218 *shift_return = g.UseRegister(m.right().node()); | |
219 } | |
220 return true; | |
221 } | 144 } |
222 | 145 |
223 | 146 |
224 static inline bool TryMatchShift(InstructionSelector* selector, | 147 bool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return, |
225 InstructionCode* opcode_return, Node* node, | 148 Node* node, InstructionOperand** value_return, |
226 InstructionOperand** value_return, | 149 InstructionOperand** shift_return) { |
227 InstructionOperand** shift_return) { | 150 return TryMatchShift<IrOpcode::kWord32Shr, 1, 32, kMode_Operand2_R_LSR_I, |
| 151 kMode_Operand2_R_LSR_R>(selector, opcode_return, node, |
| 152 value_return, shift_return); |
| 153 } |
| 154 |
| 155 |
| 156 bool TryMatchShift(InstructionSelector* selector, |
| 157 InstructionCode* opcode_return, Node* node, |
| 158 InstructionOperand** value_return, |
| 159 InstructionOperand** shift_return) { |
228 return ( | 160 return ( |
229 TryMatchASR(selector, opcode_return, node, value_return, shift_return) || | 161 TryMatchASR(selector, opcode_return, node, value_return, shift_return) || |
230 TryMatchLSL(selector, opcode_return, node, value_return, shift_return) || | 162 TryMatchLSL(selector, opcode_return, node, value_return, shift_return) || |
231 TryMatchLSR(selector, opcode_return, node, value_return, shift_return) || | 163 TryMatchLSR(selector, opcode_return, node, value_return, shift_return) || |
232 TryMatchROR(selector, opcode_return, node, value_return, shift_return)); | 164 TryMatchROR(selector, opcode_return, node, value_return, shift_return)); |
233 } | 165 } |
234 | 166 |
235 | 167 |
236 static inline bool TryMatchImmediateOrShift(InstructionSelector* selector, | 168 bool TryMatchImmediateOrShift(InstructionSelector* selector, |
237 InstructionCode* opcode_return, | 169 InstructionCode* opcode_return, Node* node, |
238 Node* node, | 170 size_t* input_count_return, |
239 size_t* input_count_return, | 171 InstructionOperand** inputs) { |
240 InstructionOperand** inputs) { | |
241 ArmOperandGenerator g(selector); | 172 ArmOperandGenerator g(selector); |
242 if (g.CanBeImmediate(node, *opcode_return)) { | 173 if (g.CanBeImmediate(node, *opcode_return)) { |
243 *opcode_return |= AddressingModeField::encode(kMode_Operand2_I); | 174 *opcode_return |= AddressingModeField::encode(kMode_Operand2_I); |
244 inputs[0] = g.UseImmediate(node); | 175 inputs[0] = g.UseImmediate(node); |
245 *input_count_return = 1; | 176 *input_count_return = 1; |
246 return true; | 177 return true; |
247 } | 178 } |
248 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) { | 179 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) { |
249 *input_count_return = 2; | 180 *input_count_return = 2; |
250 return true; | 181 return true; |
251 } | 182 } |
252 return false; | 183 return false; |
253 } | 184 } |
254 | 185 |
255 | 186 |
256 static void VisitBinop(InstructionSelector* selector, Node* node, | 187 void VisitBinop(InstructionSelector* selector, Node* node, |
257 InstructionCode opcode, InstructionCode reverse_opcode, | 188 InstructionCode opcode, InstructionCode reverse_opcode, |
258 FlagsContinuation* cont) { | 189 FlagsContinuation* cont) { |
259 ArmOperandGenerator g(selector); | 190 ArmOperandGenerator g(selector); |
260 Int32BinopMatcher m(node); | 191 Int32BinopMatcher m(node); |
261 InstructionOperand* inputs[5]; | 192 InstructionOperand* inputs[5]; |
262 size_t input_count = 0; | 193 size_t input_count = 0; |
263 InstructionOperand* outputs[2]; | 194 InstructionOperand* outputs[2]; |
264 size_t output_count = 0; | 195 size_t output_count = 0; |
265 | 196 |
266 if (m.left().node() == m.right().node()) { | 197 if (m.left().node() == m.right().node()) { |
267 // If both inputs refer to the same operand, enforce allocating a register | 198 // If both inputs refer to the same operand, enforce allocating a register |
268 // for both of them to ensure that we don't end up generating code like | 199 // for both of them to ensure that we don't end up generating code like |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 DCHECK_GE(arraysize(inputs), input_count); | 237 DCHECK_GE(arraysize(inputs), input_count); |
307 DCHECK_GE(arraysize(outputs), output_count); | 238 DCHECK_GE(arraysize(outputs), output_count); |
308 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); | 239 DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); |
309 | 240 |
310 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 241 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
311 outputs, input_count, inputs); | 242 outputs, input_count, inputs); |
312 if (cont->IsBranch()) instr->MarkAsControl(); | 243 if (cont->IsBranch()) instr->MarkAsControl(); |
313 } | 244 } |
314 | 245 |
315 | 246 |
316 static void VisitBinop(InstructionSelector* selector, Node* node, | 247 void VisitBinop(InstructionSelector* selector, Node* node, |
317 InstructionCode opcode, InstructionCode reverse_opcode) { | 248 InstructionCode opcode, InstructionCode reverse_opcode) { |
318 FlagsContinuation cont; | 249 FlagsContinuation cont; |
319 VisitBinop(selector, node, opcode, reverse_opcode, &cont); | 250 VisitBinop(selector, node, opcode, reverse_opcode, &cont); |
320 } | 251 } |
321 | 252 |
322 | 253 |
| 254 } // namespace |
| 255 |
| 256 |
323 void InstructionSelector::VisitLoad(Node* node) { | 257 void InstructionSelector::VisitLoad(Node* node) { |
324 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 258 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
325 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 259 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
326 ArmOperandGenerator g(this); | 260 ArmOperandGenerator g(this); |
327 Node* base = node->InputAt(0); | 261 Node* base = node->InputAt(0); |
328 Node* index = node->InputAt(1); | 262 Node* index = node->InputAt(1); |
329 | 263 |
330 ArchOpcode opcode; | 264 ArchOpcode opcode; |
331 switch (rep) { | 265 switch (rep) { |
332 case kRepFloat32: | 266 case kRepFloat32: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 if (g.CanBeImmediate(index, opcode)) { | 343 if (g.CanBeImmediate(index, opcode)) { |
410 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL, | 344 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL, |
411 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 345 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
412 } else { | 346 } else { |
413 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL, | 347 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL, |
414 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); | 348 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); |
415 } | 349 } |
416 } | 350 } |
417 | 351 |
418 | 352 |
419 static inline void EmitBic(InstructionSelector* selector, Node* node, | 353 namespace { |
420 Node* left, Node* right) { | 354 |
| 355 void EmitBic(InstructionSelector* selector, Node* node, Node* left, |
| 356 Node* right) { |
421 ArmOperandGenerator g(selector); | 357 ArmOperandGenerator g(selector); |
422 InstructionCode opcode = kArmBic; | 358 InstructionCode opcode = kArmBic; |
423 InstructionOperand* value_operand; | 359 InstructionOperand* value_operand; |
424 InstructionOperand* shift_operand; | 360 InstructionOperand* shift_operand; |
425 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { | 361 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { |
426 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), | 362 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), |
427 value_operand, shift_operand); | 363 value_operand, shift_operand); |
428 return; | 364 return; |
429 } | 365 } |
430 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), | 366 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), |
431 g.DefineAsRegister(node), g.UseRegister(left), | 367 g.DefineAsRegister(node), g.UseRegister(left), |
432 g.UseRegister(right)); | 368 g.UseRegister(right)); |
433 } | 369 } |
434 | 370 |
| 371 } // namespace |
| 372 |
435 | 373 |
436 void InstructionSelector::VisitWord32And(Node* node) { | 374 void InstructionSelector::VisitWord32And(Node* node) { |
437 ArmOperandGenerator g(this); | 375 ArmOperandGenerator g(this); |
438 Int32BinopMatcher m(node); | 376 Int32BinopMatcher m(node); |
439 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { | 377 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { |
440 Int32BinopMatcher mleft(m.left().node()); | 378 Int32BinopMatcher mleft(m.left().node()); |
441 if (mleft.right().Is(-1)) { | 379 if (mleft.right().Is(-1)) { |
442 EmitBic(this, node, m.right().node(), mleft.left().node()); | 380 EmitBic(this, node, m.right().node(), mleft.left().node()); |
443 return; | 381 return; |
444 } | 382 } |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 MachineOperatorBuilder::kFloat64Ceil | | 1256 MachineOperatorBuilder::kFloat64Ceil | |
1319 MachineOperatorBuilder::kFloat64RoundTruncate | | 1257 MachineOperatorBuilder::kFloat64RoundTruncate | |
1320 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1258 MachineOperatorBuilder::kFloat64RoundTiesAway; |
1321 } | 1259 } |
1322 return flags; | 1260 return flags; |
1323 } | 1261 } |
1324 | 1262 |
1325 } // namespace compiler | 1263 } // namespace compiler |
1326 } // namespace internal | 1264 } // namespace internal |
1327 } // namespace v8 | 1265 } // namespace v8 |
OLD | NEW |