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 |