New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
spirv-opt improper inlining OpKill into continue construct #2433
Comments
This is a complicated issue, and it is not clear how to handle this case. The problem is that before inlining it looks like the continue target branches back the to loop header, but it does not. The function never returns. Inlining keeps the same semantics, it just exposes that the function never returns. No solutions seems obvious. We cannot create a new dummy continue target of the function call has no return because other parts of the code have to be able to jump to the continue target. Breaking from the loop and doing the OpKill out of the loop only works if it is executed unconditionally. This will require some careful thought. I'll have to get back to it when I return from vacation in a couple weeks. |
My preferred solution (and the one I implemented in Kazan) is to treat the continue construct like a case construct in that it can fall through to the loop header, jump to merge targets, execute OpKill, and execute OpReturn*. Continue construct parsing in implementation of structure parser (structures somewhat modified but map directly to official structures): |
@programmerjake What code that does come from? I'm guessing that this is glsl code where the function in the continue contains an OpKill somewhere in the call tree. Is this a common pattern? From what I can tell, the current version of the spec allows the OpKill in the continue construct, but I don't believe it was intended. I'm trying to get clarification on this. Having an idea of what is done in real code might be useful. |
@s-perron It does come from glsl that has a call inside a continue construct to a function that has |
It is illegal to inline an OpKill instruction into a continue construct because the continue header will no longer dominate the backedge. This commit adds a check for this, and does not inline. If we still want to be able to inline a function that contains an OpKill, we can add a new pass that will wrap OpKill instructions into its own function with just the single instruction. I do not believe that this is a common case right now, so I will not do that yet. Fixes #2433.
There was a bug in the fix for this issue. I had to be reverted. |
The solution I had relies on two analysies: dominator trees and inst-to-block. Neither of which are kept up-to-date during inlining. So if we have A calls B class C. First we inline B into A. Then, when trying to inline C into A, the inst-to-block mapping it out of date and we get a segmentation fault. |
maybe add a map with "function contains reachable OpKill" and track during inlining? |
My code had a map. The problem was determining if the function all is inside of a continue construct. To determine that, I need the basic block the function call belongs to (inst-to-block mapping) and know that it dominated by the continue target for the loop it is in (dominator-trees). If I simply chose to not inline any function containing an OpKill, then many shader will be able to be correctly legalized. We would have to implement #2726 first. I will see if there is another way to keep track of whether or not we are in a continue construct. |
create a map tracking which call instructions are in continue constructs? that shouldn't be that hard to track and can be used in conjunction with the opkill-containing map to stop inlining. another alternative is to create a separate function with a body that's just OpKill and replace all other opkills with a call to that function (edit: idea was already in #2726) |
We are no able to inline OpKill instructions into a continue construct. See KhronosGroup#2433. However, we have to be able to inline to correctly do legalization. This commit creates a pass that will wrap OpKill instructions into a function of its own. That way we are able to inline the rest of the code. The follow up to this will be to not inline any function that contains an OpKill. Fixes KhronosGroup#2726
We are no able to inline OpKill instructions into a continue construct. See KhronosGroup#2433. However, we have to be able to inline to correctly do legalization. This commit creates a pass that will wrap OpKill instructions into a function of its own. That way we are able to inline the rest of the code. The follow up to this will be to not inline any function that contains an OpKill. Fixes KhronosGroup#2726
We are no able to inline OpKill instructions into a continue construct. See #2433. However, we have to be able to inline to correctly do legalization. This commit creates a pass that will wrap OpKill instructions into a function of its own. That way we are able to inline the rest of the code. The follow up to this will be to not inline any function that contains an OpKill. Fixes #2726
If an OpKill instruction is inlined into a continue construct, then the spir-v is no longer valid. To avoid this issue, we do inline into an OpKill at all. This method was chosen because it is difficult to keep track of whether or not you are in a continue construct while changing the function that is being inlined into. This will work well with wrap OpKill because every will still be inlined except for the OpKill instruction itself. Fixes KhronosGroup#2554 Fixes KhronosGroup#2433 This reverts commit aa9e8f5.
If an OpKill instruction is inlined into a continue construct, then the spir-v is no longer valid. To avoid this issue, we do inline into an OpKill at all. This method was chosen because it is difficult to keep track of whether or not you are in a continue construct while changing the function that is being inlined into. This will work well with wrap OpKill because every will still be inlined except for the OpKill instruction itself. Fixes #2554 Fixes #2433 This reverts commit aa9e8f5.
@alan-baker asked me to open this issue here from KhronosGroup/SPIRV-Headers#86
Original issue:
Is a continue construct that consists of OpKill valid? If so, the rules on the header block post-dominating the continue construct need to be fixed. Otherwise, there's a bug in spirv-opt where
kill()
is improperly inlined.http://shader-playground.timjones.io/1323167d9be3ec6d7a54996e098612de
spirv-opt output:
spirv-opt input:
The text was updated successfully, but these errors were encountered: