jcxz 245 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 8 минут назад, __inline__ сказал: Ну и то же руководство по сборке gentoo linux, не рекомендует собирать его с опциями выше, чем -O2. Потому что разработчики ядра не гарантируют работоспособность ядра на -O3 и -Ofast. Выходит, по-вашему, ядро тоже бажное? Конечно. Извините, но "разработчики некоего ядра" для меня не являются неоспоримыми авторитетами в последней инстанции. Неоспоримым доказательством наличия бага компилятора является только приведение конкретного примера кода и листинга его компиляции. Цитата Но есть тенденция, что у GCC больше шансов сделать код рабочим на -O3 или fast, чем у IAR. Код, который компилится в работоспособный только с некоторыми шансами, уже по определению - кривой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 6 7 июня, 2020 Опубликовано 7 июня, 2020 (изменено) · Жалоба 5 minutes ago, __inline__ said: Прямо всех? С -Wall и pedantic + Werror ? Да. Wall, Wextra, pedantic. Werror мне не нужен, поскольку 0 предупреждений, это 0 предупреждений. 7 minutes ago, jcxz said: А на каком ядре HF "не может быть по определению"? Полагаю, имелось в виду, что выравнивания не может быть по определению. Как раз сейчас верифицирую такое ядро. Изменено 7 июня, 2020 пользователем one_eight_seven Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 6 минут назад, one_eight_seven сказал: В Linux есть и другое объяснение, я не собирал Gentoo, я больше по RedHat'ам, но там объяснение такое, что -O2 выбрано из-за того, что -O3, -Ofast используют агрессивный инлайнинг и это увеличивает cache footprint приложений, что резко негативно сказывается на производительности. С этим согласен. Сам такое наблюдал не раз в листингах: на максимальной оптимизации по скорости, компиляторы иногда делают такое, что код становится более тормозным, чем на средней оптимизации. Но при этом он остаётся рабочим. Хотя при некоторый ключах оптимизации (особенно - по размеру), может сильно увеличиваться глубина использования стека, что в программе может привести к ошибке переполнения стека. PS: Да и оптимизация по скорости может приводить к сильному раздуванию использования стека. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 13 минут назад, jcxz сказал: А на каком ядре HF "не может быть по определению"? Да может, конечно, если уж к буквам придираться. Но ожидать, что компилятор от разработчиков ядра устроит HardFault у Cortex-M4 вот на таком коде при операции чтения из памяти... void WriteFIFO(uint8_t *src) { uit32_t *fifo = CONST; *fifo = *(uint32_t *)src; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 29 минут назад, VladislavS сказал: Да может, конечно, если уж к буквам придираться. Но ожидать, что компилятор от разработчиков ядра устроит HardFault у Cortex-M4 вот на таком коде при операции чтения из памяти... void WriteFIFO(uint8_t *src) { uit32_t *fifo = CONST; *fifo = *(uint32_t *)src; } Ну так код то кривой. Разве не видите сами? Компилятор вправе устроить HF на таком. Бага компилятора нет. PS: Я в таких случаях пишу так: *fifo = *(u32p8 *)src; набор пакованных типов uXXpYY у меня описан: typedef __packed u16 u16p8; typedef __packed s16 s16p8; typedef __packed u32 u32p8; typedef __packed s32 s32p8; typedef __packed u64 u64p8; typedef __packed s64 s64p8; И тогда компилятор использует только инструкции LDR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба Чего это он кривой? СПЕЦИАЛЬНО произведено чтение 32-битного слова по невыровненному адресу. Cortex-M4 это позволяет делать. Почему компилятор от разработчиков ядра выбрал неподходящую для этого инструкцию? *src + (*(src+1)<<8) + (*(src+2)<<16) + (*(src+3)<<24); Вот такую операцию он тоже оптимизирует до одного 32-битного чтения, но использует уже правильную инструкцию. То есть, компилятор знает, что на этом ядре так можно. Но пользуется этим знанием как-то странно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 9 minutes ago, jcxz said: Ну так код то кривой. Разве не видите сами? Компилятор вправе устроить HF на таком. Бага компилятора нет. PS: Я в таких случаях пишу так: *fifo = *(u32p8 *)src; набор пакованных типов uXXpYY у меня описан: Это уже слишком нагло со стороны компилятора. Есть соглашение, что переменные должны быть выравнены на 4 байта в режиме ARM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба Только что, __inline__ сказал: Это уже слишком нагло со стороны компилятора. Есть соглашение, что переменные должны быть выравнены на 4 байта в режиме ARM. 8-разрядные??? Это где такое написано? И при чём тут переменные и их выравнивание? Вы посмотрите откуда берётся s - где там какая-то переменная? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 6 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба Just now, __inline__ said: Это уже слишком нагло со стороны компилятора. Есть соглашение, что переменные должны быть выравнены на 4 байта в режиме ARM. Там у вас проблема не в переменной, а в адресе, т.е. значении, которое хранится в переменной. Адрес, по которому вы пытаетесь считать 32-разрядную переменную может быть выровнен по 8 байт. Пример - вы хотите взять второй байт в 32-разрядном слове (интерпретировать его как массив байт [0:3], и обратиться ко второму элементу. Адрес второго элемента не будет выровнен по границе 32 бита. Это аргумент (функции uint8_t * src). И это не должно быть запрещено компилятором. Оно не запрещено. А далее вы по этому адресу берёте не 1 байт, а 4, которые уже должны бы быть выровнены по границе 32 бита, а оно не так (см. предыдущий параграф) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 4 минуты назад, VladislavS сказал: Чего это он кривой? СПЕЦИАЛЬНО произведено чтение 32-битного слова по невыровненному адресу. Cortex-M4 это позволяет делать. Почему компилятор от разработчиков ядра выбрал неподходящую для этого инструкцию? Потому что Вы явно указали компилятору, что адресуете 32-битное значение, которые он по умолчанию считает выровненными (в целях оптимизации). Иначе - надо явно указывать, что значение не выровнено (как у меня или в опциях компилятора). А компилятор вправе выбирать любую инструкцию из доступных в ядре для доступа к значениям известного ему типа. В том числе и STRD/STM/STREX/... - как будет удобнее в целях оптимизации кода. 4 минуты назад, VladislavS сказал: *src + (*(src+1)<<8) + (*(src+2)<<16) + (*(src+3)<<24); Вот такую операцию он тоже оптимизирует до одного 32-битного чтения, но использует уже правильную инструкцию. Это просто случай. Просто в данном конкретном месте оказалось удобнее использовать именно LDR, а не LDM например. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба Адрес src на вход функции подаётся в общем случае невыровненный. По этому адресу читается 4 байта. Если бы это был Cortex-M0 какой-нибудь, то компилятор в несколько присестов как-нибудь собрал прочитал эти байты из памяти. Но тут он видит, что у него Cortex-M4 и можно с понтами сразу 32-битное чтение применить и выбирает неправильную инструкцию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба Только что, VladislavS сказал: Но тут он видит, что у него Cortex-M4 и можно с понтами сразу 32-битное чтение применить и выбирает неправильную инструкцию. Вы бы хоть привели этот "неправильный" листинг во что это скомпилировалось.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 2 минуты назад, jcxz сказал: что адресуете 32-битное значение, которые он по умолчанию считает выровненными (в целях оптимизации) С чего бы это? Кто так умолчал? 32-битное значение легко может быть частью упакованной структуры. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба 9 minutes ago, jcxz said: 8-разрядные??? Это где такое написано? И при чём тут переменные и их выравнивание? Вы посмотрите откуда берётся s - где там какая-то переменная? 22 minutes ago, jcxz said: void WriteFIFO(uint8_t *src) { uit32_t *fifo = CONST; *fifo = *(uint32_t *)src; } Да какая фиг разница? Если это указатель, то он уже обязан быть выровнен на 4 байта как минимум, если он аргумент функции. Для остальных случаев есть packed и всё с ним связанное. То что вы привели, это - костыли для компилятора чтобы избежать случая, описанного VladislavS Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 7 июня, 2020 Опубликовано 7 июня, 2020 · Жалоба Только что, VladislavS сказал: С чего бы это? Кто так умолчал? 32-битное значение легко может быть частью упакованной структуры. Тогда у него должен быть модификатор __packed. А у Вас его нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться