<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Jun 14, 2018 at 6:06 PM, Jose Maria Casanova Crespo <span dir="ltr"><<a href="mailto:jmcasanova@igalia.com" target="_blank">jmcasanova@igalia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This new function takes care of shuffle/unshuffle components of a<br>
particular bit-size in components with a different bit-size.<br>
<br>
If source type size is smaller than destination type size the operation<br>
needed is a component shuffle. The opposite case would be an unshuffle.<br>
<br>
Component units are measured in terms of the smaller type between<br>
source and destination. As we are un/shuffling the smaller components<br>
from/into a bigger one.<br>
<br>
The operation allows to skip first_component number of components from<br>
the source.<br>
<br>
Shuffle MOVs are retyped using integer types avoiding problems with<br>
denorms and float types if source and destination bitsize is different.<br>
This allows to simplify uses of shuffle functions that are dealing with<br>
these retypes individually.<br>
<br>
Now there is a new restriction so source and destination can not overlap<br>
anymore when calling this shuffle function. Following patches that migrate<br>
to use this new function will take care individually of avoiding source<br>
and destination overlaps.<br>
<br>
v2: (Jason Ekstrand)<br>
    - Rewrite overlap asserts.<br>
    - Manage type_sz(src.type) == type_sz(dst.type) case using MOVs<br>
      from source to dest. This works for 64-bit to 64-bits<br>
      operation that on Gen7 as it doesn't support Q registers.<br>
    - Explain that components units are based in the smallest type.<br>
<br>
Cc: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
---<br>
 src/intel/compiler/brw_fs_nir.<wbr>cpp | 100 ++++++++++++++++++++++++++++++<br>
 1 file changed, 100 insertions(+)<br>
<br>
diff --git a/src/intel/compiler/brw_fs_<wbr>nir.cpp b/src/intel/compiler/brw_fs_<wbr>nir.cpp<br>
index 166da0aa6d7..9c5afc9c46f 100644<br>
--- a/src/intel/compiler/brw_fs_<wbr>nir.cpp<br>
+++ b/src/intel/compiler/brw_fs_<wbr>nir.cpp<br>
@@ -5362,6 +5362,106 @@ shuffle_16bit_data_for_32bit_<wbr>write(const fs_builder &bld,<br>
    }<br>
 }<br>
