<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Aug 24, 2016 at 9:04 PM, Matt Turner <span dir="ltr"><<a href="mailto:mattst88@gmail.com" target="_blank">mattst88@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Prior to this commit rename_variables_block() is recursively called,<br>
performing a depth-first traversal of the control flow graph. The<br>
function uses a non-trivial amount of stack space for local variables,<br>
which puts us in danger of smashing the stack, given a sufficiently deep<br>
dominance tree.<br>
<br>
XCOM: Enemy Within contains a shader with such a dominance tree (1574<br>
nir_blocks in total, depth of at least 143).<br>
<br>
Jason tells me that he believes that any walk over the nir_blocks that<br>
respects dominance is sufficient (a DFS might have been necessary prior<br>
to the introduction of nir_phi_builder).<br>
<br>
In fact, the introduction of nir_phi_builder made the problem worse:<br>
rename_variables_block(), walks to the bottom of the dominance tree<br>
before calling nir_phi_builder_value_get_<wbr>block_def() which walks back to<br>
the top of the dominance tree...<br>
<br>
In any case, this patch ensures we avoid that problem as well.<br>
<br>
Cc: <a href="mailto:mesa-stable@lists.freedesktop.org">mesa-stable@lists.freedesktop.<wbr>org</a><br>
Bugzilla: <a href="https://bugs.freedesktop.org/show_bug.cgi?id=97225" rel="noreferrer" target="_blank">https://bugs.freedesktop.org/<wbr>show_bug.cgi?id=97225</a><br>
---<br>
Most easily reviewed with git show -w<br></blockquote><div><br></div><div>Yes, yes it is. :)<br><br></div><div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
src/compiler/nir/nir_lower_<wbr>vars_to_ssa.c | 207 +++++++++++++++---------------<wbr>-<br>
1 file changed, 103 insertions(+), 104 deletions(-)<br>
<br>
diff --git a/src/compiler/nir/nir_lower_<wbr>vars_to_ssa.c b/src/compiler/nir/nir_lower_<wbr>vars_to_ssa.c<br>
index 317647b..e2e13e2 100644<br>
--- a/src/compiler/nir/nir_lower_<wbr>vars_to_ssa.c<br>
+++ b/src/compiler/nir/nir_lower_<wbr>vars_to_ssa.c<br>
@@ -479,133 +479,132 @@ lower_copies_to_load_store(<wbr>struct deref_node *node,<br>
* SSA def on the stack per block.<br>
*/<br>
static bool<br>
-rename_variables_block(nir_<wbr>block *block, struct lower_variables_state *state)<br>
+rename_variables(struct lower_variables_state *state)<br>
{<br>
nir_builder b;<br>
nir_builder_init(&b, state->impl);<br>
<br>
- nir_foreach_instr_safe(instr, block) {<br>
- if (instr->type != nir_instr_type_intrinsic)<br>
- continue;<br>
-<br>
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);<br>
-<br>
- switch (intrin->intrinsic) {<br>
- case nir_intrinsic_load_var: {<br>
- struct deref_node *node =<br>
- get_deref_node(intrin-><wbr>variables[0], state);<br>
-<br>
- if (node == NULL) {<br>
- /* If we hit this path then we are referencing an invalid<br>
- * value. Most likely, we unrolled something and are<br>
- * reading past the end of some array. In any case, this<br>
- * should result in an undefined value.<br>
- */<br>
- nir_ssa_undef_instr *undef =<br>
- nir_ssa_undef_instr_create(<wbr>state->shader,<br>
- intrin->num_components,<br>
- intrin->dest.ssa.bit_size);<br>
-<br>
- nir_instr_insert_before(&<wbr>intrin->instr, &undef->instr);<br>
- nir_instr_remove(&intrin-><wbr>instr);<br>
-<br>
- nir_ssa_def_rewrite_uses(&<wbr>intrin->dest.ssa,<br>
- nir_src_for_ssa(&undef->def));<br>
+ nir_foreach_block(block, state->impl) {<br>
+ nir_foreach_instr_safe(instr, block) {<br>
+ if (instr->type != nir_instr_type_intrinsic)<br>
continue;<br>
- }<br>
<br>
- if (!node->lower_to_ssa)<br>
- continue;<br>
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);<br>
+<br>
+ switch (intrin->intrinsic) {<br>
+ case nir_intrinsic_load_var: {<br>
+ struct deref_node *node =<br>
+ get_deref_node(intrin-><wbr>variables[0], state);<br>
+<br>
+ if (node == NULL) {<br>
+ /* If we hit this path then we are referencing an invalid<br>
+ * value. Most likely, we unrolled something and are<br>
+ * reading past the end of some array. In any case, this<br>
+ * should result in an undefined value.<br>
+ */<br>
+ nir_ssa_undef_instr *undef =<br>
+ nir_ssa_undef_instr_create(<wbr>state->shader,<br>
+ intrin->num_components,<br>
+ intrin->dest.ssa.bit_size);<br>
+<br>
+ nir_instr_insert_before(&<wbr>intrin->instr, &undef->instr);<br>
+ nir_instr_remove(&intrin-><wbr>instr);<br>
+<br>
+ nir_ssa_def_rewrite_uses(&<wbr>intrin->dest.ssa,<br>
+ nir_src_for_ssa(&undef->def));<br>
+ continue;<br>
+ }<br>
<br>
- nir_alu_instr *mov = nir_alu_instr_create(state-><wbr>shader,<br>
- nir_op_imov);<br>
- mov->src[0].src = nir_src_for_ssa(<br>
- nir_phi_builder_value_get_<wbr>block_def(node->pb_value, block));<br>
- for (unsigned i = intrin->num_components; i < 4; i++)<br>
- mov->src[0].swizzle[i] = 0;<br>
+ if (!node->lower_to_ssa)<br>
+ continue;<br>
<br>
- assert(intrin->dest.is_ssa);<br>
+ nir_alu_instr *mov = nir_alu_instr_create(state-><wbr>shader,<br>
+ nir_op_imov);<br>
+ mov->src[0].src = nir_src_for_ssa(<br>
+ nir_phi_builder_value_get_<wbr>block_def(node->pb_value, block));<br>
+ for (unsigned i = intrin->num_components; i < 4; i++)<br>
+ mov->src[0].swizzle[i] = 0;<br>
<br>
- mov->dest.write_mask = (1 << intrin->num_components) - 1;<br>
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest,<br>
- intrin->num_components,<br>
- intrin->dest.ssa.bit_size, NULL);<br>
+ assert(intrin->dest.is_ssa);<br>
<br>
- nir_instr_insert_before(&<wbr>intrin->instr, &mov->instr);<br>
- nir_instr_remove(&intrin-><wbr>instr);<br>
+ mov->dest.write_mask = (1 << intrin->num_components) - 1;<br>
+ nir_ssa_dest_init(&mov->instr, &mov->dest.dest,<br>
+ intrin->num_components,<br>
+ intrin->dest.ssa.bit_size, NULL);<br>
<br>
- nir_ssa_def_rewrite_uses(&<wbr>intrin->dest.ssa,<br>
- nir_src_for_ssa(&mov->dest.<wbr>dest.ssa));<br>
- break;<br>
- }<br>
-<br>
- case nir_intrinsic_store_var: {<br>
- struct deref_node *node =<br>
- get_deref_node(intrin-><wbr>variables[0], state);<br>
-<br>
- if (node == NULL) {<br>
- /* Probably an out-of-bounds array store. That should be a<br>
- * no-op. */<br>
+ nir_instr_insert_before(&<wbr>intrin->instr, &mov->instr);<br>
nir_instr_remove(&intrin-><wbr>instr);<br>
- continue;<br>
- }<br>
<br>
- if (!node->lower_to_ssa)<br>
- continue;<br>
-<br>
- assert(intrin->num_components ==<br>
- glsl_get_vector_elements(node-<wbr>>type));<br>
-<br>
- assert(intrin->src[0].is_ssa);<br>
+ nir_ssa_def_rewrite_uses(&<wbr>intrin->dest.ssa,<br>
+ nir_src_for_ssa(&mov->dest.<wbr>dest.ssa));<br>
+ break;<br>
+ }<br>
<br>
- nir_ssa_def *new_def;<br>
- b.cursor = nir_before_instr(&intrin-><wbr>instr);<br>
+ case nir_intrinsic_store_var: {<br>
+ struct deref_node *node =<br>
+ get_deref_node(intrin-><wbr>variables[0], state);<br>
<br>
- unsigned wrmask = nir_intrinsic_write_mask(<wbr>intrin);<br>
- if (wrmask == (1 << intrin->num_components) - 1) {<br>
- /* Whole variable store - just copy the source. Note that<br>
- * intrin->num_components and intrin->src[0].ssa->num_<wbr>components<br>
- * may differ.<br>
- */<br>
- unsigned swiz[4];<br>
- for (unsigned i = 0; i < 4; i++)<br>
- swiz[i] = i < intrin->num_components ? i : 0;<br>
+ if (node == NULL) {<br>
+ /* Probably an out-of-bounds array store. That should be a<br>
+ * no-op. */<br>
+ nir_instr_remove(&intrin-><wbr>instr);<br>
+ continue;<br>
+ }<br>
<br>
- new_def = nir_swizzle(&b, intrin->src[0].ssa, swiz,<br>
- intrin->num_components, false);<br>
- } else {<br>
- nir_ssa_def *old_def =<br>
- nir_phi_builder_value_get_<wbr>block_def(node->pb_value, block);<br>
- /* For writemasked store_var intrinsics, we combine the newly<br>
- * written values with the existing contents of unwritten<br>
- * channels, creating a new SSA value for the whole vector.<br>
- */<br>
- nir_ssa_def *srcs[4];<br>
- for (unsigned i = 0; i < intrin->num_components; i++) {<br>
- if (wrmask & (1 << i)) {<br>
- srcs[i] = nir_channel(&b, intrin->src[0].ssa, i);<br>
- } else {<br>
- srcs[i] = nir_channel(&b, old_def, i);<br>
+ if (!node->lower_to_ssa)<br>
+ continue;<br>
+<br>
+ assert(intrin->num_components ==<br>
+ glsl_get_vector_elements(node-<wbr>>type));<br>
+<br>
+ assert(intrin->src[0].is_ssa);<br>
+<br>
+ nir_ssa_def *new_def;<br>
+ b.cursor = nir_before_instr(&intrin-><wbr>instr);<br>
+<br>
+ unsigned wrmask = nir_intrinsic_write_mask(<wbr>intrin);<br>
+ if (wrmask == (1 << intrin->num_components) - 1) {<br>
+ /* Whole variable store - just copy the source. Note that<br>
+ * intrin->num_components and intrin->src[0].ssa->num_<wbr>components<br>
+ * may differ.<br>
+ */<br>
+ unsigned swiz[4];<br>
+ for (unsigned i = 0; i < 4; i++)<br>
+ swiz[i] = i < intrin->num_components ? i : 0;<br>
+<br>
+ new_def = nir_swizzle(&b, intrin->src[0].ssa, swiz,<br>
+ intrin->num_components, false);<br>
+ } else {<br>
+ nir_ssa_def *old_def =<br>
+ nir_phi_builder_value_get_<wbr>block_def(node->pb_value, block);<br>
+ /* For writemasked store_var intrinsics, we combine the newly<br>
+ * written values with the existing contents of unwritten<br>
+ * channels, creating a new SSA value for the whole vector.<br>
+ */<br>
+ nir_ssa_def *srcs[4];<br>
+ for (unsigned i = 0; i < intrin->num_components; i++) {<br>
+ if (wrmask & (1 << i)) {<br>
+ srcs[i] = nir_channel(&b, intrin->src[0].ssa, i);<br>
+ } else {<br>
+ srcs[i] = nir_channel(&b, old_def, i);<br>
+ }<br>
}<br>
+ new_def = nir_vec(&b, srcs, intrin->num_components);<br>
}<br>
- new_def = nir_vec(&b, srcs, intrin->num_components);<br>
- }<br>
<br>
- assert(new_def->num_components == intrin->num_components);<br>
+ assert(new_def->num_components == intrin->num_components);<br>
<br>
- nir_phi_builder_value_set_<wbr>block_def(node->pb_value, block, new_def);<br>
- nir_instr_remove(&intrin-><wbr>instr);<br>
- break;<br>
- }<br>
+ nir_phi_builder_value_set_<wbr>block_def(node->pb_value, block, new_def);<br>
+ nir_instr_remove(&intrin-><wbr>instr);<br>
+ break;<br>
+ }<br>
<br>
- default:<br>
- break;<br>
+ default:<br>
+ break;<br>
+ }<br>
}<br>
}<br>
<br>
- for (unsigned i = 0; i < block->num_dom_children; ++i)<br>
- rename_variables_block(block-><wbr>dom_children[i], state);<br>
-<br>
return true;<br>
}<br>
<br>
@@ -737,7 +736,7 @@ nir_lower_vars_to_ssa_impl(<wbr>nir_function_impl *impl)<br>
}<br>
}<br>
<br>
- rename_variables_block(nir_<wbr>start_block(impl), &state);<br>
+ rename_variables(&state);<br>
<br>
nir_phi_builder_finish(state.<wbr>phi_builder);<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
2.7.3<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>