• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2018 Intel Corporation
3  * Copyright © 2021 Valve Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include "nir_test.h"
26 
27 namespace {
28 
29 class algebraic_test_base : public nir_test {
30 protected:
31    algebraic_test_base();
32 
33    virtual void run_pass()=0;
34 
35    void test_op(nir_op op, nir_def *src0, nir_def *src1, nir_def *src2,
36                 nir_def *src3, const char *desc);
37 
38    void test_2src_op(nir_op op, int64_t src0, int64_t src1);
39 
40    nir_variable *res_var;
41 };
42 
algebraic_test_base()43 algebraic_test_base::algebraic_test_base()
44    : nir_test::nir_test("nir_opt_algebraic_test")
45 {
46    res_var = nir_local_variable_create(b->impl, glsl_int_type(), "res");
47 }
48 
test_op(nir_op op,nir_def * src0,nir_def * src1,nir_def * src2,nir_def * src3,const char * desc)49 void algebraic_test_base::test_op(nir_op op, nir_def *src0, nir_def *src1,
50                                      nir_def *src2, nir_def *src3, const char *desc)
51 {
52    nir_def *res_deref = &nir_build_deref_var(b, res_var)->def;
53 
54    /* create optimized expression */
55    nir_intrinsic_instr *optimized_instr = nir_build_store_deref(
56       b, res_deref, nir_build_alu(b, op, src0, src1, src2, src3), 0x1);
57 
58    run_pass();
59    b->cursor = nir_after_cf_list(&b->impl->body);
60 
61    /* create reference expression */
62    nir_intrinsic_instr *ref_instr = nir_build_store_deref(
63       b, res_deref, nir_build_alu(b, op, src0, src1, src2, src3), 0x1);
64 
65    /* test equality */
66    nir_opt_constant_folding(b->shader);
67 
68    ASSERT_TRUE(nir_src_is_const(ref_instr->src[1]));
69    ASSERT_TRUE(nir_src_is_const(optimized_instr->src[1]));
70 
71    int32_t ref = nir_src_as_int(ref_instr->src[1]);
72    int32_t optimized = nir_src_as_int(optimized_instr->src[1]);
73 
74    EXPECT_EQ(ref, optimized) << "Test input: " << desc;
75 
76    /* reset shader */
77    exec_list_make_empty(&nir_start_block(b->impl)->instr_list);
78    b->cursor = nir_after_cf_list(&b->impl->body);
79 }
80 
test_2src_op(nir_op op,int64_t src0,int64_t src1)81 void algebraic_test_base::test_2src_op(nir_op op, int64_t src0, int64_t src1)
82 {
83    char desc[128];
84    snprintf(desc, sizeof(desc), "%s(%" PRId64 ", %" PRId64 ")", nir_op_infos[op].name, src0, src1);
85    test_op(op, nir_imm_int(b, src0), nir_imm_int(b, src1), NULL, NULL, desc);
86 }
87 
88 class nir_opt_algebraic_test : public algebraic_test_base {
89 protected:
run_pass()90    virtual void run_pass() {
91       nir_opt_algebraic(b->shader);
92    }
93 };
94 
95 class nir_opt_idiv_const_test : public algebraic_test_base {
96 protected:
run_pass()97    virtual void run_pass() {
98       nir_opt_idiv_const(b->shader, 8);
99    }
100 };
101 
TEST_F(nir_opt_algebraic_test,umod_pow2_src2)102 TEST_F(nir_opt_algebraic_test, umod_pow2_src2)
103 {
104    for (int i = 0; i <= 9; i++)
105       test_2src_op(nir_op_umod, i, 4);
106    test_2src_op(nir_op_umod, UINT32_MAX, 4);
107 }
108 
TEST_F(nir_opt_algebraic_test,imod_pow2_src2)109 TEST_F(nir_opt_algebraic_test, imod_pow2_src2)
110 {
111    for (int i = -9; i <= 9; i++) {
112       test_2src_op(nir_op_imod, i, 4);
113       test_2src_op(nir_op_imod, i, -4);
114       test_2src_op(nir_op_imod, i, INT32_MIN);
115    }
116    test_2src_op(nir_op_imod, INT32_MAX, 4);
117    test_2src_op(nir_op_imod, INT32_MAX, -4);
118    test_2src_op(nir_op_imod, INT32_MIN, 4);
119    test_2src_op(nir_op_imod, INT32_MIN, -4);
120    test_2src_op(nir_op_imod, INT32_MIN, INT32_MIN);
121 }
122 
TEST_F(nir_opt_algebraic_test,irem_pow2_src2)123 TEST_F(nir_opt_algebraic_test, irem_pow2_src2)
124 {
125    for (int i = -9; i <= 9; i++) {
126       test_2src_op(nir_op_irem, i, 4);
127       test_2src_op(nir_op_irem, i, -4);
128    }
129    test_2src_op(nir_op_irem, INT32_MAX, 4);
130    test_2src_op(nir_op_irem, INT32_MAX, -4);
131    test_2src_op(nir_op_irem, INT32_MIN, 4);
132    test_2src_op(nir_op_irem, INT32_MIN, -4);
133 }
134 
TEST_F(nir_opt_algebraic_test,msad)135 TEST_F(nir_opt_algebraic_test, msad)
136 {
137    options.lower_bitfield_extract = true;
138    options.has_bfe = true;
139    options.has_msad = true;
140 
141    nir_def *src0 = nir_load_var(b, nir_local_variable_create(b->impl, glsl_int_type(), "src0"));
142    nir_def *src1 = nir_load_var(b, nir_local_variable_create(b->impl, glsl_int_type(), "src1"));
143 
144    /* This mimics the sequence created by vkd3d-proton. */
145    nir_def *res = NULL;
146    for (unsigned i = 0; i < 4; i++) {
147       nir_def *ref = nir_ubitfield_extract(b, src0, nir_imm_int(b, i * 8), nir_imm_int(b, 8));
148       nir_def *src = nir_ubitfield_extract(b, src1, nir_imm_int(b, i * 8), nir_imm_int(b, 8));
149       nir_def *is_ref_zero = nir_ieq_imm(b, ref, 0);
150       nir_def *abs_diff = nir_iabs(b, nir_isub(b, ref, src));
151       nir_def *masked_diff = nir_bcsel(b, is_ref_zero, nir_imm_int(b, 0), abs_diff);
152       if (res)
153          res = nir_iadd(b, res, masked_diff);
154       else
155          res = masked_diff;
156    }
157 
158    nir_store_var(b, res_var, res, 0x1);
159 
160    while (nir_opt_algebraic(b->shader)) {
161       nir_opt_constant_folding(b->shader);
162       nir_opt_dce(b->shader);
163    }
164 
165    unsigned count = 0;
166    nir_foreach_instr(instr, nir_start_block(b->impl)) {
167       if (instr->type == nir_instr_type_alu) {
168          ASSERT_TRUE(nir_instr_as_alu(instr)->op == nir_op_msad_4x8);
169          ASSERT_EQ(count, 0);
170          count++;
171       }
172    }
173 }
174 
TEST_F(nir_opt_idiv_const_test,umod)175 TEST_F(nir_opt_idiv_const_test, umod)
176 {
177    for (uint32_t d : {16u, 17u, 0u, UINT32_MAX}) {
178       for (int i = 0; i <= 40; i++)
179          test_2src_op(nir_op_umod, i, d);
180       for (int i = 0; i < 20; i++)
181          test_2src_op(nir_op_umod, UINT32_MAX - i, d);
182    }
183 }
184 
TEST_F(nir_opt_idiv_const_test,imod)185 TEST_F(nir_opt_idiv_const_test, imod)
186 {
187    for (int32_t d : {16, -16, 17, -17, 0, INT32_MIN, INT32_MAX}) {
188       for (int i = -40; i <= 40; i++)
189          test_2src_op(nir_op_imod, i, d);
190       for (int i = 0; i < 20; i++)
191          test_2src_op(nir_op_imod, INT32_MIN + i, d);
192       for (int i = 0; i < 20; i++)
193          test_2src_op(nir_op_imod, INT32_MAX - i, d);
194    }
195 }
196 
TEST_F(nir_opt_idiv_const_test,irem)197 TEST_F(nir_opt_idiv_const_test, irem)
198 {
199    for (int32_t d : {16, -16, 17, -17, 0, INT32_MIN, INT32_MAX}) {
200       for (int i = -40; i <= 40; i++)
201          test_2src_op(nir_op_irem, i, d);
202       for (int i = 0; i < 20; i++)
203          test_2src_op(nir_op_irem, INT32_MIN + i, d);
204       for (int i = 0; i < 20; i++)
205          test_2src_op(nir_op_irem, INT32_MAX - i, d);
206    }
207 }
208 
209 }
210