Bug 1290812 - Part 16: Implement the 64bit variant of WasmTruncate on mips64. r=sunfish
authorHeiher <r@hev.cc>
Mon, 10 Oct 2016 17:08:09 +0800
changeset 317290 f9c6f59159cb6078eed717084ec1db755cb706a5
parent 317289 abd901d0835607fedae61175ade0793c7d6fad47
child 317291 df97fdf6e985ef2d54c5607d9498be33d5930d48
push id30800
push userphilringnalda@gmail.com
push dateTue, 11 Oct 2016 02:08:53 +0000
treeherdermozilla-central@ece56e142a1e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish
bugs1290812
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1290812 - Part 16: Implement the 64bit variant of WasmTruncate on mips64. r=sunfish --- js/src/jit/mips-shared/Lowering-mips-shared.cpp | 5 +- js/src/jit/mips64/CodeGenerator-mips64.cpp | 82 +++++++++++++++++++++++++ js/src/jit/mips64/CodeGenerator-mips64.h | 1 + js/src/jit/mips64/LIR-mips64.h | 14 +++++ js/src/jit/mips64/LOpcodes-mips64.h | 3 +- 5 files changed, 103 insertions(+), 2 deletions(-)
js/src/jit/mips-shared/Lowering-mips-shared.cpp
js/src/jit/mips64/CodeGenerator-mips64.cpp
js/src/jit/mips64/CodeGenerator-mips64.h
js/src/jit/mips64/LIR-mips64.h
js/src/jit/mips64/LOpcodes-mips64.h
--- a/js/src/jit/mips-shared/Lowering-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Lowering-mips-shared.cpp
@@ -637,17 +637,20 @@ LIRGeneratorMIPSShared::visitAtomicTyped
                                                    /* valueTemp= */ temp(), /* offsetTemp= */ temp(),
                                                    /* maskTemp= */ temp());
     define(lir, ins);
 }
 
 void
 LIRGeneratorMIPSShared::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins)
 {
-    MOZ_CRASH("NYI");
+    MDefinition* opd = ins->input();
+    MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
+
+    defineInt64(new(alloc()) LWasmTruncateToInt64(useRegister(opd)), ins);
 }
 
 void
 LIRGeneratorMIPSShared::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
 {
     MOZ_CRASH("NYI");
 }
 
--- a/js/src/jit/mips64/CodeGenerator-mips64.cpp
+++ b/js/src/jit/mips64/CodeGenerator-mips64.cpp
@@ -525,16 +525,98 @@ CodeGeneratorMIPS64::visitNotI64(LNotI64
 {
     Register64 input = ToRegister64(lir->getInt64Operand(0));
     Register output = ToRegister(lir->output());
 
     masm.cmp64Set(Assembler::Equal, input.reg, Imm32(0), output);
 }
 
 void
+CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
+{
+    FloatRegister input = ToFloatRegister(lir->input());
+    Register output = ToRegister(lir->output());
+
+    MWasmTruncateToInt64* mir = lir->mir();
+    MIRType fromType = mir->input()->type();
+
+    MOZ_ASSERT(fromType == MIRType::Double || fromType == MIRType::Float32);
+
+    auto* ool = new (alloc()) OutOfLineWasmTruncateCheck(mir, input);
+    addOutOfLineCode(ool, mir);
+
+    if (mir->isUnsigned()) {
+        Label isLarge, done;
+
+        if (fromType == MIRType::Double) {
+            masm.loadConstantDouble(double(INT64_MAX), ScratchDoubleReg);
+            masm.ma_bc1d(ScratchDoubleReg, input, &isLarge,
+                         Assembler::DoubleLessThanOrEqual, ShortJump);
+
+            masm.as_truncld(ScratchDoubleReg, input);
+        } else {
+            masm.loadConstantFloat32(float(INT64_MAX), ScratchFloat32Reg);
+            masm.ma_bc1s(ScratchFloat32Reg, input, &isLarge,
+                         Assembler::DoubleLessThanOrEqual, ShortJump);
+
+            masm.as_truncls(ScratchDoubleReg, input);
+        }
+
+        // Check that the result is in the uint64_t range.
+        masm.moveFromDouble(ScratchDoubleReg, output);
+        masm.as_cfc1(ScratchRegister, Assembler::FCSR);
+        masm.as_ext(ScratchRegister, ScratchRegister, 16, 1);
+        masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
+        masm.ma_or(SecondScratchReg, ScratchRegister);
+        masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
+
+        masm.ma_b(&done, ShortJump);
+
+        // The input is greater than double(INT64_MAX).
+        masm.bind(&isLarge);
+        if (fromType == MIRType::Double) {
+            masm.as_subd(ScratchDoubleReg, input, ScratchDoubleReg);
+            masm.as_truncld(ScratchDoubleReg, ScratchDoubleReg);
+        } else {
+            masm.as_subs(ScratchDoubleReg, input, ScratchDoubleReg);
+            masm.as_truncls(ScratchDoubleReg, ScratchDoubleReg);
+        }
+
+        // Check that the result is in the uint64_t range.
+        masm.moveFromDouble(ScratchDoubleReg, output);
+        masm.as_cfc1(ScratchRegister, Assembler::FCSR);
+        masm.as_ext(ScratchRegister, ScratchRegister, 16, 1);
+        masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
+        masm.ma_or(SecondScratchReg, ScratchRegister);
+        masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
+
+        masm.ma_li(ScratchRegister, Imm32(1));
+        masm.ma_dins(output, ScratchRegister, Imm32(63), Imm32(1));
+
+        masm.bind(&done);
+        return;
+    }
+
+    // When the input value is Infinity, NaN, or rounds to an integer outside the
+    // range [INT64_MIN; INT64_MAX + 1[, the Invalid Operation flag is set in the FCSR.
+    if (fromType == MIRType::Double)
+        masm.as_truncld(ScratchDoubleReg, input);
+    else
+        masm.as_truncls(ScratchDoubleReg, input);
+
+    // Check that the result is in the int64_t range.
+    masm.as_cfc1(output, Assembler::FCSR);
+    masm.as_ext(output, output, 16, 1);
+    masm.ma_b(output, Imm32(0), ool->entry(), Assembler::NotEqual);
+
+    masm.bind(ool->rejoin());
+    masm.moveFromDouble(ScratchDoubleReg, output);
+}
+
+void
 CodeGeneratorMIPS64::setReturnDoubleRegs(LiveRegisterSet* regs)
 {
     MOZ_ASSERT(ReturnFloat32Reg.reg_ == FloatRegisters::f0);
     MOZ_ASSERT(ReturnDoubleReg.reg_ == FloatRegisters::f0);
     FloatRegister f1 = { FloatRegisters::f1, FloatRegisters::Single };
     regs->add(ReturnFloat32Reg);
     regs->add(f1);
     regs->add(ReturnDoubleReg);
--- a/js/src/jit/mips64/CodeGenerator-mips64.h
+++ b/js/src/jit/mips64/CodeGenerator-mips64.h
@@ -52,16 +52,17 @@ class CodeGeneratorMIPS64 : public CodeG
     void visitAsmSelectI64(LAsmSelectI64* ins);
     void visitAsmReinterpretFromI64(LAsmReinterpretFromI64* lir);
     void visitAsmReinterpretToI64(LAsmReinterpretToI64* lir);
     void visitExtendInt32ToInt64(LExtendInt32ToInt64* lir);
     void visitWrapInt64ToInt32(LWrapInt64ToInt32* lir);
     void visitClzI64(LClzI64* lir);
     void visitCtzI64(LCtzI64* lir);
     void visitNotI64(LNotI64* lir);
+    void visitWasmTruncateToInt64(LWasmTruncateToInt64* lir);
 
     // Out of line visitors.
     void visitOutOfLineBailout(OutOfLineBailout* ool);
     void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool);
   protected:
     ValueOperand ToValue(LInstruction* ins, size_t pos);
     ValueOperand ToOutValue(LInstruction* ins);
     ValueOperand ToTempValue(LInstruction* ins, size_t pos);
--- a/js/src/jit/mips64/LIR-mips64.h
+++ b/js/src/jit/mips64/LIR-mips64.h
@@ -103,12 +103,26 @@ class LUDivOrModI64 : public LBinaryMath
 
     bool canBeDivideByZero() const {
         if (mir_->isMod())
             return mir_->toMod()->canBeDivideByZero();
         return mir_->toDiv()->canBeDivideByZero();
     }
 };
 
+class LWasmTruncateToInt64 : public LInstructionHelper<1, 1, 0>
+{
+  public:
+    LIR_HEADER(WasmTruncateToInt64);
+
+    explicit LWasmTruncateToInt64(const LAllocation& in) {
+        setOperand(0, in);
+    }
+
+    MWasmTruncateToInt64* mir() const {
+        return mir_->toWasmTruncateToInt64();
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips64_LIR_mips64_h */
--- a/js/src/jit/mips64/LOpcodes-mips64.h
+++ b/js/src/jit/mips64/LOpcodes-mips64.h
@@ -8,11 +8,12 @@
 #define jit_mips64_LOpcodes_mips64_h__
 
 #include "jit/shared/LOpcodes-shared.h"
 
 #define LIR_CPU_OPCODE_LIST(_)  \
     _(ModMaskI)                 \
     _(DivOrModI64)              \
     _(UDivOrMod)                \
-    _(UDivOrModI64)
+    _(UDivOrModI64)             \
+    _(WasmTruncateToInt64)
 
 #endif // jit_mips64_LOpcodes_mips64_h__