nir: Handle swizzle in nir_alu_srcs_negative_equal
[mesa.git] / src / compiler / nir / tests / negative_equal_tests.cpp
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 #include <gtest/gtest.h>
24 #include "nir.h"
25 #include "nir_builder.h"
26 #include "util/half_float.h"
27
28 static void count_sequence(nir_const_value c[NIR_MAX_VEC_COMPONENTS],
29 nir_alu_type full_type, int first);
30 static void negate(nir_const_value dst[NIR_MAX_VEC_COMPONENTS],
31 const nir_const_value src[NIR_MAX_VEC_COMPONENTS],
32 nir_alu_type full_type, unsigned components);
33
34 class const_value_negative_equal_test : public ::testing::Test {
35 protected:
36 const_value_negative_equal_test()
37 {
38 memset(c1, 0, sizeof(c1));
39 memset(c2, 0, sizeof(c2));
40 }
41
42 ~const_value_negative_equal_test()
43 {
44 /* empty */
45 }
46
47 nir_const_value c1[NIR_MAX_VEC_COMPONENTS];
48 nir_const_value c2[NIR_MAX_VEC_COMPONENTS];
49 };
50
51 class alu_srcs_negative_equal_test : public ::testing::Test {
52 protected:
53 alu_srcs_negative_equal_test()
54 {
55 static const nir_shader_compiler_options options = { };
56 nir_builder_init_simple_shader(&bld, NULL, MESA_SHADER_VERTEX, &options);
57 memset(c1, 0, sizeof(c1));
58 memset(c2, 0, sizeof(c2));
59 }
60
61 ~alu_srcs_negative_equal_test()
62 {
63 ralloc_free(bld.shader);
64 }
65
66 struct nir_builder bld;
67 nir_const_value c1[NIR_MAX_VEC_COMPONENTS];
68 nir_const_value c2[NIR_MAX_VEC_COMPONENTS];
69 };
70
71 TEST_F(const_value_negative_equal_test, float32_zero)
72 {
73 /* Verify that 0.0 negative-equals 0.0. */
74 EXPECT_TRUE(nir_const_value_negative_equal(c1[0], c1[0], nir_type_float32));
75 }
76
77 TEST_F(const_value_negative_equal_test, float64_zero)
78 {
79 /* Verify that 0.0 negative-equals 0.0. */
80 EXPECT_TRUE(nir_const_value_negative_equal(c1[0], c1[0], nir_type_float64));
81 }
82
83 /* Compare an object with non-zero values to itself. This should always be
84 * false.
85 */
86 #define compare_with_self(full_type) \
87 TEST_F(const_value_negative_equal_test, full_type ## _self) \
88 { \
89 count_sequence(c1, full_type, 1); \
90 EXPECT_FALSE(nir_const_value_negative_equal(c1[0], c1[0], full_type)); \
91 }
92
93 compare_with_self(nir_type_float16)
94 compare_with_self(nir_type_float32)
95 compare_with_self(nir_type_float64)
96 compare_with_self(nir_type_int8)
97 compare_with_self(nir_type_uint8)
98 compare_with_self(nir_type_int16)
99 compare_with_self(nir_type_uint16)
100 compare_with_self(nir_type_int32)
101 compare_with_self(nir_type_uint32)
102 compare_with_self(nir_type_int64)
103 compare_with_self(nir_type_uint64)
104 #undef compare_with_self
105
106 /* Compare an object with the negation of itself. This should always be true.
107 */
108 #define compare_with_negation(full_type) \
109 TEST_F(const_value_negative_equal_test, full_type ## _trivially_true) \
110 { \
111 count_sequence(c1, full_type, 1); \
112 negate(c2, c1, full_type, 1); \
113 EXPECT_TRUE(nir_const_value_negative_equal(c1[0], c2[0], full_type)); \
114 }
115
116 compare_with_negation(nir_type_float16)
117 compare_with_negation(nir_type_float32)
118 compare_with_negation(nir_type_float64)
119 compare_with_negation(nir_type_int8)
120 compare_with_negation(nir_type_uint8)
121 compare_with_negation(nir_type_int16)
122 compare_with_negation(nir_type_uint16)
123 compare_with_negation(nir_type_int32)
124 compare_with_negation(nir_type_uint32)
125 compare_with_negation(nir_type_int64)
126 compare_with_negation(nir_type_uint64)
127 #undef compare_with_negation
128
129 TEST_F(alu_srcs_negative_equal_test, trivial_float)
130 {
131 nir_ssa_def *two = nir_imm_float(&bld, 2.0f);
132 nir_ssa_def *negative_two = nir_imm_float(&bld, -2.0f);
133
134 nir_ssa_def *result = nir_fadd(&bld, two, negative_two);
135 nir_alu_instr *instr = nir_instr_as_alu(result->parent_instr);
136
137 ASSERT_NE((void *) 0, instr);
138 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 0, 1));
139 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 0, 0));
140 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 1, 1));
141 }
142
143 TEST_F(alu_srcs_negative_equal_test, trivial_int)
144 {
145 nir_ssa_def *two = nir_imm_int(&bld, 2);
146 nir_ssa_def *negative_two = nir_imm_int(&bld, -2);
147
148 nir_ssa_def *result = nir_iadd(&bld, two, negative_two);
149 nir_alu_instr *instr = nir_instr_as_alu(result->parent_instr);
150
151 ASSERT_NE((void *) 0, instr);
152 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 0, 1));
153 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 0, 0));
154 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 1, 1));
155 }
156
157 TEST_F(alu_srcs_negative_equal_test, trivial_negation_float)
158 {
159 /* Cannot just do the negation of a nir_load_const_instr because
160 * nir_alu_srcs_negative_equal expects that constant folding will convert
161 * fneg(2.0) to just -2.0.
162 */
163 nir_ssa_def *two = nir_imm_float(&bld, 2.0f);
164 nir_ssa_def *two_plus_two = nir_fadd(&bld, two, two);
165 nir_ssa_def *negation = nir_fneg(&bld, two_plus_two);
166
167 nir_ssa_def *result = nir_fadd(&bld, two_plus_two, negation);
168
169 nir_alu_instr *instr = nir_instr_as_alu(result->parent_instr);
170
171 ASSERT_NE((void *) 0, instr);
172 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 0, 1));
173 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 0, 0));
174 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 1, 1));
175 }
176
177 TEST_F(alu_srcs_negative_equal_test, trivial_negation_int)
178 {
179 /* Cannot just do the negation of a nir_load_const_instr because
180 * nir_alu_srcs_negative_equal expects that constant folding will convert
181 * ineg(2) to just -2.
182 */
183 nir_ssa_def *two = nir_imm_int(&bld, 2);
184 nir_ssa_def *two_plus_two = nir_iadd(&bld, two, two);
185 nir_ssa_def *negation = nir_ineg(&bld, two_plus_two);
186
187 nir_ssa_def *result = nir_iadd(&bld, two_plus_two, negation);
188
189 nir_alu_instr *instr = nir_instr_as_alu(result->parent_instr);
190
191 ASSERT_NE((void *) 0, instr);
192 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 0, 1));
193 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 0, 0));
194 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 1, 1));
195 }
196
197 /* Compare an object with non-zero values to itself. This should always be
198 * false.
199 */
200 #define compare_with_self(full_type) \
201 TEST_F(alu_srcs_negative_equal_test, full_type ## _self) \
202 { \
203 count_sequence(c1, full_type, 1); \
204 nir_ssa_def *a = nir_build_imm(&bld, \
205 NIR_MAX_VEC_COMPONENTS, \
206 nir_alu_type_get_type_size(full_type), \
207 c1); \
208 nir_ssa_def *result; \
209 if (nir_alu_type_get_base_type(full_type) == nir_type_float) \
210 result = nir_fadd(&bld, a, a); \
211 else \
212 result = nir_iadd(&bld, a, a); \
213 nir_alu_instr *instr = nir_instr_as_alu(result->parent_instr); \
214 ASSERT_NE((void *) 0, instr); \
215 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 0, 0)); \
216 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 0, 1)); \
217 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 1, 0)); \
218 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 1, 1)); \
219 }
220
221 compare_with_self(nir_type_float16)
222 compare_with_self(nir_type_float32)
223 compare_with_self(nir_type_float64)
224 compare_with_self(nir_type_int8)
225 compare_with_self(nir_type_uint8)
226 compare_with_self(nir_type_int16)
227 compare_with_self(nir_type_uint16)
228 compare_with_self(nir_type_int32)
229 compare_with_self(nir_type_uint32)
230 compare_with_self(nir_type_int64)
231 compare_with_self(nir_type_uint64)
232
233 /* Compare an object with the negation of itself. This should always be true.
234 */
235 #define compare_with_negation(full_type) \
236 TEST_F(alu_srcs_negative_equal_test, full_type ## _trivially_true) \
237 { \
238 count_sequence(c1, full_type, 1); \
239 negate(c2, c1, full_type, NIR_MAX_VEC_COMPONENTS); \
240 nir_ssa_def *a = nir_build_imm(&bld, \
241 NIR_MAX_VEC_COMPONENTS, \
242 nir_alu_type_get_type_size(full_type), \
243 c1); \
244 nir_ssa_def *b = nir_build_imm(&bld, \
245 NIR_MAX_VEC_COMPONENTS, \
246 nir_alu_type_get_type_size(full_type), \
247 c2); \
248 nir_ssa_def *result; \
249 if (nir_alu_type_get_base_type(full_type) == nir_type_float) \
250 result = nir_fadd(&bld, a, b); \
251 else \
252 result = nir_iadd(&bld, a, b); \
253 nir_alu_instr *instr = nir_instr_as_alu(result->parent_instr); \
254 ASSERT_NE((void *) 0, instr); \
255 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 0, 0)); \
256 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 0, 1)); \
257 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 1, 0)); \
258 EXPECT_FALSE(nir_alu_srcs_negative_equal(instr, instr, 1, 1)); \
259 }
260
261 compare_with_negation(nir_type_float16)
262 compare_with_negation(nir_type_float32)
263 compare_with_negation(nir_type_float64)
264 compare_with_negation(nir_type_int8)
265 compare_with_negation(nir_type_uint8)
266 compare_with_negation(nir_type_int16)
267 compare_with_negation(nir_type_uint16)
268 compare_with_negation(nir_type_int32)
269 compare_with_negation(nir_type_uint32)
270 compare_with_negation(nir_type_int64)
271 compare_with_negation(nir_type_uint64)
272
273 TEST_F(alu_srcs_negative_equal_test, swizzle_scalar_to_vector)
274 {
275 nir_ssa_def *v = nir_imm_vec2(&bld, 1.0, -1.0);
276 const uint8_t s0[4] = { 0, 0, 0, 0 };
277 const uint8_t s1[4] = { 1, 1, 1, 1 };
278
279 /* We can't use nir_swizzle here because it inserts an extra MOV. */
280 nir_alu_instr *instr = nir_alu_instr_create(bld.shader, nir_op_fadd);
281
282 instr->src[0].src = nir_src_for_ssa(v);
283 instr->src[1].src = nir_src_for_ssa(v);
284
285 memcpy(&instr->src[0].swizzle, s0, sizeof(s0));
286 memcpy(&instr->src[1].swizzle, s1, sizeof(s1));
287
288 nir_builder_alu_instr_finish_and_insert(&bld, instr);
289
290 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 0, 1));
291 }
292
293 TEST_F(alu_srcs_negative_equal_test, unused_components_mismatch)
294 {
295 nir_ssa_def *v1 = nir_imm_vec4(&bld, -2.0, 18.0, 43.0, 1.0);
296 nir_ssa_def *v2 = nir_imm_vec4(&bld, 2.0, 99.0, 76.0, -1.0);
297
298 nir_ssa_def *result = nir_fadd(&bld, v1, v2);
299
300 nir_alu_instr *instr = nir_instr_as_alu(result->parent_instr);
301
302 /* Disable the channels that aren't negations of each other. */
303 instr->dest.dest.is_ssa = false;
304 instr->dest.write_mask = 8 + 1;
305
306 EXPECT_TRUE(nir_alu_srcs_negative_equal(instr, instr, 0, 1));
307 }
308
309 static void
310 count_sequence(nir_const_value c[NIR_MAX_VEC_COMPONENTS],
311 nir_alu_type full_type, int first)
312 {
313 switch (full_type) {
314 case nir_type_float16:
315 for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
316 c[i].u16 = _mesa_float_to_half(float(i + first));
317
318 break;
319
320 case nir_type_float32:
321 for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
322 c[i].f32 = float(i + first);
323
324 break;
325
326 case nir_type_float64:
327 for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
328 c[i].f64 = double(i + first);
329
330 break;
331
332 case nir_type_int8:
333 case nir_type_uint8:
334 for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
335 c[i].i8 = i + first;
336
337 break;
338
339 case nir_type_int16:
340 case nir_type_uint16:
341 for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
342 c[i].i16 = i + first;
343
344 break;
345
346 case nir_type_int32:
347 case nir_type_uint32:
348 for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
349 c[i].i32 = i + first;
350
351 break;
352
353 case nir_type_int64:
354 case nir_type_uint64:
355 for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
356 c[i].i64 = i + first;
357
358 break;
359
360 case nir_type_bool:
361 default:
362 unreachable("invalid base type");
363 }
364 }
365
366 static void
367 negate(nir_const_value dst[NIR_MAX_VEC_COMPONENTS],
368 const nir_const_value src[NIR_MAX_VEC_COMPONENTS],
369 nir_alu_type full_type, unsigned components)
370 {
371 switch (full_type) {
372 case nir_type_float16:
373 for (unsigned i = 0; i < components; i++)
374 dst[i].u16 = _mesa_float_to_half(-_mesa_half_to_float(src[i].u16));
375
376 break;
377
378 case nir_type_float32:
379 for (unsigned i = 0; i < components; i++)
380 dst[i].f32 = -src[i].f32;
381
382 break;
383
384 case nir_type_float64:
385 for (unsigned i = 0; i < components; i++)
386 dst[i].f64 = -src[i].f64;
387
388 break;
389
390 case nir_type_int8:
391 case nir_type_uint8:
392 for (unsigned i = 0; i < components; i++)
393 dst[i].i8 = -src[i].i8;
394
395 break;
396
397 case nir_type_int16:
398 case nir_type_uint16:
399 for (unsigned i = 0; i < components; i++)
400 dst[i].i16 = -src[i].i16;
401
402 break;
403
404 case nir_type_int32:
405 case nir_type_uint32:
406 for (unsigned i = 0; i < components; i++)
407 dst[i].i32 = -src[i].i32;
408
409 break;
410
411 case nir_type_int64:
412 case nir_type_uint64:
413 for (unsigned i = 0; i < components; i++)
414 dst[i].i64 = -src[i].i64;
415
416 break;
417
418 case nir_type_bool:
419 default:
420 unreachable("invalid base type");
421 }
422 }