Home | History | Annotate | Download | only in i965
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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