Оцениваются ли константные операции во время выполнения?
Я занимаюсь шахматным программированием на C++, в результате я получаю много побитовых операций с большими числами. Мне было интересно, ради производительности, если постоянные операции выполняются во время выполнения? Или если они оценены во время компиляции. Например, предположим, что я должен И следующие 2 константы:
const unsigned long long FILE_A = ~0x8080808080808080;
const unsigned long long FILE_B = ~0x4040404040404040;
В такой функции
unsigned long long join(){
return (FILE_A & FILE_B);
}
Операция AND для FILE_A и FILE_B выполняется во время выполнения? Или компилятор это делает?
2 ответа
В целом: компилятору C++ разрешено выполнять любую оптимизацию, если результат оптимизации "как будто", код был выполнен буквально.
В приведенном вами примере выполнение данного вычисления во время компиляции неотличимо от выполнения во время выполнения; поэтому современные компиляторы C++ будут делать именно это. На самом деле, современные компиляторы C++, если join()
определяется в заголовочном файле (с inline
атрибут) - и если выбран умеренный уровень оптимизации - будет не только производить вычисления во время компиляции, но и полностью оптимизировать join()
прочь, и вставьте вычисленную константу прямо куда угодно join()
привыкает, делая возможной дополнительную оптимизацию во время компиляции. Это потому, что результат был бы неотличим от результата, если бы ничего не было оптимизировано.
Судя по всему, это так. Я положил свой код, приведенный выше в этом конвертере https://assembly.ynh.io/ и для строки return (FILE_A & FILE_B);
выводит следующую сборку
movabsq $4557430888798830399, %rax
И да, 4557430888798830399 является побитовым и (~0x8080808080808080)
а также (~0x4040404040404040)