Bug 1059529: SIMD x86-x64 backend: Implement bitwise operations; a=ijibaja,dougc,bbouvier; r=sunfish

This commit is contained in:
Ivan Jibaja 2014-08-27 18:07:03 -07:00
parent 80e5c8c723
commit 1e51b824ea
13 changed files with 222 additions and 8 deletions

View File

@ -266,6 +266,22 @@ class LSimdBinaryArithFx4 : public LSimdBinaryArith
LSimdBinaryArithFx4() : LSimdBinaryArith() {}
};
// Binary SIMD bitwise operation between two int32x4 or float32x4 operands
class LSimdBinaryBitwiseX4 : public LInstructionHelper<1, 2, 0>
{
public:
LIR_HEADER(SimdBinaryBitwiseX4);
const LAllocation *lhs() {
return getOperand(0);
}
const LAllocation *rhs() {
return getOperand(1);
}
MSimdBinaryBitwise::Operation operation() const {
return mir_->toSimdBinaryBitwise()->operation();
}
};
// Constant 32-bit integer.
class LInteger : public LInstructionHelper<1, 0, 0>
{

View File

@ -25,6 +25,7 @@
_(SimdBinaryCompFx4) \
_(SimdBinaryArithIx4) \
_(SimdBinaryArithFx4) \
_(SimdBinaryBitwiseX4) \
_(Value) \
_(CloneLiteral) \
_(Parameter) \

View File

@ -3765,6 +3765,20 @@ LIRGenerator::visitSimdBinaryArith(MSimdBinaryArith *ins)
return false;
}
bool
LIRGenerator::visitSimdBinaryBitwise(MSimdBinaryBitwise *ins)
{
MOZ_ASSERT(IsSimdType(ins->type()));
if (ins->type() == MIRType_Int32x4 || ins->type() == MIRType_Float32x4) {
LSimdBinaryBitwiseX4 *add = new(alloc()) LSimdBinaryBitwiseX4;
return lowerForFPU(add, ins, ins->lhs(), ins->rhs());
}
MOZ_CRASH("Unknown SIMD kind when doing bitwise operations");
return false;
}
static void
SpewResumePoint(MBasicBlock *block, MInstruction *ins, MResumePoint *resumePoint)
{

View File

@ -270,6 +270,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitSimdExtractElement(MSimdExtractElement *ins);
bool visitSimdBinaryComp(MSimdBinaryComp *ins);
bool visitSimdBinaryArith(MSimdBinaryArith *ins);
bool visitSimdBinaryBitwise(MSimdBinaryBitwise *ins);
bool visitSimdValueX4(MSimdValueX4 *ins);
bool visitSimdConstant(MSimdConstant *ins);
bool visitPhi(MPhi *ins);

View File

@ -1480,6 +1480,50 @@ class MSimdBinaryArith : public MBinaryInstruction
}
};
class MSimdBinaryBitwise : public MBinaryInstruction
{
public:
enum Operation {
and_,
or_,
xor_
};
private:
Operation operation_;
MSimdBinaryBitwise(MDefinition *left, MDefinition *right, Operation op, MIRType type)
: MBinaryInstruction(left, right), operation_(op)
{
MOZ_ASSERT(IsSimdType(type));
MOZ_ASSERT(left->type() == right->type());
MOZ_ASSERT(left->type() == type);
setResultType(type);
setMovable();
setCommutative();
}
public:
INSTRUCTION_HEADER(SimdBinaryBitwise);
static MSimdBinaryBitwise *NewAsmJS(TempAllocator &alloc, MDefinition *left,
MDefinition *right, Operation op, MIRType t)
{
return new(alloc) MSimdBinaryBitwise(left, right, op, t);
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
Operation operation() const { return operation_; }
bool congruentTo(const MDefinition *ins) const {
if (!binaryCongruentTo(ins))
return false;
return operation_ == ins->toSimdBinaryBitwise()->operation();
}
};
// Deep clone a constant JSObject.
class MCloneLiteral
: public MUnaryInstruction,

View File

@ -17,6 +17,7 @@ namespace jit {
_(SimdExtractElement) \
_(SimdBinaryComp) \
_(SimdBinaryArith) \
_(SimdBinaryBitwise) \
_(CloneLiteral) \
_(Parameter) \
_(Callee) \

View File

@ -117,6 +117,7 @@ class ParallelSafetyVisitor : public MDefinitionVisitor
SAFE_OP(SimdExtractElement)
SAFE_OP(SimdBinaryComp)
SAFE_OP(SimdBinaryArith)
SAFE_OP(SimdBinaryBitwise)
UNSAFE_OP(CloneLiteral)
SAFE_OP(Parameter)
SAFE_OP(Callee)

View File

@ -238,6 +238,7 @@ class CodeGeneratorARM : public CodeGeneratorShared
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir) { MOZ_CRASH("NYI"); }
bool visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); }
bool visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir) { MOZ_CRASH("NYI"); }
bool visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir) { MOZ_CRASH("NYI"); }
};
typedef CodeGeneratorARM CodeGeneratorSpecific;

View File

