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 <gtest/gtest.h>
26 
27 #include "nir.h"
28 #include "nir_builder.h"
29 
30 namespace {
31 
32 class algebraic_test_base : public ::testing::Test {
33 protected:
34    algebraic_test_base();
35    ~algebraic_test_base();
36 
37    virtual void run_pass()=0;
38 
39    void test_op(nir_op op, nir_ssa_def *src0, nir_ssa_def *src1, nir_ssa_def *src2,
40                 nir_ssa_def *src3, const char *desc);
41 
42    void test_2src_op(nir_op op, int64_t src0, int64_t src1);
43 
44    nir_variable *res_var;
45    nir_builder *b, _b;
46 };
47 
algebraic_test_base()48 algebraic_test_base::algebraic_test_base()
49 {
50    glsl_type_singleton_init_or_ref();
51 
52    static const nir_shader_compiler_options options = { };
53    _b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, &options, "opt_algebraic test");
54    b = &_b;
55 
56    res_var = nir_local_variable_create(b->impl, glsl_int_type(), "res");
57 }
58 
~algebraic_test_base()59 algebraic_test_base::~algebraic_test_base()
60 {
61    ralloc_free(b->shader);
62 
63    glsl_type_singleton_decref();
64 }
65 
test_op(nir_op op,nir_ssa_def * src0,nir_ssa_def * src1,nir_ssa_def * src2,nir_ssa_def * src3,const char * desc)66 void algebraic_test_base::test_op(nir_op op, nir_ssa_def *src0, nir_ssa_def *src1,
67                                      nir_ssa_def *src2, nir_ssa_def *src3, const char *desc)
68 {
69    nir_ssa_def *res_deref = &nir_build_deref_var(b, res_var)->dest.ssa;
70 
71    /* create optimized expression */
72    nir_intrinsic_instr *optimized_instr = nir_build_store_deref(
73       b, res_deref, nir_build_alu(b, op, src0, src1, src2, src3), 0x1);
74 
75    run_pass();
76    b->cursor = nir_after_cf_list(&b->impl->body);
77 
78    /* create reference expression */
79    nir_intrinsic_instr *ref_instr = nir_build_store_deref(
80       b, res_deref, nir_build_alu(b, op, src0, src1, src2, src3), 0x1);
81 
82    /* test equality */
83    nir_opt_constant_folding(b->shader);
84 
85    ASSERT_TRUE(nir_src_is_const(ref_instr->src[1]));
86    ASSERT_TRUE(nir_src_is_const(optimized_instr->src[1]));
87 
88    int32_t ref = nir_src_as_int(ref_instr->src[1]);
89    int32_t optimized = nir_src_as_int(optimized_instr->src[1]);
90 
91    EXPECT_EQ(ref, optimized) << "Test input: " << desc;
92 
93    /* reset shader */
94    exec_list_make_empty(&nir_start_block(b->impl)->instr_list);
95    b->cursor = nir_after_cf_list(&b->impl->body);
96 }
97 
test_2src_op(nir_op op,int64_t src0,int64_t src1)98 void algebraic_test_base::test_2src_op(nir_op op, int64_t src0, int64_t src1)
99 {
100    char desc[128];
101    snprintf(desc, sizeof(desc), "%s(%" PRId64 ", %" PRId64 ")", nir_op_infos[op].name, src0, src1);
102    test_op(op, nir_imm_int(b, src0), nir_imm_int(b, src1), NULL, NULL, desc);
103 }
104 
105 class nir_opt_algebraic_test : public algebraic_test_base {
106 protected:
run_pass()107    virtual void run_pass() {
108       nir_opt_algebraic(b->shader);
109    }
110 };
111 
112 class nir_opt_idiv_const_test : public algebraic_test_base {
113 protected:
run_pass()114    virtual void run_pass() {
115       nir_opt_idiv_const(b->shader, 8);
116    }
117 };
118 
TEST_F(nir_opt_algebraic_test,umod_pow2_src2)119 TEST_F(nir_opt_algebraic_test, umod_pow2_src2)
120 {
121    for (int i = 0; i <= 9; i++)
122       test_2src_op(nir_op_umod, i, 4);
123    test_2src_op(nir_op_umod, UINT32_MAX, 4);
124 }
125 
TEST_F(nir_opt_algebraic_test,imod_pow2_src2)126 TEST_F(nir_opt_algebraic_test, imod_pow2_src2)
127 {
128    for (int i = -9; i <= 9; i++) {
129       test_2src_op(nir_op_imod, i, 4);
130       test_2src_op(nir_op_imod, i, -4);
131       test_2src_op(nir_op_imod, i, INT32_MIN);
132    }
133    test_2src_op(nir_op_imod, INT32_MAX, 4);
134    test_2src_op(nir_op_imod, INT32_MAX, -4);
135    test_2src_op(nir_op_imod, INT32_MIN, 4);
136    test_2src_op(nir_op_imod, INT32_MIN, -4);
137    test_2src_op(nir_op_imod, INT32_MIN, INT32_MIN);
138 }
139 
TEST_F(nir_opt_algebraic_test,irem_pow2_src2)140 TEST_F(nir_opt_algebraic_test, irem_pow2_src2)
141 {
142    for (int i = -9; i <= 9; i++) {
143       test_2src_op(nir_op_irem, i, 4);
144       test_2src_op(nir_op_irem, i, -4);
145    }
146    test_2src_op(nir_op_irem, INT32_MAX, 4);
147    test_2src_op(nir_op_irem, INT32_MAX, -4);
148    test_2src_op(nir_op_irem, INT32_MIN, 4);
149    test_2src_op(nir_op_irem, INT32_MIN, -4);
150 }
151 
TEST_F(nir_opt_idiv_const_test,umod)152 TEST_F(nir_opt_idiv_const_test, umod)
153 {
154    for (uint32_t d : {16u, 17u, 0u, UINT32_MAX}) {
155       for (int i = 0; i <= 40; i++)
156          test_2src_op(nir_op_umod, i, d);
157       for (int i = 0; i < 20; i++)
158          test_2src_op(nir_op_umod, UINT32_MAX - i, d);
159    }
160 }
161 
TEST_F(nir_opt_idiv_const_test,imod)162 TEST_F(nir_opt_idiv_const_test, imod)
163 {
164    for (int32_t d : {16, -16, 17, -17, 0, INT32_MIN, INT32_MAX}) {
165       for (int i = -40; i <= 40; i++)
166          test_2src_op(nir_op_imod, i, d);
167       for (int i = 0; i < 20; i++)
168          test_2src_op(nir_op_imod, INT32_MIN + i, d);
169       for (int i = 0; i < 20; i++)
170          test_2src_op(nir_op_imod, INT32_MAX - i, d);
171    }
172 }
173 
TEST_F(nir_opt_idiv_const_test,irem)174 TEST_F(nir_opt_idiv_const_test, irem)
175 {
176    for (int32_t d : {16, -16, 17, -17, 0, INT32_MIN, INT32_MAX}) {
177       for (int i = -40; i <= 40; i++)
178          test_2src_op(nir_op_irem, i, d);
179       for (int i = 0; i < 20; i++)
180          test_2src_op(nir_op_irem, INT32_MIN + i, d);
181       for (int i = 0; i < 20; i++)
182          test_2src_op(nir_op_irem, INT32_MAX - i, d);
183    }
184 }
185 
186 }
187