>> Т.е не ясно, почему 1й вариант, а не 2й.
> Там четыре варианта в зависимости от целевого ядра.
> Поиграйтесь флагом -march на https://godbolt.org/z/j9q4oG Так варианты машинного кода не объясняют причину, почему выбрана именно такая. В моём случай "ясно", это когда я найду что-то вроде:
Assembly/Compiler Coding Rule 35. (M impact, ML generality) Use dependency-breaking-idiom
instructions to set a register to 0, or to break a false dependence chain resulting from re-use of
registers. In contexts where the condition codes must be preserved, move 0 into the register instead.
This requires more code space than using XOR and SUB, but avoids setting the condition codes.
>> На массиве нулей. А если данные случайны? На каждом одном слове из
>> 256, то есть 1/256 такта. При этом кеш инструкций расходуется непропорционально.
> Тут "трусы vs крестик".
> Если gcc опросили -Ofast он делает быстрее, если -Os то компактнее.
> При необходимости более оптимального решения нужно использовать PGO, либо разметку функций
> атрибутами fast/cold (кстати, LLVM этого не умеет).
Я, кстати, ошибся, 1 из 256 - это для байта. Для двойного слова выигрыш в среднем 1/0x10000000 тактов - т.е. на случайных данных отсутствует. С другой стороны, может авторы собирали какую-то статистику, когда эти биты подсчитывают (в моём случае - пиксели, а там 0 часто, то есть GCC угадал).
>[оверквотинг удален]
>> в Ваши задачи входит писать быстрый код, потому в конкретных и
>> оптимизированных решениях GCC выигрывает, присваивая себе заслуги автора кода. А вот
>> эта моя поделка https://www.opennet.ru/opennews/art.shtml?num=53778 собранная GCC,
>> выполняется в 2 раза медленнее (согласно и top, и perf). Написал
>> как попало, принципиально не заморачиваясь оптимизацией (ну, только синус табличный),
>> в цикле считаются float-ы, примерно так:
> [...]
>> Причину не искал, потому не могу пока говорить про данный случай предметно.
> Покажите ваш код (в минимально объеме) через https://godbolt.org/
> Будет понятнее что там происходит.
Благодарю за предложение. Правда, не думаю, что кому-то следует заниматься моим кодом, когда я сам отложил вопрос в долгий ящик.)
Листинг той конкретной функции мало что даёт, в первом приближении причина видна из perf report:
18.85% foxhunt_clang foxhunt_clang [.] poly_draw
18.32% foxhunt_clang foxhunt_clang [.] colorer_title 50.06% foxhunt_gcc foxhunt_gcc [.] colorer
9.28% foxhunt_gcc foxhunt_gcc [.] poly_draw
Результат GCC напоминает Clang без LTO:
43.26% foxhunt_clang_n foxhunt_clang_nolto [.] colorer
14.87% foxhunt_clang_n foxhunt_clang_nolto [.] poly_draw
12.63% foxhunt_clang_n foxhunt_clang_nolto [.] colorer_title
Почему GCC не заинлайнил функцию из 5-ти строк, вызываемую из единственного места, загадка. Наверное, я плохо читал документацию по ключам командной строки. А ещё потому-что функция вызывается по указателю. То есть простое и очевидное для меня решение -- переписать с Си на плюсы, заменив указатели шаблоном и функторами, там не возникают проблемы со встраиванием тела функции (но оно подходит не очень, исполняемый файл после GCC и так большой, когда желательно уложиться в 64КБ).