Читаем Генерация высококачественного кода для программ, написанных на СИ полностью

¦ sub SI,SI imul AX,DI,3 ¦

¦ $0265: inc j5 ¦

¦ sub CX,3 imul BX,j5,5 ¦

¦ add SI,5 cwd ¦

¦ mov AX,CX idiv BX ¦

¦ cwd mov i5,AX ¦

¦ idiv SI test DI,DI ¦

¦ mov DI,AX jg L4 ¦

¦ or CX,CX ¦

¦ jg $0265 ¦

¦ mov i5,DI ¦

+-------------------------------------------------------------+

¦ Компилятор Microsoft C 5.0 выполнил снижение мощности на ¦

¦ константном выражении и разместил в регистрах все ¦

¦ переменные внутри простого цикла, включая вычисляемое ¦

¦ значение i5. Высокая степень проведенного анализа цикла ¦

¦ демонстрируется тем, что заключительные состояния k5 и j5 ¦

¦ были определены заранее компилятором, а не позже, во ¦

¦ время выполнения. ¦

L--------------------------------------------------------------

"Вынесение инвариантного (неизменяющегося) кода" - один из путей ускорения циклов, заключающийся в вынесении выражений за пределы цикла, если значения, ими вычисляемые, являются неизменными во время выполнения цикла. Если инвариантный код выносится из следующего цикла:

unsigned char i,j,k,v,x;

for( i = 0; i < v; i++)

x = i * (j+k);

его логический эквивалент будет:

T1 = j + k;

for(i = 0; i < v; i++)

x = i * T1;

 

--------------------------------------------------------------¬

¦РИСУНОК 3: Вынесение инвариантного кода - Microsofr C 5.0 ¦

+-------------------------------------------------------------+

¦Исходный текст на Си MICROSOFT COMPUTER INNOVATIONS ¦

¦ C 5.0 C86Plus 1.10 ¦

+-------------------------------------------------------------+

¦for(i4=0;i4<=2;i4++) sub SI,SI mov i4,0 ¦

¦ ivector2[i4] =j*k; mov AX,j jmp L44@2 ¦

¦ imul k L9@2: ¦

¦ mov [BP-4],AL mov AX,j ¦

¦ $L20007: imul k ¦

¦ mov AL,[BP-4] mov SI,i4 ¦

¦ mov ivector2[SI],AL ¦

¦ inc SI mov ivector2[SI],AL¦

¦ cmp SI,2 inc i4 ¦

¦ jle $L20007 L44@2: ¦

¦ mov i4,SI cmp i4,2 ¦

¦ jle L9@2 ¦

+-------------------------------------------------------------+

¦ Вынесение инвариантного кода уменьшает время выполнения ¦

¦ цикла путем вынесения неизменяющихся выражений из тела ¦

¦ цикла. В отличие от Computer Innovations C86Plus 1.10, ¦

¦ компилятор Microsoft C 5.0 успешно выносит выражение j * h ¦

¦ за пределы цикла, так что оно выполняется только один раз, ¦

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

L--------------------------------------------------------------

Рис. 3 демонстрирует вынесение инвариантного кода компилятором Microsoft C 5.0.

Дальнейший анализ примера показывает, что значение переменной i, индекса цикла, изменяется непосредственно с каждой итерацией. Отдельное присваивание i, известной как "переменная индукции цикла", может быть удалено:

T1 = j + k;

for(x = 0; x< T1 * v; x += T1);

i = v;

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

--------------------------------------------------------------¬

¦РИСУНОК 4: Удаление переменных индукции цикла ¦

+-------------------------------------------------------------+

¦Исходный текст на Си MICROSOFT DATALIGHT ¦

¦ C 5.0 Optimum-C 3.14 ¦

+-------------------------------------------------------------+

¦for(i=0;i<100;i++) mov AX,0 ¦

¦ ivector5[i*2+3]=5; mov i,100 mov i,AX ¦

¦ mov SI,OFFSET ivector5+6 cmp AX,100 ¦

¦ $L20006: jge L134 ¦

¦ mov [SI],5 L11B: ¦

¦ add SI,4 mov BX,i ¦

¦ cmp SI,OFFSET ivector5+406 shl BX,1 ¦

¦ jb $L20006 shl BX,1 ¦

Похожие книги