Сергей Борщ 177 August 24, 2024 Posted August 24, 2024 · Report post 1 минуту назад, const сказал: я прошу sv = (glb & (1 << 6)) а получаю sv = glb Нет. Вы получаете вызов foo() c тем или иным аргументом в зависимости от значения бита 6 в glb или ее не вызов если бит 6 не изменился. Как компилятор это реализует - его личное дело. Да, я был не прав - компилятор в этом случае, действительно, ошибся. Но еще раз подчеркиваю - он не обязан был хранить в sv именно то значение, которое вы хотели. Quote Share this post Link to post Share on other sites More sharing options...
const 1 August 24, 2024 Posted August 24, 2024 · Report post 6 minutes ago, Сергей Борщ said: Нет. Вы получаете вызов foo() c тем или иным аргументом в зависимости от значения бита 6 в glb или ее не вызов если бит 6 не изменился. Как компилятор это реализует - его личное дело. Да, я был не прав - компилятор в этом случае, действительно, ошибся. Но еще раз подчеркиваю - он не обязан был хранить в sv именно то значение, которое вы хотели. да мне без разницы, что и где будет хранить компилятор, мне важен алгоритм, а он нарушается. При таком поведении компилятора, ф-ция foo будет вызыватся всегда, пока glb != 0 && glb != (1 << 6). И как писал выше, когда добавляю дополнительную (временную) переменую, все встает на свои места. А более новий IAR ведет себя предсказуемо всегда. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 August 24, 2024 Posted August 24, 2024 · Report post 2 часа назад, const сказал: @Arlleex Программа корректна, а результат компиляции нет. Ну нет так нет. 1 час назад, jcxz сказал: Результат работы программы при "high balanced" оптимизации и при "medium" будет разный. А значит компилятор неправ. Как бы он ни оптимизировал код, результат выполнения меняться не должен. Может, я что-то упускаю, но почему он будет разным? Quote Share this post Link to post Share on other sites More sharing options...
const 1 August 24, 2024 Posted August 24, 2024 · Report post Посмотрел историю IAR: ICCARM History Хватает ошибок разных, особенно на уровне оптимизации High. Вот возможно разновидность моего случая (не утверждаю): "In EWARM 6.50.4: An indirect assignment could be optimized incorrectly if the right hand side expression was masked with a constant and the only use was in a test, comparing the value, possibly masked with the same constant as in the assignment or a constant with fewer bits set, to zero. For example: p->foo = x & 0x02; ... if (p->foo & 0x02) This has been corrected. [EW23796]" Кроме перехода на более свежую версию, наверное, и оптимизацию буду ставить не више Medium (всегда ставил High Balanced или High Speed). Quote Share this post Link to post Share on other sites More sharing options...
jcxz 342 August 25, 2024 Posted August 25, 2024 · Report post 13 часов назад, Arlleex сказал: Может, я что-то упускаю, но почему он будет разным? Так вы посмотрите сами на получившийся код и подумайте - как он будет работать? И сравните с логикой, описанной исходником. Видно же, что результирующий код не соответствует логике исходника. 15 часов назад, _pv сказал: в "упрощённой" версии и glb и sv всегда равны 0, не понятно почему целиком всё не выкинул, а только присвоение "соптимизировал". Где же это видно? Вы неправы. Видно, что есть некая внешняя функция foo(), а также видно что glb - глобальная. А значит может изменяться например внутри той же foo(). А значит - она не может быть "всегда равна 0". Поэтому "выкинуть всё" - нельзя ни в каком случае. Была бы glb объявлена со "static" - другое дело. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 342 August 25, 2024 Posted August 25, 2024 · Report post 12 часов назад, const сказал: Кроме перехода на более свежую версию, наверное, и оптимизацию буду ставить не више Medium (всегда ставил High Balanced или High Speed). И зря. В IAR-ах с v7.80.4 не замечено серьёзных багов. За исключением тех о которых писал выше: 15 часов назад, jcxz сказал: но по-крайней мере если не используется FPU и некоторые intrinsinc-и, то в 7.80.4 багов не замечал И почему именно "medium"? Если боитесь потенциальных багов, так они могут быть на любом уровне оптимизации или вообще без неё. Ведь если в вашей версии IAR был такой баг, то это не гарантирует, что все другие баги будут в том же самом месте. Потенциальный баг может быть где угодно. Теоретически может быть даже такой баг, который есть при полностью выкл. оптимизации, но исчезает на высоком уровне оптимизации. Использование высоких уровней оптимизации полезно при отладке своего кода тем, что часто приводит к проявлению скрытых багов в коде, не проявляющихся при низких уровнях оптимизации. Почему чайники часто и выключают оптимизацию - ведь при выкл. их код "работает", а при вкл. высокой начинает глючить. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 August 25, 2024 Posted August 25, 2024 · Report post CLang на максимальной оптимизации и LTO просто выкинул весь код. И правильно сделал. Цитата Видно, что есть некая внешняя функция foo(), а также видно что glb - глобальная. А значит может изменяться например внутри той же foo(). А значит - она не может быть "всегда равна 0". Поэтому "выкинуть всё" - нельзя ни в каком случае. Была бы glb объявлена со "static" - другое дело. main() - точка входа в Си-программу, поэтому на момент входа все глобальные переменные без инициализации равны 0. В описании IAR-овского компилятора написано, что при High balanced осуществляется анализ памяти. Может, так он и сделал? Quote Share this post Link to post Share on other sites More sharing options...
const 1 August 25, 2024 Posted August 25, 2024 (edited) · Report post 33 minutes ago, Arlleex said: CLang на максимальной оптимизации и LTO просто выкинул весь код. И правильно сделал. вынесите ф-цию foo в другой файл. Неужели и в таком случае выкинет. 4 hours ago, jcxz said: И почему именно "medium"? Если боитесь потенциальных багов, так они могут быть на любом уровне оптимизации или вообще без неё. Ведь если в вашей версии IAR был такой баг, то это не гарантирует, что все другие баги будут в том же самом месте. Потенциальный баг может быть где угодно. Теоретически может быть даже такой баг, который есть при полностью выкл. оптимизации, но исчезает на высоком уровне оптимизации. Использование высоких уровней оптимизации полезно при отладке своего кода тем, что часто приводит к проявлению скрытых багов в коде, не проявляющихся при низких уровнях оптимизации. Почему чайники часто и выключают оптимизацию - ведь при выкл. их код "работает", а при вкл. высокой начинает глючить. Потому что по приведенной мной ссылке выражение "On optimization level High..." встречается довольно часто. Как я понял, большенство ошибок именно при такой оптимизации, если неправ - поправьте. А на счет высокого уровня оптимизации как инструмента по вылавливанию багов непонял. Всегда пишу на максимальном и в ту закладку даже не заглядываю. Как может алгоритм зависить от уровня оптимизации? Edited August 25, 2024 by const Quote Share this post Link to post Share on other sites More sharing options...
_pv 103 August 25, 2024 Posted August 25, 2024 · Report post 4 hours ago, jcxz said: Где же это видно? Вы неправы. Видно, что есть некая внешняя функция foo(), а также видно что glb - глобальная. А значит может изменяться например внутри той же foo(). А значит - она не может быть "всегда равна 0". Поэтому "выкинуть всё" - нельзя ни в каком случае. Была бы glb объявлена со "static" - другое дело. как бы да, но нет, foo() никогда не будет вызвана так как и glb и sv проинициализованны нулями, соответственно менять glb больше некому, а в коротком примере ничего больше и нет. не буду утверждать что оптимизатор у иара столь прозорливый и сгенерил приведённый странный код поэтому, а не из-за бага, но впринципе, в том коротком примере выкинуть всё право имел. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 August 25, 2024 Posted August 25, 2024 · Report post 1 час назад, const сказал: вынесите ф-цию foo в другой файл. Неужели и в таком случае выкинет. Я так и сделал, разумеется. Выкинул. Повторюсь, это при LTO. Поэтому говорю, что при High balanced в IAR возможно подобное поведение, т.к. в pdf-ке описания, которое я смог нагуглить за наносекунды, написано, что в этом случае компилятор может анализировать содержимое памяти для осуществления оптимизаций. 1 час назад, const сказал: Как может алгоритм зависить от уровня оптимизации? Вопрос одновременно и простой и сложный, чтобы ответить на него вот так, с пыру)) Компилятор не транслирует строчки Си-кода в ассемблер... На основе Си-кода строится аналитическое дерево для выявления поведенческой модели. И именно этот механизм позволяет осуществлять различные оптимизации, такие, которые здоровому человеку в голову не придут. И главное правило оптимизатора - не ломать побочные эффекты программы, если они имеют смысл. Поэтому да, отладка кода у меня не выше -O1 (почти всегда -O0), финальный релиз тестируется и отдается в продакшн только в -Obalanced + LTO. Потому что при повышенных агрессивных оптимизациях всплывает очень много скрытых багов, которые можно поймать и починить. Quote Share this post Link to post Share on other sites More sharing options...
const 1 August 25, 2024 Posted August 25, 2024 (edited) · Report post extern void foo(uint8_t b); uint8_t glb; void tst(void) { static uint8_t sv; uint8_t tmp; if (sv != (glb & (1 << 6))) { sv = (glb & (1 << 6)); tmp = (sv)? 0x00 : 0xFF; foo(tmp); } } int main() { while(1) { glb = GPIOA->IDR; tst(); } } ф-ция foo (в др. файле) void foo(uint8_t b) { GPIOB->ODR = b; } так не выкинет. У меня с добавлением строк работы с портами листинг не поменялся - есть ошибка 40 int main() 41 { \ main: \ 00000000 0xB570 PUSH {R4-R6,LR} \ 00000002 0x.... LDR.N R5,??DataTable3_1 \ 00000004 0x.... LDR.N R6,??DataTable3_2 ;; 0x40020010 \ 00000006 0xE001 B.N ??main_0 42 while(1) { 43 44 glb = GPIOA->IDR; 45 tst(); \ ??main_1: \ 00000008 0x.... 0x.... BL foo \ ??main_0: \ 0000000C 0x6830 LDR R0,[R6, #+0] // читаем порт \ 0000000E 0x7869 LDRB R1,[R5, #+1] // sv \ 00000010 0x7028 STRB R0,[R5, #+0] // glb = GPIOA->IDR \ 00000012 0x7828 LDRB R0,[R5, #+0] // glb \ 00000014 0xF000 0x0240 AND R2,R0,#0x40 // glb & (1 << 6) \ 00000018 0x4291 CMP R1,R2 \ 0000001A 0xD0F7 BEQ.N ??main_0 \ 0000001C 0x7068 STRB R0,[R5, #+1] // sv = glb (без маскирования) \ 0000001E 0x0640 LSLS R0,R0,#+25 \ 00000020 0xBF4C ITE MI \ 00000022 0x2000 MOVMI R0,#+0 \ 00000024 0x20FF MOVPL R0,#+255 \ 00000026 0xE7EF B.N ??main_1 46 47 } 48 } Edited August 25, 2024 by const Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 August 25, 2024 Posted August 25, 2024 · Report post 1 минуту назад, const сказал: int main() { while(1) { glb = GPIOA->IDR; tst(); } } так не выкинет. У меня с добавлением строк работы с портами листинг не поменялся - есть ошибка Ну так конечно не выкинет, так как присвоение glb требует порождения побочного эффекта - доступа к volatile-объекту. 7 минут назад, const сказал: так не выкинет. У меня с добавлением строк работы с портами листинг не поменялся - есть ошибка Вот теперь да, можно сказать, что ошибка есть. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 342 August 25, 2024 Posted August 25, 2024 · Report post 2 часа назад, Arlleex сказал: CLang на максимальной оптимизации и LTO просто выкинул весь код. И правильно сделал. Нет неправильно. Или ваш тест был некорректный. glb - глобальная. Которая может модифицироваться за пределами данного кода. 2 часа назад, Arlleex сказал: main() - точка входа в Си-программу, поэтому на момент входа все глобальные переменные без инициализации равны 0. Ну и что? Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 August 25, 2024 Posted August 25, 2024 · Report post 5 минут назад, jcxz сказал: Нет неправильно. Или ваш тест был некорректный. Тест ровно тот что ТС указал в первом топике. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 342 August 25, 2024 Posted August 25, 2024 · Report post 1 час назад, _pv сказал: как бы да, но нет, foo() никогда не будет вызвана так как и glb и sv проинициализованны нулями, соответственно менять glb больше некому, а в коротком примере ничего больше и нет. Ошибаетесь. Какой-то код мог быть выполнен и до main(). Например - запущен ISR или вообще - запущена ОС. Задачи которой и могут модифицировать glb уже после её инициализации. Пускай даже она без volatile. 4 минуты назад, Arlleex сказал: Тест ровно тот что ТС указал в первом топике. Код то тот, но в проекте IAR ТС-а могут быть и другие файлы (они должны быть - ведь у нас МК, где-то есть инициализация его периферии). И IAR их имел в виду. А вы в тесте взяли ровно только то, что написано в исходном сообщении. Quote Share this post Link to post Share on other sites More sharing options...