intel/fs: Cap dst-aligned region stride to maximum representable hstride value.
authorFrancisco Jerez <currojerez@riseup.net>
Thu, 17 Jan 2019 02:49:47 +0000 (18:49 -0800)
committerFrancisco Jerez <currojerez@riseup.net>
Thu, 21 Feb 2019 22:07:25 +0000 (14:07 -0800)
This is required in combination with the following commit, because
otherwise if a source region with an extended 8+ stride is present in
the instruction (which we're about to declare legal) we'll end up
emitting code that attempts to write to such a region, even though
strides greater than four are still illegal for the destination.

Tested-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/intel/compiler/brw_fs_lower_regioning.cpp

index 6a3c23892b4ad2dde2c3b3f2e5bb915d0019617b..c60d47004191a542bf72ad6a0ebebae0ac6ca5b3 100644 (file)
@@ -71,15 +71,33 @@ namespace {
           !is_byte_raw_mov(inst)) {
          return get_exec_type_size(inst);
       } else {
-         unsigned stride = inst->dst.stride * type_sz(inst->dst.type);
+         /* Calculate the maximum byte stride and the minimum/maximum type
+          * size across all source and destination operands we are required to
+          * lower.
+          */
+         unsigned max_stride = inst->dst.stride * type_sz(inst->dst.type);
+         unsigned min_size = type_sz(inst->dst.type);
+         unsigned max_size = type_sz(inst->dst.type);
 
          for (unsigned i = 0; i < inst->sources; i++) {
-            if (!is_uniform(inst->src[i]) && !inst->is_control_source(i))
-               stride = MAX2(stride, inst->src[i].stride *
-                             type_sz(inst->src[i].type));
+            if (!is_uniform(inst->src[i]) && !inst->is_control_source(i)) {
+               const unsigned size = type_sz(inst->src[i].type);
+               max_stride = MAX2(max_stride, inst->src[i].stride * size);
+               min_size = MIN2(min_size, size);
+               max_size = MAX2(max_size, size);
+            }
          }
 
-         return stride;
+         /* All operands involved in lowering need to fit in the calculated
+          * stride.
+          */
+         assert(max_size <= 4 * min_size);
+
+         /* Attempt to use the largest byte stride among all present operands,
+          * but never exceed a stride of 4 since that would lead to illegal
+          * destination regions during lowering.
+          */
+         return MIN2(max_stride, 4 * min_size);
       }
    }