Bug 1393723 - Fix handling of wasm float32/64 <-> u/int64 on mips. r=lth
authorDragan Mladjenovic <dragan.mladjenovic@rt-rk.com>
Tue, 29 Aug 2017 10:04:00 -0400
changeset 377598 330e2e4db3a7
parent 377597 04a30a0ba074
child 377599 b71a2824c224
push id32411
push userkwierso@gmail.com
push dateTue, 29 Aug 2017 23:14:35 +0000
treeherdermozilla-central@db7f19e26e57 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1393723
milestone57.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 1393723 - Fix handling of wasm float32/64 <-> u/int64 on mips. r=lth
js/src/jit/mips-shared/LIR-mips-shared.h
js/src/jit/mips-shared/Lowering-mips-shared.cpp
js/src/jit/mips-shared/Lowering-mips-shared.h
js/src/jit/mips32/CodeGenerator-mips32.cpp
js/src/jit/mips32/LIR-mips32.h
js/src/jit/mips32/Lowering-mips32.cpp
js/src/jit/mips32/Lowering-mips32.h
js/src/jit/mips64/CodeGenerator-mips64.cpp
js/src/jit/mips64/LIR-mips64.h
js/src/jit/mips64/Lowering-mips64.cpp
js/src/jit/mips64/Lowering-mips64.h
--- a/js/src/jit/mips-shared/LIR-mips-shared.h
+++ b/js/src/jit/mips-shared/LIR-mips-shared.h
@@ -279,30 +279,16 @@ class LUDivOrMod : public LBinaryMath<0>
     wasm::BytecodeOffset bytecodeOffset() const {
         MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
         if (mir_->isMod())
             return mir_->toMod()->bytecodeOffset();
         return mir_->toDiv()->bytecodeOffset();
     }
 };
 
-class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 0>
-{
-  public:
-    LIR_HEADER(Int64ToFloatingPoint);
-
-    explicit LInt64ToFloatingPoint(const LInt64Allocation& in) {
-        setInt64Operand(0, in);
-    }
-
-    MInt64ToFloatingPoint* mir() const {
-        return mir_->toInt64ToFloatingPoint();
-    }
-};
-
 namespace details {
 
 // Base class for the int64 and non-int64 variants.
 template<size_t NumDefs>
 class LWasmUnalignedLoadBase : public details::LWasmLoadBase<NumDefs, 2>
 {
   public:
     typedef LWasmLoadBase<NumDefs, 2> Base;
--- a/js/src/jit/mips-shared/Lowering-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Lowering-mips-shared.cpp
@@ -710,34 +710,16 @@ LIRGeneratorMIPSShared::visitAtomicTyped
 
     LAtomicTypedArrayElementBinop* lir =
         new(alloc()) LAtomicTypedArrayElementBinop(elements, index, value, flagTemp, outTemp,
                                                    /* valueTemp= */ temp(), /* offsetTemp= */ temp(),
                                                    /* maskTemp= */ temp());
     define(lir, ins);
 }
 
-void
-LIRGeneratorMIPSShared::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins)
-{
-    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)
-{
-    MDefinition* opd = ins->input();
-    MOZ_ASSERT(opd->type() == MIRType::Int64);
-    MOZ_ASSERT(IsFloatingPointType(ins->type()));
-
-    define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
-}
 
 void
 LIRGeneratorMIPSShared::visitCopySign(MCopySign* ins)
 {
     MDefinition* lhs = ins->lhs();
     MDefinition* rhs = ins->rhs();
 
     MOZ_ASSERT(IsFloatingPointType(lhs->type()));
--- a/js/src/jit/mips-shared/Lowering-mips-shared.h
+++ b/js/src/jit/mips-shared/Lowering-mips-shared.h
@@ -90,18 +90,16 @@ class LIRGeneratorMIPSShared : public LI
     void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins);
     void visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins);
     void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins);
     void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins);
     void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins);
     void visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins);
     void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins);
     void visitSubstr(MSubstr* ins);
-    void visitWasmTruncateToInt64(MWasmTruncateToInt64* ins);
-    void visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins);
     void visitCopySign(MCopySign* ins);
     void visitExtendInt32ToInt64(MExtendInt32ToInt64* ins);
     void visitSignExtendInt64(MSignExtendInt64* ins);
 
 };
 
 } // namespace jit
 } // namespace js
--- a/js/src/jit/mips32/CodeGenerator-mips32.cpp
+++ b/js/src/jit/mips32/CodeGenerator-mips32.cpp
@@ -733,22 +733,27 @@ CodeGeneratorMIPS::visitWasmTruncateToIn
     } else if (fromType == MIRType::Float32) {
         masm.branchFloat(Assembler::DoubleUnordered, input, input, ool->entry());
         scratch = ScratchDoubleReg;
         masm.convertFloat32ToDouble(input, scratch);
     } else {
         MOZ_CRASH("unexpected type in visitOutOfLineWasmTruncateCheck");
     }
 
-    masm.setupUnalignedABICall(output.high);
+    masm.Push(input);
+
+    masm.setupWasmABICall();
     masm.passABIArg(scratch, MoveOp::DOUBLE);
     if (lir->mir()->isUnsigned())
         masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::TruncateDoubleToUint64);
     else
         masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::TruncateDoubleToInt64);
+
+    masm.Pop(input);
+
     masm.ma_b(output.high, Imm32(0x80000000), ool->rejoin(), Assembler::NotEqual);
     masm.ma_b(output.low, Imm32(0x00000000), ool->rejoin(), Assembler::NotEqual);
     masm.ma_b(ool->entry());
 
     masm.bind(ool->rejoin());
 
     MOZ_ASSERT(ReturnReg64 == output);
 }
@@ -762,30 +767,33 @@ CodeGeneratorMIPS::visitInt64ToFloatingP
     MInt64ToFloatingPoint* mir = lir->mir();
     MIRType toType = mir->type();
 
     AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
     regs.take(input.low);
     regs.take(input.high);
     Register temp = regs.takeAny();
 
-    masm.setupUnalignedABICall(temp);
+    masm.setupWasmABICall();
     masm.passABIArg(input.high);
     masm.passABIArg(input.low);
 
     if (lir->mir()->isUnsigned())
-        masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::Uint64ToDouble, MoveOp::DOUBLE);
+        if (toType == MIRType::Double)
+            masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::Uint64ToDouble, MoveOp::DOUBLE);
+        else
+            masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::Uint64ToFloat32, MoveOp::FLOAT32);
     else
-        masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::Int64ToDouble, MoveOp::DOUBLE);
+        if (toType == MIRType::Double)
+            masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::Int64ToDouble, MoveOp::DOUBLE);
+        else
+            masm.callWithABI(mir->bytecodeOffset(), wasm::SymbolicAddress::Int64ToFloat32, MoveOp::FLOAT32);
 
     MOZ_ASSERT_IF(toType == MIRType::Double, output == ReturnDoubleReg);
-    if (toType == MIRType::Float32) {
-         MOZ_ASSERT(output == ReturnFloat32Reg);
-         masm.convertDoubleToFloat32(ReturnDoubleReg, output);
-    }
+    MOZ_ASSERT_IF(toType == MIRType::Float32, output == ReturnFloat32Reg);
 }
 
 void
 CodeGeneratorMIPS::visitTestI64AndBranch(LTestI64AndBranch* lir)
 {
     Register64 input = ToRegister64(lir->getInt64Operand(0));
 
     branchToBlock(input.high, Imm32(0), lir->ifTrue(), Assembler::NonZero);
--- a/js/src/jit/mips32/LIR-mips32.h
+++ b/js/src/jit/mips32/LIR-mips32.h
@@ -158,12 +158,27 @@ class LWasmTruncateToInt64 : public LCal
         setOperand(0, in);
     }
 
     MWasmTruncateToInt64* mir() const {
         return mir_->toWasmTruncateToInt64();
     }
 };
 
+class LInt64ToFloatingPoint : public LCallInstructionHelper<1, INT64_PIECES, 0>
+{
+  public:
+    LIR_HEADER(Int64ToFloatingPoint);
+
+    explicit LInt64ToFloatingPoint(const LInt64Allocation& in) {
+        setInt64Operand(0, in);
+    }
+
+    MInt64ToFloatingPoint* mir() const {
+        return mir_->toInt64ToFloatingPoint();
+    }
+};
+
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips32_LIR_mips32_h */
--- a/js/src/jit/mips32/Lowering-mips32.cpp
+++ b/js/src/jit/mips32/Lowering-mips32.cpp
@@ -251,8 +251,28 @@ LIRGeneratorMIPS::visitRandom(MRandom* i
 {
     LRandom *lir = new(alloc()) LRandom(temp(),
                                         temp(),
                                         temp(),
                                         temp(),
                                         temp());
     defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
 }
+
+
+void
+LIRGeneratorMIPS::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins)
+{
+    MDefinition* opd = ins->input();
+    MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
+
+    defineReturn(new(alloc()) LWasmTruncateToInt64(useRegisterAtStart(opd)), ins);
+}
+
+void
+LIRGeneratorMIPS::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
+{
+    MDefinition* opd = ins->input();
+    MOZ_ASSERT(opd->type() == MIRType::Int64);
+    MOZ_ASSERT(IsFloatingPointType(ins->type()));
+
+    defineReturn(new(alloc()) LInt64ToFloatingPoint(useInt64RegisterAtStart(opd)), ins);
+}
\ No newline at end of file
--- a/js/src/jit/mips32/Lowering-mips32.h
+++ b/js/src/jit/mips32/Lowering-mips32.h
@@ -42,16 +42,18 @@ class LIRGeneratorMIPS : public LIRGener
     void lowerUDivI64(MDiv* div);
     void lowerUModI64(MMod* mod);
 
   public:
     void visitBox(MBox* box);
     void visitUnbox(MUnbox* unbox);
     void visitReturn(MReturn* ret);
     void visitRandom(MRandom* ins);
