From 24360966ab31a9bedfe07356413769218fd2e0b6 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 20 Jan 2020 18:40:43 +0100 Subject: [PATCH] panfrost/midgard: Prettify embedded constant prints Until now, embedded constants were printed as all 32 bits integer or floats, but the compiler can pack constant from different types if severa instructions with different reg_mode and native type refer to the constant register. Let's implement something smarter so users don't have to do a manual conversion when looking at a trace. Note that 8-bit constants are not decoded yet, as we're not sure how the writemask is encoded in that case. Signed-off-by: Boris Brezillon Reviewed-by: Alyssa Rosenzweig Tested-by: Marge Bot Part-of: --- src/panfrost/midgard/disassemble.c | 172 ++++++++++++++++--------- src/panfrost/midgard/helpers.h | 6 + src/panfrost/midgard/midgard_print.c | 182 +++++++++++++++++++++++++-- 3 files changed, 292 insertions(+), 68 deletions(-) diff --git a/src/panfrost/midgard/disassemble.c b/src/panfrost/midgard/disassemble.c index f99a13f2908..2e4ab489177 100644 --- a/src/panfrost/midgard/disassemble.c +++ b/src/panfrost/midgard/disassemble.c @@ -36,6 +36,7 @@ #include "midgard_quirks.h" #include "disassemble.h" #include "helpers.h" +#include "util/bitscan.h" #include "util/half_float.h" #include "util/u_math.h" @@ -328,6 +329,69 @@ bits_for_mode_halved(midgard_reg_mode mode, bool half) return bits; } +static void +print_scalar_constant(FILE *fp, unsigned src_binary, + const midgard_constants *consts, + midgard_scalar_alu *alu) +{ + midgard_scalar_alu_src *src = (midgard_scalar_alu_src *)&src_binary; + unsigned mod = 0; + + if (!midgard_is_integer_op(alu->op)) { + if (src->abs) + mod |= MIDGARD_FLOAT_MOD_ABS; + if (src->negate) + mod |= MIDGARD_FLOAT_MOD_NEG; + } else { + mod = midgard_int_normal; + } + + fprintf(fp, "#"); + mir_print_constant_component(fp, consts, src->component, + src->full ? + midgard_reg_mode_32 : midgard_reg_mode_16, + false, mod, alu->op); +} + +static void +print_vector_constants(FILE *fp, unsigned src_binary, + const midgard_constants *consts, + midgard_vector_alu *alu) +{ + midgard_vector_alu_src *src = (midgard_vector_alu_src *)&src_binary; + unsigned bits = bits_for_mode_halved(alu->reg_mode, src->half); + unsigned max_comp = MIN2((sizeof(*consts) * 8) / bits, 8); + unsigned comp_mask, num_comp = 0; + + assert(consts); + + comp_mask = effective_writemask(alu, condense_writemask(alu->mask, bits)); + num_comp = util_bitcount(comp_mask); + + fprintf(fp, "#"); + if (num_comp > 1) + fprintf(fp, "vec%d(", num_comp); + + bool first = true; + + for (unsigned i = 0; i < max_comp; ++i) { + if (!(comp_mask & (1 << i))) continue; + + unsigned c = (src->swizzle >> (i * 2)) & 3; + + if (first) + first = false; + else + fprintf(fp, ", "); + + mir_print_constant_component(fp, consts, c, alu->reg_mode, + src->half, src->mod, alu->op); + } + + if (num_comp > 1) + fprintf(fp, ")"); +} + static void print_vector_src(FILE *fp, unsigned src_binary, midgard_reg_mode mode, unsigned reg, @@ -536,7 +600,7 @@ print_mask_4(FILE *fp, unsigned mask, bool upper) static void print_vector_field(FILE *fp, const char *name, uint16_t *words, uint16_t reg_word, - unsigned tabs) + const midgard_constants *consts, unsigned tabs) { midgard_reg_info *reg_info = (midgard_reg_info *)®_word; midgard_vector_alu *alu_field = (midgard_vector_alu *) words; @@ -581,13 +645,19 @@ print_vector_field(FILE *fp, const char *name, uint16_t *words, uint16_t reg_wor fprintf(fp, ", "); bool is_int = midgard_is_integer_op(alu_field->op); - print_vector_src(fp, alu_field->src1, mode, reg_info->src1_reg, override, is_int); + + if (reg_info->src1_reg == 26) + print_vector_constants(fp, alu_field->src1, consts, alu_field); + else + print_vector_src(fp, alu_field->src1, mode, reg_info->src1_reg, override, is_int); fprintf(fp, ", "); if (reg_info->src2_imm) { uint16_t imm = decode_vector_imm(reg_info->src2_reg, alu_field->src2 >> 2); print_immediate(fp, imm); + } else if (reg_info->src2_reg == 26) { + print_vector_constants(fp, alu_field->src2, consts, alu_field); } else { print_vector_src(fp, alu_field->src2, mode, reg_info->src2_reg, override, is_int); @@ -638,7 +708,7 @@ decode_scalar_imm(unsigned src2_reg, unsigned imm) static void print_scalar_field(FILE *fp, const char *name, uint16_t *words, uint16_t reg_word, - unsigned tabs) + const midgard_constants *consts, unsigned tabs) { midgard_reg_info *reg_info = (midgard_reg_info *)®_word; midgard_scalar_alu *alu_field = (midgard_scalar_alu *) words; @@ -664,7 +734,10 @@ print_scalar_field(FILE *fp, const char *name, uint16_t *words, uint16_t reg_wor fprintf(fp, ".%c, ", components[c]); - print_scalar_src(fp, alu_field->src1, reg_info->src1_reg); + if (reg_info->src1_reg == 26) + print_scalar_constant(fp, alu_field->src1, consts, alu_field); + else + print_scalar_src(fp, alu_field->src1, reg_info->src1_reg); fprintf(fp, ", "); @@ -672,6 +745,8 @@ print_scalar_field(FILE *fp, const char *name, uint16_t *words, uint16_t reg_wor uint16_t imm = decode_scalar_imm(reg_info->src2_reg, alu_field->src2); print_immediate(fp, imm); + } else if (reg_info->src2_reg == 26) { + print_scalar_constant(fp, alu_field->src2, consts, alu_field); } else print_scalar_src(fp, alu_field->src2, reg_info->src2_reg); @@ -883,109 +958,94 @@ print_alu_word(FILE *fp, uint32_t *words, unsigned num_quad_words, unsigned num_fields = num_alu_fields_enabled(control_word); uint16_t *word_ptr = beginning_ptr + num_fields; unsigned num_words = 2 + num_fields; + const midgard_constants *consts = NULL; bool branch_forward = false; + if ((control_word >> 17) & 1) + num_words += 3; + + if ((control_word >> 19) & 1) + num_words += 2; + + if ((control_word >> 21) & 1) + num_words += 3; + + if ((control_word >> 23) & 1) + num_words += 2; + + if ((control_word >> 25) & 1) + num_words += 3; + + if ((control_word >> 26) & 1) + num_words += 1; + + if ((control_word >> 27) & 1) + num_words += 3; + + if (num_quad_words > (num_words + 7) / 8) { + assert(num_quad_words == (num_words + 15) / 8); + //Assume that the extra quadword is constants + consts = (midgard_constants *)(words + (4 * num_quad_words - 4)); + } + if ((control_word >> 16) & 1) fprintf(fp, "unknown bit 16 enabled\n"); if ((control_word >> 17) & 1) { - print_vector_field(fp, "vmul", word_ptr, *beginning_ptr, tabs); + print_vector_field(fp, "vmul", word_ptr, *beginning_ptr, consts, tabs); beginning_ptr += 1; word_ptr += 3; - num_words += 3; } if ((control_word >> 18) & 1) fprintf(fp, "unknown bit 18 enabled\n"); if ((control_word >> 19) & 1) { - print_scalar_field(fp, "sadd", word_ptr, *beginning_ptr, tabs); + print_scalar_field(fp, "sadd", word_ptr, *beginning_ptr, consts, tabs); beginning_ptr += 1; word_ptr += 2; - num_words += 2; } if ((control_word >> 20) & 1) fprintf(fp, "unknown bit 20 enabled\n"); if ((control_word >> 21) & 1) { - print_vector_field(fp, "vadd", word_ptr, *beginning_ptr, tabs); + print_vector_field(fp, "vadd", word_ptr, *beginning_ptr, consts, tabs); beginning_ptr += 1; word_ptr += 3; - num_words += 3; } if ((control_word >> 22) & 1) fprintf(fp, "unknown bit 22 enabled\n"); if ((control_word >> 23) & 1) { - print_scalar_field(fp, "smul", word_ptr, *beginning_ptr, tabs); + print_scalar_field(fp, "smul", word_ptr, *beginning_ptr, consts, tabs); beginning_ptr += 1; word_ptr += 2; - num_words += 2; } if ((control_word >> 24) & 1) fprintf(fp, "unknown bit 24 enabled\n"); if ((control_word >> 25) & 1) { - print_vector_field(fp, "lut", word_ptr, *beginning_ptr, tabs); + print_vector_field(fp, "lut", word_ptr, *beginning_ptr, consts, tabs); word_ptr += 3; - num_words += 3; } if ((control_word >> 26) & 1) { branch_forward |= print_compact_branch_writeout_field(fp, *word_ptr); word_ptr += 1; - num_words += 1; } if ((control_word >> 27) & 1) { branch_forward |= print_extended_branch_writeout_field(fp, (uint8_t *) word_ptr, next); word_ptr += 3; - num_words += 3; } - if (num_quad_words > (num_words + 7) / 8) { - assert(num_quad_words == (num_words + 15) / 8); - //Assume that the extra quadword is constants - void *consts = words + (4 * num_quad_words - 4); - - if (is_embedded_constant_int) { - if (is_embedded_constant_half) { - int16_t *sconsts = (int16_t *) consts; - fprintf(fp, "sconstants %d, %d, %d, %d\n", - sconsts[0], - sconsts[1], - sconsts[2], - sconsts[3]); - } else { - uint32_t *iconsts = (uint32_t *) consts; - fprintf(fp, "iconstants 0x%X, 0x%X, 0x%X, 0x%X\n", - iconsts[0], - iconsts[1], - iconsts[2], - iconsts[3]); - } - } else { - if (is_embedded_constant_half) { - uint16_t *hconsts = (uint16_t *) consts; - fprintf(fp, "hconstants %g, %g, %g, %g\n", - _mesa_half_to_float(hconsts[0]), - _mesa_half_to_float(hconsts[1]), - _mesa_half_to_float(hconsts[2]), - _mesa_half_to_float(hconsts[3])); - } else { - uint32_t *fconsts = (uint32_t *) consts; - fprintf(fp, "fconstants %g, %g, %g, %g\n", - float_bitcast(fconsts[0]), - float_bitcast(fconsts[1]), - float_bitcast(fconsts[2]), - float_bitcast(fconsts[3])); - } - - } - } + if (consts) + fprintf(fp, "uconstants 0x%X, 0x%X, 0x%X, 0x%X\n", + consts->u32[0], consts->u32[1], + consts->u32[2], consts->u32[3]); return branch_forward; } diff --git a/src/panfrost/midgard/helpers.h b/src/panfrost/midgard/helpers.h index 66223f3fd78..6d1031841a5 100644 --- a/src/panfrost/midgard/helpers.h +++ b/src/panfrost/midgard/helpers.h @@ -23,6 +23,7 @@ #define __MDG_HELPERS_H #include "util/macros.h" +#include #include #define OP_IS_LOAD_VARY_F(op) (\ @@ -344,4 +345,9 @@ midgard_is_branch_unit(unsigned unit) return (unit == ALU_ENAB_BRANCH) || (unit == ALU_ENAB_BR_COMPACT); } +void +mir_print_constant_component(FILE *fp, const midgard_constants *consts, + unsigned c, midgard_reg_mode reg_mode, bool half, + unsigned mod, midgard_alu_op op); + #endif diff --git a/src/panfrost/midgard/midgard_print.c b/src/panfrost/midgard/midgard_print.c index 36a58259931..85a1d981722 100644 --- a/src/panfrost/midgard/midgard_print.c +++ b/src/panfrost/midgard/midgard_print.c @@ -21,6 +21,10 @@ * SOFTWARE. */ +#include + +#include "util/bitscan.h" +#include "util/half_float.h" #include "compiler.h" #include "helpers.h" #include "midgard_ops.h" @@ -98,6 +102,162 @@ mir_get_unit(unsigned unit) } } +void +mir_print_constant_component(FILE *fp, const midgard_constants *consts, unsigned c, + midgard_reg_mode reg_mode, bool half, + unsigned mod, midgard_alu_op op) +{ + bool is_sint = false, is_uint = false, is_hex = false; + const char *opname = alu_opcode_props[op].name; + + if (opname[0] == 'u') { + /* If the opcode starts with a 'u' we are sure we deal with an + * unsigned int operation + */ + is_uint = true; + } else if (opname[0] == 'i') { + /* Bit ops are easier to follow when the constant is printed in + * hexadecimal. Other operations starting with a 'i' are + * considered to operate on signed integers. That might not + * be true for all of them, but it's good enough for traces. + */ + if (op >= midgard_alu_op_iand && + op <= midgard_alu_op_ibitcount8) + is_hex = true; + else + is_sint = true; + } + + if (half) + reg_mode--; + + switch (reg_mode) { + case midgard_reg_mode_64: + if (is_sint) { + printf("%"PRIi64, consts->i64[c]); + } else if (is_uint) { + printf("%"PRIu64, consts->u64[c]); + } else if (is_hex) { + printf("0x%"PRIX64, consts->u64[c]); + } else { + double v = consts->f64[c]; + + if (mod & MIDGARD_FLOAT_MOD_ABS) v = fabs(v); + if (mod & MIDGARD_FLOAT_MOD_NEG) v = -v; + + printf("%g", v); + } + break; + + case midgard_reg_mode_32: + if (is_sint) { + int64_t v; + + if (half && mod == midgard_int_zero_extend) + v = consts->u32[c]; + else if (half && mod == midgard_int_shift) + v = (uint64_t)consts->u32[c] << 32; + else + v = consts->i32[c]; + + printf("%"PRIi64, v); + } else if (is_uint || is_hex) { + uint64_t v; + + if (half && mod == midgard_int_shift) + v = (uint64_t)consts->u32[c] << 32; + else + v = consts->u32[c]; + + printf(is_uint ? "%"PRIu64 : "0x%"PRIX64, v); + } else { + float v = consts->f32[c]; + + if (mod & MIDGARD_FLOAT_MOD_ABS) v = fabsf(v); + if (mod & MIDGARD_FLOAT_MOD_NEG) v = -v; + + printf("%g", v); + } + break; + + case midgard_reg_mode_16: + if (is_sint) { + int32_t v; + + if (half && mod == midgard_int_zero_extend) + v = consts->u16[c]; + else if (half && mod == midgard_int_shift) + v = (uint32_t)consts->u16[c] << 16; + else + v = consts->i16[c]; + + printf("%d", v); + } else if (is_uint || is_hex) { + uint32_t v; + + if (half && mod == midgard_int_shift) + v = (uint32_t)consts->u16[c] << 16; + else + v = consts->u16[c]; + + printf(is_uint ? "%u" : "0x%X", v); + } else { + float v = _mesa_half_to_float(consts->f16[c]); + + if (mod & MIDGARD_FLOAT_MOD_ABS) v = fabsf(v); + if (mod & MIDGARD_FLOAT_MOD_NEG) v = -v; + + printf("%g", v); + } + break; + + case midgard_reg_mode_8: + unreachable("XXX TODO: sort out how 8-bit constant encoding works"); + break; + } +} + +static void +mir_print_embedded_constant(midgard_instruction *ins, unsigned src_idx) +{ + unsigned type_size = mir_bytes_for_mode(ins->alu.reg_mode); + midgard_vector_alu_src src; + + assert(src_idx <= 1); + if (src_idx == 0) + src = vector_alu_from_unsigned(ins->alu.src1); + else + src = vector_alu_from_unsigned(ins->alu.src2); + + unsigned *swizzle = ins->swizzle[src_idx]; + unsigned comp_mask = effective_writemask(&ins->alu, ins->mask); + unsigned num_comp = util_bitcount(comp_mask); + unsigned max_comp = 16 / type_size; + bool first = true; + + printf("#"); + + if (num_comp > 1) + printf("vec%d(", num_comp); + + for (unsigned comp = 0; comp < max_comp; comp++) { + if (!(comp_mask & (1 << comp))) + continue; + + if (first) + first = false; + else + printf(", "); + + mir_print_constant_component(stdout, &ins->constants, + swizzle[comp], ins->alu.reg_mode, + src.half, src.mod, ins->alu.op); + } + + if (num_comp > 1) + printf(")"); +} + void mir_print_instruction(midgard_instruction *ins) { @@ -175,12 +335,20 @@ mir_print_instruction(midgard_instruction *ins) printf(", "); - mir_print_index(ins->src[0]); - mir_print_swizzle(ins->swizzle[0]); + unsigned r_constant = SSA_FIXED_REGISTER(REGISTER_CONSTANT); + + if (ins->src[0] == r_constant) + mir_print_embedded_constant(ins, 0); + else { + mir_print_index(ins->src[0]); + mir_print_swizzle(ins->swizzle[0]); + } printf(", "); if (ins->has_inline_constant) printf("#%d", ins->inline_constant); + else if (ins->src[1] == r_constant) + mir_print_embedded_constant(ins, 1); else { mir_print_index(ins->src[1]); mir_print_swizzle(ins->swizzle[1]); @@ -194,16 +362,6 @@ mir_print_instruction(midgard_instruction *ins) mir_print_index(ins->src[3]); mir_print_swizzle(ins->swizzle[3]); - if (ins->has_constants) { - uint32_t *uc = ins->constants.u32; - float *fc = ins->constants.f32; - - if (midgard_is_integer_op(ins->alu.op)) - printf(" <0x%X, 0x%X, 0x%X, 0x%x>", uc[0], uc[1], uc[2], uc[3]); - else - printf(" <%f, %f, %f, %f>", fc[0], fc[1], fc[2], fc[3]); - } - if (ins->no_spill) printf(" /* no spill */"); -- 2.30.2