From 3dab7b0a45e32d9c80c8f6abdcb23e91e3ef6723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 14 Feb 2025 17:19:57 +0100 Subject: [PATCH] nir/tests: add tests for nir_move_terminate_out_of_loops Reviewed-by: Rhys Perry Part-of: --- src/compiler/nir/meson.build | 1 + .../nir/tests/lower_discard_if_tests.cpp | 228 ++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 src/compiler/nir/tests/lower_discard_if_tests.cpp diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build index 8b1a043b7b9..98a56efdbca 100644 --- a/src/compiler/nir/meson.build +++ b/src/compiler/nir/meson.build @@ -407,6 +407,7 @@ if with_tests 'tests/loop_analyze_tests.cpp', 'tests/loop_unroll_tests.cpp', 'tests/lower_alu_width_tests.cpp', + 'tests/lower_discard_if_tests.cpp', 'tests/minimize_call_live_states_test.cpp', 'tests/mod_analysis_tests.cpp', 'tests/negative_equal_tests.cpp', diff --git a/src/compiler/nir/tests/lower_discard_if_tests.cpp b/src/compiler/nir/tests/lower_discard_if_tests.cpp new file mode 100644 index 00000000000..e43dfcca663 --- /dev/null +++ b/src/compiler/nir/tests/lower_discard_if_tests.cpp @@ -0,0 +1,228 @@ +/* + * Copyright 2025 Valve Corporation + * SPDX-License-Identifier: MIT + */ + +#include "nir.h" +#include "nir_builder.h" +#include "nir_test.h" + +class nir_lower_discard_if_test : public nir_test { +protected: + nir_lower_discard_if_test(); + + nir_def *in_def; + + +}; + +nir_lower_discard_if_test::nir_lower_discard_if_test() + : nir_test::nir_test("nir_lower_discard_if_test", MESA_SHADER_FRAGMENT) +{ + nir_variable *var = nir_variable_create(b->shader, nir_var_shader_in, glsl_int_type(), "in"); + in_def = nir_load_var(b, var); +} + +TEST_F(nir_lower_discard_if_test, move_single_terminate_out_of_loop) +{ + nir_loop *loop = nir_push_loop(b); + nir_def *cmp_result = nir_ieq(b, in_def, nir_imm_zero(b, 1, 32)); + nir_break_if(b, cmp_result); + nir_terminate(b); + nir_pop_loop(b, loop); + + ASSERT_TRUE(nir_lower_discard_if(b->shader, nir_move_terminate_out_of_loops)); + + check_nir_string(NIR_REFERENCE_SHADER(R"( + shader: MESA_SHADER_FRAGMENT + name: nir_lower_discard_if_test + subgroup_size: 0 + decl_var shader_in INTERP_MODE_SMOOTH none int in (VARYING_SLOT_POS.x, 0, 0) + decl_function main () (entrypoint) + + impl main { + block b0: // preds: + 32 %0 = deref_var &in (shader_in int) + 32 %1 = @load_deref (%0) (access=none) + 1 %2 = load_const (false) + // succs: b1 + loop { + block b1: // preds: b0 b7 + 32 %3 = load_const (0x00000000) + 1 %4 = ieq %1, %3 (0x0) + // succs: b2 b3 + if %4 { + block b2:// preds: b1 + break + // succs: b8 + } else { + block b3: // preds: b1, succs: b4 + } + block b4: // preds: b3 + 1 %5 = load_const (true) + // succs: b5 b6 + if %5 (true) { + block b5:// preds: b4 + break + // succs: b8 + } else { + block b6: // preds: b4, succs: b7 + } + block b7: // preds: b6, succs: b1 + } + block b8: // preds: b2 b5 + 1 %6 = phi b2: %2 (false), b5: %5 (true) + @terminate_if (%6) + // succs: b9 + block b9: + } + )")); +} + +TEST_F(nir_lower_discard_if_test, move_multiple_terminate_out_of_loop) +{ + nir_loop *loop = nir_push_loop(b); + nir_def *cmp_result = nir_ieq(b, in_def, nir_imm_zero(b, 1, 32)); + nir_terminate_if(b, cmp_result); + nir_def *cmp_result2 = nir_ieq(b, in_def, nir_imm_int(b, 1)); + nir_terminate_if(b, cmp_result2); + nir_jump(b, nir_jump_break); + nir_pop_loop(b, loop); + + ASSERT_TRUE(nir_lower_discard_if(b->shader, nir_move_terminate_out_of_loops)); + + check_nir_string(NIR_REFERENCE_SHADER(R"( + shader: MESA_SHADER_FRAGMENT + name: nir_lower_discard_if_test + subgroup_size: 0 + decl_var shader_in INTERP_MODE_SMOOTH none int in (VARYING_SLOT_POS.x, 0, 0) + decl_function main () (entrypoint) + + impl main { + block b0: // preds: + 1 %0 = undefined + 32 %1 = deref_var &in (shader_in int) + 32 %2 = @load_deref (%1) (access=none) + 1 %3 = load_const (false) + 1 %4 = load_const (false) + // succs: b1 + loop { + block b1: // preds: b0 + 32 %5 = load_const (0x00000000) + 1 %6 = ieq %2, %5 (0x0) + // succs: b2 b3 + if %6 { + block b2:// preds: b1 + break + // succs: b8 + } else { + block b3: // preds: b1, succs: b4 + } + block b4: // preds: b3 + 32 %7 = load_const (0x00000001) + 1 %8 = ieq %2, %7 (0x1) + // succs: b5 b6 + if %8 { + block b5:// preds: b4 + break + // succs: b8 + } else { + block b6: // preds: b4, succs: b7 + } + block b7:// preds: b6 + break + // succs: b8 + } + block b8: // preds: b2 b5 b7 + 1 %9 = phi b2: %6, b5: %0, b7: %3 (false) + 1 %10 = phi b2: %4 (false), b5: %8, b7: %4 (false) + @terminate_if (%10) + @terminate_if (%9) + // succs: b9 + block b9: + } + )")); +} + +TEST_F(nir_lower_discard_if_test, move_terminate_out_of_nested_loop) +{ + nir_loop *loop = nir_push_loop(b); + { + nir_def *cmp_result = nir_ieq(b, in_def, nir_imm_zero(b, 1, 32)); + nir_break_if(b, cmp_result); + nir_loop *inner = nir_push_loop(b); + { + nir_def *cmp_result2 = nir_ieq(b, in_def, nir_imm_int(b, 1)); + nir_terminate_if(b, cmp_result2); + nir_jump(b, nir_jump_break); + } + nir_pop_loop(b, inner); + } + nir_pop_loop(b, loop); + + ASSERT_TRUE(nir_lower_discard_if(b->shader, nir_move_terminate_out_of_loops)); + + check_nir_string(NIR_REFERENCE_SHADER(R"( + shader: MESA_SHADER_FRAGMENT + name: nir_lower_discard_if_test + subgroup_size: 0 + decl_var shader_in INTERP_MODE_SMOOTH none int in (VARYING_SLOT_POS.x, 0, 0) + decl_function main () (entrypoint) + + impl main { + block b0: // preds: + 32 %0 = deref_var &in (shader_in int) + 32 %1 = @load_deref (%0) (access=none) + 1 %2 = load_const (false) + // succs: b1 + loop { + block b1: // preds: b0 b12 + 32 %3 = load_const (0x00000000) + 1 %4 = ieq %1, %3 (0x0) + // succs: b2 b3 + if %4 { + block b2:// preds: b1 + break + // succs: b13 + } else { + block b3: // preds: b1, succs: b4 + } + block b4: // preds: b3 + 1 %5 = load_const (false) + // succs: b5 + loop { + block b5: // preds: b4 + 32 %6 = load_const (0x00000001) + 1 %7 = ieq %1, %6 (0x1) + // succs: b6 b7 + if %7 { + block b6:// preds: b5 + break + // succs: b9 + } else { + block b7: // preds: b5, succs: b8 + } + block b8:// preds: b7 + break + // succs: b9 + } + block b9: // preds: b6 b8 + 1 %8 = phi b6: %7, b8: %5 (false) + // succs: b10 b11 + if %8 { + block b10:// preds: b9 + break + // succs: b13 + } else { + block b11: // preds: b9, succs: b12 + } + block b12: // preds: b11, succs: b1 + } + block b13: // preds: b2 b10 + 1 %9 = phi b2: %2 (false), b10: %8 + @terminate_if (%9) + // succs: b14 + block b14: + } + )")); +} \ No newline at end of file