xref: /aosp_15_r20/external/mesa3d/src/compiler/nir/tests/mod_analysis_tests.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 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 "nir_test.h"
25 #include "util/u_math.h"
26 
27 static inline bool
nir_mod_analysis_comp0(nir_def * val,nir_alu_type val_type,unsigned div,unsigned * mod)28 nir_mod_analysis_comp0(nir_def *val, nir_alu_type val_type, unsigned div, unsigned *mod)
29 {
30    return nir_mod_analysis(nir_get_scalar(val, 0), val_type, div, mod);
31 }
32 
33 class nir_mod_analysis_test : public nir_test {
34 protected:
35    nir_mod_analysis_test();
36 
37    nir_def *nir_imul_vec2y(nir_builder *b, nir_def *src0, nir_def *src1);
38 
39    nir_def *v[50];
40    nir_def *invocation;
41 };
42 
nir_mod_analysis_test()43 nir_mod_analysis_test::nir_mod_analysis_test()
44    : nir_test::nir_test("nir_mod_analysis_test")
45 {
46    for (int i = 0; i < 50; ++i)
47       v[i] = nir_imm_int(b, i);
48    invocation = nir_load_local_invocation_index(b);
49 }
50 
51 /* returns src0 * src1.y */
52 nir_def *
nir_imul_vec2y(nir_builder * b,nir_def * src0,nir_def * src1)53 nir_mod_analysis_test::nir_imul_vec2y(nir_builder *b, nir_def *src0, nir_def *src1)
54 {
55    nir_alu_instr *instr = nir_alu_instr_create(b->shader, nir_op_imul);
56 
57    instr->src[0].src = nir_src_for_ssa(src0);
58    instr->src[1].src = nir_src_for_ssa(src1);
59    instr->src[1].swizzle[0] = 1;
60 
61    nir_def_init(&instr->instr, &instr->def, 1, 32);
62 
63    nir_builder_instr_insert(b, &instr->instr);
64    return &instr->def;
65 }
66 
TEST_F(nir_mod_analysis_test,const_val)67 TEST_F(nir_mod_analysis_test, const_val)
68 {
69    /* const % const_mod should be always known */
70    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
71       for (int cnst = 0; cnst < 10; ++cnst) {
72          unsigned mod = INT32_MAX;
73 
74          EXPECT_TRUE(nir_mod_analysis_comp0(v[cnst], nir_type_uint, const_mod, &mod));
75          EXPECT_EQ(mod, cnst % const_mod);
76       }
77    }
78 }
79 
TEST_F(nir_mod_analysis_test,dynamic)80 TEST_F(nir_mod_analysis_test, dynamic)
81 {
82    /* invocation % const_mod should never be known unless const_mod is 1 */
83 
84    unsigned mod = INT32_MAX;
85 
86    EXPECT_TRUE(nir_mod_analysis_comp0(invocation, nir_type_uint, 1, &mod));
87    EXPECT_EQ(mod, 0);
88 
89    for (unsigned const_mod = 2; const_mod <= 1024; const_mod *= 2)
90       EXPECT_FALSE(nir_mod_analysis_comp0(invocation, nir_type_uint, const_mod, &mod));
91 }
92 
TEST_F(nir_mod_analysis_test,const_plus_const)93 TEST_F(nir_mod_analysis_test, const_plus_const)
94 {
95    /* (const1 + const2) % const_mod should always be known */
96    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
97       for (unsigned c1 = 0; c1 < 10; ++c1) {
98          for (unsigned c2 = 0; c2 < 10; ++c2) {
99             nir_def *sum = nir_iadd(b, v[c1], v[c2]);
100 
101             unsigned mod = INT32_MAX;
102 
103             EXPECT_TRUE(nir_mod_analysis_comp0(sum, nir_type_uint, const_mod, &mod));
104             EXPECT_EQ(mod, (c1 + c2) % const_mod);
105          }
106       }
107    }
108 }
109 
TEST_F(nir_mod_analysis_test,dynamic_plus_const)110 TEST_F(nir_mod_analysis_test, dynamic_plus_const)
111 {
112    /* (invocation + const) % const_mod should never be known unless const_mod is 1 */
113    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
114       for (unsigned c = 0; c < 10; ++c) {
115          nir_def *sum = nir_iadd(b, invocation, v[c]);
116 
117          unsigned mod = INT32_MAX;
118 
119          if (const_mod == 1) {
120             EXPECT_TRUE(nir_mod_analysis_comp0(sum, nir_type_uint, const_mod, &mod));
121             EXPECT_EQ(mod, 0);
122          } else {
123             EXPECT_FALSE(nir_mod_analysis_comp0(sum, nir_type_uint, const_mod, &mod));
124          }
125       }
126    }
127 }
128 
TEST_F(nir_mod_analysis_test,const_mul_const)129 TEST_F(nir_mod_analysis_test, const_mul_const)
130 {
131    /* (const1 * const2) % const_mod should always be known */
132    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
133       for (unsigned c1 = 0; c1 < 10; ++c1) {
134          for (unsigned c2 = 0; c2 < 10; ++c2) {
135             nir_def *mul = nir_imul(b, v[c1], v[c2]);
136 
137             unsigned mod = INT32_MAX;
138 
139             EXPECT_TRUE(nir_mod_analysis_comp0(mul, nir_type_uint, const_mod, &mod));
140             EXPECT_EQ(mod, (c1 * c2) % const_mod);
141          }
142       }
143    }
144 }
145 
TEST_F(nir_mod_analysis_test,dynamic_mul_const)146 TEST_F(nir_mod_analysis_test, dynamic_mul_const)
147 {
148    /* (invocation * const) % const_mod == 0 only if const % const_mod == 0, unknown otherwise */
149    for (unsigned const_mod = 2; const_mod <= 1024; const_mod *= 2) {
150       for (unsigned c = 0; c < 10; ++c) {
151          nir_def *mul = nir_imul(b, invocation, v[c]);
152 
153          unsigned mod = INT32_MAX;
154 
155          if (c % const_mod == 0) {
156             EXPECT_TRUE(nir_mod_analysis_comp0(mul, nir_type_uint, const_mod, &mod));
157             EXPECT_EQ(mod, 0);
158          } else {
159             EXPECT_FALSE(nir_mod_analysis_comp0(mul, nir_type_uint, const_mod, &mod));
160          }
161       }
162    }
163 }
164 
TEST_F(nir_mod_analysis_test,dynamic_mul_const_swizzled)165 TEST_F(nir_mod_analysis_test, dynamic_mul_const_swizzled)
166 {
167    /* (invocation * const.y) % const_mod == 0 only if const.y % const_mod == 0, unknown otherwise */
168    for (unsigned const_mod = 2; const_mod <= 1024; const_mod *= 2) {
169       for (unsigned c = 0; c < 10; ++c) {
170          nir_def *vec2 = nir_imm_ivec2(b, 10 - c, c);
171          nir_def *mul = nir_imul_vec2y(b, invocation, vec2);
172 
173          unsigned mod = INT32_MAX;
174 
175          if (c % const_mod == 0) {
176             EXPECT_TRUE(nir_mod_analysis_comp0(mul, nir_type_uint, const_mod, &mod));
177             EXPECT_EQ(mod, 0);
178          } else {
179             EXPECT_FALSE(nir_mod_analysis_comp0(mul, nir_type_uint, const_mod, &mod));
180          }
181       }
182    }
183 }
184 
TEST_F(nir_mod_analysis_test,dynamic_mul32x16_const)185 TEST_F(nir_mod_analysis_test, dynamic_mul32x16_const)
186 {
187    /* (invocation mul32x16 const) % const_mod == 0 only if const % const_mod == 0
188     * and const_mod <= 2^16, unknown otherwise
189     */
190    for (unsigned const_mod = 1; const_mod <= (1u << 24); const_mod *= 2) {
191       for (unsigned c = 0; c < 10; ++c) {
192          nir_def *mul = nir_imul_32x16(b, invocation, v[c]);
193 
194          unsigned mod = INT32_MAX;
195 
196          if (c % const_mod == 0 && const_mod <= (1u << 16)) {
197             EXPECT_TRUE(nir_mod_analysis_comp0(mul, nir_type_uint, const_mod, &mod));
198             EXPECT_EQ(mod, 0);
199          } else {
200             EXPECT_FALSE(nir_mod_analysis_comp0(mul, nir_type_uint, const_mod, &mod));
201          }
202       }
203    }
204 }
205 
TEST_F(nir_mod_analysis_test,dynamic_shl_const)206 TEST_F(nir_mod_analysis_test, dynamic_shl_const)
207 {
208    /* (invocation << const) % const_mod == 0 only if const >= log2(const_mod), unknown otherwise */
209    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
210       for (unsigned c = 0; c < 10; ++c) {
211          nir_def *shl = nir_ishl(b, invocation, v[c]);
212 
213          unsigned mod = INT32_MAX;
214 
215          if (c >= util_logbase2(const_mod)) {
216             EXPECT_TRUE(nir_mod_analysis_comp0(shl, nir_type_uint, const_mod, &mod));
217             EXPECT_EQ(mod, 0);
218          } else {
219             EXPECT_FALSE(nir_mod_analysis_comp0(shl, nir_type_uint, const_mod, &mod));
220          }
221       }
222    }
223 }
224 
TEST_F(nir_mod_analysis_test,dynamic_shr_const)225 TEST_F(nir_mod_analysis_test, dynamic_shr_const)
226 {
227    /* (invocation >> const) % const_mod should never be known, unless const_mod is 1 */
228    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
229       for (unsigned i = 0; i < 10; ++i) {
230          nir_def *shr = nir_ishr(b, invocation, v[i]);
231 
232          unsigned mod = INT32_MAX;
233 
234          if (const_mod == 1) {
235             EXPECT_TRUE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
236             EXPECT_EQ(mod, 0);
237          } else {
238             EXPECT_FALSE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
239          }
240       }
241    }
242 }
243 
TEST_F(nir_mod_analysis_test,dynamic_mul_const_shr_const)244 TEST_F(nir_mod_analysis_test, dynamic_mul_const_shr_const)
245 {
246    /* ((invocation * 32) >> const) % const_mod == 0 only if
247     *   const_mod is 1 or
248     *   (32 >> const) is not 0 and (32 >> const) % const_mod == 0
249     *
250     */
251    nir_def *inv_mul_32 = nir_imul(b, invocation, v[32]);
252    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
253       for (unsigned c = 0; c < 8; ++c) {
254          nir_def *shr = nir_ishr(b, inv_mul_32, v[c]);
255 
256          unsigned mod = INT32_MAX;
257 
258          if (const_mod == 1 || ((32 >> c) > 0 && (32 >> c) % const_mod == 0)) {
259             EXPECT_TRUE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
260             EXPECT_EQ(mod, 0);
261          } else {
262             EXPECT_FALSE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
263          }
264       }
265    }
266 }
267 
TEST_F(nir_mod_analysis_test,dynamic_mul_const_swizzled_shr_const)268 TEST_F(nir_mod_analysis_test, dynamic_mul_const_swizzled_shr_const)
269 {
270    /* ((invocation * ivec2(31, 32).y) >> const) % const_mod == 0 only if
271     *   const_mod is 1 or
272     *   (32 >> const) is not 0 and (32 >> const) % const_mod == 0
273     *
274     */
275    nir_def *vec2 = nir_imm_ivec2(b, 31, 32);
276    nir_def *inv_mul_32 = nir_imul_vec2y(b, invocation, vec2);
277 
278    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
279       for (unsigned c = 0; c < 8; ++c) {
280          nir_def *shr = nir_ishr(b, inv_mul_32, v[c]);
281 
282          unsigned mod = INT32_MAX;
283 
284          if (const_mod == 1 || ((32 >> c) > 0 && (32 >> c) % const_mod == 0)) {
285             EXPECT_TRUE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
286             EXPECT_EQ(mod, 0);
287          } else {
288             EXPECT_FALSE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
289          }
290       }
291    }
292 }
293 
TEST_F(nir_mod_analysis_test,const_shr_const)294 TEST_F(nir_mod_analysis_test, const_shr_const)
295 {
296    /* (const >> const) % const_mod should always be known */
297    for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
298       for (unsigned i = 0; i < 50; ++i) {
299          for (unsigned j = 0; j < 6; ++j) {
300             nir_def *shr = nir_ishr(b, v[i], v[j]);
301 
302             unsigned mod = INT32_MAX;
303 
304             EXPECT_TRUE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
305             EXPECT_EQ(mod, (i >> j) % const_mod);
306          }
307       }
308    }
309 }
310 
TEST_F(nir_mod_analysis_test,const_shr_const_overflow)311 TEST_F(nir_mod_analysis_test, const_shr_const_overflow)
312 {
313    /* (large_const >> const_shr) % const_mod should be known if
314     * const_mod << const_shr is still below UINT32_MAX.
315     */
316    unsigned large_const_int = 0x12345678;
317    nir_def *large_const = nir_imm_int(b, large_const_int);
318 
319    for (unsigned shift = 0; shift < 30; ++shift) {
320       nir_def *shr = nir_ishr(b, large_const, v[shift]);
321 
322       for (unsigned const_mod = 1; const_mod <= 1024; const_mod *= 2) {
323          unsigned mod = INT32_MAX;
324 
325          if ((((uint64_t)const_mod) << shift) > UINT32_MAX) {
326             EXPECT_FALSE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
327          } else {
328             EXPECT_TRUE(nir_mod_analysis_comp0(shr, nir_type_uint, const_mod, &mod));
329             EXPECT_EQ(mod, (large_const_int >> shift) % const_mod);
330          }
331       }
332    }
333 }
334