| 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/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 case kShift32Imm: // Fall through. | 114 case kShift32Imm: // Fall through. |
| 115 case kShift64Imm: | 115 case kShift64Imm: |
| 116 // Shift operations only observe the bottom 5 or 6 bits of the value. | 116 // Shift operations only observe the bottom 5 or 6 bits of the value. |
| 117 // All possible shifts can be encoded by discarding bits which have no | 117 // All possible shifts can be encoded by discarding bits which have no |
| 118 // effect. | 118 // effect. |
| 119 return true; | 119 return true; |
| 120 } | 120 } |
| 121 return false; | 121 return false; |
| 122 } | 122 } |
| 123 | 123 |
| 124 bool CanBeLoadStoreShiftImmediate(Node* node, MachineRepresentation rep) { |
| 125 // TODO(arm64): Load and Store on 128 bit Q registers is not supported yet. |
| 126 DCHECK_NE(MachineRepresentation::kSimd128, rep); |
| 127 return IsIntegerConstant(node) && |
| 128 (GetIntegerConstantValue(node) == ElementSizeLog2Of(rep)); |
| 129 } |
| 130 |
| 124 private: | 131 private: |
| 125 bool IsLoadStoreImmediate(int64_t value, LSDataSize size) { | 132 bool IsLoadStoreImmediate(int64_t value, LSDataSize size) { |
| 126 return Assembler::IsImmLSScaled(value, size) || | 133 return Assembler::IsImmLSScaled(value, size) || |
| 127 Assembler::IsImmLSUnscaled(value); | 134 Assembler::IsImmLSUnscaled(value); |
| 128 } | 135 } |
| 129 }; | 136 }; |
| 130 | 137 |
| 131 | 138 |
| 132 namespace { | 139 namespace { |
| 133 | 140 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 *right_op = g->UseRegister(mleft_of_right.left().node()); | 226 *right_op = g->UseRegister(mleft_of_right.left().node()); |
| 220 *opcode |= AddressingModeField::encode( | 227 *opcode |= AddressingModeField::encode( |
| 221 (shift == 24) ? kMode_Operand2_R_SXTB : kMode_Operand2_R_SXTH); | 228 (shift == 24) ? kMode_Operand2_R_SXTB : kMode_Operand2_R_SXTH); |
| 222 return true; | 229 return true; |
| 223 } | 230 } |
| 224 } | 231 } |
| 225 } | 232 } |
| 226 return false; | 233 return false; |
| 227 } | 234 } |
| 228 | 235 |
| 236 bool TryMatchLoadStoreShift(Arm64OperandGenerator* g, |
| 237 InstructionSelector* selector, |
| 238 MachineRepresentation rep, Node* node, Node* index, |
| 239 InstructionOperand* index_op, |
| 240 InstructionOperand* shift_immediate_op) { |
| 241 if (!selector->CanCover(node, index)) return false; |
| 242 if (index->InputCount() != 2) return false; |
| 243 Node* left = index->InputAt(0); |
| 244 Node* right = index->InputAt(1); |
| 245 switch (index->opcode()) { |
| 246 case IrOpcode::kWord32Shl: |
| 247 case IrOpcode::kWord64Shl: |
| 248 if (!g->CanBeLoadStoreShiftImmediate(right, rep)) { |
| 249 return false; |
| 250 } |
| 251 *index_op = g->UseRegister(left); |
| 252 *shift_immediate_op = g->UseImmediate(right); |
| 253 return true; |
| 254 default: |
| 255 return false; |
| 256 } |
| 257 } |
| 229 | 258 |
| 230 // Shared routine for multiple binary operations. | 259 // Shared routine for multiple binary operations. |
| 231 template <typename Matcher> | 260 template <typename Matcher> |
| 232 void VisitBinop(InstructionSelector* selector, Node* node, | 261 void VisitBinop(InstructionSelector* selector, Node* node, |
| 233 InstructionCode opcode, ImmediateMode operand_mode, | 262 InstructionCode opcode, ImmediateMode operand_mode, |
| 234 FlagsContinuation* cont) { | 263 FlagsContinuation* cont) { |
| 235 Arm64OperandGenerator g(selector); | 264 Arm64OperandGenerator g(selector); |
| 236 Matcher m(node); | 265 Matcher m(node); |
| 237 InstructionOperand inputs[5]; | 266 InstructionOperand inputs[5]; |
| 238 size_t input_count = 0; | 267 size_t input_count = 0; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 } | 381 } |
| 353 } | 382 } |
| 354 return 0; | 383 return 0; |
| 355 } | 384 } |
| 356 | 385 |
| 357 } // namespace | 386 } // namespace |
| 358 | 387 |
| 359 | 388 |
| 360 void InstructionSelector::VisitLoad(Node* node) { | 389 void InstructionSelector::VisitLoad(Node* node) { |
| 361 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | 390 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 391 MachineRepresentation rep = load_rep.representation(); |
| 362 Arm64OperandGenerator g(this); | 392 Arm64OperandGenerator g(this); |
| 363 Node* base = node->InputAt(0); | 393 Node* base = node->InputAt(0); |
| 364 Node* index = node->InputAt(1); | 394 Node* index = node->InputAt(1); |
| 365 ArchOpcode opcode = kArchNop; | 395 InstructionCode opcode = kArchNop; |
| 366 ImmediateMode immediate_mode = kNoImmediate; | 396 ImmediateMode immediate_mode = kNoImmediate; |
| 367 switch (load_rep.representation()) { | 397 InstructionOperand inputs[3]; |
| 398 size_t input_count = 0; |
| 399 InstructionOperand outputs[1]; |
| 400 switch (rep) { |
| 368 case MachineRepresentation::kFloat32: | 401 case MachineRepresentation::kFloat32: |
| 369 opcode = kArm64LdrS; | 402 opcode = kArm64LdrS; |
| 370 immediate_mode = kLoadStoreImm32; | 403 immediate_mode = kLoadStoreImm32; |
| 371 break; | 404 break; |
| 372 case MachineRepresentation::kFloat64: | 405 case MachineRepresentation::kFloat64: |
| 373 opcode = kArm64LdrD; | 406 opcode = kArm64LdrD; |
| 374 immediate_mode = kLoadStoreImm64; | 407 immediate_mode = kLoadStoreImm64; |
| 375 break; | 408 break; |
| 376 case MachineRepresentation::kBit: // Fall through. | 409 case MachineRepresentation::kBit: // Fall through. |
| 377 case MachineRepresentation::kWord8: | 410 case MachineRepresentation::kWord8: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 389 case MachineRepresentation::kTagged: // Fall through. | 422 case MachineRepresentation::kTagged: // Fall through. |
| 390 case MachineRepresentation::kWord64: | 423 case MachineRepresentation::kWord64: |
| 391 opcode = kArm64Ldr; | 424 opcode = kArm64Ldr; |
| 392 immediate_mode = kLoadStoreImm64; | 425 immediate_mode = kLoadStoreImm64; |
| 393 break; | 426 break; |
| 394 case MachineRepresentation::kSimd128: // Fall through. | 427 case MachineRepresentation::kSimd128: // Fall through. |
| 395 case MachineRepresentation::kNone: | 428 case MachineRepresentation::kNone: |
| 396 UNREACHABLE(); | 429 UNREACHABLE(); |
| 397 return; | 430 return; |
| 398 } | 431 } |
| 432 |
| 433 outputs[0] = g.DefineAsRegister(node); |
| 434 inputs[0] = g.UseRegister(base); |
| 435 |
| 399 if (g.CanBeImmediate(index, immediate_mode)) { | 436 if (g.CanBeImmediate(index, immediate_mode)) { |
| 400 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 437 input_count = 2; |
| 401 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | 438 inputs[1] = g.UseImmediate(index); |
| 439 opcode |= AddressingModeField::encode(kMode_MRI); |
| 440 } else if (TryMatchLoadStoreShift(&g, this, rep, node, index, &inputs[1], |
| 441 &inputs[2])) { |
| 442 input_count = 3; |
| 443 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I); |
| 402 } else { | 444 } else { |
| 403 Emit(opcode | AddressingModeField::encode(kMode_MRR), | 445 input_count = 2; |
| 404 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); | 446 inputs[1] = g.UseRegister(index); |
| 447 opcode |= AddressingModeField::encode(kMode_MRR); |
| 405 } | 448 } |
| 449 |
| 450 Emit(opcode, arraysize(outputs), outputs, input_count, inputs); |
| 406 } | 451 } |
| 407 | 452 |
| 408 | 453 |
| 409 void InstructionSelector::VisitStore(Node* node) { | 454 void InstructionSelector::VisitStore(Node* node) { |
| 410 Arm64OperandGenerator g(this); | 455 Arm64OperandGenerator g(this); |
| 411 Node* base = node->InputAt(0); | 456 Node* base = node->InputAt(0); |
| 412 Node* index = node->InputAt(1); | 457 Node* index = node->InputAt(1); |
| 413 Node* value = node->InputAt(2); | 458 Node* value = node->InputAt(2); |
| 414 | 459 |
| 415 StoreRepresentation store_rep = StoreRepresentationOf(node->op()); | 460 StoreRepresentation store_rep = StoreRepresentationOf(node->op()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 record_write_mode = RecordWriteMode::kValueIsAny; | 494 record_write_mode = RecordWriteMode::kValueIsAny; |
| 450 break; | 495 break; |
| 451 } | 496 } |
| 452 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; | 497 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; |
| 453 size_t const temp_count = arraysize(temps); | 498 size_t const temp_count = arraysize(temps); |
| 454 InstructionCode code = kArchStoreWithWriteBarrier; | 499 InstructionCode code = kArchStoreWithWriteBarrier; |
| 455 code |= AddressingModeField::encode(addressing_mode); | 500 code |= AddressingModeField::encode(addressing_mode); |
| 456 code |= MiscField::encode(static_cast<int>(record_write_mode)); | 501 code |= MiscField::encode(static_cast<int>(record_write_mode)); |
| 457 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); | 502 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); |
| 458 } else { | 503 } else { |
| 459 ArchOpcode opcode = kArchNop; | 504 InstructionOperand inputs[4]; |
| 505 size_t input_count = 0; |
| 506 InstructionCode opcode = kArchNop; |
| 460 ImmediateMode immediate_mode = kNoImmediate; | 507 ImmediateMode immediate_mode = kNoImmediate; |
| 461 switch (rep) { | 508 switch (rep) { |
| 462 case MachineRepresentation::kFloat32: | 509 case MachineRepresentation::kFloat32: |
| 463 opcode = kArm64StrS; | 510 opcode = kArm64StrS; |
| 464 immediate_mode = kLoadStoreImm32; | 511 immediate_mode = kLoadStoreImm32; |
| 465 break; | 512 break; |
| 466 case MachineRepresentation::kFloat64: | 513 case MachineRepresentation::kFloat64: |
| 467 opcode = kArm64StrD; | 514 opcode = kArm64StrD; |
| 468 immediate_mode = kLoadStoreImm64; | 515 immediate_mode = kLoadStoreImm64; |
| 469 break; | 516 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 483 case MachineRepresentation::kTagged: // Fall through. | 530 case MachineRepresentation::kTagged: // Fall through. |
| 484 case MachineRepresentation::kWord64: | 531 case MachineRepresentation::kWord64: |
| 485 opcode = kArm64Str; | 532 opcode = kArm64Str; |
| 486 immediate_mode = kLoadStoreImm64; | 533 immediate_mode = kLoadStoreImm64; |
| 487 break; | 534 break; |
| 488 case MachineRepresentation::kSimd128: // Fall through. | 535 case MachineRepresentation::kSimd128: // Fall through. |
| 489 case MachineRepresentation::kNone: | 536 case MachineRepresentation::kNone: |
| 490 UNREACHABLE(); | 537 UNREACHABLE(); |
| 491 return; | 538 return; |
| 492 } | 539 } |
| 540 |
| 541 inputs[0] = g.UseRegisterOrImmediateZero(value); |
| 542 inputs[1] = g.UseRegister(base); |
| 543 |
| 493 if (g.CanBeImmediate(index, immediate_mode)) { | 544 if (g.CanBeImmediate(index, immediate_mode)) { |
| 494 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 545 input_count = 3; |
| 495 g.UseRegister(base), g.UseImmediate(index), | 546 inputs[2] = g.UseImmediate(index); |
| 496 g.UseRegisterOrImmediateZero(value)); | 547 opcode |= AddressingModeField::encode(kMode_MRI); |
| 548 } else if (TryMatchLoadStoreShift(&g, this, rep, node, index, &inputs[2], |
| 549 &inputs[3])) { |
| 550 input_count = 4; |
| 551 opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I); |
| 497 } else { | 552 } else { |
| 498 Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(), | 553 input_count = 3; |
| 499 g.UseRegister(base), g.UseRegister(index), | 554 inputs[2] = g.UseRegister(index); |
| 500 g.UseRegisterOrImmediateZero(value)); | 555 opcode |= AddressingModeField::encode(kMode_MRR); |
| 501 } | 556 } |
| 557 |
| 558 Emit(opcode, 0, nullptr, input_count, inputs); |
| 502 } | 559 } |
| 503 } | 560 } |
| 504 | 561 |
| 505 | 562 |
| 506 void InstructionSelector::VisitCheckedLoad(Node* node) { | 563 void InstructionSelector::VisitCheckedLoad(Node* node) { |
| 507 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); | 564 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); |
| 508 Arm64OperandGenerator g(this); | 565 Arm64OperandGenerator g(this); |
| 509 Node* const buffer = node->InputAt(0); | 566 Node* const buffer = node->InputAt(0); |
| 510 Node* const offset = node->InputAt(1); | 567 Node* const offset = node->InputAt(1); |
| 511 Node* const length = node->InputAt(2); | 568 Node* const length = node->InputAt(2); |
| (...skipping 1838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2407 MachineOperatorBuilder::kWord32ShiftIsSafe | |
| 2351 MachineOperatorBuilder::kInt32DivIsSafe | | 2408 MachineOperatorBuilder::kInt32DivIsSafe | |
| 2352 MachineOperatorBuilder::kUint32DivIsSafe | | 2409 MachineOperatorBuilder::kUint32DivIsSafe | |
| 2353 MachineOperatorBuilder::kWord32ReverseBits | | 2410 MachineOperatorBuilder::kWord32ReverseBits | |
| 2354 MachineOperatorBuilder::kWord64ReverseBits; | 2411 MachineOperatorBuilder::kWord64ReverseBits; |
| 2355 } | 2412 } |
| 2356 | 2413 |
| 2357 } // namespace compiler | 2414 } // namespace compiler |
| 2358 } // namespace internal | 2415 } // namespace internal |
| 2359 } // namespace v8 | 2416 } // namespace v8 |
| OLD | NEW |