На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Модераторы: ANDLL, ALXR
Страницы: (5) « Первая ... 2 3 [4] 5  все  ( Перейти к последнему сообщению )  
> == 0 ИЛИ !, C++
   
== 0 ИЛИ !
Гости не могут просматривать результаты голосования.
Гости не могут голосовать 
    applegame, а стоило ли рассчитывать, что эти варианты будут различаться? :)

    Вот так надо:
    ExpandedWrap disabled
      for(;x;) return false; return true;
    :D

    Добавлено
    Цитата Славян @
    Но это лишь говорит о том, что оптимизатор понял, что test (делает AND по сути ) быстрее довольно туповатого и прямого CMP!
    Это лишь говорит о том, что test короче, чем cmp. Скорость работы та же :)
    Потому что будет cmp edi,0 (3 байта), а не cmp edi,edi (2 байта, как и test edi,edi).

    Добавлено
    При этом test edi,edi можно с тем же успехом заменить на and edi,edi или на or edi,edi.
    Размер тот же, скорость та же.

    Добавлено
    У меня сейчас комп не пашет (загрузился с флешки). Кто может скомпилить и прислать дизасм такого кода (для 32-х бит)?
    ExpandedWrap disabled
      return (!x || x==0x80000000);
    Любопытно, как это оптимизируется.
    Я поаплодирую, если там будет написано так:
    ExpandedWrap disabled
      add edi,edi
      sete al
    (ну там вместо edi может быть что-то другое, разумеется)

    Добавлено
    Можно ещё так попробовать:
    ExpandedWrap disabled
      return !(x&0x7FFFFFFF);
    vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
      ExpandedWrap disabled
        int foo(int x)
        {
          return (!x || x==0x80000000);
        }
         
        int bar(int x)
        {
          return !(x&0x7FFFFFFF);
        }
      По скорости. VC2015:
      ExpandedWrap disabled
        _TEXT   SEGMENT
        _x$ = 8                                                 ; size = 4
        _bar    PROC                                            ; COMDAT
        ; File c:\disk_f\work\100olymp\q.c
        ; Line 8
                mov     eax, DWORD PTR _x$[esp-4]
                and     eax, 2147483647                         ; 7fffffffH
                neg     eax
                sbb     eax, eax
                inc     eax
        ; Line 9
                ret     0
        _bar    ENDP
        _TEXT   ENDS
        ; Function compile flags: /Ogtpy
        ;       COMDAT _foo
        _TEXT   SEGMENT
        _x$ = 8                                                 ; size = 4
        _foo    PROC                                            ; COMDAT
        ; File c:\disk_f\work\100olymp\q.c
        ; Line 3
                mov     eax, DWORD PTR _x$[esp-4]
                test    eax, eax
                je      SHORT $LN3@foo
                cmp     eax, -2147483648                        ; 80000000H
                je      SHORT $LN3@foo
                xor     eax, eax
        ; Line 4
                ret     0
        $LN3@foo:
        ; Line 3
                mov     eax, 1
        ; Line 4
                ret     0
        _foo    ENDP
        _TEXT   ENDS
      ICL2016:
      ExpandedWrap disabled
        _TEXT   SEGMENT  PARA PUBLIC FLAT  'CODE'
               ALIGN     16
                PUBLIC _foo
        ; --- foo(int)
        _foo    PROC NEAR
        ; parameter 1: 4 + esp
        .B1.1:                          ; Preds .B1.0
        L1::
                                                                   ;2.1
                mov       eax, DWORD PTR [4+esp]                        ;1.5
                test      eax, eax                                      ;3.12
                je        .B1.3         ; Prob 50%                      ;3.12
                                        ; LOE eax ebx ebp esi edi
        .B1.2:                          ; Preds .B1.1
                cmp       eax, -2147483648                              ;3.20
                jne       .B1.4         ; Prob 50%                      ;3.20
                                        ; LOE ebx ebp esi edi
        .B1.3:                          ; Preds .B1.2 .B1.1
                mov       eax, 1                                        ;3.12
                ret                                                     ;3.12
                                        ; LOE eax ebx ebp esi edi
        .B1.4:                          ; Preds .B1.2
                xor       eax, eax                                      ;3.12
                                        ; LOE eax ebx ebp esi edi
        .B1.5:                          ; Preds .B1.4
                ret                                                     ;3.12
                ALIGN     16
                                        ; LOE
        ; mark_end;
        _foo ENDP
               ALIGN     16
                PUBLIC _bar
        ; --- bar(int)
        _bar    PROC NEAR
        ; parameter 1: 4 + esp
        .B2.1:                          ; Preds .B2.0
        L2::
                                                                   ;7.1
                xor       eax, eax                                      ;8.14
                mov       edx, 1                                        ;8.14
                test      DWORD PTR [4+esp], 2147483647                 ;8.14
                cmove     eax, edx                                      ;8.14
                ret                                                     ;8.14
                ALIGN     16
                                        ; LOE
        ; mark_end;
        _bar ENDP
        ;_bar   ENDS
        _TEXT   ENDS
      По размеру. VC2015:
      ExpandedWrap disabled
        PUBLIC  _foo
        PUBLIC  _bar
        ; Function compile flags: /Ogspy
        ;       COMDAT _bar
        _TEXT   SEGMENT
        _x$ = 8                                                 ; size = 4
        _bar    PROC                                            ; COMDAT
        ; File c:\disk_f\work\100olymp\q.c
        ; Line 8
                mov     eax, DWORD PTR _x$[esp-4]
                and     eax, 2147483647                         ; 7fffffffH
                neg     eax
                sbb     eax, eax
                inc     eax
        ; Line 9
                ret     0
        _bar    ENDP
        _TEXT   ENDS
        ; Function compile flags: /Ogspy
        ;       COMDAT _foo
        _TEXT   SEGMENT
        _x$ = 8                                                 ; size = 4
        _foo    PROC                                            ; COMDAT
        ; File c:\disk_f\work\100olymp\q.c
        ; Line 3
                cmp     DWORD PTR _x$[esp-4], 0
                je      SHORT $LN3@foo
                cmp     DWORD PTR _x$[esp-4], -2147483648       ; 80000000H
                je      SHORT $LN3@foo
                xor     eax, eax
        ; Line 4
                ret     0
        $LN3@foo:
        ; Line 3
                xor     eax, eax
                inc     eax
        ; Line 4
                ret     0
        _foo    ENDP
        _TEXT   ENDS
      ICL2016:
      ExpandedWrap disabled
        _TEXT   SEGMENT  DWORD PUBLIC FLAT  'CODE'
                PUBLIC _foo
        ; --- foo(int)
        _foo    PROC NEAR
        ; parameter 1: 4 + esp
        .B1.1:                          ; Preds .B1.0
        L1::
                                                                   ;2.1
                mov       eax, DWORD PTR [4+esp]                        ;1.5
                test      eax, eax                                      ;3.12
                je        .B1.3         ; Prob 50%                      ;3.12
                                        ; LOE eax ebx ebp esi edi
        .B1.2:                          ; Preds .B1.1
                cmp       eax, -2147483648                              ;3.20
                jne       .B1.4         ; Prob 50%                      ;3.20
                                        ; LOE ebx ebp esi edi
        .B1.3:                          ; Preds .B1.2 .B1.1
                push      1                                             ;3.12
                pop       eax                                           ;3.12
                ret                                                     ;3.12
                                        ; LOE eax ebx ebp esi edi
        .B1.4:                          ; Preds .B1.2
                xor       eax, eax                                      ;3.12
                                        ; LOE eax ebx ebp esi edi
        .B1.5:                          ; Preds .B1.4
                ret                                                     ;3.12
                                        ; LOE
        ; mark_end;
        _foo ENDP
                PUBLIC _bar
        ; --- bar(int)
        _bar    PROC NEAR
        ; parameter 1: 4 + esp
        .B2.1:                          ; Preds .B2.0
        L2::
                                                                   ;7.1
                xor       eax, eax                                      ;8.14
                test      DWORD PTR [4+esp], 2147483647                 ;8.14
                sete      al                                            ;8.14
                ret                                                     ;8.14
                                        ; LOE
        ; mark_end;
        _bar ENDP
        ;_bar   ENDS
        _TEXT   ENDS
      64 бита приводить?
      Сообщение отредактировано: Qraizer -
      Одни с годами умнеют, другие становятся старше.
        Цитата Qraizer @
        64 бита приводить?
        Не надо, спасибо.

        Цитата Qraizer @
                test      DWORD PTR [4+esp], 2147483647                 ;8.14
                sete      al  
        Вот это уже нормально :good:

        Но Intel что-то гонит. Оптимизация по размеру (приведённый чуть выше код) должна быть быстрее, ибо cmovcc медленнее, чем setcc.

        Интересен вариант с icl в случае, если x будет не в стеке, а в регистре...
        vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
          Медленнее, на такт. Но она может быть спараллелена посредством задействования обоих значений результата, тогда как setcc не может.

          Добавлено
          Цитата Jin X @
          Интересен вариант с icl в случае, если x будет не в стеке, а в регистре...
          Ок, fastcall. По скорости:
          ExpandedWrap disabled
            _TEXT   SEGMENT  PARA PUBLIC FLAT  'CODE'
                   ALIGN     16
                    PUBLIC @foo@4
            ; --- foo(int)
            @foo@4  PROC NEAR
            ; parameter 1: ecx
            .B1.1:                          ; Preds .B1.0
            L1::
                                                                       ;2.1
                    test      ecx, ecx                                      ;3.12
                    je        .B1.3         ; Prob 50%                      ;3.12
                                            ; LOE ecx ebx ebp esi edi
            .B1.2:                          ; Preds .B1.1
                    cmp       ecx, -2147483648                              ;3.20
                    jne       .B1.4         ; Prob 50%                      ;3.20
                                            ; LOE ebx ebp esi edi
            .B1.3:                          ; Preds .B1.2 .B1.1
                    mov       eax, 1                                        ;3.12
                    ret                                                     ;3.12
                                            ; LOE eax ebx ebp esi edi
            .B1.4:                          ; Preds .B1.2
                    xor       eax, eax                                      ;3.12
                                            ; LOE eax ebx ebp esi edi
            .B1.5:                          ; Preds .B1.4
                    ret                                                     ;3.12
                    ALIGN     16
                                            ; LOE
            ; mark_end;
            @foo@4 ENDP
                   ALIGN     16
                    PUBLIC @bar@4
            ; --- bar(int)
            @bar@4  PROC NEAR
            ; parameter 1: ecx
            .B2.1:                          ; Preds .B2.0
            L2::
                                                                       ;7.1
                    xor       eax, eax                                      ;8.14
                    mov       edx, 1                                        ;8.14
                    test      ecx, 2147483647                               ;8.14
                    cmove     eax, edx                                      ;8.14
                    ret                                                     ;8.14
                    ALIGN     16
                                            ; LOE
            ; mark_end;
            @bar@4 ENDP
            ;@bar@4 ENDS
            _TEXT   ENDS
          По размеру:
          ExpandedWrap disabled
            _TEXT   SEGMENT  DWORD PUBLIC FLAT  'CODE'
                    PUBLIC @foo@4
            ; --- foo(int)
            @foo@4  PROC NEAR
            ; parameter 1: ecx
            .B1.1:                          ; Preds .B1.0
            L1::
                                                                       ;2.1
                    test      ecx, ecx                                      ;3.12
                    je        .B1.3         ; Prob 50%                      ;3.12
                                            ; LOE ecx ebx ebp esi edi
            .B1.2:                          ; Preds .B1.1
                    cmp       ecx, -2147483648                              ;3.20
                    jne       .B1.4         ; Prob 50%                      ;3.20
                                            ; LOE ebx ebp esi edi
            .B1.3:                          ; Preds .B1.2 .B1.1
                    push      1                                             ;3.12
                    pop       eax                                           ;3.12
                    ret                                                     ;3.12
                                            ; LOE eax ebx ebp esi edi
            .B1.4:                          ; Preds .B1.2
                    xor       eax, eax                                      ;3.12
                                            ; LOE eax ebx ebp esi edi
            .B1.5:                          ; Preds .B1.4
                    ret                                                     ;3.12
                                            ; LOE
            ; mark_end;
            @foo@4 ENDP
                    PUBLIC @bar@4
            ; --- bar(int)
            @bar@4  PROC NEAR
            ; parameter 1: ecx
            .B2.1:                          ; Preds .B2.0
            L2::
                                                                       ;7.1
                    test      ecx, 2147483647                               ;8.14
                    push      0                                             ;8.14
                    pop       eax                                           ;8.14
                    sete      al                                            ;8.14
                    ret                                                     ;8.14
                                            ; LOE
            ; mark_end;
            @bar@4 ENDP
            ;@bar@4 ENDS
            _TEXT   ENDS
          Одни с годами умнеют, другие становятся старше.
            Qraizer, с чем она может быть спараллелена, когда её работа зависит от результата предыдущей операции (всех 3-х предыдущих инструкций, я даже скажу)?

            gcc, кстати, срабатывает как xor+test+sete (xor+and+sete для регистра) при оптимизации по скорости для обоих вариантов кода.
            А вот просто !x или x==0 он компилит аж в:
            ExpandedWrap disabled
              mov edx,[esp+4]
              xor eax,eax
              test edx,edx
              sete al


            Добавлено
            Цитата Qraizer @
                    push      1
                    pop       eax  
            Жесть какая!
            Тогда бы уж сделали
            ExpandedWrap disabled
              xor eax,eax
              inc eax
            Размер тот же, но хоть быстрее должно быть...

            Добавлено
            Цитата Jin X @
            xor+test+sete
            Зачем тут xor eax,eax, когда я объявляю тип функции bool? Он же байтовый!
            Сообщение отредактировано: Jin X -
            vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
              Цитата Jin X @
              с чем она может быть спараллелена, когда её работа зависит от результата предыдущей операции
              С последующими действиями. Может использоваться либо eax, либо edx, но какой именно, станет известно лишь позднее. Временно можно использовать два потока исполнения, один из которых будет впоследствии отброшен, а второй, использующий "правильный" risc-регистр, переотображён на eax. То же можно сделать с setcc, также задействуя два risc-регистра, однако тут больше сложностей с подготовкой значения для второго. В отличие от cmovcc, где оба значения уже подготовлены и лежат в регистрах, для setcc значения 0 и 1, причём чётко байтовые, нужно подготавливать явно. Вероятно, по этой причине микрокод для них может отличаться.

              Добавлено
              Цитата Jin X @
              Жесть какая!
              Соседние push/pop не имеют штрафов по зависимостям. Они спецом для этого оптимизированы. Пара xor/inс зависит от ALU

              Добавлено
              Цитата Jin X @
              Зачем тут xor eax,eax, когда я объявляю тип функции bool? Он же байтовый!
              Ну я же привёл прототипы. Там int. Если хочешь C++, где есть честный bool, то это будут другие прототипы.

              Добавлено
              Проверил на intel, никакой разницы. Он всегда предпочитает работать с полноразмерными регистрами, ибо так куда эффективнее работает микрокод. (Вообще, даже самые древние мануалы советуют никогда не смешивать разноразмерные данные в зависимых инструкциях.) А вот visual немного удивил:
              ExpandedWrap disabled
                _TEXT   SEGMENT
                ?bar@@YI_NH@Z PROC                                      ; bar, COMDAT
                ; _x$ = ecx
                ; File c:\users\shmatko\documents\intel\документация\qq.cpp
                ; Line 8
                        test    ecx, 2147483647                         ; 7fffffffH
                        sete    al
                ; Line 9
                        ret     0
                ?bar@@YI_NH@Z ENDP                                      ; bar
                _TEXT   ENDS
                ; Function compile flags: /Ogtpy
                ;       COMDAT ?foo@@YI_NH@Z
                _TEXT   SEGMENT
                ?foo@@YI_NH@Z PROC                                      ; foo, COMDAT
                ; _x$ = ecx
                ; File c:\users\shmatko\documents\intel\документация\qq.cpp
                ; Line 3
                        test    ecx, ecx
                        je      SHORT $LN3@foo
                        cmp     ecx, -2147483648                        ; 80000000H
                        je      SHORT $LN3@foo
                        xor     al, al
                ; Line 4
                        ret     0
                $LN3@foo:
                ; Line 3
                        mov     al, 1
                ; Line 4
                        ret     0
                ?foo@@YI_NH@Z ENDP                                      ; foo
                _TEXT   ENDS
              Это по скорости.

              Добавлено
              Тока эта... сегодня VC2017.

              Добавлено
              P.S.
              Цитата Qraizer @
              Временно можно использовать два потока исполнения...
              Забыл добавить, что это лишь мои рассуждения, почему такое может иметь место. Как оно на самом деле, без понятия.
              Сообщение отредактировано: Qraizer -
              Одни с годами умнеют, другие становятся старше.
                Цитата Qraizer @
                Соседние push/pop не имеют штрафов по зависимостям.
                Так, дело не в зависимости, а в использовании стека (то бишь памяти, а это время).

                Цитата Qraizer @
                Ну я же привёл прототипы. Там int. Если хочешь C++, где есть честный bool, то это будут другие прототипы.
                Я заменил int на bool и откомпилил gcc, но результат всё равно почему-то пишется в eax.

                Цитата Qraizer @
                Вообще, даже самые древние мануалы советуют никогда не смешивать разноразмерные данные в зависимых инструкциях
                Не спорю (кстати, это может быть причиной использования cmov), просто здесь всё равно используется sete, поэтому xor eax,eax ничего ускорить не должен, по идее...
                Возможно, просто компилер устроен так, что оперирует только полными регистрами. Вот, кстати, надо посмотреть как он будет char возвращать - как байт или дворд. Intel и gcc.
                vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
                  Цитата Jin X @
                  Так, дело не в зависимости, а в использовании стека (то бишь памяти, а это время).
                  Ничего страшного. Ляжет в L1 кэша, ибо вершина стека да в кэш.промахе... когда такое бывало-то, оттуда же прочтётся, а в память запишется в фоне при отбросе кеш.строк, да и то не факт, что не перезапишется к тому времени мульён раз другими данными.
                  Одни с годами умнеют, другие становятся старше.
                    Цитата Qraizer @
                    Ничего страшного. Ляжет в L1 кэша
                    Ляжет, но обращение к кэшу тоже требует времени. Кэш (даже L1) - это же не регистры.
                    vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
                      Так это не отнимет тактов. Ещё в i486 была очередь отложенных записей, которые не тормозили ALU, в отличие от чтений, а, если не ошибаюсь, в P6 появилась фича вытаскивать эти данные прям из очереди, т.е. даже без обращения к L1. Поспрашивай leo, он больше об этом всём знает.
                      Одни с годами умнеют, другие становятся старше.
                        По поводу cmov'ов Агнер пишет так:
                        Цитата
                        The advantage of a conditional move is that it avoids branch mispredictions. But it has the disadvantage that it increases the length of a dependency chain, while a predicted branch breaks the dependency chain. If the code in example 9.9c is part of a dependency chain then the cmov instruction adds to the length of the chain. The latency of cmov is two clock cycles on Intel processors, and one clock cycle on AMD processors.
                        9.9c - это
                        ExpandedWrap disabled
                           ; Example 9.9c. Branch implemented with conditional move
                           mov eax, [b]
                           cmp eax, [c]
                           mov eax, [d]
                           cmovng eax, [e]
                        p.s. Про цепочку зависимостей, в общем-то, оно и так понятно.

                        И вот ещё:
                        Цитата
                        If a conditional jump is used for setting a Boolean variable to 0 or 1 then it is often more efficient to use the conditional set instruction.
                        Здесь он, конечно, сравнивает setcc с jcc, но всё же не про movcc не пишет, а именно про setcc.

                        Цитата Qraizer @
                        в P6 появилась фича вытаскивать эти данные прям из очереди, т.е. даже без обращения к L1
                        Может быть, конечно.
                        Но я могу лишь судить по таблице скоростей и задержек: http://agner.org/optimize/instruction_tables.pdf
                        Ну и мои тесты показывают, что push 1+pop eax работает медленнее, чем xor eax,eax+inc eax, хотя я понимаю, что при других сочетаниях результаты могут быть другими.
                        Но в любом случае вряд ли push/pop будет когда-либо быстрее, чем xor/inc.

                        Добавлено
                        Собственно, хочется понять: это продуманный умысел Intel (и тогда в чём он?) или недочёт (что было бы странно для производителя процессоров)?

                        Добавлено
                        Цитата Qraizer @
                        Поспрашивай leo, он больше об этом всём знает.
                        Я его, пожалуй, приглашу в эту тему :)
                        vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
                          Цитата Jin X @
                          Собственно, хочется понять: это продуманный умысел Intel (и тогда в чём он?) или недочёт (что было бы странно для производителя процессоров)?
                          Думаю, никаких теорий заговоров. У него просто мало информации. Если использовать эти функции в контексте, да ещё и инлайнить, код может отличаться от голых __fastcall функций разительно.
                          Одни с годами умнеют, другие становятся старше.
                            Цитата Jin X @
                            Ну и мои тесты показывают, что push 1+pop eax работает медленнее, чем xor eax,eax+inc eax, хотя я понимаю, что при других сочетаниях результаты могут быть другими.
                            Но в любом случае вряд ли push/pop будет когда-либо быстрее, чем xor/inc.
                            На AMD, судя по таймингам, одинаково, только комбинация push+pop немного длиннее. на intel push+pop выполняется дольше.
                            А непосредственная засылка единицы в регистр на обоих процессорах будет работать ещё быстрее.
                            Всё написанное выше это всего лишь моё мнение, возможно ошибочное.
                              Я вполне допускаю, что засылка значения быстрее и всё такое, но всё же идеологически вижу это медленнее/неправильнее по таким причинам: засылка значения - это как привоз некими 32-мя фурами издалека значения 0 или 1 (распараллелили), а XOR - это работат тут, на месте, недалёкая=простая в геометрико-транзисторном виде, тоже параллельная 32 раза, - должна быть существенно быстрее! Будет ещё, конечно, INC, но и он ничего извне не просит, а может и тут, на месте, молотить. Так что... :yes-sad:

                              Добавлено
                              Цитата Jin X @
                              При этом test edi,edi можно с тем же успехом заменить на and edi,edi или на or edi,edi.
                              Размер тот же, скорость та же.
                              Это они практически такие же, но идеологически test не меняет регистр, а лишь "проверяет" (and "в уме") биты, посему ДОЛЖЕН быть быстрее. :yes-sad:
                                Цитата amk @
                                посему ДОЛЖЕН быть быстрее.

                                Лично я, чтобы так плотно, на асме не прогал лет 20 точно. Но одно - помню, нет такого понятия "ДОЛЖЕН". Есть документация.
                                Мои программные ништякиhttp://majestio.info
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script Execution time: 0,2377 ]   [ 19 queries used ]   [ Generated: 23.07.19, 23:29 GMT ]