Propagate between the phi node arguments of PHI in BB and phi result users. For now this matches
p_2 = PHI <&x, &y>
<Lx>:; p_3 = p_2; z_2 = *p_3; and converts it to
z_2 = PHI <x, y>
<Lx>:; Returns true if a transformation was done and edge insertions need to be committed. Global data PHIVN and N is used to track past transformation results. We need to be especially careful here with aliasing issues as we are moving memory reads.
Check if we can "cheaply" dereference all phi arguments.
Walk the ssa chain until we reach a ssa name we already
created a value for or we reach a definition of the form
ssa_name_n = &var;
Find a dereferencing use. First follow (single use) ssa
copy chains for ptr.
Replace the first dereference of *ptr if there is one and if we
can move the loads to the place of the ptr phi node.
Check whether this is a load of *ptr.
We cannot replace a load that may throw or is volatile.
Check if we can move the loads. The def stmt of the virtual use
needs to be in a different basic block dominating bb.
Found a proper dereference. Insert a phi node if this
is the first load transformation.
Remember the value we created for *ptr.
Remove old stmt. The phi is taken care of by DCE, if we
want to delete it here we also have to delete all intermediate
copies.
Further replacements are easy, just make a copy out of the
load.
Continue searching for a proper dereference.
References gimple_assign_rhs1(), gimple_assign_single_p(), NULL_TREE, phivn_valid_p(), SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, SSA_NAME_VERSION, TREE_CODE, TREE_TYPE, types_compatible_p(), and USE_FROM_PTR.