[Mesa-dev] [PATCH v3 07/24] i965/fs: generalize the legalization d2x pass

Samuel Iglesias Gonsálvez siglesias at igalia.com
Tue Feb 14 13:00:52 UTC 2017


Add support to SEL instruction and add an assert to detect unsupported
instructions than do d2x conversions.

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
---

Curro, this patch legalizes SEL instruction too. If other optimizations
modify later any SEL's (or any other instruction's) destination type
(hence, producing a non-lowered d2x conversion), we can call it again
around the end of fs_visitor::optimize(). Possibly together with
lower_simd_width() just in case it was added later.

For that reason there is the inst->dst.stride > 1 condition in the
test. This detects if either we emitted a strided destination in
purpose or it was as a result of a previous lower_d2x run, we don't
want to lowered it.

However, as I have not hit that case yet, I prefer to wait for your
opinion. What do you think?


 src/mesa/drivers/dri/i965/brw_fs_lower_d2x.cpp | 57 ++++++++++++++++++--------
 1 file changed, 41 insertions(+), 16 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_lower_d2x.cpp b/src/mesa/drivers/dri/i965/brw_fs_lower_d2x.cpp
index a2db1154615..330f2552929 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_lower_d2x.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_lower_d2x.cpp
@@ -33,17 +33,9 @@ fs_visitor::lower_d2x()
    bool progress = false;
 
    foreach_block_and_inst_safe(block, fs_inst, inst, cfg) {
-      if (inst->opcode != BRW_OPCODE_MOV)
-         continue;
-
-      if (inst->dst.type != BRW_REGISTER_TYPE_F &&
-          inst->dst.type != BRW_REGISTER_TYPE_D &&
-          inst->dst.type != BRW_REGISTER_TYPE_UD)
-         continue;
-
-      if (inst->src[0].type != BRW_REGISTER_TYPE_DF &&
-          inst->src[0].type != BRW_REGISTER_TYPE_UQ &&
-          inst->src[0].type != BRW_REGISTER_TYPE_Q)
+      if (get_exec_type_size(inst) != 8 ||
+          type_sz(inst->dst.type) >= get_exec_type_size(inst) ||
+          inst->dst.stride > 1)
          continue;
 
       assert(inst->dst.file == VGRF);
@@ -61,13 +53,46 @@ fs_visitor::lower_d2x()
        * So we need to allocate a temporary that's two registers, and then do
        * a strided MOV to get the lower DWord of every Qword that has the
        * result.
+       *
+       * This pass legalizes all the DF conversions to narrower types.
        */
-      fs_reg temp = ibld.vgrf(inst->src[0].type, 1);
-      fs_reg strided_temp = subscript(temp, inst->dst.type, 0);
-      ibld.MOV(strided_temp, inst->src[0]);
-      ibld.MOV(dst, strided_temp);
+      switch (inst->opcode) {
+      case SHADER_OPCODE_MOV_INDIRECT:
+      case BRW_OPCODE_MOV: {
+         fs_reg temp = ibld.vgrf(inst->src[0].type, 1);
+         fs_reg strided_temp = subscript(temp, inst->dst.type, 0);
+         /* We clone the original instruction as we are going to modify it
+          * and emit another one after it.
+          */
+         fs_inst *strided_inst = new(ibld.shader->mem_ctx) fs_inst(*inst);
+         strided_inst->dst = strided_temp;
+         /* As it is an strided destination, we write n-times more
+          * being n the size difference between source and destination types.
+          */
+         strided_inst->size_written *= (type_sz(inst->src[0].type) / type_sz(inst->dst.type));
+         ibld.emit(strided_inst);
+         ibld.MOV(dst, strided_temp);
+         /* Remove original instruction, now that is superseded. */
+         inst->remove(block);
+         break;
+      }
+      case BRW_OPCODE_SEL: {
+         fs_reg temp0 = ibld.vgrf(inst->src[0].type, 1);
+         fs_reg strided_temp0 = subscript(temp0, inst->dst.type, 0);
+         fs_reg temp1 = ibld.vgrf(inst->src[1].type, 1);
+         fs_reg strided_temp1 = subscript(temp1, inst->dst.type, 0);
 
-      inst->remove(block);
+         /* Let's convert the operands to the destination type first */
+         ibld.MOV(strided_temp0, inst->src[0]);
+         ibld.MOV(strided_temp1, inst->src[1]);
+         inst->src[0] = strided_temp0;
+         inst->src[1] = strided_temp1;
+         break;
+      }
+      default:
+         /* FIXME: If this is not a supported instruction, then we need to support it. */
+         unreachable("Not supported instruction");
+      }
       progress = true;
    }
 
-- 
2.11.0



More information about the mesa-dev mailing list