OSDN Git Service

i965/fs: Exit the compile if spilling would overwrite in-use MRFs.
[android-x86/external-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, struct brw_instruction src)
33 {
34    struct brw_context *brw = p->brw;
35
36    struct brw_compact_instruction dst;
37    memset(&dst, 0xd0, sizeof(dst));
38
39    if (brw_try_compact_instruction(p, &dst, &src)) {
40       struct brw_instruction 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       struct brw_compact_instruction 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_disasm(stderr, &src, brw->gen);
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(struct brw_instruction *inst)
71 {
72    if (inst->header.opcode != BRW_OPCODE_SEND &&
73        inst->header.opcode != BRW_OPCODE_SENDC &&
74        inst->header.opcode != BRW_OPCODE_BREAK &&
75        inst->header.opcode != BRW_OPCODE_CONTINUE &&
76        inst->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE &&
77        inst->bits1.da1.src1_reg_file != BRW_IMMEDIATE_VALUE) {
78       if (inst->bits3.da1.src1_address_mode)
79          inst->bits3.ia1.pad1 = 0;
80       else
81          inst->bits3.da1.pad0 = 0;
82    }
83 }
84
85 static bool
86 skip_bit(struct brw_instruction *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    /* pad bit */
97    if (bit == 47)
98       return true;
99
100    /* pad bits */
101    if (bit >= 90 && bit <= 95)
102       return true;
103
104    /* sometimes these are pad bits. */
105    if (src->header.opcode != BRW_OPCODE_SEND &&
106        src->header.opcode != BRW_OPCODE_SENDC &&
107        src->header.opcode != BRW_OPCODE_BREAK &&
108        src->header.opcode != BRW_OPCODE_CONTINUE &&
109        src->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE &&
110        src->bits1.da1.src1_reg_file != BRW_IMMEDIATE_VALUE &&
111        bit >= 121) {
112       return true;
113    }
114
115    return false;
116 }
117
118 static bool
119 test_fuzz_compact_instruction(struct brw_compile *p,
120                               struct brw_instruction src)
121 {
122    for (int bit0 = 0; bit0 < 128; bit0++) {
123       if (skip_bit(&src, bit0))
124          continue;
125
126       for (int bit1 = 0; bit1 < 128; bit1++) {
127          struct brw_instruction instr = src;
128          uint32_t *bits = (uint32_t *)&instr;
129
130          if (skip_bit(&src, bit1))
131             continue;
132
133          bits[bit0 / 32] ^= (1 << (bit0 & 31));
134          bits[bit1 / 32] ^= (1 << (bit1 & 31));
135
136          clear_pad_bits(&instr);
137
138          if (!test_compact_instruction(p, instr)) {
139             printf("  twiddled bits for fuzzing %d, %d\n", bit0, bit1);
140             return false;
141          }
142       }
143    }
144
145    return true;
146 }
147
148 static void
149 gen_ADD_GRF_GRF_GRF(struct brw_compile *p)
150 {
151    struct brw_reg g0 = brw_vec8_grf(0, 0);
152    struct brw_reg g2 = brw_vec8_grf(2, 0);
153    struct brw_reg g4 = brw_vec8_grf(4, 0);
154
155    brw_ADD(p, g0, g2, g4);
156 }
157
158 static void
159 gen_ADD_GRF_GRF_IMM(struct brw_compile *p)
160 {
161    struct brw_reg g0 = brw_vec8_grf(0, 0);
162    struct brw_reg g2 = brw_vec8_grf(2, 0);
163
164    brw_ADD(p, g0, g2, brw_imm_f(1.0));
165 }
166
167 static void
168 gen_ADD_GRF_GRF_IMM_d(struct brw_compile *p)
169 {
170    struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D);
171    struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D);
172
173    brw_ADD(p, g0, g2, brw_imm_d(1));
174 }
175
176 static void
177 gen_MOV_GRF_GRF(struct brw_compile *p)
178 {
179    struct brw_reg g0 = brw_vec8_grf(0, 0);
180    struct brw_reg g2 = brw_vec8_grf(2, 0);
181
182    brw_MOV(p, g0, g2);
183 }
184
185 static void
186 gen_ADD_MRF_GRF_GRF(struct brw_compile *p)
187 {
188    struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
189    struct brw_reg g2 = brw_vec8_grf(2, 0);
190    struct brw_reg g4 = brw_vec8_grf(4, 0);
191
192    brw_ADD(p, m6, g2, g4);
193 }
194
195 static void
196 gen_ADD_vec1_GRF_GRF_GRF(struct brw_compile *p)
197 {
198    struct brw_reg g0 = brw_vec1_grf(0, 0);
199    struct brw_reg g2 = brw_vec1_grf(2, 0);
200    struct brw_reg g4 = brw_vec1_grf(4, 0);
201
202    brw_ADD(p, g0, g2, g4);
203 }
204
205 static void
206 gen_PLN_MRF_GRF_GRF(struct brw_compile *p)
207 {
208    struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
209    struct brw_reg interp = brw_vec1_grf(2, 0);
210    struct brw_reg g4 = brw_vec8_grf(4, 0);
211
212    brw_PLN(p, m6, interp, g4);
213 }
214
215 static void
216 gen_f0_0_MOV_GRF_GRF(struct brw_compile *p)
217 {
218    struct brw_reg g0 = brw_vec8_grf(0, 0);
219    struct brw_reg g2 = brw_vec8_grf(2, 0);
220
221    brw_push_insn_state(p);
222    brw_set_predicate_control(p, true);
223    brw_MOV(p, g0, g2);
224    brw_pop_insn_state(p);
225 }
226
227 /* The handling of f0.1 vs f0.0 changes between gen6 and gen7.  Explicitly test
228  * it, so that we run the fuzzing can run over all the other bits that might
229  * interact with it.
230  */
231 static void
232 gen_f0_1_MOV_GRF_GRF(struct brw_compile *p)
233 {
234    struct brw_reg g0 = brw_vec8_grf(0, 0);
235    struct brw_reg g2 = brw_vec8_grf(2, 0);
236
237    brw_push_insn_state(p);
238    brw_set_predicate_control(p, true);
239    current_insn(p)->bits2.da1.flag_subreg_nr = 1;
240    brw_MOV(p, g0, g2);
241    brw_pop_insn_state(p);
242 }
243
244 struct {
245    void (*func)(struct brw_compile *p);
246 } tests[] = {
247    { gen_MOV_GRF_GRF },
248    { gen_ADD_GRF_GRF_GRF },
249    { gen_ADD_GRF_GRF_IMM },
250    { gen_ADD_GRF_GRF_IMM_d },
251    { gen_ADD_MRF_GRF_GRF },
252    { gen_ADD_vec1_GRF_GRF_GRF },
253    { gen_PLN_MRF_GRF_GRF },
254    { gen_f0_0_MOV_GRF_GRF },
255    { gen_f0_1_MOV_GRF_GRF },
256 };
257
258 static bool
259 run_tests(struct brw_context *brw)
260 {
261    bool fail = false;
262
263    for (int i = 0; i < ARRAY_SIZE(tests); i++) {
264       for (int align_16 = 0; align_16 <= 1; align_16++) {
265          struct brw_compile *p = rzalloc(NULL, struct brw_compile);
266          brw_init_compile(brw, p, p);
267
268          brw_set_predicate_control(p, BRW_PREDICATE_NONE);
269          if (align_16)
270             brw_set_access_mode(p, BRW_ALIGN_16);
271          else
272             brw_set_access_mode(p, BRW_ALIGN_1);
273
274          tests[i].func(p);
275          assert(p->nr_insn == 1);
276
277          if (!test_compact_instruction(p, p->store[0])) {
278             fail = true;
279             continue;
280          }
281
282          if (!test_fuzz_compact_instruction(p, p->store[0])) {
283             fail = true;
284             continue;
285          }
286
287          ralloc_free(p);
288       }
289    }
290
291    return fail;
292 }
293
294 int
295 main(int argc, char **argv)
296 {
297    struct brw_context *brw = calloc(1, sizeof(*brw));
298    brw->gen = 6;
299    bool fail = false;
300
301    for (brw->gen = 6; brw->gen <= 7; brw->gen++) {
302       fail |= run_tests(brw);
303    }
304
305    return fail;
306 }