summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2011-07-22 13:54:15 -0700
committerEric Anholt <eric@anholt.net>2011-08-05 10:08:31 -0700
commit62722d90af9d43d889af33b080a682f2004e049c (patch)
treead3d844d5fbe05222703ce2d2d0b52316852758a
parent6bd5f43f212962a054a41290b0f8e350dae2f40d (diff)
ir_to_mesa: Try to avoid emitting a MOV_SAT to saturate an expression tree.
Fixes a regression in codegen quality for ff_fragment_shader conversion to GLSL -- glean texCombine produces 7.5% fewer Mesa IR instructions.
-rw-r--r--src/mesa/program/ir_to_mesa.cpp28
1 files changed, 24 insertions, 4 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index debadb9a39..9b615b68a2 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -915,10 +915,30 @@ ir_to_mesa_visitor::try_emit_sat(ir_expression *ir)
sat_src->accept(this);
src_reg src = this->result;
- this->result = get_temp(ir->type);
- ir_to_mesa_instruction *inst;
- inst = emit(ir, OPCODE_MOV, dst_reg(this->result), src);
- inst->saturate = true;
+ /* If we generated an expression instruction into a temporary in
+ * processing the saturate's operand, apply the saturate to that
+ * instruction. Otherwise, generate a MOV to do the saturate.
+ *
+ * Note that we have to be careful to only do this optimization if
+ * the instruction in question was what generated src->result. For
+ * example, ir_dereference_array might generate a MUL instruction
+ * to create the reladdr, and return us a src reg using that
+ * reladdr. That MUL result is not the value we're trying to
+ * saturate.
+ */
+ ir_expression *sat_src_expr = sat_src->as_expression();
+ ir_to_mesa_instruction *new_inst;
+ new_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
+ if (sat_src_expr && (sat_src_expr->operation == ir_binop_mul ||
+ sat_src_expr->operation == ir_binop_add ||
+ sat_src_expr->operation == ir_binop_dot)) {
+ new_inst->saturate = true;
+ } else {
+ this->result = get_temp(ir->type);
+ ir_to_mesa_instruction *inst;
+ inst = emit(ir, OPCODE_MOV, dst_reg(this->result), src);
+ inst->saturate = true;
+ }
return true;
}