Bug 1301400: Baseline Wasm Compiler: Part 3: Implement ConvertI64, r=lth

This commit is contained in:
h4writer 2016-09-29 22:33:22 +02:00
parent 9bff77359e
commit 2c6cdd35ac
19 changed files with 192 additions and 65 deletions

View File

@ -2762,23 +2762,31 @@ class BaseCompiler
return true;
}
void convertI64ToF32(RegI64 src, bool isUnsigned, RegF32 dest) {
#ifdef JS_CODEGEN_X64
bool convertI64ToFloatNeedsTemp(bool isUnsigned) const {
#if defined(JS_CODEGEN_X86)
return isUnsigned && AssemblerX86Shared::HasSSE3();
#else
return false;
#endif
}
void convertI64ToF32(RegI64 src, bool isUnsigned, RegF32 dest, RegI32 temp) {
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
if (isUnsigned)
masm.convertUInt64ToFloat32(src.reg.reg, dest.reg);
masm.convertUInt64ToFloat32(src.reg, dest.reg, temp.reg);
else
masm.convertInt64ToFloat32(src.reg.reg, dest.reg);
masm.convertInt64ToFloat32(src.reg, dest.reg);
#else
MOZ_CRASH("BaseCompiler platform hook: convertI64ToF32");
#endif
}
void convertI64ToF64(RegI64 src, bool isUnsigned, RegF64 dest) {
#ifdef JS_CODEGEN_X64
void convertI64ToF64(RegI64 src, bool isUnsigned, RegF64 dest, RegI32 temp) {
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
if (isUnsigned)
masm.convertUInt64ToDouble(src.reg.reg, dest.reg);
masm.convertUInt64ToDouble(src.reg, dest.reg, temp.reg);
else
masm.convertInt64ToDouble(src.reg.reg, dest.reg);
masm.convertInt64ToDouble(src.reg, dest.reg);
#else
MOZ_CRASH("BaseCompiler platform hook: convertI32ToF64");
#endif
@ -4328,7 +4336,7 @@ BaseCompiler::emitConvertI64ToF32()
{
RegI64 r0 = popI64();
RegF32 f0 = needF32();
convertI64ToF32(r0, IsUnsigned(false), f0);
convertI64ToF32(r0, IsUnsigned(false), f0, RegI32());
freeI64(r0);
pushF32(f0);
}
@ -4338,7 +4346,12 @@ BaseCompiler::emitConvertU64ToF32()
{
RegI64 r0 = popI64();
RegF32 f0 = needF32();
convertI64ToF32(r0, IsUnsigned(true), f0);
RegI32 temp;
if (convertI64ToFloatNeedsTemp(IsUnsigned(true)))
temp = needI32();
convertI64ToF32(r0, IsUnsigned(true), f0, temp);
if (temp.reg != Register::Invalid())
freeI32(temp);
freeI64(r0);
pushF32(f0);
}
@ -4378,7 +4391,7 @@ BaseCompiler::emitConvertI64ToF64()
{
RegI64 r0 = popI64();
RegF64 d0 = needF64();
convertI64ToF64(r0, IsUnsigned(false), d0);
convertI64ToF64(r0, IsUnsigned(false), d0, RegI32());
freeI64(r0);
pushF64(d0);
}
@ -4388,7 +4401,12 @@ BaseCompiler::emitConvertU64ToF64()
{
RegI64 r0 = popI64();
RegF64 d0 = needF64();
convertI64ToF64(r0, IsUnsigned(true), d0);
RegI32 temp;
if (convertI64ToFloatNeedsTemp(IsUnsigned(true)))
temp = needI32();
convertI64ToF64(r0, IsUnsigned(true), d0, temp);
if (temp.reg != Register::Invalid())
freeI32(temp);
freeI64(r0);
pushF64(d0);
}

View File

@ -11904,7 +11904,10 @@ CodeGenerator::visitRandom(LRandom* ins)
masm.and64(Imm64((1ULL << MantissaBits) - 1), s1Reg);
masm.convertUInt64ToDouble(s1Reg, tempReg, output);
if (masm.convertUInt64ToDoubleNeedsTemp())
masm.convertUInt64ToDouble(s1Reg, output, tempReg);
else
masm.convertUInt64ToDouble(s1Reg, output, Register::Invalid());
// output *= ScaleInv
masm.mulDoublePtr(ImmPtr(&ScaleInv), tempReg, output);

View File

@ -93,9 +93,16 @@ MacroAssemblerARM::convertUInt32ToDouble(Register src, FloatRegister dest_)
static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
void
MacroAssemblerARMCompat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
bool
MacroAssemblerARMCompat::convertUInt64ToDoubleNeedsTemp()
{
return false;
}
void
MacroAssemblerARMCompat::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
{
MOZ_ASSERT(temp == Register::Invalid());
convertUInt32ToDouble(src.high, dest);
movePtr(ImmPtr(&TO_DOUBLE_HIGH_SCALE), ScratchRegister);
loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);

View File

@ -1329,7 +1329,8 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
void cmpPtr(const Address& lhs, ImmGCPtr rhs);
void cmpPtr(const Address& lhs, Imm32 rhs);
void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
static bool convertUInt64ToDoubleNeedsTemp();
void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
void setStackArg(Register reg, uint32_t arg);

View File

@ -2238,7 +2238,12 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
vixl::MacroAssembler::Ret(vixl::lr);
}
void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest) {
bool convertUInt64ToDoubleNeedsTemp() {
return false;
}
void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp) {
MOZ_ASSERT(temp == Register::Invalid());
Ucvtf(ARMFPRegister(dest, 64), ARMRegister(src.reg, 64));
}

View File

@ -79,9 +79,16 @@ MacroAssemblerMIPSCompat::convertUInt32ToDouble(Register src, FloatRegister dest
static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
void
MacroAssemblerMIPSCompat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
bool
MacroAssemblerMIPSCompat::convertUInt64ToDoubleNeedsTemp()
{
return false;
}
void
MacroAssemblerMIPSCompat::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
{
MOZ_ASSERT(temp == Register::Invalid());
convertUInt32ToDouble(src.high, dest);
loadConstantDouble(TO_DOUBLE_HIGH_SCALE, ScratchDoubleReg);
asMasm().mulDouble(ScratchDoubleReg, dest);

View File

@ -941,7 +941,8 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
moveToDoubleHi(zero, reg);
}
void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
static bool convertUInt64ToDoubleNeedsTemp();
void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
void breakpoint();

View File

@ -74,9 +74,17 @@ MacroAssemblerMIPS64Compat::convertUInt32ToDouble(Register src, FloatRegister de
as_addd(dest, dest, SecondScratchDoubleReg);
}
void
MacroAssemblerMIPS64Compat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
bool
MacroAssemblerMIPS64Compat::convertUInt64ToDoubleNeedsTemp()
{
return false;
}
void
MacroAssemblerMIPS64Compat::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
{
MOZ_ASSERT(temp == Register::Invalid());
Label positive, done;
ma_b(src.reg, src.reg, &positive, NotSigned, ShortJump);

View File

@ -946,7 +946,8 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
moveToDouble(zero, reg);
}
void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
static bool convertUInt64ToDoubleNeedsTemp();
void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
void breakpoint();

View File

@ -380,7 +380,8 @@ class MacroAssemblerNone : public Assembler
template <typename T> void convertInt32ToDouble(T, FloatRegister) { MOZ_CRASH(); }
void convertFloat32ToDouble(FloatRegister, FloatRegister) { MOZ_CRASH(); }
void convertUInt64ToDouble(Register64, Register, FloatRegister) { MOZ_CRASH(); }
static bool convertUInt64ToDoubleNeedsTemp() { MOZ_CRASH(); }
void convertUInt64ToDouble(Register64, FloatRegister, Register) { MOZ_CRASH(); }
void boolValueToDouble(ValueOperand, FloatRegister) { MOZ_CRASH(); }
void boolValueToFloat32(ValueOperand, FloatRegister) { MOZ_CRASH(); }

View File

@ -839,7 +839,7 @@ CodeGeneratorX64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
void
CodeGeneratorX64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
{
Register input = ToRegister(lir->input());
Register64 input = ToRegister64(lir->getInt64Operand(0));
FloatRegister output = ToFloatRegister(lir->output());
MIRType outputType = lir->mir()->type();
@ -847,12 +847,12 @@ CodeGeneratorX64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
if (outputType == MIRType::Double) {
if (lir->mir()->isUnsigned())
masm.convertUInt64ToDouble(input, output);
masm.convertUInt64ToDouble(input, output, Register::Invalid());
else
masm.convertInt64ToDouble(input, output);
} else {
if (lir->mir()->isUnsigned())
masm.convertUInt64ToFloat32(input, output);
masm.convertUInt64ToFloat32(input, output, Register::Invalid());
else
masm.convertInt64ToFloat32(input, output);
}

View File

@ -485,7 +485,7 @@ LIRGeneratorX64::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
MOZ_ASSERT(opd->type() == MIRType::Int64);
MOZ_ASSERT(IsFloatingPointType(ins->type()));
define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd), LDefinition::BogusTemp()), ins);
}
void

