From: Matt Turner Date: Wed, 18 Sep 2013 04:34:15 +0000 (-0700) Subject: glsl: Implement [iu]mulExtended() built-ins for ARB_gpu_shader5. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=06e41a02a3564b00404dd3dd5d6f6b5897df36e9;p=mesa.git glsl: Implement [iu]mulExtended() built-ins for ARB_gpu_shader5. These built-ins have two "out" parameters, which makes implementing them efficiently with our current compiler infrastructure difficult. Instead, implement them in terms of the existing ir_binop_mul IR (to return the low 32-bits) and a new ir_binop_mul64 which returns the high 32-bits. v2: Rename mul64 -> imul_high as suggested by Ken. Reviewed-by: Kenneth Graunke --- diff --git a/src/glsl/builtin_functions.cpp b/src/glsl/builtin_functions.cpp index 5b1b9c3b7c1..d40888d3819 100644 --- a/src/glsl/builtin_functions.cpp +++ b/src/glsl/builtin_functions.cpp @@ -533,6 +533,7 @@ private: B2(frexp) B1(uaddCarry) B1(usubBorrow) + B1(mulExtended) #undef B0 #undef B1 #undef B2 @@ -1961,6 +1962,18 @@ builtin_builder::create_builtins() _usubBorrow(glsl_type::uvec3_type), _usubBorrow(glsl_type::uvec4_type), NULL); + add_function("imulExtended", + _mulExtended(glsl_type::int_type), + _mulExtended(glsl_type::ivec2_type), + _mulExtended(glsl_type::ivec3_type), + _mulExtended(glsl_type::ivec4_type), + NULL); + add_function("umulExtended", + _mulExtended(glsl_type::uint_type), + _mulExtended(glsl_type::uvec2_type), + _mulExtended(glsl_type::uvec3_type), + _mulExtended(glsl_type::uvec4_type), + NULL); #undef F #undef FI #undef FIU @@ -3762,6 +3775,24 @@ builtin_builder::_usubBorrow(const glsl_type *type) return sig; } + +/** + * For both imulExtended() and umulExtended() built-ins. + */ +ir_function_signature * +builtin_builder::_mulExtended(const glsl_type *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, 4, x, y, msb, lsb); + + body.emit(assign(msb, imul_high(x, y))); + body.emit(assign(lsb, mul(x, y))); + + return sig; +} /** @} */ /******************************************************************************/ diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 149ddbd5342..ead7456dfcc 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -398,6 +398,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1) this->type = glsl_type::uint_type; break; + case ir_binop_imul_high: case ir_binop_carry: case ir_binop_borrow: case ir_binop_lshift: @@ -529,6 +530,7 @@ static const char *const operator_strs[] = { "+", "-", "*", + "imul_high", "/", "carry", "borrow", diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 756ce9c7cd3..9fd5f5a997a 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -1091,7 +1091,8 @@ enum ir_expression_operation { ir_binop_add, ir_binop_sub, - ir_binop_mul, + ir_binop_mul, /**< Floating-point or low 32-bit integer multiply. */ + ir_binop_imul_high, /**< Calculates the high 32-bits of a 64-bit multiply. */ ir_binop_div, /** diff --git a/src/glsl/ir_builder.cpp b/src/glsl/ir_builder.cpp index b6ce889834c..6c49734bef8 100644 --- a/src/glsl/ir_builder.cpp +++ b/src/glsl/ir_builder.cpp @@ -216,6 +216,11 @@ ir_expression *mul(operand a, operand b) return expr(ir_binop_mul, a, b); } +ir_expression *imul_high(operand a, operand b) +{ + return expr(ir_binop_imul_high, a, b); +} + ir_expression *div(operand a, operand b) { return expr(ir_binop_div, a, b); diff --git a/src/glsl/ir_builder.h b/src/glsl/ir_builder.h index 1345788ab13..1f0778870e3 100644 --- a/src/glsl/ir_builder.h +++ b/src/glsl/ir_builder.h @@ -133,6 +133,7 @@ ir_expression *expr(ir_expression_operation op, operand a, operand b, operand c) ir_expression *add(operand a, operand b); ir_expression *sub(operand a, operand b); ir_expression *mul(operand a, operand b); +ir_expression *imul_high(operand a, operand b); ir_expression *div(operand a, operand b); ir_expression *carry(operand a, operand b); ir_expression *borrow(operand a, operand b); diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 38db8c20677..d6abc8eb5a8 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -429,6 +429,12 @@ ir_validate::visit_leave(ir_expression *ir) } break; + case ir_binop_imul_high: + assert(ir->type == ir->operands[0]->type); + assert(ir->type == ir->operands[1]->type); + assert(ir->type->is_integer()); + break; + case ir_binop_carry: case ir_binop_borrow: assert(ir->type == ir->operands[0]->type); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 2f87cfd65c4..cfad91bc423 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1499,6 +1499,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_triop_csel: case ir_binop_carry: case ir_binop_borrow: + case ir_binop_imul_high: assert(!"not supported"); break; diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index f33bea6eb02..8d06ac6f7a7 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -1980,6 +1980,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) case ir_binop_ldexp: case ir_binop_carry: case ir_binop_borrow: + case ir_binop_imul_high: /* This operation is not supported, or should have already been handled. */ assert(!"Invalid ir opcode in glsl_to_tgsi_visitor::visit()");