On Sun Aug 13 22:07:38 2023 +0000, Zebediah Figura wrote:
Okay, after working out the source of the confusion offline, I see the problem I was missing. The issue is that sm4 MOVC does what's effectively an integer comparison to zero, but the ternary operator does a per-type comparison to zero. I was figuring that we could reuse one or the other since they're the same thing, but they're not: ternary treats floating point negative zero as false, but MOVC treats it as true (since it has a nonzero bit representation). So with that in mind, our semantics are essentially non-overlapping: TERNARY means per-type compare to zero, MOVC means bitwise compare to zero, and CMP is of course compare >= 0. -- One thing that did come out of that discussion is that lowering passes over the HLSL IR may not be the best way to do these transformations. In general, for a translation like these, or (say) lower_division(), there are three options: (1) Generate multiple low-level instructions. This makes less sense if the lowering needs to be done per-backend. But we do this in other cases, such as subtraction. (2) Generate a high-level instruction, and use a pass to lower it to another HLSL instruction. (3) Generate a high-level instruction, and translate it to multiple low-level instructions when translating to another form of IR (or directly to the bytecode). Historically, I've done (2) because it seemed like the most obvious thing to do. It does have the disadvantage that there are more ops in the HLSL, although honestly having a proliferation of expr ops isn't that bad. It is pretty much universally more code, though, so in general we may want to start leaning toward (1) or (3). Anyway, I don't see this as a reason to object to this patch series; I think it's ultimately not going in a wrong direction. But it's something we may want to think about in the future and try to inform the way we design IR.
This does, however, need a rebase.