Flags isn’t the only way you can get poison in SelectionDAG; a bunch of operations produce poison. Among other things, we have shifts with an overflowing shift amount, overflowing fptosi, and AssertZext. IIRC we take advantage of the fptosi UB to avoid redundant masking in some cases.
I guess we could go through and limit those operations to something else instead… but I’m not quite sure what that would look like. Getting rid of poison isn’t that helpful if we still have undef (particularly if we’re going to try to get rid of undef at the IR level at some point). I guess we could get rid of undef too, but at that point I think you start seriously hurting target-independent SelectionDAG optimizations: every operation has to have a defined output for every possible input (except operations with a chain can be UB, or produce an output that’s “defined” based on the chain). I guess that would involve adding target-defined behavior for a bunch of operations, along the lines of getBooleanContents().
It makes sense say poison/undef don’t exist after isel. That might block some optimizations in theory, I guess, but I think that matches the way it currently works. (We currently have “undef” operands in MachineInstrs, but that isn’t the same thing.) Well, actually, I think the use of alias analysis in scheduling breaks this (since the result of a load which violates TBAA can be changed by the scheduler), but I don’t think that’s ever led to a practical issue.
-Eli