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

Unified 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, 5 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/arm/instruction-selector-arm.cc
diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc
index 8c7353548a69f709a5a256e4c6afb800254e788b..259c336281b4945cba21ee90e7cf633f28ae3776 100644
--- a/src/compiler/arm/instruction-selector-arm.cc
+++ b/src/compiler/arm/instruction-selector-arm.cc
@@ -338,6 +338,46 @@ void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode div_opcode,
}
}
+void EmitLoad(InstructionSelector* selector, InstructionCode opcode,
+ InstructionOperand* output, Node* base, Node* index) {
+ ArmOperandGenerator g(selector);
+ InstructionOperand inputs[3];
+ size_t input_count = 2;
+
+ inputs[0] = g.UseRegister(base);
+ if (g.CanBeImmediate(index, opcode)) {
+ inputs[1] = g.UseImmediate(index);
+ opcode |= AddressingModeField::encode(kMode_Offset_RI);
+ } else if ((opcode == kArmLdr) &&
+ TryMatchLSLImmediate(selector, &opcode, index, &inputs[1],
+ &inputs[2])) {
+ input_count = 3;
+ } else {
+ inputs[1] = g.UseRegister(index);
+ opcode |= AddressingModeField::encode(kMode_Offset_RR);
+ }
+ selector->Emit(opcode, 1, output, input_count, inputs);
+}
+
+void EmitStore(InstructionSelector* selector, InstructionCode opcode,
+ size_t input_count, InstructionOperand* inputs,
+ Node* index) {
+ ArmOperandGenerator g(selector);
+
+ if (g.CanBeImmediate(index, opcode)) {
+ inputs[input_count++] = g.UseImmediate(index);
+ opcode |= AddressingModeField::encode(kMode_Offset_RI);
+ } else if ((opcode == kArmStr) &&
+ TryMatchLSLImmediate(selector, &opcode, index, &inputs[2],
+ &inputs[3])) {
+ input_count = 4;
+ } else {
+ inputs[input_count++] = g.UseRegister(index);
+ opcode |= AddressingModeField::encode(kMode_Offset_RR);
+ }
+ selector->Emit(opcode, 0, nullptr, input_count, inputs);
+}
+
} // namespace
@@ -346,9 +386,6 @@ void InstructionSelector::VisitLoad(Node* node) {
ArmOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
- InstructionOperand inputs[3];
- size_t input_count = 0;
- InstructionOperand outputs[1];
InstructionCode opcode = kArchNop;
switch (load_rep.representation()) {
@@ -376,24 +413,8 @@ void InstructionSelector::VisitLoad(Node* node) {
return;
}
- outputs[0] = g.DefineAsRegister(node);
- inputs[0] = g.UseRegister(base);
-
- if (g.CanBeImmediate(index, opcode)) {
- input_count = 2;
- inputs[1] = g.UseImmediate(index);
- opcode |= AddressingModeField::encode(kMode_Offset_RI);
- } else if ((opcode == kArmLdr) &&
- TryMatchLSLImmediate(this, &opcode, index, &inputs[1],
- &inputs[2])) {
- input_count = 3;
- } else {
- input_count = 2;
- inputs[1] = g.UseRegister(index);
- opcode |= AddressingModeField::encode(kMode_Offset_RR);
- }
-
- Emit(opcode, arraysize(outputs), outputs, input_count, inputs);
+ InstructionOperand output = g.DefineAsRegister(node);
+ EmitLoad(this, opcode, &output, base, index);
}
@@ -445,9 +466,6 @@ void InstructionSelector::VisitStore(Node* node) {
code |= MiscField::encode(static_cast<int>(record_write_mode));
Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
} else {
- InstructionOperand inputs[4];
- size_t input_count = 0;
-
InstructionCode opcode = kArchNop;
switch (rep) {
case MachineRepresentation::kFloat32:
@@ -474,31 +492,129 @@ void InstructionSelector::VisitStore(Node* node) {
return;
}
- inputs[0] = g.UseRegister(value);
- inputs[1] = g.UseRegister(base);
+ InstructionOperand inputs[4];
+ size_t input_count = 0;
+ inputs[input_count++] = g.UseRegister(value);
+ inputs[input_count++] = g.UseRegister(base);
+ EmitStore(this, opcode, input_count, inputs, index);
+ }
+}
+
+void InstructionSelector::VisitUnalignedLoad(Node* node) {
+ UnalignedLoadRepresentation load_rep =
+ UnalignedLoadRepresentationOf(node->op());
+ ArmOperandGenerator g(this);
+ Node* base = node->InputAt(0);
+ Node* index = node->InputAt(1);
+
+ InstructionCode opcode = kArmLdr;
+ // Only floating point loads need to be specially handled; integer loads
+ // support unaligned access. We support unaligned FP loads by loading to
+ // integer registers first, then moving to the destination FP register.
+ switch (load_rep.representation()) {
+ case MachineRepresentation::kFloat32: {
+ InstructionOperand temp = g.TempRegister();
+ EmitLoad(this, opcode, &temp, base, index);
+ Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp);
+ return;
+ }
+ case MachineRepresentation::kFloat64: {
+ // TODO(arm): use vld1.8 for this when NEON is available.
+ // Compute the address of the least-significant half of the FP value.
+ // We assume that the base node is unlikely to be an encodable immediate
+ // or the result of a shift operation, so only consider the addressing
+ // mode that should be used for the index node.
+ InstructionCode add_opcode = kArmAdd;
+ InstructionOperand inputs[3];
+ inputs[0] = g.UseRegister(base);
+
+ size_t input_count;
+ if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count,
+ &inputs[1])) {
+ // input_count has been set by TryMatchImmediateOrShift(), so increment
+ // it to account for the base register in inputs[0].
+ input_count++;
+ } else {
+ add_opcode |= AddressingModeField::encode(kMode_Operand2_R);
+ inputs[1] = g.UseRegister(index);
+ input_count = 2; // Base register and index.
+ }
+
+ InstructionOperand addr = g.TempRegister();
+ Emit(add_opcode, 1, &addr, input_count, inputs);
- if (g.CanBeImmediate(index, opcode)) {
- input_count = 3;
- inputs[2] = g.UseImmediate(index);
+ // Load both halves and move to an FP register.
+ InstructionOperand fp_lo = g.TempRegister();
+ InstructionOperand fp_hi = g.TempRegister();
opcode |= AddressingModeField::encode(kMode_Offset_RI);
- } else if ((opcode == kArmStr) &&
- TryMatchLSLImmediate(this, &opcode, index, &inputs[2],
- &inputs[3])) {
- input_count = 4;
- } else {
- input_count = 3;
- inputs[2] = g.UseRegister(index);
- opcode |= AddressingModeField::encode(kMode_Offset_RR);
+ Emit(opcode, fp_lo, addr, g.TempImmediate(0));
+ Emit(opcode, fp_hi, addr, g.TempImmediate(4));
+ Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi);
+ return;
}
- Emit(opcode, 0, nullptr, input_count, inputs);
+ default:
+ // All other cases should support unaligned accesses.
+ UNREACHABLE();
+ return;
}
}
-// Architecture supports unaligned access, therefore VisitLoad is used instead
-void InstructionSelector::VisitUnalignedLoad(Node* node) { UNREACHABLE(); }
+void InstructionSelector::VisitUnalignedStore(Node* node) {
+ ArmOperandGenerator g(this);
+ Node* base = node->InputAt(0);
+ Node* index = node->InputAt(1);
+ Node* value = node->InputAt(2);
+
+ InstructionOperand inputs[4];
+ size_t input_count = 0;
-// Architecture supports unaligned access, therefore VisitStore is used instead
-void InstructionSelector::VisitUnalignedStore(Node* node) { UNREACHABLE(); }
+ UnalignedStoreRepresentation store_rep =
+ UnalignedStoreRepresentationOf(node->op());
+
+ // Only floating point stores need to be specially handled; integer stores
+ // support unaligned access. We support unaligned FP stores by moving the
+ // value to integer registers first, then storing to the destination address.
+ switch (store_rep) {
+ case MachineRepresentation::kFloat32: {
+ inputs[input_count++] = g.TempRegister();
+ Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value));
+ inputs[input_count++] = g.UseRegister(base);
+ EmitStore(this, kArmStr, input_count, inputs, index);
+ return;
+ }
+ case MachineRepresentation::kFloat64: {
+ // TODO(arm): use vst1.8 for this when NEON is available.
+ // Store a 64-bit floating point value using two 32-bit integer stores.
+ // Computing the store address here would require three live temporary
+ // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after
+ // storing the least-significant half of the value.
+
+ // First, move the 64-bit FP value into two temporary integer registers.
+ InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()};
+ inputs[input_count++] = g.UseRegister(value);
+ Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count,
+ inputs);
+
+ // Store the least-significant half.
+ inputs[0] = fp[0]; // Low 32-bits of FP value.
+ inputs[input_count++] = g.UseRegister(base); // First store base address.
+ EmitStore(this, kArmStr, input_count, inputs, index);
+
+ // Store the most-significant half.
+ InstructionOperand base4 = g.TempRegister();
+ Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4,
+ g.UseRegister(base), g.TempImmediate(4)); // Compute base + 4.
+ inputs[0] = fp[1]; // High 32-bits of FP value.
+ inputs[1] = base4; // Second store base + 4 address.
+ EmitStore(this, kArmStr, input_count, inputs, index);
+ return;
+ }
+ default:
+ // All other cases should support unaligned accesses.
+ UNREACHABLE();
+ return;
+ }
+}
void InstructionSelector::VisitCheckedLoad(Node* node) {
CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op());
@@ -2176,8 +2292,11 @@ InstructionSelector::SupportedMachineOperatorFlags() {
// static
MachineOperatorBuilder::AlignmentRequirements
InstructionSelector::AlignmentRequirements() {
+ Vector<MachineType> req_aligned = Vector<MachineType>::New(2);
+ req_aligned[0] = MachineType::Float32();
+ req_aligned[1] = MachineType::Float64();
return MachineOperatorBuilder::AlignmentRequirements::
- FullUnalignedAccessSupport();
+ SomeUnalignedAccessUnsupported(req_aligned, req_aligned);
}
} // namespace compiler
« 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