Guile has been getting some really neat optimizations lately (jit, declarative modules, efficient local recursive bindings and much more) and it is really fun to try to follow the code that gets published. Andy's blog over at wingolog.org is also great fun to read.
If you want an easy start re-implement an interpreted language first, then write a compiler for it.
The last Gcc bug I submitted was a regression that made my program take fully twice as long to run. For that case, they decided making it slow was the correct choice. (Anyway it matched Clang afterward. :-)
The program's main loop, where it had spent 90+% of its time, was just four instructions, which Haswell and later can do in one cycle per iteration, provided the instructions are presented right. Occasionally, it would encounter something that would take 50+ cycles to deal with, and then continue looping. The regression was that it re-arranged the instructions to save a cycle on the slow path and add a cycle to the fast path, so it now takes two cycles per iteration instead of one.