From 31eed95b2251ba69f04544b2baed395ac789a445 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Sun, 15 Jun 2014 11:29:22 -0700 Subject: [PATCH] i965: Add support for compacting 3-src instructions on Gen8. Reviewed-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/brw_eu_compact.c | 185 +++++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_eu_compact.c b/src/mesa/drivers/dri/i965/brw_eu_compact.c index 2acf5d3d22a..6b1cf122c8e 100644 --- a/src/mesa/drivers/dri/i965/brw_eu_compact.c +++ b/src/mesa/drivers/dri/i965/brw_eu_compact.c @@ -611,6 +611,97 @@ set_src1_index(struct brw_context *brw, brw_compact_inst *dst, brw_inst *src, return true; } +static bool +set_3src_control_index(struct brw_context *brw, brw_compact_inst *dst, brw_inst *src) +{ + assert(brw->gen >= 8); + + uint32_t uncompacted = /* 24b/BDW; 26b/CHV */ + (brw_inst_bits(src, 34, 32) << 21) | /* 3b */ + (brw_inst_bits(src, 28, 8)); /* 21b */ + + if (brw->is_cherryview) + uncompacted |= brw_inst_bits(src, 36, 35) << 24; /* 2b */ + + for (int i = 0; i < ARRAY_SIZE(gen8_3src_control_index_table); i++) { + if (gen8_3src_control_index_table[i] == uncompacted) { + brw_compact_inst_set_3src_control_index(dst, i); + return true; + } + } + + return false; +} + +static bool +set_3src_source_index(struct brw_context *brw, brw_compact_inst *dst, brw_inst *src) +{ + assert(brw->gen >= 8); + + uint64_t uncompacted = /* 46b/BDW; 49b/CHV */ + (brw_inst_bits(src, 83, 83) << 43) | /* 1b */ + (brw_inst_bits(src, 114, 107) << 35) | /* 8b */ + (brw_inst_bits(src, 93, 86) << 27) | /* 8b */ + (brw_inst_bits(src, 72, 65) << 19) | /* 8b */ + (brw_inst_bits(src, 55, 37)); /* 19b */ + + if (brw->is_cherryview) { + uncompacted |= + (brw_inst_bits(src, 126, 125) << 47) | /* 2b */ + (brw_inst_bits(src, 105, 104) << 45) | /* 2b */ + (brw_inst_bits(src, 84, 84) << 44); /* 1b */ + } else { + uncompacted |= + (brw_inst_bits(src, 125, 125) << 45) | /* 1b */ + (brw_inst_bits(src, 104, 104) << 44); /* 1b */ + } + + for (int i = 0; i < ARRAY_SIZE(gen8_3src_source_index_table); i++) { + if (gen8_3src_source_index_table[i] == uncompacted) { + brw_compact_inst_set_3src_source_index(dst, i); + return true; + } + } + + return false; +} + +static bool +brw_try_compact_3src_instruction(struct brw_context *brw, brw_compact_inst *dst, + brw_inst *src) +{ + assert(brw->gen >= 8); + +#define compact(field) \ + brw_compact_inst_set_3src_##field(dst, brw_inst_3src_##field(brw, src)) + + compact(opcode); + + if (!set_3src_control_index(brw, dst, src)) + return false; + + if (!set_3src_source_index(brw, dst, src)) + return false; + + compact(dst_reg_nr); + compact(src0_rep_ctrl); + brw_compact_inst_set_3src_cmpt_control(dst, true); + compact(debug_control); + compact(saturate); + compact(src1_rep_ctrl); + compact(src2_rep_ctrl); + compact(src0_reg_nr); + compact(src1_reg_nr); + compact(src2_reg_nr); + compact(src0_subreg_nr); + compact(src1_subreg_nr); + compact(src2_subreg_nr); + +#undef compact + + return true; +} + /* Compacted instructions have 12-bits for immediate sources, and a 13th bit * that's replicated through the high 20 bits. * @@ -627,6 +718,13 @@ is_compactable_immediate(unsigned imm) return imm == 0 || imm == 0xfffff000; } +/* Returns whether an opcode takes three sources. */ +static bool +is_3src(uint32_t op) +{ + return opcode_descs[op].nsrc == 3; +} + /** * Tries to compact instruction src into dst. * @@ -651,6 +749,16 @@ brw_try_compact_instruction(struct brw_context *brw, brw_compact_inst *dst, return false; } + if (brw->gen >= 8 && is_3src(brw_inst_opcode(brw, src))) { + memset(&temp, 0, sizeof(temp)); + if (brw_try_compact_3src_instruction(brw, &temp, src)) { + *dst = temp; + return true; + } else { + return false; + } + } + bool is_immediate = brw_inst_src0_reg_file(brw, src) == BRW_IMMEDIATE_VALUE || brw_inst_src1_reg_file(brw, src) == BRW_IMMEDIATE_VALUE; @@ -767,12 +875,89 @@ set_uncompacted_src1(struct brw_context *brw, brw_inst *dst, } } +static void +set_uncompacted_3src_control_index(struct brw_context *brw, brw_inst *dst, + brw_compact_inst *src) +{ + assert(brw->gen >= 8); + + uint32_t compacted = brw_compact_inst_3src_control_index(src); + uint32_t uncompacted = gen8_3src_control_index_table[compacted]; + + brw_inst_set_bits(dst, 34, 32, (uncompacted >> 21) & 0x7); + brw_inst_set_bits(dst, 28, 8, (uncompacted >> 0) & 0x1fffff); + + if (brw->is_cherryview) + brw_inst_set_bits(dst, 36, 35, (uncompacted >> 24) & 0x3); +} + +static void +set_uncompacted_3src_source_index(struct brw_context *brw, brw_inst *dst, + brw_compact_inst *src) +{ + assert(brw->gen >= 8); + + uint32_t compacted = brw_compact_inst_3src_source_index(src); + uint64_t uncompacted = gen8_3src_source_index_table[compacted]; + + brw_inst_set_bits(dst, 83, 83, (uncompacted >> 43) & 0x1); + brw_inst_set_bits(dst, 114, 107, (uncompacted >> 35) & 0xff); + brw_inst_set_bits(dst, 93, 86, (uncompacted >> 27) & 0xff); + brw_inst_set_bits(dst, 72, 65, (uncompacted >> 19) & 0xff); + brw_inst_set_bits(dst, 55, 37, (uncompacted >> 0) & 0x7ffff); + + if (brw->is_cherryview) { + brw_inst_set_bits(dst, 126, 125, (uncompacted >> 47) & 0x3); + brw_inst_set_bits(dst, 105, 104, (uncompacted >> 45) & 0x3); + brw_inst_set_bits(dst, 84, 84, (uncompacted >> 44) & 0x1); + } else { + brw_inst_set_bits(dst, 125, 125, (uncompacted >> 45) & 0x1); + brw_inst_set_bits(dst, 104, 104, (uncompacted >> 44) & 0x1); + } +} + +static void +brw_uncompact_3src_instruction(struct brw_context *brw, brw_inst *dst, + brw_compact_inst *src) +{ + assert(brw->gen >= 8); + +#define uncompact(field) \ + brw_inst_set_3src_##field(brw, dst, brw_compact_inst_3src_##field(src)) + + uncompact(opcode); + + set_uncompacted_3src_control_index(brw, dst, src); + set_uncompacted_3src_source_index(brw, dst, src); + + uncompact(dst_reg_nr); + uncompact(src0_rep_ctrl); + brw_inst_set_3src_cmpt_control(brw, dst, false); + uncompact(debug_control); + uncompact(saturate); + uncompact(src1_rep_ctrl); + uncompact(src2_rep_ctrl); + uncompact(src0_reg_nr); + uncompact(src1_reg_nr); + uncompact(src2_reg_nr); + uncompact(src0_subreg_nr); + uncompact(src1_subreg_nr); + uncompact(src2_subreg_nr); + +#undef uncompact +} + void brw_uncompact_instruction(struct brw_context *brw, brw_inst *dst, brw_compact_inst *src) { memset(dst, 0, sizeof(*dst)); + if (brw->gen >= 8 && is_3src(brw_compact_inst_3src_opcode(src))) { + brw_uncompact_3src_instruction(brw, dst, src); + return; + } + brw_inst_set_opcode(brw, dst, brw_compact_inst_opcode(src)); brw_inst_set_debug_control(brw, dst, brw_compact_inst_debug_control(src)); -- 2.30.2