r600/sb: do not convert if-blocks that contain indirect array access
authorGert Wollny <gw.fossdev@gmail.com>
Wed, 6 Dec 2017 16:42:02 +0000 (17:42 +0100)
committerDave Airlie <airlied@redhat.com>
Wed, 6 Dec 2017 23:48:41 +0000 (09:48 +1000)
If an array is accessed within an if block, then currently it is not known
whether the value in the address register is involved in the evaluation of the
if condition, and converting the if condition may actually result in
out-of-bounds array access. Consequently, if blocks that contain indirect array
access should not be converted.

Fixes piglits on r600/BARTS:
spec/glsl-1.10/execution/variable-indexing/
  vs-output-array-float-index-wr
  vs-output-array-vec3-index-wr
  vs-output-array-vec4-index-wr

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104143

Signed-off-by: Gert Wollny <gw.fossdev@gmail.com>
Cc: <mesa-stable@lists.freedesktop.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/sb/sb_if_conversion.cpp
src/gallium/drivers/r600/sb/sb_ir.cpp
src/gallium/drivers/r600/sb/sb_ir.h

index 3f2b1b1..3f6431b 100644 (file)
@@ -136,7 +136,7 @@ bool if_conversion::check_and_convert(region_node *r) {
        );
 
        if (s.region_count || s.fetch_count || s.alu_kill_count ||
-                       s.if_count != 1 || s.repeat_count)
+                       s.if_count != 1 || s.repeat_count || s.uses_ar)
                return false;
 
        unsigned real_alu_count = s.alu_count - s.alu_copy_mov_count;
index d989dce..fe068ab 100644 (file)
@@ -461,6 +461,8 @@ void container_node::collect_stats(node_stats& s) {
                                ++s.alu_kill_count;
                        else if (a->is_copy_mov())
                                ++s.alu_copy_mov_count;
+                       if (a->uses_ar())
+                          s.uses_ar = true;
                } else if (n->is_fetch_inst())
                        ++s.fetch_count;
                else if (n->is_cf_inst())
index ec973e7..67c7cd8 100644 (file)
@@ -726,11 +726,12 @@ struct node_stats {
        unsigned depart_count;
        unsigned repeat_count;
        unsigned if_count;
+       bool uses_ar;
 
        node_stats() : alu_count(), alu_kill_count(), alu_copy_mov_count(),
                        cf_count(), fetch_count(), region_count(),
                        loop_count(), phi_count(), loop_phi_count(), depart_count(),
-                       repeat_count(), if_count() {}
+                       repeat_count(), if_count(), uses_ar(false) {}
 
        void dump();
 };