LLVM's definition of dominance allows instructions that are cyclic in unreachable blocks, e.g.:
%pat = select i1 %condition, @global, i16* %pat
because any instruction dominates an instruction in a block that's not reachable from entry.
So, remove unreachable blocks from the function, because a) there's no point in analyzing them and b) GlobalOpt should otherwise grow some more complicated logic to break these cycles.
Couple of notes:
- This test is clearly generated by a fuzzer, so it might not show up in a real world pipeline (where I think we might run GlobalDCE before GlobalOpt).
- I wasn't able to measure an increase in compile time after this change, when e.g. self-hosting clang with LTO & with some internal benchmarks.
I think you need to do something to preserve the domtree here. (Either that, or move this earlier so it never runs after we access the domtree.)