freedreno/ir3: don't allow negative const_offset
authorRob Clark <robdclark@chromium.org>
Thu, 7 May 2020 18:09:17 +0000 (11:09 -0700)
committerMarge Bot <eric+marge@anholt.net>
Tue, 12 May 2020 23:51:46 +0000 (23:51 +0000)
Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4954>

src/freedreno/ir3/ir3_nir_analyze_ubo_ranges.c

index d2fe65cd0e39498e1cf9fc63c0abb5c7734a884c..d8a285073f194502fb8217e501c0cd3c865ae08c 100644 (file)
@@ -143,7 +143,7 @@ gather_ubo_ranges(nir_shader *nir, nir_intrinsic_instr *instr,
  * with (ie. not requiring value range tracking)
  */
 static void
-handle_partial_const(nir_builder *b, nir_ssa_def **srcp, unsigned *offp)
+handle_partial_const(nir_builder *b, nir_ssa_def **srcp, int *offp)
 {
        if ((*srcp)->parent_instr->type != nir_instr_type_alu)
                return;
@@ -233,7 +233,7 @@ lower_ubo_load_to_uniform(nir_intrinsic_instr *instr, nir_builder *b,
        }
 
        nir_ssa_def *ubo_offset = nir_ssa_for_src(b, instr->src[1], 1);
-       unsigned const_offset = 0;
+       int const_offset = 0;
 
        handle_partial_const(b, &ubo_offset, &const_offset);
 
@@ -262,9 +262,20 @@ lower_ubo_load_to_uniform(nir_intrinsic_instr *instr, nir_builder *b,
                const_offset >>= 2;
        }
 
-       const int range_offset = (range->offset - range->start) / 4;
+       const int range_offset = ((int)range->offset - (int)range->start) / 4;
        const_offset += range_offset;
 
+       /* The range_offset could be negative, if if only part of the UBO
+        * block is accessed, range->start can be greater than range->offset.
+        * But we can't underflow const_offset.  If necessary we need to
+        * insert nir instructions to compensate (which can hopefully be
+        * optimized away)
+        */
+       if (const_offset < 0) {
+               uniform_offset = nir_iadd_imm(b, uniform_offset, const_offset);
+               const_offset = 0;
+       }
+
        nir_intrinsic_instr *uniform =
                nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_uniform);
        uniform->num_components = instr->num_components;