Could you please also fix `ftoi`?
Sure. I was more concerned about ftou, since it was one of the last things preventing Wine tests from working, but it shouldn't be too much more work to fix ftoi.
I had written a similar patch at some point. The reason why I hesitated sending it is that it's not completely clear what "Behavior is undefined" mean in the SPIR-V specification, since what your code does is to compute `ConvertFToU` anyway and then ignore it if the input is not in the range. According to the C/C++ meaning of "undefined behavior" this would be invalid: once you invoke UB there's nothing you can do to "go back", and even if you ignore the computed value the compiler has no obligations any more with you. If SPIR-V adopted the same meaning, which would sound plausible, your implementation (and mine as well) would be incorrect. Do you have any specific insight in this matter?
I don't have any better insight than you, and asking for a clarification on what undefined behaviour actually means would be a good thing.
I guess there are two questions here:
(1) can an "undefined" instruction do anything other than returning an arbitrary value, including cascading to further instructions that use that undefined value in computation?
I suspect the answer is, or will be, no, if nothing else then at least for arithmetic instructions. This is at least partially because it is hard for shaders to crash, or corrupt data, in a meaningful sense. I also suspect this is the intent because SPIR-V explicitly includes an OpUndef instruction, which would otherwise mean "please crash my computer". I also suspect this is the case because given the way shaders are designed, it's not really possible to avoid executing an undefined instruction; when branching is encountered shaders will basically execute both branches in parallel invocations, so all of the code gets run anyway.
(2) can an "undefined" instruction that is *not* used in computation [as with the OpSelect here] affect the result of that computation? E.g. can "<true> ? <value> : <undef>" yield anything other than <value>?
I suspect the answer is again no, although I don't have much better to base this on than "that's the simplest and most intuitive way for shaders to behave", and also again "what would be the point of OpUndef otherwise".
I don't *know* that the answers are no, and I think we should still request a spec clarification. But I think an answer of yes to either would make the language near unusable as a compiler target. Fundamentally, if this isn't enough to avoid undefined behaviour, I don't think anything is.
And it's worth pointing out that no spec will ever be perfect, and no "conformant" implementation will be perfect either, and this behaviour seems sensible, and fixes a problem in a way that aligns with what the spec's intent *looks* like.
Also, this isn't the first time that we've avoided undefined behaviour with an OpSelect—see again udiv.