gcc и оптимизация

Тема в разделе "LANGS.C", создана пользователем Microedition, 22 июн 2009.

  1. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    компилирую прогу с использованием gcc 3.4.5 с параметрами:
    -O2 -fomit-frame-pointer

    стек-фреймы действительно отключаются, но, непонятно мне, зачем
    компилятор делает так:
    Код (Text):
    1. test:
    2.     sub    esp,n
    3.  
    4.     ; ...
    5.  
    6.     add    esp,n
    7. ret
    причем, локальных переменных нет, а параметры передаются через регистры (fastcall),
    но не более 2 параметров. (используются edx и ecx)
    то есть передача параметров через стек не используется.

    тогда зачем нужен этот пролог/эпилог из sub esp,n / add esp,n
    число n может варьироваться.
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Microedition
    > gcc ... число n может варьироваться
    Не выравнивает ли он стек на 16-тибайтную границу?
     
  3. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    ну, например:
    Код (Text):
    1. 00000020 ; int __fastcall matrix2x2_alloc()
    2. 00000020                 public @matrix2x2_alloc@0
    3. 00000020 @matrix2x2_alloc@0 proc near
    4. 00000020                 sub     esp, 0Ch
    5. 00000023                 mov    ecx, 10h
    6. 00000028                 call     @rtl_malloc@4   ; rtl_malloc(x)
    7. 0000002D                 mov    ecx, eax
    8. 0000002F                 add     esp, 0Ch
    9. 00000032                 jmp     short @matrix2x2_init@4 ; matrix2x2_init(x)
    10. 00000032 @matrix2x2_alloc@0 endp ; sp-analysis failed
    или вот:
    Код (Text):
    1. 00000080 ; __fastcall list_free(x)
    2. 00000080                 public @list_free@4
    3. 00000080 @list_free@4    proc near
    4. 00000080                 push    ebx
    5. 00000081                 sub      esp, 8
    6. 00000084                 mov     ebx, ecx
    7. 00000086                 call      @list_clear@4   ; list_clear(x)
    8. 0000008B                 add      esp, 8
    9. 0000008E                 mov     ecx, ebx
    10. 00000090                 pop      ebx
    11. 00000091                 jmp     @rtl_free@4     ; rtl_free(x)
    12. 00000091 @list_free@4    endp
     
  4. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    а вот листинг matrix2x2_init():
    Код (Text):
    1. 00000000 ; __fastcall matrix2x2_init(x)
    2. 00000000                 public @matrix2x2_init@4
    3. 00000000 @matrix2x2_init@4 proc near             ; CODE XREF: matrix2x2_alloc()
    4. 00000000                 mov     eax, 0
    5. 00000005                 mov     edx, 3F800000h
    6. 0000000A                 mov     [ecx+4], eax
    7. 0000000D                 mov     [ecx+8], eax
    8. 00000010                 mov     eax, ecx
    9. 00000012                 mov     [ecx], edx
    10. 00000014                 mov     [ecx+0Ch], edx
    11. 00000017                 retn
    12. 00000017 @matrix2x2_init@4 endp
     
  5. bugaga

    bugaga New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2007
    Сообщения:
    361
    открой для себя еще -mregparm=3 и не надо будет писать никакого __fastcall
    Код (Text):
    1. #include <inttypes.h>
    2. #include <stdio.h>
    3.  
    4. __int64 xz (__int64 my, int x)
    5. {
    6.   return my >> x;
    7. }
    8.  
    9. int main (void)
    10. {
    11.  printf ("%x", xz(0x123456789ABCDEF0,48));
    12. }
    13.  
    14.  
    15.     .file   "my.c"
    16.     .intel_syntax
    17.     .text
    18.     .p2align 4,,15
    19. .globl _xz
    20.     .def    _xz;    .scl    2;  .type   32; .endef
    21. _xz:
    22.     shrd    eax, edx, cl
    23.     sar edx, cl
    24.     test    cl, 32
    25.     je  L2
    26.     mov eax, edx
    27.     sar edx, 31
    28. L2:
    29.     ret
    30.     .def    ___main;    .scl    2;  .type   32; .endef
    31.     .section .rdata,"dr"
    32. LC0:
    33.     .ascii "%x\0"
    34.     .text
    35.     .p2align 4,,15
    36. .globl _main
    37.     .def    _main;  .scl    2;  .type   32; .endef
    38. _main:
    39.     push    ebp
    40.     mov eax, 16
    41.     mov ebp, esp
    42.     sub esp, 24
    43.     and esp, -16
    44.     call    __alloca
    45.     call    ___main
    46.     mov ecx, 48
    47.     mov eax, -1698898192
    48.     mov edx, 305419896
    49.     call    _xz
    50.     mov DWORD PTR [esp+4], eax
    51.     mov DWORD PTR [esp+8], edx
    52.     mov DWORD PTR [esp], OFFSET FLAT:LC0
    53.     call    _printf
    54.     leave
    55.     ret
    56.     .def    _printf;    .scl    2;  .type   32; .endef
    в принципе xz красотищща (и пофик на main) :)

    а да ключи компиляния
    *.S сорц проги: gcc -S -mregparm=3 -O2 -mconsole -momit-leaf-frame-pointer -masm=intel my.c

    собственно маленькая ексешка: gcc -s -mregparm=3 -O2 -mconsole -momit-leaf-frame-pointer -masm=intel my.c
     
  6. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Microedition
    Можно предположить, что gcc заботится о размещении адрес возврата из подпрограммы на 16-байтной границе.
    В int __fastcall matrix2x2_alloc() команда sub esp, 0Ch заботится об адресе возврата из rtl_malloc.
    В __fastcall list_free(x) есть push ebx, поэтому sub esp, 8.
    В __fastcall matrix2x2_init(x) нет вызовов подпрограмм, поэтому нет манипуляций с регистром esp.
     
  7. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    q_q
    да, действительно, там, где нет вызовов подпрограмм и нет локальных переменных,
    esp не изменяется.
    ну а __fastcall matrix2x2_alloc() вообще-то возвращяет указатель, но это и не важно.
     
  8. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Microedition
    > __fastcall matrix2x2_alloc() вообще-то возвращяет указатель
    Ты понял не до конца. Об адресе возврата заботится вызывающая сторона.
    Про int __fastcall matrix2x2_alloc() я написал, что она "заботится об адресе возврата из rtl_malloc".
     
  9. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    хмм.. не забывайте, что все функции передают параметры через регистры (fastcall).
    а rtl_malloc принимает один аргумент типа dword (в ecx) и возвращает dword..
    так что манипуляции с указателем стека не нужны. или я туплю, т.к. день не спал.
     
  10. Microedition

    Microedition Active Member

    Публикаций:
    0
    Регистрация:
    5 июн 2008
    Сообщения:
    814
    пропатчил код, забил nop'ами команды sub esp,xx / ass esp,xx
    программа нормально работает.
     
  11. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Microedition
    > манипуляции с указателем стека не нужны
    Что непонятно в первом предложении #6?

    > программа нормально работает
    А надо было оптимально, правда, критерии (скорость/размер) не озвучены.
    Например, с точки зрения скорости обработки данных будет лучше, если данные будут лежать по адресам кратным 16-ти.