Why is it so difficult to eliminate dead loops?
The conceptual problem here is that dead code elimination is not computable. That is, we know that there is no algorithm that can remove all instances of dead code.

Of course, tools can be created that recognize some instances of dead code and remove them. Which patterns to look for is a matter of taste and skill of the tool creator; it's better to be conservative and err on the site of not breaking things. Language semantics play a huge role as well. I don't think there are overarching conceptual issues there, but I could be wrong.

There may be language-specific subtleties at work that prevent elimination of apparently dead code. For instance, a Java compiler can never remove a private method that is never called from within the class -- it can be executed using reflection. Such special cases are beyond the scope of this site, and best discussed one by one on Stack Overflow.

In the end, I expect there to be trade-offs (as there always are): how much time do you spend on developing the optimizer, how much time do you spend during compilation, for what gain? Maybe an optimization that often creates more efficient code occasionally creates some dead code, which you are willing to accept.