glsl: [u/i]mulExtended optimization for GLSL

Optimize mulExtended to use 32x32->64 multiplication.

Drivers which are not based on NIR, they can set the
MUL64_TO_MUL_AND_MUL_HIGH lowering flag in order to have same old
behavior.

v2: Add missing condition check (Jason Ekstrand)

Signed-off-by: Sagar Ghuge <sagar.ghuge@intel.com>
Suggested-by: Matt Turner <Matt Turner <mattst88@gmail.com>
Suggested-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
Sagar Ghuge
2019-02-27 14:02:54 -08:00
parent e551040c60
commit 1d8994a63b
7 changed files with 126 additions and 4 deletions
+30 -2
View File
@@ -5866,14 +5866,42 @@ builtin_builder::_usubBorrow(const glsl_type *type)
ir_function_signature *
builtin_builder::_mulExtended(const glsl_type *type)
{
const glsl_type *mul_type, *unpack_type;
ir_expression_operation unpack_op;
if (type->base_type == GLSL_TYPE_INT) {
unpack_op = ir_unop_unpack_int_2x32;
mul_type = glsl_type::get_instance(GLSL_TYPE_INT64, type->vector_elements, 1);
unpack_type = glsl_type::ivec2_type;
} else {
unpack_op = ir_unop_unpack_uint_2x32;
mul_type = glsl_type::get_instance(GLSL_TYPE_UINT64, type->vector_elements, 1);
unpack_type = glsl_type::uvec2_type;
}
ir_variable *x = in_var(type, "x");
ir_variable *y = in_var(type, "y");
ir_variable *msb = out_var(type, "msb");
ir_variable *lsb = out_var(type, "lsb");
MAKE_SIG(glsl_type::void_type, gpu_shader5_or_es31_or_integer_functions, 4, x, y, msb, lsb);
body.emit(assign(msb, imul_high(x, y)));
body.emit(assign(lsb, mul(x, y)));
ir_variable *unpack_val = body.make_temp(unpack_type, "_unpack_val");
ir_expression *mul_res = new(mem_ctx) ir_expression(ir_binop_mul, mul_type,
new(mem_ctx)ir_dereference_variable(x),
new(mem_ctx)ir_dereference_variable(y));
if (type->vector_elements == 1) {
body.emit(assign(unpack_val, expr(unpack_op, mul_res)));
body.emit(assign(msb, swizzle_y(unpack_val)));
body.emit(assign(lsb, swizzle_x(unpack_val)));
} else {
for (int i = 0; i < type->vector_elements; i++) {
body.emit(assign(unpack_val, expr(unpack_op, swizzle(mul_res, i, 1))));
body.emit(assign(array_ref(msb, i), swizzle_y(unpack_val)));
body.emit(assign(array_ref(lsb, i), swizzle_x(unpack_val)));
}
}
return sig;
}