- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
#include <stddef.h>
__attribute__((const)) int f(int a);
void conv(int *restrict in, int *restrict out, size_t sz)
{
for(size_t i = 0; i < sz-1; i++)
{
out[i] = f(in[i])+f(in[i+1]);
}
return;
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
0
#include <stddef.h>
__attribute__((const)) int f(int a);
void conv(int *restrict in, int *restrict out, size_t sz)
{
for(size_t i = 0; i < sz-1; i++)
{
out[i] = f(in[i])+f(in[i+1]);
}
return;
}
Пример, на котором обделывается оптимизатор Clang но не обделывается оптимизатор GCC
https://godbolt.org/z/W9WshxsKG
Как тут можно заметить, компилятор внутри цикла делает лишь один вызов функции "f". Хотя тут мелкие косяки тоже есть, например в конце почему-то две инструкции "ret" непонятно нахуй нужные
Тут же так получается, что Clang в цикле вызывает функцию "f" два раза, хотя можно переиспользовать ее значение из предыдущей итерации цикта т.к. там __attribute__((const))
https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html
const
This attribute applies to functions.
Calls to functions whose return value is not affected by changes to the observable state of the program and that have no observable effects on such state other than to return a value may lend themselves to optimizations such as common subexpression elimination. Declaring such functions with the const attribute allows GCC to avoid emitting some calls in repeated invocations of the function with the same argument values.
Кстати, а надо как-то компилятору доказывать, что она чиста?
Если я петух проткнутый, и помечу атрибутом const функцию, которая читает IO, то я сам себе буратино?
Хотя конечно оптимиизация достойная Кнута: если я не ветке N вызываю f(N-1) то вероятно у меня она осталась с прошлого вызова, а инта прикопать -- не велика беда
Хитро!
Нет, но вообще говоря он их понимает и делает на основе них некоторые оптимзизации
Такую функцию компилятор clang и gcc вызовет лишь единожды и результат удвоит. Если же без атрибута const, оно честно вызывает функцию два раза.
> Кстати, а надо как-то компилятору доказывать, что она чиста?
Нет. Компилятор может сам себе иногда доказать, что функция чистая, но это надо или чтоб она была в одной единице трансляции, или чтоб какие-то (LTO) линк-тайм оптимизации были врублены. Если от функции объявлен лишь прототип, и не задействовано никаких LTO, он только на основе этого атрибута что-то там может понять. Кстати, если допустим сделать функцию, которой передаешь указатель, и она чего-то туда пишет строго по этому адресу, но более ничего не меняет, никаких атрибутов для этого уже нет. Контракты в C++26 (которые кстати не прошли утверждение в говнокомитете) этого делать не позволяют, там нельзя сказать "вот этой функции передают указатель на хуйню, и она срет только по тому-то адресу, меняя ровно 4 байтика, и больше никаких побочных эффектов не делает"
> Если я петух проткнутый, и помечу атрибутом const функцию, которая читает IO, то я сам себе буратино?
Да.
Тогда резонить про функции было бы проще.
Например назвать IO "ЗашкварАПИ", и если функция не получает ЗашкварАПИ и не получает ничего мутабельного, то она по определинию чистая: она физически ничего не может поменять в этом мире, и свой результат всегда получает от входных параметров.
Про такую функцию можно вообще таблицу составлять (может даже во время компиляции, если значения удасца посчитать конечно).
Ебать я кажется изобрел функциональные языки.