Existem três caches em um processador x86 / x64 moderno, L1, L2 e L3.
O cache L1 é dividido entre um cache de instruções e um cache de dados. Existe uma correlação entre os dois, portanto, a instrução na posição x no cache de instruções corresponde ao resultado na posição x do cache de dados. Então, sim, a CPU pode alimentar um resultado de cálculo do cache se a instrução for realmente a mesma, mas não se for apenas similar . Em outras palavras, 2 + 5 não é o mesmo que 3 + 4, embora o resultado seja idêntico.
O cache L2 é somente de dados e basicamente pode ser considerado como RAM super-rápida.
L3 é o mesmo que L2, exceto que é compartilhado entre todos os núcleos do processador (cada núcleo tem seus próprios caches L1 e L2).
Aqui estão algumas outras técnicas de otimização que também pertencem à sua pergunta.
Pré-busca de instruções: A CPU pode ler adiante no pipeline e executar instruções antes de serem realmente solicitadas. Os resultados são armazenados em cache para que a CPU possa simplesmente alimentar os resultados do cache quando a instrução finalmente chegar.
Predição de Ramificação: Quando o pré-buscador vê uma instrução de salto condicional (uma declaração If / Then no seu código), ela pode decidir qual ramificação é mais provável de ser tomada (ou se possível, executar ambos os ramos em paralelo) e pré-calcular os resultados. Se ele adivinhou corretamente (ou se executou ambos em paralelo), então o resultado é simplesmente alimentado a partir do cache.
Execução fora de ordem: O decodificador de instruções pode reorganizar as instruções no pré-buscador para que sejam executadas na ordem mais eficiente para a CPU. Os resultados são mantidos diretamente no cache para que eles possam ser alimentados na ordem correta esperada pelo programa.
Instruções SIMD (instrução única, dados múltiplos): A CPU pode executar o mesmo cálculo em vários pontos de dados com uma única instrução. Por exemplo, adicionando 5 a cada um de uma matriz de inteiros. A CPU pode executar a instrução repetidamente sem precisar decodificar a instrução ADD para cada cálculo.
Existem LOTES de otimizações que os processadores modernos fazem para melhorar o desempenho, mas também não contam a influência da otimização de compiladores. Um bom compilador conhece os pontos strongs e fracos da arquitetura da CPU e pode otimizar o código antes mesmo de chegar à CPU. Por exemplo, um compilador pode ser capaz de saber que dois valores particulares nunca mudam ao longo de um programa, então ele pode fazer com que a CPU os calcule em tempo de compilação e os incorpore no código em vez de fazer a CPU faça o trabalho em tempo de execução. Também é possível saber que uma determinada CPU é mais rápida em leituras que em saltos, por isso pode codificar o mesmo valor de dados 5 vezes, em vez de fazer com que a CPU faça 5 saltos.
Aqui está um bom recurso sobre como funcionam os caches de memória.