Средства разработки приложений



              

Реализация раннего выполнения на Intel Itanium - часть 3


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

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

При устранении зависимости по управлению достаточно гарантировать, что в случае возникновения исключительной ситуации при выполнении ранней загрузки она будет возбуждена в корректном месте программы. Для этого инструкция ld.s, выполняя раннюю загрузку в некоторый регистр, при возникновении исключительной ситуации устанавливает для него специальный флаг NaT (Not a Thing), который свидетельствует о наличии отложенного исключения. Этот флаг может быть установлен для любого регистра общего назначения. Если этот флаг был установлен для какого-либо регистра, то он также будет установлен для всех регистров, значения которых были получены с помощью вычислений, использовавших значение первого регистра.

Если впоследствии проверочная инструкция chk.s обнаруживает, что для ее операнда регистра установлен флаг NaT, то она передает управление на код восстановления, который должен устранить последствия неудачной попытки раннего выполнения. Примеры ассемблерного кода с использованием раннего выполнения приведены на рис. 3.

Исходная программа Программа с инструкциями раннего выполнения Исходная программа Программа с инструкциями раннего выполнения
adds r15=r16,r14
st8 r14=[r14]
nop.i
ld8 r18=[r19];;
st4 r15=[r33]
nop.i
ld8 r14=[r18];;
ld8.a r18=[r19];;
adds r15=r16,r14
nop.i
st8 r14=[r14]
ld8.c.clr r18=[r19]
nop.i;;
ld8 r14=[r18];;
st4 [r15]=r33
mov r1=r42
adds r14=1,r8;;
cmp4.ltu p6, r14
(p6) br.cond bd0
ld4 r14=[r33];;
add r14=r14,r8
adds r14=1,r8
ld4.s r15=[r33]
mov r1=r42;;
cmp4.ltu p6,r14
(p6) br.cond bf0
chk.s.m r15,b40;;
add r15=r15,r8
а) б)

Рис. 3. Примеры ассемблерного кода с командами раннего выполнения

а) преодоление зависимостей по данным,
б) преодоление зависимостей по управлению

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


Содержание  Назад  Вперед