freedreno/ir3: make input/output iterators declare cursor ptr
[mesa.git] / src / freedreno / ir3 / ir3_compiler_nir.c
index dc2492e242aa7ba817e58ba85d138a0e0f066b27..b3e23db243ede0c4b6050481d1ed1dfe950a9536 100644 (file)
@@ -430,9 +430,14 @@ emit_alu(struct ir3_context *ctx, nir_alu_instr *alu)
                 * src instruction and create a mov.  This is easier for cp
                 * to eliminate.
                 *
+                * NOTE: a3xx definitely seen not working with flat bary.f. Same test
+                * uses ldlv on a4xx+, so not definitive. Seems rare enough to apply
+                * everywhere.
+                *
                 * TODO probably opc_cat==4 is ok too
                 */
                if (alu->src[0].src.is_ssa &&
+                               src[0]->opc != OPC_BARY_F &&
                                (list_length(&alu->src[0].src.ssa->uses) == 1) &&
                                ((opc_cat(src[0]->opc) == 2) || (opc_cat(src[0]->opc) == 3))) {
                        src[0]->flags |= IR3_INSTR_SAT;
@@ -878,40 +883,26 @@ emit_intrinsic_store_shared(struct ir3_context *ctx, nir_intrinsic_instr *intr)
        struct ir3_block *b = ctx->block;
        struct ir3_instruction *stl, *offset;
        struct ir3_instruction * const *value;
-       unsigned base, wrmask;
+       unsigned base, wrmask, ncomp;
 
        value  = ir3_get_src(ctx, &intr->src[0]);
        offset = ir3_get_src(ctx, &intr->src[1])[0];
 
        base   = nir_intrinsic_base(intr);
        wrmask = nir_intrinsic_write_mask(intr);
+       ncomp  = ffs(~wrmask) - 1;
 
-       /* Combine groups of consecutive enabled channels in one write
-        * message. We use ffs to find the first enabled channel and then ffs on
-        * the bit-inverse, down-shifted writemask to determine the length of
-        * the block of enabled bits.
-        *
-        * (trick stolen from i965's fs_visitor::nir_emit_cs_intrinsic())
-        */
-       while (wrmask) {
-               unsigned first_component = ffs(wrmask) - 1;
-               unsigned length = ffs(~(wrmask >> first_component)) - 1;
-
-               stl = ir3_STL(b, offset, 0,
-                       ir3_create_collect(ctx, &value[first_component], length), 0,
-                       create_immed(b, length), 0);
-               stl->cat6.dst_offset = first_component + base;
-               stl->cat6.type = utype_src(intr->src[0]);
-               stl->barrier_class = IR3_BARRIER_SHARED_W;
-               stl->barrier_conflict = IR3_BARRIER_SHARED_R | IR3_BARRIER_SHARED_W;
-
-               array_insert(b, b->keeps, stl);
-
-               /* Clear the bits in the writemask that we just wrote, then try
-                * again to see if more channels are left.
-                */
-               wrmask &= (15 << (first_component + length));
-       }
+       assert(wrmask == BITFIELD_MASK(intr->num_components));
+
+       stl = ir3_STL(b, offset, 0,
+               ir3_create_collect(ctx, value, ncomp), 0,
+               create_immed(b, ncomp), 0);
+       stl->cat6.dst_offset = base;
+       stl->cat6.type = utype_src(intr->src[0]);
+       stl->barrier_class = IR3_BARRIER_SHARED_W;
+       stl->barrier_conflict = IR3_BARRIER_SHARED_R | IR3_BARRIER_SHARED_W;
+
+       array_insert(b, b->keeps, stl);
 }
 
 /* src[] = { offset }. const_index[] = { base } */
@@ -939,48 +930,27 @@ emit_intrinsic_load_shared_ir3(struct ir3_context *ctx, nir_intrinsic_instr *int
        ir3_split_dest(b, dst, load, 0, intr->num_components);
 }
 
