[Mesa-dev] [PATCH 17/24] i965: Use LZD to implement nir_op_find_lsb on Gen < 7

Ian Romanick idr at freedesktop.org
Wed Jun 29 21:04:24 UTC 2016


From: Ian Romanick <ian.d.romanick at intel.com>

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/mesa/drivers/dri/i965/brw_fs_nir.cpp   | 22 +++++++++++++++++++++-
 src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 21 ++++++++++++++++++++-
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index f8db28a..562b06d 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -1385,7 +1385,27 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr)
 
    case nir_op_find_lsb:
       assert(nir_dest_bit_size(instr->dest.dest) < 64);
-      bld.FBL(result, op[0]);
+
+      if (devinfo->gen < 7) {
+         fs_reg temp = vgrf(glsl_type::int_type);
+
+         /* (x & -x) generates a value that consists of only the LSB of x.
+          * For all powers of 2, findMSB(y) == findLSB(y).
+          */
+         fs_reg src = retype(op[0], BRW_REGISTER_TYPE_D);
+         fs_reg negated_src = src;
+
+         /* One must be negated, and the other must be non-negated.  It
+          * doesn't matter which is which.
+          */
+         negated_src.negate = true;
+         src.negate = false;
+
+         bld.AND(temp, src, negated_src);
+         nir_emit_find_msb_using_lzd(bld, result, temp, false);
+      } else {
+         bld.FBL(result, op[0]);
+      }
       break;
 
    case nir_op_ubitfield_extract:
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
index 2fc2cf2..a25ccba 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
@@ -1530,7 +1530,26 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr)
    }
 
    case nir_op_find_lsb:
-      emit(FBL(dst, op[0]));
+      if (devinfo->gen < 7) {
+         src_reg temp = src_reg(this, glsl_type::ivec4_type);
+
+         /* (x & -x) generates a value that consists of only the LSB of x.
+          * For all powers of 2, findMSB(y) == findLSB(y).
+          */
+         src_reg src = src_reg(retype(op[0], BRW_REGISTER_TYPE_D));
+         src_reg negated_src = src;
+
+         /* One must be negated, and the other must be non-negated.  It
+          * doesn't matter which is which.
+          */
+         negated_src.negate = true;
+         src.negate = false;
+
+         emit(AND(dst_reg(temp), src, negated_src));
+         nir_emit_find_msb_using_lzd(dst, temp, false);
+      } else {
+         emit(FBL(dst, op[0]));
+      }
       break;
 
    case nir_op_ubitfield_extract:
-- 
2.5.5



More information about the mesa-dev mailing list