xref: /aosp_15_r20/external/mesa3d/src/compiler/nir/tests/loop_unroll_tests.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2020 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "gtest/gtest.h"
25 #include "nir.h"
26 #include "nir_builder.h"
27 #include "nir_phi_builder.h"
28 
29 #define UNROLL_TEST_INSERT(_label, _type, _init, _limit, _step,         \
30                            _cond, _incr, _rev, _exp_res,                \
31                            _exp_instr_count, _exp_loop_count)           \
32    TEST_F(nir_loop_unroll_test, _label)                                 \
33    {                                                                    \
34       nir_def *init = nir_imm_##_type(&bld, _init);                 \
35       nir_def *limit = nir_imm_##_type(&bld, _limit);               \
36       nir_def *step = nir_imm_##_type(&bld, _step);                 \
37       loop_unroll_test_helper(&bld, init, limit, step,                  \
38                               &nir_##_cond, &nir_##_incr, _rev);        \
39       EXPECT_##_exp_res(nir_opt_loop_unroll(bld.shader));               \
40       EXPECT_EQ(_exp_instr_count, count_instr(nir_op_##_incr));         \
41       EXPECT_EQ(_exp_loop_count, count_loops());                        \
42    }
43 
44 namespace {
45 
46 class nir_loop_unroll_test : public ::testing::Test {
47 protected:
nir_loop_unroll_test()48    nir_loop_unroll_test()
49    {
50       glsl_type_singleton_init_or_ref();
51       static nir_shader_compiler_options options = { };
52       options.max_unroll_iterations = 32;
53       options.force_indirect_unrolling_sampler = false;
54       options.force_indirect_unrolling = nir_var_all;
55       bld = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, &options,
56                                            "loop unrolling tests");
57    }
~nir_loop_unroll_test()58    ~nir_loop_unroll_test()
59    {
60       ralloc_free(bld.shader);
61       glsl_type_singleton_decref();
62    }
63 
64    int count_instr(nir_op op);
65    int count_loops(void);
66 
67    nir_builder bld;
68 };
69 
70 } /* namespace */
71 
72 int
count_instr(nir_op op)73 nir_loop_unroll_test::count_instr(nir_op op)
74 {
75    int count = 0;
76    nir_foreach_block(block, bld.impl) {
77       nir_foreach_instr(instr, block) {
78          if (instr->type != nir_instr_type_alu)
79             continue;
80          nir_alu_instr *alu_instr = nir_instr_as_alu(instr);
81          if (alu_instr->op == op)
82             count++;
83       }
84    }
85 
86    return count;
87 }
88 
89 int
count_loops(void)90 nir_loop_unroll_test::count_loops(void)
91 {
92    int count = 0;
93    foreach_list_typed(nir_cf_node, cf_node, node, &bld.impl->body) {
94       if (cf_node->type == nir_cf_node_loop)
95          count++;
96    }
97 
98    return count;
99 }
100 
101 void
loop_unroll_test_helper(nir_builder * bld,nir_def * init,nir_def * limit,nir_def * step,nir_def * (* cond_instr)(nir_builder *,nir_def *,nir_def *),nir_def * (* incr_instr)(nir_builder *,nir_def *,nir_def *),bool reverse)102 loop_unroll_test_helper(nir_builder *bld, nir_def *init,
103                         nir_def *limit, nir_def *step,
104                         nir_def* (*cond_instr)(nir_builder*,
105                                                    nir_def*,
106                                                    nir_def*),
107                         nir_def* (*incr_instr)(nir_builder*,
108                                                    nir_def*,
109                                                    nir_def*),
110                         bool reverse)
111 {
112    nir_loop *loop = nir_push_loop(bld);
113 
114    nir_block *top_block =
115       nir_cf_node_as_block(nir_cf_node_prev(&loop->cf_node));
116    nir_block *head_block = nir_loop_first_block(loop);
117 
118    nir_phi_instr *phi = nir_phi_instr_create(bld->shader);
119    nir_def_init(&phi->instr, &phi->def, 1, 32);
120 
121    nir_phi_instr_add_src(phi, top_block, init);
122 
123    nir_def *cond = cond_instr(bld,
124                                   (reverse ? limit : &phi->def),
125                                   (reverse ? &phi->def : limit));
126 
127    nir_if *nif = nir_push_if(bld, cond);
128    nir_jump(bld, nir_jump_break);
129    nir_pop_if(bld, nif);
130 
131    nir_def *var = incr_instr(bld, &phi->def, step);
132 
133    nir_phi_instr_add_src(phi, nir_cursor_current_block(bld->cursor), var);
134 
135    nir_pop_loop(bld, loop);
136 
137    bld->cursor = nir_after_phis(head_block);
138    nir_builder_instr_insert(bld, &phi->instr);
139 
140    nir_validate_shader(bld->shader, NULL);
141 }
142 
143 UNROLL_TEST_INSERT(iadd,     int,   0,     24,   4,
144                    ige,      iadd,  false, TRUE, 6, 0)
145 UNROLL_TEST_INSERT(iadd_rev, int,   0,     24,   4,
146                    ilt,      iadd,  true,  TRUE, 7, 0)
147 UNROLL_TEST_INSERT(fadd,     float, 0.0,   24.0, 4.0,
148                    fge,      fadd,  false, TRUE, 6, 0)
149 UNROLL_TEST_INSERT(fadd_rev, float, 0.0,   24.0, 4.0,
150                    flt,      fadd,  true,  TRUE, 7, 0)
151 UNROLL_TEST_INSERT(imul,     int,   1,     81,   3,
152                    ige,      imul,  false, TRUE, 4, 0)
153 UNROLL_TEST_INSERT(imul_rev, int,   1,     81,   3,
154                    ilt,      imul,  true,  TRUE, 5, 0)
155 #if 0 /* Disable tests until support is re-enabled in loop_analyze. */
156 UNROLL_TEST_INSERT(fmul,     float, 1.5,   81.0, 3.0,
157                    fge,      fmul,  false, TRUE, 4, 0)
158 UNROLL_TEST_INSERT(fmul_rev, float, 1.0,   81.0, 3.0,
159                    flt,      fmul,  true,  TRUE, 5, 0)
160 #endif
161 UNROLL_TEST_INSERT(ishl,     int,   1,     128,  1,
162                    ige,      ishl,  false, TRUE, 7, 0)
163 UNROLL_TEST_INSERT(ishl_rev, int,   1,     128,  1,
164                    ilt,      ishl,  true,  TRUE, 8, 0)
165 UNROLL_TEST_INSERT(ishr,     int,   64,    4,    1,
166                    ilt,      ishr,  false, TRUE, 5, 0)
167 UNROLL_TEST_INSERT(ishr_rev, int,   64,    4,    1,
168                    ige,      ishr,  true,  TRUE, 4, 0)
169 UNROLL_TEST_INSERT(ushr,     int,   64,    4,    1,
170                    ilt,      ushr,  false, TRUE, 5, 0)
171 UNROLL_TEST_INSERT(ushr_rev, int,   64,    4,    1,
172                    ige,      ushr,  true,  TRUE, 4, 0)
173 
174 UNROLL_TEST_INSERT(lshl_neg,     int,  0xf0f0f0f0, 0,    1,
175                    ige,          ishl, false,      TRUE, 4, 0)
176 UNROLL_TEST_INSERT(lshl_neg_rev, int,  0xf0f0f0f0, 0,    1,
177                    ilt,          ishl, true,       TRUE, 4, 0)
178