panfrost/midgard: Prettify embedded constant prints
authorBoris Brezillon <boris.brezillon@collabora.com>
Mon, 20 Jan 2020 17:40:43 +0000 (18:40 +0100)
committerMarge Bot <eric+marge@anholt.net>
Mon, 27 Jan 2020 15:24:54 +0000 (15:24 +0000)
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 <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3536>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3536>

src/panfrost/midgard/disassemble.c
src/panfrost/midgard/helpers.h
src/panfrost/midgard/midgard_print.c

index f99a13f2908db27294ecbbb830dc3195ce9c469d..2e4ab489177894af811002da5d0e2315519dd9ec 100644 (file)
@@ -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 *)&reg_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 *)&reg_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;
 }
index 66223f3fd787bc54e9f6709ccc14fc245eabeb54..6d1031841a542d8b02f8c2facdc3a9a5ca9fee77 100644 (file)
@@ -23,6 +23,7 @@
 #define __MDG_HELPERS_H
 
 #include "util/macros.h"
+#include <stdio.h>
 #include <string.h>
 
 #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
index 36a582599317c931c22ba11cff2d89aa3e404d5e..85a1d981722742423ebd07ad52f884263a7a6c17 100644 (file)
  * SOFTWARE.
  */
 
+#include <math.h>
+
+#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 */");