freedreno/ir3: split out regmask
[mesa.git] / src / freedreno / ir3 / ir3_postsched.c
index 3dc4505c52da5fcb9add3ddcc106580f6f921ce9..ad2c9a6c529b33204574b4a192298523e0672ce6 100644 (file)
@@ -51,7 +51,9 @@
  */
 
 struct ir3_postsched_ctx {
-       struct ir3_context *ctx;
+       struct ir3 *ir;
+
+       struct ir3_shader_variant *v;
 
        void *mem_ctx;
        struct ir3_block *block;           /* the current block */
@@ -59,9 +61,8 @@ struct ir3_postsched_ctx {
 
        struct list_head unscheduled_list; /* unscheduled instructions */
 
-       bool error;
-
        int sfu_delay;
+       int tex_delay;
 };
 
 struct ir3_postsched_node {
@@ -92,14 +93,27 @@ schedule(struct ir3_postsched_ctx *ctx, struct ir3_instruction *instr)
 
        list_addtail(&instr->node, &instr->block->instr_list);
 
+       struct ir3_postsched_node *n = instr->data;
+       dag_prune_head(ctx->dag, &n->dag);
+
+       if (is_meta(instr) && (instr->opc != OPC_META_TEX_PREFETCH))
+               return;
+
        if (is_sfu(instr)) {
                ctx->sfu_delay = 8;
+       } else if (check_src_cond(instr, is_sfu)) {
+               ctx->sfu_delay = 0;
        } else if (ctx->sfu_delay > 0) {
                ctx->sfu_delay--;
        }
 
-       struct ir3_postsched_node *n = instr->data;
-       dag_prune_head(ctx->dag, &n->dag);
+       if (is_tex_or_prefetch(instr)) {
+               ctx->tex_delay = 10;
+       } else if (check_src_cond(instr, is_tex_or_prefetch)) {
+               ctx->tex_delay = 0;
+       } else if (ctx->tex_delay > 0) {
+               ctx->tex_delay--;
+       }
 }
 
 static void
@@ -129,10 +143,13 @@ static bool
 would_sync(struct ir3_postsched_ctx *ctx, struct ir3_instruction *instr)
 {
        if (ctx->sfu_delay) {
-               struct ir3_register *reg;
-               foreach_src (reg, instr)
-                       if (reg->instr && is_sfu(reg->instr))
-                               return true;
+               if (check_src_cond(instr, is_sfu))
+                       return true;
+       }
+
+       if (ctx->tex_delay) {
+               if (check_src_cond(instr, is_tex_or_prefetch))
+                       return true;
        }
 
        return false;
@@ -300,7 +317,7 @@ choose_instr(struct ir3_postsched_ctx *ctx)
 }
 
 struct ir3_postsched_deps_state {
-       struct ir3_context *ctx;
+       struct ir3_postsched_ctx *ctx;
 
        enum { F, R } direction;
 
@@ -385,7 +402,6 @@ static void
 calculate_deps(struct ir3_postsched_deps_state *state,
                struct ir3_postsched_node *node)
 {
-       struct ir3_register *reg;
        int b;
 
        /* Add dependencies on instructions that previously (or next,
@@ -426,7 +442,7 @@ calculate_deps(struct ir3_postsched_deps_state *state,
        /* And then after we update the state for what this instruction
         * wrote:
         */
-       reg = node->instr->regs[0];
+       struct ir3_register *reg = node->instr->regs[0];
        if (reg->flags & IR3_REG_RELATIV) {
                /* mark the entire array as written: */
                struct ir3_array *arr = ir3_lookup_array(state->ctx->ir, reg->array.id);
@@ -444,9 +460,9 @@ static void
 calculate_forward_deps(struct ir3_postsched_ctx *ctx)
 {
        struct ir3_postsched_deps_state state = {
-                       .ctx = ctx->ctx,
+                       .ctx = ctx,
                        .direction = F,
-                       .merged = ctx->ctx->compiler->gpu_id >= 600,
+                       .merged = ctx->v->mergedregs,
        };
 
        foreach_instr (instr, &ctx->unscheduled_list) {
@@ -458,9 +474,9 @@ static void
 calculate_reverse_deps(struct ir3_postsched_ctx *ctx)
 {
        struct ir3_postsched_deps_state state = {
-                       .ctx = ctx->ctx,
+                       .ctx = ctx,
                        .direction = R,
-                       .merged = ctx->ctx->compiler->gpu_id >= 600,
+                       .merged = ctx->v->mergedregs,
        };
 
        foreach_instr_rev (instr, &ctx->unscheduled_list) {
@@ -506,6 +522,14 @@ sched_dag_init(struct ir3_postsched_ctx *ctx)
        calculate_forward_deps(ctx);
        calculate_reverse_deps(ctx);
 
+       /*
+        * To avoid expensive texture fetches, etc, from being moved ahead
+        * of kills, track the kills we've seen so far, so we can add an
+        * extra dependency on them for tex/mem instructions
+        */
+       struct util_dynarray kills;
+       util_dynarray_init(&kills, ctx->mem_ctx);
+
        /*
         * Normal srcs won't be in SSA at this point, those are dealt with in
         * calculate_forward_deps() and calculate_reverse_deps().  But we still
@@ -514,7 +538,6 @@ sched_dag_init(struct ir3_postsched_ctx *ctx)
         */
        foreach_instr (instr, &ctx->unscheduled_list) {
                struct ir3_postsched_node *n = instr->data;
-               struct ir3_instruction *src;
 
                foreach_ssa_src_n (src, i, instr) {
                        if (src->block != instr->block)
@@ -532,6 +555,16 @@ sched_dag_init(struct ir3_postsched_ctx *ctx)
 
                        dag_add_edge(&sn->dag, &n->dag, NULL);
                }
+
+               if (is_kill(instr)) {
+                       util_dynarray_append(&kills, struct ir3_instruction *, instr);
+               } else if (is_tex(instr) || is_mem(instr)) {
+                       util_dynarray_foreach(&kills, struct ir3_instruction *, instrp) {
+                               struct ir3_instruction *kill = *instrp;
+                               struct ir3_postsched_node *kn = kill->data;
+                               dag_add_edge(&kn->dag, &n->dag, NULL);
+                       }
+               }
        }
 
        // TODO do we want to do this after reverse-dependencies?
@@ -550,6 +583,8 @@ static void
 sched_block(struct ir3_postsched_ctx *ctx, struct ir3_block *block)
 {
        ctx->block = block;
+       ctx->tex_delay = 0;
+       ctx->sfu_delay = 0;
 
        /* move all instructions to the unscheduled list, and
         * empty the block's instruction list (to which we will
@@ -564,7 +599,7 @@ sched_block(struct ir3_postsched_ctx *ctx, struct ir3_block *block)
        foreach_instr_safe (instr, &ctx->unscheduled_list) {
                switch (instr->opc) {
                case OPC_NOP:
-               case OPC_BR:
+               case OPC_B:
                case OPC_JUMP:
                        list_delinit(&instr->node);
                        break;
@@ -593,15 +628,7 @@ sched_block(struct ir3_postsched_ctx *ctx, struct ir3_block *block)
                        schedule(ctx, instr);
 
        while (!list_is_empty(&ctx->unscheduled_list)) {
-               struct ir3_instruction *instr;
-
-               instr = choose_instr(ctx);
-
-               /* this shouldn't happen: */
-               if (!instr) {
-                       ctx->error = true;
-                       break;
-               }
+               struct ir3_instruction *instr = choose_instr(ctx);
 
                unsigned delay = ir3_delay_calc(ctx->block, instr, false, false);
                d("delay=%u", delay);
@@ -654,7 +681,6 @@ cleanup_self_movs(struct ir3 *ir)
 {
        foreach_block (block, &ir->block_list) {
                foreach_instr_safe (instr, &block->instr_list) {
-                       struct ir3_register *reg;
 
                        foreach_src (reg, instr) {
                                if (!reg->instr)
@@ -667,7 +693,7 @@ cleanup_self_movs(struct ir3 *ir)
                        }
 
                        for (unsigned i = 0; i < instr->deps_count; i++) {
-                               if (is_self_mov(instr->deps[i])) {
+                               if (instr->deps[i] && is_self_mov(instr->deps[i])) {
                                        list_delinit(&instr->deps[i]->node);
                                        instr->deps[i] = instr->deps[i]->regs[1]->instr;
                                }
@@ -676,22 +702,20 @@ cleanup_self_movs(struct ir3 *ir)
        }
 }
 
-int
-ir3_postsched(struct ir3_context *cctx)
+bool
+ir3_postsched(struct ir3 *ir, struct ir3_shader_variant *v)
 {
        struct ir3_postsched_ctx ctx = {
-                       .ctx = cctx,
+                       .ir = ir,
+                       .v  = v,
        };
 
-       ir3_remove_nops(cctx->ir);
-       cleanup_self_movs(cctx->ir);
+       ir3_remove_nops(ir);
+       cleanup_self_movs(ir);
 
-       foreach_block (block, &cctx->ir->block_list) {
+       foreach_block (block, &ir->block_list) {
                sched_block(&ctx, block);
        }
 
-       if (ctx.error)
-               return -1;
-
-       return 0;
+       return true;
 }