The test case from:
https://bugs.llvm.org/show_bug.cgi?id=42771
...shows a ~30x slowdown caused by the awkward loop iteration (rL207302) that is seemingly done just to avoid invalidating the instruction iterator. We can instead delay instruction deletion until we reach the end of the block (or we could delay until we reach the end of all blocks).
There's a test diff here for a degenerate case with llvm.assume that I didn't step through, but I think that's caused because isInstructionTriviallyDead() may not be true for a function call even if that call has no uses.
This change probably doesn't result in much overall compile-time improvement because we call -instsimplify as a standalone pass only once in the standard -O2 opt pipeline from what I see.
I think we need to set Changed = true here as well.
I've got a test case like this:
that show that we do not propagate to pass managers that we have removed a call otherwise.
My original reproducer ended up with
due to not cleaning up the call graph after removing the call.
I'll upload a patch for this (assuming it is the correct solution).
Although, I've also noticed that the same assert was seen in https://bugs.llvm.org/show_bug.cgi?id=42751, and https://bugs.llvm.org/show_bug.cgi?id=42787 is also related to calls being optimized away (afaict). InstSimpllify is not involved in those two PRs. So it might be something else that makes isInstructionTriviallyDead returning that certain calls can be removed nowadays (such as recent changes regarding functions attributes). It should be valid for a FunctionPass to delete a call right, or is it interprocedural to for example look at function attributes to determine that the callee has no side effects? It is illegal for a FunctionPass to inspect a function other than the one being optimized. Is looking at function attributes the same as "inspecting" the callee?