зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1025100: Implement MSimdInsertElement; r=sunfish
This commit is contained in:
Родитель
9e6ba6e2bd
Коммит
a9fe05decf
|
@ -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>
|
class LSimdSignMaskX4 : public LInstructionHelper<1, 1, 0>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
_(Float32x4) \
|
_(Float32x4) \
|
||||||
_(SimdExtractElementI) \
|
_(SimdExtractElementI) \
|
||||||
_(SimdExtractElementF) \
|
_(SimdExtractElementF) \
|
||||||
|
_(SimdInsertElementI) \
|
||||||
|
_(SimdInsertElementF) \
|
||||||
_(SimdSignMaskX4) \
|
_(SimdSignMaskX4) \
|
||||||
_(SimdBinaryCompIx4) \
|
_(SimdBinaryCompIx4) \
|
||||||
_(SimdBinaryCompFx4) \
|
_(SimdBinaryCompFx4) \
|
||||||
|
|
|
@ -3738,6 +3738,21 @@ LIRGenerator::visitSimdExtractElement(MSimdExtractElement *ins)
|
||||||
MOZ_CRASH("Unknown SIMD kind when extracting element");
|
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
|
bool
|
||||||
LIRGenerator::visitSimdSignMask(MSimdSignMask *ins)
|
LIRGenerator::visitSimdSignMask(MSimdSignMask *ins)
|
||||||
{
|
{
|
||||||
|
|
|
@ -269,6 +269,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||||
bool visitGetDOMMember(MGetDOMMember *ins);
|
bool visitGetDOMMember(MGetDOMMember *ins);
|
||||||
bool visitRecompileCheck(MRecompileCheck *ins);
|
bool visitRecompileCheck(MRecompileCheck *ins);
|
||||||
bool visitSimdExtractElement(MSimdExtractElement *ins);
|
bool visitSimdExtractElement(MSimdExtractElement *ins);
|
||||||
|
bool visitSimdInsertElement(MSimdInsertElement *ins);
|
||||||
bool visitSimdSignMask(MSimdSignMask *ins);
|
bool visitSimdSignMask(MSimdSignMask *ins);
|
||||||
bool visitSimdBinaryComp(MSimdBinaryComp *ins);
|
bool visitSimdBinaryComp(MSimdBinaryComp *ins);
|
||||||
bool visitSimdBinaryArith(MSimdBinaryArith *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.
|
// Extracts the sign bits from a given vector, returning an MIRType_Int32.
|
||||||
class MSimdSignMask : public MUnaryInstruction
|
class MSimdSignMask : public MUnaryInstruction
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace jit {
|
||||||
_(SimdSplatX4) \
|
_(SimdSplatX4) \
|
||||||
_(SimdConstant) \
|
_(SimdConstant) \
|
||||||
_(SimdExtractElement) \
|
_(SimdExtractElement) \
|
||||||
|
_(SimdInsertElement) \
|
||||||
_(SimdSignMask) \
|
_(SimdSignMask) \
|
||||||
_(SimdBinaryComp) \
|
_(SimdBinaryComp) \
|
||||||
_(SimdBinaryArith) \
|
_(SimdBinaryArith) \
|
||||||
|
|
|
@ -115,6 +115,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor
|
||||||
SAFE_OP(SimdSplatX4)
|
SAFE_OP(SimdSplatX4)
|
||||||
SAFE_OP(SimdConstant)
|
SAFE_OP(SimdConstant)
|
||||||
SAFE_OP(SimdExtractElement)
|
SAFE_OP(SimdExtractElement)
|
||||||
|
SAFE_OP(SimdInsertElement)
|
||||||
SAFE_OP(SimdSignMask)
|
SAFE_OP(SimdSignMask)
|
||||||
SAFE_OP(SimdBinaryComp)
|
SAFE_OP(SimdBinaryComp)
|
||||||
SAFE_OP(SimdBinaryArith)
|
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
|
// register-to-register form has different semantics (it doesn't clobber
|
||||||
// the whole output register) and isn't needed currently.
|
// the whole output register) and isn't needed currently.
|
||||||
void movsd(const Address &src, FloatRegister dest) {
|
void movsd(const Address &src, FloatRegister dest) {
|
||||||
|
@ -540,6 +540,10 @@ class AssemblerX86Shared : public AssemblerShared
|
||||||
void movsd(FloatRegister src, const BaseIndex &dest) {
|
void movsd(FloatRegister src, const BaseIndex &dest) {
|
||||||
masm.movsd_rm(src.code(), dest.offset, dest.base.code(), dest.index.code(), dest.scale);
|
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) {
|
void movss(const Address &src, FloatRegister dest) {
|
||||||
masm.movss_mr(src.offset, src.base.code(), dest.code());
|
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) {
|
void movss(FloatRegister src, const BaseIndex &dest) {
|
||||||
masm.movss_rm(src.code(), dest.offset, dest.base.code(), dest.index.code(), dest.scale);
|
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) {
|
void movdqu(const Operand &src, FloatRegister dest) {
|
||||||
JS_ASSERT(HasSSE2());
|
JS_ASSERT(HasSSE2());
|
||||||
switch (src.kind()) {
|
switch (src.kind()) {
|
||||||
|
|
|
@ -2284,6 +2284,57 @@ CodeGeneratorX86Shared::visitSimdExtractElementF(LSimdExtractElementF *ins)
|
||||||
return true;
|
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
|
bool
|
||||||
CodeGeneratorX86Shared::visitSimdSignMaskX4(LSimdSignMaskX4 *ins)
|
CodeGeneratorX86Shared::visitSimdSignMaskX4(LSimdSignMaskX4 *ins)
|
||||||
{
|
{
|
||||||
|
|
|
@ -214,6 +214,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||||
bool visitFloat32x4(LFloat32x4 *ins);
|
bool visitFloat32x4(LFloat32x4 *ins);
|
||||||
bool visitSimdExtractElementI(LSimdExtractElementI *lir);
|
bool visitSimdExtractElementI(LSimdExtractElementI *lir);
|
||||||
bool visitSimdExtractElementF(LSimdExtractElementF *lir);
|
bool visitSimdExtractElementF(LSimdExtractElementF *lir);
|
||||||
|
bool visitSimdInsertElementI(LSimdInsertElementI *lir);
|
||||||
|
bool visitSimdInsertElementF(LSimdInsertElementF *lir);
|
||||||
bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins);
|
bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins);
|
||||||
bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir);
|
bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir);
|
||||||
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir);
|
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче