2013-02-19 5 views
8

Из-за хакерского любопытства, интересно, как gcc может оптимизировать функцию ниже этого ловко?Объяснение оптимизации gcc

int c() { 
     int i, j = 0; 
     for (i = 0; i < 10; i++) { 
       j += i; 
     } 
     return j; 
} 

$objdump -D c.o ниже для оружия, но x86 не отличается от логики.

00000000 <c>: 
    0: 202d  movs r0, #45 ; 0x2d 
    2: 4770  bx lr 

Я в основном интересуюсь, является ли это результатом цепочки оптимизаций или что-то вроде соответствия шаблону? Есть ли какая-либо документация по такой оптимизации?

+0

retaging с с будет Atract больше людей ... – qPCR4vir

ответ

10

Оптимизатор делает это поэтапно/проходит ... когда вы указываете -O2, есть много оптимизаций, которые включены. Основные оптимизации, которые вступают в игру здесь

  1. loop unrolling
  2. constant propagation
  3. constant folding
  4. dead-code elimination

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

так что этот код

int i, j = 0; 
for (i = 0; i < 10; i++) { 
    j += i; 
} 
return j; 

после того, как петли разворачивания становится

int i, j = 0; 
i=0; j += i; 
i=1; j += i; 
i=2; j += i; 
i=3; j += i; 
i=4; j += i; 
i=5; j += i; 
i=6; j += i; 
i=7; j += i; 
i=8; j += i; 
i=9; j += i; 
return j; 

после того, как постоянная распространения прохода

int i, j = 0; 
i=0; j += 0; 
i=1; j += 1; 
i=2; j += 2; 
i=3; j += 3; 
i=4; j += 4; 
i=5; j += 5; 
i=6; j += 6; 
i=7; j += 7; 
i=8; j += 8; 
i=9; j += 9; 
return j; 

после устранения мертвого кода

j = 0; 
j += 0; 
j += 1; 
j += 2; 
j += 3; 
j += 4; 
j += 5; 
j += 6; 
j += 7; 
j += 8; 
j += 9; 
return j; 

после constant folding

j = 45; 
return j; 

и, наконец,

return 45; 
+2

Просто потрясающе ... – NeonGlow

+0

Извините, вниз голосования на старом ответ, но это не точное изображение выполняется преобразование GCC (хотя оно действительно работает и является разумной аппроксимацией и опрятной демонстрацией различных оптимизаций компилятора). Если вы хотите, чтобы внутренняя работа GCC для этого тестового теста, вы можете передать -fdump-tree-cunroll-all и прочитать результат. Мое главное возражение состоит в том, что большинство из этих анализов переплетаются, GCC решает развернуть, потому что знает, что он может сбросить переменную индукции, а cunroll выполняет свертывание/распространение, поэтому никогда не будет уничтожен какой-либо мертвый код. –

Смежные вопросы