mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-30 21:21:39 +02:00
freedreno/ir3: helpful iterator macros
I remembered that we are using c99.. which makes some sugary iterator macros easier. So introduce iterator macros to iterate all src registers and all SSA src instructions. The _n variants also return the src #, since there are a handful of places that need this. Signed-off-by: Rob Clark <robclark@freedesktop.org>
This commit is contained in:
parent
26b79ac3e4
commit
f8f7548f46
9 changed files with 108 additions and 110 deletions
|
|
@ -486,6 +486,40 @@ static inline bool reg_gpr(struct ir3_register *r)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* iterator for an instructions's sources (reg), also returns src #: */
|
||||
#define foreach_src_n(__srcreg, __n, __instr) \
|
||||
if ((__instr)->regs_count) \
|
||||
for (unsigned __cnt = (__instr)->regs_count - 1, __n = 0; __n < __cnt; __n++) \
|
||||
if ((__srcreg = (__instr)->regs[__n + 1]))
|
||||
|
||||
/* iterator for an instructions's sources (reg): */
|
||||
#define foreach_src(__srcreg, __instr) \
|
||||
foreach_src_n(__srcreg, __i, __instr)
|
||||
|
||||
static inline unsigned __ssa_src_cnt(struct ir3_instruction *instr)
|
||||
{
|
||||
return instr->regs_count;
|
||||
}
|
||||
|
||||
static inline struct ir3_instruction * __ssa_src_n(struct ir3_instruction *instr, unsigned n)
|
||||
{
|
||||
return ssa(instr->regs[n]);
|
||||
}
|
||||
|
||||
#define __src_cnt(__instr) ((__instr)->address ? (__instr)->regs_count : (__instr)->regs_count - 1)
|
||||
|
||||
/* iterator for an instruction's SSA sources (instr), also returns src #: */
|
||||
#define foreach_ssa_src_n(__srcinst, __n, __instr) \
|
||||
if ((__instr)->regs_count) \
|
||||
for (unsigned __cnt = __ssa_src_cnt(__instr) - 1, __n = 0; __n < __cnt; __n++) \
|
||||
if ((__srcinst = __ssa_src_n(__instr, __n + 1)))
|
||||
|
||||
/* iterator for an instruction's SSA sources (instr): */
|
||||
#define foreach_ssa_src(__srcinst, __instr) \
|
||||
foreach_ssa_src_n(__srcinst, __i, __instr)
|
||||
|
||||
|
||||
/* dump: */
|
||||
#include <stdio.h>
|
||||
void ir3_dump(struct ir3 *shader, const char *name,
|
||||
|
|
|
|||
|
|
@ -64,18 +64,6 @@ static bool is_eligible_mov(struct ir3_instruction *instr)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void walk_children(struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* walk down the graph from each src: */
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *src = instr->regs[i];
|
||||
if (src->flags & IR3_REG_SSA)
|
||||
src->instr = instr_cp(src->instr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct ir3_instruction *
|
||||
instr_cp(struct ir3_instruction *instr)
|
||||
|
|
@ -100,8 +88,14 @@ instr_cp(struct ir3_instruction *instr)
|
|||
* up as a src, we only need to recursively walk the children
|
||||
* once.)
|
||||
*/
|
||||
if (!ir3_instr_check_mark(instr))
|
||||
walk_children(instr);
|
||||
if (!ir3_instr_check_mark(instr)) {
|
||||
struct ir3_register *reg;
|
||||
|
||||
/* walk down the graph from each src: */
|
||||
foreach_src(reg, instr)
|
||||
if (reg->flags & IR3_REG_SSA)
|
||||
reg->instr = instr_cp(reg->instr);
|
||||
}
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ static void insert_by_depth(struct ir3_instruction *instr)
|
|||
|
||||
static void ir3_instr_depth(struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i;
|
||||
struct ir3_instruction *src;
|
||||
|
||||
/* if we've already visited this instruction, bail now: */
|
||||
if (ir3_instr_check_mark(instr))
|
||||
|
|
@ -110,19 +110,15 @@ static void ir3_instr_depth(struct ir3_instruction *instr)
|
|||
|
||||
instr->depth = 0;
|
||||
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *src = instr->regs[i];
|
||||
if (src->flags & IR3_REG_SSA) {
|
||||
unsigned sd;
|
||||
foreach_ssa_src_n(src, i, instr) {
|
||||
unsigned sd;
|
||||
|
||||
/* visit child to compute it's depth: */
|
||||
ir3_instr_depth(src->instr);
|
||||
/* visit child to compute it's depth: */
|
||||
ir3_instr_depth(src);
|
||||
|
||||
sd = ir3_delayslots(src->instr, instr, i-1) +
|
||||
src->instr->depth;
|
||||
sd = ir3_delayslots(src, instr, i) + src->depth;
|
||||
|
||||
instr->depth = MAX2(instr->depth, sd);
|
||||
}
|
||||
instr->depth = MAX2(instr->depth, sd);
|
||||
}
|
||||
|
||||
/* meta-instructions don't add cycles, other than PHI.. which
|
||||
|
|
|
|||
|
|
@ -161,12 +161,9 @@ static void dump_instr(struct ir3_dump_ctx *ctx,
|
|||
if (is_meta(instr)) {
|
||||
if ((instr->opc == OPC_META_FO) ||
|
||||
(instr->opc == OPC_META_FI)) {
|
||||
unsigned i;
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = instr->regs[i];
|
||||
if (reg->flags & IR3_REG_SSA)
|
||||
dump_instr(ctx, reg->instr);
|
||||
}
|
||||
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");
|
||||
|
|
@ -226,16 +223,12 @@ static void dump_link2(struct ir3_dump_ctx *ctx,
|
|||
printdef(ctx, defer, "[label=\".%c\"]",
|
||||
"xyzw"[instr->fo.off & 0x3]);
|
||||
} else if (instr->opc == OPC_META_FI) {
|
||||
unsigned i;
|
||||
struct ir3_instruction *src;
|
||||
|
||||
/* recursively dump all parents and links */
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = instr->regs[i];
|
||||
if (reg->flags & IR3_REG_SSA) {
|
||||
dump_link2(ctx, reg->instr, target, defer);
|
||||
printdef(ctx, defer, "[label=\".%c\"]",
|
||||
"xyzw"[(i - 1) & 0x3]);
|
||||
}
|
||||
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",
|
||||
|
|
@ -274,7 +267,7 @@ static struct ir3_register *follow_flow(struct ir3_register *reg)
|
|||
static void ir3_instr_dump(struct ir3_dump_ctx *ctx,
|
||||
struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i;
|
||||
struct ir3_register *src;
|
||||
|
||||
fprintf(ctx->f, "instr%lx [shape=record,style=filled,fillcolor=lightgrey,label=\"{",
|
||||
PTRID(instr));
|
||||
|
|
@ -284,13 +277,13 @@ static void ir3_instr_dump(struct ir3_dump_ctx *ctx,
|
|||
fprintf(ctx->f, "|<dst0>");
|
||||
|
||||
/* source register(s): */
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = follow_flow(instr->regs[i]);
|
||||
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 - 1));
|
||||
fprintf(ctx->f, "<src%u> ", i);
|
||||
|
||||
dump_reg_name(ctx, reg, true);
|
||||
}
|
||||
|
|
@ -298,18 +291,18 @@ static void ir3_instr_dump(struct ir3_dump_ctx *ctx,
|
|||
fprintf(ctx->f, "}\"];\n");
|
||||
|
||||
/* and recursively dump dependent instructions: */
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = instr->regs[i];
|
||||
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 - 1));
|
||||
PTRID(instr), i);
|
||||
|
||||
dump_instr(ctx, reg->instr);
|
||||
dump_link(ctx, follow_flow(reg)->instr, instr->block, target);
|
||||
dump_link(ctx, reg->instr, instr->block, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ static struct ir3_register *unwrap(struct ir3_register *reg)
|
|||
static void ir3_instr_flatten(struct ir3_flatten_ctx *ctx,
|
||||
struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i;
|
||||
struct ir3_instruction *src;
|
||||
|
||||
/* if we've already visited this instruction, bail now: */
|
||||
if (ir3_instr_check_mark(instr))
|
||||
|
|
@ -131,11 +131,8 @@ static void ir3_instr_flatten(struct ir3_flatten_ctx *ctx,
|
|||
}
|
||||
|
||||
/* recursively visit children: */
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *src = instr->regs[i];
|
||||
if (src->flags & IR3_REG_SSA)
|
||||
ir3_instr_flatten(ctx, src->instr);
|
||||
}
|
||||
foreach_ssa_src(src, instr)
|
||||
ir3_instr_flatten(ctx, src);
|
||||
}
|
||||
|
||||
/* return >= 0 is # of phi's flattened, < 0 is error */
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ restart:
|
|||
|
||||
static void instr_find_neighbors(struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i;
|
||||
struct ir3_instruction *src;
|
||||
|
||||
if (check_stop(instr))
|
||||
return;
|
||||
|
|
@ -197,11 +197,8 @@ static void instr_find_neighbors(struct ir3_instruction *instr)
|
|||
if (is_meta(instr) && (instr->opc == OPC_META_FI))
|
||||
group_n(&instr_ops, instr, instr->regs_count - 1);
|
||||
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_instruction *src_instr = ssa(instr->regs[i]);
|
||||
if (src_instr)
|
||||
instr_find_neighbors(src_instr);
|
||||
}
|
||||
foreach_ssa_src(src, instr)
|
||||
instr_find_neighbors(src);
|
||||
}
|
||||
|
||||
/* a bit of sadness.. we can't have "holes" in inputs from PoV of
|
||||
|
|
|
|||
|
|
@ -176,8 +176,7 @@ static void legalize(struct ir3_legalize_ctx *ctx)
|
|||
* their src register(s):
|
||||
*/
|
||||
if (is_tex(n) || is_sfu(n)) {
|
||||
for (i = 1; i < n->regs_count; i++) {
|
||||
reg = n->regs[i];
|
||||
foreach_src(reg, n) {
|
||||
if (reg_gpr(reg))
|
||||
regmask_set(&needs_ss_war, reg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ static void instr_assign_src(struct ir3_ra_ctx *ctx,
|
|||
static void instr_assign(struct ir3_ra_ctx *ctx,
|
||||
struct ir3_instruction *instr, unsigned name)
|
||||
{
|
||||
struct ir3_instruction *n;
|
||||
struct ir3_instruction *n, *src;
|
||||
struct ir3_register *reg = instr->regs[0];
|
||||
|
||||
/* check if already assigned: */
|
||||
|
|
@ -404,12 +404,15 @@ static void instr_assign(struct ir3_ra_ctx *ctx,
|
|||
|
||||
/* and rename any subsequent use of result of this instr: */
|
||||
for (n = instr->next; n && !ctx->error; n = n->next) {
|
||||
unsigned i;
|
||||
foreach_ssa_src_n(src, i, n) {
|
||||
unsigned r = i + 1;
|
||||
|
||||
for (i = 1; i < n->regs_count; i++) {
|
||||
reg = n->regs[i];
|
||||
if ((reg->flags & IR3_REG_SSA) && (reg->instr == instr))
|
||||
instr_assign_src(ctx, n, i, name);
|
||||
/* skip address / etc (non real sources): */
|
||||
if (r >= n->regs_count)
|
||||
continue;
|
||||
|
||||
if (src == instr)
|
||||
instr_assign_src(ctx, n, r, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -420,9 +423,9 @@ static void instr_assign(struct ir3_ra_ctx *ctx,
|
|||
* to the actual instruction:
|
||||
*/
|
||||
if (is_meta(instr) && (instr->opc == OPC_META_FO)) {
|
||||
struct ir3_instruction *src = ssa(instr->regs[1]);
|
||||
debug_assert(name >= instr->fo.off);
|
||||
if (src)
|
||||
|
||||
foreach_ssa_src(src, instr)
|
||||
instr_assign(ctx, src, name - instr->fo.off);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,14 +170,10 @@ static unsigned delay_calc_srcn(struct ir3_sched_ctx *ctx,
|
|||
unsigned delay = 0;
|
||||
|
||||
if (is_meta(assigner)) {
|
||||
unsigned i;
|
||||
for (i = 1; i < assigner->regs_count; i++) {
|
||||
struct ir3_register *reg = assigner->regs[i];
|
||||
if (reg->flags & IR3_REG_SSA) {
|
||||
unsigned d = delay_calc_srcn(ctx, reg->instr,
|
||||
consumer, srcn);
|
||||
delay = MAX2(delay, d);
|
||||
}
|
||||
struct ir3_instruction *src;
|
||||
foreach_ssa_src(src, assigner) {
|
||||
unsigned d = delay_calc_srcn(ctx, src, consumer, srcn);
|
||||
delay = MAX2(delay, d);
|
||||
}
|
||||
} else {
|
||||
delay = ir3_delayslots(assigner, consumer, srcn);
|
||||
|
|
@ -191,15 +187,12 @@ static unsigned delay_calc_srcn(struct ir3_sched_ctx *ctx,
|
|||
static unsigned delay_calc(struct ir3_sched_ctx *ctx,
|
||||
struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i, delay = 0;
|
||||
unsigned delay = 0;
|
||||
struct ir3_instruction *src;
|
||||
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = instr->regs[i];
|
||||
if (reg->flags & IR3_REG_SSA) {
|
||||
unsigned d = delay_calc_srcn(ctx, reg->instr,
|
||||
instr, i - 1);
|
||||
delay = MAX2(delay, d);
|
||||
}
|
||||
foreach_ssa_src_n(src, i, instr) {
|
||||
unsigned d = delay_calc_srcn(ctx, src, instr, i);
|
||||
delay = MAX2(delay, d);
|
||||
}
|
||||
|
||||
return delay;
|
||||
|
|
@ -213,19 +206,16 @@ static int trysched(struct ir3_sched_ctx *ctx,
|
|||
{
|
||||
struct ir3_instruction *srcs[64];
|
||||
struct ir3_instruction *src;
|
||||
unsigned i, delay, nsrcs = 0;
|
||||
unsigned delay, nsrcs = 0;
|
||||
|
||||
/* if already scheduled: */
|
||||
if (instr->flags & IR3_INSTR_MARK)
|
||||
return 0;
|
||||
|
||||
debug_assert(instr->regs_count < ARRAY_SIZE(srcs));
|
||||
|
||||
/* figure out our src's: */
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = instr->regs[i];
|
||||
if (reg->flags & IR3_REG_SSA)
|
||||
srcs[nsrcs++] = reg->instr;
|
||||
/* figure out our src's, copy 'em out into an array for sorting: */
|
||||
foreach_ssa_src(src, instr) {
|
||||
debug_assert(nsrcs < ARRAY_SIZE(srcs));
|
||||
srcs[nsrcs++] = src;
|
||||
}
|
||||
|
||||
/* for each src register in sorted order:
|
||||
|
|
@ -302,16 +292,13 @@ static struct ir3_instruction * reverse(struct ir3_instruction *instr)
|
|||
static bool uses_current_addr(struct ir3_sched_ctx *ctx,
|
||||
struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = instr->regs[i];
|
||||
if (reg->flags & IR3_REG_SSA) {
|
||||
if (is_addr(reg->instr)) {
|
||||
struct ir3_instruction *addr;
|
||||
addr = reg->instr->regs[1]->instr; /* the mova */
|
||||
if (ctx->addr == addr)
|
||||
return true;
|
||||
}
|
||||
struct ir3_instruction *src;
|
||||
foreach_ssa_src(src, instr) {
|
||||
if (is_addr(src)) {
|
||||
struct ir3_instruction *addr =
|
||||
src->regs[1]->instr; /* the mova */
|
||||
if (ctx->addr == addr)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -320,12 +307,10 @@ static bool uses_current_addr(struct ir3_sched_ctx *ctx,
|
|||
static bool uses_current_pred(struct ir3_sched_ctx *ctx,
|
||||
struct ir3_instruction *instr)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 1; i < instr->regs_count; i++) {
|
||||
struct ir3_register *reg = instr->regs[i];
|
||||
if ((reg->flags & IR3_REG_SSA) && (ctx->pred == reg->instr))
|
||||
return true;
|
||||
}
|
||||
struct ir3_instruction *src;
|
||||
foreach_ssa_src(src, instr)
|
||||
if (ctx->pred == src)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue