[Mesa-dev] [PATCH 14/15] glsl: Add frexp_to_arith lowering pass.
Paul Berry
stereotype441 at gmail.com
Fri Aug 23 09:48:21 PDT 2013
On 22 August 2013 16:08, Matt Turner <mattst88 at gmail.com> wrote:
> ---
> src/glsl/ir_optimization.h | 1 +
> src/glsl/lower_instructions.cpp | 106
> ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 107 insertions(+)
>
Depending on how we decide to resolve the "ir_expression writing to one of
its parameters" issue I brought up in patch 5, I believe this patch will
either need to go away or get substantially rewritten. Patch 15 may also
need a small tweak.
I've sent comments on patches 3, 5, 8, 10, 11, 12, and 13. Patches 1, 2,
4, 6, 7, 9, and 15 are:
Reviewed-by: Paul Berry <stereotype441 at gmail.com>
>
> diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
> index 074686c..51c73bb 100644
> --- a/src/glsl/ir_optimization.h
> +++ b/src/glsl/ir_optimization.h
> @@ -39,6 +39,7 @@
> #define LRP_TO_ARITH 0x80
> #define BITFIELD_INSERT_TO_BFM_BFI 0x100
> #define LDEXP_TO_ARITH 0x200
> +#define FREXP_TO_ARITH 0x400
>
> /**
> * \see class lower_packing_builtins_visitor
> diff --git a/src/glsl/lower_instructions.cpp
> b/src/glsl/lower_instructions.cpp
> index 8b0a8e1..495c232 100644
> --- a/src/glsl/lower_instructions.cpp
> +++ b/src/glsl/lower_instructions.cpp
> @@ -87,6 +87,10 @@
> * -------------
> * Converts ir_binop_ldexp to arithmetic and bit operations.
> *
> + * FREXP_TO_ARITH:
> + * -------------
> + * Converts ir_binop_frexp to arithmetic and bit operations.
> + *
> * LRP_TO_ARITH:
> * -------------
> * Converts ir_triop_lrp to (op0 * (1.0f - op2)) + (op1 * op2).
> @@ -131,6 +135,7 @@ private:
> void lrp_to_arith(ir_expression *);
> void bitfield_insert_to_bfm_bfi(ir_expression *);
> void ldexp_to_arith(ir_expression *);
> + void frexp_to_arith(ir_expression *);
> };
>
> /**
> @@ -455,6 +460,102 @@
> lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
> this->progress = true;
> }
>
> +void
> +lower_instructions_visitor::frexp_to_arith(ir_expression *ir)
> +{
> + /* Translates
> + * ir_binop_frexp x_input exp
> + * into:
> + *
> + * x = x_input;
> + * exp = 0;
> + *
> + * if (abs(x) != 0.0) {
> + * bits = bitcast_f2u(x);
> + *
> + * exp += (bitcast_f2u(abs(x)) >> exp_shift) + exp_bias;
> + * bits &= sign_mantissa_mask;
> + * bits |= exponent_mask;
> + * x = bitcast_u2f(bits);
> + * }
> + * return x;
> + *
> + * which we can't actually implement as such, since the GLSL IR doesn't
> + * have vectorized if-statements. We actually implement it without
> branches
> + * using conditional-select:
> + *
> + * x = x_input;
> + *
> + * is_not_zero = abs(x) != 0.0f;
> + *
> + * exp = u2i(bitcast_f2u(abs(x)) >> exp_shift);
> + * exp += cond_sel(is_not_zero, exp_bias, 0);
> + *
> + * bits = bitcast_f2u(x);
> + * bits &= sign_mantissa_mask;
> + * bits |= cond_sel(is_not_zero, exponent_mask, 0u);
> + * x = bitcast_u2f(bits);
> + * return x;
> + */
> +
> + const unsigned vec_elem = ir->type->vector_elements;
> +
> + /* Types */
> + const glsl_type *uvec = glsl_type::get_instance(GLSL_TYPE_UINT,
> vec_elem, 1);
> + const glsl_type *bvec = glsl_type::get_instance(GLSL_TYPE_BOOL,
> vec_elem, 1);
> + const glsl_type *ivec = glsl_type::get_instance(GLSL_TYPE_INT,
> vec_elem, 1);
> +
> + /* Constants */
> + ir_constant *zeroi = ir_constant::zero(ir, ivec);
> + ir_constant *zerou = ir_constant::zero(ir, uvec);
> + ir_constant *zerof = ir_constant::zero(ir, ir->type);
> +
> + ir_constant *exp_bias = new(ir) ir_constant(-126, vec_elem);
> + ir_constant *exp_shift = new(ir) ir_constant(23u, vec_elem);
> +
> + ir_constant *sign_mantissa_mask = new(ir) ir_constant(0x807fffffu,
> vec_elem);
> + ir_constant *exponent_mask = new(ir) ir_constant(0x3f000000u,
> vec_elem);
> +
> + /* Temporary variables */
> + ir_variable *x = new(ir) ir_variable(ir->type, "x", ir_var_temporary);
> +
> + ir_variable *bits = new(ir) ir_variable(uvec, "bits",
> ir_var_temporary);
> +
> + ir_variable *is_not_zero = new(ir) ir_variable(bvec, "is_not_zero",
> + ir_var_temporary);
> +
> + /* Variable passed as <exp> parameter */
> + ir_variable *exponent = ir->operands[1]->variable_referenced();
> +
> +
> + ir_instruction &i = *base_ir;
> +
> + /* Initialize x = x_input; exponent = 0; */
> + i.insert_before(x);
> + i.insert_before(assign(x, ir->operands[0]));
> + i.insert_before(is_not_zero);
> + i.insert_before(assign(is_not_zero, nequal(abs(x), zerof)));
> +
> + /* Calculate exponent */
> + /* Use bitcast to unsigned to get shr, not asr. */
> + i.insert_before(assign(exponent, add(u2i(rshift(bitcast_f2u(abs(x)),
> + exp_shift)),
> + cond_sel(is_not_zero, exp_bias,
> + zeroi))));
> +
> + /* Calculate mantissa */
> + i.insert_before(bits);
> + i.insert_before(assign(bits, bit_and(bitcast_f2u(x),
> sign_mantissa_mask)));
> + i.insert_before(assign(bits, bit_or(bits, cond_sel(is_not_zero,
> + exponent_mask,
> zerou))));
> +
> + ir->operation = ir_unop_bitcast_u2f;
> + ir->operands[0] = new(ir) ir_dereference_variable(bits);
> + ir->operands[1] = NULL;
> +
> + this->progress = true;
> +}
> +
> ir_visitor_status
> lower_instructions_visitor::visit_leave(ir_expression *ir)
> {
> @@ -506,6 +607,11 @@ lower_instructions_visitor::visit_leave(ir_expression
> *ir)
> ldexp_to_arith(ir);
> break;
>
> + case ir_binop_frexp:
> + if (lowering(FREXP_TO_ARITH))
> + frexp_to_arith(ir);
> + break;
> +
> default:
> return visit_continue;
> }
> --
> 1.8.3.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20130823/1cf4b5a6/attachment.html>
More information about the mesa-dev
mailing list