Skip to content

nir/divergence: calculate divergence without LCSSA requirement

This is a prerequisite to finally make divergence metadata.

The basic idea is to calculate loop invariance on-the-fly during divergence analysis. If an SSA def defined in a loop is uniform and not loop invariant (i.e. it computes a potentially different value on every loop iteration, like e.g. a loop counter), and the loop has a divergent break, then any use outside the loop must be considered divergent.

Previously, this was accomplished by using loop-closed SSA form (LCSSA) which places phi nodes at the loop exit, so that we could flag the phi def as divergent. With this series, this is no longer necessary. Instead, if the divergence of an instruction depends on the sources, we also check whether that source was computed with a higher degree of "temporal divergence" (yeah, I made that up, but I kinda like the term now :)). And if that is the case, we simply flag the definition as divergent. Keep in mind that this means that some instructions now might be flagged as divergent although they solely depend on uniform sources. So, if your backend uses divergence information to determine register classes, you should still lower to LCSSA. Likewise, LCSSA might be necessary in order to prevent other invalid transformations. Thus, I only removed the lowerings to LCSSA where I'm pretty certain that it doesn't cause any harm.

v2: Instead of instr::pass_flags indexing the number of nested divergent loops, this pass now just flags ssa-defs as loop_invariant and checks whether the definition is inside a loop with divergent break and the use is outside.

RFC!

@gfxstrand @cwabbott0 @pendingchaos @alyssa

Edited by Daniel Schürmann

Merge request reports