Skip to content

nir/lower_returns: Append missing phis' sources after "break" insertion

After we lowered return into break - the control flow is changed and the block with this change has a new successor, which means that in this new successor phis should have additional source.

Since the instructions that use phis in the successor are predicated - it's ok for a new phi source to be undef.

If return is lowered in a nested loop, break is inserted in the outer loops, so all new blocks with break require the same changes to phis described above.

Examples of NIR before lowering:

  block block_0:
  loop {
     block block_1:
     if ssa_2 {
       block block_2:
       return
       // succs: block_6
     } else {
       block block_3:
       break;
       // succs: block_5
     }
     block block_4:
  }
  block block_5:
  // preds: block_3
  vec1 32 ssa_4 = phi block_3: ssa_1
  // succs: block_6
  block block_6:

Here converting return to break should add block_2 to the phis of block_5.

 block block_0:
 loop {
    block block_1:
    loop {
       block block_2:
       if ssa_2 {
         block block_3:
         return
         // succs: block_8
       } else {
         block block_4:
         break;
         // succs: block_6
       }
       block block_5:
    }
    block block_6:
    break;
    // succs: block_7
 }
 block block_7:
 // preds: block_6
 vec1 32 ssa_4 = phi block_6: ssa_1
 // succs: block_8
 block block_8:

Here converting return to break will insert conditional break in the outer loop, changing block_6 predcessors.

Cc: mesa-stable@lists.freedesktop.org Closes: #3322 (closed)

While the first test mirrors what happens in the issue above, while making the second one phis_after_outer_loop - I was unable to write a shader which will produce such NIR (I didn't try hard enough though).

Passes Intel CI: https://mesa-ci.01.org/global_logic/builds/288/group/63a9f0ea7bb98050796b649e85481845

Edited by Danylo Piliaiev

Merge request reports