Как оптимизирует MSVC 7.1 ?

Тема в разделе "WASM.WIN32", создана пользователем _DEN_, 18 апр 2005.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Вот на такой код:
    Код (Text):
    1. for(int i=0;i<10;i++)
    2.   MessageBox(0,0,0,0);


    МС-компиллер дает такой асм:
    Код (Text):
    1. .00401000:  push        esi
    2. .00401001:  mov         esi,MessageBoxA ;USER32
    3. .00401007:  push        edi
    4. .00401008:  mov         edi,00000000A  ---↑ (1)
    5. .0040100D:  lea         ecx,[ecx][00]
    6. .00401010:  push        000
    7. .00401012:  push        000
    8. .00401014:  push        000
    9. .00401016:  push        000
    10. .00401018:  call        esi
    11. .0040101A:  sub         edi,001 ;"☺"
    12. .0040101D:  jne        .000401010  ---↑ (2)
    13. .0040101F:  pop         edi
    14. .00401020:  xor         eax,eax
    15. .00401022:  pop         esi


    Оптимизация "по всем понтам на скорость".

    Во-первых не ясно, почему уменьшение счетчика делается через sub а не через dec. Далее, зачем MessageBoxA запихивать в регистр? Если уж на то пошло, могли бы и ноль в регистре хранить. Ну и совсем непонятно на кой хрен нужна команда "lea ecx,[ecx][00]" ?



    И маленький вопросик в довесок: можно ли заставить компиллер константные циклы разворачивать?
     
  2. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_

    Ну с первыми двумя все понятно: sub и dec не рекомендованы интел и втюне на них даже плюется; в регистр пихать хотябы затем чтоб в цикле вызов без референса к памяти. А вот с lea ecx,[ecx][00] явно лошит и в 8й студии такого уже нет:
    Код (Text):
    1. _main   PROC                        ; COMDAT
    2. ; Line 4
    3.     push    esi
    4. ; Line 5
    5.     mov esi, DWORD PTR __imp__MessageBoxA@16
    6.     push    edi
    7.     mov edi, 10                 ; 0000000aH
    8.     npad    3
    9. $LL3@main:
    10. ; Line 6
    11.     push    0
    12.     push    0
    13.     push    0
    14.     push    0
    15.     call    esi
    16.     sub edi, 1
    17.     jne SHORT $LL3@main
    18.     pop edi
    19. ; Line 7
    20.     xor eax, eax
    21.     pop esi
    22.     ret 0
    23. _main   ENDP


    [апдейт]

    Чета сразу не заметил, что lea это паддинг - так что и с этим притензии к компилеру сняты...
     
  3. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    _DEN_

    Ты забыл указать, с какими ключами велась компиляция.
     
  4. infern0

    infern0 New Member

    Публикаций:
    0
    Регистрация:
    7 окт 2003
    Сообщения:
    811
    Адрес:
    Russia


    что-бы выровнять начало цикла на 4-х байтовую границу и экономить потом на переходе.
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    semen







    И как это понимать?







    Это что такое?



    q_q



    Все default кроме:



    Optimization:



    - Global optimization: yes

    - Favor size or speed: favor fast code

    - Optimize for processor: Pentium 4 and above

    - Optimize for windows application: yes



    Code generation:



    - Enable enchanced instruction set: SSE2
     
  6. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    infern0

    Какой извратный способ :) И в чем заключается экономия?
     
  7. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_



    Ну во-первых на норсвуде они не дабл спид. Есть ли еще противопоказания не помню, но помню точно что во всех манах интела это не рекомендованные инструкции и must be avoid. А про паддинг сам почитай, скорее всего npad 3 и оттранислировался ассемблером в lea, тока 7&8я студия паддит на 8\16, а не на 4.
     
  8. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    semen

    Тоесть теперь dec медленнее чем sub? Я познаю мир с подгузниками хаггис... В голове не укладывается.
     
  9. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_

    Ну да - на норсвуде медленее, а на прескотте одинаково, но типа интел уже сказал что ему на эти инструкции наплевать и в будущем может стать снова медленее =)

    [апдейт]

    вобщем вот:
    Код (Text):
    1. Assembly/Compiler Coding Rule 42. (M impact, H generality) inc and
    2. dec instructions should be replaced with an add or sub instruction, because
    3. add and sub overwrite all flags, whereas inc and dec do not, therefore
    4. creating false dependencies on earlier instructions that set the flags.


    ну и плюс к этому на норсвуде and\sub пол такта, а inc\dec 1 такт.
     
  10. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    semen

    Мда...
    Код (Text):
    1. for(int i=0;i<10;i++)
    2.   {
    3.     MessageBoxA(0,0,0,0);
    4.     MessageBoxW(0,0,0,0);
    5.     MessageBeep(0);
    6.     GetMessage(0,0,0,0);
    7.   }


    Тут он уже счетчик положил в стек. И кстати начало цикла не выравнено. И что самое интересное - в начале и в конце push / pop ecx, но ecx нигде не юзается?..
    Код (Text):
    1. .00401000:  push        ecx
    2. .00401001:  push        ebx
    3. .00401002:  mov         ebx,MessageBeep ;USER32
    4. .00401008:  push        ebp
    5. .00401009:  mov         ebp,GetMessageA ;USER32
    6. .0040100F:  push        esi
    7. .00401010:  mov         esi,MessageBoxA ;USER32
    8. .00401016:  push        edi
    9. .00401017:  mov         edi,MessageBoxW ;USER32
    10. .0040101D:  mov         d,[esp][10],00000000A  ---↑ (1)
    11. .00401025:  push        000
    12. .00401027:  push        000
    13. .00401029:  push        000
    14. .0040102B:  push        000
    15. .0040102D:  call        esi
    16. .0040102F:  push        000
    17. .00401031:  push        000
    18. .00401033:  push        000
    19. .00401035:  push        000
    20. .00401037:  call        edi
    21. .00401039:  push        000
    22. .0040103B:  call        ebx
    23. .0040103D:  push        000
    24. .0040103F:  push        000
    25. .00401041:  push        000
    26. .00401043:  push        000
    27. .00401045:  call        ebp
    28. .00401047:  sub         d,[esp][10],000000001 ;"☺"
    29. .0040104C:  jne        .000401025  ---↑ (2)
    30. .0040104E:  pop         edi
    31. .0040104F:  pop         esi
    32. .00401050:  pop         ebp
    33. .00401051:  xor         eax,eax
    34. .00401053:  pop         ebx
    35. .00401054:  pop         ecx
    36. .00401055:  retn        00010 ;" ►"
     
  11. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_

    Ну тут пускай кто-нибудь компетентнее меня отвечает... Непортящиеся регистры видимо закончились и что делать с референсом к памяти пофиг, а с выравниванием - видимо линкер поставит main так, что цикл станет выровненным.
     
  12. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан




    Не понял?... Это каким образом?...
     
  13. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_

    Уже проверил, что это не так, но ведь возможно сам main подвинуть так, что цикл станет выровненным - короче хз что с выравниванием - нет его, может она более 8 нопов не делает, хз вобщем - не знаю я, скорее всего trade-off какой-то, но глюков компилятора на этих примерах я не вижу.
     
  14. Sickle

    Sickle New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2003
    Сообщения:
    181
    в начале и в конце push / pop ecx, но ecx нигде не юзается?..



    в блоке присутствует вызов API а он не обязан сохранять ecx - поэтому компилятор и вставил push/pop
     
  15. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    semen





    Возможно, но так ведь он не подвинул :derisive:



    Вобще довольно странный код этот msvc иногда генерит...
     
  16. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Sickle







    Ай здорово как :) Осталось только понять, нафига это надо - это вся прога, а не какой-то фрагмент. Можно подумать кернел упадет при закрытии процесса, если ecx не сохранить.
     
  17. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_





    Да не - на этих примерах самый что ни на есть нормальный, а вот здесь я действительно ляпы собирал http://wasm.ru/forum/index.php?action=vthread&forum=7&topic=9416&page=0 - больше пока не нашел.
     
  18. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_





    Что ты так все быстро решаешь - ecx мог crt понадобиться - main этож не entry point прикладухи. Она вообще без компиляции crt c WPO не может понять что ecx crt не нужен.
     
  19. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    semen



    Пожалуста - отрубаю crt, картина та же.
     
  20. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    _DEN_

    Ну и что? Показатель будет, если она сохранит не нужный регистр во вложенной в main функции, причем со включенным WPO.