summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Turner <[email protected]>2014-04-01 16:49:13 -0700
committerMatt Turner <[email protected]>2014-12-05 16:43:31 -0800
commit963a3c7f90672c8d4931606d45e172792caf84ca (patch)
tree20bca8068acf42adf41a539fd250a75c792b5cb6
parent6be863af0eda114e0225dfa8b68aa11b6e84d73c (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]>
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h1
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_visitor.cpp55
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;