summaryrefslogtreecommitdiffstats
path: root/src/intel/compiler/test_eu_compact.cpp
diff options
context:
space:
mode:
authorEmil Velikov <[email protected]>2017-03-07 16:13:42 +0000
committerEmil Velikov <[email protected]>2017-03-13 11:16:35 +0000
commitbdc5036464b40a76115f7c3654043bb1155bd705 (patch)
tree42f776f3b0946b7603667aa8c80c06b99fe824a4 /src/intel/compiler/test_eu_compact.cpp
parentf282ace67862c0633d0a8135e4808867740d0d39 (diff)
intel/compiler: link all tests again gtest, even test_eu_compact"
At the moment all the tests but test_eu_compact are actual C++ gtests. To simplify things, we can move the gtest.la to the common TEST_LIBS. As we're here, we can rename change the test extension [to .cpp] to avoid using the confusing dummy.cpp. Add a nice comment in the makefile for posterity. Signed-off-by: Emil Velikov <[email protected]> Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/intel/compiler/test_eu_compact.cpp')
-rw-r--r--src/intel/compiler/test_eu_compact.cpp300
1 files changed, 300 insertions, 0 deletions
diff --git a/src/intel/compiler/test_eu_compact.cpp b/src/intel/compiler/test_eu_compact.cpp
new file mode 100644
index 00000000000..39e7f1a27c3
--- /dev/null
+++ b/src/intel/compiler/test_eu_compact.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include "util/ralloc.h"
+#include "brw_eu.h"
+
+static bool
+test_compact_instruction(struct brw_codegen *p, brw_inst src)
+{
+ brw_compact_inst dst;
+ memset(&dst, 0xd0, sizeof(dst));
+
+ if (brw_try_compact_instruction(p->devinfo, &dst, &src)) {
+ brw_inst uncompacted;
+
+ brw_uncompact_instruction(p->devinfo, &uncompacted, &dst);
+ if (memcmp(&uncompacted, &src, sizeof(src))) {
+ brw_debug_compact_uncompact(p->devinfo, &src, &uncompacted);
+ return false;
+ }
+ } else {
+ brw_compact_inst unchanged;
+ memset(&unchanged, 0xd0, sizeof(unchanged));
+ /* It's not supposed to change dst unless it compacted. */
+ if (memcmp(&unchanged, &dst, sizeof(dst))) {
+ fprintf(stderr, "Failed to compact, but dst changed\n");
+ fprintf(stderr, " Instruction: ");
+ brw_disassemble_inst(stderr, p->devinfo, &src, false);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * When doing fuzz testing, pad bits won't round-trip.
+ *
+ * This sort of a superset of skip_bit, which is testing for changing bits that
+ * aren't worth testing for fuzzing. We also just want to clear bits that
+ * become meaningless once fuzzing twiddles a related bit.
+ */
+static void
+clear_pad_bits(const struct gen_device_info *devinfo, brw_inst *inst)
+{
+ if (brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SEND &&
+ brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SENDC &&
+ brw_inst_opcode(devinfo, inst) != BRW_OPCODE_BREAK &&
+ brw_inst_opcode(devinfo, inst) != BRW_OPCODE_CONTINUE &&
+ brw_inst_src0_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE &&
+ brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) {
+ brw_inst_set_bits(inst, 127, 111, 0);
+ }
+}
+
+static bool
+skip_bit(const struct gen_device_info *devinfo, brw_inst *src, int bit)
+{
+ /* pad bit */
+ if (bit == 7)
+ return true;
+
+ /* The compact bit -- uncompacted can't have it set. */
+ if (bit == 29)
+ return true;
+
+ /* pad bit */
+ if (bit == 47)
+ return true;
+
+ /* pad bits */
+ if (bit >= 90 && bit <= 95)
+ return true;
+
+ /* sometimes these are pad bits. */
+ if (brw_inst_opcode(devinfo, src) != BRW_OPCODE_SEND &&
+ brw_inst_opcode(devinfo, src) != BRW_OPCODE_SENDC &&
+ brw_inst_opcode(devinfo, src) != BRW_OPCODE_BREAK &&
+ brw_inst_opcode(devinfo, src) != BRW_OPCODE_CONTINUE &&
+ brw_inst_src0_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
+ brw_inst_src1_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE &&
+ bit >= 121) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool
+test_fuzz_compact_instruction(struct brw_codegen *p, brw_inst src)
+{
+ for (int bit0 = 0; bit0 < 128; bit0++) {
+ if (skip_bit(p->devinfo, &src, bit0))
+ continue;
+
+ for (int bit1 = 0; bit1 < 128; bit1++) {
+ brw_inst instr = src;
+ uint32_t *bits = (uint32_t *)&instr;
+
+ if (skip_bit(p->devinfo, &src, bit1))
+ continue;
+
+ bits[bit0 / 32] ^= (1 << (bit0 & 31));
+ bits[bit1 / 32] ^= (1 << (bit1 & 31));
+
+ clear_pad_bits(p->devinfo, &instr);
+
+ if (!test_compact_instruction(p, instr)) {
+ printf(" twiddled bits for fuzzing %d, %d\n", bit0, bit1);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static void
+gen_ADD_GRF_GRF_GRF(struct brw_codegen *p)
+{
+ struct brw_reg g0 = brw_vec8_grf(0, 0);
+ struct brw_reg g2 = brw_vec8_grf(2, 0);
+ struct brw_reg g4 = brw_vec8_grf(4, 0);
+
+ brw_ADD(p, g0, g2, g4);
+}
+
+static void
+gen_ADD_GRF_GRF_IMM(struct brw_codegen *p)
+{
+ struct brw_reg g0 = brw_vec8_grf(0, 0);
+ struct brw_reg g2 = brw_vec8_grf(2, 0);
+
+ brw_ADD(p, g0, g2, brw_imm_f(1.0));
+}
+
+static void
+gen_ADD_GRF_GRF_IMM_d(struct brw_codegen *p)
+{
+ struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D);
+ struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D);
+
+ brw_ADD(p, g0, g2, brw_imm_d(1));
+}
+
+static void
+gen_MOV_GRF_GRF(struct brw_codegen *p)
+{
+ struct brw_reg g0 = brw_vec8_grf(0, 0);
+ struct brw_reg g2 = brw_vec8_grf(2, 0);
+
+ brw_MOV(p, g0, g2);
+}
+
+static void
+gen_ADD_MRF_GRF_GRF(struct brw_codegen *p)
+{
+ struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
+ struct brw_reg g2 = brw_vec8_grf(2, 0);
+ struct brw_reg g4 = brw_vec8_grf(4, 0);
+
+ brw_ADD(p, m6, g2, g4);
+}
+
+static void
+gen_ADD_vec1_GRF_GRF_GRF(struct brw_codegen *p)
+{
+ struct brw_reg g0 = brw_vec1_grf(0, 0);
+ struct brw_reg g2 = brw_vec1_grf(2, 0);
+ struct brw_reg g4 = brw_vec1_grf(4, 0);
+
+ brw_ADD(p, g0, g2, g4);
+}
+
+static void
+gen_PLN_MRF_GRF_GRF(struct brw_codegen *p)
+{
+ struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
+ struct brw_reg interp = brw_vec1_grf(2, 0);
+ struct brw_reg g4 = brw_vec8_grf(4, 0);
+
+ brw_PLN(p, m6, interp, g4);
+}
+
+static void
+gen_f0_0_MOV_GRF_GRF(struct brw_codegen *p)
+{
+ struct brw_reg g0 = brw_vec8_grf(0, 0);
+ struct brw_reg g2 = brw_vec8_grf(2, 0);
+
+ brw_push_insn_state(p);
+ brw_set_default_predicate_control(p, true);
+ brw_MOV(p, g0, g2);
+ brw_pop_insn_state(p);
+}
+
+/* The handling of f0.1 vs f0.0 changes between gen6 and gen7. Explicitly test
+ * it, so that we run the fuzzing can run over all the other bits that might
+ * interact with it.
+ */
+static void
+gen_f0_1_MOV_GRF_GRF(struct brw_codegen *p)
+{
+ struct brw_reg g0 = brw_vec8_grf(0, 0);
+ struct brw_reg g2 = brw_vec8_grf(2, 0);
+
+ brw_push_insn_state(p);
+ brw_set_default_predicate_control(p, true);
+ brw_inst *mov = brw_MOV(p, g0, g2);
+ brw_inst_set_flag_subreg_nr(p->devinfo, mov, 1);
+ brw_pop_insn_state(p);
+}
+
+struct {
+ void (*func)(struct brw_codegen *p);
+} tests[] = {
+ { gen_MOV_GRF_GRF },
+ { gen_ADD_GRF_GRF_GRF },
+ { gen_ADD_GRF_GRF_IMM },
+ { gen_ADD_GRF_GRF_IMM_d },
+ { gen_ADD_MRF_GRF_GRF },
+ { gen_ADD_vec1_GRF_GRF_GRF },
+ { gen_PLN_MRF_GRF_GRF },
+ { gen_f0_0_MOV_GRF_GRF },
+ { gen_f0_1_MOV_GRF_GRF },
+};
+
+static bool
+run_tests(const struct gen_device_info *devinfo)
+{
+ brw_init_compaction_tables(devinfo);
+ bool fail = false;
+
+ for (int i = 0; i < ARRAY_SIZE(tests); i++) {
+ for (int align_16 = 0; align_16 <= 1; align_16++) {
+ struct brw_codegen *p = rzalloc(NULL, struct brw_codegen);
+ brw_init_codegen(devinfo, p, p);
+
+ brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
+ if (align_16)
+ brw_set_default_access_mode(p, BRW_ALIGN_16);
+ else
+ brw_set_default_access_mode(p, BRW_ALIGN_1);
+
+ tests[i].func(p);
+ assert(p->nr_insn == 1);
+
+ if (!test_compact_instruction(p, p->store[0])) {
+ fail = true;
+ continue;
+ }
+
+ if (!test_fuzz_compact_instruction(p, p->store[0])) {
+ fail = true;
+ continue;
+ }
+
+ ralloc_free(p);
+ }
+ }
+
+ return fail;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct gen_device_info *devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
+ devinfo->gen = 6;
+ bool fail = false;
+
+ for (devinfo->gen = 6; devinfo->gen <= 7; devinfo->gen++) {
+ fail |= run_tests(devinfo);
+ }
+
+ return fail;
+}