intel/compiler: Limit compaction unit tests to specific gens
[mesa.git] / src / intel / compiler / test_eu_compact.cpp
1 /*
2 * Copyright © 2012 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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdbool.h>
27 #include "util/ralloc.h"
28 #include "brw_eu.h"
29 #include "brw_gen_enum.h"
30
31 static bool
32 test_compact_instruction(struct brw_codegen *p, brw_inst src)
33 {
34 brw_compact_inst dst;
35 memset(&dst, 0xd0, sizeof(dst));
36
37 if (brw_try_compact_instruction(p->devinfo, &dst, &src)) {
38 brw_inst uncompacted;
39
40 brw_uncompact_instruction(p->devinfo, &uncompacted, &dst);
41 if (memcmp(&uncompacted, &src, sizeof(src))) {
42 brw_debug_compact_uncompact(p->devinfo, &src, &uncompacted);
43 return false;
44 }
45 } else {
46 brw_compact_inst unchanged;
47 memset(&unchanged, 0xd0, sizeof(unchanged));
48 /* It's not supposed to change dst unless it compacted. */
49 if (memcmp(&unchanged, &dst, sizeof(dst))) {
50 fprintf(stderr, "Failed to compact, but dst changed\n");
51 fprintf(stderr, " Instruction: ");
52 brw_disassemble_inst(stderr, p->devinfo, &src, false);
53 return false;
54 }
55 }
56
57 return true;
58 }
59
60 /**
61 * When doing fuzz testing, pad bits won't round-trip.
62 *
63 * This sort of a superset of skip_bit, which is testing for changing bits that
64 * aren't worth testing for fuzzing. We also just want to clear bits that
65 * become meaningless once fuzzing twiddles a related bit.
66 */
67 static void
68 clear_pad_bits(const struct gen_device_info *devinfo, brw_inst *inst)
69 {
70 if (brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SEND &&
71 brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SENDC &&
72 brw_inst_src0_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE &&
73 brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) {
74 brw_inst_set_bits(inst, 127, 111, 0);
75 }
76
77 if (devinfo->gen == 8 && !devinfo->is_cherryview &&
78 is_3src(devinfo, brw_inst_opcode(devinfo, inst))) {
79 brw_inst_set_bits(inst, 105, 105, 0);
80 brw_inst_set_bits(inst, 84, 84, 0);
81 brw_inst_set_bits(inst, 36, 35, 0);
82 }
83 }
84
85 static bool
86 skip_bit(const struct gen_device_info *devinfo, brw_inst *src, int bit)
87 {
88 /* pad bit */
89 if (bit == 7)
90 return true;
91
92 /* The compact bit -- uncompacted can't have it set. */
93 if (bit == 29)
94 return true;
95
96 if (is_3src(devinfo, brw_inst_opcode(devinfo, src))) {
97 if (devinfo->gen >= 9 || devinfo->is_cherryview) {
98 if (bit == 127)
99 return true;
100 } else {
101 if (bit >= 126 && bit <= 127)
102 return true;
103
104 if (bit == 105)
105 return true;
106
107 if (bit == 84)
108 return true;
109
110 if (bit >= 35 && bit <= 36)
111 return true;
112 }
113 } else {
114 if (bit == 47)
115 return true;
116
117 if (devinfo->gen >= 8) {
118 if (bit == 11)
119 return true;
120
121 if (bit == 95)
122 return true;
123 } else {
124 if (devinfo->gen < 7 && bit == 90)
125 return true;
126
127 if (bit >= 91 && bit <= 95)
128 return true;
129 }
130 }
131
132 /* sometimes these are pad bits. */
133 if (brw_inst_opcode(devinfo, src) != BRW_OPCODE_SEND &&
134 brw_inst_opcode(devinfo, src) != BRW_OPCODE_SENDC &&
135 brw_inst_src0_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
136 brw_inst_src1_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
137 bit >= 121) {
138 return true;
139 }
140
141 return false;
142 }
143
144 static bool
145 test_fuzz_compact_instruction(struct brw_codegen *p, brw_inst src)
146 {
147 for (int bit0 = 0; bit0 < 128; bit0++) {
148 if (skip_bit(p->devinfo, &src, bit0))
149 continue;
150
151 for (int bit1 = 0; bit1 < 128; bit1++) {
152 brw_inst instr = src;
153 uint64_t *bits = instr.data;
154
155 if (skip_bit(p->devinfo, &src, bit1))
156 continue;
157
158 bits[bit0 / 64] ^= (1ull << (bit0 & 63));
159 bits[bit1 / 64] ^= (1ull << (bit1 & 63));
160
161 clear_pad_bits(p->devinfo, &instr);
162
163 if (!test_compact_instruction(p, instr)) {
164 printf(" twiddled bits for fuzzing %d, %d\n", bit0, bit1);
165 return false;
166 }
167 }
168 }
169
170 return true;
171 }
172
173 static void
174 gen_ADD_GRF_GRF_GRF(struct brw_codegen *p)
175 {
176 struct brw_reg g0 = brw_vec8_grf(0, 0);
177 struct brw_reg g2 = brw_vec8_grf(2, 0);
178 struct brw_reg g4 = brw_vec8_grf(4, 0);
179
180 brw_ADD(p, g0, g2, g4);
181 }
182
183 static void
184 gen_ADD_GRF_GRF_IMM(struct brw_codegen *p)
185 {
186 struct brw_reg g0 = brw_vec8_grf(0, 0);
187 struct brw_reg g2 = brw_vec8_grf(2, 0);
188
189 brw_ADD(p, g0, g2, brw_imm_f(1.0));
190 }
191
192 static void
193 gen_ADD_GRF_GRF_IMM_d(struct brw_codegen *p)
194 {
195 struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D);
196 struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D);
197
198 brw_ADD(p, g0, g2, brw_imm_d(1));
199 }
200
201 static void
202 gen_MOV_GRF_GRF(struct brw_codegen *p)
203 {
204 struct brw_reg g0 = brw_vec8_grf(0, 0);
205 struct brw_reg g2 = brw_vec8_grf(2, 0);
206
207 brw_MOV(p, g0, g2);
208 }
209
210 static void
211 gen_ADD_MRF_GRF_GRF(struct brw_codegen *p)
212 {
213 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
214 struct brw_reg g2 = brw_vec8_grf(2, 0);
215 struct brw_reg g4 = brw_vec8_grf(4, 0);
216
217 brw_ADD(p, m6, g2, g4);
218 }
219
220 static void
221 gen_ADD_vec1_GRF_GRF_GRF(struct brw_codegen *p)
222 {
223 struct brw_reg g0 = brw_vec1_grf(0, 0);
224 struct brw_reg g2 = brw_vec1_grf(2, 0);
225 struct brw_reg g4 = brw_vec1_grf(4, 0);
226
227 brw_ADD(p, g0, g2, g4);
228 }
229
230 static void
231 gen_PLN_MRF_GRF_GRF(struct brw_codegen *p)
232 {
233 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
234 struct brw_reg interp = brw_vec1_grf(2, 0);
235 struct brw_reg g4 = brw_vec8_grf(4, 0);
236
237 brw_PLN(p, m6, interp, g4);
238 }
239
240 static void
241 gen_f0_0_MOV_GRF_GRF(struct brw_codegen *p)
242 {
243 struct brw_reg g0 = brw_vec8_grf(0, 0);
244 struct brw_reg g2 = brw_vec8_grf(2, 0);
245
246 brw_push_insn_state(p);
247 brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
248 brw_MOV(p, g0, g2);
249 brw_pop_insn_state(p);
250 }
251
252 /* The handling of f0.1 vs f0.0 changes between gen6 and gen7. Explicitly test
253 * it, so that we run the fuzzing can run over all the other bits that might
254 * interact with it.
255 */
256 static void
257 gen_f0_1_MOV_GRF_GRF(struct brw_codegen *p)
258 {
259 struct brw_reg g0 = brw_vec8_grf(0, 0);
260 struct brw_reg g2 = brw_vec8_grf(2, 0);
261
262 brw_push_insn_state(p);
263 brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
264 brw_inst *mov = brw_MOV(p, g0, g2);
265 brw_inst_set_flag_subreg_nr(p->devinfo, mov, 1);
266 brw_pop_insn_state(p);
267 }
268
269 struct {
270 void (*func)(struct brw_codegen *p);
271 int gens;
272 } tests[] = {
273 { gen_MOV_GRF_GRF, GEN_ALL },
274 { gen_ADD_GRF_GRF_GRF, GEN_ALL },
275 { gen_ADD_GRF_GRF_IMM, GEN_ALL },
276 { gen_ADD_GRF_GRF_IMM_d, GEN_ALL },
277 { gen_ADD_MRF_GRF_GRF, GEN_LE(GEN6) },
278 { gen_ADD_vec1_GRF_GRF_GRF, GEN_ALL },
279 { gen_PLN_MRF_GRF_GRF, GEN_LE(GEN6) },
280 { gen_f0_0_MOV_GRF_GRF, GEN_ALL },
281 { gen_f0_1_MOV_GRF_GRF, GEN_ALL },
282 };
283
284 static bool
285 run_tests(const struct gen_device_info *devinfo)
286 {
287 brw_init_compaction_tables(devinfo);
288 bool fail = false;
289
290 for (unsigned i = 0; i < ARRAY_SIZE(tests); i++) {
291 if ((tests[i].gens & gen_from_devinfo(devinfo)) == 0)
292 continue;
293
294 for (int align_16 = 0; align_16 <= 1; align_16++) {
295 /* Align16 support is not present on Gen11+ */
296 if (devinfo->gen >= 11 && align_16)
297 continue;
298
299 struct brw_codegen *p = rzalloc(NULL, struct brw_codegen);
300 brw_init_codegen(devinfo, p, p);
301
302 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
303 if (align_16)
304 brw_set_default_access_mode(p, BRW_ALIGN_16);
305 else
306 brw_set_default_access_mode(p, BRW_ALIGN_1);
307
308 tests[i].func(p);
309 assert(p->nr_insn == 1);
310
311 if (!test_compact_instruction(p, p->store[0])) {
312 fail = true;
313 continue;
314 }
315
316 if (!test_fuzz_compact_instruction(p, p->store[0])) {
317 fail = true;
318 continue;
319 }
320
321 ralloc_free(p);
322 }
323 }
324
325 return fail;
326 }
327
328 int
329 main(int argc, char **argv)
330 {
331 struct gen_device_info *devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
332 bool fail = false;
333
334 for (devinfo->gen = 5; devinfo->gen <= 9; devinfo->gen++) {
335 fail |= run_tests(devinfo);
336 }
337
338 return fail;
339 }