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 | 7 |
8 namespace v8 { | 8 namespace v8 { |
9 namespace internal { | 9 namespace internal { |
10 namespace compiler { | 10 namespace compiler { |
(...skipping 26 matching lines...) Expand all Loading... |
37 } | 37 } |
38 | 38 |
39 bool CanBeImmediate(Node* node, ImmediateMode mode) { | 39 bool CanBeImmediate(Node* node, ImmediateMode mode) { |
40 int64_t value; | 40 int64_t value; |
41 if (node->opcode() == IrOpcode::kInt32Constant) | 41 if (node->opcode() == IrOpcode::kInt32Constant) |
42 value = OpParameter<int32_t>(node); | 42 value = OpParameter<int32_t>(node); |
43 else if (node->opcode() == IrOpcode::kInt64Constant) | 43 else if (node->opcode() == IrOpcode::kInt64Constant) |
44 value = OpParameter<int64_t>(node); | 44 value = OpParameter<int64_t>(node); |
45 else | 45 else |
46 return false; | 46 return false; |
| 47 return CanBeImmediate(value, mode); |
| 48 } |
| 49 |
| 50 bool CanBeImmediate(int64_t value, ImmediateMode mode) { |
47 unsigned ignored; | 51 unsigned ignored; |
48 switch (mode) { | 52 switch (mode) { |
49 case kLogical32Imm: | 53 case kLogical32Imm: |
50 // TODO(dcarney): some unencodable values can be handled by | 54 // TODO(dcarney): some unencodable values can be handled by |
51 // switching instructions. | 55 // switching instructions. |
52 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 32, | 56 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 32, |
53 &ignored, &ignored, &ignored); | 57 &ignored, &ignored, &ignored); |
54 case kLogical64Imm: | 58 case kLogical64Imm: |
55 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 64, | 59 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 64, |
56 &ignored, &ignored, &ignored); | 60 &ignored, &ignored, &ignored); |
57 case kArithmeticImm: | 61 case kArithmeticImm: |
58 // TODO(dcarney): -values can be handled by instruction swapping | |
59 return Assembler::IsImmAddSub(value); | 62 return Assembler::IsImmAddSub(value); |
60 case kShift32Imm: | 63 case kShift32Imm: |
61 return 0 <= value && value < 32; | 64 return 0 <= value && value < 32; |
62 case kShift64Imm: | 65 case kShift64Imm: |
63 return 0 <= value && value < 64; | 66 return 0 <= value && value < 64; |
64 case kLoadStoreImm8: | 67 case kLoadStoreImm8: |
65 return IsLoadStoreImmediate(value, LSByte); | 68 return IsLoadStoreImmediate(value, LSByte); |
66 case kLoadStoreImm16: | 69 case kLoadStoreImm16: |
67 return IsLoadStoreImmediate(value, LSHalfword); | 70 return IsLoadStoreImmediate(value, LSHalfword); |
68 case kLoadStoreImm32: | 71 case kLoadStoreImm32: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 | 151 |
149 // Shared routine for multiple binary operations. | 152 // Shared routine for multiple binary operations. |
150 template <typename Matcher> | 153 template <typename Matcher> |
151 static void VisitBinop(InstructionSelector* selector, Node* node, | 154 static void VisitBinop(InstructionSelector* selector, Node* node, |
152 ArchOpcode opcode, ImmediateMode operand_mode) { | 155 ArchOpcode opcode, ImmediateMode operand_mode) { |
153 FlagsContinuation cont; | 156 FlagsContinuation cont; |
154 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); | 157 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); |
155 } | 158 } |
156 | 159 |
157 | 160 |
| 161 template <typename Matcher> |
| 162 static void VisitAddSub(InstructionSelector* selector, Node* node, |
| 163 ArchOpcode opcode, ArchOpcode negate_opcode) { |
| 164 Arm64OperandGenerator g(selector); |
| 165 Matcher m(node); |
| 166 if (m.right().HasValue() && (m.right().Value() < 0) && |
| 167 g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { |
| 168 selector->Emit(negate_opcode, g.DefineAsRegister(node), |
| 169 g.UseRegister(m.left().node()), |
| 170 g.TempImmediate(-m.right().Value())); |
| 171 } else { |
| 172 VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); |
| 173 } |
| 174 } |
| 175 |
| 176 |
158 void InstructionSelector::VisitLoad(Node* node) { | 177 void InstructionSelector::VisitLoad(Node* node) { |
159 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 178 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
160 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 179 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
161 Arm64OperandGenerator g(this); | 180 Arm64OperandGenerator g(this); |
162 Node* base = node->InputAt(0); | 181 Node* base = node->InputAt(0); |
163 Node* index = node->InputAt(1); | 182 Node* index = node->InputAt(1); |
164 ArchOpcode opcode; | 183 ArchOpcode opcode; |
165 ImmediateMode immediate_mode = kNoImmediate; | 184 ImmediateMode immediate_mode = kNoImmediate; |
166 switch (rep) { | 185 switch (rep) { |
167 case kRepFloat32: | 186 case kRepFloat32: |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 return; | 454 return; |
436 } | 455 } |
437 // Select Madd(x, y, z) for Add(x, Mul(x, y)). | 456 // Select Madd(x, y, z) for Add(x, Mul(x, y)). |
438 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { | 457 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { |
439 Int32BinopMatcher mright(m.right().node()); | 458 Int32BinopMatcher mright(m.right().node()); |
440 Emit(kArm64Madd32, g.DefineAsRegister(node), | 459 Emit(kArm64Madd32, g.DefineAsRegister(node), |
441 g.UseRegister(mright.left().node()), | 460 g.UseRegister(mright.left().node()), |
442 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 461 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
443 return; | 462 return; |
444 } | 463 } |
445 VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm); | 464 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Add32, kArm64Sub32); |
446 } | 465 } |
447 | 466 |
448 | 467 |
449 void InstructionSelector::VisitInt64Add(Node* node) { | 468 void InstructionSelector::VisitInt64Add(Node* node) { |
450 Arm64OperandGenerator g(this); | 469 Arm64OperandGenerator g(this); |
451 Int64BinopMatcher m(node); | 470 Int64BinopMatcher m(node); |
452 // Select Madd(x, y, z) for Add(Mul(x, y), z). | 471 // Select Madd(x, y, z) for Add(Mul(x, y), z). |
453 if (m.left().IsInt64Mul() && CanCover(node, m.left().node())) { | 472 if (m.left().IsInt64Mul() && CanCover(node, m.left().node())) { |
454 Int64BinopMatcher mleft(m.left().node()); | 473 Int64BinopMatcher mleft(m.left().node()); |
455 Emit(kArm64Madd, g.DefineAsRegister(node), | 474 Emit(kArm64Madd, g.DefineAsRegister(node), |
456 g.UseRegister(mleft.left().node()), | 475 g.UseRegister(mleft.left().node()), |
457 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node())); | 476 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node())); |
458 return; | 477 return; |
459 } | 478 } |
460 // Select Madd(x, y, z) for Add(x, Mul(x, y)). | 479 // Select Madd(x, y, z) for Add(x, Mul(x, y)). |
461 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { | 480 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { |
462 Int64BinopMatcher mright(m.right().node()); | 481 Int64BinopMatcher mright(m.right().node()); |
463 Emit(kArm64Madd, g.DefineAsRegister(node), | 482 Emit(kArm64Madd, g.DefineAsRegister(node), |
464 g.UseRegister(mright.left().node()), | 483 g.UseRegister(mright.left().node()), |
465 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 484 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
466 return; | 485 return; |
467 } | 486 } |
468 VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm); | 487 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Add, kArm64Sub); |
469 } | 488 } |
470 | 489 |
471 | 490 |
472 void InstructionSelector::VisitInt32Sub(Node* node) { | 491 void InstructionSelector::VisitInt32Sub(Node* node) { |
473 Arm64OperandGenerator g(this); | 492 Arm64OperandGenerator g(this); |
474 Int32BinopMatcher m(node); | 493 Int32BinopMatcher m(node); |
475 | 494 |
476 // Select Msub(a, x, y) for Sub(a, Mul(x, y)). | 495 // Select Msub(a, x, y) for Sub(a, Mul(x, y)). |
477 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { | 496 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { |
478 Int32BinopMatcher mright(m.right().node()); | 497 Int32BinopMatcher mright(m.right().node()); |
479 Emit(kArm64Msub32, g.DefineAsRegister(node), | 498 Emit(kArm64Msub32, g.DefineAsRegister(node), |
480 g.UseRegister(mright.left().node()), | 499 g.UseRegister(mright.left().node()), |
481 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 500 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
482 return; | 501 return; |
483 } | 502 } |
484 | 503 |
485 if (m.left().Is(0)) { | 504 if (m.left().Is(0)) { |
486 Emit(kArm64Neg32, g.DefineAsRegister(node), | 505 Emit(kArm64Neg32, g.DefineAsRegister(node), |
487 g.UseRegister(m.right().node())); | 506 g.UseRegister(m.right().node())); |
488 } else { | 507 } else { |
489 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm); | 508 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Sub32, kArm64Add32); |
490 } | 509 } |
491 } | 510 } |
492 | 511 |
493 | 512 |
494 void InstructionSelector::VisitInt64Sub(Node* node) { | 513 void InstructionSelector::VisitInt64Sub(Node* node) { |
495 Arm64OperandGenerator g(this); | 514 Arm64OperandGenerator g(this); |
496 Int64BinopMatcher m(node); | 515 Int64BinopMatcher m(node); |
497 | 516 |
498 // Select Msub(a, x, y) for Sub(a, Mul(x, y)). | 517 // Select Msub(a, x, y) for Sub(a, Mul(x, y)). |
499 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { | 518 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { |
500 Int64BinopMatcher mright(m.right().node()); | 519 Int64BinopMatcher mright(m.right().node()); |
501 Emit(kArm64Msub, g.DefineAsRegister(node), | 520 Emit(kArm64Msub, g.DefineAsRegister(node), |
502 g.UseRegister(mright.left().node()), | 521 g.UseRegister(mright.left().node()), |
503 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 522 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); |
504 return; | 523 return; |
505 } | 524 } |
506 | 525 |
507 if (m.left().Is(0)) { | 526 if (m.left().Is(0)) { |
508 Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); | 527 Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); |
509 } else { | 528 } else { |
510 VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, kArithmeticImm); | 529 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); |
511 } | 530 } |
512 } | 531 } |
513 | 532 |
514 | 533 |
515 void InstructionSelector::VisitInt32Mul(Node* node) { | 534 void InstructionSelector::VisitInt32Mul(Node* node) { |
516 Arm64OperandGenerator g(this); | 535 Arm64OperandGenerator g(this); |
517 Int32BinopMatcher m(node); | 536 Int32BinopMatcher m(node); |
518 | 537 |
519 if (m.left().IsInt32Sub() && CanCover(node, m.left().node())) { | 538 if (m.left().IsInt32Sub() && CanCover(node, m.left().node())) { |
520 Int32BinopMatcher mleft(m.left().node()); | 539 Int32BinopMatcher mleft(m.left().node()); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 call_instr->MarkAsCall(); | 904 call_instr->MarkAsCall(); |
886 if (deoptimization != NULL) { | 905 if (deoptimization != NULL) { |
887 DCHECK(continuation != NULL); | 906 DCHECK(continuation != NULL); |
888 call_instr->MarkAsControl(); | 907 call_instr->MarkAsControl(); |
889 } | 908 } |
890 } | 909 } |
891 | 910 |
892 } // namespace compiler | 911 } // namespace compiler |
893 } // namespace internal | 912 } // namespace internal |
894 } // namespace v8 | 913 } // namespace v8 |
OLD | NEW |