Bug 1129148 - Wrote a MACRO to generate conditions to inline SIMD instructions (sub, mul, and, or, xor). r=nbp
authorVictor Carlquist <victorcarlquist@gmail.com>
Tue, 10 Feb 2015 12:50:42 -0200
changeset 228598 42a06f4f0de9e8b2bfac94bafee684287b495de8
parent 228597 f0e72019665369fa87ec61ad984c3f0fa42fcab4
child 228599 1b3b467f1df502c15a336452ef8a6a4748a2e888
push id28264
push usercbook@mozilla.com
push dateWed, 11 Feb 2015 13:58:35 +0000
treeherdermozilla-central@38058cb42a0e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1129148
milestone38.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 1129148 - Wrote a MACRO to generate conditions to inline SIMD instructions (sub, mul, and, or, xor). r=nbp
js/src/asmjs/AsmJSValidate.cpp
js/src/builtin/SIMD.h
js/src/jit/BaselineIC.cpp
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.h
js/src/jit/shared/CodeGenerator-x86-shared.cpp
js/src/jit/shared/Lowering-x86-shared.cpp
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -5847,32 +5847,22 @@ static bool
 CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Global *global,
                        MDefinition **def, Type *type)
 {
     MOZ_ASSERT(global->isSimdOperation());
 
     AsmJSSimdType opType = global->simdOperationType();
 
     switch (global->simdOperation()) {
-      case AsmJSSimdOperation_add:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Add, def, type);
-      case AsmJSSimdOperation_sub:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Sub, def, type);
-      case AsmJSSimdOperation_mul:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Mul, def, type);
-      case AsmJSSimdOperation_div:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Div, def, type);
-      case AsmJSSimdOperation_max:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Max, def, type);
-      case AsmJSSimdOperation_min:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Min, def, type);
-      case AsmJSSimdOperation_maxNum:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::MaxNum, def, type);
-      case AsmJSSimdOperation_minNum:
-        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::MinNum, def, type);
+#define OP_CHECK_CASE_LIST_(OP)                                                         \
+      case AsmJSSimdOperation_##OP:                                                     \
+        return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Op_##OP, def, type);
+      ARITH_COMMONX4_SIMD_OP(OP_CHECK_CASE_LIST_)
+      ARITH_FLOAT32X4_SIMD_OP(OP_CHECK_CASE_LIST_)
+#undef OP_CHECK_CASE_LIST_
 
       case AsmJSSimdOperation_lessThan:
         return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThan, def, type);
       case AsmJSSimdOperation_lessThanOrEqual:
         return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThanOrEqual, def, type);
       case AsmJSSimdOperation_equal:
         return CheckSimdBinary(f, call, opType, MSimdBinaryComp::equal, def, type);
       case AsmJSSimdOperation_notEqual:
--- a/js/src/builtin/SIMD.h
+++ b/js/src/builtin/SIMD.h
@@ -185,41 +185,47 @@
   INT32X4_SHUFFLE_FUNCTION_LIST(V)
 
 #define FOREACH_INT32X4_SIMD_OP(_)   \
     _(fromFloat32x4)                 \
     _(fromFloat32x4Bits)             \
     _(shiftLeftByScalar)             \
     _(shiftRightArithmeticByScalar)  \
     _(shiftRightLogicalByScalar)
+#define ARITH_FLOAT32X4_SIMD_OP(_)   \
+    _(div)                           \
+    _(max)                           \
+    _(min)                           \
+    _(maxNum)                        \
+    _(minNum)
 #define FOREACH_FLOAT32X4_SIMD_OP(_) \
+    ARITH_FLOAT32X4_SIMD_OP(_)       \
     _(abs)                           \
     _(sqrt)                          \
     _(reciprocal)                    \
     _(reciprocalSqrt)                \
     _(fromInt32x4)                   \
