As an example of how tricky it can be, one of their examples is
const uint8_t *data = /* buffer head */;
const uint8_t *data_end = /* buffer tail */;
int size = bytestream_get_be16(&data);
if (data + size >= data_end || data + size < data)
return -1;
They say "A correct fix
is to replace data + x >= data_end || data + x < data
with x >= data_end − data, which is simpler and also
avoids invoking undefined behavior; one should also add
the check x < 0 if x can be negative."
Unfortunately, that replacement is itself well-defined only if data and data_end "point to elements of the same array object, or one past the last element of the array object" (and there's an implementation-dependent option for the interpretation of "one past" when ensuring the address can be represented). It looks from the comments as though that might be true in this particular case (or it's intended to be understood), but if not, avoiding the compiler's "optimisation" that messes up one form of undefined behaviour will lead you to write code that has different undefined states.
Generally, an optimising compiler for a systems language, especially one in which pointer values can be manipulated explicitly,
needs to be sure of its ground when second-guessing the effect of a given statement or expression.