• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_context.h"
29 #include "brw_eu.h"
30 
31 static bool
test_compact_instruction(struct brw_codegen * p,brw_inst src)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
clear_pad_bits(const struct gen_device_info * devinfo,brw_inst * inst)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_opcode(devinfo, inst) != BRW_OPCODE_BREAK &&
73        brw_inst_opcode(devinfo, inst) != BRW_OPCODE_CONTINUE &&
74        brw_inst_src0_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE &&
75        brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) {
76       brw_inst_set_bits(inst, 127, 111, 0);
77    }
78 }
79 
80 static bool
skip_bit(const struct gen_device_info * devinfo,brw_inst * src,int bit)81 skip_bit(const struct gen_device_info *devinfo, brw_inst *src, int bit)
82 {
83    /* pad bit */
84    if (bit == 7)
85       return true;
86 
87    /* The compact bit -- uncompacted can't have it set. */
88    if (bit == 29)
89       return true;
90 
91    /* pad bit */
92    if (bit == 47)
93       return true;
94 
95    /* pad bits */
96    if (bit >= 90 && bit <= 95)
97       return true;
98 
99    /* sometimes these are pad bits. */
100    if (brw_inst_opcode(devinfo, src) != BRW_OPCODE_SEND &&
101        brw_inst_opcode(devinfo, src) != BRW_OPCODE_SENDC &&
102        brw_inst_opcode(devinfo, src) != BRW_OPCODE_BREAK &&
103        brw_inst_opcode(devinfo, src) != BRW_OPCODE_CONTINUE &&
104        brw_inst_src0_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
105        brw_inst_src1_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
106        bit >= 121) {
107       return true;
108    }
109 
110    return false;
111 }
112 
113 static bool
test_fuzz_compact_instruction(struct brw_codegen * p,brw_inst src)114 test_fuzz_compact_instruction(struct brw_codegen *p, brw_inst src)
115 {
116    for (int bit0 = 0; bit0 < 128; bit0++) {
117       if (skip_bit(p->devinfo, &src, bit0))
118 	 continue;
119 
120       for (int bit1 = 0; bit1 < 128; bit1++) {
121          brw_inst instr = src;
122 	 uint32_t *bits = (uint32_t *)&instr;
123 
124          if (skip_bit(p->devinfo, &src, bit1))
125 	    continue;
126 
127 	 bits[bit0 / 32] ^= (1 << (bit0 & 31));
128 	 bits[bit1 / 32] ^= (1 << (bit1 & 31));
129 
130          clear_pad_bits(p->devinfo, &instr);
131 
132 	 if (!test_compact_instruction(p, instr)) {
133 	    printf("  twiddled bits for fuzzing %d, %d\n", bit0, bit1);
134 	    return false;
135 	 }
136       }
137    }
138 
139    return true;
140 }
141 
142 static void
gen_ADD_GRF_GRF_GRF(struct brw_codegen * p)143 gen_ADD_GRF_GRF_GRF(struct brw_codegen *p)
144 {
145    struct brw_reg g0 = brw_vec8_grf(0, 0);
146    struct brw_reg g2 = brw_vec8_grf(2, 0);
147    struct brw_reg g4 = brw_vec8_grf(4, 0);
148 
149    brw_ADD(p, g0, g2, g4);
150 }
151 
152 static void
gen_ADD_GRF_GRF_IMM(struct brw_codegen * p)153 gen_ADD_GRF_GRF_IMM(struct brw_codegen *p)
154 {
155    struct brw_reg g0 = brw_vec8_grf(0, 0);
156    struct brw_reg g2 = brw_vec8_grf(2, 0);
157 
158    brw_ADD(p, g0, g2, brw_imm_f(1.0));
159 }
160 
161 static void
gen_ADD_GRF_GRF_IMM_d(struct brw_codegen * p)162 gen_ADD_GRF_GRF_IMM_d(struct brw_codegen *p)
163 {
164    struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D);
165    struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D);
166 
167    brw_ADD(p, g0, g2, brw_imm_d(1));
168 }
169 
170 static void
gen_MOV_GRF_GRF(struct brw_codegen * p)171 gen_MOV_GRF_GRF(struct brw_codegen *p)
172 {
173    struct brw_reg g0 = brw_vec8_grf(0, 0);
174    struct brw_reg g2 = brw_vec8_grf(2, 0);
175 
176    brw_MOV(p, g0, g2);
177 }
178 
179 static void
gen_ADD_MRF_GRF_GRF(struct brw_codegen * p)180 gen_ADD_MRF_GRF_GRF(struct brw_codegen *p)
181 {
182    struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
183    struct brw_reg g2 = brw_vec8_grf(2, 0);
184    struct brw_reg g4 = brw_vec8_grf(4, 0);
185 
186    brw_ADD(p, m6, g2, g4);
187 }
188 
189 static void
gen_ADD_vec1_GRF_GRF_GRF(struct brw_codegen * p)190 gen_ADD_vec1_GRF_GRF_GRF(struct brw_codegen *p)
191 {
192    struct brw_reg g0 = brw_vec1_grf(0, 0);
193    struct brw_reg g2 = brw_vec1_grf(2, 0);
194    struct brw_reg g4 = brw_vec1_grf(4, 0);
195 
196    brw_ADD(p, g0, g2, g4);
197 }
198 
199 static void
gen_PLN_MRF_GRF_GRF(struct brw_codegen * p)200 gen_PLN_MRF_GRF_GRF(struct brw_codegen *p)
201 {
202    struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
203    struct brw_reg interp = brw_vec1_grf(2, 0);
204    struct brw_reg g4 = brw_vec8_grf(4, 0);
205 
206    brw_PLN(p, m6, interp, g4);
207 }
208 
209 static void
gen_f0_0_MOV_GRF_GRF(struct brw_codegen * p)210 gen_f0_0_MOV_GRF_GRF(struct brw_codegen *p)
211 {
212    struct brw_reg g0 = brw_vec8_grf(0, 0);
213    struct brw_reg g2 = brw_vec8_grf(2, 0);
214 
215    brw_push_insn_state(p);
216    brw_set_default_predicate_control(p, true);
217    brw_MOV(p, g0, g2);
218    brw_pop_insn_state(p);
219 }
220 
221 /* The handling of f0.1 vs f0.0 changes between gen6 and gen7.  Explicitly test
222  * it, so that we run the fuzzing can run over all the other bits that might
223  * interact with it.
224  */
225 static void
gen_f0_1_MOV_GRF_GRF(struct brw_codegen * p)226 gen_f0_1_MOV_GRF_GRF(struct brw_codegen *p)
227 {
228    struct brw_reg g0 = brw_vec8_grf(0, 0);
229    struct brw_reg g2 = brw_vec8_grf(2, 0);
230 
231    brw_push_insn_state(p);
232    brw_set_default_predicate_control(p, true);
233    brw_inst *mov = brw_MOV(p, g0, g2);
234    brw_inst_set_flag_subreg_nr(p->devinfo, mov, 1);
235    brw_pop_insn_state(p);
236 }
237 
238 struct {
239    void (*func)(struct brw_codegen *p);
240 } tests[] = {
241    { gen_MOV_GRF_GRF },
242    { gen_ADD_GRF_GRF_GRF },
243    { gen_ADD_GRF_GRF_IMM },
244    { gen_ADD_GRF_GRF_IMM_d },
245    { gen_ADD_MRF_GRF_GRF },
246    { gen_ADD_vec1_GRF_GRF_GRF },
247    { gen_PLN_MRF_GRF_GRF },
248    { gen_f0_0_MOV_GRF_GRF },
249    { gen_f0_1_MOV_GRF_GRF },
250 };
251 
252 static bool
run_tests(const struct gen_device_info * devinfo)253 run_tests(const struct gen_device_info *devinfo)
254 {
255    bool fail = false;
256 
257    for (int i = 0; i < ARRAY_SIZE(tests); i++) {
258       for (int align_16 = 0; align_16 <= 1; align_16++) {
259 	 struct brw_codegen *p = rzalloc(NULL, struct brw_codegen);
260 	 brw_init_codegen(devinfo, p, p);
261 
262 	 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
263 	 if (align_16)
264 	    brw_set_default_access_mode(p, BRW_ALIGN_16);
265 	 else
266 	    brw_set_default_access_mode(p, BRW_ALIGN_1);
267 
268 	 tests[i].func(p);
269 	 assert(p->nr_insn == 1);
270 
271 	 if (!test_compact_instruction(p, p->store[0])) {
272 	    fail = true;
273 	    continue;
274 	 }
275 
276 	 if (!test_fuzz_compact_instruction(p, p->store[0])) {
277 	    fail = true;
278 	    continue;
279 	 }
280 
281 	 ralloc_free(p);
282       }
283    }
284 
285    return fail;
286 }
287 
288 int
main(int argc,char ** argv)289 main(int argc, char **argv)
290 {
291    struct gen_device_info *devinfo = calloc(1, sizeof(*devinfo));
292    devinfo->gen = 6;
293    bool fail = false;
294 
295    for (devinfo->gen = 6; devinfo->gen <= 7; devinfo->gen++) {
296       fail |= run_tests(devinfo);
297    }
298 
299    return fail;
300 }
301