зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1232205 - Wasm baseline: Factor outOfLineWasmTruncateCheck and outOfLineTruncateSlow, on x86-shared. r=bbouvier
--HG-- extra : rebase_source : 06266204a20175e6939be925869c1cdcb5159d74
This commit is contained in:
Родитель
8ec23c07dd
Коммит
9af7246a47
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче