Bug 1232205 - Wasm baseline: Factor out int64ToFloatingPoint and truncateToInt64, on x64. r=bbouvier

--HG--
extra : rebase_source : 91eac395cae061be1f6309f8f36c649010e10703
This commit is contained in:
Lars T Hansen 2016-06-08 12:17:17 +02:00
Родитель 8938a215ec
Коммит 5f37b82773
3 изменённых файлов: 183 добавлений и 87 удалений

Просмотреть файл

@ -1203,57 +1203,23 @@ CodeGeneratorX64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
MWasmTruncateToInt64* mir = lir->mir();
MIRType inputType = mir->input()->type();
MOZ_ASSERT(inputType == MIRType::Double || inputType == MIRType::Float32);
auto* ool = new(alloc()) OutOfLineWasmTruncateCheck(mir, input);
addOutOfLineCode(ool, mir);
if (mir->isUnsigned()) {
FloatRegister tempDouble = ToFloatRegister(lir->temp());
FloatRegister temp = mir->isUnsigned() ? ToFloatRegister(lir->temp()) : InvalidFloatReg;
// If the input < INT64_MAX, vcvttsd2sq will do the right thing, so
// we use it directly. Else, we subtract INT64_MAX, convert to int64,
// and then add INT64_MAX to the result.
if (inputType == MIRType::Double) {
Label isLarge;
masm.loadConstantDouble(double(0x8000000000000000), ScratchDoubleReg);
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, input, ScratchDoubleReg, &isLarge);
masm.vcvttsd2sq(input, output);
masm.branchTestPtr(Assembler::Signed, output, output, ool->entry());
masm.jump(ool->rejoin());
masm.bind(&isLarge);
masm.moveDouble(input, tempDouble);
masm.subDouble(ScratchDoubleReg, tempDouble);
masm.vcvttsd2sq(tempDouble, output);
masm.branchTestPtr(Assembler::Signed, output, output, ool->entry());
masm.or64(Imm64(0x8000000000000000), Register64(output));
} else {
MOZ_ASSERT(inputType == MIRType::Float32);
Label isLarge;
masm.loadConstantFloat32(float(0x8000000000000000), ScratchDoubleReg);
masm.branchFloat(Assembler::DoubleGreaterThanOrEqual, input, ScratchDoubleReg, &isLarge);
masm.vcvttss2sq(input, output);
masm.branchTestPtr(Assembler::Signed, output, output, ool->entry());
masm.jump(ool->rejoin());
masm.bind(&isLarge);
masm.moveFloat32(input, tempDouble);
masm.vsubss(ScratchDoubleReg, tempDouble, tempDouble);
masm.vcvttss2sq(tempDouble, output);
masm.branchTestPtr(Assembler::Signed, output, output, ool->entry());
masm.or64(Imm64(0x8000000000000000), Register64(output));
}
if (inputType == MIRType::Double) {
if (mir->isUnsigned())
masm.wasmTruncateDoubleToUInt64(input, output, ool->entry(), ool->rejoin(), temp);
else
masm.wasmTruncateDoubleToInt64(input, output, ool->entry(), ool->rejoin(), temp);
} else {
if (inputType == MIRType::Double) {
masm.vcvttsd2sq(input, output);
masm.cmpq(Imm32(1), output);
masm.j(Assembler::Overflow, ool->entry());
} else {
MOZ_ASSERT(inputType == MIRType::Float32);
masm.vcvttss2sq(input, output);
masm.cmpq(Imm32(1), output);
masm.j(Assembler::Overflow, ool->entry());
}
if (mir->isUnsigned())
masm.wasmTruncateFloat32ToUInt64(input, output, ool->entry(), ool->rejoin(), temp);
else
masm.wasmTruncateFloat32ToInt64(input, output, ool->entry(), ool->rejoin(), temp);
}
masm.bind(ool->rejoin());
@ -1301,49 +1267,17 @@ CodeGeneratorX64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
MIRType outputType = lir->mir()->type();
MOZ_ASSERT(outputType == MIRType::Double || outputType == MIRType::Float32);
// Zero the output register to break dependencies, see convertInt32ToDouble.
if (outputType == MIRType::Double)
masm.zeroDouble(output);
else
masm.zeroFloat32(output);
Label done;
if (lir->mir()->isUnsigned()) {
// If the input is unsigned, we use cvtsq2sd or vcvtsq2ss directly.
// Else, we divide by 2, convert to double or float, and multiply the
// result by 2.
if (outputType == MIRType::Double) {
Label isSigned;
masm.branchTestPtr(Assembler::Signed, input, input, &isSigned);
masm.vcvtsq2sd(input, output, output);
masm.jump(&done);
masm.bind(&isSigned);
ScratchRegisterScope scratch(masm);
masm.mov(input, scratch);
masm.rshiftPtr(Imm32(1), scratch);
masm.vcvtsq2sd(scratch, output, output);
masm.vaddsd(output, output, output);
} else {
Label isSigned;
masm.branchTestPtr(Assembler::Signed, input, input, &isSigned);
masm.vcvtsq2ss(input, output, output);
masm.jump(&done);
masm.bind(&isSigned);
ScratchRegisterScope scratch(masm);
masm.mov(input, scratch);
masm.rshiftPtr(Imm32(1), scratch);
masm.vcvtsq2ss(scratch, output, output);
masm.vaddss(output, output, output);
}
} else {
if (outputType == MIRType::Double)
masm.vcvtsq2sd(input, output, output);
if (outputType == MIRType::Double) {
if (lir->mir()->isUnsigned())
masm.convertUInt64ToDouble(input, output);
else
masm.vcvtsq2ss(input, output, output);
masm.convertInt64ToDouble(input, output);
} else {
if (lir->mir()->isUnsigned())
masm.convertUInt64ToFloat32(input, output);
else
masm.convertInt64ToFloat32(input, output);
}
masm.bind(&done);
}
void

