
- •5. Программная конвейерная обработка и поддержка циклов
- •5.1. Краткий обзор
- •5.2. Терминология циклов и основная поддержка циклов
- •5.3. Оптимизация циклов
- •5.3.1. Развертывание цикла
- •5.3.2. Программная конвейерная обработка
- •5.4. Особенности поддержки циклов в архитектуре IntelItanium
- •5.4.1. Ротация регистров
- •5.4.2. Замечание об инициализации ротации предикатов
- •5.4.3. Переходы циклов с программной конвейерной обработкой
- •5.4.3.1. Переходы счетных циклов
- •5.4.3.2. Пример счетного цикла
- •5.4.3.3. Переходы while-циклов
- •5.4.4. Краткий обзор терминологии
- •5.5. Оптимизация циклов в архитектуре IntelItanium
- •5.5.1. While-циклы
- •5.5.2. Циклы с инструкциями, имеющими предикаты
- •5.5.3. Циклы с множеством выходов
- •5.5.3.1. Преобразование циклов с несколькими выходами в циклы с одним выходом.
- •5.5.3.2. Конвейерная обработка с явными многократными выходами
- •5.5.4. Соображения о программной конвейерной обработке
- •5.5.5. Программная конвейерная обработка и предварительные загрузки
- •5.5.5.1. Ограничения емкости
- •5.5.5.2. Конфликты в alat
- •5.5.6. Предварительное разворачивание циклов для программной конвейерной обработки
- •5.5.7. Осуществление сокращений
- •5.5.8. Явный пролог и эпилог
- •5.5.9. Устранение избыточной загрузки в циклах
- •5.6. Итоги
5.4.3.2. Пример счетного цикла
Ниже представлен концептуальный вид конвейерной итерации исходногопримера счетного цикла с ИИ равным единице:
стадия 1:(p16) ld4 r4 = [r5],4
стадия 2:(p17) --- // пустая стадия
стадия 3:(p18) add r7 = r4,r9
стадия 4:(p19) st4 [r6] = r7,4
Чтобы сгенерировать эффективный конвейер, транслятор должен принять во внимание время выполнения инструкций и доступность функциональных устройств. Для этого примера, время ожидания загрузки равно двум, а загрузка и сложение планируются в двух отдельных тактах. Ниже, представлен конвейерный код в предположении, что имеются два порта памяти, а счетчик цикла равен 200.
Примечание. Теперь ротация регистровGRвключается прямо в код (этого нет в предшествующем коде). Кроме того, поскольку переменные индукции, являются постинкрементируемыми, то должны располагаться в статической части регистра файлов.
mov lc = 199 // LC =счетчик циклов - 1
mov ec = 4 // EC =стадий эпилогов + 1
mov pr.rot = 1<<16;; // PR16 = 1, остальные = 0
L1:
(p16)ld4 r32 = [r5],4 // Такт 0
(p18)add r35 = r34,r9 // Такт 0
(p19)st4 [r6] = r36,4 // Такт 0
br.ctop L1;; // Такт 0
Порты памяти используются полностью. В таблице 5.1 показана трасса выполнения этого цикла.
Табл. 5.1. Трассировка цикла ctop
Цикл |
Порт/Инструкции |
Состояние перед br.ctop | ||||||||
M |
I |
M |
B |
p16 |
p17 |
p18 |
p19 |
LC |
EC | |
0 |
ld4 |
|
|
br.ctop |
1 |
|
|
|
199 |
4 |
1 |
ld4 |
|
|
br.ctop |
1 |
1 |
|
|
198 |
4 |
2 |
ld4 |
add |
|
br.ctop |
1 |
1 |
1 |
|
197 |
4 |
3 |
ld4 |
add |
st4 |
br.ctop |
1 |
1 |
1 |
1 |
196 |
4 |
… |
… |
… |
… |
… |
… |
… |
… |
… |
… |
… |
100 |
ld4 |
add |
st4 |
br.ctop |
1 |
1 |
1 |
1 |
99 |
4 |
… |
… |
… |
… |
… |
… |
… |
… |
… |
… |
… |
199 |
ld4 |
add |
st4 |
br.ctop |
1 |
1 |
1 |
1 |
0 |
4 |
200 |
|
add |
st4 |
br.ctop |
|
1 |
1 |
1 |
0 |
3 |
201 |
|
add |
st4 |
br.ctop |
|
|
1 |
1 |
0 |
2 |
202 |
|
|
st4 |
br.ctop |
|
|
|
1 |
0 |
1 |
… |
|
|
|
|
|
|
|
|
0 |
0 |
В такте 3 начинается фаза ядра, здесь в четвертой итерации цикла ядра выполняются инструкции ld4, addиst4из четвертой, второй и первой исходных итераций соответственно. На 200-ом такте выполнены все 200 загрузок и начинается фаза эпилога. На 202-ом такте, при выполнении инструкцииbr.ctop, значение ЕС равно 1. ЕС декрементируется, регистры один раз ротируются, а выполнение выходит из ядерного цикла.
Примечание. После этой финальной стадии, ЕС и предикаты стадий (р16-р19) равны нулю.
Желательно выделять переменные, которые являются циклическим вариантом ротационной части регистрового файла каждый раз, когда это возможно, для сохранения места в статической области для инвариантных переменных цикла. Переменные индукции, которые являются постинкрементируемыми, должны быть выделены в статической части регистрового файла.