gcc и оптимизация
Jan. 22nd, 2006 03:25 pmОдно из наиболее странных свойств gcc - оптимизация по принципу "или всё, или ничего". Чтобы пользоваться отладчиком, оптимизацию надо выключить. Но при этом он начинает генерировать такой код, что хоть святых выноси - восемь mov на одно значение вместо одного, сохранение значения из регистра в стек с тем чтобы тут же прочитать его из стека в регистр, и тому подобные ужасы. Чтобы получить более-менее нормальный код, надо дать хотя бы -O, но тогда начнётся смещение выполняемых действий относительно меток строк и пошаговая отладка станет невозможной. Ладно, для свежеиспечённого изделия такое понятно, но ведь gcc скоро стукнет 20 лет. Неужели за это время никто не озаботился проблемой качества кода на нижних уровнях оптимизации? Любой коммерческий компилятор (даже Borland'овский) справляется с этим значительно лучше gcc.
А самый злобный пример на его недооптимизацию выглядит так. Возьмём простейшую main():
Сассемблируем (результат одинаков для 3.4, 4.0, 4.1):
Что это за кошмар с вычислениями, которые можно было сделать на этапе компиляции?? Ах, это -mpreferred-stack-boundary=4... При подъёме до -O код становится вменяемым:
Только не надо говорить, что отладчик - сакс. Луговского слышали, всё понятно. Отладчик - рулез, если использовать его по назначению. Например, по срабатыванию breakpoint'а двигаться дальше сделав отладочную печать, или проверять условие и при его невыполнении возобновлять выполнение. (Второе не является watchpoint, по крайней мере в смысле gdb.) Есть ещё много вариантов, которые не сводятся к тупому втыканию в экран. Хотя и оно иногда полезно - чтобы наткнуться на проблему которую не замечал в упор из-за "замыленного глаза".
Насколько сложно было бы сделать в gcc нормальную промежуточную оптимизацию, действующую в пределах одной строки? И стоит ли оно возни? Смотря на коммерческие компиляторы я думаю, что стоит. И в чём загвоздка?
А самый злобный пример на его недооптимизацию выглядит так. Возьмём простейшую main():
int main()
{
int n, a, b;
return 0;
}
Сассемблируем (результат одинаков для 3.4, 4.0, 4.1):
main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl $0, %eax
leave
ret
Что это за кошмар с вычислениями, которые можно было сделать на этапе компиляции?? Ах, это -mpreferred-stack-boundary=4... При подъёме до -O код становится вменяемым:
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
subl $16, %esp
movl $0, %eax
leave
ret
Только не надо говорить, что отладчик - сакс. Луговского слышали, всё понятно. Отладчик - рулез, если использовать его по назначению. Например, по срабатыванию breakpoint'а двигаться дальше сделав отладочную печать, или проверять условие и при его невыполнении возобновлять выполнение. (Второе не является watchpoint, по крайней мере в смысле gdb.) Есть ещё много вариантов, которые не сводятся к тупому втыканию в экран. Хотя и оно иногда полезно - чтобы наткнуться на проблему которую не замечал в упор из-за "замыленного глаза".
Насколько сложно было бы сделать в gcc нормальную промежуточную оптимизацию, действующую в пределах одной строки? И стоит ли оно возни? Смотря на коммерческие компиляторы я думаю, что стоит. И в чём загвоздка?
no subject
Date: 2006-01-22 02:38 pm (UTC)В данном случае, как раз проблема в том, что компилятор вперед не заглядывает, и прошлого тоже не помнит.
(no subject)
From:(no subject)
From: (Anonymous) - Date: 2006-01-22 06:58 pm (UTC) - Expand(no subject)
From:no subject
Date: 2006-01-22 02:43 pm (UTC)(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From: (Anonymous) - Date: 2006-01-23 09:12 am (UTC) - Expand(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:no subject
Date: 2006-01-22 02:56 pm (UTC)(no subject)
From:(no subject)
From:no subject
Date: 2006-01-22 04:00 pm (UTC)main: pushl %ebp movl %esp,%ebp subl $24,%esp xorl %eax,%eax jmp .L2 .p2align 4,,7 .L2: leave ret .size main , . - main% gcc -v
Reading specs from /usr/lib/gcc-lib/i386-unknown-openbsd3.5/2.95.3/specs
gcc version 2.95.3 20010125 (prerelease, propolice)
(no subject)
From:no subject
Date: 2006-01-22 06:34 pm (UTC)-O turns on the following optimization flags: -fdefer-pop -fmerge-constants -fthread-jumps -floop-optimize -fcrossjumping -fif-conversion -fif-conversion2 -fdelayed-branch -fguess-branch-probability -fcprop-registers -O also turns on -fomit-frame-pointer on machines where doing so does not interfere with debugging.Видимо, тебе нужно подмножество этого набора. Может, без послених пяти или типа того.
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:Turbo Pascal
Date: 2006-01-23 09:10 am (UTC)joss
Re: Turbo Pascal
From:Re: Turbo Pascal
From:Re: Turbo Pascal
From:no subject
Date: 2006-01-29 10:30 pm (UTC)