View File

@ -85,25 +85,34 @@ MacroAssemblerX64::loadConstantSimd128Float(const SimdConstant&v, FloatRegister
}
void
MacroAssemblerX64::convertInt64ToDouble(Register input, FloatRegister output)
MacroAssemblerX64::convertInt64ToDouble(Register64 input, FloatRegister output)
{
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroDouble(output);
vcvtsq2sd(input, output, output);
vcvtsq2sd(input.reg, output, output);
}
void
MacroAssemblerX64::convertInt64ToFloat32(Register input, FloatRegister output)
MacroAssemblerX64::convertInt64ToFloat32(Register64 input, FloatRegister output)
{
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroFloat32(output);
vcvtsq2ss(input, output, output);
vcvtsq2ss(input.reg, output, output);
}
void
MacroAssemblerX64::convertUInt64ToDouble(Register input, FloatRegister output)
bool
MacroAssemblerX64::convertUInt64ToDoubleNeedsTemp()
{
return false;
}
void
MacroAssemblerX64::convertUInt64ToDouble(Register64 input, FloatRegister output, Register temp)
{
MOZ_ASSERT(temp == Register::Invalid());
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroDouble(output);
@ -112,15 +121,15 @@ MacroAssemblerX64::convertUInt64ToDouble(Register input, FloatRegister output)
Label done;
Label isSigned;
testq(input, input);
testq(input.reg, input.reg);
j(Assembler::Signed, &isSigned);
vcvtsq2sd(input, output, output);
vcvtsq2sd(input.reg, output, output);
jump(&done);
bind(&isSigned);
ScratchRegisterScope scratch(asMasm());
mov(input, scratch);
mov(input.reg, scratch);
shrq(Imm32(1), scratch);
vcvtsq2sd(scratch, output, output);
vaddsd(output, output, output);
@ -129,8 +138,10 @@ MacroAssemblerX64::convertUInt64ToDouble(Register input, FloatRegister output)
}
void
MacroAssemblerX64::convertUInt64ToFloat32(Register input, FloatRegister output)
MacroAssemblerX64::convertUInt64ToFloat32(Register64 input, FloatRegister output, Register temp)
{
MOZ_ASSERT(temp == Register::Invalid());
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroFloat32(output);
@ -139,15 +150,15 @@ MacroAssemblerX64::convertUInt64ToFloat32(Register input, FloatRegister output)
Label done;
Label isSigned;
testq(input, input);
testq(input.reg, input.reg);
j(Assembler::Signed, &isSigned);
vcvtsq2ss(input, output, output);
vcvtsq2ss(input.reg, output, output);
jump(&done);
bind(&isSigned);
ScratchRegisterScope scratch(asMasm());
mov(input, scratch);
mov(input.reg, scratch);
shrq(Imm32(1), scratch);
vcvtsq2ss(scratch, output, output);
vaddss(output, output, output);

View File

@ -870,11 +870,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
void loadConstantSimd128Int(const SimdConstant& v, FloatRegister dest);
void loadConstantSimd128Float(const SimdConstant& v, FloatRegister dest);
void convertInt64ToDouble(Register input, FloatRegister output);
void convertInt64ToFloat32(Register input, FloatRegister output);
void convertUInt64ToDouble(Register input, FloatRegister output);
void convertUInt64ToFloat32(Register input, FloatRegister output);
void convertInt64ToDouble(Register64 input, FloatRegister output);
void convertInt64ToFloat32(Register64 input, FloatRegister output);
static bool convertUInt64ToDoubleNeedsTemp();
void convertUInt64ToDouble(Register64 input, FloatRegister output, Register temp);
void convertUInt64ToFloat32(Register64 input, FloatRegister output, Register temp);
void wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempDouble);
@ -943,15 +943,17 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
void convertUInt32ToDouble(Register src, FloatRegister dest) {
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroDouble(dest);
vcvtsq2sd(src, dest, dest);
}
void convertUInt32ToFloat32(Register src, FloatRegister dest) {
vcvtsq2ss(src, dest, dest);
}
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroDouble(dest);
void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest) {
vcvtsi2sdq(src.reg, dest);
vcvtsq2ss(src, dest, dest);
}
inline void incrementInt32Value(const Address& addr);

