Relying on compiler optimizations is not the answer. When they work, you don't notice, but an unrelated change could very well change the compiler's state and optimization decisions, falling off a performance cliff.
This is especially pronounced in languages that rely a lot on compiler optimizations. In Haskell you can purposefully use the singly linked list for very large collections, knowing they will be optimized out, until one day the compiler decided not to optimize that and now you have a problem.
There's a reason C++17 made return-value-optimization a proper part of the language with mandatory elision of copies. People like guarantees. Optimizations are but the icing on the cake.