-/* src[] = { value, offset }. const_index[] = { base, write_mask } */
+/* src[] = { value, offset }. const_index[] = { base } */
 static void
 emit_intrinsic_store_shared_ir3(struct ir3_context *ctx, nir_intrinsic_instr *intr)
 {
        struct ir3_block *b = ctx->block;
        struct ir3_instruction *store, *offset;
        struct ir3_instruction * const *value;
-       unsigned base, wrmask;
 
        value  = ir3_get_src(ctx, &intr->src[0]);
        offset = ir3_get_src(ctx, &intr->src[1])[0];
 
-       base   = nir_intrinsic_base(intr);
-       wrmask = nir_intrinsic_write_mask(intr);
-
-       /* Combine groups of consecutive enabled channels in one write
-        * message. We use ffs to find the first enabled channel and then ffs on
-        * the bit-inverse, down-shifted writemask to determine the length of
-        * the block of enabled bits.
-        *
-        * (trick stolen from i965's fs_visitor::nir_emit_cs_intrinsic())
-        */
-       while (wrmask) {
-               unsigned first_component = ffs(wrmask) - 1;
-               unsigned length = ffs(~(wrmask >> first_component)) - 1;
-
-               store = ir3_STLW(b, offset, 0,
-                       ir3_create_collect(ctx, &value[first_component], length), 0,
-                       create_immed(b, length), 0);
+       store = ir3_STLW(b, offset, 0,
+               ir3_create_collect(ctx, value, intr->num_components), 0,
+               create_immed(b, intr->num_components), 0);
 
-               store->cat6.dst_offset = first_component + base;
-               store->cat6.type = utype_src(intr->src[0]);
-               store->barrier_class = IR3_BARRIER_SHARED_W;
-               store->barrier_conflict = IR3_BARRIER_SHARED_R | IR3_BARRIER_SHARED_W;
+       store->cat6.dst_offset = nir_intrinsic_base(intr);
+       store->cat6.type = utype_src(intr->src[0]);
+       store->barrier_class = IR3_BARRIER_SHARED_W;
+       store->barrier_conflict = IR3_BARRIER_SHARED_R | IR3_BARRIER_SHARED_W;
 
-               array_insert(b, b->keeps, store);
-
-               /* Clear the bits in the writemask that we just wrote, then try
-                * again to see if more channels are left.
-                */
-               wrmask &= (15 << (first_component + length));
-       }
+       array_insert(b, b->keeps, store);
 }
 
 /*
@@ -2261,7 +2231,7 @@ emit_tex(struct ir3_context *ctx, nir_tex_instr *tex)
                compile_assert(ctx, nir_tex_instr_src_index(tex, nir_tex_src_texture_offset) < 0);
                compile_assert(ctx, nir_tex_instr_src_index(tex, nir_tex_src_sampler_offset) < 0);
 
-               if (ctx->so->num_sampler_prefetch < IR3_MAX_SAMPLER_PREFETCH) {
+               if (ctx->so->num_sampler_prefetch < ctx->prefetch_limit) {
                        opc = OPC_META_TEX_PREFETCH;
                        ctx->so->num_sampler_prefetch++;
                        break;
@@ -2993,7 +2963,7 @@ setup_input(struct ir3_context *ctx, nir_variable *in)
                        ctx->inputs[idx] = instr;
                }
        } else if (ctx->so->type == MESA_SHADER_VERTEX) {
-               struct ir3_instruction *input = NULL, *in;
+               struct ir3_instruction *input = NULL;
                struct ir3_instruction *components[4];
                unsigned mask = (1 << (ncomp + frac)) - 1;
 
@@ -3147,6 +3117,7 @@ setup_output(struct ir3_context *ctx, nir_variable *out)
                        so->writes_smask = true;
                        break;
                default:
+                       slot += out->data.index; /* For dual-src blend */
                        if (slot >= FRAG_RESULT_DATA0)
                                break;
                        ir3_context_error(ctx, "unknown FS output name: %s\n",
@@ -3391,7 +3362,6 @@ fixup_binning_pass(struct ir3_context *ctx)
                        so->outputs[j] = so->outputs[i];
 
                        /* fixup outidx to point to new output table entry: */
-                       struct ir3_instruction *out;
                        foreach_output (out, ir) {
                                if (out->collect.outidx == i) {
                                        out->collect.outidx = j;
@@ -3455,6 +3425,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
        struct ir3_context *ctx;
        struct ir3 *ir;
        int ret = 0, max_bary;
+       bool progress;
 
        assert(!so->ir);
 
@@ -3551,26 +3522,6 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
                }
        }
 
-       /* at this point, for binning pass, throw away unneeded outputs: */
-       if (so->binning_pass && (ctx->compiler->gpu_id < 600))
-               fixup_binning_pass(ctx);
-
-       ir3_debug_print(ir, "BEFORE CF");
-
-       ir3_cf(ir);
-
-       ir3_debug_print(ir, "BEFORE CP");
-
-       ir3_cp(ir, so);
-
-       /* at this point, for binning pass, throw away unneeded outputs:
-        * Note that for a6xx and later, we do this after ir3_cp to ensure
-        * that the uniform/constant layout for BS and VS matches, so that
-        * we can re-use same VS_CONST state group.
-        */
-       if (so->binning_pass && (ctx->compiler->gpu_id >= 600))
-               fixup_binning_pass(ctx);
-
        /* for a6xx+, binning and draw pass VS use same VBO state, so we
         * need to make sure not to remove any inputs that are used by
         * the nonbinning VS.
@@ -3597,23 +3548,40 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
                }
        }
 
-       ir3_debug_print(ir, "BEFORE GROUPING");
+       /* at this point, for binning pass, throw away unneeded outputs: */
+       if (so->binning_pass && (ctx->compiler->gpu_id < 600))
+               fixup_binning_pass(ctx);
 
-       ir3_sched_add_deps(ir);
+       ir3_debug_print(ir, "AFTER: nir->ir3");
 
-       /* Group left/right neighbors, inserting mov's where needed to
-        * solve conflicts:
-        */
-       ir3_group(ir);
+       do {
+               progress = false;
+
+               progress |= IR3_PASS(ir, ir3_cf);
+               progress |= IR3_PASS(ir, ir3_cp, so);
+               progress |= IR3_PASS(ir, ir3_dce, so);
+       } while (progress);
 
-       ir3_debug_print(ir, "AFTER GROUPING");
+       /* at this point, for binning pass, throw away unneeded outputs:
+        * Note that for a6xx and later, we do this after ir3_cp to ensure
+        * that the uniform/constant layout for BS and VS matches, so that
+        * we can re-use same VS_CONST state group.
+        */
+       if (so->binning_pass && (ctx->compiler->gpu_id >= 600)) {
+               fixup_binning_pass(ctx);
+               /* cleanup the result of removing unneeded outputs: */
+               while (IR3_PASS(ir, ir3_dce, so)) {}
+       }
 
-       ir3_dce(ir, so);
+       IR3_PASS(ir, ir3_sched_add_deps);
 
-       ir3_debug_print(ir, "AFTER DCE");
+       /* Group left/right neighbors, inserting mov's where needed to
+        * solve conflicts:
+        */
+       IR3_PASS(ir, ir3_group);
 
-       /* do Sethi–Ullman numbering before scheduling: */
-       ir3_sun(ir);
+       /* At this point, all the dead code should be long gone: */
+       assert(!IR3_PASS(ir, ir3_dce, so));
 
        ret = ir3_sched(ir);
        if (ret) {
@@ -3621,7 +3589,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
                goto out;
        }
 
-       ir3_debug_print(ir, "AFTER SCHED");
+       ir3_debug_print(ir, "AFTER: ir3_sched");
 
        /* Pre-assign VS inputs on a6xx+ binning pass shader, to align
         * with draw pass VS, so binning and draw pass can both use the
@@ -3669,7 +3637,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
                ret = ir3_ra(so, precolor, ARRAY_SIZE(precolor));
        } else if (so->num_sampler_prefetch) {
                assert(so->type == MESA_SHADER_FRAGMENT);
-               struct ir3_instruction *instr, *precolor[2];
+               struct ir3_instruction *precolor[2];
                int idx = 0;
 
                foreach_input (instr, ir) {
@@ -3693,13 +3661,10 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
                goto out;
        }
 
-       ir3_postsched(ctx);
-       ir3_debug_print(ir, "AFTER POSTSCHED");
+       IR3_PASS(ir, ir3_postsched);
 
        if (compiler->gpu_id >= 600) {
-               if (ir3_a6xx_fixup_atomic_dests(ir, so)) {
-                       ir3_debug_print(ir, "AFTER ATOMIC FIXUP");
-               }
+               IR3_PASS(ir, ir3_a6xx_fixup_atomic_dests, so);
        }
 
        if (so->type == MESA_SHADER_FRAGMENT)
@@ -3719,7 +3684,6 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
        for (unsigned i = 0; i < so->outputs_count; i++)
                so->outputs[i].regid = INVALID_REG;
 
-       struct ir3_instruction *out;
        foreach_output (out, ir) {
                assert(out->opc == OPC_META_COLLECT);
                unsigned outidx = out->collect.outidx;
@@ -3728,7 +3692,6 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
                so->outputs[outidx].half  = !!(out->regs[0]->flags & IR3_REG_HALF);
        }
 
-       struct ir3_instruction *in;
        foreach_input (in, ir) {
                assert(in->opc == OPC_META_INPUT);
                unsigned inidx = in->input.inidx;
@@ -3754,9 +3717,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
        /* We need to do legalize after (for frag shader's) the "bary.f"
         * offsets (inloc) have been assigned.
         */
-       ir3_legalize(ir, so, &max_bary);
-
-       ir3_debug_print(ir, "AFTER LEGALIZE");
+       IR3_PASS(ir, ir3_legalize, so, &max_bary);
 
        /* Set (ss)(sy) on first TCS and GEOMETRY instructions, since we don't
         * know what we might have to wait on when coming in from VS chsh.
@@ -3777,8 +3738,6 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
        if (so->type == MESA_SHADER_FRAGMENT)
                so->total_in = max_bary + 1;
 
-       so->max_sun = ir->max_sun;
-
        /* Collect sampling instructions eligible for pre-dispatch. */
        collect_tex_prefetches(ctx, ir);