Mesa (master): mesa/st: don't use CMP / I2F for conditional assignments with native integers

Roland Scheidegger sroland at kemper.freedesktop.org
Sat Dec 6 17:04:07 UTC 2014


Module: Mesa
Branch: master
Commit: d8da6deceadf5e48201d848b7061dad17a5b7cac
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d8da6deceadf5e48201d848b7061dad17a5b7cac

Author: Roland Scheidegger <sroland at vmware.com>
Date:   Fri Dec  5 23:08:34 2014 +0100

mesa/st: don't use CMP / I2F for conditional assignments with native integers

The original idea was to optimize away the condition by integrating it directly
into the CMP instruction. However, with native integers this requires an extra
I2F instruction. It is also fishy because the negation used didn't really honor
ieee754 float comparison rules, not to mention the CMP instruction itself
(being pretty much a legacy instruction) doesn't really have defined special
float value behavior in any case.
So, use UCMP and adjust the code trying to optimize the condition away
accordingly (I have absolutely no idea if such conditions are actually hit
or would be translated away somewhere else already).

v2: cosmetic changes

No piglit regressions on llvmpipe.

Reviewed-by: Jose Fonseca <jfonseca at vmware.com>
Reviewed-by: Brian Paul <brianp at vmware.com>

---

 src/mesa/state_tracker/st_glsl_to_tgsi.cpp |   62 ++++++++++++++++++++--------
 1 file changed, 45 insertions(+), 17 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 8e91c4b..fd51595 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -2288,6 +2288,37 @@ glsl_to_tgsi_visitor::process_move_condition(ir_rvalue *ir)
    bool switch_order = false;
 
    ir_expression *const expr = ir->as_expression();
+
+   if (native_integers) {
+      if ((expr != NULL) && (expr->get_num_operands() == 2)) {
+         enum glsl_base_type type = expr->operands[0]->type->base_type;
+         if (type == GLSL_TYPE_INT || type == GLSL_TYPE_UINT ||
+             type == GLSL_TYPE_BOOL) {
+            if (expr->operation == ir_binop_equal) {
+               if (expr->operands[0]->is_zero()) {
+                  src_ir = expr->operands[1];
+                  switch_order = true;
+               }
+               else if (expr->operands[1]->is_zero()) {
+                  src_ir = expr->operands[0];
+                  switch_order = true;
+               }
+            }
+            else if (expr->operation == ir_binop_nequal) {
+               if (expr->operands[0]->is_zero()) {
+                  src_ir = expr->operands[1];
+               }
+               else if (expr->operands[1]->is_zero()) {
+                  src_ir = expr->operands[0];
+               }
+            }
+         }
+      }
+
+      src_ir->accept(this);
+      return switch_order;
+   }
+
    if ((expr != NULL) && (expr->get_num_operands() == 2)) {
       bool zero_on_left = false;
 
@@ -2379,7 +2410,7 @@ glsl_to_tgsi_visitor::emit_block_mov(ir_assignment *ir, const struct glsl_type *
       const struct glsl_type *vec_type;
 
       vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT,
-					 type->vector_elements, 1);
+                                         type->vector_elements, 1);
 
       for (int i = 0; i < type->matrix_columns; i++) {
          emit_block_mov(ir, vec_type, l, r);
@@ -2447,7 +2478,7 @@ glsl_to_tgsi_visitor::visit(ir_assignment *ir)
             swizzles[i] = first_enabled_chan;
       }
       r.swizzle = MAKE_SWIZZLE4(swizzles[0], swizzles[1],
-        			swizzles[2], swizzles[3]);
+                                swizzles[2], swizzles[3]);
    }
 
    assert(l.file != PROGRAM_UNDEFINED);
@@ -2460,24 +2491,21 @@ glsl_to_tgsi_visitor::visit(ir_assignment *ir)
       for (i = 0; i < type_size(ir->lhs->type); i++) {
          st_src_reg l_src = st_src_reg(l);
          st_src_reg condition_temp = condition;
+         st_src_reg op1, op2;
          l_src.swizzle = swizzle_for_size(ir->lhs->type->vector_elements);
-         
+
+         op1 = r;
+         op2 = l_src;
+         if (switch_order) {
+            op1 = l_src;
+            op2 = r;
+         }
+
          if (native_integers) {
-            /* This is necessary because TGSI's CMP instruction expects the
-             * condition to be a float, and we store booleans as integers.
-             * TODO: really want to avoid i2f path and use UCMP. Requires
-             * changes to process_move_condition though too.
-             */
-            condition_temp = get_temp(glsl_type::vec4_type);
-            condition.negate = 0;
-            emit(ir, TGSI_OPCODE_I2F, st_dst_reg(condition_temp), condition);
-            condition_temp.swizzle = condition.swizzle;
+            emit(ir, TGSI_OPCODE_UCMP, l, condition_temp, op1, op2);
          }
-         
-         if (switch_order) {
-            emit(ir, TGSI_OPCODE_CMP, l, condition_temp, l_src, r);
-         } else {
-            emit(ir, TGSI_OPCODE_CMP, l, condition_temp, r, l_src);
+         else {
+            emit(ir, TGSI_OPCODE_CMP, l, condition_temp, op1, op2);
          }
 
          l.index++;




More information about the mesa-commit mailing list