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