diff options
author | Matt Turner <[email protected]> | 2014-04-01 16:49:13 -0700 |
---|---|---|
committer | Matt Turner <[email protected]> | 2014-12-05 16:43:31 -0800 |
commit | 963a3c7f90672c8d4931606d45e172792caf84ca (patch) | |
tree | 20bca8068acf42adf41a539fd250a75c792b5cb6 /src | |
parent | 6be863af0eda114e0225dfa8b68aa11b6e84d73c (diff) |
i965/fs: Try to emit LINE instructions on Gen <= 5.
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.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=77544
Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 55 |
2 files changed, 56 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index daaa89fe98f..807001bc91c 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -508,6 +508,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 e4296ce9787..b4f8f37bfa2 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; |