I implemented the idea of keeping the past `copy_propagation_value`s and I think it looks quite nice.
Also I don't think it is inefficient for the following reasons: 1- We can lookup the list of recorded values from newer to older, so in most cases (except swizzles) the lookup will be O(1). 2- The number of entries we will have to store should be less than 4 times the number of program instructions. 3- We can still discard each block's `copy_propagation_state` once we finish processing the block itself, and thus delete all the values recorded in it.
So I am closing this MR in favor of !487.