diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index fcc29eee2c81..d231a5f3bedc 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -128,6 +128,25 @@ class LMoveGroup : public LInstructionHelper<0, 0, 0> } }; +// Constructs a SIMD value with 4 components (e.g. int32x4, float32x4). +class LSimdValueX4 : public LInstructionHelper<1, 4, 0> +{ + public: + LIR_HEADER(SimdValueX4) + LSimdValueX4(const LAllocation &x, const LAllocation &y, + const LAllocation &z, const LAllocation &w) + { + setOperand(0, x); + setOperand(1, y); + setOperand(2, z); + setOperand(3, w); + } + + MSimdValueX4 *mir() const { + return mir_->toSimdValueX4(); + } +}; + // Extracts an element from a given SIMD int32x4 lane. class LSimdExtractElementI : public LInstructionHelper<1, 1, 0> { diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h index e2aaa7a186a6..fd4305059985 100644 --- a/js/src/jit/LOpcodes.h +++ b/js/src/jit/LOpcodes.h @@ -16,6 +16,7 @@ _(Pointer) \ _(Double) \ _(Float32) \ + _(SimdValueX4) \ _(SimdExtractElementI) \ _(SimdExtractElementF) \ _(Value) \ diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 7b73f9bde075..8e15ab3c6a08 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -3650,6 +3650,17 @@ LIRGenerator::visitRecompileCheck(MRecompileCheck *ins) return assignSafepoint(lir, ins); } +bool +LIRGenerator::visitSimdValueX4(MSimdValueX4 *ins) +{ + LAllocation x = useRegisterAtStart(ins->getOperand(0)); + LAllocation y = useRegisterAtStart(ins->getOperand(1)); + LAllocation z = useRegisterAtStart(ins->getOperand(2)); + LAllocation w = useRegisterAtStart(ins->getOperand(3)); + + return define(new(alloc()) LSimdValueX4(x, y, z, w), ins); +} + bool LIRGenerator::visitSimdExtractElement(MSimdExtractElement *ins) { diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index 973c9cb839e1..97a60e95ed58 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -265,6 +265,7 @@ class LIRGenerator : public LIRGeneratorSpecific bool visitGetDOMMember(MGetDOMMember *ins); bool visitRecompileCheck(MRecompileCheck *ins); bool visitSimdExtractElement(MSimdExtractElement *ins); + bool visitSimdValueX4(MSimdValueX4 *ins); }; } // namespace jit diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index cdec8be10792..19cf3503cf5f 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -13,6 +13,7 @@ #define jit_MIR_h #include "mozilla/Array.h" +#include "mozilla/DebugOnly.h" #include "jit/CompilerRoot.h" #include "jit/FixedList.h" @@ -1233,6 +1234,42 @@ class MConstant : public MNullaryInstruction ALLOW_CLONE(MConstant) }; +// Generic constructor of SIMD valuesX4. +class MSimdValueX4 : public MQuaternaryInstruction +{ + protected: + MSimdValueX4(MIRType type, MDefinition *x, MDefinition *y, MDefinition *z, MDefinition *w) + : MQuaternaryInstruction(x, y, z, w) + { + JS_ASSERT(IsSimdType(type)); + mozilla::DebugOnly scalarType = SimdTypeToScalarType(type); + JS_ASSERT(scalarType == x->type()); + JS_ASSERT(scalarType == y->type()); + JS_ASSERT(scalarType == z->type()); + JS_ASSERT(scalarType == w->type()); + + setMovable(); + setResultType(type); + } + + public: + INSTRUCTION_HEADER(SimdValueX4) + + static MSimdValueX4 *New(TempAllocator &alloc, MIRType type, MDefinition *x, + MDefinition *y, MDefinition *z, MDefinition *w) + { + return new(alloc) MSimdValueX4(type, x, y, z, w); + } + + AliasSet getAliasSet() const { + return AliasSet::None(); + } + + bool congruentTo(const MDefinition *ins) const { + return congruentIfOperandsEqual(ins); + } +}; + // Extracts a lane element from a given vector type, given by its lane symbol. class MSimdExtractElement : public MUnaryInstruction { diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index 1e08c0ad4548..2fb01340168a 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -12,6 +12,7 @@ namespace jit { #define MIR_OPCODE_LIST(_) \ _(Constant) \ + _(SimdValueX4) \ _(SimdExtractElement) \ _(CloneLiteral) \ _(Parameter) \ diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp index fa927d0c4536..1aec7a62c742 100644 --- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -112,6 +112,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor // obviously safe for now. We can loosen as we need. SAFE_OP(Constant) + SAFE_OP(SimdValueX4) SAFE_OP(SimdExtractElement) UNSAFE_OP(CloneLiteral) SAFE_OP(Parameter) diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index ca2e3e0030a3..ed66e286752c 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -227,6 +227,7 @@ class CodeGeneratorARM : public CodeGeneratorShared public: // Unimplemented SIMD instructions + bool visitSimdValueX4(LSimdValueX4 *lir) { MOZ_ASSUME_UNREACHABLE("NYI"); } bool visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_ASSUME_UNREACHABLE("NYI"); } bool visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_ASSUME_UNREACHABLE("NYI"); } }; diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.cpp b/js/src/jit/shared/CodeGenerator-x86-shared.cpp index 077ca7c61d56..72e50e053f63 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp @@ -2053,6 +2053,41 @@ CodeGeneratorX86Shared::visitNegF(LNegF *ins) return true; } +bool +CodeGeneratorX86Shared::visitSimdValueX4(LSimdValueX4 *ins) +{ + FloatRegister output = ToFloatRegister(ins->output()); + + MSimdValueX4 *mir = ins->mir(); + JS_ASSERT(IsSimdType(mir->type())); + JS_STATIC_ASSERT(sizeof(float) == sizeof(int32_t)); + + masm.reserveStack(Simd128DataSize); + // TODO see bug 1051860 for possible optimizations. + switch (mir->type()) { + case MIRType_Int32x4: { + for (size_t i = 0; i < 4; ++i) { + Register r = ToRegister(ins->getOperand(i)); + masm.store32(r, Address(StackPointer, i * sizeof(int32_t))); + } + masm.loadAlignedInt32x4(Address(StackPointer, 0), output); + break; + } + case MIRType_Float32x4: { + for (size_t i = 0; i < 4; ++i) { + FloatRegister r = ToFloatRegister(ins->getOperand(i)); + masm.storeFloat32(r, Address(StackPointer, i * sizeof(float))); + } + masm.loadAlignedFloat32x4(Address(StackPointer, 0), output); + break; + } + default: MOZ_ASSUME_UNREACHABLE("Unknown SIMD kind"); + } + + masm.freeStack(Simd128DataSize); + return true; +} + bool CodeGeneratorX86Shared::visitSimdExtractElementI(LSimdExtractElementI *ins) { diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.h b/js/src/jit/shared/CodeGenerator-x86-shared.h index 6d33809f36bb..c87626d2b03d 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.h +++ b/js/src/jit/shared/CodeGenerator-x86-shared.h @@ -205,6 +205,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared bool visitNegF(LNegF *lir); // SIMD operators + bool visitSimdValueX4(LSimdValueX4 *lir); bool visitSimdExtractElementI(LSimdExtractElementI *lir); bool visitSimdExtractElementF(LSimdExtractElementF *lir);