pan/mdg: Type CSEL with a NIR pass

As an off-shoot of trying to delete modifiers (and nir_register) from NIR, I'd
like to get rid of some of the modifier NIR silliness that Midgard is doing.
The CSEL type selection heuristic at NIR->MIR time is peak backend silly, so
replace it with nir_gather_ssa_types.

Small win on shader-db. I didn't investigate much, but this matches my intution
for how this patch would perform: very small instruction/cycle count
improvements due to slightly better decisions around modifiers, more substantial
space savings due to more float constants getting inlined.

   total instructions in shared programs: 1518422 -> 1518414 (<.01%)
   instructions in affected programs: 1914 -> 1906 (-0.42%)
   helped: 8
   HURT: 0
   Instructions are helped.

   total bundles in shared programs: 646941 -> 646937 (<.01%)
   bundles in affected programs: 344 -> 340 (-1.16%)
   helped: 4
   HURT: 0
   Bundles are helped.

   total quadwords in shared programs: 1134727 -> 1134324 (-0.04%)
   quadwords in affected programs: 66752 -> 66349 (-0.60%)
   helped: 351
   HURT: 54
   Quadwords are helped.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Italo Nicola <italonicola@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23769>
This commit is contained in:
Alyssa Rosenzweig 2023-06-20 16:43:22 -04:00
parent 311bfd0623
commit 074e5700cc
4 changed files with 53 additions and 47 deletions

View file

@ -35,6 +35,7 @@ libpanfrost_midgard_files = files(
'mir_promote_uniforms.c',
'mir_squeeze.c',
'midgard_nir_lower_image_bitsize.c',
'midgard_nir_type_csel.c',
'midgard_opt_copy_prop.c',
'midgard_opt_dce.c',
'midgard_opt_perspective.c',

View file

@ -459,6 +459,7 @@ optimise_nir(nir_shader *nir, unsigned quirks, bool is_blend)
/* Now that booleans are lowered, we can run out late opts */
NIR_PASS(progress, nir, midgard_nir_lower_algebraic_late);
NIR_PASS(progress, nir, midgard_nir_cancel_inot);
NIR_PASS_V(nir, midgard_nir_type_csel);
NIR_PASS(progress, nir, nir_copy_prop);
NIR_PASS(progress, nir, nir_opt_dce);
@ -697,50 +698,6 @@ mir_copy_src(midgard_instruction *ins, nir_alu_instr *instr, unsigned i,
}
}
/* Midgard features both fcsel and icsel, depending on whether you want int or
* float modifiers. NIR's csel is typeless, so we want a heuristic to guess if
* we should emit an int or float csel depending on what modifiers could be
* placed. In the absense of modifiers, this is probably arbitrary. */
static bool
mir_is_bcsel_float(nir_alu_instr *instr)
{
nir_op intmods[] = {nir_op_i2i8, nir_op_i2i16, nir_op_i2i32, nir_op_i2i64};
nir_op floatmods[] = {nir_op_fabs, nir_op_fneg, nir_op_f2f16, nir_op_f2f32,
nir_op_f2f64};
nir_op floatdestmods[] = {nir_op_fsat, nir_op_fsat_signed_mali,
nir_op_fclamp_pos_mali, nir_op_f2f16,
nir_op_f2f32};
signed score = 0;
for (unsigned i = 1; i < 3; ++i) {
nir_alu_src s = instr->src[i];
for (unsigned q = 0; q < ARRAY_SIZE(intmods); ++q) {
if (pan_has_source_mod(&s, intmods[q]))
score--;
}
}
for (unsigned i = 1; i < 3; ++i) {
nir_alu_src s = instr->src[i];
for (unsigned q = 0; q < ARRAY_SIZE(floatmods); ++q) {
if (pan_has_source_mod(&s, floatmods[q]))
score++;
}
}
for (unsigned q = 0; q < ARRAY_SIZE(floatdestmods); ++q) {
nir_dest *dest = &instr->dest.dest;
if (pan_has_dest_mod(&dest, floatdestmods[q]))
score++;
}
return (score > 0);
}
static void
emit_alu(compiler_context *ctx, nir_alu_instr *instr)
{
@ -940,9 +897,10 @@ emit_alu(compiler_context *ctx, nir_alu_instr *instr)
break;
}
case nir_op_b32csel: {
case nir_op_b32csel:
case nir_op_b32fcsel_mdg: {
bool mixed = nir_is_non_scalar_swizzle(&instr->src[0], nr_components);
bool is_float = mir_is_bcsel_float(instr);
bool is_float = instr->op == nir_op_b32fcsel_mdg;
op = is_float ? (mixed ? midgard_alu_op_fcsel_v : midgard_alu_op_fcsel)
: (mixed ? midgard_alu_op_icsel_v : midgard_alu_op_icsel);
@ -1021,7 +979,7 @@ emit_alu(compiler_context *ctx, nir_alu_instr *instr)
for (unsigned i = 0; i < nr_inputs; ++i) {
unsigned to = i;
if (instr->op == nir_op_b32csel) {
if (instr->op == nir_op_b32csel || instr->op == nir_op_b32fcsel_mdg) {
/* The condition is the first argument; move
* the other arguments up one to be a binary
* instruction for Midgard with the condition

View file

@ -4,4 +4,5 @@
bool midgard_nir_lower_algebraic_early(nir_shader *shader);
bool midgard_nir_lower_algebraic_late(nir_shader *shader);
bool midgard_nir_cancel_inot(nir_shader *shader);
void midgard_nir_type_csel(nir_shader *shader);
bool midgard_nir_lower_image_bitsize(nir_shader *shader);

View file

@ -0,0 +1,46 @@
/*
* Copyright 2023 Valve Corporation
* SPDX-License-Identifier: MIT
*/
#include "compiler/nir/nir.h"
#include "compiler/nir/nir_builder.h"
#include "midgard_nir.h"
#include "nir_opcodes.h"
static bool
pass(nir_builder *b, nir_instr *instr, void *data)
{
if (instr->type != nir_instr_type_alu)
return false;
nir_alu_instr *alu = nir_instr_as_alu(instr);
if (alu->op != nir_op_b32csel)
return false;
BITSET_WORD *float_types = data;
assert(alu->dest.dest.is_ssa);
if (BITSET_TEST(float_types, alu->dest.dest.ssa.index)) {
alu->op = nir_op_b32fcsel_mdg;
return true;
} else {
return false;
}
}
void
midgard_nir_type_csel(nir_shader *shader)
{
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
nir_index_ssa_defs(impl);
BITSET_WORD *float_types =
calloc(BITSET_WORDS(impl->ssa_alloc), sizeof(BITSET_WORD));
nir_gather_ssa_types(impl, float_types, NULL);
nir_shader_instructions_pass(
shader, pass, nir_metadata_block_index | nir_metadata_dominance,
float_types);
free(float_types);
}