From: Rob Clark Date: Mon, 2 Feb 2015 17:54:25 +0000 (-0500) Subject: freedreno/ir3: helpful iterator macros X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f8f7548f466509bf881db1826ef6dd23ffe2acdf;p=mesa.git 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 --- diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h index 18d59fa7d55..3d3ad07c330 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.h +++ b/src/gallium/drivers/freedreno/ir3/ir3.h @@ -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 void ir3_dump(struct ir3 *shader, const char *name, diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cp.c b/src/gallium/drivers/freedreno/ir3/ir3_cp.c index c55425d68d4..b70aba956c9 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_cp.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_cp.c @@ -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; } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_depth.c b/src/gallium/drivers/freedreno/ir3/ir3_depth.c index 8ff62ba70a6..0cda62bf102 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_depth.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_depth.c @@ -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 diff --git a/src/gallium/drivers/freedreno/ir3/ir3_dump.c b/src/gallium/drivers/freedreno/ir3/ir3_dump.c index e4a13f9b4b8..42a38d7511e 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_dump.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_dump.c @@ -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; - - /* 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]); - } + 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::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, "|"); /* 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, " ", (i - 1)); + fprintf(ctx->f, " ", 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:", - 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); } } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_flatten.c b/src/gallium/drivers/freedreno/ir3/ir3_flatten.c index 9389227034c..419cd9dfcd4 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_flatten.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_flatten.c @@ -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 */ diff --git a/src/gallium/drivers/freedreno/ir3/ir3_group.c b/src/gallium/drivers/freedreno/ir3/ir3_group.c index a571e2e8eea..d48ecc307aa 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_group.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_group.c @@ -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 diff --git a/src/gallium/drivers/freedreno/ir3/ir3_legalize.c b/src/gallium/drivers/freedreno/ir3/ir3_legalize.c index 4e0b42b8d3a..db501e7a51c 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_legalize.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_legalize.c @@ -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); } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_ra.c b/src/gallium/drivers/freedreno/ir3/ir3_ra.c index 75ea4d69301..03180b13b18 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_ra.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_ra.c @@ -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); } } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_sched.c b/src/gallium/drivers/freedreno/ir3/ir3_sched.c index 29689dbed7e..1288452d29d 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_sched.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_sched.c @@ -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; }