Bug 1135039: Generalize swizzle MIR node to SimdGeneralShuffle; r=sunfish

This commit is contained in:
Benjamin Bouvier 2015-03-18 20:07:45 +01:00
parent 85af73e764
commit 6a2263406f
18 changed files with 266 additions and 131 deletions

View File

@ -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;
}

View File

@ -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) \

View File

@ -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);

View File

@ -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);

View File

@ -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)
{}
};

View File

@ -28,8 +28,8 @@
_(SimdInsertElementI) \
_(SimdInsertElementF) \
_(SimdSignMaskX4) \
_(SimdGeneralSwizzleI) \
_(SimdGeneralSwizzleF) \
_(SimdGeneralShuffleI) \
_(SimdGeneralShuffleF) \
_(SimdSwizzleI) \
_(SimdSwizzleF) \
_(SimdShuffle) \

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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<uint32_t> 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 <typename T>

View File

@ -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);
}

View File

@ -24,7 +24,7 @@ namespace jit {
_(SimdInsertElement) \
_(SimdSignMask) \
_(SimdSwizzle) \
_(SimdGeneralSwizzle) \
_(SimdGeneralShuffle) \
_(SimdShuffle) \
_(SimdUnaryArith) \
_(SimdBinaryComp) \

View File

@ -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) \

View File

@ -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_;

View File

@ -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"); }

View File

@ -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;

View File

@ -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

View File

@ -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);