101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2012 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include <stdlib.h> 2501e04c3fSmrg#include <stdio.h> 2601e04c3fSmrg#include <stdbool.h> 2701e04c3fSmrg#include "util/ralloc.h" 2801e04c3fSmrg#include "brw_eu.h" 2901e04c3fSmrg 307ec681f3Smrg#include <gtest/gtest.h> 317ec681f3Smrg 327ec681f3Smrgstruct CompactParams { 337ec681f3Smrg unsigned verx10; 347ec681f3Smrg unsigned align; 357ec681f3Smrg}; 367ec681f3Smrg 377ec681f3Smrgstd::string 387ec681f3Smrgget_compact_params_name(const testing::TestParamInfo<CompactParams> p) 397ec681f3Smrg{ 407ec681f3Smrg CompactParams params = p.param; 417ec681f3Smrg std::stringstream ss; 427ec681f3Smrg ss << params.verx10 << "_"; 437ec681f3Smrg switch (params.align) { 447ec681f3Smrg case BRW_ALIGN_1: 457ec681f3Smrg ss << "Align_1"; 467ec681f3Smrg break; 477ec681f3Smrg case BRW_ALIGN_16: 487ec681f3Smrg ss << "Align_16"; 497ec681f3Smrg break; 507ec681f3Smrg default: 517ec681f3Smrg unreachable("invalid align"); 527ec681f3Smrg } 537ec681f3Smrg return ss.str(); 547ec681f3Smrg} 557ec681f3Smrg 5601e04c3fSmrgstatic bool 5701e04c3fSmrgtest_compact_instruction(struct brw_codegen *p, brw_inst src) 5801e04c3fSmrg{ 5901e04c3fSmrg brw_compact_inst dst; 6001e04c3fSmrg memset(&dst, 0xd0, sizeof(dst)); 6101e04c3fSmrg 6201e04c3fSmrg if (brw_try_compact_instruction(p->devinfo, &dst, &src)) { 6301e04c3fSmrg brw_inst uncompacted; 6401e04c3fSmrg 6501e04c3fSmrg brw_uncompact_instruction(p->devinfo, &uncompacted, &dst); 6601e04c3fSmrg if (memcmp(&uncompacted, &src, sizeof(src))) { 6701e04c3fSmrg brw_debug_compact_uncompact(p->devinfo, &src, &uncompacted); 6801e04c3fSmrg return false; 6901e04c3fSmrg } 7001e04c3fSmrg } else { 7101e04c3fSmrg brw_compact_inst unchanged; 7201e04c3fSmrg memset(&unchanged, 0xd0, sizeof(unchanged)); 7301e04c3fSmrg /* It's not supposed to change dst unless it compacted. */ 7401e04c3fSmrg if (memcmp(&unchanged, &dst, sizeof(dst))) { 7501e04c3fSmrg fprintf(stderr, "Failed to compact, but dst changed\n"); 7601e04c3fSmrg fprintf(stderr, " Instruction: "); 777ec681f3Smrg brw_disassemble_inst(stderr, p->devinfo, &src, false, 0, NULL); 7801e04c3fSmrg return false; 7901e04c3fSmrg } 8001e04c3fSmrg } 8101e04c3fSmrg 8201e04c3fSmrg return true; 8301e04c3fSmrg} 8401e04c3fSmrg 8501e04c3fSmrg/** 8601e04c3fSmrg * When doing fuzz testing, pad bits won't round-trip. 8701e04c3fSmrg * 8801e04c3fSmrg * This sort of a superset of skip_bit, which is testing for changing bits that 8901e04c3fSmrg * aren't worth testing for fuzzing. We also just want to clear bits that 9001e04c3fSmrg * become meaningless once fuzzing twiddles a related bit. 9101e04c3fSmrg */ 9201e04c3fSmrgstatic void 937ec681f3Smrgclear_pad_bits(const struct intel_device_info *devinfo, brw_inst *inst) 9401e04c3fSmrg{ 9501e04c3fSmrg if (brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SEND && 9601e04c3fSmrg brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SENDC && 9701e04c3fSmrg brw_inst_src0_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE && 9801e04c3fSmrg brw_inst_src1_reg_file(devinfo, inst) != BRW_IMMEDIATE_VALUE) { 9901e04c3fSmrg brw_inst_set_bits(inst, 127, 111, 0); 10001e04c3fSmrg } 10101e04c3fSmrg 1027ec681f3Smrg if (devinfo->ver == 8 && !devinfo->is_cherryview && 1037ec681f3Smrg is_3src(devinfo, brw_inst_opcode(devinfo, inst))) { 10401e04c3fSmrg brw_inst_set_bits(inst, 105, 105, 0); 10501e04c3fSmrg brw_inst_set_bits(inst, 84, 84, 0); 10601e04c3fSmrg brw_inst_set_bits(inst, 36, 35, 0); 10701e04c3fSmrg } 10801e04c3fSmrg} 10901e04c3fSmrg 11001e04c3fSmrgstatic bool 1117ec681f3Smrgskip_bit(const struct intel_device_info *devinfo, brw_inst *src, int bit) 11201e04c3fSmrg{ 11301e04c3fSmrg /* pad bit */ 11401e04c3fSmrg if (bit == 7) 11501e04c3fSmrg return true; 11601e04c3fSmrg 11701e04c3fSmrg /* The compact bit -- uncompacted can't have it set. */ 11801e04c3fSmrg if (bit == 29) 11901e04c3fSmrg return true; 12001e04c3fSmrg 1217ec681f3Smrg if (is_3src(devinfo, brw_inst_opcode(devinfo, src))) { 1227ec681f3Smrg if (devinfo->ver >= 9 || devinfo->is_cherryview) { 12301e04c3fSmrg if (bit == 127) 12401e04c3fSmrg return true; 12501e04c3fSmrg } else { 12601e04c3fSmrg if (bit >= 126 && bit <= 127) 12701e04c3fSmrg return true; 12801e04c3fSmrg 12901e04c3fSmrg if (bit == 105) 13001e04c3fSmrg return true; 13101e04c3fSmrg 13201e04c3fSmrg if (bit == 84) 13301e04c3fSmrg return true; 13401e04c3fSmrg 13501e04c3fSmrg if (bit >= 35 && bit <= 36) 13601e04c3fSmrg return true; 13701e04c3fSmrg } 13801e04c3fSmrg } else { 13901e04c3fSmrg if (bit == 47) 14001e04c3fSmrg return true; 14101e04c3fSmrg 1427ec681f3Smrg if (devinfo->ver >= 8) { 14301e04c3fSmrg if (bit == 11) 14401e04c3fSmrg return true; 14501e04c3fSmrg 14601e04c3fSmrg if (bit == 95) 14701e04c3fSmrg return true; 14801e04c3fSmrg } else { 1497ec681f3Smrg if (devinfo->ver < 7 && bit == 90) 15001e04c3fSmrg return true; 15101e04c3fSmrg 15201e04c3fSmrg if (bit >= 91 && bit <= 95) 15301e04c3fSmrg return true; 15401e04c3fSmrg } 15501e04c3fSmrg } 15601e04c3fSmrg 15701e04c3fSmrg /* sometimes these are pad bits. */ 15801e04c3fSmrg if (brw_inst_opcode(devinfo, src) != BRW_OPCODE_SEND && 15901e04c3fSmrg brw_inst_opcode(devinfo, src) != BRW_OPCODE_SENDC && 16001e04c3fSmrg brw_inst_src0_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE && 16101e04c3fSmrg brw_inst_src1_reg_file(devinfo, src) != BRW_IMMEDIATE_VALUE && 16201e04c3fSmrg bit >= 121) { 16301e04c3fSmrg return true; 16401e04c3fSmrg } 16501e04c3fSmrg 16601e04c3fSmrg return false; 16701e04c3fSmrg} 16801e04c3fSmrg 16901e04c3fSmrgstatic bool 17001e04c3fSmrgtest_fuzz_compact_instruction(struct brw_codegen *p, brw_inst src) 17101e04c3fSmrg{ 17201e04c3fSmrg for (int bit0 = 0; bit0 < 128; bit0++) { 17301e04c3fSmrg if (skip_bit(p->devinfo, &src, bit0)) 17401e04c3fSmrg continue; 17501e04c3fSmrg 17601e04c3fSmrg for (int bit1 = 0; bit1 < 128; bit1++) { 17701e04c3fSmrg brw_inst instr = src; 17801e04c3fSmrg uint64_t *bits = instr.data; 17901e04c3fSmrg 18001e04c3fSmrg if (skip_bit(p->devinfo, &src, bit1)) 18101e04c3fSmrg continue; 18201e04c3fSmrg 18301e04c3fSmrg bits[bit0 / 64] ^= (1ull << (bit0 & 63)); 18401e04c3fSmrg bits[bit1 / 64] ^= (1ull << (bit1 & 63)); 18501e04c3fSmrg 18601e04c3fSmrg clear_pad_bits(p->devinfo, &instr); 18701e04c3fSmrg 1887ec681f3Smrg if (!brw_validate_instruction(p->devinfo, &instr, 0, NULL)) 1897ec681f3Smrg continue; 1907ec681f3Smrg 19101e04c3fSmrg if (!test_compact_instruction(p, instr)) { 19201e04c3fSmrg printf(" twiddled bits for fuzzing %d, %d\n", bit0, bit1); 19301e04c3fSmrg return false; 19401e04c3fSmrg } 19501e04c3fSmrg } 19601e04c3fSmrg } 19701e04c3fSmrg 19801e04c3fSmrg return true; 19901e04c3fSmrg} 20001e04c3fSmrg 2017ec681f3Smrgclass CompactTestFixture : public testing::TestWithParam<CompactParams> { 2027ec681f3Smrgprotected: 2037ec681f3Smrg virtual void SetUp() { 2047ec681f3Smrg CompactParams params = GetParam(); 2057ec681f3Smrg mem_ctx = ralloc_context(NULL); 2067ec681f3Smrg devinfo = rzalloc(mem_ctx, intel_device_info); 2077ec681f3Smrg p = rzalloc(mem_ctx, brw_codegen); 2087ec681f3Smrg 2097ec681f3Smrg devinfo->verx10 = params.verx10; 2107ec681f3Smrg devinfo->ver = devinfo->verx10 / 10; 2117ec681f3Smrg 2127ec681f3Smrg brw_init_codegen(devinfo, p, p); 2137ec681f3Smrg brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 2147ec681f3Smrg brw_set_default_access_mode(p, params.align); 2157ec681f3Smrg }; 2167ec681f3Smrg 2177ec681f3Smrg virtual void TearDown() { 2187ec681f3Smrg EXPECT_EQ(p->nr_insn, 1); 2197ec681f3Smrg EXPECT_TRUE(test_compact_instruction(p, p->store[0])); 2207ec681f3Smrg EXPECT_TRUE(test_fuzz_compact_instruction(p, p->store[0])); 2217ec681f3Smrg 2227ec681f3Smrg ralloc_free(mem_ctx); 2237ec681f3Smrg }; 2247ec681f3Smrg 2257ec681f3Smrg void *mem_ctx; 2267ec681f3Smrg intel_device_info *devinfo; 2277ec681f3Smrg brw_codegen *p; 2287ec681f3Smrg}; 2297ec681f3Smrg 2307ec681f3Smrgclass Instructions : public CompactTestFixture {}; 2317ec681f3Smrg 2327ec681f3SmrgINSTANTIATE_TEST_CASE_P( 2337ec681f3Smrg CompactTest, 2347ec681f3Smrg Instructions, 2357ec681f3Smrg testing::Values( 2367ec681f3Smrg CompactParams{ 50, BRW_ALIGN_1 }, CompactParams{ 50, BRW_ALIGN_16 }, 2377ec681f3Smrg CompactParams{ 60, BRW_ALIGN_1 }, CompactParams{ 60, BRW_ALIGN_16 }, 2387ec681f3Smrg CompactParams{ 70, BRW_ALIGN_1 }, CompactParams{ 70, BRW_ALIGN_16 }, 2397ec681f3Smrg CompactParams{ 75, BRW_ALIGN_1 }, CompactParams{ 75, BRW_ALIGN_16 }, 2407ec681f3Smrg CompactParams{ 80, BRW_ALIGN_1 }, CompactParams{ 80, BRW_ALIGN_16 }, 2417ec681f3Smrg CompactParams{ 90, BRW_ALIGN_1 }, CompactParams{ 90, BRW_ALIGN_16 }, 2427ec681f3Smrg CompactParams{ 110, BRW_ALIGN_1 }, 2437ec681f3Smrg CompactParams{ 120, BRW_ALIGN_1 }, 2447ec681f3Smrg CompactParams{ 125, BRW_ALIGN_1 } 2457ec681f3Smrg ), 2467ec681f3Smrg get_compact_params_name); 2477ec681f3Smrg 2487ec681f3Smrgclass InstructionsBeforeIvyBridge : public CompactTestFixture {}; 2497ec681f3Smrg 2507ec681f3SmrgINSTANTIATE_TEST_CASE_P( 2517ec681f3Smrg CompactTest, 2527ec681f3Smrg InstructionsBeforeIvyBridge, 2537ec681f3Smrg testing::Values( 2547ec681f3Smrg CompactParams{ 50, BRW_ALIGN_1 }, CompactParams{ 50, BRW_ALIGN_16 }, 2557ec681f3Smrg CompactParams{ 60, BRW_ALIGN_1 }, CompactParams{ 60, BRW_ALIGN_16 } 2567ec681f3Smrg ), 2577ec681f3Smrg get_compact_params_name); 2587ec681f3Smrg 2597ec681f3Smrg 2607ec681f3SmrgTEST_P(Instructions, ADD_GRF_GRF_GRF) 26101e04c3fSmrg{ 26201e04c3fSmrg struct brw_reg g0 = brw_vec8_grf(0, 0); 26301e04c3fSmrg struct brw_reg g2 = brw_vec8_grf(2, 0); 26401e04c3fSmrg struct brw_reg g4 = brw_vec8_grf(4, 0); 26501e04c3fSmrg 26601e04c3fSmrg brw_ADD(p, g0, g2, g4); 26701e04c3fSmrg} 26801e04c3fSmrg 2697ec681f3SmrgTEST_P(Instructions, ADD_GRF_GRF_IMM) 27001e04c3fSmrg{ 27101e04c3fSmrg struct brw_reg g0 = brw_vec8_grf(0, 0); 27201e04c3fSmrg struct brw_reg g2 = brw_vec8_grf(2, 0); 27301e04c3fSmrg 27401e04c3fSmrg brw_ADD(p, g0, g2, brw_imm_f(1.0)); 27501e04c3fSmrg} 27601e04c3fSmrg 2777ec681f3SmrgTEST_P(Instructions, ADD_GRF_GRF_IMM_d) 27801e04c3fSmrg{ 27901e04c3fSmrg struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D); 28001e04c3fSmrg struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D); 28101e04c3fSmrg 28201e04c3fSmrg brw_ADD(p, g0, g2, brw_imm_d(1)); 28301e04c3fSmrg} 28401e04c3fSmrg 2857ec681f3SmrgTEST_P(Instructions, MOV_GRF_GRF) 28601e04c3fSmrg{ 28701e04c3fSmrg struct brw_reg g0 = brw_vec8_grf(0, 0); 28801e04c3fSmrg struct brw_reg g2 = brw_vec8_grf(2, 0); 28901e04c3fSmrg 29001e04c3fSmrg brw_MOV(p, g0, g2); 29101e04c3fSmrg} 29201e04c3fSmrg 2937ec681f3SmrgTEST_P(InstructionsBeforeIvyBridge, ADD_MRF_GRF_GRF) 29401e04c3fSmrg{ 29501e04c3fSmrg struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0); 29601e04c3fSmrg struct brw_reg g2 = brw_vec8_grf(2, 0); 29701e04c3fSmrg struct brw_reg g4 = brw_vec8_grf(4, 0); 29801e04c3fSmrg 29901e04c3fSmrg brw_ADD(p, m6, g2, g4); 30001e04c3fSmrg} 30101e04c3fSmrg 3027ec681f3SmrgTEST_P(Instructions, ADD_vec1_GRF_GRF_GRF) 30301e04c3fSmrg{ 30401e04c3fSmrg struct brw_reg g0 = brw_vec1_grf(0, 0); 30501e04c3fSmrg struct brw_reg g2 = brw_vec1_grf(2, 0); 30601e04c3fSmrg struct brw_reg g4 = brw_vec1_grf(4, 0); 30701e04c3fSmrg 30801e04c3fSmrg brw_ADD(p, g0, g2, g4); 30901e04c3fSmrg} 31001e04c3fSmrg 3117ec681f3SmrgTEST_P(InstructionsBeforeIvyBridge, PLN_MRF_GRF_GRF) 31201e04c3fSmrg{ 31301e04c3fSmrg struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0); 31401e04c3fSmrg struct brw_reg interp = brw_vec1_grf(2, 0); 31501e04c3fSmrg struct brw_reg g4 = brw_vec8_grf(4, 0); 31601e04c3fSmrg 31701e04c3fSmrg brw_PLN(p, m6, interp, g4); 31801e04c3fSmrg} 31901e04c3fSmrg 3207ec681f3SmrgTEST_P(Instructions, f0_0_MOV_GRF_GRF) 32101e04c3fSmrg{ 32201e04c3fSmrg struct brw_reg g0 = brw_vec8_grf(0, 0); 32301e04c3fSmrg struct brw_reg g2 = brw_vec8_grf(2, 0); 32401e04c3fSmrg 32501e04c3fSmrg brw_push_insn_state(p); 3267ec681f3Smrg brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL); 32701e04c3fSmrg brw_MOV(p, g0, g2); 32801e04c3fSmrg brw_pop_insn_state(p); 32901e04c3fSmrg} 33001e04c3fSmrg 3317ec681f3Smrg/* The handling of f0.1 vs f0.0 changes between gfx6 and gfx7. Explicitly test 33201e04c3fSmrg * it, so that we run the fuzzing can run over all the other bits that might 33301e04c3fSmrg * interact with it. 33401e04c3fSmrg */ 3357ec681f3SmrgTEST_P(Instructions, f0_1_MOV_GRF_GRF) 33601e04c3fSmrg{ 33701e04c3fSmrg struct brw_reg g0 = brw_vec8_grf(0, 0); 33801e04c3fSmrg struct brw_reg g2 = brw_vec8_grf(2, 0); 33901e04c3fSmrg 34001e04c3fSmrg brw_push_insn_state(p); 3417ec681f3Smrg brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL); 34201e04c3fSmrg brw_inst *mov = brw_MOV(p, g0, g2); 34301e04c3fSmrg brw_inst_set_flag_subreg_nr(p->devinfo, mov, 1); 34401e04c3fSmrg brw_pop_insn_state(p); 34501e04c3fSmrg} 346