Arlleex 179 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба Не понятно, что SII не нравится в создании локальной неквалифицированной версии идентификатора, ведь это: а) максимально короткий по тексту в исходнике способ, который не мозолит глаза, ведь в случае с какими-то директивами нужно было бы указывать некий диапазон (т.е. иметь открывающий и закрывающий тэг директивы, что дает куда больше лишнего текста); б) не сует палки в колеса оптимизатору, который будет работать максимально эффективно, если как раз руками не расставлять кускам кода "тут оптимизировать, а тут нет"; в) дает возможность обращаться как к volatile-версии, так и к неквалифицированной локальной копии в тех местах, где это крайне необходимо. А нужно это там, где volatile-переменная используется в режиме read-read-...-modify-write. А еще же ведь бывают ситуации, где в одной операции используется несколько volatile-объектов, и доступ к ним необходимо сериализовать. Там тоже без чтения в локальную копию не обойтись. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SII 0 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 2 часа назад, Arlleex сказал: Не понятно, что SII не нравится в создании локальной неквалифицированной версии идентификатора, ведь это: А ещё это -- загромождение текста лишними объявлениями. Мне не нравится то, что, кроме volatile, нет других атрибутов для переменных, которые могли бы указать, в частности, что данную переменную нельзя выкинуть из программы по желанию компилятора. Если бы был такой атрибут, его пришлось бы указать ровно один раз -- в объявлении самой переменной. Нет и атрибутов для функций, чтобы можно было, скажем, указать, что функция может вызывать побочные эффекты, поэтому нельзя перемещать код до и после вызова этой функции. Ну и т.д. и т.п. 2 часа назад, Arlleex сказал: Там тоже без чтения в локальную копию не обойтись. Да, бывают случаи, когда действительно не обойтись. Однако мне не нравится, что нужно постоянно применять костыли просто из-за того, что в языке отсутствуют средства, которые позволили бы объяснить компилятору, что можно делать, а что нельзя. Как человек выше указал, существуют же барьеры памяти -- так почему нельзя указать, что некая функция является барьером для оптимизации? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 179 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 7 минут назад, SII сказал: Мне не нравится то, что, кроме volatile, нет других атрибутов для переменных, которые могли бы указать, в частности, что данную переменную нельзя выкинуть из программы по желанию компилятора. Компилятор может выкинуть и volatile-объект. А атрибут есть - __attribute__((used)). Цитата Нет и атрибутов для функций, чтобы можно было, скажем, указать, что функция может вызывать побочные эффекты, поэтому нельзя перемещать код до и после вызова этой функции. Это какие, например, побочные эффекты и для чего запрещать перемещение? Так-то для этого есть барьеры оптимизации. Может, Вы о них просто не в курсе? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 16 минут назад, SII сказал: Мне не нравится то, что, кроме volatile, нет других атрибутов для переменных, которые могли бы указать, в частности, что данную переменную нельзя выкинуть из программы по желанию компилятора. Если бы был такой атрибут, его пришлось бы указать ровно один раз -- в объявлении самой переменной. В IAR есть атрибут __root: __root int x; Он указывает компилятору не выбрасывать сам объект (переменную, константу, ...) из программы даже если к нему нет обращений. Но именно только: не выбрасывать сам объект. __root совсем не даёт гарантии от удаления операций работы с переменной, если оптимизатор решил, что скажем x нигде не используется. Если скажем в программе оптимизатор видит только обращения по записи к x, но нет чтений; или наоборот - только чтения, без записи; или есть запись и чтение, но потом считанное никак не используется - в этих случаях с _root сама x останется в памяти, но все обращения к ней могут быть удалены полностью. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SII 0 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 6 минут назад, Arlleex сказал: А атрибут есть - __attribute__((used)) Стандартный? Или конкретного компилятора? В числе стандартных я не находил. 7 минут назад, Arlleex сказал: Это какие, например, побочные эффекты и для чего запрещать перемещение? Ну, выше я указывал проблему с моей функцией Append, добавляющей новый элемент в хвост очереди: inline void FIFO_HDR::Append(FIFO_LNK *Entry) { Entry->Next = nullptr; Last->Next = Entry; Last = Entry; } Когда очередь пуста, поле First заголовка очереди содержит нуль, а поле Last -- адрес поля First. Поле Next всегда является самым первым полем элемента очереди, поэтому такой "трюк" благополучно работает. Собственно, это очень распространённый способ организации очереди, который я встречал миллион раз (в частности, в Винде, но далеко не только в ней). Проблема возникла из-за того, что компилятор не способен увидеть, что вызов Append может поменять поле First заголовка очереди (что происходит, когда перед вызовом очередь пуста), он видит изменение только Last. В моём случае он выполнил предвыборку полей First и Last одной командой LDRD, затем сгенерировал вызов Append, а потом воспользовался предвыбранным, а не обновлённым значением поля First -- что дало неверный результат. Если бы была возможность атрибутировать эту функцию как имеющую побочные эффекты, запрещающие перемещение кода мимо неё, проблема бы не возникала. Конечно, это в какой-то мере ограничило бы оптимизатор, но не слишком сильно, думается. 14 минут назад, Arlleex сказал: Может, Вы о них просто не в курсе? Запросто. Це++ необъятен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 29 минут назад, SII сказал: Как человек выше указал, существуют же барьеры памяти -- так почему нельзя указать, что некая функция является барьером для оптимизации? Так укажите - внесите их внутрь функции. Кто вам мешает? Либо можно функцию обернуть в макрос, в котором перед и после вызова функции поставить барьеры. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SII 0 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 1 минуту назад, jcxz сказал: В IAR есть атрибут __root: __root int x; Он указывает компилятору не выбрасывать сам объект (переменную, константу, ...) из программы даже если к нему нет обращений. Но именно только: не выбрасывать сам объект. __root совсем не даёт гарантии от удаления операций работы с переменной, если оптимизатор решил, что скажем x нигде не используется. Ну, во-первых, он не решает данную проблему, как понимаете. А во-вторых, он специфичен для конкретного компилятора, что не шибко хорошо. 1 минуту назад, jcxz сказал: Так укажите - внесите их внутрь функции. Кто вам мешает? Либо можно функцию обернуть в макрос, в котором перед и после вызова функции поставить барьеры. Ну, в моём представлении, барьер памяти влияет на работу процессора, а не компилятора (применительно к ARM -- команды DMB, DSB, ISB). А мне нужно именно на компилятор повлиять, чтоб не переносил код, куда ему вздумается. Или речь о чём-то другом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 13 минут назад, SII сказал: В моём случае он выполнил предвыборку полей First и Last одной командой LDRD, затем сгенерировал вызов Append, а потом воспользовался предвыбранным, а не обновлённым значением поля First -- что дало неверный результат. Вы бы хоть привели это в качестве примера. Но примера полного, компилируемого, со всеми объявлениями, который любой желающий может просто скопировать КАК ЕСТЬ себе в компилятор, скомпилить и проверить. А не лазать по всему топику, собирая по крупицам и додумывая, "что же у вас там твориться"? Тогда может кто и посоветовал бы, что дельное. А то складывается впечатление, что ИЛИ вы что-то не то делаете, но не договариваете; ИЛИ баг в компиляторе. Телепатическими способностями никто не обладает. Вам это уже говорили, но вы продолжаете просто жаловаться не делая реальных попыток к решению проблемы. Достаточно минимального фрагмента кода. Главное - чтобы он компилировался. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SII 0 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба Да решил я уже проблему, решил. И не жалуюсь я, а просто констатирую, что без костылей и/или потери эффективности в современной версии языка, похоже, не обойтись. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
amaora 24 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 57 minutes ago, SII said: Проблема возникла из-за того, что компилятор не способен увидеть, что вызов Append может поменять поле First заголовка очереди (что происходит, когда перед вызовом очередь пуста), он видит изменение только Last. В моём случае он выполнил предвыборку полей First и Last одной командой LDRD, затем сгенерировал вызов Append, а потом воспользовался предвыбранным, а не обновлённым значением поля First -- что дало неверный результат. Если бы была возможность атрибутировать эту функцию как имеющую побочные эффекты, запрещающие перемещение кода мимо неё, проблема бы не возникала. Конечно, это в какой-то мере ограничило бы оптимизатор, но не слишком сильно, думается. Это называется aliasing, обычно наоборот приходится объяснять компилятору (квалификатор restrict в аргументах функции), что это гарантированно разные переменные и перечитывать после записи по указателю не нужно. Есть правила запрещающие обращаться к одной области памяти по указателям разных типов, может быть UB, зависит от настроек компилятора. 1 hour ago, SII said: Ну, в моём представлении, барьер памяти влияет на работу процессора, а не компилятора Есть и на уровне компилятора барьеры, любой вызов extern функции (компилятор не видит реализации) не помеченной как pure имеет такой эффект, например. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SII 0 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 1 час назад, amaora сказал: квалификатор restrict в аргументах функции Он чисто сишный, вроде как, а в це++ не поддерживается. 1 час назад, amaora сказал: Есть и на уровне компилятора барьеры, любой вызов extern функции А в данном случае она inline -- для эффективности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 179 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба В ARM CLang тоже поддерживаются: https://developer.arm.com/documentation/dui0375/g/Compiler-Features/Compiler-intrinsics-for-inserting-optimization-barriers Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SII 0 5 февраля, 2023 Опубликовано 5 февраля, 2023 · Жалоба 1 час назад, Arlleex сказал: В ARM CLang тоже поддерживаются О, спасибо. Похоже, то, что нужно. Жаль, конечно, что это не стандартное средство языка, а расширение компилятора, но жрём, что дают 🙂 ADD. Правда, ссылка -- не для ARM Clang, а для старого компилятора 5-й версии, но в ARM Clang тоже есть. ADD2. Увы, не помогло. Похоже, эти вещи срабатывают лишь для операций, которые, с точки зрения компилятора, имеют побочные эффекты, и не препятствуют ему производить предзагрузку из ячейки, явного обращения на запись к которой нет. Так что только volatile. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 64 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 9 часов назад, Arlleex сказал: Компилятор может выкинуть и volatile-объект. На основании чего? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 2 часа назад, dxp сказал: На основании чего? А зачем его оставлять, если нет обращений к нему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться