Bug 1021716: SIMD x86x-64: Implement MSimdSwizzle; r=sunfish

This commit is contained in:
Benjamin Bouvier 2014-06-18 22:38:00 +02:00
Родитель 5e55d9abaa
Коммит 39ac3875bc
10 изменённых файлов: 157 добавлений и 0 удалений

Просмотреть файл

@ -229,6 +229,42 @@ class LSimdSignMaskX4 : public LInstructionHelper<1, 1, 0>
} }
}; };
// Base class for both int32x4 and float32x4 shuffle instructions.
class LSimdSwizzleBase : public LInstructionHelper<1, 1, 0>
{
public:
LSimdSwizzleBase(const LAllocation &base)
{
setOperand(0, base);
}
const LAllocation *getBase() {
return getOperand(0);
}
SimdLane laneX() const { return mir_->toSimdSwizzle()->laneX(); }
SimdLane laneY() const { return mir_->toSimdSwizzle()->laneY(); }
SimdLane laneZ() const { return mir_->toSimdSwizzle()->laneZ(); }
SimdLane laneW() const { return mir_->toSimdSwizzle()->laneW(); }
};
// Shuffles a int32x4 into another int32x4 vector.
class LSimdSwizzleI : public LSimdSwizzleBase
{
public:
LIR_HEADER(SimdSwizzleI);
LSimdSwizzleI(const LAllocation &base) : LSimdSwizzleBase(base)
{}
};
// Shuffles a float32x4 into another float32x4 vector.
class LSimdSwizzleF : public LSimdSwizzleBase
{
public:
LIR_HEADER(SimdSwizzleF);
LSimdSwizzleF(const LAllocation &base) : LSimdSwizzleBase(base)
{}
};
// Binary SIMD comparison operation between two SIMD operands // Binary SIMD comparison operation between two SIMD operands
class LSimdBinaryComp: public LInstructionHelper<1, 2, 0> class LSimdBinaryComp: public LInstructionHelper<1, 2, 0>
{ {

Просмотреть файл

@ -24,6 +24,8 @@
_(SimdInsertElementI) \ _(SimdInsertElementI) \
_(SimdInsertElementF) \ _(SimdInsertElementF) \
_(SimdSignMaskX4) \ _(SimdSignMaskX4) \
_(SimdSwizzleI) \
_(SimdSwizzleF) \
_(SimdUnaryArithIx4) \ _(SimdUnaryArithIx4) \
_(SimdUnaryArithFx4) \ _(SimdUnaryArithFx4) \
_(SimdBinaryCompIx4) \ _(SimdBinaryCompIx4) \

Просмотреть файл

@ -3808,6 +3808,28 @@ LIRGenerator::visitSimdSignMask(MSimdSignMask *ins)
} }
} }
bool
LIRGenerator::visitSimdSwizzle(MSimdSwizzle *ins)
{
MOZ_ASSERT(IsSimdType(ins->input()->type()));
MOZ_ASSERT(IsSimdType(ins->type()));
if (ins->input()->type() == MIRType_Int32x4) {
LUse use = useRegisterAtStart(ins->input());
LSimdSwizzleI *lir = new (alloc()) LSimdSwizzleI(use);
return define(lir, ins);
}
if (ins->input()->type() == MIRType_Float32x4) {
LUse use = useRegisterAtStart(ins->input());
LSimdSwizzleF *lir = new (alloc()) LSimdSwizzleF(use);
return define(lir, ins);
}
MOZ_CRASH("Unknown SIMD kind when getting lane");
return false;
}
bool bool
LIRGenerator::visitSimdUnaryArith(MSimdUnaryArith *ins) LIRGenerator::visitSimdUnaryArith(MSimdUnaryArith *ins)
{ {

Просмотреть файл

@ -272,6 +272,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitSimdExtractElement(MSimdExtractElement *ins); bool visitSimdExtractElement(MSimdExtractElement *ins);
bool visitSimdInsertElement(MSimdInsertElement *ins); bool visitSimdInsertElement(MSimdInsertElement *ins);
bool visitSimdSignMask(MSimdSignMask *ins); bool visitSimdSignMask(MSimdSignMask *ins);
bool visitSimdSwizzle(MSimdSwizzle *ins);
bool visitSimdUnaryArith(MSimdUnaryArith *ins); bool visitSimdUnaryArith(MSimdUnaryArith *ins);
bool visitSimdBinaryComp(MSimdBinaryComp *ins); bool visitSimdBinaryComp(MSimdBinaryComp *ins);
bool visitSimdBinaryArith(MSimdBinaryArith *ins); bool visitSimdBinaryArith(MSimdBinaryArith *ins);

Просмотреть файл

@ -1575,6 +1575,72 @@ class MSimdSignMask : public MUnaryInstruction
ALLOW_CLONE(MSimdSignMask) ALLOW_CLONE(MSimdSignMask)
}; };
// Applies a shuffle operation to the input, putting the input lanes as
// indicated in the output register's lanes. This implements the SIMD.js
// "shuffle" function, that takes one vector and one mask.
class MSimdSwizzle : public MUnaryInstruction
{
protected:
// As of now, there are at most 4 lanes.
SimdLane laneX_;
SimdLane laneY_;
SimdLane laneZ_;
SimdLane laneW_;
MSimdSwizzle(MDefinition *obj, MIRType type,
SimdLane laneX, SimdLane laneY, SimdLane laneZ, SimdLane laneW)
: MUnaryInstruction(obj),
laneX_(laneX), laneY_(laneY), laneZ_(laneZ), laneW_(laneW)
{
MOZ_ASSERT(IsSimdType(obj->type()));
// Returned value needs to be in a vector too
MOZ_ASSERT(IsSimdType(type));
MOZ_ASSERT(SimdTypeToScalarType(obj->type()) == type);
mozilla::DebugOnly<uint32_t> expectedLength = SimdTypeToLength(obj->type());
MOZ_ASSERT(uint32_t(laneX_) < expectedLength);
MOZ_ASSERT(uint32_t(laneY_) < expectedLength);
MOZ_ASSERT(uint32_t(laneZ_) < expectedLength);
MOZ_ASSERT(uint32_t(laneW_) < expectedLength);
setResultType(type);
setMovable();
}
public:
INSTRUCTION_HEADER(SimdSwizzle);
static MSimdSwizzle *NewAsmJS(TempAllocator &alloc, MDefinition *obj, MIRType type,
SimdLane laneX, SimdLane laneY, SimdLane laneZ, SimdLane laneW)
{
return new(alloc) MSimdSwizzle(obj, type, laneX, laneY, laneZ, laneW);
}
SimdLane laneX() const { return laneX_; }
SimdLane laneY() const { return laneY_; }
SimdLane laneZ() const { return laneZ_; }
SimdLane laneW() const { return laneW_; }
AliasSet getAliasSet() const {
return AliasSet::None();
}
bool congruentTo(const MDefinition *ins) const {
if (!ins->isSimdSwizzle())
return false;
const MSimdSwizzle *other = ins->toSimdSwizzle();
if (other->laneX_ != laneX_ ||
other->laneY_ != laneY_ ||
other->laneZ_ != laneZ_ ||
other->laneW_ != laneW_)
{
return false;
}
return congruentIfOperandsEqual(other);
}
ALLOW_CLONE(MSimdSwizzle)
};
class MSimdUnaryArith : public MUnaryInstruction class MSimdUnaryArith : public MUnaryInstruction
{ {
public: public:

Просмотреть файл

@ -20,6 +20,7 @@ namespace jit {
_(SimdExtractElement) \ _(SimdExtractElement) \
_(SimdInsertElement) \ _(SimdInsertElement) \
_(SimdSignMask) \ _(SimdSignMask) \
_(SimdSwizzle) \
_(SimdUnaryArith) \ _(SimdUnaryArith) \
_(SimdBinaryComp) \ _(SimdBinaryComp) \
_(SimdBinaryArith) \ _(SimdBinaryArith) \

Просмотреть файл

@ -119,6 +119,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor
SAFE_OP(SimdExtractElement) SAFE_OP(SimdExtractElement)
SAFE_OP(SimdInsertElement) SAFE_OP(SimdInsertElement)
SAFE_OP(SimdSignMask) SAFE_OP(SimdSignMask)
SAFE_OP(SimdSwizzle)
SAFE_OP(SimdUnaryArith) SAFE_OP(SimdUnaryArith)
SAFE_OP(SimdBinaryComp) SAFE_OP(SimdBinaryComp)
SAFE_OP(SimdBinaryArith) SAFE_OP(SimdBinaryArith)

Просмотреть файл

@ -222,6 +222,8 @@ class CodeGeneratorARM : public CodeGeneratorShared
bool visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); } bool visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); }
bool visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); } bool visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); }
bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); } bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); }
bool visitSimdSwizzleI(LSimdSwizzleI *lir) { MOZ_CRASH("NYI"); }
bool visitSimdSwizzleF(LSimdSwizzleF *lir) { MOZ_CRASH("NYI"); }
bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); } bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); }
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir) { MOZ_CRASH("NYI"); } bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir) { MOZ_CRASH("NYI"); }
bool visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); } bool visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); }

Просмотреть файл

@ -2388,6 +2388,30 @@ CodeGeneratorX86Shared::visitSimdSignMaskX4(LSimdSignMaskX4 *ins)
return true; return true;
} }
bool
CodeGeneratorX86Shared::visitSimdSwizzleI(LSimdSwizzleI *ins)
{
FloatRegister input = ToFloatRegister(ins->input());
FloatRegister output = ToFloatRegister(ins->output());
uint32_t mask = MacroAssembler::ComputeShuffleMask(ins->laneX(), ins->laneY(), ins->laneZ(),
ins->laneW());
masm.shuffleInt32(mask, input, output);
return true;
}
bool
CodeGeneratorX86Shared::visitSimdSwizzleF(LSimdSwizzleF *ins)
{
FloatRegister input = ToFloatRegister(ins->input());
FloatRegister output = ToFloatRegister(ins->output());
uint32_t mask = MacroAssembler::ComputeShuffleMask(ins->laneX(), ins->laneY(), ins->laneZ(),
ins->laneW());
masm.shuffleFloat32(mask, input, output);
return true;
}
bool bool
CodeGeneratorX86Shared::visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *ins) CodeGeneratorX86Shared::visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *ins)
{ {

Просмотреть файл

@ -219,6 +219,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
bool visitSimdInsertElementI(LSimdInsertElementI *lir); bool visitSimdInsertElementI(LSimdInsertElementI *lir);
bool visitSimdInsertElementF(LSimdInsertElementF *lir); bool visitSimdInsertElementF(LSimdInsertElementF *lir);
bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins); bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins);
bool visitSimdSwizzleI(LSimdSwizzleI *lir);
bool visitSimdSwizzleF(LSimdSwizzleF *lir);
bool visitSimdUnaryArithIx4(LSimdUnaryArithIx4 *lir); bool visitSimdUnaryArithIx4(LSimdUnaryArithIx4 *lir);
bool visitSimdUnaryArithFx4(LSimdUnaryArithFx4 *lir); bool visitSimdUnaryArithFx4(LSimdUnaryArithFx4 *lir);
bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir); bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir);