glsl: Kill __intrinsic_atomic_sub
authorIan Romanick <ian.d.romanick@intel.com>
Thu, 7 Jul 2016 20:57:11 +0000 (13:57 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 4 Oct 2016 23:53:32 +0000 (16:53 -0700)
Just generate an __intrinsic_atomic_add with a negated parameter.

Some background on the non-obvious reasons for the the big change to
builtin_builder::call()... this is cribbed from some discussion with
Ilia on mesa-dev.

Why change builtin_builder::call() to allow taking dereferences and
create them here rather than just feeding in the ir_variables directly?
The problem is the neg_data ir_variable node would have to be in two
lists at the same time: the instruction stream and parameters.  The
ir_variable node is automatically added to the instruction stream by the
call to make_temp.  Restructuring the code so that the ir_variables
could be in parameters then move them to the instruction stream would
have been pretty terrible.

ir_call in the instruction stream has an exec_list that contains
ir_dereference_variable nodes.

The builtin_builder::call method previously took an exec_list of
ir_variables and created a list of ir_dereference_variable.  All of the
original users of that method wanted to make a function call using
exactly the set of parameters passed to the built-in function (i.e.,
call __intrinsic_atomic_add using the parameters to atomicAdd).  For
these users, the list of ir_variables already existed:  the list of
parameters in the built-in function signature.

This new caller doesn't do that.  It wants to call a function with a
parameter from the function and a value calculated in the function.  So,
I changed builtin_builder::call to take a list that could either be a
list of ir_variable or a list of ir_dereference_variable.  In the former
case it behaves just as it previously did.  In the latter case, it uses
(and removes from the input list) the ir_dereference_variable nodes
instead of creating new ones.

   text    data     bss     dec     hex filename
6036395  283160   28608 6348163  60dd83 lib64/i965_dri.so before
6036923  283160   28608 6348691  60df93 lib64/i965_dri.so after

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/compiler/glsl/builtin_functions.cpp
src/compiler/glsl/ir.h
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index 258671ab6bc3a3bb7df7d67a0a3ae56a43d514a9..ad3d981c44b0a099be2d209534e95c6b91507328 100644 (file)
@@ -1010,10 +1010,6 @@ builtin_builder::create_intrinsics()
                 _atomic_counter_intrinsic1(shader_atomic_counter_ops,
                                            ir_intrinsic_atomic_counter_add),
                 NULL);
-   add_function("__intrinsic_atomic_sub",
-                _atomic_counter_intrinsic1(shader_atomic_counter_ops,
-                                           ir_intrinsic_atomic_counter_sub),
-                NULL);
    add_function("__intrinsic_atomic_min",
                 _atomic_intrinsic2(buffer_atomics_supported,
                                    glsl_type::uint_type,
@@ -3365,13 +3361,29 @@ builtin_builder::asin_expr(ir_variable *x, float p0, float p1)
                                           mul(abs(x), imm(p1))))))))));
 }
 
+/**
+ * Generate a ir_call to a function with a set of parameters
+ *
+ * The input \c params can either be a list of \c ir_variable or a list of
+ * \c ir_dereference_variable.  In the latter case, all nodes will be removed
+ * from \c params and used directly as the parameters to the generated
+ * \c ir_call.
+ */
 ir_call *
 builtin_builder::call(ir_function *f, ir_variable *ret, exec_list params)
 {
    exec_list actual_params;
 
-   foreach_in_list(ir_variable, var, &params) {
-      actual_params.push_tail(var_ref(var));
+   foreach_in_list_safe(ir_instruction, ir, &params) {
+      ir_dereference_variable *d = ir->as_dereference_variable();
+      if (d != NULL) {
+         d->remove();
+         actual_params.push_tail(d);
+      } else {
+         ir_variable *var = ir->as_variable();
+         assert(var != NULL);
+         actual_params.push_tail(var_ref(var));
+      }
    }
 
    ir_function_signature *sig =
@@ -5348,8 +5360,34 @@ builtin_builder::_atomic_counter_op1(const char *intrinsic,
    MAKE_SIG(glsl_type::uint_type, avail, 2, counter, data);
 
    ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval");
-   body.emit(call(shader->symbols->get_function(intrinsic), retval,
-                  sig->parameters));
+
+   /* Instead of generating an __intrinsic_atomic_sub, generate an
+    * __intrinsic_atomic_add with the data parameter negated.
+    */
+   if (strcmp("__intrinsic_atomic_sub", intrinsic) == 0) {
+      ir_variable *const neg_data =
+         body.make_temp(glsl_type::uint_type, "neg_data");
+
+      body.emit(assign(neg_data, neg(data)));
+
+      exec_list parameters;
+
+      parameters.push_tail(new(mem_ctx) ir_dereference_variable(counter));
+      parameters.push_tail(new(mem_ctx) ir_dereference_variable(neg_data));
+
+      ir_function *const func =
+         shader->symbols->get_function("__intrinsic_atomic_add");
+      ir_instruction *const c = call(func, retval, parameters);
+
+      assert(c != NULL);
+      assert(parameters.is_empty());
+
+      body.emit(c);
+   } else {
+      body.emit(call(shader->symbols->get_function(intrinsic), retval,
+                     sig->parameters));
+   }
+
    body.emit(ret(retval));
    return sig;
 }
index 388b1bec3372e4b7e3af515731e3e3ee8463c770..83b810bba91318d5314a21476ea5d3d069496a8f 100644 (file)
@@ -1045,7 +1045,6 @@ enum ir_intrinsic_id {
    ir_intrinsic_atomic_counter_increment,
    ir_intrinsic_atomic_counter_predecrement,
    ir_intrinsic_atomic_counter_add,
-   ir_intrinsic_atomic_counter_sub,
    ir_intrinsic_atomic_counter_and,
    ir_intrinsic_atomic_counter_or,
    ir_intrinsic_atomic_counter_xor,
index 749008b0fe14cada3c3ab607e7eb4e60cf1617de..bb88196780e6ee01dfa65e15f779591075f812ac 100644 (file)
@@ -3218,15 +3218,6 @@ glsl_to_tgsi_visitor::visit_atomic_counter_intrinsic(ir_call *ir)
          data2 = this->result;
          break;
       }
-      case ir_intrinsic_atomic_counter_sub: {
-         opcode = TGSI_OPCODE_ATOMUADD;
-         st_src_reg res = get_temp(glsl_type::uvec4_type);
-         st_dst_reg dstres = st_dst_reg(res);
-         dstres.writemask = dst.writemask;
-         emit_asm(ir, TGSI_OPCODE_INEG, dstres, data);
-         data = res;
-         break;
-      }
       default:
          assert(!"Unexpected intrinsic");
          return;
@@ -3672,7 +3663,6 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
    case ir_intrinsic_atomic_counter_increment:
    case ir_intrinsic_atomic_counter_predecrement:
    case ir_intrinsic_atomic_counter_add:
-   case ir_intrinsic_atomic_counter_sub:
    case ir_intrinsic_atomic_counter_min:
    case ir_intrinsic_atomic_counter_max:
    case ir_intrinsic_atomic_counter_and: