This has the added advantage that it will stop traversing the tree as soon as the first call is found. The output of all test cases was verified to be the same using diff.
This may trigger other optimization phases to make more progress themselves.
This is pretty basic. Right now it only handles pure assignments -- same type on each side, no swizzling, and only within basic blocks.