If all the shifts amount are already poison-producing,
then we can add more poison-producing flags ontop:
https://rise4fun.com/Alive/Ocwi
Otherwise, we should only consider the possible range of shift amts that don't result in poison.
For unsigned range not not overflow, we must not shift out any set bits,
and the actual limit for x can be computed by backtransforming
the maximal value we could ever get out of the shl - -1 through
lshr. If the x is any larger than that then it will overflow.
Likewise for signed range, but just in signed domain..
This is based on the general idea outlined by @nikic in https://reviews.llvm.org/D68672#1714990
While an empty set here is conservatively correct, I believe that the more precise return value would be the range containing only zero [0, 1). The shift amount is < the bitwidth by assumption (otherwise the result is poison), and [0, 1) is the result for the worst-case assumption of shift amount = bitwidth - 1.
Even more precise would be to intersect the incoming range with [0, BitWidth), which may differ non-trivially from this approach for wrapped ranges. E.g. if you have a signed range [INT_MIN, 5), the UMax will be UINT_MAX, but the intersection [INT_MIN, 5) /\ [0, 32) is [0, 5) and the UMax will be 4, resulting in a much larger guaranteed nowrap region.