Просмотреть файл

@ -72,6 +72,151 @@ MacroAssemblerX64::loadConstantSimd128Float(const SimdConstant&v, FloatRegister
propagateOOM(val->uses.append(CodeOffset(j.offset())));
}
void
MacroAssemblerX64::convertInt64ToDouble(Register input, FloatRegister output)
{
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroDouble(output);
vcvtsq2sd(input, output, output);
}
void
MacroAssemblerX64::convertInt64ToFloat32(Register input, FloatRegister output)
{
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroFloat32(output);
vcvtsq2ss(input, output, output);
}
void
MacroAssemblerX64::convertUInt64ToDouble(Register input, FloatRegister output)
{
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroDouble(output);
// If the input's sign bit is not set we use vcvtsq2sd directly.
// Else, we divide by 2, convert to double, and multiply the result by 2.
Label done;
Label isSigned;
testq(input, input);
j(Assembler::Signed, &isSigned);
vcvtsq2sd(input, output, output);
jump(&done);
bind(&isSigned);
ScratchRegisterScope scratch(asMasm());
mov(input, scratch);
shrq(Imm32(1), scratch);
vcvtsq2sd(scratch, output, output);
vaddsd(output, output, output);
bind(&done);
}
void
MacroAssemblerX64::convertUInt64ToFloat32(Register input, FloatRegister output)
{
// Zero the output register to break dependencies, see convertInt32ToDouble.
zeroFloat32(output);
// If the input's sign bit is not set we use vcvtsq2ss directly.
// Else, we divide by 2, convert to float, and multiply the result by 2.
Label done;
Label isSigned;
testq(input, input);
j(Assembler::Signed, &isSigned);
vcvtsq2ss(input, output, output);
jump(&done);
bind(&isSigned);
ScratchRegisterScope scratch(asMasm());
mov(input, scratch);
shrq(Imm32(1), scratch);
vcvtsq2ss(scratch, output, output);
vaddss(output, output, output);
bind(&done);
}
void
MacroAssemblerX64::wasmTruncateDoubleToInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempReg)
{
vcvttsd2sq(input, output);
cmpq(Imm32(1), output);
j(Assembler::Overflow, oolEntry);
}
void
MacroAssemblerX64::wasmTruncateFloat32ToInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempReg)
{
vcvttss2sq(input, output);
cmpq(Imm32(1), output);
j(Assembler::Overflow, oolEntry);
}
void
MacroAssemblerX64::wasmTruncateDoubleToUInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempReg)
{
// If the input < INT64_MAX, vcvttsd2sq will do the right thing, so
// we use it directly. Else, we subtract INT64_MAX, convert to int64,
// and then add INT64_MAX to the result.
Label isLarge;
ScratchDoubleScope scratch(asMasm());
loadConstantDouble(double(0x8000000000000000), scratch);
asMasm().branchDouble(Assembler::DoubleGreaterThanOrEqual, input, scratch, &isLarge);
vcvttsd2sq(input, output);
testq(output, output);
j(Assembler::Signed, oolEntry);
jump(oolRejoin);
bind(&isLarge);
moveDouble(input, tempReg);
vsubsd(scratch, tempReg, tempReg);
vcvttsd2sq(tempReg, output);
testq(output, output);
j(Assembler::Signed, oolEntry);
asMasm().or64(Imm64(0x8000000000000000), Register64(output));
}
void
MacroAssemblerX64::wasmTruncateFloat32ToUInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempReg)
{
// If the input < INT64_MAX, vcvttss2sq will do the right thing, so
// we use it directly. Else, we subtract INT64_MAX, convert to int64,
// and then add INT64_MAX to the result.
Label isLarge;
ScratchFloat32Scope scratch(asMasm());
loadConstantFloat32(float(0x8000000000000000), scratch);
asMasm().branchFloat(Assembler::DoubleGreaterThanOrEqual, input, scratch, &isLarge);
vcvttss2sq(input, output);
testq(output, output);
j(Assembler::Signed, oolEntry);
jump(oolRejoin);
bind(&isLarge);
moveFloat32(input, tempReg);
vsubss(scratch, tempReg, tempReg);
vcvttss2sq(tempReg, output);
testq(output, output);
j(Assembler::Signed, oolEntry);
asMasm().or64(Imm64(0x8000000000000000), Register64(output));
}
void
MacroAssemblerX64::bindOffsets(const MacroAssemblerX86Shared::UsesVector& uses)
{

Просмотреть файл

@ -864,6 +864,23 @@ 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 wasmTruncateDoubleToInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempDouble);
void wasmTruncateDoubleToUInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempDouble);
void wasmTruncateFloat32ToInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempDouble);
void wasmTruncateFloat32ToUInt64(FloatRegister input, Register output, Label* oolEntry,
Label* oolRejoin, FloatRegister tempDouble);
public:
Condition testInt32Truthy(bool truthy, const ValueOperand& operand) {
test32(operand.valueReg(), operand.valueReg());
return truthy ? NonZero : Zero;