freedreno: move shader-stage dirty bits to global dirty flag
[mesa.git] / src / gallium / drivers / freedreno / ir3 / ir3_sched.c
index 6aaa16edbfe5b9255635005d4d4fde92c093aad3..b56da304f9289e2350ed156b8717262b1e210c5c 100644 (file)
@@ -187,6 +187,9 @@ delay_calc(struct ir3_sched_ctx *ctx, struct ir3_instruction *instr)
 
        foreach_ssa_src_n(src, i, instr) {
                unsigned d;
+               /* for array writes, no need to delay on previous write: */
+               if (i == 0)
+                       continue;
                if (src->block != instr->block)
                        continue;
                d = delay_calc_srcn(ctx, src, instr, i);
@@ -508,8 +511,7 @@ sched_block(struct ir3_sched_ctx *ctx, struct ir3_block *block)
         * occupied), and move remaining to depth sorted list:
         */
        list_for_each_entry_safe (struct ir3_instruction, instr, &unscheduled_list, node) {
-               if (is_meta(instr) && ((instr->opc == OPC_META_INPUT) ||
-                               (instr->opc == OPC_META_PHI))) {
+               if ((instr->opc == OPC_META_INPUT) || (instr->opc == OPC_META_PHI)) {
                        schedule(ctx, instr);
                } else {
                        ir3_insert_by_depth(instr, &ctx->depth_list);
@@ -624,14 +626,29 @@ static void
 sched_insert_parallel_copies(struct ir3_block *block)
 {
        list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
-               if (is_meta(instr) && (instr->opc == OPC_META_PHI)) {
-                       struct ir3_register *reg;
+               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 =
-                                       ir3_MOV(src->block, src, TYPE_U32);
-                               mov->regs[0]->flags |= IR3_REG_PHI_SRC;
-                               mov->regs[0]->instr = 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;
                        }
                }