Yeah, but only toy compilers don't do optimizations.
All observable and defined side effects should be identical otherwise you have a compiler bug. Optimizations that are not generically semantics preserving may be used, but should only be used where the program is semantically identical for your use case otherwise you have incorrectly used the options available in your compiler.
For example a JIT compiler can produce completely different kinds of machine code depending on the application data that was processed, and the overall machine workload.
The output program does what the input source code does. The abstraction is a precise translation and non-leaky, it just admits multiple possible internals. That does not make the translation any less precise.