nir_opt_cse getting ssa defined inside a loop to be used out of the loop
Some context to explain the issue better:
Right the following test is failing with v3dv: dEQP-VK.graphicsfuzz.cov-loop-condition-clamp-vec-of-ones
During the NIR to VIR (V3D IR) conversion it detects a non-const ubo index, that the driver doesn't support. But that is not the case on the original spirv-to-nir shader. We understand that having a ubo index going from const to non-const is also non desirable, even for drivers that supports it.
We found that this const to non-const conversion happens on the loop unrolling. Disabling loop unrolling gets the test working for v3dv. But @tarceri properly pointed that the shader is already non-fully-correct when loop unroll is called, because the ubo index comes from inside a previous loop, that should be out of the scope of the load_ubo out of the loop.
Checking when this starts to happen, it happens after calling nir_opt_cse. Disabling (by hand) this optimization also gets the test to pass on v3dv.
nir_opt_cse itself is simple, as it basically calls nir_instr_set_add_or_rewrite with all the instructions, using a block dominance condition. I guess that what it is needed to be done is update this condition, to add some extra checks, but not 100% sure.
With this issue I'm attaching the nir shaders before and after calling this optimization. The easier way to see this issue it using as reference the last load_ubo of the shader. Before the optimization the ubo index is computed just before the load_ubo and using a const (ssa_111) that was defined just at the beginning of the shader. After the optimization the load_ubo uses ssa_164 as ubo index, that it is defined inside the loop, on a previous block.