i965: Recognize saturates and turn them into a saturated mov.
authorEric Anholt <eric@anholt.net>
Fri, 19 Nov 2010 02:36:06 +0000 (10:36 +0800)
committerEric Anholt <eric@anholt.net>
Sat, 20 Nov 2010 03:09:31 +0000 (19:09 -0800)
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.

src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h

index 34f978435affafc49ea75d3f09bdfcd2ec77b7a3..1b2989f46ec3ea0471cc11a6adbd5d6c68b64b9a 100644 (file)
@@ -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:
index 896dc57705b42272522515b21d81b5a5d65a6c5a..f546fabd55720a50aa54f5f627f48c4b3e716224 100644 (file)
@@ -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);