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