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 fb04eb1cf44c929eebdb9899e9a25a1db8a42a44..b9cd35ad9a921fad503c2b6c0d233580e5355c92 100644 |
--- a/src/compiler/arm/instruction-selector-arm.cc |
+++ b/src/compiler/arm/instruction-selector-arm.cc |
@@ -560,37 +560,41 @@ void InstructionSelector::VisitUnalignedLoad(Node* node) { |
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++; |
+ if (CpuFeatures::IsSupported(NEON)) { |
+ InstructionOperand output = g.DefineAsRegister(node); |
+ EmitLoad(this, kArmVld1F64, &output, base, index); |
} else { |
- add_opcode |= AddressingModeField::encode(kMode_Operand2_R); |
- inputs[1] = g.UseRegister(index); |
- input_count = 2; // Base register and index. |
- } |
+ // 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); |
+ InstructionOperand addr = g.TempRegister(); |
+ Emit(add_opcode, 1, &addr, input_count, inputs); |
- // 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); |
- 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); |
+ // 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); |
+ 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; |
} |
default: |
@@ -624,30 +628,35 @@ void InstructionSelector::VisitUnalignedStore(Node* node) { |
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); |
+ if (CpuFeatures::IsSupported(NEON)) { |
+ inputs[input_count++] = g.UseRegister(value); |
+ inputs[input_count++] = g.UseRegister(base); |
+ EmitStore(this, kArmVst1F64, input_count, inputs, index); |
+ } else { |
+ // 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: |