> but also couldn't possibly be rewritten to eliminate undefined behaviour (while keeping the same speed)?
Undefined behavior is, for the most part, meant to enable compiler optimizations. If you're willing to do all your optimizations by hand rather than relying on the compiler to do them – in other words, use C as the "portable assembler" it was originally conceived as – then you don't really need it. (At least, not to the extent it exists in C.) And for small, tight loops, that's a perfectly reasonable proposition. For large programs, on the other hand, especially if you want to pile on a lot of abstraction and rely on the compiler to turn it into nice code (see C++)... not so much.
Undefined behavior is, for the most part, meant to enable compiler optimizations. If you're willing to do all your optimizations by hand rather than relying on the compiler to do them – in other words, use C as the "portable assembler" it was originally conceived as – then you don't really need it. (At least, not to the extent it exists in C.) And for small, tight loops, that's a perfectly reasonable proposition. For large programs, on the other hand, especially if you want to pile on a lot of abstraction and rely on the compiler to turn it into nice code (see C++)... not so much.