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

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

Issue 2182493003: ARM: Implement UnaligedLoad and UnaligedStore turbofan operators. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 4 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
« no previous file with comments | « src/compiler/arm/instruction-scheduler-arm.cc ('k') | src/compiler/machine-operator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/base/adapters.h" 5 #include "src/base/adapters.h"
6 #include "src/base/bits.h" 6 #include "src/base/bits.h"
7 #include "src/compiler/instruction-selector-impl.h" 7 #include "src/compiler/instruction-selector-impl.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 10
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 selector->Emit(kArmMls, result_operand, div_operand, right_operand, 331 selector->Emit(kArmMls, result_operand, div_operand, right_operand,
332 left_operand); 332 left_operand);
333 } else { 333 } else {
334 InstructionOperand mul_operand = g.TempRegister(); 334 InstructionOperand mul_operand = g.TempRegister();
335 selector->Emit(kArmMul, mul_operand, div_operand, right_operand); 335 selector->Emit(kArmMul, mul_operand, div_operand, right_operand);
336 selector->Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R), 336 selector->Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R),
337 result_operand, left_operand, mul_operand); 337 result_operand, left_operand, mul_operand);
338 } 338 }
339 } 339 }
340 340
341 void EmitLoad(InstructionSelector* selector, InstructionCode opcode,
342 InstructionOperand* output, Node* base, Node* index) {
343 ArmOperandGenerator g(selector);
344 InstructionOperand inputs[3];
345 size_t input_count = 2;
346
347 inputs[0] = g.UseRegister(base);
348 if (g.CanBeImmediate(index, opcode)) {
349 inputs[1] = g.UseImmediate(index);
350 opcode |= AddressingModeField::encode(kMode_Offset_RI);
351 } else if ((opcode == kArmLdr) &&
352 TryMatchLSLImmediate(selector, &opcode, index, &inputs[1],
353 &inputs[2])) {
354 input_count = 3;
355 } else {
356 inputs[1] = g.UseRegister(index);
357 opcode |= AddressingModeField::encode(kMode_Offset_RR);
358 }
359 selector->Emit(opcode, 1, output, input_count, inputs);
360 }
361
362 void EmitStore(InstructionSelector* selector, InstructionCode opcode,
363 size_t input_count, InstructionOperand* inputs,
364 Node* index) {
365 ArmOperandGenerator g(selector);
366
367 if (g.CanBeImmediate(index, opcode)) {
368 inputs[input_count++] = g.UseImmediate(index);
369 opcode |= AddressingModeField::encode(kMode_Offset_RI);
370 } else if ((opcode == kArmStr) &&
371 TryMatchLSLImmediate(selector, &opcode, index, &inputs[2],
372 &inputs[3])) {
373 input_count = 4;
374 } else {
375 inputs[input_count++] = g.UseRegister(index);
376 opcode |= AddressingModeField::encode(kMode_Offset_RR);
377 }
378 selector->Emit(opcode, 0, nullptr, input_count, inputs);
379 }
380
341 } // namespace 381 } // namespace
342 382
343 383
344 void InstructionSelector::VisitLoad(Node* node) { 384 void InstructionSelector::VisitLoad(Node* node) {
345 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); 385 LoadRepresentation load_rep = LoadRepresentationOf(node->op());
346 ArmOperandGenerator g(this); 386 ArmOperandGenerator g(this);
347 Node* base = node->InputAt(0); 387 Node* base = node->InputAt(0);
348 Node* index = node->InputAt(1); 388 Node* index = node->InputAt(1);
349 InstructionOperand inputs[3];
350 size_t input_count = 0;
351 InstructionOperand outputs[1];
352 389
353 InstructionCode opcode = kArchNop; 390 InstructionCode opcode = kArchNop;
354 switch (load_rep.representation()) { 391 switch (load_rep.representation()) {
355 case MachineRepresentation::kFloat32: 392 case MachineRepresentation::kFloat32:
356 opcode = kArmVldrF32; 393 opcode = kArmVldrF32;
357 break; 394 break;
358 case MachineRepresentation::kFloat64: 395 case MachineRepresentation::kFloat64:
359 opcode = kArmVldrF64; 396 opcode = kArmVldrF64;
360 break; 397 break;
361 case MachineRepresentation::kBit: // Fall through. 398 case MachineRepresentation::kBit: // Fall through.
362 case MachineRepresentation::kWord8: 399 case MachineRepresentation::kWord8:
363 opcode = load_rep.IsUnsigned() ? kArmLdrb : kArmLdrsb; 400 opcode = load_rep.IsUnsigned() ? kArmLdrb : kArmLdrsb;
364 break; 401 break;
365 case MachineRepresentation::kWord16: 402 case MachineRepresentation::kWord16:
366 opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh; 403 opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh;
367 break; 404 break;
368 case MachineRepresentation::kTagged: // Fall through. 405 case MachineRepresentation::kTagged: // Fall through.
369 case MachineRepresentation::kWord32: 406 case MachineRepresentation::kWord32:
370 opcode = kArmLdr; 407 opcode = kArmLdr;
371 break; 408 break;
372 case MachineRepresentation::kWord64: // Fall through. 409 case MachineRepresentation::kWord64: // Fall through.
373 case MachineRepresentation::kSimd128: // Fall through. 410 case MachineRepresentation::kSimd128: // Fall through.
374 case MachineRepresentation::kNone: 411 case MachineRepresentation::kNone:
375 UNREACHABLE(); 412 UNREACHABLE();
376 return; 413 return;
377 } 414 }
378 415
379 outputs[0] = g.DefineAsRegister(node); 416 InstructionOperand output = g.DefineAsRegister(node);
380 inputs[0] = g.UseRegister(base); 417 EmitLoad(this, opcode, &output, base, index);
381
382 if (g.CanBeImmediate(index, opcode)) {
383 input_count = 2;
384 inputs[1] = g.UseImmediate(index);
385 opcode |= AddressingModeField::encode(kMode_Offset_RI);
386 } else if ((opcode == kArmLdr) &&
387 TryMatchLSLImmediate(this, &opcode, index, &inputs[1],
388 &inputs[2])) {
389 input_count = 3;
390 } else {
391 input_count = 2;
392 inputs[1] = g.UseRegister(index);
393 opcode |= AddressingModeField::encode(kMode_Offset_RR);
394 }
395
396 Emit(opcode, arraysize(outputs), outputs, input_count, inputs);
397 } 418 }
398 419
399 420
400 void InstructionSelector::VisitStore(Node* node) { 421 void InstructionSelector::VisitStore(Node* node) {
401 ArmOperandGenerator g(this); 422 ArmOperandGenerator g(this);
402 Node* base = node->InputAt(0); 423 Node* base = node->InputAt(0);
403 Node* index = node->InputAt(1); 424 Node* index = node->InputAt(1);
404 Node* value = node->InputAt(2); 425 Node* value = node->InputAt(2);
405 426
406 StoreRepresentation store_rep = StoreRepresentationOf(node->op()); 427 StoreRepresentation store_rep = StoreRepresentationOf(node->op());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 record_write_mode = RecordWriteMode::kValueIsAny; 459 record_write_mode = RecordWriteMode::kValueIsAny;
439 break; 460 break;
440 } 461 }
441 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; 462 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
442 size_t const temp_count = arraysize(temps); 463 size_t const temp_count = arraysize(temps);
443 InstructionCode code = kArchStoreWithWriteBarrier; 464 InstructionCode code = kArchStoreWithWriteBarrier;
444 code |= AddressingModeField::encode(addressing_mode); 465 code |= AddressingModeField::encode(addressing_mode);
445 code |= MiscField::encode(static_cast<int>(record_write_mode)); 466 code |= MiscField::encode(static_cast<int>(record_write_mode));
446 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); 467 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
447 } else { 468 } else {
448 InstructionOperand inputs[4];
449 size_t input_count = 0;
450
451 InstructionCode opcode = kArchNop; 469 InstructionCode opcode = kArchNop;
452 switch (rep) { 470 switch (rep) {
453 case MachineRepresentation::kFloat32: 471 case MachineRepresentation::kFloat32:
454 opcode = kArmVstrF32; 472 opcode = kArmVstrF32;
455 break; 473 break;
456 case MachineRepresentation::kFloat64: 474 case MachineRepresentation::kFloat64:
457 opcode = kArmVstrF64; 475 opcode = kArmVstrF64;
458 break; 476 break;
459 case MachineRepresentation::kBit: // Fall through. 477 case MachineRepresentation::kBit: // Fall through.
460 case MachineRepresentation::kWord8: 478 case MachineRepresentation::kWord8:
461 opcode = kArmStrb; 479 opcode = kArmStrb;
462 break; 480 break;
463 case MachineRepresentation::kWord16: 481 case MachineRepresentation::kWord16:
464 opcode = kArmStrh; 482 opcode = kArmStrh;
465 break; 483 break;
466 case MachineRepresentation::kTagged: // Fall through. 484 case MachineRepresentation::kTagged: // Fall through.
467 case MachineRepresentation::kWord32: 485 case MachineRepresentation::kWord32:
468 opcode = kArmStr; 486 opcode = kArmStr;
469 break; 487 break;
470 case MachineRepresentation::kWord64: // Fall through. 488 case MachineRepresentation::kWord64: // Fall through.
471 case MachineRepresentation::kSimd128: // Fall through. 489 case MachineRepresentation::kSimd128: // Fall through.
472 case MachineRepresentation::kNone: 490 case MachineRepresentation::kNone:
473 UNREACHABLE(); 491 UNREACHABLE();
474 return; 492 return;
475 } 493 }
476 494
477 inputs[0] = g.UseRegister(value); 495 InstructionOperand inputs[4];
478 inputs[1] = g.UseRegister(base); 496 size_t input_count = 0;
479 497 inputs[input_count++] = g.UseRegister(value);
480 if (g.CanBeImmediate(index, opcode)) { 498 inputs[input_count++] = g.UseRegister(base);
481 input_count = 3; 499 EmitStore(this, opcode, input_count, inputs, index);
482 inputs[2] = g.UseImmediate(index);
483 opcode |= AddressingModeField::encode(kMode_Offset_RI);
484 } else if ((opcode == kArmStr) &&
485 TryMatchLSLImmediate(this, &opcode, index, &inputs[2],
486 &inputs[3])) {
487 input_count = 4;
488 } else {
489 input_count = 3;
490 inputs[2] = g.UseRegister(index);
491 opcode |= AddressingModeField::encode(kMode_Offset_RR);
492 }
493 Emit(opcode, 0, nullptr, input_count, inputs);
494 } 500 }
495 } 501 }
496 502
497 // Architecture supports unaligned access, therefore VisitLoad is used instead 503 void InstructionSelector::VisitUnalignedLoad(Node* node) {
498 void InstructionSelector::VisitUnalignedLoad(Node* node) { UNREACHABLE(); } 504 UnalignedLoadRepresentation load_rep =
505 UnalignedLoadRepresentationOf(node->op());
506 ArmOperandGenerator g(this);
507 Node* base = node->InputAt(0);
508 Node* index = node->InputAt(1);
499 509
500 // Architecture supports unaligned access, therefore VisitStore is used instead 510 InstructionCode opcode = kArmLdr;
501 void InstructionSelector::VisitUnalignedStore(Node* node) { UNREACHABLE(); } 511 // Only floating point loads need to be specially handled; integer loads
512 // support unaligned access. We support unaligned FP loads by loading to
513 // integer registers first, then moving to the destination FP register.
514 switch (load_rep.representation()) {
515 case MachineRepresentation::kFloat32: {
516 InstructionOperand temp = g.TempRegister();
517 EmitLoad(this, opcode, &temp, base, index);
518 Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp);
519 return;
520 }
521 case MachineRepresentation::kFloat64: {
522 // TODO(arm): use vld1.8 for this when NEON is available.
523 // Compute the address of the least-significant half of the FP value.
524 // We assume that the base node is unlikely to be an encodable immediate
525 // or the result of a shift operation, so only consider the addressing
526 // mode that should be used for the index node.
527 InstructionCode add_opcode = kArmAdd;
528 InstructionOperand inputs[3];
529 inputs[0] = g.UseRegister(base);
530
531 size_t input_count;
532 if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count,
533 &inputs[1])) {
534 // input_count has been set by TryMatchImmediateOrShift(), so increment
535 // it to account for the base register in inputs[0].
536 input_count++;
537 } else {
538 add_opcode |= AddressingModeField::encode(kMode_Operand2_R);
539 inputs[1] = g.UseRegister(index);
540 input_count = 2; // Base register and index.
541 }
542
543 InstructionOperand addr = g.TempRegister();
544 Emit(add_opcode, 1, &addr, input_count, inputs);
545
546 // Load both halves and move to an FP register.
547 InstructionOperand fp_lo = g.TempRegister();
548 InstructionOperand fp_hi = g.TempRegister();
549 opcode |= AddressingModeField::encode(kMode_Offset_RI);
550 Emit(opcode, fp_lo, addr, g.TempImmediate(0));
551 Emit(opcode, fp_hi, addr, g.TempImmediate(4));
552 Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi);
553 return;
554 }
555 default:
556 // All other cases should support unaligned accesses.
557 UNREACHABLE();
558 return;
559 }
560 }
561
562 void InstructionSelector::VisitUnalignedStore(Node* node) {
563 ArmOperandGenerator g(this);
564 Node* base = node->InputAt(0);
565 Node* index = node->InputAt(1);
566 Node* value = node->InputAt(2);
567
568 InstructionOperand inputs[4];
569 size_t input_count = 0;
570
571 UnalignedStoreRepresentation store_rep =
572 UnalignedStoreRepresentationOf(node->op());
573
574 // Only floating point stores need to be specially handled; integer stores
575 // support unaligned access. We support unaligned FP stores by moving the
576 // value to integer registers first, then storing to the destination address.
577 switch (store_rep) {
578 case MachineRepresentation::kFloat32: {
579 inputs[input_count++] = g.TempRegister();
580 Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value));
581 inputs[input_count++] = g.UseRegister(base);
582 EmitStore(this, kArmStr, input_count, inputs, index);
583 return;
584 }
585 case MachineRepresentation::kFloat64: {
586 // TODO(arm): use vst1.8 for this when NEON is available.
587 // Store a 64-bit floating point value using two 32-bit integer stores.
588 // Computing the store address here would require three live temporary
589 // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after
590 // storing the least-significant half of the value.
591
592 // First, move the 64-bit FP value into two temporary integer registers.
593 InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()};
594 inputs[input_count++] = g.UseRegister(value);
595 Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count,
596 inputs);
597
598 // Store the least-significant half.
599 inputs[0] = fp[0]; // Low 32-bits of FP value.
600 inputs[input_count++] = g.UseRegister(base); // First store base address.
601 EmitStore(this, kArmStr, input_count, inputs, index);
602
603 // Store the most-significant half.
604 InstructionOperand base4 = g.TempRegister();
605 Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4,
606 g.UseRegister(base), g.TempImmediate(4)); // Compute base + 4.
607 inputs[0] = fp[1]; // High 32-bits of FP value.
608 inputs[1] = base4; // Second store base + 4 address.
609 EmitStore(this, kArmStr, input_count, inputs, index);
610 return;
611 }
612 default:
613 // All other cases should support unaligned accesses.
614 UNREACHABLE();
615 return;
616 }
617 }
502 618
503 void InstructionSelector::VisitCheckedLoad(Node* node) { 619 void InstructionSelector::VisitCheckedLoad(Node* node) {
504 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); 620 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op());
505 ArmOperandGenerator g(this); 621 ArmOperandGenerator g(this);
506 Node* const buffer = node->InputAt(0); 622 Node* const buffer = node->InputAt(0);
507 Node* const offset = node->InputAt(1); 623 Node* const offset = node->InputAt(1);
508 Node* const length = node->InputAt(2); 624 Node* const length = node->InputAt(2);
509 ArchOpcode opcode = kArchNop; 625 ArchOpcode opcode = kArchNop;
510 switch (load_rep.representation()) { 626 switch (load_rep.representation()) {
511 case MachineRepresentation::kWord8: 627 case MachineRepresentation::kWord8:
(...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 MachineOperatorBuilder::kFloat64RoundTiesEven | 2285 MachineOperatorBuilder::kFloat64RoundTiesEven |
2170 MachineOperatorBuilder::kFloat32Neg | 2286 MachineOperatorBuilder::kFloat32Neg |
2171 MachineOperatorBuilder::kFloat64Neg; 2287 MachineOperatorBuilder::kFloat64Neg;
2172 } 2288 }
2173 return flags; 2289 return flags;
2174 } 2290 }
2175 2291
2176 // static 2292 // static
2177 MachineOperatorBuilder::AlignmentRequirements 2293 MachineOperatorBuilder::AlignmentRequirements
2178 InstructionSelector::AlignmentRequirements() { 2294 InstructionSelector::AlignmentRequirements() {
2295 Vector<MachineType> req_aligned = Vector<MachineType>::New(2);
2296 req_aligned[0] = MachineType::Float32();
2297 req_aligned[1] = MachineType::Float64();
2179 return MachineOperatorBuilder::AlignmentRequirements:: 2298 return MachineOperatorBuilder::AlignmentRequirements::
2180 FullUnalignedAccessSupport(); 2299 SomeUnalignedAccessUnsupported(req_aligned, req_aligned);
2181 } 2300 }
2182 2301
2183 } // namespace compiler 2302 } // namespace compiler
2184 } // namespace internal 2303 } // namespace internal
2185 } // namespace v8 2304 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm/instruction-scheduler-arm.cc ('k') | src/compiler/machine-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698