View File

@ -385,18 +385,23 @@ class LSimdValueFloat32x4 : public LInstructionHelper<1, 4, 1>
}
};
class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 0>
class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 1>
{
public:
LIR_HEADER(Int64ToFloatingPoint);
explicit LInt64ToFloatingPoint(const LInt64Allocation& in) {
explicit LInt64ToFloatingPoint(const LInt64Allocation& in, const LDefinition& temp) {
setInt64Operand(0, in);
setTemp(0, temp);
}
MInt64ToFloatingPoint* mir() const {
return mir_->toInt64ToFloatingPoint();
}
const LDefinition* temp() {
return getTemp(0);
}
};
} // namespace jit

View File

@ -1279,18 +1279,19 @@ CodeGeneratorX86::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
{
Register64 input = ToRegister64(lir->getInt64Operand(0));
FloatRegister output = ToFloatRegister(lir->output());
Register temp = lir->temp()->isBogusTemp() ? InvalidReg : ToRegister(lir->temp());
MIRType outputType = lir->mir()->type();
MOZ_ASSERT(outputType == MIRType::Double || outputType == MIRType::Float32);
if (outputType == MIRType::Double) {
if (lir->mir()->isUnsigned())
masm.convertUInt64ToFloat64(input, output);
masm.convertUInt64ToDouble(input, output, temp);
else
masm.convertInt64ToFloat64(input, output);
masm.convertInt64ToDouble(input, output);
} else {
if (lir->mir()->isUnsigned())
masm.convertUInt64ToFloat32(input, output);
masm.convertUInt64ToFloat32(input, output, temp);
else
masm.convertInt64ToFloat32(input, output);
}

View File

@ -638,7 +638,10 @@ LIRGeneratorX86::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
MOZ_ASSERT(opd->type() == MIRType::Int64);
MOZ_ASSERT(IsFloatingPointType(ins->type()));
define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
LDefinition maybeTemp =
(ins->isUnsigned() && AssemblerX86Shared::HasSSE3()) ? temp() : LDefinition::BogusTemp();
define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd), maybeTemp), ins);
}
void

