emit_x64_floating_point: AVX512 implementation of EmitFPMinMaxNumeric
This commit is contained in:
parent
a1192a51d8
commit
c6125082ea
1 changed files with 84 additions and 69 deletions
|
@ -444,12 +444,27 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
template<size_t fsize, bool is_max>
|
template<size_t fsize, bool is_max>
|
||||||
static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
using FPT = mp::unsigned_integer_of_size<fsize>;
|
using FPT = mp::unsigned_integer_of_size<fsize>;
|
||||||
|
constexpr FPT default_nan = FP::FPInfo<FPT>::DefaultNaN();
|
||||||
constexpr u8 mantissa_msb_bit = static_cast<u8>(FP::FPInfo<FPT>::explicit_mantissa_width - 1);
|
constexpr u8 mantissa_msb_bit = static_cast<u8>(FP::FPInfo<FPT>::explicit_mantissa_width - 1);
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
const Xbyak::Xmm op1 = ctx.reg_alloc.UseScratchXmm(args[0]);
|
const Xbyak::Xmm op1 = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||||
const Xbyak::Xmm op2 = ctx.reg_alloc.UseScratchXmm(args[1]); // Result stored here!
|
const Xbyak::Xmm op2 = ctx.reg_alloc.UseScratchXmm(args[1]); // Result stored here!
|
||||||
|
|
||||||
|
DenormalsAreZero<fsize>(code, ctx, {op1, op2});
|
||||||
|
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||||
|
// vrangep{s,d} will already correctly handle comparing
|
||||||
|
// signed zeros and propagating NaNs similar to ARM
|
||||||
|
constexpr FpRangeSelect range_select = is_max ? FpRangeSelect::Max : FpRangeSelect::Min;
|
||||||
|
FCODE(vranges)(op2, op1, op2, FpRangeLUT(range_select, FpRangeSign::Preserve));
|
||||||
|
|
||||||
|
if (ctx.FPCR().DN()) {
|
||||||
|
FCODE(vcmps)(k1, op2, op2, Cmp::Unordered_Q);
|
||||||
|
FCODE(vmovs)(op2 | k1, code.MConst(xword, default_nan));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Xbyak::Reg tmp = ctx.reg_alloc.ScratchGpr();
|
Xbyak::Reg tmp = ctx.reg_alloc.ScratchGpr();
|
||||||
tmp.setBit(fsize);
|
tmp.setBit(fsize);
|
||||||
|
|
||||||
|
@ -463,7 +478,6 @@ static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
||||||
|
|
||||||
Xbyak::Label end, z, nan, op2_is_nan, snan, maybe_both_nan, normal;
|
Xbyak::Label end, z, nan, op2_is_nan, snan, maybe_both_nan, normal;
|
||||||
|
|
||||||
DenormalsAreZero<fsize>(code, ctx, {op1, op2});
|
|
||||||
FCODE(ucomis)(op1, op2);
|
FCODE(ucomis)(op1, op2);
|
||||||
code.jz(z, code.T_NEAR);
|
code.jz(z, code.T_NEAR);
|
||||||
code.L(normal);
|
code.L(normal);
|
||||||
|
@ -503,7 +517,7 @@ static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
||||||
code.jc(maybe_both_nan);
|
code.jc(maybe_both_nan);
|
||||||
if (ctx.FPCR().DN()) {
|
if (ctx.FPCR().DN()) {
|
||||||
code.L(snan);
|
code.L(snan);
|
||||||
code.movaps(op2, code.MConst(xword, FP::FPInfo<FPT>::DefaultNaN()));
|
code.movaps(op2, code.MConst(xword, default_nan));
|
||||||
code.jmp(end);
|
code.jmp(end);
|
||||||
} else {
|
} else {
|
||||||
code.movaps(op2, op1);
|
code.movaps(op2, op1);
|
||||||
|
@ -534,6 +548,7 @@ static void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
||||||
code.jmp(end);
|
code.jmp(end);
|
||||||
|
|
||||||
code.SwitchToNearCode();
|
code.SwitchToNearCode();
|
||||||
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, op2);
|
ctx.reg_alloc.DefineValue(inst, op2);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue