ASM-оптимизации теряются после компиляции? - PullRequest
2 голосов
/ 06 января 2010

Не то чтобы я сейчас в такой ситуации, но мне просто интересен ответ ...

Предполагается, что у вас есть код, написанный на C / C ++, и вы хотите вручную оптимизировать его, изменив его в ASM.

Что произойдет, если вы измените код на C / C ++ и перекомпилируете из исходного кода. Конечно, оптимизация только что скомпилированного файла потеряна. Как избежать необходимости повторной оптимизации каждый раз при компиляции проекта? Вы создаете отдельные исходные файлы для частей, которые должны быть оптимизированы, чтобы сделать его менее сложным? Или есть какой-то автоматический инструмент для этого ...? Думаю, вы не можете использовать diff / patch для этого ...

Пожалуйста, поделитесь своим опытом, спасибо

Ответы [ 7 ]

7 голосов
/ 06 января 2010

Вместо того, чтобы изменять вывод, почему бы вам не переписать критические разделы кода во встроенном ассемблере? Как это сделать, зависит от компиляторов. Проверьте документацию по компиляторам.

В MSVC:

// asm_overview.cpp
// processor: x86
void __declspec(naked) main()
{
    // Naked functions must provide their own prolog...
    __asm {
        push ebp
        mov ebp, esp
        sub esp, __LOCAL_SIZE
    }

    // ... and epilog
    __asm {
        pop ebp
        ret
    }
}

В GCC:

 __asm__ ("movl %eax, %ebx\n\t"
          "movl $56, %esi\n\t"
          "movl %ecx, $label(%edx,%ebx,$4)\n\t"
          "movb %ah, (%ebx)");

Обратите внимание, что внесение изменений в ASM ПОСЛЕ компиляции и оптимизации - это то, что нужно только тем, кто точно знает, что они делают. Компилятор не только оптимизирует структуру так, как это не может сделать человек (по крайней мере, без возможностей калькулятора освещения), он также выполняет гораздо более сложный анализ кода, который мы могли бы когда-либо делать.

Доверьтесь своему компилятору. Это самый лучший инструмент, с которым вы когда-либо работали;).

7 голосов
/ 06 января 2010

Вы пишете некоторые функции в отдельном файле ASM и вызываете эти функции из своего кода C / C ++. Или вы пишете встроенную сборку прямо в коде C / C ++.

Другими словами, вы можете начать с некоторого кода C / C ++, чтобы получить некоторый базовый код ASM, но после того, как вы начнете его настраивать, вы удаляете исходный код C / C ++ и заменяете на ASM код, используя один из этих 2 методов.

4 голосов
/ 06 января 2010

Не изменяйте код сборки, сгенерированный вашим компилятором. Его изменение, как и изменение любого автоматически сгенерированного кода, является очень плохой идеей именно по той причине, которую вы обнаружили сами.

Если есть определенная часть кода, которую вы хотите оптимизировать вручную, внедрив ее в ASM, у вас есть два варианта:

  1. Сначала напишите код в виде кода ASM и свяжите собранный файл ASM с исполняемым файлом. Вы можете сначала позволить компилятору сгенерировать сборку из C / C ++, а затем изменить ее, если это экономит ваше время. Но с этого момента управляйте этим кодом на уровне ASM.
  2. Используйте встроенную сборку в вашем коде C / C ++. Поскольку оптимизированные вручную части кода ASM обычно невелики, часто это лучшая идея. Использование встроенного ASM очень просто в большинстве компиляторов. Ниже приведен простой фрагмент для GCC :

int main(void)
{
        int foo = 10, bar = 15;
        __asm__ __volatile__("addl  %%ebx,%%eax"
                             :"=a"(foo)
                             :"a"(foo), "b"(bar)
                             );
        printf("foo+bar=%d\n", foo);
        return 0;
}

Он демонстрирует, как правильно комбинировать код C с ASM, совместно используя переменные.

3 голосов
/ 06 января 2010

Если ваш компилятор поддерживает это, возможно, вы ищете что-то вроде встроенной сборки ?

2 голосов
/ 06 января 2010

Еще одна веская причина для использования встроенной сборки: встроенная сборка в стиле gcc предоставляет генератору кода кучу информации (clobbers, volatile и т. Д.), Которую генератор кода может использовать, чтобы ваша сборка хорошо вписалась (и встроена!) В вашу. C / C ++ код без потери возможностей для оптимизации.


Edit:

Например, код C из другого ответа:

int main(void)
{
    int foo = 10, bar = 15;
    __asm__ __volatile__("addl  %%ebx,%%eax"
                         :"=a"(foo)
                         :"a"(foo), "b"(bar)
                         );
    printf("foo+bar=%d\n", foo);
    return 0;
}

производит:

....
movl    $15, %ebx
movl    $10, %eax
#APP
addl  %ebx,%eax
#NO_APP
movl    %eax, 8(%esp)
movl    $.str, (%esp)
movl    %eax, 4(%esp)
call    printf
....

Переменные foo и bar хранятся в регистрах и даже никогда не хранятся в стеке.

2 голосов
/ 06 января 2010

Извините, не совсем ответ на ваш вопрос, но я считаю, что люди, делающие компилятор, намного лучше в asm, чем большинство из нас. Таким образом, я бы больше полагался на то, что компилятор делает «правильные вещи», а не на написание некоторого кода asm посреди исходного кода c ++.

Еще один аргумент в пользу того, что я не использую хотя бы встроенный asm (хотя иногда мне нравится вставлять __asm int 3; в код), заключается в том, что компилятор MS Visual Studio не поддерживает встроенный asm для 64-битных сборок.

И последнее: пытались ли вы использовать другой алгоритм оптимизации вместо того, чтобы предполагать, что, скажем, gcc (который может использовать оптимизации SSE_whwhat_is_the_current_version) производит код asm хуже, чем вы можете написать.

1 голос
/ 06 января 2010

Вы либо связываетесь с модулями, явно написанными на ассемблере, либо используете встроенный asm.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...