From: Eric Anholt Date: Fri, 19 Nov 2010 02:36:06 +0000 (+0800) Subject: i965: Recognize saturates and turn them into a saturated mov. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=19631fab35ca4d5ca64d606922f3f20774b27645;p=mesa.git 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. --- 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);