diff options
author | Nicolai Hähnle <[email protected]> | 2016-11-17 22:24:07 +0100 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2016-11-21 08:18:47 +0100 |
commit | 47db6b4600cfd3919c6120d392950d624b5a6ea7 (patch) | |
tree | 8573d6de77895c8bc80f79b8239952db0f3c6209 /src/compiler | |
parent | 39c47e7698fdcc6fc215daf973d8762cfb8b02ca (diff) |
glsl: don't flatten if-blocks with dynamic array indices
This fixes the regression of radeonsi in
glsl-1.10/execution/variable-indexing/vs-output-array-vec3-index-wr
caused by commit 74e39de9324d2d2333cda6adca50ae2a3fc36de2.
Acked-by: Edward O'Callaghan <[email protected]>
Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/glsl/lower_if_to_cond_assign.cpp | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/compiler/glsl/lower_if_to_cond_assign.cpp b/src/compiler/glsl/lower_if_to_cond_assign.cpp index ae048be0d27..37f1ec8600c 100644 --- a/src/compiler/glsl/lower_if_to_cond_assign.cpp +++ b/src/compiler/glsl/lower_if_to_cond_assign.cpp @@ -86,6 +86,7 @@ public: bool found_unsupported_op; bool found_expensive_op; + bool found_dynamic_arrayref; bool is_then; bool progress; gl_shader_stage stage; @@ -148,8 +149,13 @@ check_ir_node(ir_instruction *ir, void *data) v->found_expensive_op = true; break; + case ir_type_dereference_array: { + ir_dereference_array *deref = ir->as_dereference_array(); + + if (deref->array_index->ir_type != ir_type_constant) + v->found_dynamic_arrayref = true; + } /* fall-through */ case ir_type_expression: - case ir_type_dereference_array: case ir_type_dereference_record: if (v->is_then) v->then_cost++; @@ -229,6 +235,7 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir) this->found_unsupported_op = false; this->found_expensive_op = false; + this->found_dynamic_arrayref = false; this->then_cost = 0; this->else_cost = 0; @@ -248,9 +255,17 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir) if (this->found_unsupported_op) return visit_continue; /* can't handle inner unsupported opcodes */ - /* Skip if the branch cost is high enough or if there's an expensive op. */ + /* Skip if the branch cost is high enough or if there's an expensive op. + * + * Also skip if non-constant array indices were encountered, since those + * can be out-of-bounds for a not-taken branch, and so generating an + * assignment would be incorrect. In the case of must_lower, it's up to the + * backend to deal with any potential fall-out (perhaps by translating the + * assignments to hardware-predicated moves). + */ if (!must_lower && (this->found_expensive_op || + this->found_dynamic_arrayref || MAX2(this->then_cost, this->else_cost) >= this->min_branch_cost)) return visit_continue; |