Because there are no portable semantics for doing so, or specifying such semantics would unnecessarily constrain implementations.
Performance is oft-cited as the reason for undefined behavior but this tends to be more of a ex-post facto justification for certain compiler behaviors rather thanhide the real reason.
Undefined behavior comes from the fact that to specify everything in a programming language would be incredibly infeasible and would also not allow differentiation of implementations.
This is why some things are left undefined in programming language standards rather than them being explicitly spelled out. It both encourages a diversity of implementations that the language can support while letting those that want to target a specific superset do so by opting into certain features at the expense of loss of portability.
Signed integer overflow is a classic example. What do you get when you do
int i = INT_MAX + 1;
It certainly... is C code1, but what does it actually do. Well... it's not defined because there's no portable semantics for such an operation. Depending on the implementation, it may wraparound (as many programmers on two's complement machines expect), it may saturate (as on some DSPs), it may trap, or do any number of things. You could also conceive of an implementation that checked all additions it couldn't prove or aborted translation if it could prove such a thing (at least within some set of assumptions!).
Especially in languages that gained popularity before standardization (such as C (or languages that inherited such concerns from those languages, like C++), many compilers had and have differing ways of expressing certain idioms.
1. There are certainly some who would argue that this isn't C code at all, but it's a view that, for all intents and purposes, is an unnecessarily prescriptivist (and perhaps useless) view of what a C program is, one which is unsupported by the standard itself.