diff options
author | Dave Airlie <[email protected]> | 2014-11-28 00:49:48 +0000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2014-12-02 13:57:27 +1000 |
commit | 7b0067d23a6f64cf83c42e7f11b2cd4100c569fe (patch) | |
tree | c1b19a88e374755ce463457f31daa94bcd9d1732 /src/gallium/drivers/r600/sb | |
parent | 036f434ac2dfed6ff730a1bd8f74eafd95bcad4e (diff) |
r600g/sb: fix issues cause by GLSL switching to loops for switch
Since 73dd50acf6d244979c2a657906aa56d3ac60d550
glsl: implement switch flow control using a loop
The SB backend was falling over in an assert or crashing.
Tracked this down to the loops having no repeats, but requiring
a working break, initial code just called the loop handler for
all non-if statements, but this caused a regression in
tests/shaders/dead-code-break-interaction.shader_test.
So I had to add further code to detect if all the departure
nodes are empty and avoid generating an empty loop for that case.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86089
Cc: "10.4" <[email protected]>
Reviewed-By: Glenn Kennard <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium/drivers/r600/sb')
-rw-r--r-- | src/gallium/drivers/r600/sb/sb_bc_finalize.cpp | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp index f0849ca6b6b..0fa0910ba17 100644 --- a/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp +++ b/src/gallium/drivers/r600/sb/sb_bc_finalize.cpp @@ -46,15 +46,22 @@ int bc_finalizer::run() { for (regions_vec::reverse_iterator I = rv.rbegin(), E = rv.rend(); I != E; ++I) { region_node *r = *I; - + bool is_if = false; assert(r); - bool loop = r->is_loop(); + assert(r->first); + if (r->first->is_container()) { + container_node *repdep1 = static_cast<container_node*>(r->first); + assert(repdep1->is_depart() || repdep1->is_repeat()); + if_node *n_if = static_cast<if_node*>(repdep1->first); + if (n_if && n_if->is_if()) + is_if = true; + } - if (loop) - finalize_loop(r); - else + if (is_if) finalize_if(r); + else + finalize_loop(r); r->expand(); } @@ -112,16 +119,33 @@ void bc_finalizer::finalize_loop(region_node* r) { cf_node *loop_start = sh.create_cf(CF_OP_LOOP_START_DX10); cf_node *loop_end = sh.create_cf(CF_OP_LOOP_END); + bool has_instr = false; + + if (!r->is_loop()) { + for (depart_vec::iterator I = r->departs.begin(), E = r->departs.end(); + I != E; ++I) { + depart_node *dep = *I; + if (!dep->empty()) { + has_instr = true; + break; + } + } + } else + has_instr = true; - loop_start->jump_after(loop_end); - loop_end->jump_after(loop_start); + if (has_instr) { + loop_start->jump_after(loop_end); + loop_end->jump_after(loop_start); + } for (depart_vec::iterator I = r->departs.begin(), E = r->departs.end(); I != E; ++I) { depart_node *dep = *I; - cf_node *loop_break = sh.create_cf(CF_OP_LOOP_BREAK); - loop_break->jump(loop_end); - dep->push_back(loop_break); + if (has_instr) { + cf_node *loop_break = sh.create_cf(CF_OP_LOOP_BREAK); + loop_break->jump(loop_end); + dep->push_back(loop_break); + } dep->expand(); } @@ -137,8 +161,10 @@ void bc_finalizer::finalize_loop(region_node* r) { rep->expand(); } - r->push_front(loop_start); - r->push_back(loop_end); + if (has_instr) { + r->push_front(loop_start); + r->push_back(loop_end); + } } void bc_finalizer::finalize_if(region_node* r) { |