blob: e43dfcca6633ee7934a0b8f0cf57bd4acd699747 [file] [log] [blame]
/*
* 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:
}
)"));
}