mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Bug 919838: Specialize ToInt32 for Float32; r=sstangl
This commit is contained in:
parent
009454da8e
commit
c5f86b8e06
@ -2459,6 +2459,13 @@ public:
|
||||
m_formatter.twoByteOp(OP2_MOVMSKPD_EdVd, dst, (RegisterID)src);
|
||||
}
|
||||
|
||||
void movmskps_rr(XMMRegisterID src, RegisterID dst)
|
||||
{
|
||||
spew("movmskps %s, %s",
|
||||
nameFPReg(src), nameIReg(dst));
|
||||
m_formatter.twoByteOp(OP2_MOVMSKPD_EdVd, dst, (RegisterID)src);
|
||||
}
|
||||
|
||||
void ptest_rr(XMMRegisterID lhs, XMMRegisterID rhs) {
|
||||
spew("ptest %s, %s",
|
||||
nameFPReg(lhs), nameFPReg(rhs));
|
||||
|
@ -361,6 +361,18 @@ CodeGenerator::visitDoubleToInt32(LDoubleToInt32 *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitFloat32ToInt32(LFloat32ToInt32 *lir)
|
||||
{
|
||||
Label fail;
|
||||
FloatRegister input = ToFloatRegister(lir->input());
|
||||
Register output = ToRegister(lir->output());
|
||||
masm.convertFloat32ToInt32(input, output, &fail, lir->mir()->canBeNegativeZero());
|
||||
if (!bailoutFrom(&fail, lir->snapshot()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::emitOOLTestObject(Register objreg, Label *ifTruthy, Label *ifFalsy, Register scratch)
|
||||
{
|
||||
|
@ -120,6 +120,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitFilterArguments(LFilterArguments *lir);
|
||||
bool visitCallDirectEval(LCallDirectEval *lir);
|
||||
bool visitDoubleToInt32(LDoubleToInt32 *lir);
|
||||
bool visitFloat32ToInt32(LFloat32ToInt32 *lir);
|
||||
bool visitNewSlots(LNewSlots *lir);
|
||||
bool visitNewParallelArrayVMCall(LNewParallelArray *lir);
|
||||
bool visitNewParallelArray(LNewParallelArray *lir);
|
||||
|
@ -2672,6 +2672,23 @@ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a float32 to an int32.
|
||||
// Input: floating-point register
|
||||
// Output: 32-bit integer
|
||||
// Bailout: if the float32 cannot be converted to an integer.
|
||||
class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(Float32ToInt32)
|
||||
|
||||
LFloat32ToInt32(const LAllocation &in) {
|
||||
setOperand(0, in);
|
||||
}
|
||||
|
||||
MToInt32 *mir() const {
|
||||
return mir_->toToInt32();
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a double to a truncated int32.
|
||||
// Input: floating-point register
|
||||
|
@ -127,6 +127,7 @@
|
||||
_(ValueToInt32) \
|
||||
_(ValueToFloat32) \
|
||||
_(DoubleToInt32) \
|
||||
_(Float32ToInt32) \
|
||||
_(TruncateDToInt32) \
|
||||
_(IntToString) \
|
||||
_(DoubleToString) \
|
||||
|
@ -1670,6 +1670,12 @@ LIRGenerator::visitToInt32(MToInt32 *convert)
|
||||
case MIRType_Boolean:
|
||||
return redefine(convert, opd);
|
||||
|
||||
case MIRType_Float32:
|
||||
{
|
||||
LFloat32ToInt32 *lir = new LFloat32ToInt32(useRegister(opd));
|
||||
return assignSnapshot(lir) && define(lir, convert);
|
||||
}
|
||||
|
||||
case MIRType_Double:
|
||||
{
|
||||
LDoubleToInt32 *lir = new LDoubleToInt32(useRegister(opd));
|
||||
|
@ -2849,9 +2849,7 @@ class MAsmJSUnsignedToDouble
|
||||
// Converts a primitive (either typed or untyped) to an int32. If the input is
|
||||
// not primitive at runtime, a bailout occurs. If the input cannot be converted
|
||||
// to an int32 without loss (i.e. "5.5" or undefined) then a bailout occurs.
|
||||
class MToInt32
|
||||
: public MUnaryInstruction,
|
||||
public NoFloatPolicy<0>
|
||||
class MToInt32 : public MUnaryInstruction
|
||||
{
|
||||
bool canBeNegativeZero_;
|
||||
|
||||
@ -2891,9 +2889,9 @@ class MToInt32
|
||||
}
|
||||
void computeRange();
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
bool isConsistentFloat32Use() const { return true; }
|
||||
#endif
|
||||
};
|
||||
|
||||
// Converts a value or typed input to a truncated int32, for use with bitwise
|
||||
|
@ -116,6 +116,34 @@ MacroAssemblerARM::convertDoubleToInt32(const FloatRegister &src, const Register
|
||||
}
|
||||
}
|
||||
|
||||
// Checks whether a float32 is representable as a 32-bit integer. If so, the
|
||||
// integer is written to the output register. Otherwise, a bailout is taken to
|
||||
// the given snapshot. This function overwrites the scratch float register.
|
||||
void
|
||||
MacroAssemblerARM::convertFloat32ToInt32(const FloatRegister &src, const Register &dest, Label *fail, bool negativeZeroCheck)
|
||||
{
|
||||
// convert the floating point value to an integer, if it did not fit,
|
||||
// then when we convert it *back* to a float, it will have a
|
||||
// different value, which we can test.
|
||||
ma_vcvt_F32_I32(src, ScratchFloatReg);
|
||||
// move the value into the dest register.
|
||||
ma_vxfer(ScratchFloatReg, dest);
|
||||
ma_vcvt_I32_F32(ScratchFloatReg, ScratchFloatReg);
|
||||
ma_vcmp_f32(src, ScratchFloatReg);
|
||||
as_vmrs(pc);
|
||||
ma_b(fail, Assembler::VFP_NotEqualOrUnordered);
|
||||
|
||||
if (negativeZeroCheck) {
|
||||
ma_cmp(dest, Imm32(0));
|
||||
// Test and bail for -0.0, when integer result is 0
|
||||
// Move the top word of the double into the output reg, if it is non-zero,
|
||||
// then the original value was -0.0
|
||||
as_vxfer(dest, InvalidReg, src, FloatToCore, Assembler::Equal, 0);
|
||||
ma_cmp(dest, Imm32(0x80000000), Assembler::Equal);
|
||||
ma_b(fail, Assembler::Equal);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARM::convertFloatToDouble(const FloatRegister &src, const FloatRegister &dest) {
|
||||
as_vcvt(VFPRegister(dest), VFPRegister(src).singleOverlay());
|
||||
@ -1486,6 +1514,11 @@ MacroAssemblerARM::ma_vcmp(FloatRegister src1, FloatRegister src2, Condition cc)
|
||||
as_vcmp(VFPRegister(src1), VFPRegister(src2), cc);
|
||||
}
|
||||
void
|
||||
MacroAssemblerARM::ma_vcmp_f32(FloatRegister src1, FloatRegister src2, Condition cc)
|
||||
{
|
||||
as_vcmp(VFPRegister(src1).singleOverlay(), VFPRegister(src2).singleOverlay(), cc);
|
||||
}
|
||||
void
|
||||
MacroAssemblerARM::ma_vcmpz(FloatRegister src1, Condition cc)
|
||||
{
|
||||
as_vcmpz(VFPRegister(src1), cc);
|
||||
|
@ -53,6 +53,8 @@ class MacroAssemblerARM : public Assembler
|
||||
void branchTruncateDouble(const FloatRegister &src, const Register &dest, Label *fail);
|
||||
void convertDoubleToInt32(const FloatRegister &src, const Register &dest, Label *fail,
|
||||
bool negativeZeroCheck = true);
|
||||
void convertFloat32ToInt32(const FloatRegister &src, const Register &dest, Label *fail,
|
||||
bool negativeZeroCheck = true);
|
||||
|
||||
void convertFloatToDouble(const FloatRegister &src, const FloatRegister &dest);
|
||||
void branchTruncateFloat32(const FloatRegister &src, const Register &dest, Label *fail);
|
||||
@ -322,6 +324,7 @@ class MacroAssemblerARM : public Assembler
|
||||
void ma_vimm_f32(float value, FloatRegister dest, Condition cc = Always);
|
||||
|
||||
void ma_vcmp(FloatRegister src1, FloatRegister src2, Condition cc = Always);
|
||||
void ma_vcmp_f32(FloatRegister src1, FloatRegister src2, Condition cc = Always);
|
||||
void ma_vcmpz(FloatRegister src1, Condition cc = Always);
|
||||
|
||||
void ma_vadd_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst);
|
||||
|
@ -1303,6 +1303,10 @@ class AssemblerX86Shared
|
||||
JS_ASSERT(HasSSE2());
|
||||
masm.movmskpd_rr(src.code(), dest.code());
|
||||
}
|
||||
void movmskps(const FloatRegister &src, const Register &dest) {
|
||||
JS_ASSERT(HasSSE2());
|
||||
masm.movmskps_rr(src.code(), dest.code());
|
||||
}
|
||||
void ptest(const FloatRegister &lhs, const FloatRegister &rhs) {
|
||||
JS_ASSERT(HasSSE41());
|
||||
masm.ptest_rr(rhs.code(), lhs.code());
|
||||
|
@ -457,6 +457,38 @@ class MacroAssemblerX86Shared : public Assembler
|
||||
}
|
||||
}
|
||||
|
||||
// Checks whether a float32 is representable as a 32-bit integer. If so, the
|
||||
// integer is written to the output register. Otherwise, a bailout is taken to
|
||||
// the given snapshot. This function overwrites the scratch float register.
|
||||
void convertFloat32ToInt32(FloatRegister src, Register dest, Label *fail,
|
||||
bool negativeZeroCheck = true)
|
||||
{
|
||||
cvttss2si(src, dest);
|
||||
convertInt32ToFloat32(dest, ScratchFloatReg);
|
||||
ucomiss(src, ScratchFloatReg);
|
||||
j(Assembler::Parity, fail);
|
||||
j(Assembler::NotEqual, fail);
|
||||
|
||||
// Check for -0
|
||||
if (negativeZeroCheck) {
|
||||
Label notZero;
|
||||
branchTest32(Assembler::NonZero, dest, dest, ¬Zero);
|
||||
|
||||
if (Assembler::HasSSE41()) {
|
||||
ptest(src, src);
|
||||
j(Assembler::NonZero, fail);
|
||||
} else {
|
||||
// bit 0 = sign of low float
|
||||
// bits 1 to 3 = signs of higher floats
|
||||
movmskps(src, dest);
|
||||
andl(Imm32(1), dest);
|
||||
j(Assembler::NonZero, fail);
|
||||
}
|
||||
|
||||
bind(¬Zero);
|
||||
}
|
||||
}
|
||||
|
||||
void clampIntToUint8(Register reg) {
|
||||
Label inRange;
|
||||
branchTest32(Assembler::Zero, reg, Imm32(0xffffff00), &inRange);
|
||||
|
Loading…
Reference in New Issue
Block a user