Устранение конфликтов, связанных с ложными взаимозависимостями данных, часто возможно путем переименования регистров (register renaming).
Суть этого механизма заключается в следующем. Ядра процессоров, использующие переименование регистров, имеют значительно больше физических регистров по сравнению с архитектурными регистрами. При этом если какой-либо команде требуется использовать регистр, ядро процессора динамически ставит в соответствие этому архитектурному регистру один из более многочисленных физических регистров. Если другая команда пытается обратиться к тому же архитектурному регистру, ядро процессора для предотвращения конфликта может поставить ему в соответствие другой физический регистр. Такие переименования действуют, пока команды продвигаются по конвейеру.
Таким образом, каждый раз, когда команда прямо или косвенно пишет в регистр, ей выделяется новый физический регистр. В ядре процессора имеется таблица отображения архитектурных (видимых программисту) регистров на физические регистры (видимые только ядру процессора). Когда команде выделяется новый физический регистр, таблица обновляется: архитектурный регистр, на который ссылалась команда, ставится в соответствие выделенному физическому регистру (табл. 30.3).
Таблица 30.3. Механизм переименования регистров
Команда | Действие | Рабочий регистр |
i | Пишет в архитектурный регистр R0 | С этого момента регистру архитектурному R0 соответствует выделенный для команды физический регистр PФ0 |
i+1 | Читает из архитектурного регистра R0 | Читает из физического регистра PФ0 |
i+2 | Пишет в архитектурный регистр R0 | С этого момента архитектурному регистру R0 соответствует выделенный для команды физический регистр PФ1 |
i+3 | Читает из архитектурного регистра R0 | Читает из физического регистра PФ1 |
При определении операндов команды имена архитектурных регистров преобразуются в имена физических, после чего значения последних заносятся в поля операндов внутренних команд. Внутренние команды ядра процессора работают только с физическими регистрами.
Как можно увидеть, после дешифрации команды с номером i, которая в качестве приемника результата использует архитектурный регистр R0, все прочие команды, использующие в качестве операнда архитектурный регистр R0, будут обращаться к физическому регистру, выделенному для команды с номером i. При этом если какая-то команда после команды с номером i будет писать в тот же архитектурный регистр, ей будет выделен новый физический регистр, и все команды после нее будут использовать уже новый физический регистр.
Из табл. 30.3 видно, что команды стали независимы. Если команды, работающие с архитектурным регистром R0, зависят друг от друга и их нельзя выполнять параллельно, то внутренние команды "разведены" по физическим регистрам PФ0 и PФ1 и независимы.
Значение физического регистра переписывается в архитектурный регистр, когда завершается выполнение команды (фиксируется ее результат). В свою очередь, завершение выполнения команды происходит, когда все предыдущие команды успешно завершились в заданном программой порядке.
Однако такой подход требует, чтобы ядро процессора помимо программно доступных архитектурных регистров содержало блок из гораздо большего количества невидимых программисту физических регистров, что и реализовано в большинстве ядер современных процессоров.
Как отмечалось выше, наличие конфликтов приводит к значительному снижению производительности процессора. Определенные типы конфликтов требуют приостановки конвейера. При этом останавливается выполнение всех команд, находящихся в конвейере на различных стадиях обработки. Другие конфликты, например, при неверном предсказанном направлении перехода, ведут к необходимости полной перезагрузки конвейера. Потери будут тем больше, чем более длинный конвейер используется в ядре процессора. Такая ситуация явилась одной из причин сокращения числа ступеней в ядрах процессоров последних моделей. В них конвейер содержит всего 10 - 15 ступеней.