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

3.5.4. Использование постинкрементных загрузок и сохранений.

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

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

ld8 r2=[r1]

add r1=1,r1 ;;

ld8 r3=[r1]

может быть переписан с использованием постинкрементной загрузки:

ld8 r2=[r1],1 ;;

ld8 r3=[r1]

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

  • Постинкрементные загрузки избегают расширения размеров кода путем объединения двух инструкций в одну.

  • Сложение может быть запущено либо на устройстве типа I, либо – типаM. Если программа объединяет сложение и загрузку, то один из ресурсов устройствIилиMостается свободным, а иначе он был бы использован. Таким образом, производительность, зависящая от сложений и загрузок, может быть удвоена с помощью постинкрементных загрузок.

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

3.5.5. Оптимизация циклов.

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

while (cond) {

c = a + b; // Вероятно инвариант цикла

*ptr++ = c; // Может указывать на a или b

}

Переменные aиbвероятно являются инвариантами цикла (т.е. не меняются в цикле), однако компилятор должен предположить, что сохранения в*ptrбудут перезаписыватьaиb, если анализ не гарантирует, что этого никогда не случится. Использование предварительных загрузок и проверок позволяет удалить из цикла код, который вероятно будет инвариантным, даже когда указатель не может быть не двусмысленным.

ld4.a r1 = [&a]

ld4.a r2 = [&b]

add r3 = r1,r2 // Выносим вычисление из цикла

while (cond) {

chk.a.nc r1, recover1

L1: chk.a.nc r2, recover2

L2: *p++ = r3

}

А в конце модуля нужно добавить:

recover1: // Восстановление для неудачной загрузки a

ld4.a r1 = [&a]

add r3 = r1, r2

br.sptk L1 // Безусловный переход

recover2: // Восстановление для неудачной загрузки b

ld4.a r2 = [&b]

add r3 = r1, r2

br.sptk L2 // Безусловный переход

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

Так как проверки имеют две формы – с очисткой (clr) и без очистки (nc), то программист должен выбрать какую из них использовать. Этот пример показывает, что когда проверки перемещаются вне цикла, то не должна использоваться версия с очисткой. Это так, потому что версия с очисткой (clr) вызовет удаление соответствующего элементаALAT(а это привело бы к тому, что при следующей проверке регистр был бы ошибочным).