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

4.3. Оптимизация потока управления

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

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

Третья оптимизация, относящаяся к управлению потоком, использует предикацию для улучшения выборки инструкций с помощью преобразования типа if, для генерации прямолинейных (straight-line) последовательностей, которые могут быть эффективно выбраны. Использование этих случаев и их оптимизация, описаны в остальной части данного раздела.

4.3.1. Уменьшение критического пути при параллельном сравнении

Вычисление составного условия перехода показанное ниже, требует нескольких инструкций в процессоре без специальных инструкций:

if ( rA || rB || rC || rD ) {

/* Инструкции блока If */

}

/* Нечто, следующее за блоком If*/

Следующий псевдокод показывает одно из возможных решений, использующее последовательность переходов:

cmp.ne p1,p0 = rA,0

cmp.ne p2,p0 = rB,0

(p1) br.cond if_block // Переход к инструкциям блока If

(p2) br.cond if_block

cmp.ne p3,p0 = rC,0

cmp.ne p4,p0 = rD,0

(p3) br.cond if_block

(p4) br.cond if_block

// Нечто, следующее за блоком If

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

or r1 = rA, rB

or r2 = rC, rD ;;

or r3 = r1, r2 ;;

cmp.ne p1,p2 = r3,0

(p1) br if_block

Это решение требует трех тактов для вычисления условия перехода, который, затем, может использоваться для перехода к блоку if.

Примечание. Его также можно использовать как предикатp1используемый блокомif, для того, чтобы избежать неправильного предсказания перехода.

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

Чтобы эта модель использования работала должным образом, архитектура требует, чтобы программист гарантировал, что пока выполняется данный код, все инструкции, приемник которых является данным предикатным регистром:

  • либо записывают одно и то же значение (0 или 1),

  • либо вовсе не записывают приемный регистр.

Эта модель использования означает, что иногда параллельное сравнение не может обновить значение своих приемных регистров и таким образом, в отличие от обычного сравнения, предикаты, используемые в параллельном сравнении, должны быть инициализированы до параллельного сравнения. Для полной информации об операциях параллельного сравнения см. «Часть I. Руководство по прикладной архитектуре».

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

Инструкции ниже показывают, как генерировать код для вышеприведенного примера, используя инструкции параллельного сравнения:

cmp.ne p1,p0 = r0,r0;; // инициализируем p1 в 0

cmp.ne.or p1,p0 = rA,r0

cmp.ne.or p1,p0 = rB,r0

cmp.ne.or p1,p0 = rC,r0

cmp.ne.or p1,p0 = rD,r0

(p1) br.cond if_block

Также возможно использовать p1 для предикации встроенного блокаif, чтобы избежать возможного промаха предсказания. Параллельным сравнением, также, могут быть сгенерированы более сложные выражения:

if ((rA < 0) && (rB == -15) && (rC > 0))

/* Инструкции If-блока */

Ниже показана возможная последовательность ассемблерного псевдокода для вышеприведенного кода C:

cmp.eq p1,p0=r0,r0;; // инициализируем p1 в 1

cmp.ne.and p1,p0=rB,-15

cmp.ge.and p1,p0=rA,r0

cmp.le.and p1,p0=rC,r0

При корректном использовании, сравнения И/ИЛИ, либо запишут в оба предикатных приемника одно и то же значение, либо ничего не запишут в предикатные приемники. Для другого варианта использования параллельного сравнения нужны обе части сложного условного выражения и if, иelse:

if ( rA == 0 || rB == 10 )

r1 = r2 + r3;

else

r4 = r5 - r6;

Параллельные инструкции имеют вариант andcm, который одновременно вычисляет и предикат, и его дополнение.

cmp.ne p1,p2 = r0,r0;; // инициализация p1,p2

cmp.eq.or.andcm p1,p2 = rA,r0

cmp.eq.or.andcm p1,p2 = rB,10;;

(p1) add r1=r2,r3

(p2) sub r4=r5,r6

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