Bug 1129148 - Wrote a MACRO to generate conditions to inline SIMD instructions (sub, mul, and, or, xor). r=nbp

--HG--
extra : rebase_source : 8bea5ac7a63434082b5636766883c985a7f5118d
This commit is contained in:
Victor Carlquist 2015-02-10 12:50:42 -02:00
parent 1e887fd19a
commit 4e40652ac1
7 changed files with 73 additions and 72 deletions

View File

@ -5852,22 +5852,12 @@ CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompile
AsmJSSimdType opType = global->simdOperationType(); AsmJSSimdType opType = global->simdOperationType();
switch (global->simdOperation()) { switch (global->simdOperation()) {
case AsmJSSimdOperation_add: #define OP_CHECK_CASE_LIST_(OP) \
return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Add, def, type); case AsmJSSimdOperation_##OP: \
case AsmJSSimdOperation_sub: return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Op_##OP, def, type);
return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Sub, def, type); ARITH_COMMONX4_SIMD_OP(OP_CHECK_CASE_LIST_)
case AsmJSSimdOperation_mul: ARITH_FLOAT32X4_SIMD_OP(OP_CHECK_CASE_LIST_)
return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Mul, def, type); #undef OP_CHECK_CASE_LIST_
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);
case AsmJSSimdOperation_lessThan: case AsmJSSimdOperation_lessThan:
return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThan, def, type); return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThan, def, type);

View File

@ -190,31 +190,37 @@
_(shiftLeftByScalar) \ _(shiftLeftByScalar) \
_(shiftRightArithmeticByScalar) \ _(shiftRightArithmeticByScalar) \
_(shiftRightLogicalByScalar) _(shiftRightLogicalByScalar)
#define FOREACH_FLOAT32X4_SIMD_OP(_) \ #define ARITH_FLOAT32X4_SIMD_OP(_) \
_(abs) \
_(sqrt) \
_(reciprocal) \
_(reciprocalSqrt) \
_(fromInt32x4) \
_(fromInt32x4Bits) \
_(div) \ _(div) \
_(max) \ _(max) \
_(min) \ _(min) \
_(maxNum) \ _(maxNum) \
_(minNum) _(minNum)
#define FOREACH_COMMONX4_SIMD_OP(_) \ #define FOREACH_FLOAT32X4_SIMD_OP(_) \
ARITH_FLOAT32X4_SIMD_OP(_) \
_(abs) \
_(sqrt) \
_(reciprocal) \
_(reciprocalSqrt) \
_(fromInt32x4) \
_(fromInt32x4Bits)
#define ARITH_COMMONX4_SIMD_OP(_) \
_(add) \ _(add) \
_(sub) \ _(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) \ _(lessThan) \
_(lessThanOrEqual) \ _(lessThanOrEqual) \
_(equal) \ _(equal) \
_(notEqual) \ _(notEqual) \
_(greaterThan) \ _(greaterThan) \
_(greaterThanOrEqual) \ _(greaterThanOrEqual) \
_(and) \
_(or) \
_(xor) \
_(bitselect) \ _(bitselect) \
_(select) \ _(select) \
_(swizzle) \ _(swizzle) \

View File

@ -9167,13 +9167,18 @@ GetTemplateObjectForNative(JSContext *cx, HandleScript script, jsbytecode *pc,
} }
if (JitSupportsSimd()) { 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())); Rooted<TypeDescr *> descr(cx, &Int32x4::GetTypeDescr(*cx->global()));
res.set(TypedObject::createZeroed(cx, descr, 0, gc::TenuredHeap)); res.set(TypedObject::createZeroed(cx, descr, 0, gc::TenuredHeap));
if (!res) if (!res)
return false; return false;
return true; return true;
} }
#undef ADD_INT32X4_SIMD_OP_NAME_
} }
return true; return true;

View File

@ -257,10 +257,17 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target)
return inlineBoundFunction(callInfo, target); return inlineBoundFunction(callInfo, target);
// Simd functions // Simd functions
if (native == js::simd_int32x4_add) #define INLINE_INT32X4_SIMD_ARITH_(OP) \
return inlineSimdInt32x4BinaryArith(callInfo, native, MSimdBinaryArith::Add); if (native == js::simd_int32x4_##OP) \
if (native == js::simd_int32x4_and) return inlineSimdInt32x4BinaryArith(callInfo, native, MSimdBinaryArith::Op_##OP);
return inlineSimdInt32x4BinaryBitwise(callInfo, native, MSimdBinaryBitwise::and_); 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; return InliningStatus_NotInlined;
} }

View File

@ -15,6 +15,7 @@
#include "mozilla/Array.h" #include "mozilla/Array.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "builtin/SIMD.h"
#include "jit/AtomicOp.h" #include "jit/AtomicOp.h"
#include "jit/FixedList.h" #include "jit/FixedList.h"
#include "jit/InlineList.h" #include "jit/InlineList.h"
@ -1958,26 +1959,18 @@ class MSimdBinaryArith
{ {
public: public:
enum Operation { enum Operation {
Add, #define OP_LIST_(OP) Op_##OP,
Sub, ARITH_COMMONX4_SIMD_OP(OP_LIST_)
Mul, ARITH_FLOAT32X4_SIMD_OP(OP_LIST_)
Div, #undef OP_LIST_
Min,
Max,
MinNum,
MaxNum
}; };
static const char* OperationName(Operation op) { static const char* OperationName(Operation op) {
switch (op) { switch (op) {
case Add: return "Add"; #define OP_CASE_LIST_(OP) case Op_##OP: return #OP;
case Sub: return "Sub"; ARITH_COMMONX4_SIMD_OP(OP_CASE_LIST_)
case Mul: return "Mul"; ARITH_FLOAT32X4_SIMD_OP(OP_CASE_LIST_)
case Div: return "Div"; #undef OP_CASE_LIST_
case Min: return "Min";
case Max: return "Max";
case MinNum: return "MinNum";
case MaxNum: return "MaxNum";
} }
MOZ_CRASH("unexpected operation"); MOZ_CRASH("unexpected operation");
} }
@ -1988,11 +1981,11 @@ class MSimdBinaryArith
MSimdBinaryArith(MDefinition *left, MDefinition *right, Operation op, MIRType type) MSimdBinaryArith(MDefinition *left, MDefinition *right, Operation op, MIRType type)
: MBinaryInstruction(left, right), operation_(op) : 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)); MOZ_ASSERT(IsSimdType(type));
setResultType(type); setResultType(type);
setMovable(); setMovable();
if (op == Add || op == Mul || op == Min || op == Max) if (op == Op_add || op == Op_mul || op == Op_min || op == Op_max)
setCommutative(); setCommutative();
} }

View File

@ -2657,13 +2657,13 @@ CodeGeneratorX86Shared::visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *ins)
MSimdBinaryArith::Operation op = ins->operation(); MSimdBinaryArith::Operation op = ins->operation();
switch (op) { switch (op) {
case MSimdBinaryArith::Add: case MSimdBinaryArith::Op_add:
masm.vpaddd(rhs, lhs, output); masm.vpaddd(rhs, lhs, output);
return; return;
case MSimdBinaryArith::Sub: case MSimdBinaryArith::Op_sub:
masm.vpsubd(rhs, lhs, output); masm.vpsubd(rhs, lhs, output);
return; return;
case MSimdBinaryArith::Mul: { case MSimdBinaryArith::Op_mul: {
if (AssemblerX86Shared::HasSSE41()) { if (AssemblerX86Shared::HasSSE41()) {
masm.vpmulld(rhs, lhs, output); masm.vpmulld(rhs, lhs, output);
return; return;
@ -2684,19 +2684,19 @@ CodeGeneratorX86Shared::visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *ins)
masm.vshufps(MacroAssembler::ComputeShuffleMask(LaneZ, LaneX, LaneW, LaneY), lhs, lhs, lhs); masm.vshufps(MacroAssembler::ComputeShuffleMask(LaneZ, LaneX, LaneW, LaneY), lhs, lhs, lhs);
return; return;
} }
case MSimdBinaryArith::Div: case MSimdBinaryArith::Op_div:
// x86 doesn't have SIMD i32 div. // x86 doesn't have SIMD i32 div.
break; break;
case MSimdBinaryArith::Max: case MSimdBinaryArith::Op_max:
// we can do max with a single instruction only if we have SSE4.1 // we can do max with a single instruction only if we have SSE4.1
// using the PMAXSD instruction. // using the PMAXSD instruction.
break; break;
case MSimdBinaryArith::Min: case MSimdBinaryArith::Op_min:
// we can do max with a single instruction only if we have SSE4.1 // we can do max with a single instruction only if we have SSE4.1
// using the PMINSD instruction. // using the PMINSD instruction.
break; break;
case MSimdBinaryArith::MinNum: case MSimdBinaryArith::Op_minNum:
case MSimdBinaryArith::MaxNum: case MSimdBinaryArith::Op_maxNum:
break; break;
} }
MOZ_CRASH("unexpected SIMD op"); MOZ_CRASH("unexpected SIMD op");
@ -2711,19 +2711,19 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
MSimdBinaryArith::Operation op = ins->operation(); MSimdBinaryArith::Operation op = ins->operation();
switch (op) { switch (op) {
case MSimdBinaryArith::Add: case MSimdBinaryArith::Op_add:
masm.vaddps(rhs, lhs, output); masm.vaddps(rhs, lhs, output);
return; return;
case MSimdBinaryArith::Sub: case MSimdBinaryArith::Op_sub:
masm.vsubps(rhs, lhs, output); masm.vsubps(rhs, lhs, output);
return; return;
case MSimdBinaryArith::Mul: case MSimdBinaryArith::Op_mul:
masm.vmulps(rhs, lhs, output); masm.vmulps(rhs, lhs, output);
return; return;
case MSimdBinaryArith::Div: case MSimdBinaryArith::Op_div:
masm.vdivps(rhs, lhs, output); masm.vdivps(rhs, lhs, output);
return; return;
case MSimdBinaryArith::Max: { case MSimdBinaryArith::Op_max: {
FloatRegister lhsCopy = masm.reusedInputFloat32x4(lhs, ScratchSimdReg); FloatRegister lhsCopy = masm.reusedInputFloat32x4(lhs, ScratchSimdReg);
masm.vcmpunordps(rhs, lhsCopy, ScratchSimdReg); masm.vcmpunordps(rhs, lhsCopy, ScratchSimdReg);
@ -2736,14 +2736,14 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
masm.vorps(ScratchSimdReg, output, output); // or in the all-ones NaNs masm.vorps(ScratchSimdReg, output, output); // or in the all-ones NaNs
return; return;
} }
case MSimdBinaryArith::Min: { case MSimdBinaryArith::Op_min: {
FloatRegister rhsCopy = masm.reusedInputAlignedFloat32x4(rhs, ScratchSimdReg); FloatRegister rhsCopy = masm.reusedInputAlignedFloat32x4(rhs, ScratchSimdReg);
masm.vminps(Operand(lhs), rhsCopy, ScratchSimdReg); masm.vminps(Operand(lhs), rhsCopy, ScratchSimdReg);
masm.vminps(rhs, lhs, output); masm.vminps(rhs, lhs, output);
masm.vorps(ScratchSimdReg, output, output); // NaN or'd with arbitrary bits is NaN masm.vorps(ScratchSimdReg, output, output); // NaN or'd with arbitrary bits is NaN
return; return;
} }
case MSimdBinaryArith::MinNum: { case MSimdBinaryArith::Op_minNum: {
FloatRegister tmp = ToFloatRegister(ins->temp()); FloatRegister tmp = ToFloatRegister(ins->temp());
masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), tmp); masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), tmp);
@ -2773,7 +2773,7 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
} }
return; return;
} }
case MSimdBinaryArith::MaxNum: { case MSimdBinaryArith::Op_maxNum: {
FloatRegister mask = ScratchSimdReg; FloatRegister mask = ScratchSimdReg;
masm.loadConstantInt32x4(SimdConstant::SplatX4(0), mask); masm.loadConstantInt32x4(SimdConstant::SplatX4(0), mask);
masm.vpcmpeqd(Operand(lhs), mask, mask); masm.vpcmpeqd(Operand(lhs), mask, mask);

View File

@ -639,7 +639,7 @@ LIRGeneratorX86Shared::visitSimdBinaryArith(MSimdBinaryArith *ins)
if (ins->type() == MIRType_Int32x4) { if (ins->type() == MIRType_Int32x4) {
LSimdBinaryArithIx4 *lir = new(alloc()) LSimdBinaryArithIx4(); 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()); lir->setTemp(0, needsTemp ? temp(LDefinition::INT32X4) : LDefinition::BogusTemp());
lowerForFPU(lir, ins, lhs, rhs); lowerForFPU(lir, ins, lhs, rhs);
return; return;
@ -649,9 +649,9 @@ LIRGeneratorX86Shared::visitSimdBinaryArith(MSimdBinaryArith *ins)
LSimdBinaryArithFx4 *lir = new(alloc()) LSimdBinaryArithFx4(); LSimdBinaryArithFx4 *lir = new(alloc()) LSimdBinaryArithFx4();
bool needsTemp = ins->operation() == MSimdBinaryArith::Max || bool needsTemp = ins->operation() == MSimdBinaryArith::Op_max ||
ins->operation() == MSimdBinaryArith::MinNum || ins->operation() == MSimdBinaryArith::Op_minNum ||
ins->operation() == MSimdBinaryArith::MaxNum; ins->operation() == MSimdBinaryArith::Op_maxNum;
lir->setTemp(0, needsTemp ? temp(LDefinition::FLOAT32X4) : LDefinition::BogusTemp()); lir->setTemp(0, needsTemp ? temp(LDefinition::FLOAT32X4) : LDefinition::BogusTemp());
lowerForFPU(lir, ins, lhs, rhs); lowerForFPU(lir, ins, lhs, rhs);