Obviamente, a condição é verificada todas as vezes. Mas, no momento em que é verificado, já está no pipeline da CPU. Nesse meio tempo, outras instruções também entraram no pipeline e estão em vários estágios de execução.
Geralmente, uma condição é imediatamente seguida por uma instrução de ramificação condicional, que ramifica se a condição for avaliada como TRUE ou será reprovada se a condição for avaliada como FALSE. Isso significa que existem dois fluxos de instruções diferentes que podem ser carregados no pipeline após a instrução de condição e a instrução de ramificação, dependendo se a condição é avaliada como TRUE ou FALSE. Infelizmente, imediatamente após o carregamento da instrução de condição e da instrução de ramificação, a CPU ainda não sabe o que avaliará a condição, mas ainda precisará carregar o material no pipeline. Portanto, ele escolhe um dos dois conjuntos de instruções com base em um palpite sobre o que a condição avaliará.
Posteriormente, conforme a instrução de condição percorre o oleoduto, é hora de ser avaliada. Nesse momento, a CPU descobre se seu palpite estava certo ou errado.
Se o palpite estiver correto, o ramo foi para o local correto e as instruções corretas foram carregadas no pipeline. Se o palpite estiver errado, todas as instruções que foram carregadas no pipeline após a instrução de ramificação condicional estavam erradas, elas precisam ser descartadas e a busca de instruções deve começar novamente no lugar certo.
Alteração
Em resposta ao comentário do StarWeaver, para ter uma idéia do que a CPU deve fazer para executar uma única instrução:
Considere algo tão simples como o MOV AX,[SI+10]
que nós humanos imaginamos como "carregamos o AX com a palavra SI mais 10". Aproximadamente, a CPU precisa:
- emita o conteúdo do PC (o "registro do contador de programa") para o barramento de endereços;
- leia o código de operação da instrução no barramento de dados;
- incremento de PC;
- decodifique o código de operação para descobrir o que fazer com ele;
- emitir o conteúdo do PC para o barramento de endereços;
- leia o operando da instrução (neste caso 10) no barramento de dados;
- incremento de PC;
- alimente o operando e o SI ao somador;
- emitir o resultado do adicionador para o barramento de endereços;
- leia o AX no barramento de dados.
São 10 etapas impressionantes. Algumas dessas etapas serão otimizadas, mesmo em CPUs sem pipeline, por exemplo, a CPU quase sempre incrementará o PC em paralelo com a próxima etapa, o que é fácil, pois o PC é um registro muito, muito especial. nunca usado para qualquer outro trabalho, portanto, não há possibilidade de contenção entre diferentes partes da CPU para acessar esse registro específico. Porém, ainda temos 8 etapas para uma instrução tão simples e observe que já estou assumindo algum grau de sofisticação em nome da CPU, por exemplo, estou assumindo que não haverá necessidade de uma etapa extra inteira para o adicionador para efetivamente realizar a adição antes que o resultado possa ser lido dela,
Agora, considere que existem modos de endereçamento mais complicados, como MOV AX, [DX+SI*4+10]
e instruções ainda mais complicadas, como os MUL AX, operand
que realmente executam loops dentro da CPU para calcular seu resultado.
Portanto, meu argumento aqui é que a metáfora do "nível atômico" está longe de ser adequada ao nível de instrução da CPU. Pode ser adequado para o nível de etapa do pipeline, se você não quiser ir muito longe até o nível real da porta lógica.