[Mesa-dev] [PATCH 16/26] i965: Implement the new imod and irem opcodes

Jason Ekstrand jason at jlekstrand.net
Thu Apr 7 00:22:37 UTC 2016


On Fri, Mar 25, 2016 at 4:12 PM, Jason Ekstrand <jason at jlekstrand.net>
wrote:

> ---
>  src/mesa/drivers/dri/i965/brw_fs_nir.cpp   | 32
> ++++++++++++++++++++++++++++++
>  src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 32
> ++++++++++++++++++++++++++++++
>  2 files changed, 64 insertions(+)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> index 14480fb..131f50e 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> @@ -844,8 +844,40 @@ fs_visitor::nir_emit_alu(const fs_builder &bld,
> nir_alu_instr *instr)
>        unreachable("Should have been lowered by borrow_to_arith().");
>
>     case nir_op_umod:
> +   case nir_op_irem:
> +      /* According to the sign table for INT DIV in the Ivy Bridge PRM, it
> +       * appears that our hardware just does the right thing for signed
> +       * remainder.
> +       */
> +      bld.emit(SHADER_OPCODE_INT_REMAINDER, result, op[0], op[1]);
> +      break;
> +
> +   case nir_op_imod: {
> +      /* Get a regular C-style remainder.  If a % b == 0, set the
> predicate. */
>        bld.emit(SHADER_OPCODE_INT_REMAINDER, result, op[0], op[1]);
> +
> +      /* Math instructions don't support conditional mod */
> +      inst = bld.MOV(bld.null_reg_d(), result);
> +      inst->conditional_mod = BRW_CONDITIONAL_NZ;
> +
> +      /* Now, we need to determine if signs of the sources are different.
> +       * When we XOR the sources, the top bit is 0 if they are the same
> and 1
> +       * if they are different.  We can then use a conditional modifier to
> +       * turn that into a predicate.  This leads us to an XOR.l
> instruction.
>

I've added the following to this comment in both versions:

* Technically, according to the PRM, you're not allowed to use .l on a
* XOR instruction.  However, emperical experiments and Curro's reading
* of the simulator source both indicate that it's safe.



> +       */
> +      fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_D);
> +      inst = bld.XOR(tmp, op[0], op[1]);
> +      inst->predicate = BRW_PREDICATE_NORMAL;
> +      inst->conditional_mod = BRW_CONDITIONAL_L;
> +
> +      /* If the result of the initial remainder operation is non-zero and
> the
> +       * two sources have different signs, add in a copy of op[1] to get
> the
> +       * final integer modulus value.
> +       */
> +      inst = bld.ADD(result, result, op[1]);
> +      inst->predicate = BRW_PREDICATE_NORMAL;
>        break;
> +   }
>
>     case nir_op_flt:
>     case nir_op_ilt:
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> index 585674f..c18694f 100644
> --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> @@ -1109,9 +1109,41 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr)
>        break;
>
>     case nir_op_umod:
> +   case nir_op_irem:
> +      /* According to the sign table for INT DIV in the Ivy Bridge PRM, it
> +       * appears that our hardware just does the right thing for signed
> +       * remainder.
> +       */
>        emit_math(SHADER_OPCODE_INT_REMAINDER, dst, op[0], op[1]);
>        break;
>
> +   case nir_op_imod: {
> +      /* Get a regular C-style remainder.  If a % b == 0, set the
> predicate. */
> +      inst = emit_math(SHADER_OPCODE_INT_REMAINDER, dst, op[0], op[1]);
> +
> +      /* Math instructions don't support conditional mod */
> +      inst = emit(MOV(dst_null_d(), src_reg(dst)));
> +      inst->conditional_mod = BRW_CONDITIONAL_NZ;
> +
> +      /* Now, we need to determine if signs of the sources are different.
> +       * When we XOR the sources, the top bit is 0 if they are the same
> and 1
> +       * if they are different.  We can then use a conditional modifier to
> +       * turn that into a predicate.  This leads us to an XOR.l
> instruction.
> +       */
> +      src_reg tmp = src_reg(this, glsl_type::ivec4_type);
> +      inst = emit(XOR(dst_reg(tmp), op[0], op[1]));
> +      inst->predicate = BRW_PREDICATE_NORMAL;
> +      inst->conditional_mod = BRW_CONDITIONAL_L;
> +
> +      /* If the result of the initial remainder operation is non-zero and
> the
> +       * two sources have different signs, add in a copy of op[1] to get
> the
> +       * final integer modulus value.
> +       */
> +      inst = emit(ADD(dst, src_reg(dst), op[1]));
> +      inst->predicate = BRW_PREDICATE_NORMAL;
> +      break;
> +   }
> +
>     case nir_op_ldexp:
>        unreachable("not reached: should be handled by ldexp_to_arith()");
>
> --
> 2.5.0.400.gff86faf
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160406/e4333bd0/attachment.html>


More information about the mesa-dev mailing list