That's still 250% more instructions than the necessary "xor eax, eax; ret". I find it a bit disappointing that the compiler would miss this trivial optimisation opportunity, while at the same time doing subtle and often unwanted things with undefined behaviour. C was conceived as a "portable assembly language", and as much as the language lawyers, theoreticists, and compiler writers love to exercise their "undefined behaviour" rights and try to dissuade others from thinking of it that way, that's what people use it for and that's what they'll expect.
Rather, undefined behaviour should be interpreted as "do the obvious thing, the results may differ on different platforms, and turn off all optimisations exploiting it because it's either intentional or the programmer has made a mistake so the compiler should also generate obviously wrong code." A warning would be nice too. Instead of blind adherence to the standard, consider what behaviour programmers actually expect, and write compilers accordingly. One example of this is casting integers to pointers of various types, and using them to access hardware. Device drivers would be impossible to write if the compiler decided that such undefined behaviour meant it could remove the accesses completely (which is completely legal according to the standard.)
More examples: dereferencing a null pointer should generate code that accesses address 0. Signed integers should wrap around on overflow. Shifts should do whatever the shift instruction of the architecture does. Trying to access beyond the end of the array should try to access memory there. Division by zero will do what the machine instruction would do. Etc.