-    _(fromInt32x4Bits)               \
-    _(div)                           \
-    _(max)                           \
-    _(min)                           \
-    _(maxNum)                        \
-    _(minNum)
-#define FOREACH_COMMONX4_SIMD_OP(_)  \
+    _(fromInt32x4Bits)
+#define ARITH_COMMONX4_SIMD_OP(_)    \
     _(add)                           \
     _(sub)                           \
-    _(mul)                           \
+    _(mul)
+#define BITWISE_COMMONX4_SIMD_OP(_)  \
+    _(and)                           \
+    _(or)                            \
+    _(xor)
+#define FOREACH_COMMONX4_SIMD_OP(_)  \
+    ARITH_COMMONX4_SIMD_OP(_)        \
+    BITWISE_COMMONX4_SIMD_OP(_)      \
     _(lessThan)                      \
     _(lessThanOrEqual)               \
     _(equal)                         \
     _(notEqual)                      \
     _(greaterThan)                   \
     _(greaterThanOrEqual)            \
-    _(and)                           \
-    _(or)                            \
-    _(xor)                           \
     _(bitselect)                     \
     _(select)                        \
     _(swizzle)                       \
     _(shuffle)                       \
     _(splat)                         \
     _(withX)                         \
     _(withY)                         \
     _(withZ)                         \
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -9162,23 +9162,28 @@ GetTemplateObjectForNative(JSContext *cx
         RootedObject proto(cx, args[0].toObjectOrNull());
         res.set(ObjectCreateImpl(cx, proto, TenuredObject));
         if (!res)
             return false;
         return true;
     }
 
     if (JitSupportsSimd()) {
-        if (native == js::simd_int32x4_add || native == js::simd_int32x4_and) {
+#define ADD_INT32X4_SIMD_OP_NAME_(OP) || native == js::simd_int32x4_##OP
+       if (false
+           ARITH_COMMONX4_SIMD_OP(ADD_INT32X4_SIMD_OP_NAME_)
+           BITWISE_COMMONX4_SIMD_OP(ADD_INT32X4_SIMD_OP_NAME_))
+       {
             Rooted<TypeDescr *> descr(cx, &Int32x4::GetTypeDescr(*cx->global()));
             res.set(TypedObject::createZeroed(cx, descr, 0, gc::TenuredHeap));
             if (!res)
                 return false;
             return true;
-        }
+       }
+#undef ADD_INT32X4_SIMD_OP_NAME_
     }
 
     return true;
 }
 
 static bool
 GetTemplateObjectForClassHook(JSContext *cx, JSNative hook, CallArgs &args,
                               MutableHandleObject templateObject)
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -252,20 +252,27 @@ IonBuilder::inlineNativeCall(CallInfo &c
     if (native == testingFunc_assertFloat32)
         return inlineAssertFloat32(callInfo);
 
     // Bound function
     if (native == js::CallOrConstructBoundFunction)
         return inlineBoundFunction(callInfo, target);
 
     // Simd functions
-    if (native == js::simd_int32x4_add)
-        return inlineSimdInt32x4BinaryArith(callInfo, native, MSimdBinaryArith::Add);
-    if (native == js::simd_int32x4_and)
-        return inlineSimdInt32x4BinaryBitwise(callInfo, native, MSimdBinaryBitwise::and_);
+#define INLINE_INT32X4_SIMD_ARITH_(OP)                                                      \
+    if (native == js::simd_int32x4_##OP)                                                    \
+        return inlineSimdInt32x4BinaryArith(callInfo, native, MSimdBinaryArith::Op_##OP);
+    ARITH_COMMONX4_SIMD_OP(INLINE_INT32X4_SIMD_ARITH_)
+#undef INLINE_INT32X4_SIMD_ARITH_
+
+#define INLINE_INT32X4_SIMD_BITWISE_(OP)                                                    \
+    if (native == js::simd_int32x4_##OP)                                                    \
+        return inlineSimdInt32x4BinaryBitwise(callInfo, native, MSimdBinaryBitwise::OP##_);
+    BITWISE_COMMONX4_SIMD_OP(INLINE_INT32X4_SIMD_BITWISE_)
+#undef INLINE_INT32X4_SIMD_BITWISE_
 
     return InliningStatus_NotInlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineNativeGetter(CallInfo &callInfo, JSFunction *target)
 {
     MOZ_ASSERT(target->isNative());
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -10,16 +10,17 @@
  */
 
 #ifndef jit_MIR_h
 #define jit_MIR_h
 
 #include "mozilla/Array.h"
 #include "mozilla/DebugOnly.h"
 
+#include "builtin/SIMD.h"
 #include "jit/AtomicOp.h"
 #include "jit/FixedList.h"
 #include "jit/InlineList.h"
 #include "jit/JitAllocPolicy.h"
 #include "jit/MacroAssembler.h"
 #include "jit/MOpcodes.h"
 #include "jit/TypedObjectPrediction.h"
 #include "jit/TypePolicy.h"
@@ -1953,51 +1954,43 @@ class MSimdBinaryComp
 };
 
 class MSimdBinaryArith
   : public MBinaryInstruction,
     public MixPolicy<SimdSameAsReturnedTypePolicy<0>, SimdSameAsReturnedTypePolicy<1> >::Data
 {
   public:
     enum Operation {
-        Add,
-        Sub,
-        Mul,
-        Div,
-        Min,
-        Max,
-        MinNum,
-        MaxNum
+#define OP_LIST_(OP) Op_##OP,
+        ARITH_COMMONX4_SIMD_OP(OP_LIST_)
+        ARITH_FLOAT32X4_SIMD_OP(OP_LIST_)
+#undef OP_LIST_
     };
 
     static const char* OperationName(Operation op) {
         switch (op) {
-          case Add:    return "Add";
-          case Sub:    return "Sub";
-          case Mul:    return "Mul";
-          case Div:    return "Div";
-          case Min:    return "Min";
-          case Max:    return "Max";
-          case MinNum: return "MinNum";
-          case MaxNum: return "MaxNum";
+#define OP_CASE_LIST_(OP) case Op_##OP: return #OP;
+          ARITH_COMMONX4_SIMD_OP(OP_CASE_LIST_)
+          ARITH_FLOAT32X4_SIMD_OP(OP_CASE_LIST_)
+#undef OP_CASE_LIST_
         }
         MOZ_CRASH("unexpected operation");
     }
 
   private:
     Operation operation_;
 
     MSimdBinaryArith(MDefinition *left, MDefinition *right, Operation op, MIRType type)
       : MBinaryInstruction(left, right), operation_(op)
     {
-        MOZ_ASSERT_IF(type == MIRType_Int32x4, op == Add || op == Sub || op == Mul);
+        MOZ_ASSERT_IF(type == MIRType_Int32x4, op == Op_add || op == Op_sub || op == Op_mul);
         MOZ_ASSERT(IsSimdType(type));
         setResultType(type);
         setMovable();
-        if (op == Add || op == Mul || op == Min || op == Max)
+        if (op == Op_add || op == Op_mul || op == Op_min || op == Op_max)
             setCommutative();
     }
 
   public:
     INSTRUCTION_HEADER(SimdBinaryArith)
     static MSimdBinaryArith *New(TempAllocator &alloc, MDefinition *left, MDefinition *right,
                                  Operation op, MIRType t)
     {
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -2652,23 +2652,23 @@ void
 CodeGeneratorX86Shared::visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *ins)
 {
     FloatRegister lhs = ToFloatRegister(ins->lhs());
     Operand rhs = ToOperand(ins->rhs());
     FloatRegister output = ToFloatRegister(ins->output());
 
     MSimdBinaryArith::Operation op = ins->operation();
     switch (op) {
-      case MSimdBinaryArith::Add:
+      case MSimdBinaryArith::Op_add:
         masm.vpaddd(rhs, lhs, output);
         return;
-      case MSimdBinaryArith::Sub:
+      case MSimdBinaryArith::Op_sub:
         masm.vpsubd(rhs, lhs, output);
         return;
-      case MSimdBinaryArith::Mul: {
+      case MSimdBinaryArith::Op_mul: {
         if (AssemblerX86Shared::HasSSE41()) {
             masm.vpmulld(rhs, lhs, output);
             return;
         }
 
         masm.loadAlignedInt32x4(rhs, ScratchSimdReg);
         masm.vpmuludq(lhs, ScratchSimdReg, ScratchSimdReg);
         // ScratchSimdReg contains (Rx, _, Rz, _) where R is the resulting vector.
@@ -2679,76 +2679,76 @@ CodeGeneratorX86Shared::visitSimdBinaryA
         masm.vpmuludq(temp, lhs, lhs);
         // lhs contains (Ry, _, Rw, _) where R is the resulting vector.
 
         masm.vshufps(MacroAssembler::ComputeShuffleMask(LaneX, LaneZ, LaneX, LaneZ), ScratchSimdReg, lhs, lhs);
         // lhs contains (Ry, Rw, Rx, Rz)
         masm.vshufps(MacroAssembler::ComputeShuffleMask(LaneZ, LaneX, LaneW, LaneY), lhs, lhs, lhs);
         return;
       }
-      case MSimdBinaryArith::Div:
+      case MSimdBinaryArith::Op_div:
         // x86 doesn't have SIMD i32 div.
         break;
-      case MSimdBinaryArith::Max:
+      case MSimdBinaryArith::Op_max:
         // we can do max with a single instruction only if we have SSE4.1
         // using the PMAXSD instruction.
         break;
-      case MSimdBinaryArith::Min:
+      case MSimdBinaryArith::Op_min:
         // we can do max with a single instruction only if we have SSE4.1
         // using the PMINSD instruction.
         break;
-      case MSimdBinaryArith::MinNum:
-      case MSimdBinaryArith::MaxNum:
+      case MSimdBinaryArith::Op_minNum:
+      case MSimdBinaryArith::Op_maxNum:
         break;
     }
     MOZ_CRASH("unexpected SIMD op");
 }
 
 void
 CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
 {
     FloatRegister lhs = ToFloatRegister(ins->lhs());
     Operand rhs = ToOperand(ins->rhs());
     FloatRegister output = ToFloatRegister(ins->output());
 
     MSimdBinaryArith::Operation op = ins->operation();
     switch (op) {
-      case MSimdBinaryArith::Add:
+      case MSimdBinaryArith::Op_add:
         masm.vaddps(rhs, lhs, output);
         return;
-      case MSimdBinaryArith::Sub:
+      case MSimdBinaryArith::Op_sub:
         masm.vsubps(rhs, lhs, output);
         return;
-      case MSimdBinaryArith::Mul:
+      case MSimdBinaryArith::Op_mul:
         masm.vmulps(rhs, lhs, output);
         return;
-      case MSimdBinaryArith::Div:
+      case MSimdBinaryArith::Op_div:
         masm.vdivps(rhs, lhs, output);
         return;
-      case MSimdBinaryArith::Max: {
+      case MSimdBinaryArith::Op_max: {
         FloatRegister lhsCopy = masm.reusedInputFloat32x4(lhs, ScratchSimdReg);
         masm.vcmpunordps(rhs, lhsCopy, ScratchSimdReg);
 
         FloatRegister tmp = ToFloatRegister(ins->temp());
         FloatRegister rhsCopy = masm.reusedInputAlignedFloat32x4(rhs, tmp);
         masm.vmaxps(Operand(lhs), rhsCopy, tmp);
         masm.vmaxps(rhs, lhs, output);
 
         masm.vandps(tmp, output, output);
         masm.vorps(ScratchSimdReg, output, output); // or in the all-ones NaNs
         return;
       }
-      case MSimdBinaryArith::Min: {
+      case MSimdBinaryArith::Op_min: {
         FloatRegister rhsCopy = masm.reusedInputAlignedFloat32x4(rhs, ScratchSimdReg);
         masm.vminps(Operand(lhs), rhsCopy, ScratchSimdReg);
         masm.vminps(rhs, lhs, output);
         masm.vorps(ScratchSimdReg, output, output); // NaN or'd with arbitrary bits is NaN
         return;
       }
-      case MSimdBinaryArith::MinNum: {
+      case MSimdBinaryArith::Op_minNum: {
         FloatRegister tmp = ToFloatRegister(ins->temp());
         masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), tmp);
 
         FloatRegister mask = ScratchSimdReg;
         FloatRegister tmpCopy = masm.reusedInputFloat32x4(tmp, ScratchSimdReg);
         masm.vpcmpeqd(Operand(lhs), tmpCopy, mask);
         masm.vandps(tmp, mask, mask);
 
@@ -2768,17 +2768,17 @@ CodeGeneratorX86Shared::visitSimdBinaryA
             if (lhs != output)
                 masm.moveFloat32x4(lhs, output);
             masm.vandps(Operand(mask), output, output);
             masm.vandnps(Operand(tmp), mask, mask);
             masm.vorps(Operand(mask), output, output);
         }
         return;
       }
-      case MSimdBinaryArith::MaxNum: {
+      case MSimdBinaryArith::Op_maxNum: {
         FloatRegister mask = ScratchSimdReg;
         masm.loadConstantInt32x4(SimdConstant::SplatX4(0), mask);
         masm.vpcmpeqd(Operand(lhs), mask, mask);
 
         FloatRegister tmp = ToFloatRegister(ins->temp());
         masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), tmp);
         masm.vandps(tmp, mask, mask);
 
--- a/js/src/jit/shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/shared/Lowering-x86-shared.cpp
@@ -634,29 +634,29 @@ LIRGeneratorX86Shared::visitSimdBinaryAr
     MDefinition *lhs = ins->lhs();
     MDefinition *rhs = ins->rhs();
 
     if (ins->isCommutative())
         ReorderCommutative(&lhs, &rhs, ins);
 
     if (ins->type() == MIRType_Int32x4) {
         LSimdBinaryArithIx4 *lir = new(alloc()) LSimdBinaryArithIx4();
-        bool needsTemp = ins->operation() == MSimdBinaryArith::Mul && !MacroAssembler::HasSSE41();
+        bool needsTemp = ins->operation() == MSimdBinaryArith::Op_mul && !MacroAssembler::HasSSE41();
         lir->setTemp(0, needsTemp ? temp(LDefinition::INT32X4) : LDefinition::BogusTemp());
         lowerForFPU(lir, ins, lhs, rhs);
         return;
     }
 
     MOZ_ASSERT(ins->type() == MIRType_Float32x4, "unknown simd type on binary arith operation");
 
     LSimdBinaryArithFx4 *lir = new(alloc()) LSimdBinaryArithFx4();
 
-    bool needsTemp = ins->operation() == MSimdBinaryArith::Max ||
-                     ins->operation() == MSimdBinaryArith::MinNum ||
-                     ins->operation() == MSimdBinaryArith::MaxNum;
+    bool needsTemp = ins->operation() == MSimdBinaryArith::Op_max ||
+                     ins->operation() == MSimdBinaryArith::Op_minNum ||
+                     ins->operation() == MSimdBinaryArith::Op_maxNum;
     lir->setTemp(0, needsTemp ? temp(LDefinition::FLOAT32X4) : LDefinition::BogusTemp());
 
     lowerForFPU(lir, ins, lhs, rhs);
 }
 
 void
 LIRGeneratorX86Shared::visitSimdSelect(MSimdSelect *ins)
 {