[Mesa-dev] [PATCH 3/4] i965/fs: Try to emit LINE instructions on Gen <= 5.

Ian Romanick idr at freedesktop.org
Thu Dec 4 19:07:25 PST 2014


On 12/04/2014 04:37 PM, Matt Turner wrote:
> The LINE instruction performs a multiply-add instruction (a * b + c)
> where b and c are scalar arguments. It reads b and c from offsets in
> src0 such that you can load them (it they're representable) as a
> vector-float immediate with a single instruction.
> 
> Hurts some programs, but that'll all get better once we CSE the
> vector-float MOVs in the next patch.
> 

Why only on Gen <= 5?  It looks like the instruction still exists at
least on Gen6.

Either way, the series looks good.

Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>

> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=77544
> ---
>  src/mesa/drivers/dri/i965/brw_fs.h           |  1 +
>  src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 55 ++++++++++++++++++++++++++++
>  2 files changed, 56 insertions(+)
> 
> diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
> index b29b6b0..fed1208 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs.h
> +++ b/src/mesa/drivers/dri/i965/brw_fs.h
> @@ -500,6 +500,7 @@ public:
>     void emit_minmax(enum brw_conditional_mod conditionalmod, const fs_reg &dst,
>                      const fs_reg &src0, const fs_reg &src1);
>     bool try_emit_saturate(ir_expression *ir);
> +   bool try_emit_line(ir_expression *ir);
>     bool try_emit_mad(ir_expression *ir);
>     void try_replace_with_sel();
>     bool opt_peephole_sel();
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> index 62ef853..465e59a 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> @@ -296,6 +296,59 @@ fs_visitor::try_emit_saturate(ir_expression *ir)
>  }
>  
>  bool
> +fs_visitor::try_emit_line(ir_expression *ir)
> +{
> +   /* LINE's src0 must be of type float. */
> +   if (ir->type != glsl_type::float_type)
> +      return false;
> +
> +   ir_rvalue *nonmul = ir->operands[1];
> +   ir_expression *mul = ir->operands[0]->as_expression();
> +
> +   if (!mul || mul->operation != ir_binop_mul) {
> +      nonmul = ir->operands[0];
> +      mul = ir->operands[1]->as_expression();
> +
> +      if (!mul || mul->operation != ir_binop_mul)
> +         return false;
> +   }
> +
> +   ir_constant *const_add = nonmul->as_constant();
> +   if (!const_add)
> +      return false;
> +
> +   int add_operand_vf = brw_float_to_vf(const_add->value.f[0]);
> +   if (add_operand_vf == -1)
> +      return false;
> +
> +   ir_rvalue *non_const_mul = mul->operands[1];
> +   ir_constant *const_mul = mul->operands[0]->as_constant();
> +   if (!const_mul) {
> +      const_mul = mul->operands[1]->as_constant();
> +
> +      if (!const_mul)
> +         return false;
> +
> +      non_const_mul = mul->operands[0];
> +   }
> +
> +   int mul_operand_vf = brw_float_to_vf(const_mul->value.f[0]);
> +   if (mul_operand_vf == -1)
> +      return false;
> +
> +   non_const_mul->accept(this);
> +   fs_reg src1 = this->result;
> +
> +   fs_reg src0 = fs_reg(this, ir->type);
> +   emit(BRW_OPCODE_MOV, src0,
> +        fs_reg((uint8_t)mul_operand_vf, 0, 0, (uint8_t)add_operand_vf));
> +
> +   this->result = fs_reg(this, ir->type);
> +   emit(BRW_OPCODE_LINE, this->result, src0, src1);
> +   return true;
> +}
> +
> +bool
>  fs_visitor::try_emit_mad(ir_expression *ir)
>  {
>     /* 3-src instructions were introduced in gen6. */
> @@ -482,6 +535,8 @@ fs_visitor::visit(ir_expression *ir)
>     /* Deal with the real oddball stuff first */
>     switch (ir->operation) {
>     case ir_binop_add:
> +      if (brw->gen <= 5 && try_emit_line(ir))
> +         return;
>        if (try_emit_mad(ir))
>           return;
>        break;
> 



More information about the mesa-dev mailing list