You can think of poison as of just an extra element added to the type (e.g. to the set represented by i32 or i1). Only freezing it will replace it with something concrete such that if x is poison then freeze(x) == freeze(x), etc.
Why do you insist on treating it as an attribute? It's more like NaN for floating point: "not a value".
As I understand (others have better thoughts on this than I do) it is difficult to make the "definitely not poison" analysis return useful answers very much of the time. Instead, we try to write transformations that work regardless of whether a value is poisoned.