nir/lower_idiv: Be less creative about signs

I'm sorry to whoever wrote this, but

   (x - (int) (x < 0)) ^ -((int) (x < 0))

is not an acceptable way to write iabs.

Shader-db results on Intel Tiger Lake with lower_idiv enabled:

    total instructions in shared programs: 21122548 -> 21122570 (<.01%)
    instructions in affected programs: 2369 -> 2391 (0.93%)
    helped: 2
    HURT: 8

    total cycles in shared programs: 791609360 -> 791608062 (<.01%)
    cycles in affected programs: 114106 -> 112808 (-1.14%)
    helped: 9
    HURT: 1

If we make the Intel back-end less stupid, we get to 9/1 helped/HURT for
instructions as well but that's for a different MR.

Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17845>
This commit is contained in:
Alyssa Rosenzweig 2022-08-01 18:56:01 -04:00 committed by Marge Bot
parent e13c9d2168
commit a4a15f500c

View file

@ -162,23 +162,17 @@ emit_idiv(nir_builder *bld, nir_ssa_def *numer, nir_ssa_def *denom, nir_op op)
{
nir_ssa_def *lh_sign = nir_ilt(bld, numer, nir_imm_int(bld, 0));
nir_ssa_def *rh_sign = nir_ilt(bld, denom, nir_imm_int(bld, 0));
lh_sign = nir_bcsel(bld, lh_sign, nir_imm_int(bld, -1), nir_imm_int(bld, 0));
rh_sign = nir_bcsel(bld, rh_sign, nir_imm_int(bld, -1), nir_imm_int(bld, 0));
nir_ssa_def *lhs = nir_iadd(bld, numer, lh_sign);
nir_ssa_def *rhs = nir_iadd(bld, denom, rh_sign);
lhs = nir_ixor(bld, lhs, lh_sign);
rhs = nir_ixor(bld, rhs, rh_sign);
nir_ssa_def *lhs = nir_iabs(bld, numer);
nir_ssa_def *rhs = nir_iabs(bld, denom);
if (op == nir_op_idiv) {
nir_ssa_def *d_sign = nir_ixor(bld, lh_sign, rh_sign);
nir_ssa_def *res = emit_udiv(bld, lhs, rhs, false);
res = nir_ixor(bld, res, d_sign);
return nir_isub(bld, res, d_sign);
return nir_bcsel(bld, d_sign, nir_ineg(bld, res), res);
} else {
nir_ssa_def *res = emit_udiv(bld, lhs, rhs, true);
res = nir_ixor(bld, res, lh_sign);
res = nir_isub(bld, res, lh_sign);
res = nir_bcsel(bld, lh_sign, nir_ineg(bld, res), res);
if (op == nir_op_imod) {
nir_ssa_def *cond = nir_ieq_imm(bld, res, 0);
cond = nir_ior(bld, nir_ieq(bld, lh_sign, rh_sign), cond);