author | Haitao Feng <haitao.feng@intel.com> |
Tue, 04 Mar 2014 20:06:26 -0500 | |
changeset 171821 | 7efaabf97f0cc5b22f4b789af7807056f5d9a537 |
parent 171820 | 3194cb1d73f6a269f114b84f5e5fcf4a8b835806 |
child 171822 | 780785bdec58e105c1774da0edaed9c98f04ad3c |
push id | 40586 |
push user | nmatsakis@mozilla.com |
push date | Wed, 05 Mar 2014 01:09:37 +0000 |
treeherder | mozilla-inbound@7efaabf97f0c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | nmatsakis |
bugs | 943769 |
milestone | 30.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
|
--- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -151,17 +151,17 @@ class IonBuilder : public MIRGenerator jsbytecode *exitpc; // Deferred break and continue targets. DeferredEdge *breaks; // MIR instruction MTableSwitch *ins; - // The number of current successor that get mapped into a block. + // The number of current successor that get mapped into a block. uint32_t currentBlock; } tableswitch; struct { // Vector of body blocks to process after the cases. FixedList<MBasicBlock *> *bodies; // When processing case statements, this counter points at the @@ -644,16 +644,20 @@ class IonBuilder : public MIRGenerator InliningStatus inlineMathHypot(CallInfo &callInfo); InliningStatus inlineMathMinMax(CallInfo &callInfo, bool max); InliningStatus inlineMathPow(CallInfo &callInfo); InliningStatus inlineMathRandom(CallInfo &callInfo); InliningStatus inlineMathImul(CallInfo &callInfo); InliningStatus inlineMathFRound(CallInfo &callInfo); InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function); + // SIMD natives. + InliningStatus checkSIMDArgs(CallInfo &callInfo, const MIRType *argumentTypes); + InliningStatus inlineSIMDFunction(CallInfo &callInfo, uint32_t id, uint32_t argumentCount); + // String natives. InliningStatus inlineStringObject(CallInfo &callInfo); InliningStatus inlineStringSplit(CallInfo &callInfo); InliningStatus inlineStrCharCodeAt(CallInfo &callInfo); InliningStatus inlineStrFromCharCode(CallInfo &callInfo); InliningStatus inlineStrCharAt(CallInfo &callInfo); InliningStatus inlineStrReplace(CallInfo &callInfo);
--- a/js/src/jit/IonTypes.h +++ b/js/src/jit/IonTypes.h @@ -159,16 +159,19 @@ ValueTypeFromMIRType(MIRType type) return JSVAL_TYPE_INT32; case MIRType_Float32: // Fall through, there's no JSVAL for Float32 case MIRType_Double: return JSVAL_TYPE_DOUBLE; case MIRType_String: return JSVAL_TYPE_STRING; case MIRType_Magic: return JSVAL_TYPE_MAGIC; + case MIRType_Float32x4: + case MIRType_Int32x4: + return JSVAL_TYPE_OBJECT; default: JS_ASSERT(type == MIRType_Object); return JSVAL_TYPE_OBJECT; } } static inline JSValueTag MIRTypeToTag(MIRType type) @@ -189,16 +192,20 @@ StringFromMIRType(MIRType type) case MIRType_Int32: return "Int32"; case MIRType_Double: return "Double"; case MIRType_Float32: return "Float32"; case MIRType_String: return "String"; + case MIRType_Float32x4: + return "Float32x4"; + case MIRType_Int32x4: + return "Int32x4"; case MIRType_Object: return "Object"; case MIRType_Magic: return "Magic"; case MIRType_Value: return "Value"; case MIRType_None: return "None";
--- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -1,16 +1,17 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jsmath.h" +#include "builtin/SIMD.h" #include "builtin/TestingFunctions.h" #include "jit/BaselineInspector.h" #include "jit/IonBuilder.h" #include "jit/Lowering.h" #include "jit/MIR.h" #include "jit/MIRGraph.h" #include "jsscriptinlines.h" @@ -103,16 +104,67 @@ IonBuilder::inlineNativeCall(CallInfo &c return inlineMathFunction(callInfo, MMathFunction::ATanH); if (native == js::math_sign) return inlineMathFunction(callInfo, MMathFunction::Sign); if (native == js::math_trunc) return inlineMathFunction(callInfo, MMathFunction::Trunc); if (native == js::math_cbrt) return inlineMathFunction(callInfo, MMathFunction::Cbrt); + // SIMD natives. +#define INLINE_FLOAT32X4_NULLARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDNullaryFunction::Float32x4##MIRId, 0); +FLOAT32X4_NULLARY_FUNCTION_LIST(INLINE_FLOAT32X4_NULLARY_FUNCTION) +#undef INLINE_FLOAT32X4_NULLARY_FUNCTION +#define INLINE_INT32X4_NULLARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDNullaryFunction::Int32x4##MIRId, 0); +INT32X4_NULLARY_FUNCTION_LIST(INLINE_INT32X4_NULLARY_FUNCTION) +#undef INLINE_INT32X4_NULLARY_FUNCTION + +#define INLINE_FLOAT32X4_UNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDUnaryFunction::Float32x4##MIRId, 1); +FLOAT32X4_UNARY_FUNCTION_LIST(INLINE_FLOAT32X4_UNARY_FUNCTION) +#undef INLINE_FLOAT32X4_UNARY_FUNCTION +#define INLINE_INT32X4_UNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDUnaryFunction::Int32x4##MIRId, 1); +INT32X4_UNARY_FUNCTION_LIST(INLINE_INT32X4_UNARY_FUNCTION) +#undef INLINE_INT32X4_UNARY_FUNCTION + +#define INLINE_FLOAT32X4_BINARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDBinaryFunction::Float32x4##MIRId, 2); +FLOAT32X4_BINARY_FUNCTION_LIST(INLINE_FLOAT32X4_BINARY_FUNCTION) +#undef INLINE_FLOAT32X4_BINARY_FUNCTION +#define INLINE_INT32X4_BINARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDBinaryFunction::Int32x4##MIRId, 2); +INT32X4_BINARY_FUNCTION_LIST(INLINE_INT32X4_BINARY_FUNCTION) +#undef INLINE_INT32X4_BINARY_FUNCTION + +#define INLINE_FLOAT32X4_TERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_float32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDTernaryFunction::Float32x4##MIRId, 3); +FLOAT32X4_TERNARY_FUNCTION_LIST(INLINE_FLOAT32X4_TERNARY_FUNCTION) +#undef INLINE_FLOAT32X4_TERNARY_FUNCTION +#define INLINE_INT32X4_TERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDTernaryFunction::Int32x4##MIRId, 3); +INT32X4_TERNARY_FUNCTION_LIST(INLINE_INT32X4_TERNARY_FUNCTION) +#undef INLINE_INT32X4_TERNARY_FUNCTION + +#define INLINE_INT32X4_QUARTERNARY_FUNCTION(Name, Func, Operands, Flags, MIRId) \ + if (native == js::simd_int32x4_##Name) \ + return inlineSIMDFunction(callInfo, MSIMDQuarternaryFunction::Int32x4##MIRId, 4); +INT32X4_QUARTERNARY_FUNCTION_LIST(INLINE_INT32X4_QUARTERNARY_FUNCTION) +#undef INLINE_INT32X4_QUARTERNARY_FUNCTION + // String natives. if (native == js_String) return inlineStringObject(callInfo); if (native == js::str_split) return inlineStringSplit(callInfo); if (native == js_str_charCodeAt) return inlineStrCharCodeAt(callInfo); if (native == js::str_fromCharCode) @@ -212,16 +264,110 @@ IonBuilder::inlineMathFunction(CallInfo MMathFunction *ins = MMathFunction::New(alloc(), callInfo.getArg(0), function, cache); current->add(ins); current->push(ins); return InliningStatus_Inlined; } IonBuilder::InliningStatus +IonBuilder::checkSIMDArgs(CallInfo &callInfo, const MIRType *argumentTypes) +{ + for (uint32_t i = 0; i < callInfo.argc(); i++) { + MDefinition *arg = callInfo.getArg(i); + MIRType type = argumentTypes[i]; + switch (type) { + case MIRType_Float32x4: + case MIRType_Int32x4: + // SIMDTypePolicy will do the type check and un-box the typed object. + break; + + case MIRType_Int32: + case MIRType_Float32: + if (!IsNumberType(arg->type())) + return InliningStatus_NotInlined; + break; + + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD MIR Type"); + } + } + return InliningStatus_Inlined; +} + +IonBuilder::InliningStatus +IonBuilder::inlineSIMDFunction(CallInfo &callInfo, uint32_t id, uint32_t argumentCount) +{ + if (callInfo.constructing()) + return InliningStatus_NotInlined; + + if (callInfo.argc() != argumentCount) + return InliningStatus_NotInlined; + + if (getInlineReturnType() != MIRType_Object) + return InliningStatus_NotInlined; + + MIRType *argumentTypes = nullptr; + switch (argumentCount) { + case 0: + break; + case 1: + argumentTypes = &MSIMDUnaryFunction::ArgumentTypes[id]; + break; + case 2: + argumentTypes = MSIMDBinaryFunction::ArgumentTypes[id]; + break; + case 3: + argumentTypes = MSIMDTernaryFunction::ArgumentTypes[id]; + break; + case 4: + argumentTypes = MSIMDQuarternaryFunction::ArgumentTypes[id]; + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD function argument count"); + } + InliningStatus s = checkSIMDArgs(callInfo, argumentTypes); + if (s != InliningStatus_Inlined) + return s; + + callInfo.setImplicitlyUsedUnchecked(); + + MInstruction *ins = nullptr; + switch (argumentCount) { + case 0: + ins = MSIMDNullaryFunction::New(alloc(), static_cast<MSIMDNullaryFunction::Id>(id)); + break; + case 1: + ins = MSIMDUnaryFunction::New(alloc(), callInfo.getArg(0), + static_cast<MSIMDUnaryFunction::Id>(id)); + break; + case 2: + ins = MSIMDBinaryFunction::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), + static_cast<MSIMDBinaryFunction::Id>(id)); + break; + case 3: + ins = MSIMDTernaryFunction::New(alloc(), callInfo.getArg(0), + callInfo.getArg(1), callInfo.getArg(2), + static_cast<MSIMDTernaryFunction::Id>(id)); + break; + case 4: + ins = MSIMDQuarternaryFunction::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), + callInfo.getArg(2), callInfo.getArg(3), + static_cast<MSIMDQuarternaryFunction::Id>(id)); + break; + default: + MOZ_ASSUME_UNREACHABLE("Unknown SIMD function argument count"); + } + + current->add(ins); + current->push(ins); + return InliningStatus_Inlined; +} + +IonBuilder::InliningStatus IonBuilder::inlineArray(CallInfo &callInfo) { uint32_t initLength = 0; MNewArray::AllocatingBehaviour allocating = MNewArray::NewArray_Unallocating; JSObject *templateObject = inspector->getTemplateObjectForNative(pc, js_Array); if (!templateObject) return InliningStatus_NotInlined;
--- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -8,16 +8,17 @@ #include "mozilla/FloatingPoint.h" #include <ctype.h> #include "jslibmath.h" #include "jsstr.h" +#include "builtin/SIMD.h" #include "jit/BaselineInspector.h" #include "jit/IonBuilder.h" #include "jit/IonSpewer.h" #include "jit/MIRGraph.h" #include "jit/RangeAnalysis.h" #include "jsatominlines.h" #include "jsinferinlines.h" @@ -619,16 +620,126 @@ MMathFunction::FunctionName(Function fun void MMathFunction::printOpcode(FILE *fp) const { MDefinition::printOpcode(fp); fprintf(fp, " %s", FunctionName(function())); } +const char *MSIMDNullaryFunction::Names[] = { +#define MSIMD_NULLARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType) "SIMD." Name, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_NAME_TYPE) +#undef MSIMD_NULLARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDNullaryFunction::ReturnTypes[] = { +#define MSIMD_NULLARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType) ReturnType, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_NULLARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +const char *MSIMDUnaryFunction::Names[] = { +#define MSIMD_UNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, ArgumentType) \ + "SIMD." Name, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_UNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDUnaryFunction::ReturnTypes[] = { +#define MSIMD_UNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, ArgumentType) \ + ReturnType, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_UNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDUnaryFunction::ArgumentTypes[] = { +#define MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE(Id, Name, ReturnType, ArgumentType) \ + ArgumentType, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE) +#undef MSIMD_UNARY_FUNCTION_ARGUMENT_TYPE + MIRType_None +}; + +const char *MSIMDBinaryFunction::Names[] = { +#define MSIMD_BINARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + "SIMD." Name, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_NAME_TYPE) +#undef MSIMD_BINARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDBinaryFunction::ReturnTypes[] = { +#define MSIMD_BINARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + ReturnType, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_BINARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDBinaryFunction::ArgumentTypes[][2] = { +#define MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type) \ + {Argument1Type, Argument2Type}, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_BINARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None} +}; + +const char *MSIMDTernaryFunction::Names[] = { +#define MSIMD_TERNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + "SIMD." Name, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_TERNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDTernaryFunction::ReturnTypes[] = { +#define MSIMD_TERNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + ReturnType, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_TERNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDTernaryFunction::ArgumentTypes[][3] = { +#define MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type) \ + {Argument1Type, Argument2Type, Argument3Type}, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_TERNARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None, MIRType_None} +}; + +const char *MSIMDQuarternaryFunction::Names[] = { +#define MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + "SIMD." Name, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_NAME_TYPE + "" +}; + +MIRType MSIMDQuarternaryFunction::ReturnTypes[] = { +#define MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + ReturnType, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_RETURN_TYPE + MIRType_None +}; + +MIRType MSIMDQuarternaryFunction::ArgumentTypes[][4] = { +#define MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE(Id, Name, ReturnType, Argument1Type, Argument2Type, Argument3Type, Argument4Type) \ + {Argument1Type, Argument2Type, Argument3Type, Argument4Type}, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE) +#undef MSIMD_QUARTERNARY_FUNCTION_ARGUMENTS_TYPE + {MIRType_None, MIRType_None, MIRType_None, MIRType_None} +}; + MParameter * MParameter::New(TempAllocator &alloc, int32_t index, types::TemporaryTypeSet *types) { return new(alloc) MParameter(index, types); } void MParameter::printOpcode(FILE *fp) const @@ -891,17 +1002,17 @@ MUnbox::printOpcode(FILE *fp) const void MTypeBarrier::printOpcode(FILE *fp) const { PrintOpcodeName(fp, op()); fprintf(fp, " "); getOperand(0)->printName(fp); } - + void MPhi::removeOperand(size_t index) { MUse *use = getUseFor(index); JS_ASSERT(index < inputs_.length()); JS_ASSERT(inputs_.length() > 1); @@ -2439,17 +2550,17 @@ MCompare::evaluateConstantOperands(bool Value lhs = left->toConstant()->value(); Value rhs = right->toConstant()->value(); // Fold away some String equality comparisons. if (lhs.isString() && rhs.isString()) { int32_t comp = 0; // Default to equal. if (left != right) comp = CompareAtoms(&lhs.toString()->asAtom(), &rhs.toString()->asAtom()); - + switch (jsop_) { case JSOP_LT: *result = (comp < 0); break; case JSOP_LE: *result = (comp <= 0); break; case JSOP_GT:
--- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -3931,16 +3931,293 @@ class MMathFunction bool isFloat32Commutative() const { return function_ == Floor || function_ == Ceil || function_ == Round; } void trySpecializeFloat32(TempAllocator &alloc); void computeRange(TempAllocator &alloc); }; +#define DECLARE_COMMON_SIMD_FUNCTION(opcode) \ + static MIRType ReturnTypes[]; \ + static const char *Names[]; \ + Id id() const { \ + return id_; \ + } \ + bool congruentTo(MDefinition *ins) const { \ + if (!ins->is##opcode()) \ + return false; \ + if (ins->to##opcode()->id() != id()) \ + return false; \ + return congruentIfOperandsEqual(ins); \ + } \ + AliasSet getAliasSet() const { \ + return AliasSet::None(); \ + } \ + bool possiblyCalls() const { \ + return true; \ + } \ + void printOpcode(FILE *fp) const { \ + MDefinition::printOpcode(fp); \ + fprintf(fp, " %s", Names[id()]); \ + } + +#define MSIMD_NULLARY_FUNCTION_LIST(V) \ + V(Float32x4Zero, "float32x4.zero", MIRType_Float32x4) \ + V(Int32x4Zero, "int32x4.zero", MIRType_Int32x4) + +class MSIMDNullaryFunction + : public MNullaryInstruction +{ + public: + enum Id { +#define MSIMD_NULLARY_FUNCTION_ID(Id, Name, Type) Id, + MSIMD_NULLARY_FUNCTION_LIST(MSIMD_NULLARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_NULLARY_FUNCTION_ID + }; + + private: + Id id_; + + MSIMDNullaryFunction(Id id) + : MNullaryInstruction(), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDNullaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDNullaryFunction) + static MSIMDNullaryFunction *New(TempAllocator &alloc, Id id) + { + return new(alloc) MSIMDNullaryFunction(id); + } +}; + +#define MSIMD_UNARY_FUNCTION_LIST(V) \ + V(Float32x4Abs, "float32x4.abs", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4BitsToInt32x4, "float32x4.bitstoInt32x4", MIRType_Int32x4, MIRType_Float32x4) \ + V(Float32x4Neg, "float32x4.neg", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Reciprocal, "float32x4.reciprocal", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ReciprocalSqrt, "float32x4.reciprocalSqrt", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Splat, "float32x4.splat", MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4Sqrt, "float32x4.sqrt", MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ToInt32x4, "float32x4.toInt32x4", MIRType_Int32x4, MIRType_Float32x4) \ + V(Float32x4GetX, "float32x4.getX", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetY, "float32x4.getY", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetZ, "float32x4.getZ", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetW, "float32x4.getW", MIRType_Float32, MIRType_Float32x4) \ + V(Float32x4GetSignMask, "float32x4.getSignMask", MIRType_Int32, MIRType_Float32x4) \ + V(Int32x4BitsToFloat32x4, "int32x4.bitsToFloat32x4", MIRType_Float32x4, MIRType_Int32x4) \ + V(Int32x4Neg, "int32x4.neg", MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Not, "int32x4.not", MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Splat, "int32x4.splat", MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4ToFloat32x4, "int32x4.toFloat32x4", MIRType_Float32x4, MIRType_Int32x4) \ + V(Int32x4GetX, "int32x4.getX", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetY, "int32x4.getY", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetZ, "int32x4.getZ", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetW, "int32x4.getW", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetSignMask, "int32x4.getSignMask", MIRType_Int32, MIRType_Int32x4) \ + V(Int32x4GetFlagX, "int32x4.getFlagX", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagY, "int32x4.getFlagY", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagZ, "int32x4.getFlagZ", MIRType_Boolean, MIRType_Int32x4) \ + V(Int32x4GetFlagW, "int32x4.getFlagW", MIRType_Boolean, MIRType_Int32x4) + +class MSIMDUnaryFunction + : public MUnaryInstruction +{ + public: + enum Id { +#define MSIMD_UNARY_FUNCTION_ID(Id, Name, ReturnType, ArgumentType) Id, + MSIMD_UNARY_FUNCTION_LIST(MSIMD_UNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_UNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[]; + + private: + Id id_; + + MSIMDUnaryFunction(MDefinition *argument, Id id) + : MUnaryInstruction(argument), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDUnaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDUnaryFunction) + static MSIMDUnaryFunction *New(TempAllocator &alloc, MDefinition *argument, Id id) + { + return new(alloc) MSIMDUnaryFunction(argument, id); + } + bool canProduceFloat32() const { + return type() == MIRType_Float32; + } + bool canConsumeFloat32(MUse *use) const { + return id() == Float32x4Splat; + } +#ifdef DEBUG + bool isConsistentFloat32Use(MUse *use) const { return canProduceFloat32() || canConsumeFloat32(use); } +#endif +}; + +#define MSIMD_BINARY_FUNCTION_LIST(V) \ + V(Float32x4Add, "float32x4.add", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Div, "float32x4.div", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Equal, "float32x4.equal", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4GreaterThan, "float32x4.greaterThan", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4GreaterThanOrEqual, "float32x4.greaterThanOrEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4LessThan, "float32x4.lessThan", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4LessThanOrEqual, "float32x4.lessThanOrEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Max, "float32x4.max", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Min, "float32x4.min", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Mul, "float32x4.mul", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4NotEqual, "float32x4.notEqual", MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4Shuffle, "float32x4.shuffle", MIRType_Float32x4, MIRType_Float32x4, MIRType_Int32) \ + V(Float32x4Scale, "float32x4.scale", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4Sub, "float32x4.sub", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4WithX, "float32x4.withX", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithY, "float32x4.withY", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithZ, "float32x4.withZ", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Float32x4WithW, "float32x4.withW", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32) \ + V(Int32x4Add, "int32x4.add", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4And, "int32x4.and", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Mul, "int32x4.mul", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Or, "int32x4.or", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Sub, "int32x4.sub", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) \ + V(Int32x4Shuffle, "int32x4.shuffle", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithFlagX, "int32x4.withFlagX", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagY, "int32x4.withFlagY", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagZ, "int32x4.withFlagZ", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithFlagW, "int32x4.withFlagW", MIRType_Int32x4, MIRType_Int32x4, MIRType_Boolean) \ + V(Int32x4WithX, "int32x4.withX", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithY, "int32x4.withY", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithZ, "int32x4.withZ", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4WithW, "int32x4.withW", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) \ + V(Int32x4Xor, "int32x4.xor", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4) + +class MSIMDBinaryFunction + : public MBinaryInstruction +{ + public: + enum Id { +#define MSIMD_BINARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type) Id, + MSIMD_BINARY_FUNCTION_LIST(MSIMD_BINARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_BINARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][2]; + + private: + Id id_; + + MSIMDBinaryFunction(MDefinition *left, MDefinition *right, Id id) + : MBinaryInstruction(left, right), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDBinaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDBinaryFunction) + static MSIMDBinaryFunction *New(TempAllocator &alloc, MDefinition *left, MDefinition *right, Id id) + { + return new(alloc) MSIMDBinaryFunction(left, right, id); + } + bool canConsumeFloat32(MUse *use) const { + return id() == Float32x4Scale || id() == Float32x4WithX || id() == Float32x4WithY || + id() == Float32x4WithZ || id() == Float32x4WithW; + } +#ifdef DEBUG + bool isConsistentFloat32Use(MUse *use) const { + return canConsumeFloat32(use); + } +#endif +}; + +#define MSIMD_TERNARY_FUNCTION_LIST(V) \ + V(Float32x4Clamp, "float32x4.clamp", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Float32x4ShuffleMix, "float32x4.shuffleMix", MIRType_Float32x4, MIRType_Float32x4, MIRType_Float32x4, MIRType_Int32) \ + V(Int32x4Select, "int32x4.select", MIRType_Float32x4, MIRType_Int32x4, MIRType_Float32x4, MIRType_Float32x4) \ + V(Int32x4ShuffleMix, "int32x4.shuffleMix", MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32x4, MIRType_Int32) + +class MSIMDTernaryFunction + : public MTernaryInstruction +{ + public: + enum Id { +#define MSIMD_TERNARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type, Argument3Type) Id, + MSIMD_TERNARY_FUNCTION_LIST(MSIMD_TERNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_TERNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][3]; + + private: + Id id_; + + MSIMDTernaryFunction(MDefinition *first, MDefinition *second, MDefinition *third, Id id) + : MTernaryInstruction(first, second, third), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDTernaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDTernaryFunction) + static MSIMDTernaryFunction *New(TempAllocator &alloc, MDefinition *first, MDefinition *second, MDefinition *third, Id id) + { + return new(alloc) MSIMDTernaryFunction(first, second, third, id); + } +}; + +#define MSIMD_QUARTERNARY_FUNCTION_LIST(V) \ + V(Int32x4Bool, "int32x4.bool", MIRType_Int32x4, MIRType_Boolean, MIRType_Boolean, MIRType_Boolean, MIRType_Boolean) + +class MSIMDQuarternaryFunction + : public MQuaternaryInstruction +{ + public: + enum Id { +#define MSIMD_QUARTERNARY_FUNCTION_ID(Id, Name, Type, Argument1Type, Argument2Type, Argument3Type, Argument4Type) Id, + MSIMD_QUARTERNARY_FUNCTION_LIST(MSIMD_QUARTERNARY_FUNCTION_ID) + NUMBER_OF_IDS +#undef MSIMD_QUARTERNARY_FUNCTION_ID + }; + + static MIRType ArgumentTypes[][4]; + + private: + Id id_; + + MSIMDQuarternaryFunction(MDefinition *first, MDefinition *second, MDefinition *third, MDefinition *fourth, Id id) + : MQuaternaryInstruction(first, second, third, fourth), id_(id) + { + setMovable(); + setResultType(ReturnTypes[id]); + } + + public: + INSTRUCTION_HEADER(SIMDQuarternaryFunction) + DECLARE_COMMON_SIMD_FUNCTION(SIMDQuarternaryFunction) + static MSIMDQuarternaryFunction *New(TempAllocator &alloc, MDefinition *first, MDefinition *second, MDefinition *third, MDefinition *fourth, Id id) + { + return new(alloc) MSIMDQuarternaryFunction(first, second, third, fourth, id); + } +}; + class MAdd : public MBinaryArithInstruction { // Is this instruction really an int at heart? MAdd(MDefinition *left, MDefinition *right) : MBinaryArithInstruction(left, right) { setResultType(MIRType_Value); }
--- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -58,16 +58,21 @@ namespace jit { _(Abs) \ _(Sqrt) \ _(Atan2) \ _(Hypot) \ _(Pow) \ _(PowHalf) \ _(Random) \ _(MathFunction) \ + _(SIMDNullaryFunction) \ + _(SIMDUnaryFunction) \ + _(SIMDBinaryFunction) \ + _(SIMDTernaryFunction) \ + _(SIMDQuarternaryFunction) \ _(Add) \ _(Sub) \ _(Mul) \ _(Div) \ _(Mod) \ _(Concat) \ _(ConcatPar) \ _(CharCodeAt) \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -153,16 +153,21 @@ class ParallelSafetyVisitor : public MIn SAFE_OP(Rsh) SAFE_OP(Ursh) SPECIALIZED_OP(MinMax, PERMIT_NUMERIC) SAFE_OP(Abs) SAFE_OP(Sqrt) UNSAFE_OP(Atan2) UNSAFE_OP(Hypot) CUSTOM_OP(MathFunction) + SAFE_OP(SIMDNullaryFunction) + SAFE_OP(SIMDUnaryFunction) + SAFE_OP(SIMDBinaryFunction) + SAFE_OP(SIMDTernaryFunction) + SAFE_OP(SIMDQuarternaryFunction) SPECIALIZED_OP(Add, PERMIT_NUMERIC) SPECIALIZED_OP(Sub, PERMIT_NUMERIC) SPECIALIZED_OP(Mul, PERMIT_NUMERIC) SPECIALIZED_OP(Div, PERMIT_NUMERIC) SPECIALIZED_OP(Mod, PERMIT_NUMERIC) CUSTOM_OP(Concat) SAFE_OP(ConcatPar) UNSAFE_OP(CharCodeAt)