[Mlir-commits] [mlir] [mlir][spirv] Split conditional basic blocks during deserialization (PR #127639)
Igor Wodiany
llvmlistbot at llvm.org
Wed Feb 19 09:25:38 PST 2025
IgWod-IMG wrote:
I have replaced `std::distance()` and updated test, so hopefully it's more readable now.
Regarding the bigger issue. I have redesigned the code so now it only splits conditional blocks that are headers of selection regions. Loops are not touched. Looking at loops (https://mlir.llvm.org/docs/Dialects/SPIR-V/#loop) the entry block will always be unconditional, so splitting would not be applied here. Then conditional blocks that form the loop header and continue will be fully sunk anyway, regardless of splitting, so we can skip splitting them.
So, to sum up. This PR only targets selection regions (which so far were the only problem on my side when it comes to sinking), and if we need anything for loops, we can work it out in the future.
@mishaobu please let me know if the new patch causes any issues. Loops should be untouched now, so they should keep their structure (unless something else is going on). The `if` statement looked the same in both code snippets, so I hope splitting doesn't cause any issues there. Just to verify, I attempted to run your `raymarchwater` (GLSL -> SPIR-V -> MLIR -> SPIR-V -> GLSL) and I got the function as you would with your patch. Let me know your thoughts.
There is still an extra block in one of the tests:
```mlir
spirv.func @selection_cf() "None" {
%0 = spirv.Variable : !spirv.ptr<i1, Function>
spirv.Branch ^bb1
^bb1: // pred: ^bb0
%true = spirv.Constant true
spirv.Branch ^bb2
^bb2: // pred: ^bb1
spirv.mlir.selection {
spirv.BranchConditional %true, ^bb1, ^bb2
^bb1: // pred: ^bb0
%true_1 = spirv.Constant true
spirv.Store "Function" %0, %true_1 : i1
spirv.Branch ^bb3
^bb2: // pred: ^bb0
%false = spirv.Constant false
spirv.Store "Function" %0, %false : i1
spirv.Branch ^bb3
^bb3: // 2 preds: ^bb1, ^bb2
spirv.mlir.merge
}
```
Compared against:
```mlir
spirv.func @selection_cf() "None" {
%0 = spirv.Variable : !spirv.ptr<i1, Function>
spirv.Branch ^bb1
^bb1: // pred: ^bb0
spirv.mlir.selection {
%true = spirv.Constant true
spirv.BranchConditional %true, ^bb1, ^bb2
^bb1: // pred: ^bb0
%true_1 = spirv.Constant true
spirv.Store "Function" %0, %true_1 : i1
spirv.Branch ^bb3
^bb2: // pred: ^bb0
%false = spirv.Constant false
spirv.Store "Function" %0, %false : i1
spirv.Branch ^bb3
^bb3: // 2 preds: ^bb1, ^bb2
spirv.mlir.merge
}
```
It happens because the `%true` constant gets pushed outside the selection region. Arguably this works as intended; the header block gets split. From my perspective this is a rather minor issue (that will probably get optimised at some later stages anyway), and I think a price worth paying for a more robust deserialization. And improving it is something that can be addressed in the future. @kuhar do you have any thoughts on that?
Nevertheless, if we cannot reach a consensus, I'm happy to look for an alternative fix. Potentially taking @mishaobu implementation and getting it into a mergeable state.
https://github.com/llvm/llvm-project/pull/127639
More information about the Mlir-commits
mailing list