Skip to content

GCC:Optimization

gcc는 기본적으로 아무런 옵션을 지정하지 않으면, 만들어지는 코드를 최적화(optimization)시키지 않는다. 최적화를 위해, 여러가지 옵션을 제공하는데, 이들 옵션을 일일히 선택하기 보다는 이들 옵션을 세트로 묶어 제공하는 -O, -O1, -O2, -O3 등을 일반적으로 사용한다.

(gcc version 3.2.2, 3.4.6 기준.)
(참고로 -O0는 전혀 최적화하지 말라는, default 옵션이다.)

Optimization set

-O, -O1
만들어지는 오브젝트, 또는 실행 파일을 가능한 작게 하면서, 컴파일 시간이 오래걸리지 않는 범위에서 최적화를 수행한다.
-O2
만들어지는 코드가 가능한 빠르게 수행되도록 하지만, 코드의 크기가 너무 커지지 않도록 하는 범위에서 최적화를 수행한다.
-Os
-O2에서 제공하는 모든 최적화 기능을 다 쓰지만, 코드의 크기를 증가시키는 최적화 기능은 빼고 나서 최적화를 수행한다.
-O3
코드의 크기는 전혀 신경 쓰지 않고, 오직 빠른 코드를 만들어 내기 위해 최적화를 수행한다. 그러나, 꼭 생각해 두어야 할 점은, -O3로 만들어낸 코드가 반드시 -O2를 써서 만들어낸 코드보다 빠르다는 보장은 없다. 그 이유는, 보통 CPU가 기계어를 수행할 때, 일정한 분량만큼 먼저 CPU 내부의 cache(캐시)에 불러와서 수행하는데, -O3를 써서 만든 코드는 대개 크기가 커서, 이 cache에 들어갈 수 있는 명령의 양이 상대적으로 적어지기 때문에, 오히려 느려질 가능성도 있다.

-On (n=1, 2, 3) 꼴의 옵션과 더불어 다른 옵션을 섞어 쓸 수도 있다. 예를 들어, -O2 를 쓸 경우, inline-function 최적화는 적용되지 않는다. 따라서 아래와 같이 -O2 에 해당하는 모든 최적화 기법들과 -inline-functions 을 함께 쓸 수 있다.

$ gcc -O2 -finline-funtions hello.c

물론, 특정 옵션 기능을 빼는 것도 가능하다. 아래는 -O3 가 제공하는 모든 최적화 기법을 적용하지만 inline-functions 최적화만 빼고 컴파일하는 것을 보여준다.

$ gcc -O3 -fno-inline-functions hello.c

즉, 추가 옵션을 적용시키려면(on) -f<OPTION_NAME>을 쓰고, 끄려면(off), -fno-<OPTION_NAME>꼴을 사용하면 된다.

GCC Optimization Option List

최적화옵션리스트는 아래와 같다. 최적화셋트옵션에 대한 사용여부도 함께 정리했다.

Optimization

-O1

-O2

-Os

-O3

Remarks

defer-pop

O

O

O

O

thread-jumps

O

O

O

O

branch-probabilities

O

O

O

O

cprop-registers

O

O

O

O

guess-branch-probability

O

O

O

O

omit-frame-pointer

O

O

O

O

merge-constants

O

O

O

O

loop-optimize

O

O

O

O

if-conversion

O

O

O

O

if-conversion2

O

O

O

O

align-loops

X

O

X

O

align-jumps

X

O

X

O

align-labels

X

O

X

O

align-functions

X

O

X

O

crossjumping

X

O

O

O

prefetch-loop-array

?

?

X

?

optimize-sibling-calls

X

O

O

O

cse-follow-jumps

X

O

O

O

cse-skip-blocks

X

O

O

O

gcse

X

O

O

O

gcse-lm

X

O

O

O

gcse-sm

X

O

O

O

gcse-las

X

O

O

O

expensive-optimizations

X

O

O

O

strength-reduce

X

O

O

O

rerun-cse-after-loop

X

O

O

O

rerun-loop-opt

X

O

O

O

caller-saves

X

O

O

O

force-mem

X

O

O

O

peephole2

X

O

O

O

regmove

X

O

O

O

strict-aliasing

X

O

O

O

컴파일러는 서로 다른 타입의 변수는 동일한 메모리를 가리키지 않는다. (상세 정보)

delete-null-pointer-checks

X

O

O

O

reorder-blocks

X

O

O

O

reorder-functions

X

O

O

O

unit-at-a-time

X

O

?

O

schedule-insns

X

O

O

O

schedule-insns2

X

X

X

O

schedule-interblock

X

O

?

O

sched-spec

X

O

?

O

inline-functions

X

X

X

O

rename-registers

X

X

X

O

web

X

X

X

O

unswitch-loops

X

X

?

O

FORTIFY SOURCE

FORTIFY_SOURCE가 적용되면 일반 메모리/문자열 및 버퍼 관련 함수들은 GCC builtin 함수로 바뀌는데 이들은 연산을 수행할 대상 (Destination, 즉 결과가 저장될 영역)의 크기를 알아야만 Overflow 검사를 할 수 있다. 이러한 메모리 영역의 크기를 알아내기 위해 __builtin_object_size() 내장 함수가 사용된다.

사용방법은 아래와 같다.

  • -O1이상의 최적화 옵션.
  • -D_FORTIFY_SOURCE=N으로 Define 추가.

See also

Favorite site

References


  1. GCC_optimization_-_Gentoo_Wiki.pdf