1 /*
2 * Copyright © 2021 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 #include <gtest/gtest.h>
24 #include "nir.h"
25 #include "nir_builder.h"
26 #include "nir_range_analysis.h"
27
28 class ssa_def_bits_used_test : public ::testing::Test {
29 protected:
ssa_def_bits_used_test()30 ssa_def_bits_used_test()
31 {
32 glsl_type_singleton_init_or_ref();
33
34 static const nir_shader_compiler_options options = { };
35 bld = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, &options,
36 "ssa_def_bits_used test");
37 }
38
~ssa_def_bits_used_test()39 ~ssa_def_bits_used_test()
40 {
41 ralloc_free(bld.shader);
42 glsl_type_singleton_decref();
43 }
44
45 nir_alu_instr *build_alu_instr(nir_op op, nir_ssa_def *, nir_ssa_def *);
46
47 struct nir_builder bld;
48 };
49
50 static bool
is_used_once(const nir_ssa_def * def)51 is_used_once(const nir_ssa_def *def)
52 {
53 return list_is_singular(&def->uses) &&
54 list_is_empty(&def->if_uses);
55 }
56
57 nir_alu_instr *
build_alu_instr(nir_op op,nir_ssa_def * src0,nir_ssa_def * src1)58 ssa_def_bits_used_test::build_alu_instr(nir_op op,
59 nir_ssa_def *src0, nir_ssa_def *src1)
60 {
61 nir_ssa_def *def = nir_build_alu(&bld, op, src0, src1, NULL, NULL);
62
63 if (def == NULL)
64 return NULL;
65
66 nir_alu_instr *alu = nir_instr_as_alu(def->parent_instr);
67
68 if (alu == NULL)
69 return NULL;
70
71 alu->dest.write_mask = 1;
72 alu->dest.dest.ssa.num_components = 1;
73
74 return alu;
75 }
76
TEST_F(ssa_def_bits_used_test,iand_with_const_vector)77 TEST_F(ssa_def_bits_used_test, iand_with_const_vector)
78 {
79 static const unsigned src0_imm[4] = { 255u << 24, 255u << 16, 255u << 8, 255u };
80
81 nir_ssa_def *src0 = nir_imm_ivec4(&bld,
82 src0_imm[0], src0_imm[1],
83 src0_imm[2], src0_imm[3]);
84 nir_ssa_def *src1 = nir_imm_int(&bld, 0xffffffff);
85
86 nir_alu_instr *alu = build_alu_instr(nir_op_iand, src0, src1);
87
88 ASSERT_NE((void *) 0, alu);
89
90 for (unsigned i = 0; i < 4; i++) {
91 /* If the test is changed, and somehow src1 is used multiple times,
92 * nir_ssa_def_bits_used will accumulate *all* the uses (as it should).
93 * This isn't what we're trying to test here.
94 */
95 ASSERT_TRUE(is_used_once(src1));
96
97 alu->src[0].swizzle[0] = i;
98
99 const uint64_t bits_used = nir_ssa_def_bits_used(alu->src[1].src.ssa);
100
101 /* The answer should be the value swizzled from src0. */
102 EXPECT_EQ(src0_imm[i], bits_used);
103 }
104 }
105
TEST_F(ssa_def_bits_used_test,ior_with_const_vector)106 TEST_F(ssa_def_bits_used_test, ior_with_const_vector)
107 {
108 static const unsigned src0_imm[4] = { 255u << 24, 255u << 16, 255u << 8, 255u };
109
110 nir_ssa_def *src0 = nir_imm_ivec4(&bld,
111 src0_imm[0], src0_imm[1],
112 src0_imm[2], src0_imm[3]);
113 nir_ssa_def *src1 = nir_imm_int(&bld, 0xffffffff);
114
115 nir_alu_instr *alu = build_alu_instr(nir_op_ior, src0, src1);
116
117 ASSERT_NE((void *) 0, alu);
118
119 for (unsigned i = 0; i < 4; i++) {
120 /* If the test is changed, and somehow src1 is used multiple times,
121 * nir_ssa_def_bits_used will accumulate *all* the uses (as it should).
122 * This isn't what we're trying to test here.
123 */
124 ASSERT_TRUE(is_used_once(src1));
125
126 alu->src[0].swizzle[0] = i;
127
128 const uint64_t bits_used = nir_ssa_def_bits_used(alu->src[1].src.ssa);
129
130 /* The answer should be the value swizzled from ~src0. */
131 EXPECT_EQ(~src0_imm[i], bits_used);
132 }
133 }
134
TEST_F(ssa_def_bits_used_test,extract_i16_with_const_index)135 TEST_F(ssa_def_bits_used_test, extract_i16_with_const_index)
136 {
137 nir_ssa_def *src0 = nir_imm_int(&bld, 0xffffffff);
138
139 static const unsigned src1_imm[4] = { 9, 1, 0, 9 };
140
141 nir_ssa_def *src1 = nir_imm_ivec4(&bld,
142 src1_imm[0],
143 src1_imm[1],
144 src1_imm[2],
145 src1_imm[3]);
146
147 nir_alu_instr *alu = build_alu_instr(nir_op_extract_i16, src0, src1);
148
149 ASSERT_NE((void *) 0, alu);
150
151 for (unsigned i = 1; i < 3; i++) {
152 /* If the test is changed, and somehow src1 is used multiple times,
153 * nir_ssa_def_bits_used will accumulate *all* the uses (as it should).
154 * This isn't what we're trying to test here.
155 */
156 ASSERT_TRUE(is_used_once(src1));
157
158 alu->src[1].swizzle[0] = i;
159
160 const uint64_t bits_used = nir_ssa_def_bits_used(alu->src[0].src.ssa);
161
162 EXPECT_EQ(0xffffu << (16 * src1_imm[i]), bits_used);
163 }
164 }
165
TEST_F(ssa_def_bits_used_test,extract_u16_with_const_index)166 TEST_F(ssa_def_bits_used_test, extract_u16_with_const_index)
167 {
168 nir_ssa_def *src0 = nir_imm_int(&bld, 0xffffffff);
169
170 static const unsigned src1_imm[4] = { 9, 1, 0, 9 };
171
172 nir_ssa_def *src1 = nir_imm_ivec4(&bld,
173 src1_imm[0],
174 src1_imm[1],
175 src1_imm[2],
176 src1_imm[3]);
177
178 nir_alu_instr *alu = build_alu_instr(nir_op_extract_u16, src0, src1);
179
180 ASSERT_NE((void *) 0, alu);
181
182 for (unsigned i = 1; i < 3; i++) {
183 /* If the test is changed, and somehow src1 is used multiple times,
184 * nir_ssa_def_bits_used will accumulate *all* the uses (as it should).
185 * This isn't what we're trying to test here.
186 */
187 ASSERT_TRUE(is_used_once(src1));
188
189 alu->src[1].swizzle[0] = i;
190
191 const uint64_t bits_used = nir_ssa_def_bits_used(alu->src[0].src.ssa);
192
193 EXPECT_EQ(0xffffu << (16 * src1_imm[i]), bits_used);
194 }
195 }
196
TEST_F(ssa_def_bits_used_test,extract_i8_with_const_index)197 TEST_F(ssa_def_bits_used_test, extract_i8_with_const_index)
198 {
199 nir_ssa_def *src0 = nir_imm_int(&bld, 0xffffffff);
200
201 static const unsigned src1_imm[4] = { 3, 2, 1, 0 };
202
203 nir_ssa_def *src1 = nir_imm_ivec4(&bld,
204 src1_imm[0],
205 src1_imm[1],
206 src1_imm[2],
207 src1_imm[3]);
208
209 nir_alu_instr *alu = build_alu_instr(nir_op_extract_i8, src0, src1);
210
211 ASSERT_NE((void *) 0, alu);
212
213 for (unsigned i = 0; i < 4; i++) {
214 /* If the test is changed, and somehow src1 is used multiple times,
215 * nir_ssa_def_bits_used will accumulate *all* the uses (as it should).
216 * This isn't what we're trying to test here.
217 */
218 ASSERT_TRUE(is_used_once(src1));
219
220 alu->src[1].swizzle[0] = i;
221
222 const uint64_t bits_used = nir_ssa_def_bits_used(alu->src[0].src.ssa);
223
224 EXPECT_EQ(0xffu << (8 * src1_imm[i]), bits_used);
225 }
226 }
227
TEST_F(ssa_def_bits_used_test,extract_u8_with_const_index)228 TEST_F(ssa_def_bits_used_test, extract_u8_with_const_index)
229 {
230 nir_ssa_def *src0 = nir_imm_int(&bld, 0xffffffff);
231
232 static const unsigned src1_imm[4] = { 3, 2, 1, 0 };
233
234 nir_ssa_def *src1 = nir_imm_ivec4(&bld,
235 src1_imm[0],
236 src1_imm[1],
237 src1_imm[2],
238 src1_imm[3]);
239
240 nir_alu_instr *alu = build_alu_instr(nir_op_extract_u8, src0, src1);
241
242 ASSERT_NE((void *) 0, alu);
243
244 for (unsigned i = 0; i < 4; i++) {
245 /* If the test is changed, and somehow src1 is used multiple times,
246 * nir_ssa_def_bits_used will accumulate *all* the uses (as it should).
247 * This isn't what we're trying to test here.
248 */
249 ASSERT_TRUE(is_used_once(src1));
250
251 alu->src[1].swizzle[0] = i;
252
253 const uint64_t bits_used = nir_ssa_def_bits_used(alu->src[0].src.ssa);
254
255 EXPECT_EQ(0xffu << (8 * src1_imm[i]), bits_used);
256 }
257 }
258