Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/compiler/arm64/instruction-selector-arm64.cc

Issue 1972103002: [turbofan] ARM64: Support shifted indexes in loads and stores (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/arm64/code-generator-arm64.cc ('k') | test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698