>All of these 'problems' have simple and straigtforward workarounds, I'm not convinced these UB are needed at all.
He gave you a simple and straightforward example, but that example may not be representative of a real world program where complex analysis leads to better performing code.
As a programmer, its far easier to just insert bounds checks everywhere, and trust the system to remove them when possible. This is what Rust does, and it safe. The problem isn't the compiler, the problem is the standard. More broadly, the standard wasn't written with optimizing compilers in mind.
If we're inlining the call, then we can hoist the NULL check out of the loop. Now it's 1 check per 20 million operations. There's no need to eliminate it or have UB at that point.
If the compiler can "prove" that the pointer is not NULL it can (after inlining the call) remove 20 million checks for a 20 megapixel image.
The silly issue is the compiler using "you accessed it before" (aka "undefined behaviour") to "prove" that the pointer is not NULL.
But I can attest that avoiding 20 million such checks does indeed make a huge difference.