Mesa (main): nir/idiv_const: optimize imod/irem
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Aug 9 11:39:13 UTC 2021
Module: Mesa
Branch: main
Commit: b627b9fcecbbf437c11a6639fb8e5221b462a148
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=b627b9fcecbbf437c11a6639fb8e5221b462a148
Author: Rhys Perry <pendingchaos02 at gmail.com>
Date: Wed Jul 21 17:02:11 2021 +0100
nir/idiv_const: optimize imod/irem
fossil-db changes (Sienna Cichlid):
Totals from 223 (0.15% of 150170) affected shaders:
CodeSize: 384564 -> 370824 (-3.57%)
Instrs: 74518 -> 71961 (-3.43%)
Latency: 351620 -> 344640 (-1.99%)
InvThroughput: 80122 -> 74846 (-6.58%)
VClause: 919 -> 920 (+0.11%)
SClause: 2879 -> 2877 (-0.07%); split: -0.10%, +0.03%
Copies: 3099 -> 3103 (+0.13%)
Signed-off-by: Rhys Perry <pendingchaos02 at gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12039>
---
src/compiler/nir/nir_opt_idiv_const.c | 57 ++++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/src/compiler/nir/nir_opt_idiv_const.c b/src/compiler/nir/nir_opt_idiv_const.c
index f94efc55991..20e3d552575 100644
--- a/src/compiler/nir/nir_opt_idiv_const.c
+++ b/src/compiler/nir/nir_opt_idiv_const.c
@@ -100,6 +100,53 @@ build_idiv(nir_builder *b, nir_ssa_def *n, int64_t d)
}
}
+static nir_ssa_def *
+build_irem(nir_builder *b, nir_ssa_def *n, int64_t d)
+{
+ int64_t int_min = u_intN_min(n->bit_size);
+ if (d == 0) {
+ return nir_imm_intN_t(b, 0, n->bit_size);
+ } else if (d == int_min) {
+ return nir_bcsel(b, nir_ieq_imm(b, n, int_min), nir_imm_intN_t(b, 0, n->bit_size), n);
+ } else {
+ d = d < 0 ? -d : d;
+ if (util_is_power_of_two_or_zero64(d)) {
+ nir_ssa_def *tmp = nir_bcsel(b, nir_ilt(b, n, nir_imm_intN_t(b, 0, n->bit_size)),
+ nir_iadd_imm(b, n, d - 1), n);
+ return nir_isub(b, n, nir_iand_imm(b, tmp, -d));
+ } else {
+ return nir_isub(b, n, nir_imul(b, build_idiv(b, n, d),
+ nir_imm_intN_t(b, d, n->bit_size)));
+ }
+ }
+}
+
+static nir_ssa_def *
+build_imod(nir_builder *b, nir_ssa_def *n, int64_t d)
+{
+ int64_t int_min = u_intN_min(n->bit_size);
+ if (d == 0) {
+ return nir_imm_intN_t(b, 0, n->bit_size);
+ } else if (d == int_min) {
+ nir_ssa_def *int_min_def = nir_imm_intN_t(b, int_min, n->bit_size);
+ nir_ssa_def *is_neg_not_int_min = nir_ult(b, int_min_def, n);
+ nir_ssa_def *is_zero = nir_ieq_imm(b, n, 0);
+ return nir_bcsel(b, nir_ior(b, is_neg_not_int_min, is_zero), n, nir_iadd(b, int_min_def, n));
+ } else if (d > 0 && util_is_power_of_two_or_zero64(d)) {
+ return nir_iand(b, n, nir_imm_intN_t(b, d - 1, n->bit_size));
+ } else if (d < 0 && util_is_power_of_two_or_zero64(-d)) {
+ nir_ssa_def *d_def = nir_imm_intN_t(b, d, n->bit_size);
+ nir_ssa_def *res = nir_ior(b, n, d_def);
+ return nir_bcsel(b, nir_ieq(b, res, d_def), nir_imm_intN_t(b, 0, n->bit_size), res);
+ } else {
+ nir_ssa_def *rem = build_irem(b, n, d);
+ nir_ssa_def *zero = nir_imm_intN_t(b, 0, n->bit_size);
+ nir_ssa_def *sign_same = d < 0 ? nir_ilt(b, n, zero) : nir_ige(b, n, zero);
+ nir_ssa_def *rem_zero = nir_ieq(b, rem, zero);
+ return nir_bcsel(b, nir_ior(b, rem_zero, sign_same), rem, nir_iadd_imm(b, rem, d));
+ }
+}
+
static bool
nir_opt_idiv_const_instr(nir_builder *b, nir_alu_instr *alu)
{
@@ -143,6 +190,12 @@ nir_opt_idiv_const_instr(nir_builder *b, nir_alu_instr *alu)
case nir_op_umod:
q[comp] = build_umod(b, n, d);
break;
+ case nir_op_imod:
+ q[comp] = build_imod(b, n, d);
+ break;
+ case nir_op_irem:
+ q[comp] = build_irem(b, n, d);
+ break;
default:
unreachable("Unknown integer division op");
}
@@ -171,7 +224,9 @@ nir_opt_idiv_const_impl(nir_function_impl *impl, unsigned min_bit_size)
nir_alu_instr *alu = nir_instr_as_alu(instr);
if (alu->op != nir_op_udiv &&
alu->op != nir_op_idiv &&
- alu->op != nir_op_umod)
+ alu->op != nir_op_umod &&
+ alu->op != nir_op_imod &&
+ alu->op != nir_op_irem)
continue;
assert(alu->dest.dest.is_ssa);
More information about the mesa-commit
mailing list