I think the right approach is to get a decent high level understanding of how compilers work. Some surprising optimizations and failures to optimize become a lot clearer. For example, SSA makes it obvious why there's absolutely no penalty for using lots of named temporary register-sized variables.
Then learn your particular compilers' abilities by research and reading your assembly output. If you're depending on an optimization, always read the output. You might be pleasantly surprised as often as you're disappointed.
Understanding the rules of the language are important too. In C++, pointer aliasing and the worthlessness of 'const' are huge obstacles to some seemingly easy optimizations.
Then learn your particular compilers' abilities by research and reading your assembly output. If you're depending on an optimization, always read the output. You might be pleasantly surprised as often as you're disappointed.
Understanding the rules of the language are important too. In C++, pointer aliasing and the worthlessness of 'const' are huge obstacles to some seemingly easy optimizations.