Как проверить, известен ли параметр встроенной функции во время компиляции? - PullRequest
5 голосов
/ 16 февраля 2011

У меня есть встроенная функция, критичная к производительности. Он генерирует некоторые данные на основе параметра. Я хочу, чтобы компилятор оптимизировал генерацию данных для всех вызовов, где параметр известен во время компиляции. Проблема в том, что я не могу заставить компилятор поместить оптимизированные данные из стека в статическую константу, так как маркировка данных static нарушит случай, когда параметр не является постоянной времени компиляции. Наличие постоянных данных в стеке снижает производительность. Есть ли способ сделать вывод (возможно, с помощью templates / boost :: enable_if), что параметр является константой времени компиляции, и выбрать подходящую реализацию для генерации данных?

ПОЯСНЕНИЯ

В основном у меня есть что-то вроде следующего:

struct Data {
     int d_[16];
};

inline Data fun(int param)
{  //param can sometimes be a compile-time constant

    ... //generate the data
    Data res = {gen0, gen2, gen3, ..., gen15}; //put the data into result
    return res;
}

Так что, когда param не является постоянной времени компиляции, мы просто генерируем все данные и возвращаем.
Когда известно param, компилятор может оптимизировать генерацию данных. Но затем он не может оптимизировать следующую строку и генерирует много кода, который просто устанавливает res членов для известных данных (данные внедряются в программный код). Я хочу, чтобы компилятор создал статическую константу, а затем скопировал ее в возвращаемый объект (это быстрее, чем выполнение большого количества кода со встроенными данными). Поскольку это встроенная функция, даже копирование может не потребоваться.

Отказ

Этот вопрос отличается от Как использовать различную перегрузку встроенной функции в зависимости от параметра времени компиляции? . Это более общая проблема.

Ответы [ 5 ]

2 голосов
/ 17 февраля 2011

Вы действительно профилировали свой код и доказали, что передача констант в вашу (встроенную?) Функцию (и) является узким местом?

Если вы выполняли профилирование, то вам придется помочькомпилятор разберется с этим, поскольку нет способа сделать это автоматически.В противном случае вам придется вручную вызывать шаблонную версию функции, если вы знаете постоянную и нормальную версию.

2 голосов
/ 17 февраля 2011

Я не верю, что есть способ сделать это; ответственность за оптимизацию вызовов лежит на компиляторе, а не на языке ... так что нет портативного способа сделать это. : \

1 голос
/ 19 ноября 2012

Это не переносимо, но в GCC и, возможно, в Clang есть функция компилятора __builtin_constant_p.Это позволяет вам спросить компилятор, знает ли он значение переменной во время компиляции.Вы можете использовать его следующим образом:

void f(int arg) {
  if (__builtin_constant_p(arg) && arg == 0) {
    // Handle case where arg is 0 AND known at compile time.
  } else {
    // Generic code.
  }
}

При этом компилятор не будет генерировать код в ветке else, если arg оба известны во время компиляции и равны 0.

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

#ifdef __GNUC__
#  define CONSTANT_P(x) __builtin_constant_p(x)
#else
#  define CONSTANT_P(x) 0
#endif

При необходимости добавьте другие компиляторы, которые поддерживают что-то похожее на это, и теперь вы можете использовать это бездополнительные затраты на компиляторы, которые не поддерживают это.То есть эти компиляторы, если они вообще чего-то стоят, удаляют ветки CONSTANT_P, оставляя только общий код.

1 голос
/ 17 февраля 2011

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

1 голос
/ 17 февраля 2011

Похоже, у вас есть:

template <int N> myfunc_const_N() { /*...*/ }
inline myfunc_var_N(int N);

, и вы хотите иметь возможность набирать myfunc(n); и иметь вызов компилятора myfunc_const_N<n>();, если он действителен, или myfunc_var_N(n);, если нет?

Полагаю, это невозможно, но это сложно доказать.

Но разве это могло бы принести вам много пользы, если бы вы могли?Как часто вы не знаете во время написания кода, является ли данное выражение константой времени компиляции или нет?Почему бы просто не использовать версию шаблона самостоятельно, если у вас есть константа, и версию параметра функции, если у вас ее нет?

...