Почему вы думаете, что это оптимизация?
Почему бы не 2*x
→ x+x
? Или, может быть, операция умножения выполняется так же быстро, как и операция левого сдвига (может быть, только если в множителе установлен только один бит)? Если вы никогда не используете результат, почему бы не исключить его из скомпилированного вывода? Если компилятор уже загрузил 2
в некоторый регистр, возможно, инструкция умножения будет быстрее, например если бы нам сначала нужно было загрузить счетчик смен. Может быть, операция сдвига больше, и ваш внутренний цикл больше не помещается в буфер предварительной выборки ЦП, что снижает производительность? Может быть, компилятор может доказать, что единственный раз, когда вы вызываете вашу функцию x
, будет иметь значение 37 и x*2
может быть заменено на 74
? Может быть, вы делаете 2*x
, где x
- это число циклов (очень распространенное, хотя и неявное при циклическом выполнении двухбайтовых объектов)? Тогда компилятор может изменить цикл с
for(int x = 0; x < count; ++x) ...2*x...
к эквиваленту (без учета патологий)
int count2 = count * 2
for(int x = 0; x < count2; x += 2) ...x...
, который заменяет count
умножения на одно умножение, или он может использовать команду lea
, которая объединяет умножение с чтением из памяти.
Моя точка зрения : миллионы факторов решают, даст ли замена x*2
на x<<1
более быстрый двоичный файл. Оптимизирующий компилятор попытается сгенерировать самый быстрый код для данной программы, а не для изолированной операции. Поэтому результаты оптимизации для одного и того же кода могут в значительной степени различаться в зависимости от окружающего кода, и они могут быть совсем не тривиальными.
Как правило, очень мало тестов, которые показывают большие различия между компиляторами. Поэтому вполне справедливо предположить, что компиляторы делают хорошую работу, потому что если бы остались дешевые оптимизации, по крайней мере, один из компиляторов реализовал бы их - а все остальные последовали бы в следующем выпуске.