mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 19:40:10 +01:00
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 <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>
This commit is contained in:
parent
aa973fc14e
commit
24360966ab
3 changed files with 292 additions and 68 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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 */");
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue