But you pay a performance cost for either of those decisions. Consider code like this:
for (int i=0; i <= N; i++) func();
Most processors have special support for looping a fixed number of times, e.g. "decrement then branch if zero." If overflow is UB, the compiler can use this support.
But if overflow returns an implementation defined value, then it is possible that N is INT_MAX and the loop will not terminate. In this case the compiler cannot use the fixed-iteration form, and must emit a more expensive instruction sequence.
A correctly predicted branch is almost free, the compiler could check for that case.
The real problem of course is that C requires the programmer to obscure their intent by messing with a counter variable. Is there really no "loop exactly N times" construct in the language?
But if overflow returns an implementation defined value, then it is possible that N is INT_MAX and the loop will not terminate. In this case the compiler cannot use the fixed-iteration form, and must emit a more expensive instruction sequence.