nir/loop_analyze: support umin and {u,i,f}max

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Acked-by: Timothy Arceri <tarceri@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26225>
This commit is contained in:
Rhys Perry 2023-12-01 19:56:25 +00:00 committed by Marge Bot
parent 9591c36666
commit fc1ebc67b1
2 changed files with 27 additions and 4 deletions

View file

@ -675,11 +675,19 @@ static nir_op invert_comparison_if_needed(nir_op alu_op, bool invert);
/* Returns whether "limit_op(a, b) alu_op c" is equivalent to "(a alu_op c) || (b alu_op c)". */
static bool
is_min_compatible(nir_op limit_op, nir_op alu_op, bool limit_rhs, bool invert_cond)
is_minmax_compatible(nir_op limit_op, nir_op alu_op, bool limit_rhs, bool invert_cond)
{
bool is_max;
switch (limit_op) {
case nir_op_imin:
case nir_op_fmin:
case nir_op_umin:
is_max = false;
break;
case nir_op_imax:
case nir_op_fmax:
case nir_op_umax:
is_max = true;
break;
default:
return false;
@ -690,15 +698,19 @@ is_min_compatible(nir_op limit_op, nir_op alu_op, bool limit_rhs, bool invert_co
/* Comparisons we can split are:
* - min(a, b) < c
* - c < max(a, b)
* - max(a, b) >= c
* - c >= min(a, b)
*/
switch (invert_comparison_if_needed(alu_op, invert_cond)) {
case nir_op_ilt:
case nir_op_flt:
return !limit_rhs;
case nir_op_ult:
return (!limit_rhs && !is_max) || (limit_rhs && is_max);
case nir_op_ige:
case nir_op_fge:
return limit_rhs;
case nir_op_uge:
return (!limit_rhs && is_max) || (limit_rhs && !is_max);
default:
return false;
}
@ -713,7 +725,7 @@ try_find_limit_of_alu(nir_scalar limit, nir_const_value *limit_val, nir_op alu_o
return false;
nir_op limit_op = nir_scalar_alu_op(limit);
if (is_min_compatible(limit_op, alu_op, !terminator->induction_rhs, invert_cond)) {
if (is_minmax_compatible(limit_op, alu_op, !terminator->induction_rhs, invert_cond)) {
for (unsigned i = 0; i < 2; i++) {
nir_scalar src = nir_scalar_chase_alu_src(limit, i);
if (nir_scalar_is_const(src)) {

View file

@ -305,6 +305,7 @@ CMP_MIN_REV(ige, imin)
CMP_MIN(ige, fmin)
CMP_MIN(uge, imin)
CMP_MIN(ilt, imin)
CMP_MIN(ilt, imax)
CMP_MIN_REV(ilt, imin)
INOT_COMPARE(ilt_imin_rev)
@ -1603,3 +1604,13 @@ UNKNOWN_COUNT_TEST(0x00000008, 0x00000004, 0xffffffff, ige_imin_rev, iadd)
* }
*/
UNKNOWN_COUNT_TEST(0x00000008, 0x00000004, 0xffffffff, ilt_imin, iadd)
/* int i = 8;
* while (true) {
* if (i < imax(vertex_id, 4))
* break;
*
* i--;
* }
*/
INEXACT_COUNT_TEST(0x00000008, 0x00000004, 0xffffffff, ilt_imax, iadd, 5)