mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1094855: Implement SIMD.float32x4.minNum/maxNum in the JITs; r=sunfish
This commit is contained in:
parent
9d4ff51379
commit
286105327c
@ -4083,7 +4083,9 @@ LIRGenerator::visitSimdBinaryArith(MSimdBinaryArith *ins)
|
|||||||
|
|
||||||
LSimdBinaryArithFx4 *lir = new(alloc()) LSimdBinaryArithFx4();
|
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());
|
lir->setTemp(0, needsTemp ? temp(LDefinition::FLOAT32X4) : LDefinition::BogusTemp());
|
||||||
|
|
||||||
return lowerForFPU(lir, ins, lhs, rhs);
|
return lowerForFPU(lir, ins, lhs, rhs);
|
||||||
|
@ -1857,17 +1857,21 @@ class MSimdBinaryArith : public MBinaryInstruction
|
|||||||
Mul,
|
Mul,
|
||||||
Div,
|
Div,
|
||||||
Min,
|
Min,
|
||||||
Max
|
Max,
|
||||||
|
MinNum,
|
||||||
|
MaxNum
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* OperationName(Operation op) {
|
static const char* OperationName(Operation op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Add: return "Add";
|
case Add: return "Add";
|
||||||
case Sub: return "Sub";
|
case Sub: return "Sub";
|
||||||
case Mul: return "Mul";
|
case Mul: return "Mul";
|
||||||
case Div: return "Div";
|
case Div: return "Div";
|
||||||
case Min: return "Min";
|
case Min: return "Min";
|
||||||
case Max: return "Max";
|
case Max: return "Max";
|
||||||
|
case MinNum: return "MinNum";
|
||||||
|
case MaxNum: return "MaxNum";
|
||||||
}
|
}
|
||||||
MOZ_CRASH("unexpected operation");
|
MOZ_CRASH("unexpected operation");
|
||||||
}
|
}
|
||||||
|
@ -1907,6 +1907,7 @@ class AssemblerX86Shared : public AssemblerShared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void andnps(const Operand &src, FloatRegister dest) {
|
void andnps(const Operand &src, FloatRegister dest) {
|
||||||
|
// Negates bits of dest and then applies AND
|
||||||
MOZ_ASSERT(HasSSE2());
|
MOZ_ASSERT(HasSSE2());
|
||||||
switch (src.kind()) {
|
switch (src.kind()) {
|
||||||
case Operand::FPREG:
|
case Operand::FPREG:
|
||||||
|
@ -2769,6 +2769,9 @@ CodeGeneratorX86Shared::visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *ins)
|
|||||||
// we can do max with a single instruction only if we have SSE4.1
|
// we can do max with a single instruction only if we have SSE4.1
|
||||||
// using the PMINSD instruction.
|
// using the PMINSD instruction.
|
||||||
break;
|
break;
|
||||||
|
case MSimdBinaryArith::MinNum:
|
||||||
|
case MSimdBinaryArith::MaxNum:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
MOZ_CRASH("unexpected SIMD op");
|
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
|
masm.orps(rhsCopy, lhs); // NaN or'd with arbitrary bits is NaN
|
||||||
return true;
|
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");
|
MOZ_CRASH("unexpected SIMD op");
|
||||||
}
|
}
|
||||||
@ -2965,8 +3016,6 @@ CodeGeneratorX86Shared::visitSimdSelect(LSimdSelect *ins)
|
|||||||
FloatRegister onFalse = ToFloatRegister(ins->rhs());
|
FloatRegister onFalse = ToFloatRegister(ins->rhs());
|
||||||
|
|
||||||
MOZ_ASSERT(onTrue == ToFloatRegister(ins->output()));
|
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.bitwiseAndX4(Operand(mask), onTrue);
|
||||||
masm.bitwiseAndNotX4(Operand(onFalse), mask);
|
masm.bitwiseAndNotX4(Operand(onFalse), mask);
|
||||||
masm.bitwiseOrX4(Operand(mask), onTrue);
|
masm.bitwiseOrX4(Operand(mask), onTrue);
|
||||||
|
Loading…
Reference in New Issue
Block a user