Bien sûr, l'état est vérifié à chaque fois. Mais au moment où il est vérifié, il est loin dans le pipeline du processeur. Entre-temps, d'autres instructions sont également entrées dans le pipeline et sont à divers stades d'exécution.
Habituellement, une condition est immédiatement suivie d'une instruction de branchement conditionnel, qui se branche si la condition est évaluée à VRAI, ou échoue si la condition est évaluée à FAUX. Cela signifie qu'il existe deux flux d'instructions différents qui peuvent être chargés dans le pipeline après l'instruction de condition et l'instruction de branchement, selon que la condition est évaluée à VRAI ou FAUX. Malheureusement, immédiatement après le chargement de l'instruction de condition et de l'instruction de branchement, le processeur ne sait pas encore à quoi la condition va être évaluée, mais il doit toujours continuer à charger des éléments dans le pipeline. Il choisit donc l'un des deux ensembles d'instructions en fonction d'une supposition quant à la condition à laquelle la condition sera évaluée.
Plus tard, alors que l'instruction de condition remonte le pipeline, il est temps de l'évaluer. À ce moment-là, le CPU découvre si sa supposition était bonne ou mauvaise.
Si la supposition s'avère juste, alors la branche est allée au bon endroit et les bonnes instructions ont été chargées dans le pipeline. S'il s'avère que la supposition était erronée, alors toutes les instructions qui ont été chargées dans le pipeline après que l'instruction de branchement conditionnel était erronée, elles doivent être rejetées et la récupération des instructions doit recommencer au bon endroit.
Amendement
En réponse au commentaire de StarWeaver, pour donner une idée de ce que le CPU doit faire pour exécuter une seule instruction:
Considérez quelque chose d'aussi simple que MOV AX,[SI+10]
ce que nous, humains, considérons naïvement comme «charger AX avec le mot à SI plus 10». En gros, le CPU doit:
- émettre le contenu du PC (le "registre de compteur de programme") vers le bus d'adresse;
- lire l'opcode d'instruction du bus de données;
- incrémenter PC;
- décoder l'opcode pour savoir quoi en faire;
- émettre le contenu du PC vers le bus d'adresse;
- lire l'opérande d'instruction (dans ce cas 10) à partir du bus de données;
- incrémenter PC;
- fournir l'opérande et SI à l'additionneur;
- émettre le résultat de l'additionneur sur le bus d'adresse;
- lire AX depuis le bus de données.
C'est un énorme 10 étapes. Certaines de ces étapes seront optimisées même dans les processeurs non pipelinés, par exemple le CPU incrémentera presque toujours le PC en parallèle avec l'étape suivante, ce qui est une chose facile à faire car le PC est un registre très très spécial qui est jamais utilisé pour un autre travail, il n'y a donc aucune possibilité de conflit entre les différentes parties du CPU pour accéder à ce registre particulier. Mais encore, il nous reste 8 étapes pour une instruction aussi simple, et notez que je suppose déjà un certain degré de sophistication au nom du CPU, par exemple je suppose qu'il n'y aura pas besoin d'une étape supplémentaire entière pour le additionneur pour effectuer l'ajout avant de pouvoir en lire le résultat,
Maintenant, considérez qu'il existe des modes d'adressage plus compliqués, comme MOV AX, [DX+SI*4+10]
, et même des instructions beaucoup plus compliquées, comme celles MUL AX, operand
qui effectuent réellement des boucles à l'intérieur du CPU pour calculer leur résultat.
Donc, mon point ici est que la métaphore du "niveau atomique" est loin d'être appropriée pour le niveau d'instruction CPU. Il peut convenir au niveau de l'étape du pipeline, si vous ne voulez pas aller trop loin jusqu'au niveau de la porte logique réelle.