It's the just-in-time aspect that makes me leery of a compiler that has that much on its plate. I'm unaware of any compiler that does all three things outlined with such a time constraint.
The Java HotSpot JIT Compiler does global register allocation via graph coloring.
There is no need to view the situation as AOT/JIT. Hybrid systems are all around. Static compilation, followed by JIT profile collection, followed by reoptimization with idle CPU.
HotSpot takes its name because it doesn't optimize everything, instead, it uses heuristics to decide which are the "hot" parts of the code, and how much work it can devote to optimization based on predicting how long it will take. HotSpot has two modes 'client' and 'server'. Client mode uses a different set of algorithms and tries to minimize pauses, interruptions, and startup time for real time UI feedback. Server mode uses more aggressive optimizations where throughput matters more than latency. (e.g. graph coloring vs linear scan register allocation)
In Java6 a new hybrid JIT is being introduced. Code can be interpreted, then compiled via the C1 compiler (optimized for startup, latency), then compiled via C2 "server" compiler (as the app runs longer). Think of this as a 3 gear automatic transmission.
IBM's Java VM goes further. It has 4 gears: interpreted, trivially compiled (baseline compiler, no optimizations, but translation of IR to asm), compiled, and aggressively compiled. (think of it the last three cc -g, -O1, -O2). Add to this, they have AOT (ahead of time/static compile) as well.
Some research JITs have included the ability to store profile data between runs too, so that something which was once AOT compiled, can be switched to aggressive JIT optimizations on restart without recollecting profile info.
As I mentioned in another post, modern OO programming languages and modern component-oriented programming styles interfere with static compilation ala C. Polymorphism is the enemy of inline and global data flow analysis (e.g. cross-method register allocation), and so is other forms of late binding (COM, DLL/so, etc) Since C's linker is as dumb as they come, and C object format does not store IR related information, optimizing against pre-compiled third party libraries is hard as well. Also, most operating systems do not have a binary format (e.g. ELF) which stores high level IR representation along with executable code, interprocedural analysis is hampered as well.
For example, if you dynamically load a DLL/SO, and call a method, there is no way for the compiler to statically determine a) what DLL was loaded and b) of the method that is called in that DLL which methods the DLL might go on to call!
JIT systems fix the growing dynamism problem of OO languages and component-oriented programming by storing enough information to re-link and recompile methods at run time, and perform whole-program analysis across previous event horizons like dynamically loaded third party libraries.
Moreover, with JITs you get more flexible garbage collection algorithms, like generational copying which can vastly improve memory hierarchy performance, as well as run-time lock elimination based on biased locking and lock coarsening as well as runtime escape analysis.
You wouldn't want a JIT in an embedded scenario (like a console) due to unpredictability, but for most of the other apps in the world, they make sense, especially as CPUs diversify their architecture. JITs are a win for the same reason that OOOE is a win vs static Itanium architectures , and that's runtime information is critical to some applications.
The ideal is to have a continuum from aggressive static compilation to profile directed JIT recompilation when the user wants it. Static compilers with feedback don't neccessarily cut the mustard when you have a long running app that you don't want to reboot.
(BTW, another benefit is that JIT systems allow *runtime* patching of code as well as debugging of heavily optimized code through deoptimization. I can attach to a running process and patch a method with a fixed version. Great for non-stop interactive development)