From 391e16be64095585ae4ab4b62355323fad0e52b4 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 31 Jul 2018 16:20:19 -0400 Subject: [PATCH] emit_x64_vector: Vectorize 32-bit variants of paired min/max Gets rid of the fallbacks for these cases. --- src/backend_x64/emit_x64_vector.cpp | 122 +++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 12 deletions(-) diff --git a/src/backend_x64/emit_x64_vector.cpp b/src/backend_x64/emit_x64_vector.cpp index 4f180d8a..7385ff51 100644 --- a/src/backend_x64/emit_x64_vector.cpp +++ b/src/backend_x64/emit_x64_vector.cpp @@ -1919,9 +1919,31 @@ void EmitX64::EmitVectorPairedMaxS16(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitVectorPairedMaxS32(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - PairedMax(result, a, b); - }); + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm y = ctx.reg_alloc.UseXmm(args[1]); + const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm(); + + code.movdqa(tmp, x); + code.shufps(tmp, y, 0b10001000); + code.shufps(x, y, 0b11011101); + + if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41)) { + code.pmaxsd(x, tmp); + + ctx.reg_alloc.DefineValue(inst, x); + } else { + const Xbyak::Xmm tmp2 = ctx.reg_alloc.ScratchXmm(); + + code.movdqa(tmp2, tmp); + code.pcmpgtd(tmp2, x); + code.pand(tmp, tmp2); + code.pandn(tmp2, x); + code.por(tmp2, tmp); + + ctx.reg_alloc.DefineValue(inst, tmp2); + } } void EmitX64::EmitVectorPairedMaxU8(EmitContext& ctx, IR::Inst* inst) { @@ -1937,9 +1959,36 @@ void EmitX64::EmitVectorPairedMaxU16(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitVectorPairedMaxU32(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - PairedMax(result, a, b); - }); + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm y = ctx.reg_alloc.UseXmm(args[1]); + const Xbyak::Xmm tmp1 = ctx.reg_alloc.ScratchXmm(); + + code.movdqa(tmp1, x); + code.shufps(tmp1, y, 0b10001000); + code.shufps(x, y, 0b11011101); + + if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41)) { + code.pmaxud(x, tmp1); + + ctx.reg_alloc.DefineValue(inst, x); + } else { + const Xbyak::Xmm tmp3 = ctx.reg_alloc.ScratchXmm(); + code.movdqa(tmp3, code.MConst(xword, 0x8000000080000000, 0x8000000080000000)); + + const Xbyak::Xmm tmp2 = ctx.reg_alloc.ScratchXmm(); + code.movdqa(tmp2, x); + + code.pxor(tmp2, tmp3); + code.pxor(tmp3, tmp1); + code.pcmpgtd(tmp3, tmp2); + code.pand(tmp1, tmp3); + code.pandn(tmp3, x); + code.por(tmp1, tmp3); + + ctx.reg_alloc.DefineValue(inst, tmp1); + } } void EmitX64::EmitVectorPairedMinS8(EmitContext& ctx, IR::Inst* inst) { @@ -1955,9 +2004,31 @@ void EmitX64::EmitVectorPairedMinS16(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitVectorPairedMinS32(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - PairedMin(result, a, b); - }); + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm y = ctx.reg_alloc.UseXmm(args[1]); + const Xbyak::Xmm tmp = ctx.reg_alloc.ScratchXmm(); + + code.movdqa(tmp, x); + code.shufps(tmp, y, 0b10001000); + code.shufps(x, y, 0b11011101); + + if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41)) { + code.pminsd(x, tmp); + + ctx.reg_alloc.DefineValue(inst, x); + } else { + const Xbyak::Xmm tmp2 = ctx.reg_alloc.ScratchXmm(); + + code.movaps(tmp2, x); + code.pcmpgtd(tmp2, tmp); + code.pand(tmp, tmp2); + code.pandn(tmp2, x); + code.por(tmp2, tmp); + + ctx.reg_alloc.DefineValue(inst, tmp2); + } } void EmitX64::EmitVectorPairedMinU8(EmitContext& ctx, IR::Inst* inst) { @@ -1973,9 +2044,36 @@ void EmitX64::EmitVectorPairedMinU16(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitVectorPairedMinU32(EmitContext& ctx, IR::Inst* inst) { - EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - PairedMin(result, a, b); - }); + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm y = ctx.reg_alloc.UseXmm(args[1]); + const Xbyak::Xmm tmp1 = ctx.reg_alloc.ScratchXmm(); + + code.movdqa(tmp1, x); + code.shufps(tmp1, y, 0b10001000); + code.shufps(x, y, 0b11011101); + + if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSE41)) { + code.pminud(x, tmp1); + + ctx.reg_alloc.DefineValue(inst, x); + } else { + const Xbyak::Xmm tmp3 = ctx.reg_alloc.ScratchXmm(); + code.movdqa(tmp3, code.MConst(xword, 0x8000000080000000, 0x8000000080000000)); + + const Xbyak::Xmm tmp2 = ctx.reg_alloc.ScratchXmm(); + code.movdqa(tmp2, tmp1); + + code.pxor(tmp2, tmp3); + code.pxor(tmp3, x); + code.pcmpgtd(tmp3, tmp2); + code.pand(tmp1, tmp3); + code.pandn(tmp3, x); + code.por(tmp1, tmp3); + + ctx.reg_alloc.DefineValue(inst, tmp1); + } } template