dxp 56 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 19 минут назад, VladislavS сказал: А зачем его оставлять, если нет обращений к нему? Ну, ведь это асинхронно изменяемый объект, и если в данном месте обращений нет, это не значит, что их нет вообще. Это речь про случай объявления объекта в данной единице компиляции. В случае, если такой объект объявлен где-то в другом месте, а в данной функции к нему нет обращений, то тут и удалять нечего — объект в коде не присутствует (по определению: нет обращений к нему). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 214 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 1 час назад, VladislavS сказал: А зачем его оставлять, если нет обращений к нему? https://en.cppreference.com/w/c/language/volatile Цитата Every access (both read and write) made through an lvalue expression of volatile-qualified type is considered an observable side effect for the purpose of optimization and is evaluated strictly according to the rules of the abstract machine (that is, all writes are completed at some time before the next sequence point). This means that within a single thread of execution, a volatile access cannot be optimized out or reordered relative to another visible side effect that is separated by a sequence point from the volatile access. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 166 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 1 час назад, dxp сказал: Ну, ведь это асинхронно изменяемый объект, и если в данном месте обращений нет, это не значит, что их нет вообще. Это речь про случай объявления объекта в данной единице компиляции. Так все объекты описываются в языке для некой абстрактной машины - и если машина никоим образом не влияет (не читает, не пишет) volatile-объект, то и из образа оптимизатор его выкинет. Для того, чтобы точно не выкидывал, логично задействуют линкер, которому через __attribute__((used)) компилятор "помечает" нужную переменную (константу), мол, "не трожь!". Компилятор ничего сам не выкидывает, разумеется, у него не хватает для этого полномочий. А вот линкер - вполне. Ближайшая аналогия - неиспользуемые функции - в map-файле обычно их видно хорошо. 53 минуты назад, makc сказал: https://en.cppreference.com/w/c/language/volatile Так это как раз не противоречит тому, о чем говорит VladislavS. Полагаю, Вы хотели процитировать SII Цитата Похоже, эти вещи срабатывают лишь для операций, которые, с точки зрения компилятора, имеют побочные эффекты, и не препятствуют ему производить предзагрузку из ячейки, явного обращения на запись к которой нет. Так что только volatile. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 214 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 17 минут назад, Arlleex сказал: Так это как раз не противоречит тому, о чем говорит VladislavS. Полагаю, Вы хотели процитировать SII Обращение как раз есть - на запись. Поскольку компилятор не знает свойств абстрактной машины, то не может делать выводы о бесполезности volatile и должен его оставлять. 18 минут назад, Arlleex сказал: Компилятор ничего сам не выкидывает, разумеется, у него не хватает для этого полномочий. А вот линкер - вполне. Ближайшая аналогия - неиспользуемые функции - в map-файле обычно их видно хорошо. Компилятор вполне себе может выкидывать неиспользуемые переменные, к которым нет обращений (ни на чтение, ни на запись), или изменяемые переменные, априори недоступные за пределами области видимости. Но что касается линкера, то при записи чего-то по адресу уже появляется обращение (на запись) и линкер, как и компилятор, не может делать выводов о его бесполезности. В приведённой мною цитате прямо сказано, что volatile по сути отключает оптимизации и делает невозможным для компилятора удаление подобных присваиваний. В подтверждение своих слов приведу цитату из стандарта C99: Цитата 5.1.2.3 Program execution The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant. Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression may produce side effects. At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place. (A summary of the sequence points is given in annex C.) Так что сказанное мною на основании стандарта C99 противоречит утверждению @VladislavS 24 минуты назад, Arlleex сказал: Полагаю, Вы хотели процитировать SII Нет, ни в коем разе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 22 минуты назад, Arlleex сказал: Компилятор ничего сам не выкидывает, разумеется, у него не хватает для этого полномочий. А вот линкер - вполне. Так и надо говорить, что линкер. Это таки две большие разницы. 🙂 Но и линкер имеет право выбросить только если нет ни одной ссылки (обращения) на объект. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 166 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 2 минуты назад, makc сказал: Обращение как раз есть - на запись. Что-то я упустил. VladislavS (и я тоже) имели в виду случай, когда нет явных обращений к переменной из любых единиц трансляции. Откуда появилась запись? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 214 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 13 минут назад, dxp сказал: Но и линкер имеет право выбросить только если нет ни одной ссылки (обращения) на объек Совершенно верно. Но ведь запись по произвольному адресу (по произвольному указателю) это не обращение объекту, которым оперирует линкер, это просто некий ассемблерный код, порождаемый компилятором и оптимизируемый линкером на более на более высоком уровне. Поэтому линкер на подобные элементы кода не обращает внимания, на сколько я знаю. 9 минут назад, Arlleex сказал: Что-то я упустил. VladislavS (и я тоже) имели в виду случай, когда нет явных обращений к переменной из любых единиц трансляции. Откуда появилась запись? Нет, это я упустил момент перехода на обсуждение варианта с volatile объектом, к которому вообще нет обращений ни на чтение, ни на запись. В таком случае он, естественно, может быть безопасно удалён, т.к. с ним работы нет и нет определяемых в связи с этим побочных эффектов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 6 минут назад, makc сказал: Совершенно верно. Но ведь запись по произвольному адресу (по произвольному указателю) это не обращение объекту, которым оперирует линкер, это просто некий ассемблерный код, порождаемый компилятором и оптимизируемый линкером на более на более высоком уровне. Поэтому линкер на подобные элементы кода не обращает внимания, на сколько я знаю. Очевидно, имеется в виду LTO. Хотя это уже не просто линкер, а про сути проход компилятором уже по собранному коду. Нестандартная вещь. Со спорными в смысле надёжности/"устойчивости" результатами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 214 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба Только что, dxp сказал: Очевидно, имеется в виду LTO. Хотя это уже не просто линкер, а про сути проход компилятором уже по собранному коду. Нестандартная вещь. Со спорными в смысле надёжности/"устойчивости" результатами. Исходя из моего понимания LTO в gcc (лечил пару ошибок в его работе) он делает только безопасные оптимизации типа замены команды с длинным параметром адреса, занимающей, допустим 4 байта, на её двухбайтовый аналог. И тому подобное. Сложных оптимизаций я там не видел, какие делаются внутри компилятора исходя из наличия зависимостей между данными и т.п., хотя может быть просто это прошло мимо меня. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 56 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба Ну, технически-то на LTO не очень сложно отследить, что к тому или иному объекту вообще нет обращений, т.ч. его можно безопасно выкинуть из памяти. Вполне себе безопасная оптимизация, имхо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 214 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 6 минут назад, dxp сказал: Ну, технически-то на LTO не очень сложно отследить, что к тому или иному объекту вообще нет обращений, т.ч. его можно безопасно выкинуть из памяти. Вполне себе безопасная оптимизация, имхо. Ну это как сказать... На этом уровне уже нет информации о потоке исполнения команд, а есть только ассемблер. Поэтому для проведения таких оптимизаций необходимо восстановить из ассемблера (машинных кодов) логику и далее на её основе проводить анализ потоков данных и т.п. Мне кажется это большое поле для ошибок и главное верифицировать подобный механизм будет весьма непросто. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 226 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 2 часа назад, dxp сказал: Ну, ведь это асинхронно изменяемый объект, и если в данном месте обращений нет, это не значит, что их нет вообще. Только исходное сообщение Arleex не совсем корректно. Компилятор выкидывает не сам объект, а обращения к объекту, если они не дают никакого эффекта в программе. А сам объект выкидывает компоновщик, если видит, что к нему нет обращений ни из одной единицы трансляции. А компоновщик уже прекрасно видит "есть ли обращения вообще хоть откуда то". Вот от выкидывания компоновщиком спасает __root в IAR, а не volatile. 1 час назад, Arlleex сказал: Ближайшая аналогия - неиспользуемые функции - в map-файле обычно их видно хорошо. Неиспользуемых функций .map-файле не должно быть по определению. По указанной выше причине. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 166 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 7 минут назад, jcxz сказал: Неиспользуемых функций .map-файле не должно быть по определению. "В map-файле их видно хорошо"... (в смысле список выкинутых функций, имеется в виду). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 226 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 51 минуту назад, makc сказал: Совершенно верно. Но ведь запись по произвольному адресу (по произвольному указателю) это не обращение объекту, которым оперирует линкер, это просто некий ассемблерный код, порождаемый компилятором и оптимизируемый линкером на более на более высоком уровне. Поэтому линкер на подобные элементы кода не обращает внимания, на сколько я знаю. Вы не правы. Если обращение именно к объекту си-программы, а не по абсолютному констатному адресу, то в функции, в которой это обращение находится, должна быть запись о зависимости (или required-запись) с указанием на все объекты, к которым функция обращается. (такая запись находится в .obj-файле, полученном компилятором из функции). Комповщик должен просматривать все такие записи и по ним - строить карту обращений к объектам. Если по карте он увидит, что к какому-то объекту нет ни одного обращения (это касается как переменных/констант, так и функций без __root (или его аналога)), то компоновщик удалит такой объект. И его не будет в .map-файле. 12 минут назад, Arlleex сказал: "В map-файле их видно хорошо"... (в смысле список выкинутых функций, имеется в виду). Вы уверены? В каком компиляторе/компоновщике? Только что ещё раз на всякий случай проверил в IAR, создал: int fff1() { return UART0.RBR; } где UART0.RBR - volatile. fff1() ни откуда не вызывается. В .lst она конечно же есть, в .map - нету. int fff1() { return UART0.RBR; _Z4fff1v: (+1) 00000000 0x.... LDR.N R0,??DataTable14_17 ;; 0x4000c000 00000002 0x6800 LDR R0,[R0, #+0] 00000004 0x4770 BX LR ;; return 00000006 REQUIRE UART0 } И вполне логично. Ведь в .map вроде должно находиться только то, что реально есть в образе программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 214 6 февраля, 2023 Опубликовано 6 февраля, 2023 · Жалоба 1 минуту назад, jcxz сказал: Вы не правы. Если обращение именно к объекту си-программы, а не по абсолютному констатному адресу Не вижу в чём я ошибаюсь, т.к. вы сказали по сути то же самое, что и я, когда говорил об обращении с помощью указателя по произвольному адресу (неважно константному или вычисляемому динамически). При обращении по адресу теряется связь с объектом и, соответственно, исчезает явная зависимость по данным. Вы же наоборот акцентируете внимание на обращении по указателю к некому объекту (по его имени символа, которым оперирует линкер) и в этом случае связь по данным прослеживается, линкер эту связь учитывает и не удаляет соответствующий объект при запуске алгоритма сборки мусора. Так что мы оба правы, просто смотрим на слона с разных сторон. 😉 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться