Bug 1025100: Implement MSimdInsertElement; r=sunfish

This commit is contained in:
Benjamin Bouvier 2014-09-19 14:53:25 +02:00
Родитель 9e6ba6e2bd
Коммит a9fe05decf
10 изменённых файлов: 166 добавлений и 1 удалений

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

@ -178,6 +178,47 @@ class LSimdExtractElementF : public LSimdExtractElementBase
{}
};
class LSimdInsertElementBase : public LInstructionHelper<1, 2, 0>
{
protected:
LSimdInsertElementBase(const LAllocation &vec, const LAllocation &val)
{
setOperand(0, vec);
setOperand(1, val);
}
public:
const LAllocation *vector() {
return getOperand(0);
}
const LAllocation *value() {
return getOperand(1);
}
const SimdLane lane() const {
return mir_->toSimdInsertElement()->lane();
}
};
// Replace an element from a given SIMD int32x4 lane with a given value.
class LSimdInsertElementI : public LSimdInsertElementBase
{
public:
LIR_HEADER(SimdInsertElementI);
LSimdInsertElementI(const LAllocation &vec, const LAllocation &val)
: LSimdInsertElementBase(vec, val)
{}
};
// Replace an element from a given SIMD float32x4 lane with a given value.
class LSimdInsertElementF : public LSimdInsertElementBase
{
public:
LIR_HEADER(SimdInsertElementF);
LSimdInsertElementF(const LAllocation &vec, const LAllocation &val)
: LSimdInsertElementBase(vec, val)
{}
};
class LSimdSignMaskX4 : public LInstructionHelper<1, 1, 0>
{
public:

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

@ -21,6 +21,8 @@
_(Float32x4) \
_(SimdExtractElementI) \
_(SimdExtractElementF) \
_(SimdInsertElementI) \
_(SimdInsertElementF) \
_(SimdSignMaskX4) \
_(SimdBinaryCompIx4) \
_(SimdBinaryCompFx4) \

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

@ -3738,6 +3738,21 @@ LIRGenerator::visitSimdExtractElement(MSimdExtractElement *ins)
MOZ_CRASH("Unknown SIMD kind when extracting element");
}
bool
LIRGenerator::visitSimdInsertElement(MSimdInsertElement *ins)
{
JS_ASSERT(IsSimdType(ins->type()));
LUse vec = useRegisterAtStart(ins->vector());
LUse val = useRegister(ins->value());
if (ins->type() == MIRType_Int32x4)
return defineReuseInput(new(alloc()) LSimdInsertElementI(vec, val), ins, 0);
if (ins->type() == MIRType_Float32x4)
return defineReuseInput(new(alloc()) LSimdInsertElementF(vec, val), ins, 0);
MOZ_CRASH("Unknown SIMD kind when generating constant");
}
bool
LIRGenerator::visitSimdSignMask(MSimdSignMask *ins)
{

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

@ -269,6 +269,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitGetDOMMember(MGetDOMMember *ins);
bool visitRecompileCheck(MRecompileCheck *ins);
bool visitSimdExtractElement(MSimdExtractElement *ins);
bool visitSimdInsertElement(MSimdInsertElement *ins);
bool visitSimdSignMask(MSimdSignMask *ins);
bool visitSimdBinaryComp(MSimdBinaryComp *ins);
bool visitSimdBinaryArith(MSimdBinaryArith *ins);

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

@ -1402,6 +1402,50 @@ class MSimdExtractElement : public MUnaryInstruction
}
};
// Replaces the datum in the given lane by a scalar value of the same type.
class MSimdInsertElement : public MBinaryInstruction
{
private:
SimdLane lane_;
MSimdInsertElement(MDefinition *vec, MDefinition *val, MIRType type, SimdLane lane)
: MBinaryInstruction(vec, val), lane_(lane)
{
MOZ_ASSERT(IsSimdType(type) && vec->type() == type);
MOZ_ASSERT(SimdTypeToScalarType(type) == val->type());
setMovable();
setResultType(type);
}
public:
INSTRUCTION_HEADER(SimdInsertElement)
static MSimdInsertElement *NewAsmJS(TempAllocator &alloc, MDefinition *vec, MDefinition *val,
MIRType type, SimdLane lane)
{
return new(alloc) MSimdInsertElement(vec, val, type, lane);
}
MDefinition *vector() {
return getOperand(0);
}
MDefinition *value() {
return getOperand(1);
}
SimdLane lane() const {
return lane_;
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
bool congruentTo(const MDefinition *ins) const {
return binaryCongruentTo(ins) && lane_ == ins->toSimdInsertElement()->lane();
}
};
// Extracts the sign bits from a given vector, returning an MIRType_Int32.
class MSimdSignMask : public MUnaryInstruction
{

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

@ -16,6 +16,7 @@ namespace jit {
_(SimdSplatX4) \
_(SimdConstant) \
_(SimdExtractElement) \
_(SimdInsertElement) \
_(SimdSignMask) \
_(SimdBinaryComp) \
_(SimdBinaryArith) \

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

@ -115,6 +115,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor
SAFE_OP(SimdSplatX4)
SAFE_OP(SimdConstant)
SAFE_OP(SimdExtractElement)
SAFE_OP(SimdInsertElement)
SAFE_OP(SimdSignMask)
SAFE_OP(SimdBinaryComp)
SAFE_OP(SimdBinaryArith)

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

@ -525,7 +525,7 @@ class AssemblerX86Shared : public AssemblerShared
}
}
// movsd and movss are only provided in load/store form since the
// movsd is only provided in load/store form since the
// register-to-register form has different semantics (it doesn't clobber
// the whole output register) and isn't needed currently.
void movsd(const Address &src, FloatRegister dest) {
@ -540,6 +540,10 @@ class AssemblerX86Shared : public AssemblerShared
void movsd(FloatRegister src, const BaseIndex &dest) {
masm.movsd_rm(src.code(), dest.offset, dest.base.code(), dest.index.code(), dest.scale);
}
// Although movss is not only provided in load/store form (for the same
// reasons as movsd above), the register to register form should be only
// used in contexts where we care about not clearing the higher lanes of
// the FloatRegister.
void movss(const Address &src, FloatRegister dest) {
masm.movss_mr(src.offset, src.base.code(), dest.code());
}
@ -552,6 +556,9 @@ class AssemblerX86Shared : public AssemblerShared
void movss(FloatRegister src, const BaseIndex &dest) {
masm.movss_rm(src.code(), dest.offset, dest.base.code(), dest.index.code(), dest.scale);
}
void movss(FloatRegister src, const FloatRegister &dest) {
masm.movss_rr(src.code(), dest.code());
}
void movdqu(const Operand &src, FloatRegister dest) {
JS_ASSERT(HasSSE2());
switch (src.kind()) {

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

@ -2284,6 +2284,57 @@ CodeGeneratorX86Shared::visitSimdExtractElementF(LSimdExtractElementF *ins)
return true;
}
bool
CodeGeneratorX86Shared::visitSimdInsertElementI(LSimdInsertElementI *ins)
{
FloatRegister vector = ToFloatRegister(ins->vector());
Register value = ToRegister(ins->value());
FloatRegister output = ToFloatRegister(ins->output());
MOZ_ASSERT(vector == output); // defineReuseInput(0)
unsigned component = unsigned(ins->lane());
// Note that, contrarily to float32x4, we cannot use movd if the inserted
// value goes into the first component, as movd clears out the higher lanes
// of the output.
if (AssemblerX86Shared::HasSSE41()) {
masm.pinsrd(component, value, output);
return true;
}
masm.reserveStack(Simd128DataSize);
masm.storeAlignedInt32x4(vector, Address(StackPointer, 0));
masm.store32(value, Address(StackPointer, component * sizeof(int32_t)));
masm.loadAlignedInt32x4(Address(StackPointer, 0), output);
masm.freeStack(Simd128DataSize);
return true;
}
bool
CodeGeneratorX86Shared::visitSimdInsertElementF(LSimdInsertElementF *ins)
{
FloatRegister vector = ToFloatRegister(ins->vector());
FloatRegister value = ToFloatRegister(ins->value());
FloatRegister output = ToFloatRegister(ins->output());
MOZ_ASSERT(vector == output); // defineReuseInput(0)
if (ins->lane() == SimdLane::LaneX) {
// As both operands are registers, movss doesn't modify the upper bits
// of the destination operand.
if (value != output)
masm.movss(value, output);
return true;
}
unsigned component = unsigned(ins->lane());
masm.reserveStack(Simd128DataSize);
masm.storeAlignedFloat32x4(vector, Address(StackPointer, 0));
masm.storeFloat32(value, Address(StackPointer, component * sizeof(int32_t)));
masm.loadAlignedFloat32x4(Address(StackPointer, 0), output);
masm.freeStack(Simd128DataSize);
return true;
}
bool
CodeGeneratorX86Shared::visitSimdSignMaskX4(LSimdSignMaskX4 *ins)
{

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

@ -214,6 +214,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
bool visitFloat32x4(LFloat32x4 *ins);
bool visitSimdExtractElementI(LSimdExtractElementI *lir);
bool visitSimdExtractElementF(LSimdExtractElementF *lir);
bool visitSimdInsertElementI(LSimdInsertElementI *lir);
bool visitSimdInsertElementF(LSimdInsertElementF *lir);
bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins);
bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir);
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir);