343f060b7481b35fbf045d33fb3fbb06cc6bd9c2
[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, 0, NULL);
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 (!brw_validate_instruction(p->devinfo, &instr, 0, NULL))
164 continue;
165
166 if (!test_compact_instruction(p, instr)) {
167 printf(" twiddled bits for fuzzing %d, %d\n", bit0, bit1);
168 return false;
169 }
170 }
171 }
172
173 return true;
174 }
175
176 static void
177 gen_ADD_GRF_GRF_GRF(struct brw_codegen *p)
178 {
179 struct brw_reg g0 = brw_vec8_grf(0, 0);
180 struct brw_reg g2 = brw_vec8_grf(2, 0);
181 struct brw_reg g4 = brw_vec8_grf(4, 0);
182
183 brw_ADD(p, g0, g2, g4);
184 }
185
186 static void
187 gen_ADD_GRF_GRF_IMM(struct brw_codegen *p)
188 {
189 struct brw_reg g0 = brw_vec8_grf(0, 0);
190 struct brw_reg g2 = brw_vec8_grf(2, 0);
191
192 brw_ADD(p, g0, g2, brw_imm_f(1.0));
193 }
194
195 static void
196 gen_ADD_GRF_GRF_IMM_d(struct brw_codegen *p)
197 {
198 struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D);
199 struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D);
200
201 brw_ADD(p, g0, g2, brw_imm_d(1));
202 }
203
204 static void
205 gen_MOV_GRF_GRF(struct brw_codegen *p)
206 {
207 struct brw_reg g0 = brw_vec8_grf(0, 0);
208 struct brw_reg g2 = brw_vec8_grf(2, 0);
209
210 brw_MOV(p, g0, g2);
211 }
212
213 static void
214 gen_ADD_MRF_GRF_GRF(struct brw_codegen *p)
215 {
216 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
217 struct brw_reg g2 = brw_vec8_grf(2, 0);
218 struct brw_reg g4 = brw_vec8_grf(4, 0);
219
220 brw_ADD(p, m6, g2, g4);
221 }
222
223 static void
224 gen_ADD_vec1_GRF_GRF_GRF(struct brw_codegen *p)
225 {
226 struct brw_reg g0 = brw_vec1_grf(0, 0);
227 struct brw_reg g2 = brw_vec1_grf(2, 0);
228 struct brw_reg g4 = brw_vec1_grf(4, 0);
229
230 brw_ADD(p, g0, g2, g4);
231 }
232
233 static void
234 gen_PLN_MRF_GRF_GRF(struct brw_codegen *p)
235 {
236 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
237 struct brw_reg interp = brw_vec1_grf(2, 0);
238 struct brw_reg g4 = brw_vec8_grf(4, 0);
239
240 brw_PLN(p, m6, interp, g4);
241 }
242
243 static void
244 gen_f0_0_MOV_GRF_GRF(struct brw_codegen *p)
245 {
246 struct brw_reg g0 = brw_vec8_grf(0, 0);
247 struct brw_reg g2 = brw_vec8_grf(2, 0);
248
249 brw_push_insn_state(p);
250 brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
251 brw_MOV(p, g0, g2);
252 brw_pop_insn_state(p);
253 }
254
255 /* The handling of f0.1 vs f0.0 changes between gen6 and gen7. Explicitly test
256 * it, so that we run the fuzzing can run over all the other bits that might
257 * interact with it.
258 */
259 static void
260 gen_f0_1_MOV_GRF_GRF(struct brw_codegen *p)
261 {
262 struct brw_reg g0 = brw_vec8_grf(0, 0);
263 struct brw_reg g2 = brw_vec8_grf(2, 0);
264
265 brw_push_insn_state(p);
266 brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
267 brw_inst *mov = brw_MOV(p, g0, g2);
268 brw_inst_set_flag_subreg_nr(p->devinfo, mov, 1);
269 brw_pop_insn_state(p);
270 }
271
272 struct {
273 void (*func)(struct brw_codegen *p);
274 int gens;
275 } tests[] = {
276 { gen_MOV_GRF_GRF, GEN_ALL },
277 { gen_ADD_GRF_GRF_GRF, GEN_ALL },
278 { gen_ADD_GRF_GRF_IMM, GEN_ALL },
279 { gen_ADD_GRF_GRF_IMM_d, GEN_ALL },
280 { gen_ADD_MRF_GRF_GRF, GEN_LE(GEN6) },
281 { gen_ADD_vec1_GRF_GRF_GRF, GEN_ALL },
282 { gen_PLN_MRF_GRF_GRF, GEN_LE(GEN6) },
283 { gen_f0_0_MOV_GRF_GRF, GEN_ALL },
284 { gen_f0_1_MOV_GRF_GRF, GEN_ALL },
285 };
286
287 static bool
288 run_tests(const struct gen_device_info *devinfo)
289 {
290 brw_init_compaction_tables(devinfo);
291 bool fail = false;
292
293 for (unsigned i = 0; i < ARRAY_SIZE(tests); i++) {
294 if ((tests[i].gens & gen_from_devinfo(devinfo)) == 0)
295 continue;
296
297 for (int align_16 = 0; align_16 <= 1; align_16++) {
298 /* Align16 support is not present on Gen11+ */
299 if (devinfo->gen >= 11 && align_16)
300 continue;
301
302 struct brw_codegen *p = rzalloc(NULL, struct brw_codegen);
303 brw_init_codegen(devinfo, p, p);
304
305 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
306 if (align_16)
307 brw_set_default_access_mode(p, BRW_ALIGN_16);
308 else
309 brw_set_default_access_mode(p, BRW_ALIGN_1);
310
311 tests[i].func(p);
312 assert(p->nr_insn == 1);
313
314 if (!test_compact_instruction(p, p->store[0])) {
315 fail = true;
316 continue;
317 }
318
319 if (!test_fuzz_compact_instruction(p, p->store[0])) {
320 fail = true;
321 continue;
322 }
323
324 ralloc_free(p);
325 }
326 }
327
328 return fail;
329 }
330
331 int
332 main(int argc, char **argv)
333 {
334 struct gen_device_info *devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
335 bool fail = false;
336
337 for (devinfo->gen = 5; devinfo->gen <= 12; devinfo->gen++) {
338 fail |= run_tests(devinfo);
339 }
340
341 return fail;
342 }