However, an implementation could define various UBs however it wants. The difference between "undefined" and "implement-defined" is really that an implementation doesn't have to anything even remotely sensible for "undefined" behavior, but it has do define some ("sensible") behavior for "implementation-defined" behavior. Usually, "implementation-defined" behavior also tends to remain consistent across versions whereas "undefined" behavior usually has no such constraints. For example, for "undefined" behavior, version 5.1.2.3 of the compiler may differ drastically from 5.1.2.4 in terms of optimizations which rely on UB.
Undefined - the compiler may assume this can never happen, and if it does happen, it can "poison" the whole execution including whatever logically happens before the undefined part.
Unspecified - the behavior must be deterministic and cannot affect the semantics of other well-defined parts of the program, but the implementation need not guarantee any single behavior.
Implementation-specified - like above, but the implementation must specify the exact behavior.
Even though the standard imposes no specific requirements, it explicitly calls that out at something you could do: http://port70.net/~nsz/c/c11/n1570.html#3.4.3
But for some reason nobody seems to ever think this is an option.
The compiler doesn't specifically search for undefined behavior and use it as an excuse to do something "quirky." Instead, it assumes the code is well-defined and interprets (and transforms) it in ways that preserve its semantics. For example, "One cannot dereference null pointers. The author dereferenced the pointer p. Therefore, p is not null. Since p is not null, the compiler can avoid checking it after the first dereference." The compiler is essentially assuming that the author knows something that it may not and just runs with it.
However, there are a lot of transformations--and corner cases--many of which can interact. This can produce complex unwanted behavior that looks like "nasal demons", but largely as a side effect. The compiler does not say "OVERFLOW DETECTED. REPLACING ENTIRE FUNCTION WITH NOOP"