Bug 1094855: Implement SIMD.float32x4.minNum/maxNum in the JITs; r=sunfish

This commit is contained in:
Benjamin Bouvier 2014-11-21 17:27:40 +01:00
parent 9d4ff51379
commit 286105327c
4 changed files with 66 additions and 10 deletions

View File

@ -4083,7 +4083,9 @@ LIRGenerator::visitSimdBinaryArith(MSimdBinaryArith *ins)
LSimdBinaryArithFx4 *lir = new(alloc()) LSimdBinaryArithFx4();
bool needsTemp = ins->operation() == MSimdBinaryArith::Max;
bool needsTemp = ins->operation() == MSimdBinaryArith::Max ||
ins->operation() == MSimdBinaryArith::MinNum ||
ins->operation() == MSimdBinaryArith::MaxNum;
lir->setTemp(0, needsTemp ? temp(LDefinition::FLOAT32X4) : LDefinition::BogusTemp());
return lowerForFPU(lir, ins, lhs, rhs);

View File

@ -1857,17 +1857,21 @@ class MSimdBinaryArith : public MBinaryInstruction
Mul,
Div,
Min,
Max
Max,
MinNum,
MaxNum
};
static const char* OperationName(Operation op) {
switch (op) {
case Add: return "Add";
case Sub: return "Sub";
case Mul: return "Mul";
case Div: return "Div";
case Min: return "Min";
case Max: return "Max";
case Add: return "Add";
case Sub: return "Sub";
case Mul: return "Mul";
case Div: return "Div";
case Min: return "Min";
case Max: return "Max";
case MinNum: return "MinNum";
case MaxNum: return "MaxNum";
}
MOZ_CRASH("unexpected operation");
}

View File

@ -1907,6 +1907,7 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void andnps(const Operand &src, FloatRegister dest) {
// Negates bits of dest and then applies AND
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::FPREG:

View File

@ -2769,6 +2769,9 @@ CodeGeneratorX86Shared::visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *ins)
// we can do max with a single instruction only if we have SSE4.1
// using the PMINSD instruction.
break;
case MSimdBinaryArith::MinNum:
case MSimdBinaryArith::MaxNum:
break;
}
MOZ_CRASH("unexpected SIMD op");
}
@ -2815,6 +2818,54 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
masm.orps(rhsCopy, lhs); // NaN or'd with arbitrary bits is NaN
return true;
}
case MSimdBinaryArith::MinNum: {
FloatRegister tmp = ToFloatRegister(ins->temp());
masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), ScratchSimdReg);
masm.movdqa(ScratchSimdReg, tmp);
FloatRegister mask = ScratchSimdReg;
masm.pcmpeqd(Operand(lhs), mask);
masm.andps(tmp, mask);
masm.movaps(lhs, tmp);
masm.minps(rhs, tmp);
masm.orps(mask, tmp);
masm.movaps(rhs, mask);
masm.cmpneqps(Operand(mask), mask);
// Emulates blendv
masm.andps(Operand(mask), lhs);
masm.andnps(Operand(tmp), mask);
masm.orps(Operand(mask), lhs);
return true;
}
case MSimdBinaryArith::MaxNum: {
FloatRegister mask = ScratchSimdReg;
masm.loadConstantInt32x4(SimdConstant::SplatX4(0), mask);
masm.pcmpeqd(Operand(lhs), mask);
FloatRegister tmp = ToFloatRegister(ins->temp());
masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), tmp);
masm.andps(tmp, mask);
masm.movaps(lhs, tmp);
masm.maxps(rhs, tmp);
masm.andnps(Operand(tmp), mask);
// Ensure tmp always contains the temporary result
mask = tmp;
tmp = ScratchSimdReg;
masm.movaps(rhs, mask);
masm.cmpneqps(Operand(mask), mask);
// Emulates blendv
masm.andps(Operand(mask), lhs);
masm.andnps(Operand(tmp), mask);
masm.orps(Operand(mask), lhs);
return true;
}
}
MOZ_CRASH("unexpected SIMD op");
}
@ -2965,8 +3016,6 @@ CodeGeneratorX86Shared::visitSimdSelect(LSimdSelect *ins)
FloatRegister onFalse = ToFloatRegister(ins->rhs());
MOZ_ASSERT(onTrue == ToFloatRegister(ins->output()));
// The onFalse argument is not destroyed but due to limitations of the
// register allocator its life ends at the start of the operation.
masm.bitwiseAndX4(Operand(mask), onTrue);
masm.bitwiseAndNotX4(Operand(onFalse), mask);
masm.bitwiseOrX4(Operand(mask), onTrue);