@ -1665,6 +1665,54 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_CRASH("unexpected operand kind");
}
}
void andps(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::FPREG:
masm.andps_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.andps_mr(src.disp(), src.base(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.andps_mr(src.address(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void orps(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::FPREG:
masm.orps_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.orps_mr(src.disp(), src.base(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.orps_mr(src.address(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void xorps(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::FPREG:
masm.xorps_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.xorps_mr(src.disp(), src.base(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.xorps_mr(src.address(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void pxor(FloatRegister src, FloatRegister dest) {
JS_ASSERT(HasSSE2());
masm.pxor_rr(src.code(), dest.code());

View File

@ -295,6 +295,9 @@ private:
OP2_CVTTSD2SI_GdWsd = 0x2C,
OP2_UCOMISD_VsdWsd = 0x2E,
OP2_MOVMSKPD_EdVd = 0x50,
OP2_ANDPS_VpsWps = 0x54,
OP2_ORPS_VpsWps = 0x56,
OP2_XORPS_VpsWps = 0x57,
OP2_ADDSD_VsdWsd = 0x58,
OP2_ADDPS_VpsWps = 0x58,
OP2_MULSD_VsdWsd = 0x59,
@ -3424,13 +3427,6 @@ public:
m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
}
void xorps_rr(XMMRegisterID src, XMMRegisterID dst)
{
spew("xorps %s, %s",
nameFPReg(src), nameFPReg(dst));
m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
}
void orpd_rr(XMMRegisterID src, XMMRegisterID dst)
{
spew("orpd %s, %s",
@ -3451,7 +3447,63 @@ public:
{
spew("andps %s, %s",
nameFPReg(src), nameFPReg(dst));
m_formatter.twoByteOp(OP2_ANDPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
m_formatter.twoByteOp(OP2_ANDPS_VpsWps, (RegisterID)dst, (RegisterID)src);
}
void andps_mr(int offset, RegisterID base, XMMRegisterID dst)
{
spew("andps %s0x%x(%s), %s",
PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
m_formatter.twoByteOp(OP2_ANDPS_VpsWps, (RegisterID)dst, base, offset);
}
void andps_mr(const void* address, XMMRegisterID dst)
{
spew("andps %p, %s",
address, nameFPReg(dst));
m_formatter.twoByteOp(OP2_ANDPS_VpsWps, (RegisterID)dst, address);
}
void orps_rr(XMMRegisterID src, XMMRegisterID dst)
{
spew("orps %s, %s",
nameFPReg(src), nameFPReg(dst));
m_formatter.twoByteOp(OP2_ORPS_VpsWps, (RegisterID)dst, (RegisterID)src);
}
void orps_mr(int offset, RegisterID base, XMMRegisterID dst)
{
spew("orps %s0x%x(%s), %s",
PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
m_formatter.twoByteOp(OP2_ORPS_VpsWps, (RegisterID)dst, base, offset);
}
void orps_mr(const void* address, XMMRegisterID dst)
{
spew("orps %p, %s",
address, nameFPReg(dst));
m_formatter.twoByteOp(OP2_ORPS_VpsWps, (RegisterID)dst, address);
}
void xorps_rr(XMMRegisterID src, XMMRegisterID dst)
{
spew("xorps %s, %s",
nameFPReg(src), nameFPReg(dst));
m_formatter.twoByteOp(OP2_XORPS_VpsWps, (RegisterID)dst, (RegisterID)src);
}
void xorps_mr(int offset, RegisterID base, XMMRegisterID dst)
{
spew("xorps %s0x%x(%s), %s",
PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
m_formatter.twoByteOp(OP2_XORPS_VpsWps, (RegisterID)dst, base, offset);
}
void xorps_mr(const void* address, XMMRegisterID dst)
{
spew("xorps %p, %s",
address, nameFPReg(dst));
m_formatter.twoByteOp(OP2_XORPS_VpsWps, (RegisterID)dst, address);
}
void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)

View File

@ -2309,6 +2309,28 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
MOZ_CRASH("unexpected SIMD op");
}
bool
CodeGeneratorX86Shared::visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *ins)
{
FloatRegister lhs = ToFloatRegister(ins->lhs());
Operand rhs = ToOperand(ins->rhs());
MOZ_ASSERT(ToFloatRegister(ins->output()) == lhs);
MSimdBinaryBitwise::Operation op = ins->operation();
switch (op) {
case MSimdBinaryBitwise::and_:
masm.bitwiseAndX4(rhs, lhs);
return true;
case MSimdBinaryBitwise::or_:
masm.bitwiseOrX4(rhs, lhs);
return true;
case MSimdBinaryBitwise::xor_:
masm.bitwiseXorX4(rhs, lhs);
return true;
}
MOZ_CRASH("unexpected SIMD bitwise op");
}
bool
CodeGeneratorX86Shared::visitForkJoinGetSlice(LForkJoinGetSlice *ins)
{

View File

@ -215,6 +215,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir);
bool visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir);
bool visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir);
bool visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir);
// Out of line visitors.
bool visitOutOfLineBailout(OutOfLineBailout *ool);

View File

@ -467,6 +467,18 @@ class MacroAssemblerX86Shared : public Assembler
cvtsd2ss(src, dest);
}
void bitwiseAndX4(const Operand &src, FloatRegister dest) {
// TODO Using the "ps" variant for all types incurs a domain crossing
// penalty for integer types and double.
andps(src, dest);
}
void bitwiseOrX4(const Operand &src, FloatRegister dest) {
orps(src, dest);
}
void bitwiseXorX4(const Operand &src, FloatRegister dest) {
xorps(src, dest);
}
void loadAlignedInt32x4(const Address &src, FloatRegister dest) {
movdqa(Operand(src), dest);
}