xref: /aosp_15_r20/external/mesa3d/src/compiler/nir/tests/dce_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 "nir_test.h"
25 
26 class nir_opt_dce_test : public nir_test {
27 protected:
nir_opt_dce_test()28    nir_opt_dce_test()
29       : nir_test::nir_test("nir_opt_dce_test")
30    {
31    }
32 };
33 
34 class nir_opt_dead_cf_test : public nir_test {
35 protected:
nir_opt_dead_cf_test()36    nir_opt_dead_cf_test()
37       : nir_test::nir_test("nir_opt_dead_cf_test")
38    {
39    }
40 };
41 
create_one_source_phi(nir_shader * shader,nir_block * pred,nir_def * def)42 nir_phi_instr *create_one_source_phi(nir_shader *shader, nir_block *pred,
43                                      nir_def *def)
44 {
45    nir_phi_instr *phi = nir_phi_instr_create(shader);
46    nir_phi_instr_add_src(phi, pred, def);
47    nir_def_init(&phi->instr, &phi->def, def->num_components,
48                 def->bit_size);
49 
50    return phi;
51 }
52 
TEST_F(nir_opt_dce_test,return_before_loop)53 TEST_F(nir_opt_dce_test, return_before_loop)
54 {
55    /* Test that nir_opt_dce() works correctly with loops immediately following a jump.
56     * nir_opt_dce() has a fast path for loops without continues, and this test ensures that it
57     * looks at the actual predecessors of the header instead of just counting.
58     *
59     *  block block_0:
60     *  // preds:
61     *  return
62     *  // succs: block_3
63     *  loop {
64     *     block block_1:
65     *     // preds: block_1
66     *     vec1 32 ssa_1 = phi block_1: ssa_0
67     *     vec1 32 ssa_0 = load_const (0x00000001)
68     *     vec1 32 ssa_2 = deref_var &out (shader_out int)
69     *     intrinsic store_deref (ssa_2, ssa_1) (1, 0)
70     *     // succs: block_1
71     *  }
72     *  block block_2:
73     *  // preds:
74     *  // succs: block_3
75     *  block block_3:
76     *
77     * If the fast path is taken here, ssa_0 will be incorrectly DCE'd.
78     */
79 
80    nir_variable *var = nir_variable_create(b->shader, nir_var_shader_out, glsl_int_type(), "out");
81 
82    nir_jump(b, nir_jump_return);
83 
84    nir_loop *loop = nir_push_loop(b);
85 
86    nir_def *one = nir_imm_int(b, 1);
87 
88    nir_phi_instr *phi = create_one_source_phi(b->shader, one->parent_instr->block, one);
89    nir_instr_insert_before_block(one->parent_instr->block, &phi->instr);
90 
91    nir_store_var(b, var, &phi->def, 0x1);
92 
93    nir_pop_loop(b, loop);
94 
95    ASSERT_FALSE(nir_opt_dce(b->shader));
96 
97    nir_validate_shader(b->shader, NULL);
98 }
99 
TEST_F(nir_opt_dead_cf_test,jump_before_constant_if)100 TEST_F(nir_opt_dead_cf_test, jump_before_constant_if)
101 {
102    /*
103     * Test that nir_opt_dead_cf removes everything after the jump, instead of trying and failing to
104     * stitch b0 and b3.
105     *
106     * block b0:  // preds:
107     * 1     %0 = load_const (false)
108     *            return
109     *            // succs: b4
110     * if %0 (false) {
111     *     block b1:  // preds:
112     *     32    %1 = load_const (0x00000001)
113     *     32    %2 = deref_var &out (shader_out int)
114     *                @store_deref (%2, %1 (0x1)) (wrmask=x, access=0)
115     *                // succs: b3
116     * } else {
117     *     block b2:  // preds: , succs: b3
118     * }
119     * block b3:  // preds: b1 b2
120     * 32    %3 = load_const (0x00000000)
121     * 32    %4 = deref_var &out (shader_out int)
122     *            @store_deref (%4, %3 (0x0)) (wrmask=x, access=0)
123     *            // succs: b4
124     * block b4:
125     */
126    nir_variable *var = nir_variable_create(b->shader, nir_var_shader_out, glsl_int_type(), "out");
127 
128    nir_def *cond = nir_imm_false(b);
129    nir_jump(b, nir_jump_return);
130    nir_push_if(b, cond);
131    nir_store_var(b, var, nir_imm_int(b, 1), 0x1);
132    nir_pop_if(b, NULL);
133 
134    nir_store_var(b, var, nir_imm_int(b, 0), 0x1);
135 
136    ASSERT_TRUE(nir_opt_dead_cf(b->shader));
137 
138    nir_validate_shader(b->shader, NULL);
139 }
140