Por que "while (i ++ <n) {}" é significativamente mais lento que "while (++ i <n) {}"

Aparentemente, no meu laptop Windows 8 com HotSpot JDK 1.7.0_45 (com todas as opções de compilador / VM definidas como padrão), o loop abaixo

final int n = Integer.MAX_VALUE;
int i = 0;
while (++i < n) {
}

é pelo menos 2 ordens de magnitude mais rápido (~ 10 ms vs. ~ 5000 ms) do que:

final int n = Integer.MAX_VALUE;
int i = 0;
while (i++ < n) {
}

Por acaso, notei esse problema enquanto escrevia um loop para avaliar outro problema de desempenho irrelevante. E a diferença entre++i < n ei++ < n foi enorme o suficiente para influenciar significativamente o resultado.

Se olharmos para o bytecode, o corpo do loop da versão mais rápida é:

iinc
iload
ldc
if_icmplt

E para a versão mais lenta:

iload
iinc
ldc
if_icmplt

Então para++i < n, primeiro incrementa a variável locali por 1 e empurre-o para a pilha de operandos enquantoi++ < n executa essas duas etapas na ordem inversa. Mas isso não parece explicar por que o primeiro é muito mais rápido. Existe alguma cópia temporária envolvida neste último caso? Ou é algo além do bytecode (implementação de VM, hardware etc.) que deve ser responsável pela diferença de desempenho?

Eu li alguma outra discussão sobre++i ei++ (não exaustivamente), mas não encontrou nenhuma resposta específica do Java e diretamente relacionada ao caso em que++i oui++ está envolvido em uma comparação de valores.

questionAnswers(5)

yourAnswerToTheQuestion