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/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler-intrinsics.h" | 7 #include "src/compiler-intrinsics.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 // Shared routine for multiple binary operations. | 243 // Shared routine for multiple binary operations. |
244 static void VisitBinop(InstructionSelector* selector, Node* node, | 244 static void VisitBinop(InstructionSelector* selector, Node* node, |
245 InstructionCode opcode, InstructionCode reverse_opcode) { | 245 InstructionCode opcode, InstructionCode reverse_opcode) { |
246 ArmOperandGenerator g(selector); | 246 ArmOperandGenerator g(selector); |
247 Int32BinopMatcher m(node); | 247 Int32BinopMatcher m(node); |
248 InstructionOperand* inputs[3]; | 248 InstructionOperand* inputs[3]; |
249 size_t input_count = 0; | 249 size_t input_count = 0; |
250 InstructionOperand* outputs[1] = {g.DefineAsRegister(node)}; | |
251 const size_t output_count = ARRAY_SIZE(outputs); | |
titzer
2014/07/31 15:16:34
Why'd you move that code?
Benedikt Meurer
2014/07/31 15:18:19
For consistency; I plan to merge the two VisitBino
| |
250 | 252 |
251 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), | 253 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), |
252 &input_count, &inputs[1])) { | 254 &input_count, &inputs[1])) { |
253 inputs[0] = g.UseRegister(m.left().node()); | 255 inputs[0] = g.UseRegister(m.left().node()); |
254 input_count++; | 256 input_count++; |
255 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, | 257 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, |
256 m.left().node(), &input_count, | 258 m.left().node(), &input_count, |
257 &inputs[1])) { | 259 &inputs[1])) { |
258 inputs[0] = g.UseRegister(m.right().node()); | 260 inputs[0] = g.UseRegister(m.right().node()); |
259 opcode = reverse_opcode; | 261 opcode = reverse_opcode; |
260 input_count++; | 262 input_count++; |
261 } else { | 263 } else { |
262 opcode |= AddressingModeField::encode(kMode_Operand2_R); | 264 opcode |= AddressingModeField::encode(kMode_Operand2_R); |
263 inputs[input_count++] = g.UseRegister(m.left().node()); | 265 inputs[input_count++] = g.UseRegister(m.left().node()); |
264 inputs[input_count++] = g.UseRegister(m.right().node()); | 266 inputs[input_count++] = g.UseRegister(m.right().node()); |
265 } | 267 } |
266 | 268 |
267 ASSERT_NE(0, input_count); | 269 ASSERT_NE(0, input_count); |
268 ASSERT_GE(ARRAY_SIZE(inputs), input_count); | 270 ASSERT_GE(ARRAY_SIZE(inputs), input_count); |
269 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); | 271 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); |
270 | 272 |
271 InstructionOperand* outputs[1] = {g.DefineAsRegister(node)}; | |
272 const size_t output_count = ARRAY_SIZE(outputs); | |
273 selector->Emit(opcode, output_count, outputs, input_count, inputs); | 273 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
274 } | 274 } |
275 | 275 |
276 | |
277 static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node, | |
278 InstructionCode opcode, | |
279 InstructionCode reverse_opcode) { | |
280 ArmOperandGenerator g(selector); | |
281 Int32BinopMatcher m(node); | |
282 InstructionOperand* inputs[3]; | |
283 size_t input_count = 0; | |
284 InstructionOperand* outputs[2]; | |
285 size_t output_count = 0; | |
286 | |
287 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), | |
288 &input_count, &inputs[1])) { | |
289 inputs[0] = g.UseRegister(m.left().node()); | |
290 input_count++; | |
291 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, | |
292 m.left().node(), &input_count, | |
293 &inputs[1])) { | |
294 inputs[0] = g.UseRegister(m.right().node()); | |
295 opcode = reverse_opcode; | |
296 input_count++; | |
297 } else { | |
298 opcode |= AddressingModeField::encode(kMode_Operand2_R); | |
299 inputs[input_count++] = g.UseRegister(m.left().node()); | |
300 inputs[input_count++] = g.UseRegister(m.right().node()); | |
301 } | |
302 | |
303 // Define outputs depending on the projections. | |
304 Node* projections[2]; | |
305 node->CollectProjections(ARRAY_SIZE(projections), projections); | |
306 if (projections[0]) { | |
307 outputs[output_count++] = g.DefineAsRegister(projections[0]); | |
308 } | |
309 if (projections[1]) { | |
310 opcode |= FlagsModeField::encode(kFlags_set); | |
311 opcode |= FlagsConditionField::encode(kOverflow); | |
312 outputs[output_count++] = g.DefineAsRegister(projections[1]); | |
313 } | |
314 | |
315 ASSERT_NE(0, input_count); | |
316 ASSERT_NE(0, output_count); | |
317 ASSERT_GE(ARRAY_SIZE(inputs), input_count); | |
318 ASSERT_GE(ARRAY_SIZE(outputs), output_count); | |
319 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); | |
320 | |
321 selector->Emit(opcode, output_count, outputs, input_count, inputs); | |
322 } | |
323 | |
276 | 324 |
277 void InstructionSelector::VisitLoad(Node* node) { | 325 void InstructionSelector::VisitLoad(Node* node) { |
278 MachineRepresentation rep = OpParameter<MachineRepresentation>(node); | 326 MachineRepresentation rep = OpParameter<MachineRepresentation>(node); |
279 ArmOperandGenerator g(this); | 327 ArmOperandGenerator g(this); |
280 Node* base = node->InputAt(0); | 328 Node* base = node->InputAt(0); |
281 Node* index = node->InputAt(1); | 329 Node* index = node->InputAt(1); |
282 | 330 |
283 InstructionOperand* result = rep == kMachineFloat64 | 331 InstructionOperand* result = rep == kMachineFloat64 |
284 ? g.DefineAsDoubleRegister(node) | 332 ? g.DefineAsDoubleRegister(node) |
285 : g.DefineAsRegister(node); | 333 : g.DefineAsRegister(node); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { | 580 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { |
533 Int32BinopMatcher mright(m.right().node()); | 581 Int32BinopMatcher mright(m.right().node()); |
534 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), | 582 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), |
535 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 583 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
536 return; | 584 return; |
537 } | 585 } |
538 VisitBinop(this, node, kArmAdd, kArmAdd); | 586 VisitBinop(this, node, kArmAdd, kArmAdd); |
539 } | 587 } |
540 | 588 |
541 | 589 |
590 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | |
591 VisitBinopWithOverflow(this, node, kArmAdd, kArmAdd); | |
592 } | |
593 | |
594 | |
542 void InstructionSelector::VisitInt32Sub(Node* node) { | 595 void InstructionSelector::VisitInt32Sub(Node* node) { |
543 ArmOperandGenerator g(this); | 596 ArmOperandGenerator g(this); |
544 Int32BinopMatcher m(node); | 597 Int32BinopMatcher m(node); |
545 if (CpuFeatures::IsSupported(MLS) && m.right().IsInt32Mul() && | 598 if (CpuFeatures::IsSupported(MLS) && m.right().IsInt32Mul() && |
546 CanCover(node, m.right().node())) { | 599 CanCover(node, m.right().node())) { |
547 Int32BinopMatcher mright(m.right().node()); | 600 Int32BinopMatcher mright(m.right().node()); |
548 Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), | 601 Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), |
549 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 602 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
550 return; | 603 return; |
551 } | 604 } |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
894 ASSERT(cont->IsSet()); | 947 ASSERT(cont->IsSet()); |
895 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), | 948 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), |
896 g.UseDoubleRegister(m.left().node()), | 949 g.UseDoubleRegister(m.left().node()), |
897 g.UseDoubleRegister(m.right().node())); | 950 g.UseDoubleRegister(m.right().node())); |
898 } | 951 } |
899 } | 952 } |
900 | 953 |
901 } // namespace compiler | 954 } // namespace compiler |
902 } // namespace internal | 955 } // namespace internal |
903 } // namespace v8 | 956 } // namespace v8 |
OLD | NEW |