Подтвердить что ты не робот

Могут ли современные компиляторы оптимизировать операцию x * 2 до x << 1?

Компилятор С++ оптимизирует эту операцию?

Мне хотелось бы верить, что да.

4b9b3361

Ответ 1

Фактически VS2008 оптимизирует это для x + x:

01391000  push        ecx  
    int x = 0;

    scanf("%d", &x);
01391001  lea         eax,[esp] 
01391004  push        eax  
01391005  push        offset string "%d" (13920F4h) 
0139100A  mov         dword ptr [esp+8],0 
01391012  call        dword ptr [__imp__scanf (13920A4h)] 

    int y = x * 2;
01391018  mov         ecx,dword ptr [esp+8] 
0139101C  lea         edx,[ecx+ecx] 

В сборке x64 он еще более явчен и использует:

    int y = x * 2;
000000013FB9101E  mov         edx,dword ptr [x] 

    printf("%d", y);
000000013FB91022  lea         rcx,[string "%d" (13FB921B0h)] 
000000013FB91029  add         edx,edx 

Это будут настройки оптимизации на "Максимизировать скорость" (/O2)

Ответ 2

Эта статья из Раймонда Чена может быть интересной:

Когда x/2 отличается от x → 1?: http://blogs.msdn.com/oldnewthing/archive/2005/05/27/422551.aspx

Цитата: Раймонд:

Конечно, компилятор может распознать это и переписать операцию умножения или сдвига. На самом деле, это очень вероятно, потому что x + x легче получить, чем умножение или сдвиг. Ваш сдвиг или умножение на два, вероятно, будет переписан как нечто более близкое к команде add eax, eax.

     

[...]

     

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

     

(- 1)/2 ≡ 0
     (-1) → 1 ≡ -1

     

[...]

     

Мораль этой истории - написать, что вы имеете в виду. Если вы хотите разделить на два, напишите "/2", а не " → 1".

Мы можем только предположить, что разумно рассказать компилятору, что вы хотите, а не то, что вы хотите от него: Компилятор лучше, чем человек, при оптимизации небольшого масштаба кода (спасибо Daemin чтобы указать на эту тонкую точку): если вы действительно хотите оптимизировать, используйте профилировщик и изучите эффективность своих алгоритмов.

Ответ 3

VS 2008 оптимизировал шахту до x < 1.

    x = x * 2;
004013E7  mov         eax,dword ptr [x] 
004013EA  shl         eax,1 
004013EC  mov         dword ptr [x],eax 

EDIT: это использовало конфигурацию по умолчанию "Отладка" по умолчанию с отключенной оптимизацией (/Od). Используя любой из оптимизационных переключателей (/O1,/O2 (VS "Retail" ), или /Ox ), появляется добавленный код self Rob. Кроме того, только для хорошей меры, я подтвердил, что x = x << 1 действительно рассматривается так же, как x = x * 2 компилятором cl в обоих /Od и/Ox. Итак, в заключение, cl.exe версии 15.00.30729.01 для x86 относится к * 2 и << 1 тождественно, и я ожидаю, что почти все другие компиляторы последнего времени сделают то же самое.

Ответ 4

Нет, если x - это float, это не будет.

Ответ 5

Да. Они также оптимизируют другие подобные операции, такие как умножение на не-силы двух, которые могут быть переписаны как суммы некоторых сдвигов. Они также оптимизируют деления по степеням 2 в правые смены, но будьте осторожны, что при работе со целыми целыми знаками две операции разные! Компилятор должен выпустить несколько дополнительных инструкций для сверления бит, чтобы убедиться, что результаты одинаковы для положительных и отрицательных чисел, но все же быстрее, чем выполнение разделения. Он также аналогично оптимизирует модули по степеням 2.

Ответ 6

Ответ: "если он быстрее" (или меньше). Это зависит от целевой архитектуры, а также от модели использования регистра для данного компилятора. В общем, ответ "да, всегда", так как это очень простая оптимизация глазок, чтобы реализовать и обычно достойная победа.

Ответ 7

Это только начало того, что оптимизаторы могут сделать. Чтобы узнать, что делает ваш компилятор, найдите переключатель, который заставляет его испускать источник ассемблера. Для компиляторов Digital Mars выходной ассемблер может быть проверен с помощью инструмента OBJ2ASM. Если вы хотите узнать, как работает ваш компилятор, то просмотр на выходе ассемблера может быть очень освещающим.

Ответ 8

Я уверен, что все они делают такие оптимизации, но мне интересно, насколько они актуальны. Старые процессоры умножали на сдвиг и добавление, что может занять несколько циклов. С другой стороны, у современных процессоров есть набор баррель-переключателей, которые могут делать все необходимые сдвиги и дополнения одновременно за один такт или меньше. Кто-нибудь на самом деле сравнивает, действительно ли помогают эти оптимизации?

Ответ 9

Да, они будут.

Ответ 10

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

Ответ 11

@Ferruccio Barletta​​p >

Это хороший вопрос. Я отправился в Гуглинг, чтобы попытаться найти ответ.

Я не мог найти ответы на процессоры Intel напрямую, но эта страница имеет тот, кто пытался что-то время. Он показывает, что сдвиги будут более чем в два раза быстрее, чем реклама и умножаются. Бит сдвиги настолько просты (где умножение может быть сдвигом и добавлением), что это имеет смысл.

Итак, я разобрался с AMD и нашел старое руководство по оптимизации для Athlon с 2002 года, в котором перечислены самые быстрые способы умножения чисел на группы от 2 до 32. Интересно, что это зависит от числа. Некоторые из них - реклама, некоторые смены. Это на стр. 122.

Руководство для Athlon 64 показывает то же самое (стр. 164 или около того). Он говорит, что умножения - это 3 (в 32-битных) или 4 (в 64-битных) циклах, где сдвиги равны 1 и добавляются 2.

Кажется, он по-прежнему полезен как оптимизация.

Игнорируя количество циклов, этот метод может помешать вам связать блоки выполнения умножения (возможно), поэтому, если вы делаете много умножений в узком цикле, где некоторые используют константы, а некоторые не используют дополнительное планирование комната может быть полезна.

Но эта спекуляция.

Ответ 12

Это зависит от того, какой у вас компилятор. Например, Visual С++, как известно, плохо оптимизирован. Если вы отредактируете сообщение, чтобы сказать, какой компилятор вы используете, было бы легче ответить.