i965/fs: Fix register spilling for 16-wide.
authorEric Anholt <eric@anholt.net>
Wed, 16 Oct 2013 19:16:51 +0000 (12:16 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 31 Oct 2013 00:51:10 +0000 (17:51 -0700)
Things blew up when I enabled the debug register spill code without
disabling 16-wide, so I decided to just fix 16-wide spilling.

We still don't generate 16-wide when register spilling happens as part of
allocation (since we expect it to be slower), but now we can experiment
with allowing it in some cases in the future.

Reviewed-by: Paul Berry <stereotype441@gmail.com>
src/mesa/drivers/dri/i965/brw_fs_generator.cpp
src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp

index ef858370dbb7a9f8d27e095d9fe3237c0cb39095..e16d8748ede54553ea61057336b3d95d09009676 100644 (file)
@@ -756,8 +756,8 @@ fs_generator::generate_spill(fs_inst *inst, struct brw_reg src)
    brw_MOV(p,
           retype(brw_message_reg(inst->base_mrf + 1), BRW_REGISTER_TYPE_UD),
           retype(src, BRW_REGISTER_TYPE_UD));
-   brw_oword_block_write_scratch(p, brw_message_reg(inst->base_mrf), 1,
-                                inst->offset);
+   brw_oword_block_write_scratch(p, brw_message_reg(inst->base_mrf),
+                                 inst->mlen, inst->offset);
 }
 
 void
@@ -765,8 +765,8 @@ fs_generator::generate_unspill(fs_inst *inst, struct brw_reg dst)
 {
    assert(inst->mlen != 0);
 
-   brw_oword_block_read_scratch(p, dst, brw_message_reg(inst->base_mrf), 1,
-                               inst->offset);
+   brw_oword_block_read_scratch(p, dst, brw_message_reg(inst->base_mrf),
+                                dispatch_width / 8, inst->offset);
 }
 
 void
index 35dae8432906600b4efc5ecc51390b83380d6b4f..64fb78b6bdd41c5a85a647ef0aadda96e1ab076d 100644 (file)
@@ -547,15 +547,12 @@ fs_visitor::emit_unspill(fs_inst *inst, fs_reg dst, uint32_t spill_offset,
       unspill_inst->ir = inst->ir;
       unspill_inst->annotation = inst->annotation;
 
-      /* Choose a MRF that won't conflict with an MRF that's live across the
-       * spill.  Nothing else will make it up to MRF 14/15.
-       */
       unspill_inst->base_mrf = 14;
       unspill_inst->mlen = 1; /* header contains offset */
       inst->insert_before(unspill_inst);
 
       dst.reg_offset++;
-      spill_offset += REG_SIZE;
+      spill_offset += dispatch_width * sizeof(float);
    }
 }
 
@@ -639,10 +636,10 @@ fs_visitor::choose_spill_reg(struct ra_graph *g)
 void
 fs_visitor::spill_reg(int spill_reg)
 {
+   int reg_size = dispatch_width * sizeof(float);
    int size = virtual_grf_sizes[spill_reg];
    unsigned int spill_offset = c->last_scratch;
    assert(ALIGN(spill_offset, 16) == spill_offset); /* oword read/write req. */
-   c->last_scratch += size * REG_SIZE;
    int spill_base_mrf = dispatch_width > 8 ? 13 : 14;
 
    /* Spills may use MRFs 13-15 in the SIMD16 case.  Our texturing is done
@@ -666,6 +663,8 @@ fs_visitor::spill_reg(int spill_reg)
       spilled_any_registers = true;
    }
 
+   c->last_scratch += size * reg_size;
+
    /* Generate spill/unspill instructions for the objects being
     * spilled.  Right now, we spill or unspill the whole thing to a
     * virtual grf of the same size.  For most instructions, though, we
@@ -683,7 +682,7 @@ fs_visitor::spill_reg(int spill_reg)
             inst->src[i].reg_offset = 0;
 
             emit_unspill(inst, inst->src[i],
-                         spill_offset + REG_SIZE * inst->src[i].reg_offset,
+                         spill_offset + reg_size * inst->src[i].reg_offset,
                          regs_read);
         }
       }
@@ -691,7 +690,7 @@ fs_visitor::spill_reg(int spill_reg)
       if (inst->dst.file == GRF &&
          inst->dst.reg == spill_reg) {
          int subset_spill_offset = (spill_offset +
-                                    REG_SIZE * inst->dst.reg_offset);
+                                    reg_size * inst->dst.reg_offset);
          inst->dst.reg = virtual_grf_alloc(inst->regs_written);
          inst->dst.reg_offset = 0;
 
@@ -714,11 +713,11 @@ fs_visitor::spill_reg(int spill_reg)
            fs_inst *spill_inst = new(mem_ctx) fs_inst(FS_OPCODE_SPILL,
                                                       reg_null_f, spill_src);
            spill_src.reg_offset++;
-           spill_inst->offset = subset_spill_offset + chan * REG_SIZE;
+           spill_inst->offset = subset_spill_offset + chan * reg_size;
            spill_inst->ir = inst->ir;
            spill_inst->annotation = inst->annotation;
-           spill_inst->base_mrf = 14;
-           spill_inst->mlen = 2; /* header, value */
+           spill_inst->mlen = 1 + dispatch_width / 8; /* header, value */
+           spill_inst->base_mrf = spill_base_mrf;
            inst->insert_after(spill_inst);
         }
       }