
- •4. Предикация, поток управления и поток инструкций
- •4.1. Краткий обзор
- •4.2. Предикация
- •4.2.1. Стоимость эффективности переходов
- •4.2.1.1. Ресурсы предсказания
- •4.2.1.2. Планирование инструкций
- •4.2.2. Предикация в архитектуре IntelItanium
- •4.2.3. Оптимизация эффективности программы использующей предикацию
- •4.2.3.1. Применение преобразования типа if
- •4.2.3.2. Предикация вне пути
- •4.2.3.3. Перемещение кода вверх.
- •4.2.3.4. Перемещение кода вниз
- •4.2.3.5. Сокращение засорения кэша.
- •4.2.4. Соображения о предикации
- •4.2.4.1. Несбалансированные пути выполнения.
- •4.2.4.2. Случай 1
- •4.2.4.3. Случай 2
- •4.2.4.4. Случай 3
- •4.2.4.5. Использование наложения ресурсов
- •4.2.4.6. Случай 1
- •4.2.5. Рекомендации по удалению ветвей
- •4.3. Оптимизация потока управления
- •4.3.1. Уменьшение критического пути при параллельном сравнении
- •4.3.2. Сокращения критического пути с помощью ветвлений.
- •4.3.3. Выбор множества значений для одной переменной или регистра с предикацией
- •4.3.3.1. Выбор одного из нескольких значений
- •4.3.3.2. Уменьшение использования регистров.
- •4.3.4. Улучшение выборки потока инструкций
- •4.3.4.1. Выравнивание потока инструкций.
- •4.4. Подсказки перехода и предвыборки
- •4.5. Итоги
4.3.2. Сокращения критического пути с помощью ветвлений.
Хотя нет никаких специальных инструкций для поддержки переходов с множеством условий и множеством адресатов, но в архитектуре Itaniumимеется неявная поддержка, путем разрешения множества последовательных слотов «В» инструкций в одной группе инструкций.
Пример использует основной блок с четырьмя возможными разветвлениями (successors). Следующий разветвляющий код типаItanium, использует шаблон связки ВВВ, и может выполнить переход, либо в блокB, либо в блокC, либо в блокD, либо пройти вниз в блокA:
label_AA:
. . . // Инструкции блока AA
{ .bbb
(p1) br.cond label_B
(p2) br.cond label_C
(p3) br.cond label_D
}
// Прошли вниз до блока A
label_A:
. . . // Инструкции блока A
Если все ветви не являются взаимоисключающими, то порядок переходов важен для правильности работы программы, иначе транслятор может выбрать любое желаемое упорядочивание.
4.3.3. Выбор множества значений для одной переменной или регистра с предикацией
Обычно, в программах встречается набор путей, которые вычисляют значение для одной и той же переменной, а затем пути соединяются. Разновидностью этого является случай, когда разные пути должны вычислять разные результаты, но могут использовать один и тот же регистр, поскольку известно, что пути являются комплиментарными. Использование предикации может оптимизировать эти случаи.
4.3.3.1. Выбор одного из нескольких значений
Когда встречаются несколько путей управления, каждый из которых вычисляет различное значение одной переменной, то обычно требуется последовательность условных выражений для выбора значения, которое будет обновлять переменную. Использование предикации может эффективно осуществить этот код без переходов:
switch (rW)
case 1:
rA = rB + rC;
break;
case 2:
rA = rE + rF;
break;
case 3:
rA = rH - rI;
break;
Вышеприведенный switch-блок может быть полностью выполнен в одном такте с использованием предикации, если все предикаты были вычислены ранее. Предположим, что еслиrWравно 1, 2 или 3, тоp1, p2 илиp3,соответственно, равно истине.
(p1) add rA = rB, rC
(p2) add rA = rE, rF
(p3) sub rA = rH, rI;;
Без этой предикатной способности, для свертки этих значений, нужны были бы многочисленные переходы или условные перемещения.
Архитектура Itaniumпозволяет множеству инструкций использовать, на одном и том же такте, в качестве приемника один и тот же регистр, при условии, что в этом такте, только одна инструкция, записывающая приемный регистр, имеет предикат равный истине. Как обсуждалось в разделе 4.3.1, подобные способности существуют для записи предикатных регистров.
4.3.3.2. Уменьшение использования регистров.
В некоторых случаях, можно использовать один и тот же регистр для отдельных вычислений в присутствии предикации. Эта методика подобна методике для множественной записи для сохранения значения в одном и том же регистре, хотя это скорее оптимизация распределения регистра, чем использование критического пути.
После преобразования типа if, это чаще всего встречается в последовательностях инструкций, которые предикатируются комплиментарными предикатами. Приведенная ниже управляющая последовательность, содержит предикатыp1иp2, о которых компилятору известно, что они являются комплиментарными:
(p1) add r1=r2,r3
(p2) sub r5=r4,r56
(p1) ld8 r7=[r2]
(p2) ld8 r9=[r6];;
(p1) использование r1
(p2) использование r5
(p1) использование r7
(p2) использование r9
Регистры r1, r5, r7 и r9, используются для временных переменных компилятора, каждая из которых живет только до ее следующего использования, поэтому предшествующий сегмент кода может быть переписан так:
(p1) add r1=r2,r3
(p2) sub r1=r4,r56 // Повторное использованиеr1
(p1) ld8 r7=[r2]
(p2) ld8 r7=[r6];; // Повторное использованиеr7
(p1) использование r1
(p2) использование r1
(p1) использование r7
(p2) использование r7
Новая последовательность использует на два регистра меньше. При 128 регистрах определенных в архитектуре, это может показаться не существенным, но сокращение использования регистров может еще уменьшить программу, а также операции сливания/заливания механизма регистрового стека, которые обычны в кодах с высоким уровнем параллелизма инструкций.