diff options
author | Ian Romanick <[email protected]> | 2016-07-07 13:57:11 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2016-10-04 16:53:32 -0700 |
commit | c42fe30c8650a5bd19b22289f33a7ed35e427057 (patch) | |
tree | 841a7c201c877c23eded9c2b40962caef5c466b9 /src/compiler | |
parent | bb290b5679745e3b7f84dd14174aae6688ab4cac (diff) |
glsl: Kill __intrinsic_atomic_sub
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 <[email protected]>
Acked-by: Ilia Mirkin <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/glsl/builtin_functions.cpp | 54 | ||||
-rw-r--r-- | src/compiler/glsl/ir.h | 1 |
2 files changed, 46 insertions, 9 deletions
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp index 258671ab6bc..ad3d981c44b 100644 --- a/src/compiler/glsl/builtin_functions.cpp +++ b/src/compiler/glsl/builtin_functions.cpp @@ -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, ¶ms) { - actual_params.push_tail(var_ref(var)); + foreach_in_list_safe(ir_instruction, ir, ¶ms) { + 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; } diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h index 388b1bec337..83b810bba91 100644 --- a/src/compiler/glsl/ir.h +++ b/src/compiler/glsl/ir.h @@ -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, |