From 6a2263406f75a256854c922a52ada7cc57f1e060 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Wed, 18 Mar 2015 20:07:45 +0100 Subject: [PATCH] Bug 1135039: Generalize swizzle MIR node to SimdGeneralShuffle; r=sunfish --- js/src/asmjs/AsmJSValidate.cpp | 4 +- js/src/builtin/SIMD.h | 2 +- js/src/jit-test/tests/SIMD/shuffle.js | 81 ++++++++++++++++++ js/src/jit/IonBuilder.h | 3 +- js/src/jit/LIR-Common.h | 41 +++++---- js/src/jit/LOpcodes.h | 4 +- js/src/jit/Lowering.cpp | 39 +++++---- js/src/jit/Lowering.h | 2 +- js/src/jit/MCallOptimize.cpp | 28 +++++-- js/src/jit/MIR.cpp | 21 +++-- js/src/jit/MIR.h | 83 ++++++++++++------- js/src/jit/MOpcodes.h | 2 +- js/src/jit/TypePolicy.cpp | 19 +++-- js/src/jit/TypePolicy.h | 2 +- js/src/jit/arm/CodeGenerator-arm.h | 4 +- js/src/jit/mips/CodeGenerator-mips.h | 4 +- .../jit/shared/CodeGenerator-x86-shared.cpp | 54 +++++++----- js/src/jit/shared/CodeGenerator-x86-shared.h | 4 +- 18 files changed, 266 insertions(+), 131 deletions(-) create mode 100644 js/src/jit-test/tests/SIMD/shuffle.js diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index 3d1f7e0921a..10c1de1b90b 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -2732,7 +2732,7 @@ class FunctionCompiler if (inDeadCode()) return nullptr; - MSimdSwizzle *ins = MSimdSwizzle::NewAsmJS(alloc(), vector, type, X, Y, Z, W); + MSimdSwizzle *ins = MSimdSwizzle::New(alloc(), vector, type, X, Y, Z, W); curBlock_->add(ins); return ins; } @@ -2743,7 +2743,7 @@ class FunctionCompiler if (inDeadCode()) return nullptr; - MInstruction *ins = MSimdShuffle::NewAsmJS(alloc(), lhs, rhs, type, X, Y, Z, W); + MInstruction *ins = MSimdShuffle::New(alloc(), lhs, rhs, type, X, Y, Z, W); curBlock_->add(ins); return ins; } diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h index 4ae2ce1010b..4082a1cd688 100644 --- a/js/src/builtin/SIMD.h +++ b/js/src/builtin/SIMD.h @@ -242,13 +242,13 @@ _(not) \ _(neg) \ _(swizzle) \ + _(shuffle) \ _(load) \ _(store) \ _(check) #define FOREACH_COMMONX4_SIMD_OP(_) \ ION_COMMONX4_SIMD_OP(_) \ COMP_COMMONX4_TO_INT32X4_SIMD_OP(_) \ - _(shuffle) \ _(loadX) \ _(loadXY) \ _(loadXYZ) \ diff --git a/js/src/jit-test/tests/SIMD/shuffle.js b/js/src/jit-test/tests/SIMD/shuffle.js new file mode 100644 index 00000000000..33a09e68e8d --- /dev/null +++ b/js/src/jit-test/tests/SIMD/shuffle.js @@ -0,0 +1,81 @@ +if (!this.hasOwnProperty("SIMD")) + quit(); + +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var i1 = SIMD.int32x4(1, 2, 3, 4); + var i2 = SIMD.int32x4(5, 6, 7, 8); + + var leet = Math.fround(13.37); + var f1 = SIMD.float32x4(-.5, -0, Infinity, leet); + var f2 = SIMD.float32x4(42, .5, 23, -10); + + // computes all rotations of a given array + function *gen(arr) { + var previous = arr.slice().splice(0, 4); + var i = 4; + for (var j = 0; j < 8; j++) { + yield previous.slice(); + previous = previous.splice(1, previous.length - 1); + previous.push(arr[i]); + i = (i + 1) % arr.length; + } + } + + var compI = []; + for (var k of gen([i1.x, i1.y, i1.z, i1.w, i2.x, i2.y, i2.z, i2.w])) + compI.push(k); + + var compF = []; + for (var k of gen([f1.x, f1.y, f1.z, f1.w, f2.x, f2.y, f2.z, f2.w])) + compF.push(k); + + for (var i = 0; i < 150; i++) { + // Variable lanes + var r = SIMD.float32x4.shuffle(f1, f2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8); + assertEqX4(r, compF[i % 8]); + + // Constant lanes + assertEqX4(SIMD.float32x4.shuffle(f1, f2, 3, 2, 4, 5), [leet, Infinity, 42, .5]); + + // Variable lanes + var r = SIMD.int32x4.shuffle(i1, i2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8); + assertEqX4(r, compI[i % 8]); + + // Constant lanes + assertEqX4(SIMD.int32x4.shuffle(i1, i2, 3, 2, 4, 5), [4, 3, 5, 6]); + } +} + +function testBailouts(uglyDuckling) { + var i1 = SIMD.int32x4(1, 2, 3, 4); + var i2 = SIMD.int32x4(5, 6, 7, 8); + + for (var i = 0; i < 150; i++) { + // Test bailouts + var value = i == 149 ? uglyDuckling : 3; + var caught = false; + try { + assertEqX4(SIMD.int32x4.shuffle(i1, i2, value, 2, 4, 5), [4, 3, 5, 6]); + } catch(e) { + print(e); + caught = true; + assertEq(i, 149); + assertEq(e instanceof TypeError, true); + } + assertEq(i < 149 || caught, true); + } +} + +f(); +testBailouts(-1); +testBailouts(8); +testBailouts(2.5); +testBailouts(undefined); +testBailouts(null); +testBailouts({}); +testBailouts('one'); +testBailouts(true); diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index ff3d90bce89..83305063397 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -832,7 +832,8 @@ class IonBuilder InliningStatus inlineSimdWith(CallInfo &callInfo, JSNative native, SimdLane lane, SimdTypeDescr::Type type); InliningStatus inlineSimdSplat(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type); - InliningStatus inlineSimdSwizzle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type); + InliningStatus inlineSimdShuffle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type, + unsigned numVectors, unsigned numLanes); InliningStatus inlineSimdCheck(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type); InliningStatus inlineSimdConvert(CallInfo &callInfo, JSNative native, bool isCast, SimdTypeDescr::Type from, SimdTypeDescr::Type to); diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index 503802b1e19..7317a0d947d 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -374,46 +374,43 @@ class LSimdSwizzleF : public LSimdSwizzleBase {} }; -class LSimdGeneralSwizzleBase : public LInstructionHelper<1, 5, 1> +class LSimdGeneralShuffleBase : public LVariadicInstruction<1, 1> { public: - LSimdGeneralSwizzleBase(const LAllocation &base, const LAllocation lanes[4], - const LDefinition &temp) - { - setOperand(0, base); - for (size_t i = 0; i < 4; i++) - setOperand(1 + i, lanes[i]); + explicit LSimdGeneralShuffleBase(const LDefinition &temp) { setTemp(0, temp); } - - const LAllocation *base() { - return getOperand(0); + const LAllocation *vector(unsigned i) { + MOZ_ASSERT(i < mir()->numVectors()); + return getOperand(i); } - const LAllocation *lane(size_t i) { - return getOperand(1 + i); + const LAllocation *lane(unsigned i) { + MOZ_ASSERT(i < mir()->numLanes()); + return getOperand(mir()->numVectors() + i); } const LDefinition *temp() { return getTemp(0); } + MSimdGeneralShuffle *mir() const { + return mir_->toSimdGeneralShuffle(); + } }; -class LSimdGeneralSwizzleI : public LSimdGeneralSwizzleBase +class LSimdGeneralShuffleI : public LSimdGeneralShuffleBase { public: - LIR_HEADER(SimdGeneralSwizzleI); - LSimdGeneralSwizzleI(const LAllocation &base, const LAllocation lanes[4], - const LDefinition &temp) - : LSimdGeneralSwizzleBase(base, lanes, temp) + LIR_HEADER(SimdGeneralShuffleI); + explicit LSimdGeneralShuffleI(const LDefinition &temp) + : LSimdGeneralShuffleBase(temp) {} }; -class LSimdGeneralSwizzleF : public LSimdGeneralSwizzleBase +class LSimdGeneralShuffleF : public LSimdGeneralShuffleBase { public: - LIR_HEADER(SimdGeneralSwizzleF); - LSimdGeneralSwizzleF(const LAllocation &base, const LAllocation lanes[4], - const LDefinition &temp) - : LSimdGeneralSwizzleBase(base, lanes, temp) + LIR_HEADER(SimdGeneralShuffleF); + explicit LSimdGeneralShuffleF(const LDefinition &temp) + : LSimdGeneralShuffleBase(temp) {} }; diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h index 136da45aeb3..e87f519e6e9 100644 --- a/js/src/jit/LOpcodes.h +++ b/js/src/jit/LOpcodes.h @@ -28,8 +28,8 @@ _(SimdInsertElementI) \ _(SimdInsertElementF) \ _(SimdSignMaskX4) \ - _(SimdGeneralSwizzleI) \ - _(SimdGeneralSwizzleF) \ + _(SimdGeneralShuffleI) \ + _(SimdGeneralShuffleF) \ _(SimdSwizzleI) \ _(SimdSwizzleF) \ _(SimdShuffle) \ diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index feba5784cce..e1fc9972d42 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -3957,28 +3957,33 @@ LIRGenerator::visitSimdSwizzle(MSimdSwizzle *ins) } void -LIRGenerator::visitSimdGeneralSwizzle(MSimdGeneralSwizzle *ins) +LIRGenerator::visitSimdGeneralShuffle(MSimdGeneralShuffle*ins) { - MOZ_ASSERT(IsSimdType(ins->input()->type())); MOZ_ASSERT(IsSimdType(ins->type())); - LAllocation lanesUses[4]; - for (size_t i = 0; i < 4; i++) - lanesUses[i] = use(ins->lane(i)); + LSimdGeneralShuffleBase *lir; + if (ins->type() == MIRType_Int32x4) + lir = new (alloc()) LSimdGeneralShuffleI(temp()); + else if (ins->type() == MIRType_Float32x4) + lir = new (alloc()) LSimdGeneralShuffleF(temp()); + else + MOZ_CRASH("Unknown SIMD kind when doing a shuffle"); - if (ins->input()->type() == MIRType_Int32x4) { - LSimdGeneralSwizzleI *lir = new (alloc()) LSimdGeneralSwizzleI(useRegister(ins->input()), - lanesUses, temp()); - assignSnapshot(lir, Bailout_BoundsCheck); - define(lir, ins); - } else if (ins->input()->type() == MIRType_Float32x4) { - LSimdGeneralSwizzleF *lir = new (alloc()) LSimdGeneralSwizzleF(useRegister(ins->input()), - lanesUses, temp()); - assignSnapshot(lir, Bailout_BoundsCheck); - define(lir, ins); - } else { - MOZ_CRASH("Unknown SIMD kind when getting lane"); + if (!lir->init(alloc(), ins->numVectors() + ins->numLanes())) + return; + + for (unsigned i = 0; i < ins->numVectors(); i++) { + MOZ_ASSERT(IsSimdType(ins->vector(i)->type())); + lir->setOperand(i, useRegister(ins->vector(i))); } + + for (unsigned i = 0; i < ins->numLanes(); i++) { + MOZ_ASSERT(ins->lane(i)->type() == MIRType_Int32); + lir->setOperand(i + ins->numVectors(), useRegister(ins->lane(i))); + } + + assignSnapshot(lir, Bailout_BoundsCheck); + define(lir, ins); } void diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index 81c5d219fae..4977131f1ab 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -269,7 +269,7 @@ class LIRGenerator : public LIRGeneratorSpecific void visitSimdInsertElement(MSimdInsertElement *ins); void visitSimdSignMask(MSimdSignMask *ins); void visitSimdSwizzle(MSimdSwizzle *ins); - void visitSimdGeneralSwizzle(MSimdGeneralSwizzle *ins); + void visitSimdGeneralShuffle(MSimdGeneralShuffle *ins); void visitSimdShuffle(MSimdShuffle *ins); void visitSimdUnaryArith(MSimdUnaryArith *ins); void visitSimdBinaryComp(MSimdBinaryComp *ins); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 0cad20a13e4..80d9afa889d 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -351,9 +351,13 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target) return inlineSimdSelect(callInfo, native, IsElementWise(false), SimdTypeDescr::TYPE_FLOAT32); if (native == js::simd_int32x4_swizzle) - return inlineSimdSwizzle(callInfo, native, SimdTypeDescr::TYPE_INT32); + return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_INT32, 1, 4); if (native == js::simd_float32x4_swizzle) - return inlineSimdSwizzle(callInfo, native, SimdTypeDescr::TYPE_FLOAT32); + return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_FLOAT32, 1, 4); + if (native == js::simd_int32x4_shuffle) + return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_INT32, 2, 4); + if (native == js::simd_float32x4_shuffle) + return inlineSimdShuffle(callInfo, native, SimdTypeDescr::TYPE_FLOAT32, 2, 4); if (native == js::simd_int32x4_load) return inlineSimdLoad(callInfo, native, SimdTypeDescr::TYPE_INT32); @@ -3113,18 +3117,24 @@ IonBuilder::inlineSimdCheck(CallInfo &callInfo, JSNative native, SimdTypeDescr:: } IonBuilder::InliningStatus -IonBuilder::inlineSimdSwizzle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type) +IonBuilder::inlineSimdShuffle(CallInfo &callInfo, JSNative native, SimdTypeDescr::Type type, + unsigned numVectors, unsigned numLanes) { InlineTypedObject *templateObj = nullptr; - if (!checkInlineSimd(callInfo, native, type, 5, &templateObj)) + if (!checkInlineSimd(callInfo, native, type, numVectors + numLanes, &templateObj)) return InliningStatus_NotInlined; - MDefinition *lanes[4]; - for (size_t i = 0; i < 4; i++) - lanes[i] = callInfo.getArg(1 + i); - MIRType mirType = SimdTypeDescrToMIRType(type); - MSimdGeneralSwizzle *ins = MSimdGeneralSwizzle::New(alloc(), callInfo.getArg(0), lanes, mirType); + MSimdGeneralShuffle *ins = MSimdGeneralShuffle::New(alloc(), numVectors, numLanes, mirType); + + if (!ins->init(alloc())) + return InliningStatus_Error; + + for (unsigned i = 0; i < numVectors; i++) + ins->setVector(i, callInfo.getArg(i)); + for (size_t i = 0; i < numLanes; i++) + ins->setLane(i, callInfo.getArg(numVectors + i)); + return boxSimd(callInfo, ins, templateObj); } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 610dc1b61ca..680984b09d5 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -965,17 +965,26 @@ MSimdSwizzle::foldsTo(TempAllocator &alloc) } MDefinition * -MSimdGeneralSwizzle::foldsTo(TempAllocator &alloc) +MSimdGeneralShuffle::foldsTo(TempAllocator &alloc) { - int32_t lanes[4]; - for (size_t i = 0; i < 4; i++) { + FixedList lanes; + if (!lanes.init(alloc, numLanes())) + return this; + + for (size_t i = 0; i < numLanes(); i++) { if (!lane(i)->isConstant() || lane(i)->type() != MIRType_Int32) return this; - lanes[i] = lane(i)->toConstant()->value().toInt32(); - if (lanes[i] < 0 || lanes[i] >= 4) + int32_t temp = lane(i)->toConstant()->value().toInt32(); + if (temp < 0 || uint32_t(temp) >= numLanes() * numVectors()) return this; + lanes[i] = uint32_t(temp); } - return MSimdSwizzle::New(alloc, input(), type(), lanes[0], lanes[1], lanes[2], lanes[3]); + + if (numVectors() == 1) + return MSimdSwizzle::New(alloc, vector(0), type(), lanes[0], lanes[1], lanes[2], lanes[3]); + + MOZ_ASSERT(numVectors() == 2); + return MSimdShuffle::New(alloc, vector(0), vector(1), type(), lanes[0], lanes[1], lanes[2], lanes[3]); } template diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index fd1f9939131..a3c66b4636f 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -1814,12 +1814,6 @@ class MSimdSwizzle public: INSTRUCTION_HEADER(SimdSwizzle) - static MSimdSwizzle *NewAsmJS(TempAllocator &alloc, MDefinition *obj, MIRType type, - uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW) - { - return new(alloc) MSimdSwizzle(obj, type, laneX, laneY, laneZ, laneW); - } - static MSimdSwizzle *New(TempAllocator &alloc, MDefinition *obj, MIRType type, uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW) { @@ -1842,23 +1836,24 @@ class MSimdSwizzle ALLOW_CLONE(MSimdSwizzle) }; -// A "general swizzle" is a swizzle with non-constant lane indices. This is the -// one that Ion inlines and it can be folded into a MSimdSwizzle if lane indices -// are constant. Performance of general swizzle does not really matter, as we -// expect to always get constant indices. -class MSimdGeneralSwizzle : - public MAryInstruction<5>, - public SimdSwizzlePolicy::Data +// A "general swizzle" is a swizzle or a shuffle with non-constant lane +// indices. This is the one that Ion inlines and it can be folded into a +// MSimdSwizzle/MSimdShuffle if lane indices are constant. Performance of +// general swizzle/shuffle does not really matter, as we expect to get +// constant indices most of the time. +class MSimdGeneralShuffle : + public MVariadicInstruction, + public SimdShufflePolicy::Data { + unsigned numVectors_; + unsigned numLanes_; + protected: - MSimdGeneralSwizzle(MDefinition *vec, MDefinition *lanes[4], MIRType type) + MSimdGeneralShuffle(unsigned numVectors, unsigned numLanes, MIRType type) + : numVectors_(numVectors), numLanes_(numLanes) { MOZ_ASSERT(IsSimdType(type)); - MOZ_ASSERT(SimdTypeToLength(type) == 4); - - initOperand(0, vec); - for (unsigned i = 0; i < 4; i++) - initOperand(1 + i, lanes[i]); + MOZ_ASSERT(SimdTypeToLength(type) == numLanes_); setResultType(type); specialization_ = type; @@ -1866,24 +1861,48 @@ class MSimdGeneralSwizzle : } public: - INSTRUCTION_HEADER(SimdGeneralSwizzle); - ALLOW_CLONE(MSimdGeneralSwizzle); + INSTRUCTION_HEADER(SimdGeneralShuffle); - static MSimdGeneralSwizzle *New(TempAllocator &alloc, MDefinition *vec, MDefinition *lanes[4], + static MSimdGeneralShuffle *New(TempAllocator &alloc, unsigned numVectors, unsigned numLanes, MIRType type) { - return new(alloc) MSimdGeneralSwizzle(vec, lanes, type); + return new(alloc) MSimdGeneralShuffle(numVectors, numLanes, type); } - MDefinition *input() const { - return getOperand(0); + bool init(TempAllocator &alloc) { + return MVariadicInstruction::init(alloc, numVectors_ + numLanes_); } - MDefinition *lane(size_t i) const { - return getOperand(1 + i); + void setVector(unsigned i, MDefinition* vec) { + MOZ_ASSERT(i < numVectors_); + initOperand(i, vec); + } + void setLane(unsigned i, MDefinition* laneIndex) { + MOZ_ASSERT(i < numLanes_); + initOperand(numVectors_ + i, laneIndex); + } + + unsigned numVectors() const { + return numVectors_; + } + unsigned numLanes() const { + return numLanes_; + } + MDefinition *vector(unsigned i) const { + MOZ_ASSERT(i < numVectors_); + return getOperand(i); + } + MDefinition *lane(unsigned i) const { + MOZ_ASSERT(i < numLanes_); + return getOperand(numVectors_ + i); } bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE { - return congruentIfOperandsEqual(ins); + if (!ins->isSimdGeneralShuffle()) + return false; + const MSimdGeneralShuffle *other = ins->toSimdGeneralShuffle(); + return numVectors_ == other->numVectors() && + numLanes_ == other->numLanes() && + congruentIfOperandsEqual(other); } MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE; @@ -1918,9 +1937,9 @@ class MSimdShuffle public: INSTRUCTION_HEADER(SimdShuffle) - static MInstruction *NewAsmJS(TempAllocator &alloc, MDefinition *lhs, MDefinition *rhs, - MIRType type, uint32_t laneX, uint32_t laneY, uint32_t laneZ, - uint32_t laneW) + static MInstruction *New(TempAllocator &alloc, MDefinition *lhs, MDefinition *rhs, + MIRType type, uint32_t laneX, uint32_t laneY, uint32_t laneZ, + uint32_t laneW) { // Swap operands so that new lanes come from LHS in majority. // In the balanced case, swap operands if needs be, in order to be able @@ -1936,7 +1955,7 @@ class MSimdShuffle // If all lanes come from the same vector, just use swizzle instead. if (laneX < 4 && laneY < 4 && laneZ < 4 && laneW < 4) - return MSimdSwizzle::NewAsmJS(alloc, lhs, type, laneX, laneY, laneZ, laneW); + return MSimdSwizzle::New(alloc, lhs, type, laneX, laneY, laneZ, laneW); return new(alloc) MSimdShuffle(lhs, rhs, type, laneX, laneY, laneZ, laneW); } diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index 39097ad1a60..74b3e56b7b0 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -24,7 +24,7 @@ namespace jit { _(SimdInsertElement) \ _(SimdSignMask) \ _(SimdSwizzle) \ - _(SimdGeneralSwizzle) \ + _(SimdGeneralShuffle) \ _(SimdShuffle) \ _(SimdUnaryArith) \ _(SimdBinaryComp) \ diff --git a/js/src/jit/TypePolicy.cpp b/js/src/jit/TypePolicy.cpp index 8528644aa95..b7f9e95701e 100644 --- a/js/src/jit/TypePolicy.cpp +++ b/js/src/jit/TypePolicy.cpp @@ -786,23 +786,26 @@ template bool SimdPolicy<0>::adjustInputs(TempAllocator &alloc, MInstruction *ins); bool -SimdSwizzlePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) +SimdShufflePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) { MIRType specialization = ins->typePolicySpecialization(); - // First input is the vector input. - if (!MaybeSimdUnbox(alloc, ins, specialization, 0)) - return false; + MSimdGeneralShuffle *s = ins->toSimdGeneralShuffle(); + + for (unsigned i = 0; i < s->numVectors(); i++) { + if (!MaybeSimdUnbox(alloc, ins, specialization, i)) + return false; + } // Next inputs are the lanes, which need to be int32 - for (unsigned i = 0; i < 4; i++) { - MDefinition *in = ins->getOperand(i + 1); + for (unsigned i = 0; i < s->numLanes(); i++) { + MDefinition *in = ins->getOperand(s->numVectors() + i); if (in->type() == MIRType_Int32) continue; MInstruction *replace = MToInt32::New(alloc, in, MacroAssembler::IntConversion_NumbersOnly); ins->block()->insertBefore(ins, replace); - ins->replaceOperand(i + 1, replace); + ins->replaceOperand(s->numVectors() + i, replace); if (!replace->typePolicy()->adjustInputs(alloc, replace)) return false; } @@ -1115,7 +1118,7 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) _(PowPolicy) \ _(SimdAllPolicy) \ _(SimdSelectPolicy) \ - _(SimdSwizzlePolicy) \ + _(SimdShufflePolicy) \ _(StoreTypedArrayElementStaticPolicy) \ _(StoreTypedArrayHolePolicy) \ _(StoreUnboxedScalarPolicy) \ diff --git a/js/src/jit/TypePolicy.h b/js/src/jit/TypePolicy.h index 5f6cf4b6380..013f027b40c 100644 --- a/js/src/jit/TypePolicy.h +++ b/js/src/jit/TypePolicy.h @@ -330,7 +330,7 @@ class SimdSelectPolicy MOZ_FINAL : public TypePolicy virtual bool adjustInputs(TempAllocator &alloc, MInstruction *ins) MOZ_OVERRIDE; }; -class SimdSwizzlePolicy MOZ_FINAL : public TypePolicy +class SimdShufflePolicy MOZ_FINAL : public TypePolicy { public: SPECIALIZATION_DATA_; diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index 54cbdc37d7e..2e6d31d33e2 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -245,8 +245,8 @@ class CodeGeneratorARM : public CodeGeneratorShared void visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); } void visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); } void visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); } - void visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *lir) { MOZ_CRASH("NYI"); } - void visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *lir) { MOZ_CRASH("NYI"); } + void visitSimdGeneralShuffleI(LSimdGeneralShuffleI *lir) { MOZ_CRASH("NYI"); } + void visitSimdGeneralShuffleF(LSimdGeneralShuffleF *lir) { MOZ_CRASH("NYI"); } void visitSimdSwizzleI(LSimdSwizzleI *lir) { MOZ_CRASH("NYI"); } void visitSimdSwizzleF(LSimdSwizzleF *lir) { MOZ_CRASH("NYI"); } void visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); } diff --git a/js/src/jit/mips/CodeGenerator-mips.h b/js/src/jit/mips/CodeGenerator-mips.h index 8f3273dae66..7ba07cab280 100644 --- a/js/src/jit/mips/CodeGenerator-mips.h +++ b/js/src/jit/mips/CodeGenerator-mips.h @@ -290,8 +290,8 @@ class CodeGeneratorMIPS : public CodeGeneratorShared void visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); } void visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir) { MOZ_CRASH("NYI"); } void visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir) { MOZ_CRASH("NYI"); } - void visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *lir) { MOZ_CRASH("NYI"); } - void visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *lir) { MOZ_CRASH("NYI"); } + void visitSimdGeneralShuffleI(LSimdGeneralShuffleI *lir) { MOZ_CRASH("NYI"); } + void visitSimdGeneralShuffleF(LSimdGeneralShuffleF *lir) { MOZ_CRASH("NYI"); } }; typedef CodeGeneratorMIPS CodeGeneratorSpecific; diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.cpp b/js/src/jit/shared/CodeGenerator-x86-shared.cpp index 971f3c05c53..5079f79474a 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp @@ -2386,24 +2386,28 @@ CodeGeneratorX86Shared::visitSimdSignMaskX4(LSimdSignMaskX4 *ins) } void -CodeGeneratorX86Shared::visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *ins) +CodeGeneratorX86Shared::visitSimdGeneralShuffleI(LSimdGeneralShuffleI *ins) { - FloatRegister input = ToFloatRegister(ins->base()); + MSimdGeneralShuffle *mir = ins->mir(); + unsigned numVectors = mir->numVectors(); + Register temp = ToRegister(ins->temp()); // This won't generate fast code, but it's fine because we expect users - // to have used constant indices (and thus MSimdGeneralSwizzle to be fold - // into MSimdSwizzle, which are fast). - masm.reserveStack(Simd128DataSize * 2); + // to have used constant indices (and thus MSimdGeneralShuffle to be fold + // into MSimdSwizzle/MSimdShuffle, which are fast). + masm.reserveStack(Simd128DataSize * numVectors); - masm.storeAlignedInt32x4(input, Address(StackPointer, Simd128DataSize)); + for (unsigned i = 0; i < numVectors; i++) + masm.storeAlignedInt32x4(ToFloatRegister(ins->vector(i)), + Address(StackPointer, Simd128DataSize * (1 + i))); Label bail; - for (size_t i = 0; i < 4; i++) { + for (size_t i = 0; i < mir->numLanes(); i++) { Operand lane = ToOperand(ins->lane(i)); - masm.cmp32(lane, Imm32(3)); + masm.cmp32(lane, Imm32(mir->numVectors() * mir->numLanes() - 1)); masm.j(Assembler::Above, &bail); if (lane.kind() == Operand::REG) { @@ -2425,37 +2429,43 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *ins) { masm.bind(&bail); - masm.freeStack(Simd128DataSize * 2); + masm.freeStack(Simd128DataSize * numVectors); bailout(ins->snapshot()); } masm.bind(&join); - masm.setFramePushed(masm.framePushed() + Simd128DataSize * 2); - masm.freeStack(Simd128DataSize * 2); + masm.setFramePushed(masm.framePushed() + Simd128DataSize * numVectors); + masm.freeStack(Simd128DataSize * numVectors); } void -CodeGeneratorX86Shared::visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *ins) +CodeGeneratorX86Shared::visitSimdGeneralShuffleF(LSimdGeneralShuffleF *ins) { - FloatRegister input = ToFloatRegister(ins->base()); + MSimdGeneralShuffle *mir = ins->mir(); + unsigned numVectors = mir->numVectors(); + Register temp = ToRegister(ins->temp()); - // See comment in the visitSimdGeneralSwizzleI. - masm.reserveStack(Simd128DataSize * 2); + // This won't generate fast code, but it's fine because we expect users + // to have used constant indices (and thus MSimdGeneralShuffle to be fold + // into MSimdSwizzle/MSimdShuffle, which are fast). + masm.reserveStack(Simd128DataSize * numVectors); - masm.storeAlignedFloat32x4(input, Address(StackPointer, Simd128DataSize)); + for (unsigned i = 0; i < numVectors; i++) + masm.storeAlignedFloat32x4(ToFloatRegister(ins->vector(i)), + Address(StackPointer, Simd128DataSize * (1 + i))); Label bail; - for (size_t i = 0; i < 4; i++) { + for (size_t i = 0; i < mir->numLanes(); i++) { Operand lane = ToOperand(ins->lane(i)); - masm.cmp32(lane, Imm32(3)); + masm.cmp32(lane, Imm32(mir->numVectors() * mir->numLanes() - 1)); masm.j(Assembler::Above, &bail); if (lane.kind() == Operand::REG) { masm.loadFloat32(Operand(StackPointer, ToRegister(ins->lane(i)), TimesFour, Simd128DataSize), - ScratchFloat32Reg); + ScratchFloat32Reg); } else { masm.load32(lane, temp); masm.loadFloat32(Operand(StackPointer, temp, TimesFour, Simd128DataSize), ScratchFloat32Reg); @@ -2472,13 +2482,13 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *ins) { masm.bind(&bail); - masm.freeStack(Simd128DataSize * 2); + masm.freeStack(Simd128DataSize * numVectors); bailout(ins->snapshot()); } masm.bind(&join); - masm.setFramePushed(masm.framePushed() + Simd128DataSize * 2); - masm.freeStack(Simd128DataSize * 2); + masm.setFramePushed(masm.framePushed() + Simd128DataSize * numVectors); + masm.freeStack(Simd128DataSize * numVectors); } void diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.h b/js/src/jit/shared/CodeGenerator-x86-shared.h index 9b13ae7dece..175ccfcc76c 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.h +++ b/js/src/jit/shared/CodeGenerator-x86-shared.h @@ -258,8 +258,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared void visitSimdInsertElementI(LSimdInsertElementI *lir); void visitSimdInsertElementF(LSimdInsertElementF *lir); void visitSimdSignMaskX4(LSimdSignMaskX4 *ins); - void visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *lir); - void visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *lir); + void visitSimdGeneralShuffleI(LSimdGeneralShuffleI *lir); + void visitSimdGeneralShuffleF(LSimdGeneralShuffleF *lir); void visitSimdSwizzleI(LSimdSwizzleI *lir); void visitSimdSwizzleF(LSimdSwizzleF *lir); void visitSimdShuffle(LSimdShuffle *lir);