[Mesa-dev] [PATCH 062/133] nir: Differentiate between signed and unsigned versions of find_msb

Jason Ekstrand jason at jlekstrand.net
Mon Dec 15 22:05:12 PST 2014


We also make the return types match GLSL.  The GLSL spec specifies that
findMSB and findLSB return a signed integer.  Previously, nir had them
return unsigned.  This updates nir's behavior to match what GLSL expects.

We also update the nir-to-fs generator to take the new instructions.  While
we're at it, we fix the case where the input to findMSB is zero.
---
 src/glsl/nir/glsl_to_nir.cpp             | 22 +++++++++++++++++++---
 src/glsl/nir/nir_opcodes.h               |  5 +++--
 src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 14 ++++++++------
 3 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp
index d6306e7..240a2c1 100644
--- a/src/glsl/nir/glsl_to_nir.cpp
+++ b/src/glsl/nir/glsl_to_nir.cpp
@@ -1128,9 +1128,25 @@ nir_visitor::visit(ir_expression *ir)
    case ir_unop_bitfield_reverse:
       emit(nir_op_bitfield_reverse, dest_size, srcs);
       break;
-   case ir_unop_bit_count: emit(nir_op_bit_count, dest_size, srcs); break;
-   case ir_unop_find_msb:  emit(nir_op_find_msb,  dest_size, srcs); break;
-   case ir_unop_find_lsb:  emit(nir_op_find_lsb,  dest_size, srcs); break;
+   case ir_unop_bit_count:
+      emit(nir_op_bit_count, dest_size, srcs);
+      break;
+   case ir_unop_find_msb:
+      switch (types[0]) {
+      case GLSL_TYPE_UINT:
+         emit(nir_op_ufind_msb, dest_size, srcs);
+         break;
+      case GLSL_TYPE_INT:
+         emit(nir_op_ifind_msb, dest_size, srcs);
+         break;
+      default:
+         unreachable("Invalid type for findMSB()");
+      }
+      break;
+   case ir_unop_find_lsb:
+      emit(nir_op_find_lsb,  dest_size, srcs);
+      break;
+
    case ir_unop_noise:
       switch (ir->type->vector_elements) {
       case 1:
diff --git a/src/glsl/nir/nir_opcodes.h b/src/glsl/nir/nir_opcodes.h
index 9a7a2ab..988f691 100644
--- a/src/glsl/nir/nir_opcodes.h
+++ b/src/glsl/nir/nir_opcodes.h
@@ -147,8 +147,9 @@ UNOP_HORIZ(unpack_half_2x16_split_y, 1, nir_type_float, 1, nir_type_unsigned)
 /*@{*/
 UNOP(bitfield_reverse, nir_type_unsigned)
 UNOP(bit_count, nir_type_unsigned)
-UNOP(find_msb, nir_type_unsigned)
-UNOP(find_lsb, nir_type_unsigned)
+UNOP_CONVERT(ufind_msb, nir_type_unsigned, nir_type_int)
+UNOP(ifind_msb, nir_type_int)
+UNOP(find_lsb, nir_type_int)
 /*@}*/
 
 UNOP_HORIZ(fnoise1_1, 1, nir_type_float, 1, nir_type_float)
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index 1fac9a0..561c709 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -877,19 +877,21 @@ fs_visitor::nir_emit_alu(nir_alu_instr *instr)
       emit_percomp(CBIT(result, op[0]), instr->dest.write_mask);
       break;
 
-   case nir_op_find_msb: {
-      fs_reg temp = fs_reg(this, glsl_type::uvec4_type);
-      emit_percomp(FBH(temp, op[0]), instr->dest.write_mask);
+   case nir_op_ufind_msb:
+   case nir_op_ifind_msb: {
+      emit_percomp(FBH(retype(result, BRW_REGISTER_TYPE_UD), op[0]),
+                   instr->dest.write_mask);
 
       /* FBH counts from the MSB side, while GLSL's findMSB() wants the count
        * from the LSB side. If FBH didn't return an error (0xFFFFFFFF), then
        * subtract the result from 31 to convert the MSB count into an LSB count.
        */
 
-      emit_percomp(CMP(reg_null_d, temp, fs_reg(~0), BRW_CONDITIONAL_NZ),
+      emit_percomp(CMP(reg_null_d, result, fs_reg(-1), BRW_CONDITIONAL_NZ),
                    instr->dest.write_mask);
-      temp.negate = true;
-      fs_inst *inst = ADD(result, temp, fs_reg(31));
+      fs_reg neg_result(result);
+      neg_result.negate = true;
+      fs_inst *inst = ADD(result, neg_result, fs_reg(31));
       inst->predicate = BRW_PREDICATE_NORMAL;
       emit_percomp(inst, instr->dest.write_mask);
       break;
-- 
2.2.0



More information about the mesa-dev mailing list