Ovviamente la condizione viene controllata ogni volta. Ma quando viene controllato, è molto in alto nella pipeline della CPU. Nel frattempo, anche altre istruzioni sono entrate nella pipeline e sono in varie fasi di esecuzione.
Di solito, una condizione viene immediatamente seguita da un'istruzione di ramo condizionale, che si dirama se la condizione restituisce TRUE o se la condizione viene valutata su FALSE. Ciò significa che ci sono due diversi flussi di istruzioni che possono essere caricati nella pipeline dopo l'istruzione di condizione e l'istruzione di ramo, a seconda che la condizione valuti su VERO o FALSO. Sfortunatamente, subito dopo aver caricato l'istruzione di condizione e l'istruzione di salto, la CPU non sa ancora a quali condizioni valuterà la condizione, ma deve comunque continuare a caricare roba nella pipeline. Quindi seleziona uno dei due gruppi di istruzioni in base a un'ipotesi su quale sarà la condizione a cui valuterà.
Successivamente, mentre l'istruzione sulla condizione si sposta lungo la pipeline, è il momento di essere valutata. A quel tempo, la CPU scopre se la sua ipotesi è giusta o sbagliata.
Se l'ipotesi si rivela corretta, il ramo si è spostato nella posizione corretta e le istruzioni corrette sono state caricate nella pipeline. Se si scopre che l'ipotesi è sbagliata, tutte le istruzioni che sono state caricate nella pipeline dopo l'istruzione del ramo condizionale sono errate, devono essere eliminate e il recupero delle istruzioni deve riprendere dal punto giusto.
Emendamento
In risposta al commento di StarWeaver, per dare un'idea di cosa deve fare la CPU per eseguire una singola istruzione:
Considera qualcosa di semplice come MOV AX,[SI+10]
che noi umani pensiamo ingenuamente come "carica AX con la parola a SI più 10". Approssimativamente, la CPU deve:
- emette il contenuto del PC (il "registro del contatore del programma") sul bus indirizzo;
- legge l'opcode dell'istruzione dal bus dati;
- incrementa PC;
- decodifica l'opcode per capire cosa fare con esso;
- emette il contenuto del PC sul bus indirizzo;
- legge l'operando delle istruzioni (in questo caso 10) dal bus dati;
- incrementa PC;
- alimenta l'operando e SI al sommatore;
- emette il risultato dell'adder sul bus indirizzo;
- legge AX dal bus dati.
Questo è un enorme 10 passi. Alcuni di questi passaggi saranno ottimizzati anche in CPU non pipeline, ad esempio la CPU incrementerà quasi sempre il PC in parallelo con il prossimo passo, operazione semplice perché il PC è un registro molto, molto speciale che è mai usato per nessun altro lavoro, quindi non c'è possibilità di contesa tra diverse parti della CPU per accedere a questo particolare registro. Tuttavia, ci rimangono 8 passaggi per un'istruzione così semplice, e si noti che sto già assumendo un certo grado di sofisticazione per conto della CPU, ad esempio presumo che non ci sarà bisogno di un intero passo in più per sommatore per eseguire effettivamente l'aggiunta prima che il risultato possa essere letto da esso e presumo che l'output dell'adder possa essere inviato direttamente al bus indirizzo senza dover essere memorizzato in un registro di indirizzamento interno intermedio.
Ora, considera che esistono modi di indirizzamento più complicati, come MOV AX, [DX+SI*4+10]
, e anche istruzioni molto più complicate, come MUL AX, operand
che effettivamente eseguono loop all'interno della CPU per calcolare il loro risultato.
Quindi, il mio punto qui è che la metafora del "livello atomico" è lungi dall'essere adatta al livello di istruzione della CPU. Potrebbe essere adatto per il livello di passaggio della pipeline, se non si vuole andare troppo in basso fino al livello effettivo della porta logica.