summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-11-19 10:36:06 +0800
committerEric Anholt <[email protected]>2010-11-19 19:09:31 -0800
commit19631fab35ca4d5ca64d606922f3f20774b27645 (patch)
tree27a248c09a675598f67f377bd03c7dc93197c9ec
parent02939d643f878ce3a3dcd2e7b2c6f035c64ecda7 (diff)
i965: Recognize saturates and turn them into a saturated mov.
On pre-gen6, this turns 4 instructions into 1. We could still do better by folding the saturate into the instruction generating the value if nobody else uses it, but that should be a separate pass.
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp26
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h1
2 files changed, 27 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 34f978435af..1b2989f46ec 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -704,6 +704,27 @@ fs_visitor::visit(ir_dereference_array *ir)
}
}
+/* Instruction selection: Produce a MOV.sat instead of
+ * MIN(MAX(val, 0), 1) when possible.
+ */
+bool
+fs_visitor::try_emit_saturate(ir_expression *ir)
+{
+ ir_rvalue *sat_val = ir->as_rvalue_to_saturate();
+
+ if (!sat_val)
+ return false;
+
+ sat_val->accept(this);
+ fs_reg src = this->result;
+
+ this->result = fs_reg(this, ir->type);
+ fs_inst *inst = emit(fs_inst(BRW_OPCODE_MOV, this->result, src));
+ inst->saturate = true;
+
+ return true;
+}
+
void
fs_visitor::visit(ir_expression *ir)
{
@@ -712,6 +733,10 @@ fs_visitor::visit(ir_expression *ir)
fs_inst *inst;
assert(ir->get_num_operands() <= 2);
+
+ if (try_emit_saturate(ir))
+ return;
+
for (operand = 0; operand < ir->get_num_operands(); operand++) {
ir->operands[operand]->accept(this);
if (this->result.file == BAD_FILE) {
@@ -3162,6 +3187,7 @@ fs_visitor::generate_code()
brw_set_conditionalmod(p, inst->conditional_mod);
brw_set_predicate_control(p, inst->predicated);
+ brw_set_saturate(p, inst->saturate);
switch (inst->opcode) {
case BRW_OPCODE_MOV:
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 896dc57705b..f546fabd557 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -397,6 +397,7 @@ public:
fs_inst *emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate);
fs_inst *emit_math(fs_opcodes op, fs_reg dst, fs_reg src0);
fs_inst *emit_math(fs_opcodes op, fs_reg dst, fs_reg src0, fs_reg src1);
+ bool try_emit_saturate(ir_expression *ir);
void emit_bool_to_cond_code(ir_rvalue *condition);
void emit_if_gen6(ir_if *ir);
void emit_unspill(fs_inst *inst, fs_reg reg, uint32_t spill_offset);