Если компилятор C знает, что указатель не является псевдонимом, он может выполнить много оптимизаций.Например, если я скомпилирую следующую функцию с помощью gcc -O2
:
int f_noalias(int *arr, int x)
{
int res = 0;
int *p = &arr[17];
*p = x;
res += *p;
res += *p;
return res;
}
, компилятор знает, что чтение *p
всегда будет иметь значение x
, поэтому сгенерированный код эквивалентен тому, который сгенерирован дляследующая функция:
int f_noalias2(int *arr, int x)
{
int *p = &arr[17];
*p = x;
return 2*x;
}
Однако, если компилятор считает, что указатель может быть псевдонимом, он больше не выполняет эту оптимизацию.Например, если мы изменим f
так, чтобы между чтениями была вызвана неизвестная функция *p
, сгенерированный код будет разыменовывать p
дважды.Компилятор предполагает, что функция read_arr
могла бы изменить значение, на которое указывает p
.
int f_withalias(int *arr, int x)
{
int res = 0;
int *p = &arr[17];
*p = x;
res += *p;
read_array(arr);
res += *p;
return res;
}
В моей конкретной программе, когда функция f
выполняет указатель p
, онаhold - единственный, кто пишет в этот элемент массива arr
.Другие функции в коде могут читать из arr
в это время, но не будут писать в него.(Они могут записать другие значения в arr
после того, как f
закончит работу.)
Итак, теперь у меня есть три вопроса:
Первый: Есть ли способ, которым я могу объявитьмои переменные, чтобы дать эту подсказку компилятору C? Я пытался добавить ограничивающую аннотацию к p
, но сгенерированный код в gcc -O2
был идентичен сгенерированному коду для f_withalias
int f_restrict(int *arr, int x)
{
int res = 0;
int * restrict p = &arr[17];
*p = x;
res += *p;
read_array(arr);
res += *p;
return res;
}
Второе: Является ли моя попытка использовать ограничение здесь действительной? Я понимаю, что ограничение означает, что никакие другие указатели не могут иметь псевдоним p как для чтения, так и для записи.Но в моем случае функция read_arr
также может обращаться к массиву arr
, на который указывает p
.
Третий: Если ответ на предыдущий вопрос «нет», могу ли я попробовать что-то другое вместо restrict
?
В основном мне нужноубедитесь, что если я сделаю *p = x
в f
, то эта запись будет немедленно замечена другими функциями, считывающими из arr[17]
.Однако я хочу, чтобы GCC не стеснялся оптимизировать такие вещи, как от x = *p; y = *p
до x = *p; y = x
, даже если между двумя операциями чтения есть вызовы функций.