Оптимизируют ли компиляторы переключатели иначе, чем длинные цепочки if-then-else? - PullRequest
0 голосов
/ 08 ноября 2018

Предположим, у меня есть N различных интегральных значений, известных во время компиляции, от V_1 до V_N. Рассмотрим следующие структуры:

const int x = foo();
switch(x) {
case V_1: { /* commands for V_1 which don't change x */ } break;
case V_2: { /* commands for V_1 which don't change x */ } break;
/* ... */
case V_N: { /* commands for V_1 which don't change x */ } break;
}

против

const int x = foo();
if      (x == V_1) { /* commands for V_1 which don't change x */ }
else if (x == V_2) { /* commands for V_2 which don't change x */ }
else ...
else if (x == V_N) { /* commands for V_N which don't change x */ }

Современные компиляторы C ++ относятся к ним по-разному? То есть они применяют различные потенциальные оптимизации к этим структурам кода? Или они «канонизируют» их для одного и того же, а затем принимают решение об оптимизации (например, следует ли формировать таблицу переходов или нет)?

Примечания:

  • Под современными компиляторами C ++ я подразумеваю в основном последние версии GCC, clang и MSVC. МУС также может иметь значение.
  • Пожалуйста, ответьте относительно максимального уровня оптимизации (-O3 для clang и GCC)
  • ... но тогда, если обработка switch es и if-then-else -цепей одинакова на одних уровнях оптимизации и различна на других, это также интересно.
  • Я предполагаю, что ответ может зависеть от значения N - укажите пороги, если это возможно.

1 Ответ

0 голосов
/ 08 ноября 2018

По иронии судьбы, именно этот тест я выполнил всего пару дней назад для самых последних компиляторов. Как и в случае с последними компиляторами, clang создает одну и ту же сборку для switch и if - для небольшого числа случаев (ниже 5) он производит набор прямых условных переходов, тогда как для 5 или более случаев это делает косвенный скачок таблицы.

С другой стороны, gcc трактует их по-разному: switch преобразует в косвенный переход к таблице, в то время как серия операторов if остается серией условных прямых переходов.

Стоит также отметить, что если в корпусе переключателя есть «дыры» (т. Е. Возможные значения управляющей переменной, которые не указаны в регистре), он все равно может быть преобразован в серию условных прямых переходов или косвенных переходов таблицы. , но я не смог понять точную формулу.

Вот некоторый игровой код: https://gcc.godbolt.org/z/Lll1Kd

...