Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MProc / M9 / Оптимизация часть 4..doc
Скачиваний:
19
Добавлен:
16.04.2013
Размер:
124.42 Кб
Скачать

4.2.3.4. Перемещение кода вниз

Также как и при перемещении кода вверх, перемещение кода вниз затруднено при присутствии сохранений. Следующий пример показывает, как код может быть передвинут мимо метки вниз, это преобразование часто опасно без предикации:

ld8 r56 = [r45];; // Такт 0: загрузка

st4 [r23] = r56;; // Такт 2: сохранение

label_A:

add ... // Такт 3

add ...

add ...

add ...;;

В вышеприведенном коде предполагаемое время ожидания между загрузкой и сохранением составляет два такта. Допустим, что инструкция загрузки не может быть передвинута вверх из-за других зависимостей, единственный способ перепланирования инструкций так, чтобы время выполнения совмещалось – это передвинуть сохранение вниз, мимо метки.

Следующий код демонстрирует общую идею использования предикатов для разрешения перемещения кода вниз. В коде, фактически сгенерированном компилятором, предикаты, явно вычисляемые в этом примере, уже могли бы быть доступны в предикатных регистрах, и не требовать дополнительных инструкций.

// Точка, которая "доминирует" над label_A

cmp.ne p1,p0 = r0,r0 // Инициализация p1 для false

// Другие инструкции

cmp.eq p1,p0 = r0, // Инициализация p1 для true

ld8 r56=[r45];; // Такт 0

label_A:

add ... // Такт 1

add ...

add ...

add ...;;

(p1) st4 [r23]=r56 // Такт 2

Здесь перемещение кода вниз сохраняет один такт. Имеются примеры более сложных ситуаций, включающих циклическое планирование, другие ограниченные сохранениями перемещения кода или вынесения кода за пределы циклов, но они не описываются здесь.

4.2.3.5. Сокращение засорения кэша.

Загрузки и сохранения с предикатами, которые являются ложными во время выполнения, обычно, вероятно, не трогают строки кэша для удаления, замены или вызова. Также не требуется ни каких дополнительных инструкций или кода восстановления, как это было необходимо при спекуляциях по данным или управлению. Поэтому, когда использование предикации приводит к такой же длине критического пути, что и спекуляция по данным или управлению, то почти всегда предпочтительнее использовать предикацию.

4.2.4. Соображения о предикации

Хотя предикация имеет рад выгодных эффектов, но имеется несколько случаев, где использование предикации должно рассматриваться тщательнее. Такие случаи обычно связаны с путями выполнения, которые имеют несбалансированное общее время выполнения либо со слишком интенсивным использованием специфического ресурса, типа тех, которые связаны с операциями памяти.

4.2.4.1. Несбалансированные пути выполнения.

Нижеприведенное простое условное выражение имеет не сбалансированный размер потоковой зависимости. Предположим, что не предикатное ассемблирование для этой последовательности занимает два такта для блока if, и примерно 18 тактов, если мы считаем, чтоsetfзанимает 8 тактов,getfзанимает 2 такта, аxmaзанимает 6 тактов:

if (r4) // 2 такта

r3 = r2 + r1;

else // 18 тактов

r3 = r2 * r1;

f (r3); // Целочисленное использование r3

Ниже показано преобразование типа ifдляItaniumкода. Количество тактов показано в зависимости от значенийp1иp2и описывает время выполнения:

// Использовано тактов, если p2есть:True False

cmp.ne p1,p2=r4,r0;; // 0 0

(p1) add r3=r2,r1 // 1 1

(p2) setf f1=r1 // 1 1

(p2) setf f2=r2;; // 1 1

(p2) xma.l f3=f1,f2,f0;; // 9 2

(p2) getf r3=f3;; // 15 3

(p2) use of r3 // 17 4

Этот код требует восемнадцати тактов, если p2есть истина, но пяти тактов, еслиp2есть ложь. При анализе таких случаев рассматриваются веса выполнения, вероятности промахов предсказания, и затраты на предикацию по каждому пути.

В трех сценариях, представленных ниже, предположим, что промах перехода стоит десять тактов. Нет кэша инструкций или штрафы, связанные с принятием перехода не рассматриваются.