Генерация высококачественного кода для программ, написанных на СИ | страница 11
¦ накоплению смещения для каждого элемента массива и ¦
¦ добавлению результата к базовому адресу массива. ¦
L--------------------------------------------------------------
"Слияние циклов" минимизирует управляющие заголовки циклов путем сращивания кода из циклов, имеющих одинаковые управляющие заголовки, в один цикл. Для того, чтобы удалить управляющий заголовок второго цикла, два простых цикла
>for(i = 0; i < 10; i++)
> a = b + c;
>for(i = 0; i < 10; i++)
> d = e + f;
могут быть объединены в один цикл
>for(i = 0; i < 10; i++) {
> a = b + c;
> d = e + f;
>}
Поскольку для поддержки слияния циклов требуется процедурная оптимизация, в общем случае это действие не выполняется. Ни один из включенных в обзор компиляторов этот метод не применяет.
Непосредственно связано со слиянием циклов "разворачивание циклов", которое минимизирует количество проходов через цикл путем увеличения числа операций, выполняемых внутри каждой итерации. Цикл инициализации массива
>int a[3];
>int i;
>for(i = 0; i < 3; i++)
> a[i] = 0;
странслированный компилятором без оптимизации, может получить следующий эквивалент в языке ассемблера:
>mov i,0
>LOOP:
> mov BX,i
> shl BX,1
> mov a[BX],0
> inc i
> cmp i,3
> jl LOOP
В том же коде, оптимизированном по методу разворачивания цикла, удаляется цикл путем замещения его тремя инструкциями присваивания:
>mov a,0
>mov a+2,0
>mov a+4,0
Хотя ни один из компиляторов, включенных в обзор, не выполняет буквальное разворачивание циклов, некоторые из них оптимизируют цикл путем использования "специализированных инструкций прцессора". Многие процессоры предоставляют специализированные инструкции для управления перемещением блоков данных, инициализации памяти и других часто встречающихся ситуаций управления данными. К примеру, строковые инструкции с префиксом повторения (в семействе процессоров 80x86), выполняющиеся быстрее, чем посимвольные команды в цикле. Оптимизирующий компилятор использует, когда возможно, инструкции процессора для управления ситуациями в специальных случаях. Применение специализированных инструкций процессора к расширенной версии предыдущего примера разворачивания циклов
>int a[10000];
>int i;
>for(i = 0; i < 10000; i++)
> a[i] = 0;
дает приведенный ниже ассемблерный код процессора 80x86. Он гораздо быстрее, чем его аналог, записанный в виде цикла или набора инструкций непосредственной засылки в память, имеющего соответствующую длину: