On Fri, Mar 25, 2016 at 4:12 PM, Jason Ekstrand <ja...@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 > >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev