| 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 |