+    void visitWasmTruncateToInt64(MWasmTruncateToInt64* ins);
+    void visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins);
 };
 
 typedef LIRGeneratorMIPS LIRGeneratorSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips32_Lowering_mips32_h */
--- a/js/src/jit/mips64/CodeGenerator-mips64.cpp
+++ b/js/src/jit/mips64/CodeGenerator-mips64.cpp
@@ -659,17 +659,18 @@ CodeGeneratorMIPS64::visitWasmTruncateTo
                          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);
+        // extract invalid operation flag (bit 6) from FCSR
+        masm.as_ext(ScratchRegister, ScratchRegister, 6, 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);
@@ -679,17 +680,17 @@ CodeGeneratorMIPS64::visitWasmTruncateTo
         } 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.as_ext(ScratchRegister, ScratchRegister, 6, 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);
@@ -700,17 +701,17 @@ CodeGeneratorMIPS64::visitWasmTruncateTo
     // 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.as_ext(output, output, 6, 1);
     masm.ma_b(output, Imm32(0), ool->entry(), Assembler::NotEqual);
 
     masm.bind(ool->rejoin());
     masm.moveFromDouble(ScratchDoubleReg, output);
 }
 
 void
 CodeGeneratorMIPS64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
--- a/js/src/jit/mips64/LIR-mips64.h
+++ b/js/src/jit/mips64/LIR-mips64.h
@@ -129,12 +129,26 @@ class LWasmTruncateToInt64 : public LIns
         setOperand(0, in);
     }
 
     MWasmTruncateToInt64* mir() const {
         return mir_->toWasmTruncateToInt64();
     }
 };
 
+class LInt64ToFloatingPoint : public LInstructionHelper<1, 1, 0>
+{
+  public:
+    LIR_HEADER(Int64ToFloatingPoint);
+
+    explicit LInt64ToFloatingPoint(const LInt64Allocation& in) {
+        setInt64Operand(0, in);
+    }
+
+    MInt64ToFloatingPoint* mir() const {
+        return mir_->toInt64ToFloatingPoint();
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips64_LIR_mips64_h */
--- a/js/src/jit/mips64/Lowering-mips64.cpp
+++ b/js/src/jit/mips64/Lowering-mips64.cpp
@@ -177,8 +177,28 @@ LIRGeneratorMIPS64::lowerTruncateFToInt3
 }
 
 void
 LIRGeneratorMIPS64::visitRandom(MRandom* ins)
 {
     LRandom *lir = new(alloc()) LRandom(temp(), temp(), temp());
     defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
 }
+
+
+void
+LIRGeneratorMIPS64::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins)
+{
+    MDefinition* opd = ins->input();
+    MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
+
+    defineInt64(new(alloc()) LWasmTruncateToInt64(useRegister(opd)), ins);
+}
+
+void
+LIRGeneratorMIPS64::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
+{
+    MDefinition* opd = ins->input();
+    MOZ_ASSERT(opd->type() == MIRType::Int64);
+    MOZ_ASSERT(IsFloatingPointType(ins->type()));
+
+    define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
+}
\ No newline at end of file
--- a/js/src/jit/mips64/Lowering-mips64.h
+++ b/js/src/jit/mips64/Lowering-mips64.h
@@ -42,16 +42,18 @@ class LIRGeneratorMIPS64 : public LIRGen
     void lowerUDivI64(MDiv* div);
     void lowerUModI64(MMod* mod);
 
   public:
     void visitBox(MBox* box);
     void visitUnbox(MUnbox* unbox);
     void visitReturn(MReturn* ret);
     void visitRandom(MRandom* ins);
+    void visitWasmTruncateToInt64(MWasmTruncateToInt64* ins);
+    void visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins);
 };
 
 typedef LIRGeneratorMIPS64 LIRGeneratorSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips64_Lowering_mips64_h */