aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBoris Brezillon <[email protected]>2020-01-20 18:40:43 +0100
committerMarge Bot <[email protected]>2020-01-27 15:24:54 +0000
commit24360966ab31a9bedfe07356413769218fd2e0b6 (patch)
treecc24cb4c1a1ad227454e15ecee3d8ec9c9bfd708 /src
parentaa973fc14e140753d3c5b47eda79e451c1dc61ed (diff)
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 <[email protected]> Reviewed-by: Alyssa Rosenzweig <[email protected]> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3536> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3536>
Diffstat (limited to 'src')
-rw-r--r--src/panfrost/midgard/disassemble.c172
-rw-r--r--src/panfrost/midgard/helpers.h6
-rw-r--r--src/panfrost/midgard/midgard_print.c182
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"
@@ -329,6 +330,69 @@ bits_for_mode_halved(midgard_reg_mode mode, bool half)
}
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,
midgard_dest_override override, bool is_int)
@@ -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;
}
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 <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
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 <math.h>
+
+#include "util/bitscan.h"
+#include "util/half_float.h"
#include "compiler.h"
#include "helpers.h"
#include "midgard_ops.h"
@@ -99,6 +103,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)
{
printf("\t");
@@ -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 */");