|
|
|
Инлайновая функция |
|
|
|
Jul 10 2018, 15:26
|
Знающий
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842
|
Почему ничего не меняется? По-моему меняется инлайн или нет инлайна. Возможно вы захватили ссылку на годболт в котором я описался в тайпдефе и постарался быстро это исправить, посмотрите это место внимательно. ЗЫ Вообще я как-то притомился от этой дискуссии. Была озвучена задача "как избежать инлайна", было озвучено решение, попросили аргументы почему оно должно работать, ссылки были приведены. Но почему-то когда оппоненты декларируют что что-то не работает или может работать по другому своё мнение ссылками не подтверждают. В общем я пас продолжать в том же духе. Приводите ссылки на стандарт которые по вашем мнению его подтверждают, тогда поговорим. УПД Поправил ссылку на годболт с вариантом lvalue без volatile. Если обратить внимание оно поняло что вызывается конкретная функция и происходит сразу джамп куда надо, да оно не захотело инлайнить, но по стандарту компилятор имеет на это полное право. Ваша надежда на lvalue без volatile и есть тот самый "тонкий лёд" который сейчас работает, а потом может и перестать. УПД2: Вот кстати шланг замечательно заинлайнил ваш lvalue.
|
|
|
|
|
Jul 11 2018, 05:55
|
Местный
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682
|
Цитата(Kabdim @ Jul 10 2018, 18:26) Это был не lvalue, а xvalue. Чтобы получить lvalue надо "fptrnv ftnv = (fptrnv)&func;" вынести за пределы функции и тогда происходит вызов. По поводу lvalue у меня лишь предположение в надежде что кто-то знающий стандарт или подтвердит или опровергнет. Насчет модификатора "volatile" у меня возражений изначально не было, просто хотелось найти объяснение почему не работает ((fptr)func)();. Отличия лишь только в том, что c указателем - xvalue, с преобразованием - rvalue.
Сообщение отредактировал aiwa - Jul 11 2018, 05:56
|
|
|
|
|
Jul 11 2018, 06:57
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(aiwa @ Jul 10 2018, 17:36) Если его объявление заменить просто вызовом функции ничего не поменяется. Точнее - заменить команду BLX Rx. Чтение указателя из памяти должно остаться так как он volatile. А вот заменить BLX Rx на тело функции - это нисколько не противоречит концепции volatile, так как volatile (судя по её определению), должна сохранять неизменным только порядок доступов к памяти (чтений/записи). А не всю последовательность команд подряд. Но пара команд BLX Rx/BX LR - не осуществляет доступов к памяти. Так что - даже если современные версии компиляторов не инлайнят, то ничто не мешает инлайнить последующим версиям.
|
|
|
|
|
Jul 11 2018, 07:04
|
Гуру
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136
|
Цитата(jcxz @ Jul 11 2018, 09:57) ничто не мешает инлайнить последующим версиям. У вас какая-то избирательная манера читать. Напоминаю: Цитата(scifi @ Jul 10 2018, 09:23) Причина, по которой этого не случится: указатель объявлен как volatile, поэтому компилятор не знает, что в нём, поэтому не знает, какой код туда можно заинлайнить вместо вызова функции по указателю. Следовательно, вызовет функцию. Возражения есть? Возражений нет.
|
|
|
|
|
Jul 11 2018, 07:10
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(Kabdim @ Jul 10 2018, 18:26) попросили аргументы почему оно должно работать, ссылки были приведены. Где??? Пролистал только что весь топик - ни одной ссылки по теме не увидел. Ваши ссылки тут вообще ни к селу ни к городу. Это как если бы доказывать, что вот, раз сейчас у меня компилятор компилит функцию с переменной расположенной в регистре R4, то значит и всегда все компиляторы должны компилить эту функцию с данной переменной расположенной в R4. Надеюсь достаточно доходчиво объяснил бесполезность ваших ссылок? А я придерживаюсь строгого правила: пока не доказано обратное, может быть и так и сяк - гарантий нет.
|
|
|
|
|
Jul 11 2018, 07:45
|
Гуру
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136
|
Код уже приводили: Код void f(void) { do_something(); }
void foobar(void) { void (*volatile fptr)(void); fptr = f; fptr(); } Цитата(jcxz @ Jul 11 2018, 10:40) Все эти случаи для обычных data-переменных современные оптимизаторы определяют на раз, узнавая в них просто константы. Для этого и существует слово volatile: "Оптимизатор, не твоё пи-пи дело, какой адрес хранится в указателе fptr. Может, святой дух там изменил значение. Вызывай функцию по адресу и не выпендривайся." Вот: "An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects." Собственно, отсюда и следует.
|
|
|
|
|
Jul 11 2018, 07:59
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(jcxz @ Jul 11 2018, 09:57) так как volatile (судя по её определению), должна сохранять неизменным только порядок доступов к памяти (чтений/записи). Да, похоже что и даже это не так. Только что проверил: указание volatile даже не гарантирует сохранение порядка доступов к памяти. По крайней мере в IAR 7.80: Код static int DteTstInline1(char const *str, uint, uint) { return 0x3871; } static int DteTstInline0(char const *str, uint c, uint n) { static int (* volatile const pf)(char const *, uint, uint) = DteTstInline1; ... return (*pf)(str, c, __CLZ(n)); } Код ... LDR.W R3,??DataTable647_10 LDR R3,[R3, #+0] CLZ R2,R6 MOV R1,R5 MOV R0,R4 ADD SP,SP,#+4 POP {R4-R9,LR} BX R3
??DataTable647_10: DC32 `...::pf`
??_Z13DteTstInline1PKcjj: MOVW R0,#+14449 BX LR Как видно - компилятор разорвал выражение (*pf)(str, c, __CLZ(n)) и вставил между чтением volatile-константы и вызовом функции другой доступ к памяти: POP {R4-R9,LR}. Что странно, так как в пределах volatile он не должен вроде менять порядок доступов к памяти....
|
|
|
|
|
Jul 11 2018, 08:03
|
Гуру
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136
|
Цитата(jcxz @ Jul 11 2018, 10:59) Как видно - компилятор разорвал выражение (*pf)(str, c, __CLZ(n)) и вставил между чтением volatile-константы и вызовом функции другой доступ к памяти: POP {R4-R9,LR}. Что странно, так как в пределах volatile он не должен вроде менять порядок доступов к памяти.... Гарантируется порядок доступа к volatile-объектам. У вас в примере только один такой объект, поэтому говорить о порядке доступа не приходится. Вы откровенно плохо знаете стандарт. При этом риторика огого. Почаще туда заглядывайте.
|
|
|
|
|
Jul 11 2018, 09:06
|
Знающий
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842
|
Цитата(jcxz @ Jul 11 2018, 10:10) Где??? Пролистал только что весь топик - ни одной ссылки по теме не увидел. #50 Цитата(jcxz @ Jul 11 2018, 10:10) Ваши ссылки тут вообще ни к селу ни к городу. Это как если бы доказывать, что вот, раз сейчас у меня компилятор компилит функцию с переменной расположенной в регистре R4, то значит и всегда все компиляторы должны компилить эту функцию с данной переменной расположенной в R4. Надеюсь достаточно доходчиво объяснил бесполезность ваших ссылок? Нет, просто упорствуете в своем очевидном всем остальным невежестве. :D Цитата(aiwa @ Jul 11 2018, 08:55) Это был не lvalue, а xvalue. Чтобы получить lvalue надо "fptrnv ftnv = (fptrnv)&func;" вынести за пределы функции и тогда происходит вызов. Под конкретный оптимизатор всегда можно найти танец с бубном который выключит ту или иную оптимизацию. В предложеном варианте вы просто разносите присваивание и использование за границу глубины анализа. Но лет через 10 она поменяется, компилятор сново увидит в конкретном месте что значение переменной - конкретное им вычисленное и заоптимизирует так как заохочет. Единственная гарантированная защита которая возможна по стандарту это volatile.
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|