<br>
+/*<br>
+ * This helper takes a source register and un/shuffles it into the destination<br>
+ * register.<br>
+ *<br>
+ * If source type size is smaller than destination type size the operation<br>
+ * needed is a component shuffle. The opposite case would be an unshuffle. If<br>
+ * source/destination type size is equal a shuffle is done that would be<br>
+ * equivalent to a simple MOV.<br>
+ *<br>
+ * For example, if source is a 16-bit type and destination is 32-bit. A 3<br>
+ * components .xyz 16-bit vector on SIMD8 would be.<br>
+ *<br>
+ *    |x1|x2|x3|x4|x5|x6|x7|x8|y1|<wbr>y2|y3|y4|y5|y6|y7|y8|<br>
+ *    |z1|z2|z3|z4|z5|z6|z7|z8|  |  |  |  |  |  |  |  |<br>
+ *<br>
+ * This helper will return the following 2 32-bit components with the 16-bit<br>
+ * values shuffled:<br>
+ *<br>
+ *    |x1 y1|x2 y2|x3 y3|x4 y4|x5 y5|x6 y6|x7 y7|x8 y8|<br>
+ *    |z1   |z2   |z3   |z4   |z5   |z6   |z7   |z8   |<br>
+ *<br>
+ * For unshuffle, the example would be the opposite, a 64-bit type source<br>
+ * and a 32-bit destination. A 2 component .xy 64-bit vector on SIMD8<br>
+ * would be:<br>
+ *<br>
+ *    | x1l   x1h | x2l   x2h | x3l   x3h | x4l   x4h |<br>
+ *    | x5l   x5h | x6l   x6h | x7l   x7h | x8l   x8h |<br>
+ *    | y1l   y1h | y2l   y2h | y3l   y3h | y4l   y4h |<br>
+ *    | y5l   y5h | y6l   y6h | y7l   y7h | y8l   y8h |<br>
+ *<br>
+ * The returned result would be the following 4 32-bit components unshuffled:<br>
+ *<br>
+ *    | x1l | x2l | x3l | x4l | x5l | x6l | x7l | x8l |<br>
+ *    | x1h | x2h | x3h | x4h | x5h | x6h | x7h | x8h |<br>
+ *    | y1l | y2l | y3l | y4l | y5l | y6l | y7l | y8l |<br>
+ *    | y1h | y2h | y3h | y4h | y5h | y6h | y7h | y8h |<br>
+ *<br>
+ * - Source and destination register must not be overlapped.<br>
+ * - components units are measured in terms of the smaller type between<br>
+ *   source and destination because we are un/shuffling the smaller<br>
+ *   components from/into the bigger ones.<br>
+ * - first_component parameter allows skipping source components.<br>
+ */<br>
+void<br>
+shuffle_src_to_dst(const fs_builder &bld,<br>
+                   const fs_reg &dst,<br>
+                   const fs_reg &src,<br>
+                   uint32_t first_component,<br>
+                   uint32_t components)<br>
+{<br>
+   if (type_sz(src.type) == type_sz(dst.type)) {<br>
+      assert(!regions_overlap(dst,<br>
+         type_sz(dst.type) * bld.dispatch_width() * components,<br>
+         offset(src, bld, first_component),<br>
+         type_sz(src.type) * bld.dispatch_width() * components));<br>
+      for (unsigned i = 0; i < components; i++) {<br>
+         bld.MOV(retype(offset(dst, bld, i), src.type),<br>
+                 offset(src, bld, i + first_component));<br>
+      }<br>
+   } else if (type_sz(src.type) < type_sz(dst.type)) {<br>
+      /* Source is shuffled into destination */<br>
+      unsigned size_ratio = type_sz(dst.type) / type_sz(src.type);<br>
+      assert(!regions_overlap(dst,<br>
+         type_sz(dst.type) * bld.dispatch_width() *<br>
+         DIV_ROUND_UP(components, size_ratio),<br>
+         offset(src, bld, first_component),<br>
+         type_sz(src.type) * bld.dispatch_width() * components));<br>
+<br>
+      brw_reg_type shuffle_type =<br>
+         brw_reg_type_from_bit_size(8 * type_sz(src.type),<br>
+                                    BRW_REGISTER_TYPE_D);<br>
+      for (unsigned i = 0; i < components; i++) {<br>
+         fs_reg shuffle_component_i =<br>
+            subscript(offset(dst, bld, i / size_ratio),<br>
+                      shuffle_type, i % size_ratio);<br>
+         bld.MOV(shuffle_component_i,<br>
+                 retype(offset(src, bld, i + first_component), shuffle_type));<br>
+      }<br>
+   } else {<br>
+      /* Source is unshuffled into destination */<br>
+      unsigned size_ratio = type_sz(src.type) / type_sz(dst.type);<br>
+      assert(!regions_overlap(dst,<br>
+         type_sz(dst.type) * bld.dispatch_width() * components,<br>
+         offset(src, bld, first_component / size_ratio),<br>
+         type_sz(src.type) * bld.dispatch_width() *<br>
+         DIV_ROUND_UP(components + first_component, size_ratio)));<br></blockquote><div><br></div>This seems a bit high.  Do we want "DIV_ROUND_UP(components + (first_component % size_ratio), size_ratio)" instead?</div><div class="gmail_quote"><br></div><div class="gmail_quote">With that,</div><div class="gmail_quote"><br></div><div class="gmail_quote">Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><div class="gmail_quote"><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+      brw_reg_type shuffle_type =<br>
+         brw_reg_type_from_bit_size(8 * type_sz(dst.type),<br>
+                                    BRW_REGISTER_TYPE_D);<br>
+      for (unsigned i = 0; i < components; i++) {<br>
+         fs_reg shuffle_component_i =<br>
+            subscript(offset(src, bld, (first_component + i) / size_ratio),<br>
+                      shuffle_type, (first_component + i) % size_ratio);<br>
+         bld.MOV(retype(offset(dst, bld, i), shuffle_type),<br>
+                 shuffle_component_i);<br>
+      }<br>
+   }<br>
+}<br>
+<br>
 fs_reg<br>
 setup_imm_df(const fs_builder &bld, double v)<br>
 {<br>
<span class="HOEnZb"><font color="#888888">-- <br>
2.17.1<br>
<br>
</font></span></blockquote></div><br></div></div>