Bug 1232205 - Wasm baseline: Factor outOfLineWasmTruncateCheck and outOfLineTruncateSlow, on x86-shared. r=bbouvier

--HG--
extra : rebase_source : 06266204a20175e6939be925869c1cdcb5159d74
This commit is contained in:
Lars T Hansen 2016-06-06 15:11:51 +02:00
Родитель 8ec23c07dd
Коммит 9af7246a47
6 изменённых файлов: 121 добавлений и 91 удалений

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

@ -1819,6 +1819,49 @@ MacroAssembler::convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, Flo
}
}
void
MacroAssembler::outOfLineTruncateSlow(FloatRegister src, Register dest, bool widenFloatToDouble,
bool compilingWasm)
{
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
if (widenFloatToDouble) {
convertFloat32ToDouble(src, ScratchDoubleReg);
src = ScratchDoubleReg;
}
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
FloatRegister srcSingle;
if (widenFloatToDouble) {
MOZ_ASSERT(src.isSingle());
srcSingle = src;
src = src.asDouble();
push(srcSingle);
convertFloat32ToDouble(srcSingle, src);
}
#else
// Also see below
MOZ_CRASH("MacroAssembler platform hook: outOfLineTruncateSlow");
#endif
MOZ_ASSERT(src.isDouble());
setupUnalignedABICall(dest);
passABIArg(src, MoveOp::DOUBLE);
if (compilingWasm)
callWithABI(wasm::SymbolicAddress::ToInt32);
else
callWithABI(mozilla::BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32));
storeCallResult(dest);
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
// Nothing
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
if (widenFloatToDouble)
pop(srcSingle);
#else
MOZ_CRASH("MacroAssembler platform hook: outOfLineTruncateSlow");
#endif
}
void
MacroAssembler::convertDoubleToInt(FloatRegister src, Register output, FloatRegister temp,
Label* truncateFail, Label* fail,

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

@ -1642,6 +1642,9 @@ class MacroAssembler : public MacroAssemblerSpecific
void convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, FloatRegister output,
Label* fail, MIRType outputType);
void outOfLineTruncateSlow(FloatRegister src, Register dest, bool widenFloatToDouble,
bool compilingAsmJS);
void convertInt32ValueToDouble(const Address& address, Register scratch, Label* done);
void convertValueToDouble(ValueOperand value, FloatRegister output, Label* fail) {
convertValueToFloatingPoint(value, output, fail, MIRType::Double);

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

@ -1398,11 +1398,11 @@ class OutOfLineTruncateSlow : public OutOfLineCodeBase<CodeGeneratorShared>
{
FloatRegister src_;
Register dest_;
bool needFloat32Conversion_;
bool widenFloatToDouble_;
public:
OutOfLineTruncateSlow(FloatRegister src, Register dest, bool needFloat32Conversion = false)
: src_(src), dest_(dest), needFloat32Conversion_(needFloat32Conversion)
OutOfLineTruncateSlow(FloatRegister src, Register dest, bool widenFloatToDouble = false)
: src_(src), dest_(dest), widenFloatToDouble_(widenFloatToDouble)
{ }
void accept(CodeGeneratorShared* codegen) {
@ -1414,8 +1414,8 @@ class OutOfLineTruncateSlow : public OutOfLineCodeBase<CodeGeneratorShared>
Register dest() const {
return dest_;
}
bool needFloat32Conversion() const {
return needFloat32Conversion_;
bool widenFloatToDouble() const {
return widenFloatToDouble_;
}
};
@ -1454,36 +1454,9 @@ CodeGeneratorShared::visitOutOfLineTruncateSlow(OutOfLineTruncateSlow* ool)
Register dest = ool->dest();
saveVolatile(dest);
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
if (ool->needFloat32Conversion()) {
masm.convertFloat32ToDouble(src, ScratchDoubleReg);
src = ScratchDoubleReg;
}
#else
FloatRegister srcSingle = src.asSingle();
if (ool->needFloat32Conversion()) {
MOZ_ASSERT(src.isSingle());
masm.push(src);
masm.convertFloat32ToDouble(src, src);
src = src.asDouble();
}
#endif
masm.setupUnalignedABICall(dest);
masm.passABIArg(src, MoveOp::DOUBLE);
if (gen->compilingAsmJS())
masm.callWithABI(wasm::SymbolicAddress::ToInt32);
else
masm.callWithABI(BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32));
masm.storeCallResult(dest);
#if !defined(JS_CODEGEN_ARM) && !defined(JS_CODEGEN_ARM64)
if (ool->needFloat32Conversion())
masm.pop(srcSingle);
#endif
masm.outOfLineTruncateSlow(src, dest, ool->widenFloatToDouble(), gen->compilingAsmJS());
restoreVolatile(dest);
masm.jump(ool->rejoin());
}

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

@ -4475,63 +4475,7 @@ CodeGeneratorX86Shared::visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateChe
MIRType fromType = ool->fromType();
MIRType toType = ool->toType();
// Eagerly take care of NaNs.
Label inputIsNaN;
if (fromType == MIRType::Double)
masm.branchDouble(Assembler::DoubleUnordered, input, input, &inputIsNaN);
else if (fromType == MIRType::Float32)
masm.branchFloat(Assembler::DoubleUnordered, input, input, &inputIsNaN);
else
MOZ_CRASH("unexpected type in visitOutOfLineWasmTruncateCheck");
Label fail;
// Handle special values (not needed for unsigned values).
if (!ool->isUnsigned()) {
if (toType == MIRType::Int32) {
// MWasmTruncateToInt32
if (fromType == MIRType::Double) {
// We've used vcvttsd2si. The only valid double values that can
// truncate to INT32_MIN are in ]INT32_MIN - 1; INT32_MIN].
masm.loadConstantDouble(double(INT32_MIN) - 1.0, ScratchDoubleReg);
masm.branchDouble(Assembler::DoubleLessThanOrEqual, input, ScratchDoubleReg, &fail);
masm.loadConstantDouble(double(INT32_MIN), ScratchDoubleReg);
masm.branchDouble(Assembler::DoubleGreaterThan, input, ScratchDoubleReg, &fail);
} else {
MOZ_ASSERT(fromType == MIRType::Float32);
// We've used vcvttss2si. Check that the input wasn't
// float(INT32_MIN), which is the only legimitate input that
// would truncate to INT32_MIN.
masm.loadConstantFloat32(float(INT32_MIN), ScratchFloat32Reg);
masm.branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail);
}
} else {
// MWasmTruncateToInt64
MOZ_ASSERT(toType == MIRType::Int64);
if (fromType == MIRType::Double) {
// We've used vcvtsd2sq. The only legit value whose i64
// truncation is INT64_MIN is double(INT64_MIN): exponent is so
// high that the highest resolution around is much more than 1.
masm.loadConstantDouble(double(int64_t(INT64_MIN)), ScratchDoubleReg);
masm.branchDouble(Assembler::DoubleNotEqual, input, ScratchDoubleReg, &fail);
} else {
// We've used vcvtss2sq. Same comment applies.
MOZ_ASSERT(fromType == MIRType::Float32);
masm.loadConstantFloat32(float(int64_t(INT64_MIN)), ScratchFloat32Reg);
masm.branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail);
}
}
masm.jump(ool->rejoin());
}
// Handle errors.
masm.bind(&fail);
masm.jump(wasm::JumpTarget::IntegerOverflow);
masm.bind(&inputIsNaN);
masm.jump(wasm::JumpTarget::InvalidConversionToInteger);
masm.outOfLineWasmTruncateCheck(input, fromType, toType, ool->isUnsigned(), ool->rejoin());
}
void

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

@ -403,6 +403,70 @@ MacroAssemblerX86Shared::minMaxFloat32(FloatRegister first, FloatRegister second
bind(&done);
}
void
MacroAssemblerX86Shared::outOfLineWasmTruncateCheck(FloatRegister input, MIRType fromType,
MIRType toType, bool isUnsigned,
Label* rejoin)
{
// Eagerly take care of NaNs.
Label inputIsNaN;
if (fromType == MIRType::Double)
asMasm().branchDouble(Assembler::DoubleUnordered, input, input, &inputIsNaN);
else if (fromType == MIRType::Float32)
asMasm().branchFloat(Assembler::DoubleUnordered, input, input, &inputIsNaN);
else
MOZ_CRASH("unexpected type in visitOutOfLineWasmTruncateCheck");
Label fail;
// Handle special values (not needed for unsigned values).
if (!isUnsigned) {
if (toType == MIRType::Int32) {
// MWasmTruncateToInt32
if (fromType == MIRType::Double) {
// We've used vcvttsd2si. The only valid double values that can
// truncate to INT32_MIN are in ]INT32_MIN - 1; INT32_MIN].
asMasm().loadConstantDouble(double(INT32_MIN) - 1.0, ScratchDoubleReg);
asMasm().branchDouble(Assembler::DoubleLessThanOrEqual, input, ScratchDoubleReg, &fail);
asMasm().loadConstantDouble(double(INT32_MIN), ScratchDoubleReg);
asMasm().branchDouble(Assembler::DoubleGreaterThan, input, ScratchDoubleReg, &fail);
} else {
MOZ_ASSERT(fromType == MIRType::Float32);
// We've used vcvttss2si. Check that the input wasn't
// float(INT32_MIN), which is the only legimitate input that
// would truncate to INT32_MIN.
asMasm().loadConstantFloat32(float(INT32_MIN), ScratchFloat32Reg);
asMasm().branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail);
}
} else {
// MWasmTruncateToInt64
MOZ_ASSERT(toType == MIRType::Int64);
if (fromType == MIRType::Double) {
// We've used vcvtsd2sq. The only legit value whose i64
// truncation is INT64_MIN is double(INT64_MIN): exponent is so
// high that the highest resolution around is much more than 1.
asMasm().loadConstantDouble(double(int64_t(INT64_MIN)), ScratchDoubleReg);
asMasm().branchDouble(Assembler::DoubleNotEqual, input, ScratchDoubleReg, &fail);
} else {
// We've used vcvtss2sq. Same comment applies.
MOZ_ASSERT(fromType == MIRType::Float32);
asMasm().loadConstantFloat32(float(int64_t(INT64_MIN)), ScratchFloat32Reg);
asMasm().branchFloat(Assembler::DoubleNotEqual, input, ScratchFloat32Reg, &fail);
}
}
jump(rejoin);
}
// Handle errors.
bind(&fail);
jump(wasm::JumpTarget::IntegerOverflow);
bind(&inputIsNaN);
jump(wasm::JumpTarget::InvalidConversionToInteger);
}
//{{{ check_macroassembler_style
// ===============================================================
// MacroAssembler high-level usage.

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

@ -107,6 +107,9 @@ class MacroAssemblerX86Shared : public Assembler
void minMaxDouble(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax);
void minMaxFloat32(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax);
void outOfLineWasmTruncateCheck(FloatRegister input, MIRType fromType, MIRType toType,
bool isUnsigned, Label* rejoin);
void compareDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs) {
if (cond & DoubleConditionBitInvert)
vucomisd(lhs, rhs);