Как получается, что троичный не скомпилирован в ту же сборку, как если бы? - PullRequest
0 голосов
/ 29 мая 2018

У меня есть два файла:

int PolyMod(int s);
void CreateChecksum(int isTestNet, int *mod) {
    *mod = PolyMod(isTestNet == 0 ? 5 : 9);
}

и

int PolyMod(int s);
void CreateChecksum(int isTestNet, int *mod) {
    if (isTestNet == 0) {
        *mod = PolyMod(5);
    } else {
        *mod = PolyMod(9);
    }
}

Каким-то образом результат их сборки отличается.Зачем?Вы можете увидеть сборку, созданную из первого файла здесь и из второго файла здесь .

Разве компилятор не знает, что они эквивалентны, и одинбыстрее?Была ли причина, по которой у них были разные сборки, заключалась в том, что они были одинаково быстрыми, и единственное различие между ними было в порядке операций?

Я задавался вопросом, было ли различие вызвано статическим предсказанием ветвления.После экспериментов с __builtin_expect я считаю, что ответ - нет.

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Похоже, что проблема заключается в ошибке пропущенной оптимизации , вызванной GIMPLE в GCC.У Clang нет этой ошибки, поэтому он генерирует ту же сборку.

Я сообщил об этом в GCC;ошибку можно отследить здесь: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85971

0 голосов
/ 29 мая 2018

C не накладывает никаких ограничений на то, какие инструкции генерировать в аппаратных средствах.

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

Компилятор преобразует код C во многие промежуточные языки (комбинаторы, rtl, ssa, generic, gimple и т. д. и т. д.), в частности в RTL, и оттуда генерируется аппаратно-зависимыйcode.

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

...