Для алгоритма планирования команд сначала необходимо определить цепочки зависимостей. (То же самое, что и при определении критических путей задержки для exe-порядка exe c.)
Чтобы запланировать инструкции для машины порядка: чередуйте инструкции из разных цепочек dep, начиная с самой длинной .
При ручной настройке (или в оптимизирующем компиляторе) вы даже можете выполнять такие вещи, как перестановка ассоциативных операций (например, add
), чтобы создавать различные временные эффекты, создавая больше ILP (параллелизм на уровне команд). например, превращение a+b+c+d
в (a+b)+(c+d)
. Целочисленная математика ассоциативна; математика с плавающей запятой, как правило, не.
Конечно, это безопасно, только если код использует addu
/ addiu
, а не переполнение ловушки при подписи MIPS add
/ addi
. C компиляторы никогда не используют trapping add / sub, поэтому они могут свободно оптимизировать арифметику c с временными значениями, отличными от источника C. Вы также должны, если вы специально не хотите инструкцию, которая может перехватить переполнение со знаком.
Очевидно, что ассемблеры classi c MIPS могли бы перестроить ваш код для вас заполнить слоты загрузки и задержки ; это руководство по сборке Silicon Graphics от 1992 г. содержит некоторые подробности об агрессивном переупорядочении команд ассемблером (если только вы не используете .set noreorder
, а затем не видны слоты задержки ветвления.) Книга См. MIPS Run может также упомянуть об этом.
Предположительно, ассемблер SGI обнаруживает блоки basi c с точки зрения меток и инструкций ветвления и выполняет планирование команд внутри отдельных блоков.
Конечно, хорошо компиляторы для языков высокого уровня также выполняют планирование команд. (Например, G CC). Я не думаю, что ассемблер GNU имеет оптимизирующий режим переупорядочения; он разработан как бэкэнд для компилятора, который сам расписывает инструкции.
В отличие от вашего игрушечного примера с многоцикловой задержкой, прежде чем вы сможете использовать результат add
, real classi c MIPS представлял собой classi c 5-ступенчатый RIS C с переадресацией обхода и задержкой ALU с одним циклом. У первого поколения не было блокировок, поэтому был интервал задержки загрузки 1 цикл, и слоты задержки ветвления оставались архитектурно видимыми. Но простые инструкции ALU имеют задержку в 1 цикл. Таким образом, настоящие MIPS имели гораздо меньше опасностей, которых следует избегать при планировании инструкций. Но даже в этом случае, более поздняя версия MIPS убрала слот задержки загрузки для лучшей плотности кода, когда относительно примитивные компиляторы того времени не могли найти что-либо, что можно было бы там разместить. (Остановка вместо необходимости в NOP.)
Реальная машина с таким количеством временных интервалов задержки (без аппаратной блокировки для блокировки) была бы очень непрактичной для плотности кода / занимаемой памяти L1i, а также из-за плохой производительности. Есть причина, по которой реальные коммерческие проекты обходят пересылку вместо остановки. Но ваш пример действительно многоцикловой задержки - это реалистичность c для плавающей запятой.
(забавный факт: MIPS может переадресовать целевой адрес ветвления с первой половины EX на полупериод IF в общей сложности только 1 цикл задержки ветвления.
MIPS застрял с интервалами задержки ветвления до тех пор, пока в основном (и не обратно совместимом) реорге кодов операций не появятся ветки без задержки () MIPS32 / 64r6 в 2014 г.). Инструкция в слоте задержки ветвления выполняется независимо от того, занято ветвление или нет, поэтому позднее аппаратное обеспечение MIPS не могло удалить его так же, как для слотов задержки загрузки. RIS C -V избежал этой ошибки.