Генерация кода: использование регистров

Персональный блог одноименного форумчанина. Человека и парохода, не побоюсь этого сравнения :)

Модератор: tyomitch

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Генерация кода: использование регистров

Сообщение tyomitch » 27.05.2006 (Сб) 6:38

* В прошлый раз мы получили вот такой вот код:
Код: Выделить всё
push A
push B
mov reg, C
sub [sp], reg
pop reg
add [sp], reg
push D
mov ax, E
mul [sp]
mov [sp], ax
pop reg
add [sp], reg

Хотелось бы "оптимизировать" его так, чтобы все промежуточные значения в вычислениях хранились в регистрах, а не на стеке.


* Прежде всего, нужно решить, что делать с регистрами reg: можно просто нумеровать их, вести до самого конца в виде таких "логических регистров", и только в самом конце подставлять на их место "физические регистры". (Будем в рамках этой задачи считать, что у x86 есть 4 доступных нам регистра общего назначения: ax, bx, cx, dx.) Преимущество здесь в потенциальной переносимости: может оказаться, что код с такими "логическими регистрами" легко превратить в машинный код нескольких реальных процессоров. Но возникает риск "переиспользования" регистров: что, если в конце генерации кода окажутся одновременно используемыми 5 регистров? придётся откатываться на использование стека?

Другой подход -- расставить "физические регистры" сразу же, и тащить их до конца. Потом, если возникнет конфликт (двум "логическим регистрам" поставлен в соответствие один "физический", и оба этих регистра должны использоваться одновременно), то придётся каким-то образом их переименовывать, возможно, даже каскадом. Зато худшее, что может произойти -- лишние промежуточные значения останутся на стеке, а это не смертельно.

Последнее замечание про регистры -- то, что некоторые инструкции x86 навязывают использование конкретных регистров: например, инструкции mul и div всегда сохраняет результат в паре dx:ax, поэтому во время выполнения этих инструкций ни в dx, ни в ax не должно храниться промежуточных значений. Поэтому в нашем примере я расставляю "физические регистры" так, чтобы вокруг инструкции mul не было поблизости ни dx, ни ax.

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

Код: Выделить всё
                use prod cons
push A          st
push B          st
mov dx, C             dx
sub [sp], dx    st        dx
pop bx          st    bx
add [sp], bx    st        bx
push D          st
mov ax, E             ax
mul [sp]        st,ax dx  dx
mov [sp], ax    st        ax
pop cx          st    cx
add [sp], cx    st        cx


Здесь правая часть до неприличия простая, в связи с тем, что слева очень ограниченный набор инструкций. Но мы увидим, что она будет оказываться в дальнейшем более сложной, и более полезной.
Последний раз редактировалось tyomitch 27.05.2006 (Сб) 15:42, всего редактировалось 2 раз(а).
Изображение

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 27.05.2006 (Сб) 11:09

Хотелось бы высказать благодарность лично г-ну tyomitch за написание интересных топиков. ПО моему мнению, его блог - самый интересный на форуме.
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Сообщение BV » 27.05.2006 (Сб) 12:17

Просто у вас интересы совпадают.
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;


Вернуться в Tyomitch

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11

    TopList