Index: src/compiler/arm/code-generator-arm.cc |
diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc |
index e969f02e1f5dfeb727118057fcdbb4162b1e7e22..d61a530d88ba3c4ebf91cbff56c527e72a92daf3 100644 |
--- a/src/compiler/arm/code-generator-arm.cc |
+++ b/src/compiler/arm/code-generator-arm.cc |
@@ -136,25 +136,13 @@ class ArmOperandConverter final : public InstructionOperandConverter { |
FrameOffset offset = frame_access_state()->GetFrameOffset(slot); |
return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); |
} |
- |
- FloatRegister InputFloat32Register(size_t index) { |
- return ToFloat32Register(instr_->InputAt(index)); |
- } |
- |
- FloatRegister OutputFloat32Register() { |
- return ToFloat32Register(instr_->Output()); |
- } |
- |
- FloatRegister ToFloat32Register(InstructionOperand* op) { |
- return LowDwVfpRegister::from_code(ToDoubleRegister(op).code()).low(); |
- } |
}; |
namespace { |
-class OutOfLineLoadFloat32 final : public OutOfLineCode { |
+class OutOfLineLoadFloat final : public OutOfLineCode { |
public: |
- OutOfLineLoadFloat32(CodeGenerator* gen, SwVfpRegister result) |
+ OutOfLineLoadFloat(CodeGenerator* gen, SwVfpRegister result) |
: OutOfLineCode(gen), result_(result) {} |
void Generate() final { |
@@ -1122,54 +1110,54 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
} |
case kArmVcmpF32: |
if (instr->InputAt(1)->IsFPRegister()) { |
- __ VFPCompareAndSetFlags(i.InputFloat32Register(0), |
- i.InputFloat32Register(1)); |
+ __ VFPCompareAndSetFlags(i.InputFloatRegister(0), |
+ i.InputFloatRegister(1)); |
} else { |
DCHECK(instr->InputAt(1)->IsImmediate()); |
// 0.0 is the only immediate supported by vcmp instructions. |
DCHECK(i.InputFloat32(1) == 0.0f); |
- __ VFPCompareAndSetFlags(i.InputFloat32Register(0), i.InputFloat32(1)); |
+ __ VFPCompareAndSetFlags(i.InputFloatRegister(0), i.InputFloat32(1)); |
} |
DCHECK_EQ(SetCC, i.OutputSBit()); |
break; |
case kArmVaddF32: |
- __ vadd(i.OutputFloat32Register(), i.InputFloat32Register(0), |
- i.InputFloat32Register(1)); |
+ __ vadd(i.OutputFloatRegister(), i.InputFloatRegister(0), |
+ i.InputFloatRegister(1)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVsubF32: |
- __ vsub(i.OutputFloat32Register(), i.InputFloat32Register(0), |
- i.InputFloat32Register(1)); |
+ __ vsub(i.OutputFloatRegister(), i.InputFloatRegister(0), |
+ i.InputFloatRegister(1)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVmulF32: |
- __ vmul(i.OutputFloat32Register(), i.InputFloat32Register(0), |
- i.InputFloat32Register(1)); |
+ __ vmul(i.OutputFloatRegister(), i.InputFloatRegister(0), |
+ i.InputFloatRegister(1)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVmlaF32: |
- __ vmla(i.OutputFloat32Register(), i.InputFloat32Register(1), |
- i.InputFloat32Register(2)); |
+ __ vmla(i.OutputFloatRegister(), i.InputFloatRegister(1), |
+ i.InputFloatRegister(2)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVmlsF32: |
- __ vmls(i.OutputFloat32Register(), i.InputFloat32Register(1), |
- i.InputFloat32Register(2)); |
+ __ vmls(i.OutputFloatRegister(), i.InputFloatRegister(1), |
+ i.InputFloatRegister(2)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVdivF32: |
- __ vdiv(i.OutputFloat32Register(), i.InputFloat32Register(0), |
- i.InputFloat32Register(1)); |
+ __ vdiv(i.OutputFloatRegister(), i.InputFloatRegister(0), |
+ i.InputFloatRegister(1)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVsqrtF32: |
- __ vsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
+ __ vsqrt(i.OutputFloatRegister(), i.InputFloatRegister(0)); |
break; |
case kArmVabsF32: |
- __ vabs(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
+ __ vabs(i.OutputFloatRegister(), i.InputFloatRegister(0)); |
break; |
case kArmVnegF32: |
- __ vneg(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
+ __ vneg(i.OutputFloatRegister(), i.InputFloatRegister(0)); |
break; |
case kArmVcmpF64: |
if (instr->InputAt(1)->IsFPRegister()) { |
@@ -1238,7 +1226,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
break; |
case kArmVrintmF32: { |
CpuFeatureScope scope(masm(), ARMv8); |
- __ vrintm(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
+ __ vrintm(i.OutputFloatRegister(), i.InputFloatRegister(0)); |
break; |
} |
case kArmVrintmF64: { |
@@ -1248,7 +1236,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
} |
case kArmVrintpF32: { |
CpuFeatureScope scope(masm(), ARMv8); |
- __ vrintp(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
+ __ vrintp(i.OutputFloatRegister(), i.InputFloatRegister(0)); |
break; |
} |
case kArmVrintpF64: { |
@@ -1258,7 +1246,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
} |
case kArmVrintzF32: { |
CpuFeatureScope scope(masm(), ARMv8); |
- __ vrintz(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
+ __ vrintz(i.OutputFloatRegister(), i.InputFloatRegister(0)); |
break; |
} |
case kArmVrintzF64: { |
@@ -1273,7 +1261,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
} |
case kArmVrintnF32: { |
CpuFeatureScope scope(masm(), ARMv8); |
- __ vrintn(i.OutputFloat32Register(), i.InputFloat32Register(0)); |
+ __ vrintn(i.OutputFloatRegister(), i.InputFloatRegister(0)); |
break; |
} |
case kArmVrintnF64: { |
@@ -1282,26 +1270,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
break; |
} |
case kArmVcvtF32F64: { |
- __ vcvt_f32_f64(i.OutputFloat32Register(), i.InputDoubleRegister(0)); |
+ __ vcvt_f32_f64(i.OutputFloatRegister(), i.InputDoubleRegister(0)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
} |
case kArmVcvtF64F32: { |
- __ vcvt_f64_f32(i.OutputDoubleRegister(), i.InputFloat32Register(0)); |
+ __ vcvt_f64_f32(i.OutputDoubleRegister(), i.InputFloatRegister(0)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
} |
case kArmVcvtF32S32: { |
SwVfpRegister scratch = kScratchDoubleReg.low(); |
__ vmov(scratch, i.InputRegister(0)); |
- __ vcvt_f32_s32(i.OutputFloat32Register(), scratch); |
+ __ vcvt_f32_s32(i.OutputFloatRegister(), scratch); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
} |
case kArmVcvtF32U32: { |
SwVfpRegister scratch = kScratchDoubleReg.low(); |
__ vmov(scratch, i.InputRegister(0)); |
- __ vcvt_f32_u32(i.OutputFloat32Register(), scratch); |
+ __ vcvt_f32_u32(i.OutputFloatRegister(), scratch); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
} |
@@ -1321,7 +1309,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
} |
case kArmVcvtS32F32: { |
SwVfpRegister scratch = kScratchDoubleReg.low(); |
- __ vcvt_s32_f32(scratch, i.InputFloat32Register(0)); |
+ __ vcvt_s32_f32(scratch, i.InputFloatRegister(0)); |
__ vmov(i.OutputRegister(), scratch); |
// Avoid INT32_MAX as an overflow indicator and use INT32_MIN instead, |
// because INT32_MIN allows easier out-of-bounds detection. |
@@ -1332,7 +1320,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
} |
case kArmVcvtU32F32: { |
SwVfpRegister scratch = kScratchDoubleReg.low(); |
- __ vcvt_u32_f32(scratch, i.InputFloat32Register(0)); |
+ __ vcvt_u32_f32(scratch, i.InputFloatRegister(0)); |
__ vmov(i.OutputRegister(), scratch); |
// Avoid UINT32_MAX as an overflow indicator and use 0 instead, |
// because 0 allows easier out-of-bounds detection. |
@@ -1356,11 +1344,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
break; |
} |
case kArmVmovU32F32: |
- __ vmov(i.OutputRegister(), i.InputFloat32Register(0)); |
+ __ vmov(i.OutputRegister(), i.InputFloatRegister(0)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVmovF32U32: |
- __ vmov(i.OutputFloat32Register(), i.InputRegister(0)); |
+ __ vmov(i.OutputFloatRegister(), i.InputRegister(0)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVmovLowU32F64: |
@@ -1418,12 +1406,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVldrF32: { |
- __ vldr(i.OutputFloat32Register(), i.InputOffset()); |
+ __ vldr(i.OutputFloatRegister(), i.InputOffset()); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
} |
case kArmVstrF32: |
- __ vstr(i.InputFloat32Register(0), i.InputOffset(1)); |
+ __ vstr(i.InputFloatRegister(0), i.InputOffset(1)); |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmVldrF64: |
@@ -1435,9 +1423,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
DCHECK_EQ(LeaveCC, i.OutputSBit()); |
break; |
case kArmFloat32Max: { |
- SwVfpRegister result = i.OutputFloat32Register(); |
- SwVfpRegister left = i.InputFloat32Register(0); |
- SwVfpRegister right = i.InputFloat32Register(1); |
+ SwVfpRegister result = i.OutputFloatRegister(); |
+ SwVfpRegister left = i.InputFloatRegister(0); |
+ SwVfpRegister right = i.InputFloatRegister(1); |
if (left.is(right)) { |
__ Move(result, left); |
} else { |
@@ -1463,9 +1451,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
break; |
} |
case kArmFloat32Min: { |
- SwVfpRegister result = i.OutputFloat32Register(); |
- SwVfpRegister left = i.InputFloat32Register(0); |
- SwVfpRegister right = i.InputFloat32Register(1); |
+ SwVfpRegister result = i.OutputFloatRegister(); |
+ SwVfpRegister left = i.InputFloatRegister(0); |
+ SwVfpRegister right = i.InputFloatRegister(1); |
if (left.is(right)) { |
__ Move(result, left); |
} else { |
@@ -1504,7 +1492,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); |
} else { |
DCHECK_EQ(MachineRepresentation::kFloat32, op->representation()); |
- __ vpush(i.InputFloat32Register(0)); |
+ __ vpush(i.InputFloatRegister(0)); |
frame_access_state()->IncreaseSPDelta(1); |
} |
} else { |
@@ -1535,7 +1523,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
ASSEMBLE_CHECKED_LOAD_INTEGER(ldr); |
break; |
case kCheckedLoadFloat32: |
- ASSEMBLE_CHECKED_LOAD_FP(Float32); |
+ ASSEMBLE_CHECKED_LOAD_FP(Float); |
break; |
case kCheckedLoadFloat64: |
ASSEMBLE_CHECKED_LOAD_FP(Double); |
@@ -1550,7 +1538,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
ASSEMBLE_CHECKED_STORE_INTEGER(str); |
break; |
case kCheckedStoreFloat32: |
- ASSEMBLE_CHECKED_STORE_FP(Float32); |
+ ASSEMBLE_CHECKED_STORE_FP(Float); |
break; |
case kCheckedStoreFloat64: |
ASSEMBLE_CHECKED_STORE_FP(Double); |
@@ -1792,7 +1780,6 @@ void CodeGenerator::AssembleReturn() { |
__ Ret(pop_count); |
} |
- |
void CodeGenerator::AssembleMove(InstructionOperand* source, |
InstructionOperand* destination) { |
ArmOperandConverter g(this, nullptr); |
@@ -1861,12 +1848,12 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, |
} |
if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination)); |
} else if (src.type() == Constant::kFloat32) { |
- if (destination->IsFPStackSlot()) { |
+ if (destination->IsFloatStackSlot()) { |
MemOperand dst = g.ToMemOperand(destination); |
__ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
__ str(ip, dst); |
} else { |
- SwVfpRegister dst = g.ToFloat32Register(destination); |
+ SwVfpRegister dst = g.ToFloatRegister(destination); |
__ vmov(dst, src.ToFloat32()); |
} |
} else { |
@@ -1875,28 +1862,60 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, |
? g.ToDoubleRegister(destination) |
: kScratchDoubleReg; |
__ vmov(dst, src.ToFloat64(), kScratchReg); |
- if (destination->IsFPStackSlot()) { |
+ if (destination->IsDoubleStackSlot()) { |
__ vstr(dst, g.ToMemOperand(destination)); |
} |
} |
} else if (source->IsFPRegister()) { |
- DwVfpRegister src = g.ToDoubleRegister(source); |
- if (destination->IsFPRegister()) { |
- DwVfpRegister dst = g.ToDoubleRegister(destination); |
- __ Move(dst, src); |
+ MachineRepresentation rep = LocationOperand::cast(source)->representation(); |
+ if (rep == MachineRepresentation::kFloat64) { |
+ DwVfpRegister src = g.ToDoubleRegister(source); |
+ if (destination->IsDoubleRegister()) { |
+ DwVfpRegister dst = g.ToDoubleRegister(destination); |
+ __ Move(dst, src); |
+ } else { |
+ DCHECK(destination->IsDoubleStackSlot()); |
+ __ vstr(src, g.ToMemOperand(destination)); |
+ } |
} else { |
- DCHECK(destination->IsFPStackSlot()); |
- __ vstr(src, g.ToMemOperand(destination)); |
+ DCHECK_EQ(MachineRepresentation::kFloat32, rep); |
+ // GapResolver may give us reg codes that don't map to actual s-registers. |
+ // Generate code to work around those cases. |
+ int src_code = LocationOperand::cast(source)->register_code(); |
+ if (destination->IsFloatRegister()) { |
+ int dst_code = LocationOperand::cast(destination)->register_code(); |
+ __ VmovExtended(dst_code, src_code, kScratchReg); |
+ } else { |
+ DCHECK(destination->IsFloatStackSlot()); |
+ __ VmovExtended(g.ToMemOperand(destination), src_code, kScratchReg); |
+ } |
} |
} else if (source->IsFPStackSlot()) { |
MemOperand src = g.ToMemOperand(source); |
+ MachineRepresentation rep = |
+ LocationOperand::cast(destination)->representation(); |
if (destination->IsFPRegister()) { |
+ if (rep == MachineRepresentation::kFloat64) { |
__ vldr(g.ToDoubleRegister(destination), src); |
+ } else { |
+ DCHECK_EQ(MachineRepresentation::kFloat32, rep); |
+ // GapResolver may give us reg codes that don't map to actual |
+ // s-registers. Generate code to work around those cases. |
+ int dst_code = LocationOperand::cast(destination)->register_code(); |
+ __ VmovExtended(dst_code, src, kScratchReg); |
+ } |
} else { |
DCHECK(destination->IsFPStackSlot()); |
+ if (rep == MachineRepresentation::kFloat64) { |
DwVfpRegister temp = kScratchDoubleReg; |
__ vldr(temp, src); |
__ vstr(temp, g.ToMemOperand(destination)); |
+ } else { |
+ DCHECK_EQ(MachineRepresentation::kFloat32, rep); |
+ SwVfpRegister temp = kScratchDoubleReg.low(); |
+ __ vldr(temp, src); |
+ __ vstr(temp, g.ToMemOperand(destination)); |
+ } |
} |
} else { |
UNREACHABLE(); |
@@ -1936,17 +1955,35 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, |
__ str(temp_0, dst); |
__ vstr(temp_1, src); |
} else if (source->IsFPRegister()) { |
+ MachineRepresentation rep = LocationOperand::cast(source)->representation(); |
LowDwVfpRegister temp = kScratchDoubleReg; |
- DwVfpRegister src = g.ToDoubleRegister(source); |
- if (destination->IsFPRegister()) { |
- DwVfpRegister dst = g.ToDoubleRegister(destination); |
- __ vswp(src, dst); |
+ if (rep == MachineRepresentation::kFloat64) { |
+ DwVfpRegister src = g.ToDoubleRegister(source); |
+ if (destination->IsFPRegister()) { |
+ DwVfpRegister dst = g.ToDoubleRegister(destination); |
+ __ vswp(src, dst); |
+ } else { |
+ DCHECK(destination->IsFPStackSlot()); |
+ MemOperand dst = g.ToMemOperand(destination); |
+ __ Move(temp, src); |
+ __ vldr(src, dst); |
+ __ vstr(temp, dst); |
+ } |
} else { |
- DCHECK(destination->IsFPStackSlot()); |
- MemOperand dst = g.ToMemOperand(destination); |
- __ Move(temp, src); |
- __ vldr(src, dst); |
- __ vstr(temp, dst); |
+ DCHECK_EQ(MachineRepresentation::kFloat32, rep); |
+ int src_code = LocationOperand::cast(source)->register_code(); |
+ if (destination->IsFPRegister()) { |
+ int dst_code = LocationOperand::cast(destination)->register_code(); |
+ __ VmovExtended(temp.low().code(), src_code, kScratchReg); |
+ __ VmovExtended(src_code, dst_code, kScratchReg); |
+ __ VmovExtended(dst_code, temp.low().code(), kScratchReg); |
+ } else { |
+ DCHECK(destination->IsFPStackSlot()); |
+ MemOperand dst = g.ToMemOperand(destination); |
+ __ VmovExtended(temp.low().code(), src_code, kScratchReg); |
+ __ VmovExtended(src_code, dst, kScratchReg); |
+ __ vstr(temp.low(), dst); |
+ } |
} |
} else if (source->IsFPStackSlot()) { |
DCHECK(destination->IsFPStackSlot()); |
@@ -1954,21 +1991,29 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, |
LowDwVfpRegister temp_1 = kScratchDoubleReg; |
MemOperand src0 = g.ToMemOperand(source); |
MemOperand dst0 = g.ToMemOperand(destination); |
- MemOperand src1(src0.rn(), src0.offset() + kPointerSize); |
- MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize); |
- __ vldr(temp_1, dst0); // Save destination in temp_1. |
- __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination. |
- __ str(temp_0, dst0); |
- __ ldr(temp_0, src1); |
- __ str(temp_0, dst1); |
- __ vstr(temp_1, src0); |
+ MachineRepresentation rep = LocationOperand::cast(source)->representation(); |
+ if (rep == MachineRepresentation::kFloat64) { |
+ MemOperand src1(src0.rn(), src0.offset() + kPointerSize); |
+ MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize); |
+ __ vldr(temp_1, dst0); // Save destination in temp_1. |
+ __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination. |
+ __ str(temp_0, dst0); |
+ __ ldr(temp_0, src1); |
+ __ str(temp_0, dst1); |
+ __ vstr(temp_1, src0); |
+ } else { |
+ DCHECK_EQ(MachineRepresentation::kFloat32, rep); |
+ __ vldr(temp_1.low(), dst0); // Save destination in temp_1. |
+ __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination. |
+ __ str(temp_0, dst0); |
+ __ vstr(temp_1.low(), src0); |
+ } |
} else { |
// No other combinations are possible. |
UNREACHABLE(); |
} |
} |
- |
void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) { |
// On 32-bit ARM we emit the jump tables inline. |
UNREACHABLE(); |