mesa/src/compiler/nir/nir_opt_uniform_subgroup.c
Ian Romanick f10d1ef372 nir: Initial framework for optimizing uniform subgroup operations
The first commit just optimizes operation where the result of the
subgroup operation is the same as each of the individual channel
results.

This is a subset of the things optimized by ACO. See also
https://gitlab.freedesktop.org/mesa/mesa/-/issues/3731#note_682802.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27044>
2024-02-27 08:38:31 -08:00

81 lines
2 KiB
C

/*
* Copyright 2023 Intel Corporation
* SPDX-License-Identifier: MIT
*/
/**
* \file
* Optimize subgroup operations with uniform sources.
*/
#include "nir/nir.h"
#include "nir/nir_builder.h"
static bool
opt_uniform_subgroup_filter(const nir_instr *instr, const void *_state)
{
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
switch (intrin->intrinsic) {
case nir_intrinsic_shuffle:
case nir_intrinsic_read_invocation:
case nir_intrinsic_read_first_invocation:
case nir_intrinsic_quad_broadcast:
case nir_intrinsic_quad_swap_horizontal:
case nir_intrinsic_quad_swap_vertical:
case nir_intrinsic_quad_swap_diagonal:
case nir_intrinsic_quad_swizzle_amd:
case nir_intrinsic_masked_swizzle_amd:
return !nir_src_is_divergent(intrin->src[0]);
case nir_intrinsic_reduce:
case nir_intrinsic_inclusive_scan: {
if (nir_src_is_divergent(intrin->src[0]))
return false;
const nir_op reduction_op = (nir_op) nir_intrinsic_reduction_op(intrin);
switch (reduction_op) {
case nir_op_imin:
case nir_op_umin:
case nir_op_fmin:
case nir_op_imax:
case nir_op_umax:
case nir_op_fmax:
case nir_op_iand:
case nir_op_ior:
return true;
/* FINISHME: iadd, ixor, and fadd are also possible. */
default:
return false;
}
}
default:
return false;
}
}
static nir_def *
opt_uniform_subgroup_instr(nir_builder *b, nir_instr *instr, void *_state)
{
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
return intrin->src[0].ssa;
}
bool
nir_opt_uniform_subgroup(nir_shader *shader)
{
bool progress = nir_shader_lower_instructions(shader,
opt_uniform_subgroup_filter,
opt_uniform_subgroup_instr,
NULL);
return progress;
}