Многие компиляторы используют подсказки, чтобы выяснить, можно ли повторно использовать результат предыдущего вызова функции. Классический пример:
for (int i=0; i < strlen(str); i++)
Без оптимизации этого сложность этого цикла составляет не менее O (n 2 ), но после оптимизации это может быть O (n).
Подсказки, которые могут взять gcc, clang и многие другие: __attribute__((pure))
и __attribute__((const))
, которые описаны здесь . Например, GNU strlen
объявлен как чистая функция.
GCC может обнаруживать чистые функции и предлагать программисту, какие функции должны быть женаты в чистом виде. Фактически, это происходит автоматически для следующего упрощенного примера:
unsigned my_strlen(const char* str)
{
int i=0;
while (str[i])
++i;
return i;
}
unsigned word_len(const char *str)
{
for (unsigned i=0 ; i < my_strlen(str); ++i) {
if (str[i] == ' ')
return i;
}
return my_strlen(str);
}
Вы можете посмотреть результат компиляции для gcc с -O3 -fno-inline
. Он вызывает my_strlen(str)
только один раз за всю функцию word_len
. Clang 7.0.0, похоже, не выполняет эту оптимизацию.
word_len:
mov rcx, rdi
call my_strlen ; <-- this is the only call (outside any loop)
test eax, eax
je .L7
xor edx, edx
cmp BYTE PTR [rcx], 32
lea rdi, [rdi+1]
jne .L11
jmp .L19
.L12:
add rdi, 1
cmp BYTE PTR [rdi-1], 32
je .L9
.L11:
add edx, 1
cmp eax, edx
jne .L12
.L7:
ret
.L19:
xor edx, edx
.L9:
mov eax, edx
ret