Basically, JIT compilers has a chance to actually profile the application being run, and do some hinting based on that information.
"offline" compilers will not be able to determine how often a branch jumps and how often it falls through, without inserting special code, ask the dev to run the program, put it through its paces, and recompile.
Why does this matter?
//code before
if(errorCondition)
{
//error handling
}
//code after
Gets converted into something like:
//code before
Branch if not error to Code After
//error handling
Code After:
//Code After
And x86 processors would not predict a conditional jump ahead in the absence of information from the branch prediction unit. That means that it predicts the error handling code to run, and the processor's going to have to flush the pipeline when it figures out that the error condition didn't occur.
A JIT compiler could see that, and insert a hint for the branch, so that the CPU would predict in the correct direction. Granted, offline compilers can structure the code in a way that would avoid the mispredict, but if you ever need to look at the assembly, you might not like it jumping around everywhere....