Commit 24360966 authored by Boris Brezillon's avatar Boris Brezillon Committed by Marge Bot
Browse files

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's avatarBoris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig's avatarAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tested-by: Marge Bot <mesa/mesa!3536>
Part-of: <mesa/mesa!3536>
parent aa973fc1
......@@ -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;
}
......
......@@ -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 */");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment