freedreno/ir3: remove ir3 phi instruction
authorRob Clark <robdclark@gmail.com>
Mon, 29 Jan 2018 21:22:26 +0000 (16:22 -0500)
committerRob Clark <robdclark@gmail.com>
Sat, 10 Feb 2018 19:54:58 +0000 (14:54 -0500)
Now that we convert phi webs to ssa, we can drop all this.

Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/drivers/freedreno/ir3/instr-a3xx.h
src/gallium/drivers/freedreno/ir3/ir3.h
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
src/gallium/drivers/freedreno/ir3/ir3_cp.c
src/gallium/drivers/freedreno/ir3/ir3_group.c
src/gallium/drivers/freedreno/ir3/ir3_print.c
src/gallium/drivers/freedreno/ir3/ir3_ra.c
src/gallium/drivers/freedreno/ir3/ir3_sched.c

index 6aebb057619c89abe01401dd215ffa22ccf17f27..904f88c7e282c4341b100f050128d4c831cb10af 100644 (file)
@@ -202,7 +202,6 @@ typedef enum {
        /* meta instructions (category -1): */
        /* placeholder instr to mark shader inputs: */
        OPC_META_INPUT      = _OPC(-1, 0),
-       OPC_META_PHI        = _OPC(-1, 1),
        /* The "fan-in" and "fan-out" instructions are used for keeping
         * track of instructions that write to multiple dst registers
         * (fan-out) like texture sample instructions, or read multiple
index 781a660bff855c94ce7ef8c3939794d3994c1ade..250d4672b6b44408548ccc35444ca995c6fe4216 100644 (file)
@@ -93,7 +93,6 @@ struct ir3_register {
                 */
                IR3_REG_SSA    = 0x4000,   /* 'instr' is ptr to assigning instr */
                IR3_REG_ARRAY  = 0x8000,
-               IR3_REG_PHI_SRC= 0x10000,  /* phi src, regs[0]->instr points to phi */
 
        } flags;
        union {
@@ -261,12 +260,6 @@ struct ir3_instruction {
                struct {
                        int off;              /* component/offset */
                } fo;
-               struct {
-                       /* used to temporarily hold reference to nir_phi_instr
-                        * until we resolve the phi srcs
-                        */
-                       void *nphi;
-               } phi;
                struct {
                        struct ir3_block *block;
                } inout;
index 4c37461292f24216427feb983e14be07960fea07..9cbf9ce47f15c46bad24a801b9b4c02375878683 100644 (file)
@@ -2593,64 +2593,6 @@ emit_tex_txs(struct ir3_context *ctx, nir_tex_instr *tex)
        put_dst(ctx, &tex->dest);
 }
 
-static void
-emit_phi(struct ir3_context *ctx, nir_phi_instr *nphi)
-{
-       struct ir3_instruction *phi, **dst;
-
-       /* NOTE: phi's should be lowered to scalar at this point */
-       compile_assert(ctx, nphi->dest.ssa.num_components == 1);
-
-       dst = get_dst(ctx, &nphi->dest, 1);
-
-       phi = ir3_instr_create2(ctx->block, OPC_META_PHI,
-                       1 + exec_list_length(&nphi->srcs));
-       ir3_reg_create(phi, 0, 0);         /* dst */
-       phi->phi.nphi = nphi;
-
-       dst[0] = phi;
-
-       put_dst(ctx, &nphi->dest);
-}
-
-/* phi instructions are left partially constructed.  We don't resolve
- * their srcs until the end of the block, since (eg. loops) one of
- * the phi's srcs might be defined after the phi due to back edges in
- * the CFG.
- */
-static void
-resolve_phis(struct ir3_context *ctx, struct ir3_block *block)
-{
-       list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
-               nir_phi_instr *nphi;
-
-               /* phi's only come at start of block: */
-               if (instr->opc != OPC_META_PHI)
-                       break;
-
-               if (!instr->phi.nphi)
-                       break;
-
-               nphi = instr->phi.nphi;
-               instr->phi.nphi = NULL;
-
-               foreach_list_typed(nir_phi_src, nsrc, node, &nphi->srcs) {
-                       struct ir3_instruction *src = get_src(ctx, &nsrc->src)[0];
-
-                       /* NOTE: src might not be in the same block as it comes from
-                        * according to the phi.. but in the end the backend assumes
-                        * it will be able to assign the same register to each (which
-                        * only works if it is assigned in the src block), so insert
-                        * an extra mov to make sure the phi src is assigned in the
-                        * block it comes from:
-                        */
-                       src = ir3_MOV(get_block(ctx, nsrc->pred), src, TYPE_U32);
-
-                       ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
-               }
-       }
-}
-
 static void
 emit_jump(struct ir3_context *ctx, nir_jump_instr *jump)
 {
@@ -2701,12 +2643,13 @@ emit_instr(struct ir3_context *ctx, nir_instr *instr)
                }
                break;
        }
-       case nir_instr_type_phi:
-               emit_phi(ctx, nir_instr_as_phi(instr));
-               break;
        case nir_instr_type_jump:
                emit_jump(ctx, nir_instr_as_jump(instr));
                break;
+       case nir_instr_type_phi:
+               /* we have converted phi webs to regs in NIR by now */
+               compile_error(ctx, "Unexpected NIR instruction type: %d\n", instr->type);
+               break;
        case nir_instr_type_call:
        case nir_instr_type_parallel_copy:
                compile_error(ctx, "Unhandled NIR instruction type: %d\n", instr->type);
@@ -3180,10 +3123,6 @@ emit_instructions(struct ir3_context *ctx)
        /* And emit the body: */
        ctx->impl = fxn;
        emit_function(ctx, fxn);
-
-       list_for_each_entry (struct ir3_block, block, &ctx->ir->block_list, node) {
-               resolve_phis(ctx, block);
-       }
 }
 
 /* from NIR perspective, we actually have inputs.  But most of the "inputs"
index 2bf41e722b636cb346c8c69f99fd1c11658e301d..ca4ced734837bd53d0de3ccc68a78b0328f219b9 100644 (file)
@@ -67,13 +67,7 @@ static bool is_eligible_mov(struct ir3_instruction *instr, bool allow_flags)
                /* TODO: remove this hack: */
                if (src_instr->opc == OPC_META_FO)
                        return false;
-               /* TODO: we currently don't handle left/right neighbors
-                * very well when inserting parallel-copies into phi..
-                * to avoid problems don't eliminate a mov coming out
-                * of phi..
-                */
-               if (src_instr->opc == OPC_META_PHI)
-                       return false;
+
                return true;
        }
        return false;
@@ -328,12 +322,6 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
 {
        struct ir3_instruction *src = ssa(reg);
 
-       /* don't propagate copies into a PHI, since we don't know if the
-        * src block executed:
-        */
-       if (instr->opc == OPC_META_PHI)
-               return;
-
        if (is_eligible_mov(src, true)) {
                /* simple case, no immed/const/relativ, only mov's w/ ssa src: */
                struct ir3_register *src_reg = src->regs[1];
index 961fae5c1e96c645a30d5a16c8ba8086d0277225..fecb89ff34b827f12d6471ec5bafd9fb818da85b 100644 (file)
@@ -133,10 +133,6 @@ restart:
                        conflict = conflicts(instr->cp.left, left) ||
                                conflicts(instr->cp.right, right);
 
-                       /* RA can't yet deal very well w/ group'd phi's: */
-                       if (instr->opc == OPC_META_PHI)
-                               conflict = true;
-
                        /* Mixing array elements and higher register classes
                         * (ie. groups) doesn't really work out in RA.  See:
                         *
index c399c69ea2a3b5c11f1e1ef0c313accb4ca5370a..0b0a66b20911a52dcf6ebb3325068d13838dfdcf 100644 (file)
@@ -50,20 +50,13 @@ static void print_instr_name(struct ir3_instruction *instr)
                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_FO:     printf("_meta:fo");   break;
-                       case OPC_META_FI:     printf("_meta:fi");   break;
+               switch (instr->opc) {
+               case OPC_META_INPUT:  printf("_meta:in");   break;
+               case OPC_META_FO:     printf("_meta:fo");   break;
+               case OPC_META_FI:     printf("_meta:fi");   break;
 
-                       default: printf("_meta:%d", instr->opc); break;
-                       }
-                       break;
+               /* shouldn't hit here.. just for debugging: */
+               default: printf("_meta:%d", instr->opc);    break;
                }
        } else if (instr->opc == OPC_MOV) {
                static const char *type[] = {
index 9158aa53b7dd33d7129d8c104f7f22f7442d769d..56e9782befd1540935a80f58373fd963e331901b 100644 (file)
@@ -484,41 +484,6 @@ get_definer(struct ir3_ra_ctx *ctx, struct ir3_instruction *instr,
                d = instr;
        }
 
-       if (d->regs[0]->flags & IR3_REG_PHI_SRC) {
-               struct ir3_instruction *phi = d->regs[0]->instr;
-               struct ir3_instruction *dd;
-               int dsz, doff;
-
-               dd = get_definer(ctx, phi, &dsz, &doff);
-
-               *sz = MAX2(*sz, dsz);
-               *off = doff;
-
-               if (instr_before(dd, d)) {
-                       d = dd;
-               }
-       }
-
-       if (d->opc == OPC_META_PHI) {
-               /* we have already inserted parallel-copies into
-                * the phi, so we don't need to chase definers
-                */
-               struct ir3_register *src;
-               struct ir3_instruction *dd = d;
-
-               /* note: don't use foreach_ssa_src as this gets called once
-                * while assigning regs (which clears SSA flag)
-                */
-               foreach_src(src, d) {
-                       if (!src->instr)
-                               continue;
-                       if (instr_before(src->instr, dd))
-                               dd = src->instr;
-               }
-
-               d = dd;
-       }
-
        if (d->opc == OPC_META_FO) {
                struct ir3_instruction *dd;
                int dsz, doff;
@@ -713,13 +678,7 @@ ra_block_compute_live_ranges(struct ir3_ra_ctx *ctx, struct ir3_block *block)
                 *     to texture sample instructions;  We consider these to be
                 *     defined at the earliest fanin source.
                 *
-                * phi: used to merge values from different flow control paths
-                *     to the same reg.  Consider defined at earliest phi src,
-                *     and update all the other phi src's (which may come later
-                *     in the program) as users to extend the var's live range.
-                *
-                * Most of this, other than phi, is completely handled in the
-                * get_definer() helper.
+                * Most of this is handled in the get_definer() helper.
                 *
                 * In either case, we trace the instruction back to the original
                 * definer and consider that as the def/use ip.
@@ -734,8 +693,6 @@ ra_block_compute_live_ranges(struct ir3_ra_ctx *ctx, struct ir3_block *block)
                                        ir3_lookup_array(ctx->ir, dst->array.id);
                                unsigned i;
 
-                               debug_assert(!(dst->flags & IR3_REG_PHI_SRC));
-
                                arr->start_ip = MIN2(arr->start_ip, instr->ip);
                                arr->end_ip = MAX2(arr->end_ip, instr->ip);
 
@@ -780,24 +737,6 @@ ra_block_compute_live_ranges(struct ir3_ra_ctx *ctx, struct ir3_block *block)
                                        ra_set_node_class(ctx->g, name,
                                                        ctx->set->classes[id->cls]);
                                }
-
-                               /* extend the live range for phi srcs, which may come
-                                * from the bottom of the loop
-                                */
-                               if (id->defn->regs[0]->flags & IR3_REG_PHI_SRC) {
-                                       struct ir3_instruction *phi = id->defn->regs[0]->instr;
-                                       foreach_ssa_src(src, phi) {
-                                               /* if src is after phi, then we need to extend
-                                                * the liverange to the end of src's block:
-                                                */
-                                               if (src->ip > phi->ip) {
-                                                       struct ir3_instruction *last =
-                                                                       list_last_entry(&src->block->instr_list,
-                                                                                       struct ir3_instruction, node);
-                                                       ctx->use[name] = MAX2(ctx->use[name], last->ip);
-                                               }
-                                       }
-                               }
                        }
                }
 
@@ -1064,7 +1003,7 @@ reg_assign(struct ir3_ra_ctx *ctx, struct ir3_register *reg,
                        num += FIRST_HIGH_REG;
 
                reg->num = num;
-               reg->flags &= ~(IR3_REG_SSA | IR3_REG_PHI_SRC);
+               reg->flags &= ~IR3_REG_SSA;
 
                if (is_half(id->defn))
                        reg->flags |= IR3_REG_HALF;
index cbb213d7738b4f9ccc1e0058b34b16ca7d77112a..72bd0b2ce0701538bf1f95b911a1167de737e4ba 100644 (file)
@@ -516,12 +516,12 @@ sched_block(struct ir3_sched_ctx *ctx, struct ir3_block *block)
        list_inithead(&block->instr_list);
        list_inithead(&ctx->depth_list);
 
-       /* first a pre-pass to schedule all meta:input/phi instructions
+       /* first a pre-pass to schedule all meta:input instructions
         * (which need to appear first so that RA knows the register is
         * occupied), and move remaining to depth sorted list:
         */
        list_for_each_entry_safe (struct ir3_instruction, instr, &unscheduled_list, node) {
-               if ((instr->opc == OPC_META_INPUT) || (instr->opc == OPC_META_PHI)) {
+               if (instr->opc == OPC_META_INPUT) {
                        schedule(ctx, instr);
                } else {
                        ir3_insert_by_depth(instr, &ctx->depth_list);
@@ -633,46 +633,10 @@ sched_block(struct ir3_sched_ctx *ctx, struct ir3_block *block)
         */
 }
 
-/* this is needed to ensure later RA stage succeeds: */
-static void
-sched_insert_parallel_copies(struct ir3_block *block)
-{
-       list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
-               if (instr->opc == OPC_META_PHI) {
-                       struct ir3_register *reg, *reg2;
-                       foreach_src(reg, instr) {
-                               struct ir3_instruction *src = reg->instr;
-                               struct ir3_instruction *mov = NULL;
-
-                               /* after CP we could end up w/ duplicate phi srcs: */
-                               foreach_src(reg2, instr) {
-                                       if (reg == reg2)
-                                               break;
-                                       /* reg2 is before reg1 so already an inserted mov: */
-                                       else if (reg2->instr->regs[1]->instr == src) {
-                                               mov = reg2->instr;
-                                               break;
-                                       }
-                               }
-
-                               if (!mov) {
-                                       mov = ir3_MOV(src->block, src, TYPE_U32);
-                                       mov->regs[0]->flags |= IR3_REG_PHI_SRC;
-                                       mov->regs[0]->instr = instr;
-                               }
-
-                               reg->instr = mov;
-                       }
-               }
-       }
-}
-
 int ir3_sched(struct ir3 *ir)
 {
        struct ir3_sched_ctx ctx = {0};
-       list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
-               sched_insert_parallel_copies(block);
-       }
+
        ir3_clear_mark(ir);
        list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
                sched_block(&ctx, block);