From: Francisco Jerez Date: Wed, 18 Mar 2015 12:34:51 +0000 (+0200) Subject: i965: Define some useful swizzle helper functions. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cff670b009ee8c8a60d1551148bf02038824507b;p=mesa.git i965: Define some useful swizzle helper functions. This defines helper functions implementing some common swizzle transformations that are usually open-coded in the compiler back-end, causing a lot of clutter. Some optimization passes will become almost trivial implemented in terms of these functions (e.g. vec4_visitor::opt_reduce_swizzle()). Reviewed-by: Matt Turner --- diff --git a/src/mesa/drivers/dri/i965/brw_reg.h b/src/mesa/drivers/dri/i965/brw_reg.h index eaf6620998e..adbb173988c 100644 --- a/src/mesa/drivers/dri/i965/brw_reg.h +++ b/src/mesa/drivers/dri/i965/brw_reg.h @@ -95,6 +95,103 @@ brw_is_single_value_swizzle(int swiz) swiz == BRW_SWIZZLE_WWWW); } +/** + * Compute the swizzle obtained from the application of \p swz0 on the result + * of \p swz1. The argument ordering is expected to match function + * composition. + */ +static inline unsigned +brw_compose_swizzle(unsigned swz0, unsigned swz1) +{ + return BRW_SWIZZLE4( + BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 0)), + BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 1)), + BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 2)), + BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 3))); +} + +/** + * Return the result of applying swizzle \p swz to shuffle the bits of \p mask + * (AKA image). + */ +static inline unsigned +brw_apply_swizzle_to_mask(unsigned swz, unsigned mask) +{ + unsigned result = 0; + + for (unsigned i = 0; i < 4; i++) { + if (mask & (1 << BRW_GET_SWZ(swz, i))) + result |= 1 << i; + } + + return result; +} + +/** + * Return the result of applying the inverse of swizzle \p swz to shuffle the + * bits of \p mask (AKA preimage). Useful to find out which components are + * read from a swizzled source given the instruction writemask. + */ +static inline unsigned +brw_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask) +{ + unsigned result = 0; + + for (unsigned i = 0; i < 4; i++) { + if (mask & (1 << i)) + result |= 1 << BRW_GET_SWZ(swz, i); + } + + return result; +} + +/** + * Construct an identity swizzle for the set of enabled channels given by \p + * mask. The result will only reference channels enabled in the provided \p + * mask, assuming that \p mask is non-zero. The constructed swizzle will + * satisfy the property that for any instruction OP and any mask: + * + * brw_OP(p, brw_writemask(dst, mask), + * brw_swizzle(src, brw_swizzle_for_mask(mask))); + * + * will be equivalent to the same instruction without swizzle: + * + * brw_OP(p, brw_writemask(dst, mask), src); + */ +static inline unsigned +brw_swizzle_for_mask(unsigned mask) +{ + unsigned last = (mask ? ffs(mask) - 1 : 0); + unsigned swz[4]; + + for (unsigned i = 0; i < 4; i++) + last = swz[i] = (mask & (1 << i) ? i : last); + + return BRW_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); +} + +/** + * Construct an identity swizzle for the first \p n components of a vector. + * When only a subset of channels of a vec4 are used we don't want to + * reference the other channels, as that will tell optimization passes that + * those other channels are used. + */ +static inline unsigned +brw_swizzle_for_size(unsigned n) +{ + return brw_swizzle_for_mask((1 << n) - 1); +} + +/** + * Converse of brw_swizzle_for_mask(). Returns the mask of components + * accessed by the specified swizzle \p swz. + */ +static inline unsigned +brw_mask_for_swizzle(unsigned swz) +{ + return brw_apply_inv_swizzle_to_mask(swz, ~0); +} + enum PACKED brw_reg_type { BRW_REGISTER_TYPE_UD = 0, BRW_REGISTER_TYPE_D,