freedreno/ir3: drop dot graph dumping

At least for now.. right now the instruction and instruction list
printing should suffice, and the re-working of ir3_block would require
a lot of changes in that code.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
This commit is contained in:
Rob Clark
2015-04-30 10:10:14 -04:00
parent 5c8c2e2f97
commit 67d994c676
10 changed files with 228 additions and 525 deletions
@@ -125,13 +125,13 @@ ir3_SOURCES := \
ir3/ir3_compiler.h \
ir3/ir3_cp.c \
ir3/ir3_depth.c \
ir3/ir3_dump.c \
ir3/ir3_flatten.c \
ir3/ir3_group.c \
ir3/ir3.h \
ir3/ir3_legalize.c \
ir3/ir3_nir.h \
ir3/ir3_nir_lower_if_else.c \
ir3/ir3_print.c \
ir3/ir3_ra.c \
ir3/ir3_sched.c \
ir3/ir3_shader.c \
@@ -68,7 +68,6 @@ static const struct debug_named_value debug_options[] = {
{"fraghalf", FD_DBG_FRAGHALF, "Use half-precision in fragment shader"},
{"nobin", FD_DBG_NOBIN, "Disable hw binning"},
{"optmsgs", FD_DBG_OPTMSGS,"Enable optimizer debug messages"},
{"optdump", FD_DBG_OPTDUMP,"Dump shader DAG to .dot files"},
{"glsl120", FD_DBG_GLSL120,"Temporary flag to force GLSL 120 (rather than 130) on a3xx+"},
{"nocp", FD_DBG_NOCP, "Disable copy-propagation"},
{"nir", FD_DBG_NIR, "Enable experimental NIR compiler"},
@@ -63,7 +63,6 @@ enum adreno_stencil_op fd_stencil_op(unsigned op);
#define FD_DBG_FRAGHALF 0x0080
#define FD_DBG_NOBIN 0x0100
#define FD_DBG_OPTMSGS 0x0400
#define FD_DBG_OPTDUMP 0x0800
#define FD_DBG_GLSL120 0x1000
#define FD_DBG_NOCP 0x2000
#define FD_DBG_NIR 0x4000
+3 -7
View File
@@ -747,12 +747,8 @@ static inline struct ir3_instruction * __ssa_src_n(struct ir3_instruction *instr
/* dump: */
#include <stdio.h>
void ir3_dump(struct ir3 *shader, const char *name,
struct ir3_block *block /* XXX maybe 'block' ptr should move to ir3? */,
FILE *f);
void ir3_dump_instr_single(struct ir3_instruction *instr);
void ir3_dump_instr_list(struct ir3_instruction *instr);
void ir3_print(struct ir3 *ir);
void ir3_print_instr(struct ir3_instruction *instr);
/* flatten if/else: */
int ir3_block_flatten(struct ir3_block *block);
@@ -765,7 +761,7 @@ void ir3_block_depth(struct ir3_block *block);
/* copy-propagate: */
void ir3_block_cp(struct ir3_block *block);
/* group neightbors and insert mov's to resolve conflicts: */
/* group neighbors and insert mov's to resolve conflicts: */
void ir3_block_group(struct ir3_block *block);
/* scheduling: */
@@ -30,6 +30,7 @@
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include "tgsi/tgsi_parse.h"
@@ -243,7 +244,7 @@ int main(int argc, char **argv)
while (n < argc) {
if (!strcmp(argv[n], "--verbose")) {
fd_mesa_debug |= FD_DBG_OPTDUMP | FD_DBG_MSGS | FD_DBG_OPTMSGS;
fd_mesa_debug |= FD_DBG_MSGS | FD_DBG_OPTMSGS;
n++;
continue;
}
@@ -3515,22 +3515,6 @@ compile_instructions(struct ir3_compile_context *ctx)
}
}
static void
compile_dump(struct ir3_compile_context *ctx)
{
const char *name = (ctx->so->type == SHADER_VERTEX) ? "vert" : "frag";
static unsigned n = 0;
char fname[16];
FILE *f;
snprintf(fname, sizeof(fname), "%s-%04u.dot", name, n++);
f = fopen(fname, "w");
if (!f)
return;
ir3_block_depth(ctx->block);
ir3_dump(ctx->ir, name, ctx->block, f);
fclose(f);
}
int
ir3_compile_shader(struct ir3_shader_variant *so,
const struct tgsi_token *tokens, struct ir3_shader_key key,
@@ -3613,20 +3597,15 @@ ir3_compile_shader(struct ir3_shader_variant *so,
block->outputs[block->noutputs++] = ctx.kill[i];
}
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(&ctx);
ret = ir3_block_flatten(block);
if (ret < 0) {
DBG("FLATTEN failed!");
goto out;
}
if ((ret > 0) && (fd_mesa_debug & FD_DBG_OPTDUMP))
compile_dump(&ctx);
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE CP:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ir3_block_depth(block);
@@ -3641,7 +3620,7 @@ ir3_compile_shader(struct ir3_shader_variant *so,
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE GROUPING:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
/* Group left/right neighbors, inserting mov's where needed to
@@ -3649,14 +3628,11 @@ ir3_compile_shader(struct ir3_shader_variant *so,
*/
ir3_block_group(block);
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(&ctx);
ir3_block_depth(block);
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER DEPTH:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ret = ir3_block_sched(block);
@@ -3667,7 +3643,7 @@ ir3_compile_shader(struct ir3_shader_variant *so,
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER SCHED:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ret = ir3_block_ra(block, so->type, so->frag_coord, so->frag_face);
@@ -3678,7 +3654,7 @@ ir3_compile_shader(struct ir3_shader_variant *so,
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER RA:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ir3_block_legalize(block, &so->has_samp, &max_bary);
@@ -1908,22 +1908,6 @@ fixup_frag_inputs(struct ir3_compile *ctx)
block->inputs = inputs;
}
static void
compile_dump(struct ir3_compile *ctx)
{
const char *name = (ctx->so->type == SHADER_VERTEX) ? "vert" : "frag";
static unsigned n = 0;
char fname[16];
FILE *f;
snprintf(fname, sizeof(fname), "%s-%04u.dot", name, n++);
f = fopen(fname, "w");
if (!f)
return;
ir3_block_depth(ctx->block);
ir3_dump(ctx->ir, name, ctx->block, f);
fclose(f);
}
int
ir3_compile_shader_nir(struct ir3_shader_variant *so,
const struct tgsi_token *tokens, struct ir3_shader_key key)
@@ -2008,12 +1992,9 @@ ir3_compile_shader_nir(struct ir3_shader_variant *so,
block->outputs[block->noutputs++] = ctx->kill[i];
}
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(ctx);
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE CP:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ir3_block_depth(block);
@@ -2022,7 +2003,7 @@ ir3_compile_shader_nir(struct ir3_shader_variant *so,
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("BEFORE GROUPING:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
/* Group left/right neighbors, inserting mov's where needed to
@@ -2030,14 +2011,11 @@ ir3_compile_shader_nir(struct ir3_shader_variant *so,
*/
ir3_block_group(block);
if (fd_mesa_debug & FD_DBG_OPTDUMP)
compile_dump(ctx);
ir3_block_depth(block);
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER DEPTH:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ret = ir3_block_sched(block);
@@ -2048,7 +2026,7 @@ ir3_compile_shader_nir(struct ir3_shader_variant *so,
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER SCHED:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ret = ir3_block_ra(block, so->type, so->frag_coord, so->frag_face);
@@ -2059,7 +2037,7 @@ ir3_compile_shader_nir(struct ir3_shader_variant *so,
if (fd_mesa_debug & FD_DBG_OPTMSGS) {
printf("AFTER RA:\n");
ir3_dump_instr_list(block->head);
ir3_print(so->ir);
}
ir3_block_legalize(block, &so->has_samp, &max_bary);
@@ -1,456 +0,0 @@
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
#include <stdarg.h>
#include "ir3.h"
#define PTRID(x) ((unsigned long)(x))
struct ir3_dump_ctx {
FILE *f;
bool verbose;
};
static void dump_instr_name(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr)
{
/* for debugging: */
if (ctx->verbose) {
#ifdef DEBUG
fprintf(ctx->f, "%04u:", instr->serialno);
#endif
fprintf(ctx->f, "%03u: ", instr->depth);
}
if (instr->flags & IR3_INSTR_SY)
fprintf(ctx->f, "(sy)");
if (instr->flags & IR3_INSTR_SS)
fprintf(ctx->f, "(ss)");
if (is_meta(instr)) {
switch(instr->opc) {
case OPC_META_PHI:
fprintf(ctx->f, "&#934;");
break;
default:
/* shouldn't hit here.. just for debugging: */
switch (instr->opc) {
case OPC_META_INPUT: fprintf(ctx->f, "_meta:in"); break;
case OPC_META_OUTPUT: fprintf(ctx->f, "_meta:out"); break;
case OPC_META_FO: fprintf(ctx->f, "_meta:fo"); break;
case OPC_META_FI: fprintf(ctx->f, "_meta:fi"); break;
case OPC_META_FLOW: fprintf(ctx->f, "_meta:flow"); break;
default: fprintf(ctx->f, "_meta:%d", instr->opc); break;
}
break;
}
} else if (instr->category == 1) {
static const char *type[] = {
[TYPE_F16] = "f16",
[TYPE_F32] = "f32",
[TYPE_U16] = "u16",
[TYPE_U32] = "u32",
[TYPE_S16] = "s16",
[TYPE_S32] = "s32",
[TYPE_U8] = "u8",
[TYPE_S8] = "s8",
};
if (instr->cat1.src_type == instr->cat1.dst_type)
fprintf(ctx->f, "mov");
else
fprintf(ctx->f, "cov");
fprintf(ctx->f, ".%s%s", type[instr->cat1.src_type], type[instr->cat1.dst_type]);
} else {
fprintf(ctx->f, "%s", ir3_instr_name(instr));
if (instr->flags & IR3_INSTR_3D)
fprintf(ctx->f, ".3d");
if (instr->flags & IR3_INSTR_A)
fprintf(ctx->f, ".a");
if (instr->flags & IR3_INSTR_O)
fprintf(ctx->f, ".o");
if (instr->flags & IR3_INSTR_P)
fprintf(ctx->f, ".p");
if (instr->flags & IR3_INSTR_S)
fprintf(ctx->f, ".s");
if (instr->flags & IR3_INSTR_S2EN)
fprintf(ctx->f, ".s2en");
}
}
static void dump_reg_name(struct ir3_dump_ctx *ctx,
struct ir3_register *reg, bool followssa)
{
if ((reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) &&
(reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)))
fprintf(ctx->f, "(absneg)");
else if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT))
fprintf(ctx->f, "(neg)");
else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS))
fprintf(ctx->f, "(abs)");
if (reg->flags & IR3_REG_IMMED) {
fprintf(ctx->f, "imm[%f,%d,0x%x]", reg->fim_val, reg->iim_val, reg->iim_val);
} else if (reg->flags & IR3_REG_SSA) {
if (ctx->verbose) {
fprintf(ctx->f, "_");
if (followssa) {
fprintf(ctx->f, "[");
dump_instr_name(ctx, reg->instr);
fprintf(ctx->f, "]");
}
}
} else if (reg->flags & IR3_REG_RELATIV) {
if (reg->flags & IR3_REG_HALF)
fprintf(ctx->f, "h");
if (reg->flags & IR3_REG_CONST)
fprintf(ctx->f, "c<a0.x + %u>", reg->num);
else
fprintf(ctx->f, "\x1b[0;31mr<a0.x + %u>\x1b[0m (%u)", reg->num, reg->size);
} else {
if (reg->flags & IR3_REG_HALF)
fprintf(ctx->f, "h");
if (reg->flags & IR3_REG_CONST)
fprintf(ctx->f, "c%u.%c", reg_num(reg), "xyzw"[reg_comp(reg)]);
else
fprintf(ctx->f, "\x1b[0;31mr%u.%c\x1b[0m", reg_num(reg), "xyzw"[reg_comp(reg)]);
}
}
static void ir3_instr_dump(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr);
static void ir3_block_dump(struct ir3_dump_ctx *ctx,
struct ir3_block *block, const char *name);
static void dump_instr(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr)
{
/* if we've already visited this instruction, bail now: */
if (ir3_instr_check_mark(instr))
return;
/* some meta-instructions need to be handled specially: */
if (is_meta(instr)) {
if ((instr->opc == OPC_META_FO) ||
(instr->opc == OPC_META_FI)) {
struct ir3_instruction *src;
foreach_ssa_src(src, instr)
dump_instr(ctx, src);
} else if (instr->opc == OPC_META_FLOW) {
struct ir3_register *reg = instr->regs[1];
ir3_block_dump(ctx, instr->flow.if_block, "if");
if (instr->flow.else_block)
ir3_block_dump(ctx, instr->flow.else_block, "else");
if (reg->flags & IR3_REG_SSA)
dump_instr(ctx, reg->instr);
} else if (instr->opc == OPC_META_PHI) {
/* treat like a normal instruction: */
ir3_instr_dump(ctx, instr);
}
} else {
ir3_instr_dump(ctx, instr);
}
}
/* arrarraggh! if link is to something outside of the current block, we
* need to defer emitting the link until the end of the block, since the
* edge triggers pre-creation of the node it links to inside the cluster,
* even though it is meant to be outside..
*/
static struct {
char buf[40960];
unsigned n;
} edge_buf;
/* helper to print or defer: */
static void printdef(struct ir3_dump_ctx *ctx,
bool defer, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (defer) {
unsigned n = edge_buf.n;
n += vsnprintf(&edge_buf.buf[n], sizeof(edge_buf.buf) - n,
fmt, ap);
edge_buf.n = n;
} else {
vfprintf(ctx->f, fmt, ap);
}
va_end(ap);
}
static void dump_link2(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr, const char *target, bool defer)
{
/* some meta-instructions need to be handled specially: */
if (is_meta(instr)) {
if (instr->opc == OPC_META_INPUT) {
printdef(ctx, defer, "input%lx:<in%u>:w -> %s",
PTRID(instr->inout.block),
instr->regs[0]->num, target);
} else if (instr->opc == OPC_META_FO) {
struct ir3_register *reg = instr->regs[1];
dump_link2(ctx, reg->instr, target, defer);
printdef(ctx, defer, "[label=\".%c\"]",
"xyzw"[instr->fo.off & 0x3]);
} else if (instr->opc == OPC_META_FI) {
struct ir3_instruction *src;
foreach_ssa_src_n(src, i, instr) {
dump_link2(ctx, src, target, defer);
printdef(ctx, defer, "[label=\".%c\"]",
"xyzw"[i & 0x3]);
}
} else if (instr->opc == OPC_META_OUTPUT) {
printdef(ctx, defer, "output%lx:<out%u>:w -> %s",
PTRID(instr->inout.block),
instr->regs[0]->num, target);
} else if (instr->opc == OPC_META_PHI) {
/* treat like a normal instruction: */
printdef(ctx, defer, "instr%lx:<dst0> -> %s", PTRID(instr), target);
}
} else {
printdef(ctx, defer, "instr%lx:<dst0> -> %s", PTRID(instr), target);
}
}
static void dump_link(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr,
struct ir3_block *block, const char *target)
{
bool defer = instr->block != block;
dump_link2(ctx, instr, target, defer);
printdef(ctx, defer, "\n");
}
static struct ir3_register *follow_flow(struct ir3_register *reg)
{
if (reg->flags & IR3_REG_SSA) {
struct ir3_instruction *instr = reg->instr;
/* go with the flow.. */
if (is_meta(instr) && (instr->opc == OPC_META_FLOW))
return instr->regs[1];
}
return reg;
}
static void ir3_instr_dump(struct ir3_dump_ctx *ctx,
struct ir3_instruction *instr)
{
struct ir3_register *src;
fprintf(ctx->f, "instr%lx [shape=record,style=filled,fillcolor=lightgrey,label=\"{",
PTRID(instr));
dump_instr_name(ctx, instr);
/* destination register: */
fprintf(ctx->f, "|<dst0>");
/* source register(s): */
foreach_src_n(src, i, instr) {
struct ir3_register *reg = follow_flow(src);
fprintf(ctx->f, "|");
if (reg->flags & IR3_REG_SSA)
fprintf(ctx->f, "<src%u> ", i);
dump_reg_name(ctx, reg, true);
}
fprintf(ctx->f, "}\"];\n");
/* and recursively dump dependent instructions: */
foreach_src_n(src, i, instr) {
struct ir3_register *reg = follow_flow(src);
char target[32]; /* link target */
if (!(reg->flags & IR3_REG_SSA))
continue;
snprintf(target, sizeof(target), "instr%lx:<src%u>",
PTRID(instr), i);
dump_instr(ctx, reg->instr);
dump_link(ctx, reg->instr, instr->block, target);
}
}
static void ir3_block_dump(struct ir3_dump_ctx *ctx,
struct ir3_block *block, const char *name)
{
unsigned i, n;
n = edge_buf.n;
fprintf(ctx->f, "subgraph cluster%lx {\n", PTRID(block));
fprintf(ctx->f, "label=\"%s\";\n", name);
/* draw inputs: */
fprintf(ctx->f, "input%lx [shape=record,label=\"inputs", PTRID(block));
for (i = 0; i < block->ninputs; i++)
if (block->inputs[i])
fprintf(ctx->f, "|<in%u> i%u.%c", i, (i >> 2), "xyzw"[i & 0x3]);
fprintf(ctx->f, "\"];\n");
/* draw instruction graph: */
for (i = 0; i < block->noutputs; i++)
if (block->outputs[i])
dump_instr(ctx, block->outputs[i]);
/* draw outputs: */
fprintf(ctx->f, "output%lx [shape=record,label=\"outputs", PTRID(block));
for (i = 0; i < block->noutputs; i++)
fprintf(ctx->f, "|<out%u> o%u.%c", i, (i >> 2), "xyzw"[i & 0x3]);
fprintf(ctx->f, "\"];\n");
/* and links to outputs: */
for (i = 0; i < block->noutputs; i++) {
char target[32]; /* link target */
/* NOTE: there could be outputs that are never assigned,
* so skip them
*/
if (!block->outputs[i])
continue;
snprintf(target, sizeof(target), "output%lx:<out%u>:e",
PTRID(block), i);
dump_link(ctx, block->outputs[i], block, target);
}
fprintf(ctx->f, "}\n");
/* and links to inputs: */
if (block->parent) {
for (i = 0; i < block->ninputs; i++) {
char target[32]; /* link target */
if (!block->inputs[i])
continue;
dump_instr(ctx, block->inputs[i]);
snprintf(target, sizeof(target), "input%lx:<in%u>:e",
PTRID(block), i);
dump_link(ctx, block->inputs[i], block, target);
}
}
/* dump deferred edges: */
if (edge_buf.n > n) {
fprintf(ctx->f, "%*s", edge_buf.n - n, &edge_buf.buf[n]);
edge_buf.n = n;
}
}
void ir3_dump(struct ir3 *shader, const char *name,
struct ir3_block *block /* XXX maybe 'block' ptr should move to ir3? */,
FILE *f)
{
struct ir3_dump_ctx ctx = {
.f = f,
};
ir3_clear_mark(shader);
fprintf(ctx.f, "digraph G {\n");
fprintf(ctx.f, "rankdir=RL;\n");
fprintf(ctx.f, "nodesep=0.25;\n");
fprintf(ctx.f, "ranksep=1.5;\n");
ir3_block_dump(&ctx, block, name);
fprintf(ctx.f, "}\n");
}
/*
* For Debugging:
*/
void
ir3_dump_instr_single(struct ir3_instruction *instr)
{
struct ir3_dump_ctx ctx = {
.f = stdout,
.verbose = true,
};
unsigned i;
dump_instr_name(&ctx, instr);
for (i = 0; i < instr->regs_count; i++) {
struct ir3_register *reg = instr->regs[i];
printf(i ? ", " : " ");
dump_reg_name(&ctx, reg, !!i);
}
if (instr->address) {
fprintf(ctx.f, ", address=_");
fprintf(ctx.f, "[");
dump_instr_name(&ctx, instr->address);
fprintf(ctx.f, "]");
}
if (instr->fanin) {
fprintf(ctx.f, ", fanin=_");
fprintf(ctx.f, "[");
dump_instr_name(&ctx, instr->fanin);
fprintf(ctx.f, "]");
}
if (is_meta(instr)) {
if (instr->opc == OPC_META_FO) {
printf(", off=%d", instr->fo.off);
} else if ((instr->opc == OPC_META_FI) && instr->fi.aid) {
printf(", aid=%d", instr->fi.aid);
}
}
printf("\n");
}
void
ir3_dump_instr_list(struct ir3_instruction *instr)
{
struct ir3_block *block = instr->block;
unsigned n = 0;
while (instr) {
ir3_dump_instr_single(instr);
if (!is_meta(instr))
n++;
instr = instr->next;
}
printf("%u instructions\n", n);
for (n = 0; n < block->noutputs; n++) {
if (!block->outputs[n])
continue;
printf("out%d: ", n);
ir3_dump_instr_single(block->outputs[n]);
}
}
@@ -0,0 +1,210 @@
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
/*
* Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Rob Clark <robclark@freedesktop.org>
*/
#include <stdarg.h>
#include <stdio.h>
#include "ir3.h"
#define PTRID(x) ((unsigned long)(x))
static void print_instr_name(struct ir3_instruction *instr)
{
#ifdef DEBUG
printf("%04u:", instr->serialno);
#endif
printf("%03u: ", instr->depth);
if (instr->flags & IR3_INSTR_SY)
printf("(sy)");
if (instr->flags & IR3_INSTR_SS)
printf("(ss)");
if (is_meta(instr)) {
switch(instr->opc) {
case OPC_META_PHI:
printf("&#934;");
break;
default:
/* shouldn't hit here.. just for debugging: */
switch (instr->opc) {
case OPC_META_INPUT: printf("_meta:in"); break;
case OPC_META_OUTPUT: printf("_meta:out"); break;
case OPC_META_FO: printf("_meta:fo"); break;
case OPC_META_FI: printf("_meta:fi"); break;
case OPC_META_FLOW: printf("_meta:flow"); break;
default: printf("_meta:%d", instr->opc); break;
}
break;
}
} else if (instr->category == 1) {
static const char *type[] = {
[TYPE_F16] = "f16",
[TYPE_F32] = "f32",
[TYPE_U16] = "u16",
[TYPE_U32] = "u32",
[TYPE_S16] = "s16",
[TYPE_S32] = "s32",
[TYPE_U8] = "u8",
[TYPE_S8] = "s8",
};
if (instr->cat1.src_type == instr->cat1.dst_type)
printf("mov");
else
printf("cov");
printf(".%s%s", type[instr->cat1.src_type], type[instr->cat1.dst_type]);
} else {
printf("%s", ir3_instr_name(instr));
if (instr->flags & IR3_INSTR_3D)
printf(".3d");
if (instr->flags & IR3_INSTR_A)
printf(".a");
if (instr->flags & IR3_INSTR_O)
printf(".o");
if (instr->flags & IR3_INSTR_P)
printf(".p");
if (instr->flags & IR3_INSTR_S)
printf(".s");
if (instr->flags & IR3_INSTR_S2EN)
printf(".s2en");
}
}
static void print_reg_name(struct ir3_register *reg, bool followssa)
{
if ((reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) &&
(reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)))
printf("(absneg)");
else if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT))
printf("(neg)");
else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS))
printf("(abs)");
if (reg->flags & IR3_REG_IMMED) {
printf("imm[%f,%d,0x%x]", reg->fim_val, reg->iim_val, reg->iim_val);
} else if (reg->flags & IR3_REG_SSA) {
printf("_");
if (followssa) {
printf("[");
print_instr_name(reg->instr);
printf("]");
}
} else if (reg->flags & IR3_REG_RELATIV) {
if (reg->flags & IR3_REG_HALF)
printf("h");
if (reg->flags & IR3_REG_CONST)
printf("c<a0.x + %u>", reg->num);
else
printf("\x1b[0;31mr<a0.x + %u>\x1b[0m (%u)", reg->num, reg->size);
} else {
if (reg->flags & IR3_REG_HALF)
printf("h");
if (reg->flags & IR3_REG_CONST)
printf("c%u.%c", reg_num(reg), "xyzw"[reg_comp(reg)]);
else
printf("\x1b[0;31mr%u.%c\x1b[0m", reg_num(reg), "xyzw"[reg_comp(reg)]);
}
}
static void
tab(int lvl)
{
for (int i = 0; i < lvl; i++)
printf("\t");
}
static void
print_instr(struct ir3_instruction *instr, int lvl)
{
unsigned i;
tab(lvl);
print_instr_name(instr);
for (i = 0; i < instr->regs_count; i++) {
struct ir3_register *reg = instr->regs[i];
printf(i ? ", " : " ");
print_reg_name(reg, !!i);
}
if (instr->address) {
printf(", address=_");
printf("[");
print_instr_name(instr->address);
printf("]");
}
if (instr->fanin) {
printf(", fanin=_");
printf("[");
print_instr_name(instr->fanin);
printf("]");
}
if (is_meta(instr)) {
if (instr->opc == OPC_META_FO) {
printf(", off=%d", instr->fo.off);
} else if ((instr->opc == OPC_META_FI) && instr->fi.aid) {
printf(", aid=%d", instr->fi.aid);
}
}
printf("\n");
}
void ir3_print_instr(struct ir3_instruction *instr)
{
print_instr(instr, 0);
}
static void
print_block(struct ir3_block *block, int lvl)
{
struct ir3_instruction *instr;
tab(lvl); printf("block {\n");
for (instr = block->head; instr; instr = instr->next) {
print_instr(instr, lvl+1);
}
tab(lvl); printf("}\n");
}
void
ir3_print(struct ir3 *ir)
{
struct ir3_block *block = ir->block;
print_block(block, 0);
for (unsigned i = 0; i < block->noutputs; i++) {
if (!block->outputs[i])
continue;
printf("out%d: ", i);
print_instr(block->outputs[i], 0);
}
}
+2 -2
View File
@@ -78,14 +78,14 @@ struct ir3_ra_ctx {
#define ra_dump_list(msg, n) do { \
if (ra_debug) { \
debug_printf("-- " msg); \
ir3_dump_instr_list(n); \
ir3_print(n->block->shader); \
} \
} while (0)
#define ra_dump_instr(msg, n) do { \
if (ra_debug) { \
debug_printf(">> " msg); \
ir3_dump_instr_single(n); \
ir3_print_instr(n); \
} \
} while (0)