nir/deref: Preserve alignments in opt_remove_cast_cast()

This also removes the loop so opt_remove_cast_cast() will only optimize
cast(cast(x)) and not cast(cast(cast(x))).  However, since nir_opt_deref
walks instructions top-down, there will almost never be a tripple cast
because the parent cast will have opt_remove_cast_cast() run on it.

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
(cherry picked from commit af9212dd82)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21467>
This commit is contained in:
Faith Ekstrand 2023-02-10 16:21:19 -06:00 committed by Marge Bot
parent d55de21f0f
commit 785cf85296

View file

@ -1024,19 +1024,28 @@ opt_remove_restricting_cast_alignments(nir_deref_instr *cast)
static bool
opt_remove_cast_cast(nir_deref_instr *cast)
{
nir_deref_instr *first_cast = cast;
while (true) {
nir_deref_instr *parent = nir_deref_instr_parent(first_cast);
if (parent == NULL || parent->deref_type != nir_deref_type_cast)
break;
first_cast = parent;
}
if (cast == first_cast)
nir_deref_instr *parent = nir_deref_instr_parent(cast);
if (parent == NULL || parent->deref_type != nir_deref_type_cast)
return false;
/* Copy align info from the parent cast if needed
*
* In the case that align_mul = 0, the alignment for this cast is inhereted
* from the parent deref (if any). If we aren't careful, removing our
* parent cast from the chain may lose alignment information so we need to
* copy the parent's alignment information (if any).
*
* opt_remove_restricting_cast_alignments() above is run before this pass
* and will will have cleared our alignment (set align_mul = 0) in the case
* where the parent's alignment information is somehow superior.
*/
if (cast->cast.align_mul == 0) {
cast->cast.align_mul = parent->cast.align_mul;
cast->cast.align_offset = parent->cast.align_offset;
}
nir_instr_rewrite_src(&cast->instr, &cast->parent,
nir_src_for_ssa(first_cast->parent.ssa));
nir_src_for_ssa(parent->parent.ssa));
return true;
}