In canCreateUndefOrPoison(), take not only poison-generating flags, but also poison-generating metadata into account. The helpers are written generally, but I believe the only case that can actually matter is !range on calls -- !nonnull and !align are only valid on loads, can those can create undef/poison anyway.
Unfortunately, this negatively impacts logical to bitwise and/or conversion: For ctpop/ctlz/cttz we always attach !range metadata, which will now block the transform, because it might introduce poison. Of course, the metadata we attach cannot actually produce new poison, but this is not generally the case (it could be an incorrect range).
I'm a bit unsure on what to do about this. A possibility would be to update the impliesPoison() helper to support ConsiderFlagsAndMetadata=false mode, and collect instructions that it has checked, and then drop poison generating flags/metadata on all those instructions.
not sure about align.
If a pointer is not sufficiently aligned, a load may crash. Returning poison in that case is not strong enough for the hardware behavior.