1 /*
2  * Copyright © 2018 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 
26 #include "nir.h"
27 #include "nir_builder.h"
28 
29 namespace {
30 
31 class nir_core_test : public ::testing::Test {
32 protected:
33    nir_core_test();
34    ~nir_core_test();
35 
36    bool shader_contains_def(nir_ssa_def *def);
37 
38    nir_builder *b, _b;
39 };
40 
nir_core_test()41 nir_core_test::nir_core_test()
42 {
43    glsl_type_singleton_init_or_ref();
44 
45    static const nir_shader_compiler_options options = { };
46    _b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, &options, "builder test");
47    b = &_b;
48 }
49 
~nir_core_test()50 nir_core_test::~nir_core_test()
51 {
52    if (HasFailure()) {
53       printf("\nShader from the failed test:\n\n");
54       nir_print_shader(b->shader, stdout);
55    }
56 
57    ralloc_free(b->shader);
58 
59    glsl_type_singleton_decref();
60 }
61 
62 struct contains_def_state {
63    nir_ssa_def *def;
64    bool found;
65 };
66 
67 static bool
contains_def_cb(nir_ssa_def * def,void * _state)68 contains_def_cb(nir_ssa_def *def, void *_state)
69 {
70    struct contains_def_state *state = (struct contains_def_state *)_state;
71    if (def == state->def)
72       state->found = true;
73 
74    return true;
75 }
76 
77 bool
shader_contains_def(nir_ssa_def * def)78 nir_core_test::shader_contains_def(nir_ssa_def *def)
79 {
80    nir_foreach_block(block, b->impl) {
81       nir_foreach_instr(instr, block) {
82          struct contains_def_state state = {
83             .def = def,
84             .found = false,
85          };
86          nir_foreach_ssa_def(instr, contains_def_cb, &state);
87          if (state.found)
88             return true;
89       }
90    }
91    return false;
92 }
93 
TEST_F(nir_core_test,nir_instr_free_and_dce_test)94 TEST_F(nir_core_test, nir_instr_free_and_dce_test)
95 {
96    nir_ssa_def *zero = nir_imm_int(b, 0);
97    nir_ssa_def *one = nir_imm_int(b, 1);
98    nir_ssa_def *add01 = nir_iadd(b, zero, one);
99    nir_ssa_def *add11 = nir_iadd(b, one, one);
100 
101    nir_cursor c = nir_instr_free_and_dce(add01->parent_instr);
102    ASSERT_FALSE(shader_contains_def(add01));
103    ASSERT_TRUE(shader_contains_def(add11));
104    ASSERT_FALSE(shader_contains_def(zero));
105    ASSERT_TRUE(shader_contains_def(one));
106 
107    ASSERT_TRUE(nir_cursors_equal(c, nir_before_instr(add11->parent_instr)));
108 
109    nir_validate_shader(b->shader, "after remove_and_dce");
110 }
111 
TEST_F(nir_core_test,nir_instr_free_and_dce_all_test)112 TEST_F(nir_core_test, nir_instr_free_and_dce_all_test)
113 {
114    nir_ssa_def *one = nir_imm_int(b, 1);
115    nir_ssa_def *add = nir_iadd(b, one, one);
116 
117    nir_cursor c = nir_instr_free_and_dce(add->parent_instr);
118    ASSERT_FALSE(shader_contains_def(add));
119    ASSERT_FALSE(shader_contains_def(one));
120 
121    ASSERT_TRUE(nir_cursors_equal(c, nir_before_block(nir_start_block(b->impl))));
122 
123    nir_validate_shader(b->shader, "after remove_and_dce");
124 }
125 
TEST_F(nir_core_test,nir_instr_free_and_dce_multiple_src_test)126 TEST_F(nir_core_test, nir_instr_free_and_dce_multiple_src_test)
127 {
128    nir_ssa_def *one = nir_imm_int(b, 1);
129    nir_ssa_def *add = nir_iadd(b, one, one);
130 
131    /* This risks triggering removing add multiple times, which can segfault in
132     * nir_instr_remove for instructions with srcs. */
133    nir_ssa_def *add2 = nir_iadd(b, add, add);
134 
135    nir_cursor c = nir_instr_free_and_dce(add2->parent_instr);
136    ASSERT_FALSE(shader_contains_def(add2));
137    ASSERT_FALSE(shader_contains_def(add));
138    ASSERT_FALSE(shader_contains_def(one));
139 
140    ASSERT_TRUE(nir_cursors_equal(c, nir_before_block(nir_start_block(b->impl))));
141 
142    nir_validate_shader(b->shader, "after remove_and_dce");
143 }
144 
145 }
146