View File

@ -32,17 +32,37 @@ MOZ_ALIGNED_DECL(static const uint64_t, 16) TO_DOUBLE[4] = {
static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
bool
MacroAssemblerX86::convertUInt64ToDoubleNeedsTemp()
{
return HasSSE3();
}
void
MacroAssemblerX86::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
MacroAssemblerX86::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
{
// SUBPD needs SSE2, HADDPD needs SSE3.
if (!HasSSE3()) {
convertUInt32ToDouble(src.high, dest);
movePtr(ImmPtr(&TO_DOUBLE_HIGH_SCALE), temp);
loadDouble(Address(temp, 0), ScratchDoubleReg);
asMasm().mulDouble(ScratchDoubleReg, dest);
convertUInt32ToDouble(src.low, ScratchDoubleReg);
asMasm().addDouble(ScratchDoubleReg, dest);
MOZ_ASSERT(temp == Register::Invalid());
// Zero the dest register to break dependencies, see convertInt32ToDouble.
zeroDouble(dest);
asMasm().Push(src.high);
asMasm().Push(src.low);
fild(Operand(esp, 0));
Label notNegative;
asMasm().branch32(Assembler::NotSigned, src.high, Imm32(0), &notNegative);
double add_constant = 18446744073709551616.0; // 2^64
store64(Imm64(mozilla::BitwiseCast<uint64_t>(add_constant)), Address(esp, 0));
fld(Operand(esp, 0));
faddp();
bind(&notNegative);
fstp(Operand(esp, 0));
vmovsd(Address(esp, 0), dest);
asMasm().freeStack(2*sizeof(intptr_t));
return;
}
@ -70,7 +90,7 @@ MacroAssemblerX86::convertUInt64ToDouble(Register64 src, Register temp, FloatReg
// here, each 64-bit part of dest represents following double:
// HI(dest) = 0x 1.00000HHHHHHHH * 2**84 == 2**84 + 0x HHHHHHHH 00000000
// LO(dest) = 0x 1.00000LLLLLLLL * 2**52 == 2**52 + 0x 00000000 LLLLLLLL
movePtr(ImmPtr(TO_DOUBLE), temp);
movePtr(ImmWord((uintptr_t)TO_DOUBLE), temp);
vpunpckldq(Operand(temp, 0), dest128, dest128);
// Subtract a constant C2 from dest, for each 64-bit part:
@ -806,6 +826,35 @@ MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input, Register output
//}}} check_macroassembler_style
void
MacroAssemblerX86::convertInt64ToDouble(Register64 input, FloatRegister output)
{
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroDouble(output);
asMasm().Push(input.high);
asMasm().Push(input.low);
fild(Operand(esp, 0));
fstp(Operand(esp, 0));
vmovsd(Address(esp, 0), output);
asMasm().freeStack(2*sizeof(intptr_t));
}
void
MacroAssemblerX86::convertInt64ToFloat32(Register64 input, FloatRegister output)
{
convertInt64ToDouble(input, output);
convertDoubleToFloat32(output, output);
}
void
MacroAssemblerX86::convertUInt64ToFloat32(Register64 input, FloatRegister output, Register temp)
{
convertUInt64ToDouble(input, output.asDouble(), temp);
convertDoubleToFloat32(output, output);
}
void
MacroAssemblerX86::wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempReg)

View File

@ -834,7 +834,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
// Note: this function clobbers the source register.
inline void convertUInt32ToFloat32(Register src, FloatRegister dest);
void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
void convertUInt64ToFloat32(Register64 src, FloatRegister dest, Register temp);
void convertInt64ToFloat32(Register64 src, FloatRegister dest);
static bool convertUInt64ToDoubleNeedsTemp();
void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
void convertInt64ToDouble(Register64 src, FloatRegister dest);
void wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempDouble);