[Mesa-dev] [PATCH 15/23] glsl: Distribute binary operations over ir_triop_csel

Ian Romanick idr at freedesktop.org
Fri Mar 20 13:58:15 PDT 2015


From: Ian Romanick <ian.d.romanick at intel.com>

If the both result operands of the ir_triop_csel are constants and the
other operand of the binary operation is constant, distributing the
unary operation allows constant folding to eliminate it.

Shader-db results:

GM45 (0x2A42):
total instructions in shared programs: 3545351 -> 3545378 (0.00%)
instructions in affected programs:     28774 -> 28801 (0.09%)
helped:                                59
HURT:                                  65

Iron Lake (0x0046):
total instructions in shared programs: 4975577 -> 4975572 (-0.00%)
instructions in affected programs:     31837 -> 31832 (-0.02%)
helped:                                74
HURT:                                  66

Sandy Bridge (0x0116):
total instructions in shared programs: 6802556 -> 6800913 (-0.02%)
instructions in affected programs:     207412 -> 205769 (-0.79%)
helped:                                710
HURT:                                  152

Sandy Bridge (0x0116) NIR:
total instructions in shared programs: 6815965 -> 6815782 (-0.00%)
instructions in affected programs:     241297 -> 241114 (-0.08%)
helped:                                292
HURT:                                  628

Ivy Bridge (0x0166):
total instructions in shared programs: 6277594 -> 6275305 (-0.04%)
instructions in affected programs:     224874 -> 222585 (-1.02%)
helped:                                812
HURT:                                  152

Ivy Bridge (0x0166) NIR:
total instructions in shared programs: 6323362 -> 6322876 (-0.01%)
instructions in affected programs:     142728 -> 142242 (-0.34%)
helped:                                297
HURT:                                  314

Haswell (0x0426):
total instructions in shared programs: 5763055 -> 5761392 (-0.03%)
instructions in affected programs:     170608 -> 168945 (-0.97%)
helped:                                702
HURT:                                  152

Haswell (0x0426) NIR:
total instructions in shared programs: 5799128 -> 5798963 (-0.00%)
instructions in affected programs:     199397 -> 199232 (-0.08%)
helped:                                284
HURT:                                  622

Broadwell (0x162E):
total instructions in shared programs: 6811079 -> 6809460 (-0.02%)
instructions in affected programs:     171789 -> 170170 (-0.94%)
helped:                                702
HURT:                                  155

Broadwell (0x162E) NIR:
total instructions in shared programs: 7013948 -> 7013761 (-0.00%)
instructions in affected programs:     201721 -> 201534 (-0.09%)
helped:                                300
HURT:                                  625

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/glsl/opt_algebraic.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp
index b1f0fa9..7d58e9b 100644
--- a/src/glsl/opt_algebraic.cpp
+++ b/src/glsl/opt_algebraic.cpp
@@ -354,6 +354,69 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
       }
    }
 
+   /* If the expression is a binary operation with one constant operand over
+    * an ir_triop_csel with constant results, distribute the binary operation
+    * over the ir_triop_csel results.  Constant folding will do the rest.
+    *
+    * Example: 5 * mix(0, 57, condition) becomes mix(5, 285, condition).
+    */
+   if (ir->get_num_operands() == 2) {
+      for (i = 0; i < 2; i++) {
+         if (op_expr[i] != NULL &&
+             op_const[i ^ 1] != NULL &&
+             op_expr[i]->operation == ir_triop_csel &&
+             op_expr[i]->operands[1]->as_constant() &&
+             op_expr[i]->operands[2]->as_constant()) {
+            ir_rvalue *left[2];
+            ir_rvalue *right[2];
+
+            /* Make sure the constant is in the same "position" after being
+             * distributed.  Otherwise a division could get inverted, and that
+             * would be bad.
+             */
+            if (i == 0) {
+               left[0] = op_expr[0]->operands[1];
+               left[1] = op_expr[0]->operands[2];
+               right[0] = op_const[1];
+               right[1] = op_const[1]->clone(mem_ctx, NULL);
+            } else {
+               left[0] = op_const[0];
+               left[1] = op_const[0]->clone(mem_ctx, NULL);
+               right[0] = op_expr[1]->operands[1];
+               right[1] = op_expr[1]->operands[2];
+            }
+
+            ir_expression *const tmp_expr[2] = {
+               new(mem_ctx) ir_expression(ir->operation, left[0], right[0]),
+               new(mem_ctx) ir_expression(ir->operation, left[1], right[1])
+            };
+
+            /* Constant-fold the expressions now to (possibly) save an
+             * interation through the optimization loop.
+             */
+            op_expr[i]->operands[1] = tmp_expr[0]->constant_expression_value();
+            op_expr[i]->operands[2] = tmp_expr[1]->constant_expression_value();
+            assert(op_expr[i]->operands[1] != NULL);
+            assert(op_expr[i]->operands[2] != NULL);
+
+            /* The type of the ir_triop_csel is now whatever the type of the
+             * distributed expression was.
+             */
+            assert(ir->type == op_expr[i]->operands[1]->type);
+            assert(ir->type == op_expr[i]->operands[2]->type);
+            op_expr[i]->type = ir->type;
+
+            /* Now let the rest of the algebraic optimization operate on the
+             * ir_triop_csel expression that replace the original unary
+             * expression.
+             */
+            ir = op_expr[i];
+            if (!preprocess_operands(ir, op_const, op_expr))
+                return ir;
+         }
+      }
+   }
+
    switch (ir->operation) {
    case ir_unop_bit_not:
       if (op_expr[0] && op_expr[0]->operation == ir_unop_bit_not)
-- 
2.1.0



More information about the mesa-dev mailing list