freedreno/ir3: helpful iterator macros
authorRob Clark <robclark@freedesktop.org>
Mon, 2 Feb 2015 17:54:25 +0000 (12:54 -0500)
committerRob Clark <robclark@freedesktop.org>
Sun, 8 Mar 2015 21:42:43 +0000 (17:42 -0400)
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>
src/gallium/drivers/freedreno/ir3/ir3.h
src/gallium/drivers/freedreno/ir3/ir3_cp.c
src/gallium/drivers/freedreno/ir3/ir3_depth.c
src/gallium/drivers/freedreno/ir3/ir3_dump.c
src/gallium/drivers/freedreno/ir3/ir3_flatten.c
src/gallium/drivers/freedreno/ir3/ir3_group.c
src/gallium/drivers/freedreno/ir3/ir3_legalize.c
src/gallium/drivers/freedreno/ir3/ir3_ra.c
src/gallium/drivers/freedreno/ir3/ir3_sched.c

index 18d59fa7d55c56601d9b2a83f1718a22ce573b02..3d3ad07c330ee313daff30acace5d3b0fc35ff7a 100644 (file)
@@ -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,
index c55425d68d4d1eb6eb492e026ae2e81d16cccd9e..b70aba956c92c63a2794c195505f1b72576a16a7 100644 (file)
@@ -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;
 }
index 8ff62ba70a67476d431c05b1a25f134697c6542e..0cda62bf102923d6ec1e957ce7d8d1ae9914479d 100644 (file)
@@ -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
index e4a13f9b4b89ea14f7ab0911d77dbe6af18ca603..42a38d7511e755641a592ca3e40d112846e8e2a3 100644 (file)
@@ -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:<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);
        }
 }
 
index 9389227034c9cc9dacff58b53c8b1b878deec882..419cd9dfcd4302d58be68659317d2ab0a04750ad 100644 (file)
@@ -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 */
index a571e2e8eea0a6a5cd1c3a48cb79545f9e533059..d48ecc307aa8ff751706f3f559a9f06accea9042 100644 (file)
@@ -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
index 4e0b42b8d3abdbd250fee3cb3be7dc58f2914016..db501e7a51c9ead349bc1e376b50997615f0473f 100644 (file)
@@ -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);
                        }
index 75ea4d69301845aec0e3549a82a1bf818b2ae062..03180b13b18df371011528166559cc0b1a35a125 100644 (file)
@@ -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);
        }
 }
index 29689dbed7ec283da9c70b1e1366d9df20484b2a..1288452d29db08677cdf03519a1f88bd748c0e1e 100644 (file)
@@ -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;
 }