godbolt.org is a tool for exploring compiler behavior and output. It offers the ability to compile C++ and other languages with a variety of different compiler versions and machine targets, and view the resulting assembly code.
As an example, here's some code to calculate the Fibonacci numbers using tail-recursion:
and here's the resulting x64 assembly output, compiled with gcc version 8.1. using the -O1 flag:
Each line of source is color-coded to match the corresponding assembly instructions (though this mapping is not always as straightforward as one would like.) The Compiler Explorer provides help interpreting the assembly: you can hover over an instruction to get a quick summary:
What happens if we switch to a higher optimization level, and use -O2 instead?
Now the compiler has successfully implemented tail recursion. Instead of the assembly "call fibIter" to recursively call the function, the compiler has reduced fibIter to a loop. This is a great way to try out "will the compiler perform optimization X?" or try toggling individual optimizations using compiler flags.
What about -O3?
Now we have a mess. The compiler applied a lot of different optimizations that caused the code to become enormously more complex. It inlined fibIter into the fib function. It not only converted the tail recursion to a loop, but also unrolled that loop and parallelized it using SIMD instructions, to do two multiplications at once.
We can easily compare with a different architecture, like ARM, that doesn't have SIMD instructions:
You can also explore different versions of the same compiler/architecture combo to see if the output differs.
Compiler Explorer supports assembly, C, C++, CUDA, D, Go, Haskell, LLVM's intermediate representation (a psuedo-assembly language), Pascal, Rust, and Swift. Its source is online at Github (https://github.com/mattgodbolt/compiler-explorer) and its author, Matt Godbolt, has a Patreon: https://www.patreon.com/mattgodbolt