зеркало из 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>
|
||||
{
|
||||
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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче