An alternative is to use a worklist approach. However, that approach
would break the traversing order so that we couldn't lookup SeenExprs
efficiently. I don't see a clear winner here, so I picked the easier approach.
Along with two minor improvements:
- preserves ScalarEvolution by forgetting instructions replaced
- removes dead code locally avoiding the need of running DCE afterwards