nir: Flatten ifs with discards in nir_opt_peephole_select for HW without CF.

i915g and r300-r400 don't have if statements, and discards are all
nir_intrinsic_discard_if.  We can flatten those discards here, saving a
separate GLSL pass to try to do so.

i915g:
GAINED: shaders/closed/xcom-enemy-unknown/413.shader_test FS

rv370:
GAINED: shaders/closed/xcom-enemy-unknown/12.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/122.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/132.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/145.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/146.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/19.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/413.shader_test FS
GAINED: shaders/closed/xcom-enemy-unknown/415.shader_test FS

Closes: #9918
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24763>
This commit is contained in:
Emma Anholt
2023-10-03 10:04:04 -07:00
committed by Marge Bot
parent 2c4d5c6aec
commit c5712410ec

View File

@@ -23,6 +23,7 @@
#include "nir/nir_builder.h"
#include "nir.h"
#include "nir_builder.h"
#include "nir_control_flow.h"
#include "nir_search_helpers.h"
@@ -74,10 +75,21 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count,
case nir_instr_type_tex:
break;
case nir_instr_type_intrinsic:
if (!nir_intrinsic_can_reorder(nir_instr_as_intrinsic(instr)))
return false;
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
switch (intr->intrinsic) {
case nir_intrinsic_discard:
case nir_intrinsic_discard_if:
/* For non-CF hardware, we need to be able to move discards up
* and flatten, so let them pass.
*/
continue;
default:
if (!nir_intrinsic_can_reorder(intr))
return false;
}
break;
}
case nir_instr_type_call:
case nir_instr_type_jump:
@@ -362,6 +374,32 @@ nir_opt_collapse_if(nir_if *if_stmt, nir_shader *shader, unsigned limit,
return true;
}
/* If we're moving discards out of the if for non-CF hardware, we need to add
* the if's condition to it
*/
static void
rewrite_discard_conds(nir_instr *instr, nir_def *if_cond, bool is_else)
{
if (instr->type != nir_instr_type_intrinsic)
return;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_discard_if && intr->intrinsic != nir_intrinsic_discard)
return;
nir_builder b = nir_builder_at(nir_before_instr(instr));
if (is_else)
if_cond = nir_inot(&b, if_cond);
if (intr->intrinsic == nir_intrinsic_discard_if) {
nir_src_rewrite(&intr->src[0], nir_iand(&b, intr->src[0].ssa, if_cond));
} else {
nir_discard_if(&b, if_cond);
nir_instr_remove(instr);
}
}
static bool
nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
unsigned limit, bool indirect_load_ok,
@@ -434,12 +472,14 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
exec_node_remove(&instr->node);
instr->block = prev_block;
exec_list_push_tail(&prev_block->instr_list, &instr->node);
rewrite_discard_conds(instr, if_stmt->condition.ssa, false);
}
nir_foreach_instr_safe(instr, else_block) {
exec_node_remove(&instr->node);
instr->block = prev_block;
exec_list_push_tail(&prev_block->instr_list, &instr->node);
rewrite_discard_conds(instr, if_stmt->condition.ssa, true);
}
nir_foreach_phi_safe(phi, block) {