Module: Mesa Branch: main Commit: 72a9d12c96e6a57dca6d2d5fc94bb1a195146a37 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=72a9d12c96e6a57dca6d2d5fc94bb1a195146a37
Author: Ian Romanick <[email protected]> Date: Fri Feb 17 12:20:09 2023 -0800 nir/tests: Port almost all loop_analyze tests to new macro-based infastructure The one test that remains would have an automatically generated name that would conflict with another test. This test is also a little special (per the comment in the test), so it's probably best to leave it separate anyway. Reviewed-by: Timothy Arceri <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3445> --- src/compiler/nir/tests/loop_analyze_tests.cpp | 723 +++----------------------- 1 file changed, 83 insertions(+), 640 deletions(-) diff --git a/src/compiler/nir/tests/loop_analyze_tests.cpp b/src/compiler/nir/tests/loop_analyze_tests.cpp index 6f79a0aa2b0..8454f5ef3ac 100644 --- a/src/compiler/nir/tests/loop_analyze_tests.cpp +++ b/src/compiler/nir/tests/loop_analyze_tests.cpp @@ -185,484 +185,6 @@ loop_builder_invert(nir_builder *b, loop_builder_invert_param p) return loop; } -TEST_F(nir_loop_analyze_test, infinite_loop_feq) -{ - /* Create IR: - * - * float i = 0.0; - * while (true) { - * if (i == 0.9) - * break; - * - * i = i + 0.2; - * } - */ - nir_loop *loop = - loop_builder(&b, {.init_value = 0x00000000, .cond_value = 0x3e4ccccd, - .incr_value = 0x3f666666, - .cond_instr = nir_feq, .incr_instr = nir_fadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_1 = load_const (0x3e4ccccd = 0.900000) - * vec1 32 ssa_2 = load_const (0x3f666666 = 0.200000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 1 ssa_3 = feq ssa_5, ssa_1 - * // succs: block_2 block_3 - * if ssa_3 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * vec1 32 ssa_4 = fadd ssa_5, ssa_2 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_FALSE(loop->info->guessed_trip_count); - EXPECT_FALSE(loop->info->exact_trip_count_known); - EXPECT_EQ((void *)0, loop->info->limiting_terminator); - - /* Loop should have an induction variable for ssa_5 and ssa_4. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - -TEST_F(nir_loop_analyze_test, zero_iterations_ine) -{ - /* Create IR: - * - * uint i = 1; - * while (true) { - * if (i != 0) - * break; - * - * i++; - * } - * - * This loop should have an iteration count of zero. See also - * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19732#note_1648999 - */ - nir_loop *loop = - loop_builder(&b, {.init_value = 0x00000001, .cond_value = 0x00000000, - .incr_value = 0x00000001, - .cond_instr = nir_ine, .incr_instr = nir_iadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000001 = 0.000000) - * vec1 32 ssa_1 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_2 = load_const (0x00000001 = 0.000000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 1 ssa_3 = ine ssa_5, ssa_1 - * // succs: block_2 block_3 - * if ssa_3 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * vec1 32 ssa_4 = iadd ssa_5, ssa_2 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_EQ(0, loop->info->max_trip_count); - EXPECT_TRUE(loop->info->exact_trip_count_known); - - /* Loop should have an induction variable for ssa_5 and ssa_4. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - -TEST_F(nir_loop_analyze_test, one_iteration_uge) -{ - /* Create IR: - * - * uint i = 0; - * while (true) { - * if (i >= 1) - * break; - * - * i++; - * } - */ - nir_loop *loop = - loop_builder(&b, {.init_value = 0x00000000, .cond_value = 0x00000001, - .incr_value = 0x00000001, - .cond_instr = nir_uge, .incr_instr = nir_iadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_1 = load_const (0x00000001 = 0.000000) - * vec1 32 ssa_2 = load_const (0x00000001 = 0.000000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 1 ssa_3 = uge ssa_5, ssa_1 - * // succs: block_2 block_3 - * if ssa_3 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * vec1 32 ssa_4 = iadd ssa_5, ssa_2 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_EQ(1, loop->info->max_trip_count); - EXPECT_TRUE(loop->info->exact_trip_count_known); - - /* Loop should have an induction variable for ssa_5 and ssa_4. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - -TEST_F(nir_loop_analyze_test, one_iteration_ine) -{ - /* Create IR: - * - * uint i = 0; - * while (true) { - * if (i != 0) - * break; - * - * i++; - * } - */ - nir_loop *loop = - loop_builder(&b, {.init_value = 0x00000000, .cond_value = 0x00000000, - .incr_value = 0x00000001, - .cond_instr = nir_ine, .incr_instr = nir_iadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_1 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_2 = load_const (0x00000001 = 0.000000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 1 ssa_3 = ine ssa_5, ssa_1 - * // succs: block_2 block_3 - * if ssa_3 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * vec1 32 ssa_4 = iadd ssa_5, ssa_2 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_EQ(1, loop->info->max_trip_count); - EXPECT_TRUE(loop->info->exact_trip_count_known); - - /* Loop should have an induction variable for ssa_5 and ssa_4. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - -TEST_F(nir_loop_analyze_test, one_iteration_ieq) -{ - /* Create IR: - * - * uint i = 0; - * while (true) { - * if (i == 1) - * break; - * - * i++; - * } - */ - nir_loop *loop = - loop_builder(&b, {.init_value = 0x00000000, .cond_value = 0x00000001, - .incr_value = 0x00000001, - .cond_instr = nir_ieq, .incr_instr = nir_iadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_1 = load_const (0x00000001 = 0.000000) - * vec1 32 ssa_2 = load_const (0x00000001 = 0.000000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 1 ssa_3 = ieq ssa_5, ssa_1 - * // succs: block_2 block_3 - * if ssa_3 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * vec1 32 ssa_4 = iadd ssa_5, ssa_2 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_EQ(1, loop->info->max_trip_count); - EXPECT_TRUE(loop->info->exact_trip_count_known); - - /* Loop should have an induction variable for ssa_5 and ssa_4. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - -TEST_F(nir_loop_analyze_test, one_iteration_easy_fneu) -{ - /* Create IR: - * - * float i = 0.0; - * while (true) { - * if (i != 0.0) - * break; - * - * i = i + 1.0; - * } - */ - nir_loop *loop = - loop_builder(&b, {.init_value = 0x00000000, .cond_value = 0x00000000, - .incr_value = 0x3f800000, - .cond_instr = nir_fneu, .incr_instr = nir_fadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_1 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_2 = load_const (0x3f800000 = 1.000000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 1 ssa_3 = fneu ssa_5, ssa_1 - * // succs: block_2 block_3 - * if ssa_3 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * vec1 32 ssa_4 = fadd ssa_5, ssa_2 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_EQ(1, loop->info->max_trip_count); - EXPECT_TRUE(loop->info->exact_trip_count_known); - - /* Loop should have an induction variable for ssa_5 and ssa_4. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - TEST_F(nir_loop_analyze_test, one_iteration_fneu) { /* Create IR: @@ -747,168 +269,6 @@ TEST_F(nir_loop_analyze_test, one_iteration_fneu) } } -TEST_F(nir_loop_analyze_test, zero_iterations_ine_inverted) -{ - /* Create IR: - * - * uint i = 0; - * while (true) { - * i++; - * - * if (i != 0) - * break; - * } - * - * This loop should have an iteration count of zero. - */ - nir_loop *loop = - loop_builder_invert(&b, {.init_value = 0x00000000, .incr_value = 0x00000001, - .cond_value = 0x00000000, - .cond_instr = nir_ine, .incr_instr = nir_iadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_1 = load_const (0x00000001 = 0.000000) - * vec1 32 ssa_2 = load_const (0x00000000 = 0.000000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 32 ssa_3 = iadd ssa_5, ssa_1 - * vec1 1 ssa_4 = ine ssa_3, ssa_2 - * // succs: block_2 block_3 - * if ssa_4 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_EQ(0, loop->info->max_trip_count); - EXPECT_TRUE(loop->info->exact_trip_count_known); - - /* Loop should have an induction variable for ssa_5 and ssa_3. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - -TEST_F(nir_loop_analyze_test, five_iterations_ige_inverted) -{ - /* Create IR: - * - * int i = 0; - * while (true) { - * i++; - * - * if (i >= 6) - * break; - * } - * - * This loop should have an iteration count of 5. - */ - nir_loop *loop = - loop_builder_invert(&b, {.init_value = 0x00000000, .incr_value = 0x00000001, - .cond_value = 0x00000006, - .cond_instr = nir_ige, .incr_instr = nir_iadd}); - - /* At this point, we should have: - * - * impl main { - * block block_0: - * // preds: - * vec1 32 ssa_0 = load_const (0x00000000 = 0.000000) - * vec1 32 ssa_1 = load_const (0x00000001 = 0.000000) - * vec1 32 ssa_2 = load_const (0x00000006 = 0.000000) - * // succs: block_1 - * loop { - * block block_1: - * // preds: block_0 block_4 - * vec1 32 ssa_5 = phi block_0: ssa_0, block_4: ssa_4 - * vec1 32 ssa_3 = iadd ssa_5, ssa_1 - * vec1 1 ssa_4 = ilt ssa_3, ssa_2 - * // succs: block_2 block_3 - * if ssa_4 { - * block block_2: - * // preds: block_1 - * break - * // succs: block_5 - * } else { - * block block_3: - * // preds: block_1 - * // succs: block_4 - * } - * block block_4: - * // preds: block_3 - * // succs: block_1 - * } - * block block_5: - * // preds: block_2 - * // succs: block_6 - * block block_6: - * } - */ - nir_validate_shader(b.shader, "input"); - - nir_loop_analyze_impl(b.impl, nir_var_all, false); - - ASSERT_NE((void *)0, loop->info); - EXPECT_EQ(5, loop->info->max_trip_count); - EXPECT_TRUE(loop->info->exact_trip_count_known); - - /* Loop should have an induction variable for ssa_5 and ssa_3. */ - EXPECT_EQ(2, loop->info->num_induction_vars); - ASSERT_NE((void *)0, loop->info->induction_vars); - - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. - */ - const nir_loop_induction_variable *const ivars = loop->info->induction_vars; - - for (unsigned i = 0; i < loop->info->num_induction_vars; i++) { - EXPECT_NE((void *)0, ivars[i].def); - ASSERT_NE((void *)0, ivars[i].init_src); - EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src)); - ASSERT_NE((void *)0, ivars[i].update_src); - EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src)); - } -} - #define COMPARE_REVERSE(comp) \ static nir_ssa_def * \ nir_ ## comp ## _rev(nir_builder *b, nir_ssa_def *x, nir_ssa_def *y) \ @@ -1079,6 +439,89 @@ INOT_COMPARE(ilt_rev) EXPECT_FALSE(loop->info->exact_trip_count_known); \ } +/* float i = 0.0; + * while (true) { + * if (i == 0.9) + * break; + * + * i = i + 0.2; + * } + */ +INFINITE_LOOP_UNKNOWN_COUNT_TEST(0x00000000, 0x3e4ccccd, 0x3f666666, feq, fadd) + +/* uint i = 1; + * while (true) { + * if (i != 0) + * break; + * + * i++; + * } + * + * This loop should have an iteration count of zero. See also + * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19732#note_1648999 + */ +KNOWN_COUNT_TEST(0x00000001, 0x00000000, 0x00000001, ine, iadd, 0) + +/* uint i = 0; + * while (true) { + * if (i >= 1) + * break; + * + * i++; + * } + */ +KNOWN_COUNT_TEST(0x00000000, 0x00000001, 0x00000001, uge, iadd, 1) + +/* uint i = 0; + * while (true) { + * if (i != 0) + * break; + * + * i++; + * } + */ +KNOWN_COUNT_TEST(0x00000000, 0x00000000, 0x00000001, ine, iadd, 1) + +/* uint i = 0; + * while (true) { + * if (i == 1) + * break; + * + * i++; + * } + */ +KNOWN_COUNT_TEST(0x00000000, 0x00000001, 0x00000001, ieq, iadd, 1) + +/* float i = 0.0; + * while (true) { + * if (i != 0.0) + * break; + * + * i = i + 1.0; + * } + */ +KNOWN_COUNT_TEST(0x00000000, 0x00000000, 0x3f800000, fneu, fadd, 1) + +/* uint i = 0; + * while (true) { + * i++; + * + * if (i != 0) + * break; + * } + */ +KNOWN_COUNT_TEST_INVERT(0x00000000, 0x00000001, 0x00000000, ine, iadd, 0) + +/* int i = 0; + * while (true) { + * i++; + * + * if (i >= 6) + * break; + * } + */ +KNOWN_COUNT_TEST_INVERT(0x00000000, 0x00000001, 0x00000006, ige, iadd, 5) + /* uint i = 10; * while (true) { * if (!(5 < i))
