Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как отключить оптимизацию switch() ?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
GetSmart
Перепробовал все прагмы типа
#pragma optimize=high/medium/low size/balanced/speed no_cse no_unroll no_tbaa no_inline no_code_motion

Всё равно switch() оптимизирует и тратит из-за этого DPL,DPH & B в прерывании MCS-51.

Мне надо чтобы switch из четырёх элементов сделался как через if () ...

Ну неужели придётся делать ручками через if
Xenia
Цитата(GetSmart @ Jan 29 2012, 11:40) *
Мне надо чтобы switch из четырёх элементов сделался как через if () ...

Тогда и пишите 4 ифа вместо свича sm.gif.

Во всех реализациях языков программирования (с которыми я встречалась) switch - это выбор из списка адресов, каковыми могут быть либо адреса безусловных переходов, либо адреса подпрограмм. Поэтому и реализация его такова, что где-то такой список составляется, а конкретные реализации различается между собой лишь способом вычисления смещения от начала списка с последующим переходом на этот адрес.

Впервые слышу, чтобы switch оптимизировали путем замены на батарею if-ов. Если какие-то компиляторы на это способны, то хотелось бы услышать их названия.
Палыч
Цитата(Xenia @ Jan 29 2012, 12:03) *
...хотелось бы услышать их названия.

Keil
sonycman
Да и тот же IAR для ARM.
Switch из 15 case компилируется в простейший, но длинный список инструкций cmp - branch на максимальной оптимизации.
Вероятно, так будет экономнее по размеру памяти, по сравнению с таблицей адресов.
GetSmart
Неужели в самом деле родители ИАРа решили, что их детищу лучше знать всегда когда и где?

Цитата(sonycman @ Jan 29 2012, 13:24) *
Да и тот же IAR для ARM.
Switch из 15 case компилируется в простейший, но длинный список инструкций cmp - branch на максимальной оптимизации.

Именно енто я и хочу. Не знаю как его заставить.
GetSmart
Нда.
Переделал на if-ы.
Стало на 11 байт короче самого оптимизированного варианта со свичём. Плюс в 2 раза меньше стека юзает 5 vs 10 байт. Оптимизаторы, рационализаторы sm.gif
При этом в каждом if-е перечитывает переменную заново, хотя мог бы в акке держать и XOR-ить от варианта к варианту.

IAR 7.60, оптимизация high/size.

Ну а чего он читая битовую переменную (__bit || __bdata || sfr bit) анализирует её через флаг C, а не сразу в JB bit,label тоже вопрос к гениальным разработчикам.
_Pasha
Цитата(Xenia @ Jan 29 2012, 11:03) *
Впервые слышу, чтобы switch оптимизировали путем замены на батарею if-ов. Если какие-то компиляторы на это способны, то хотелось бы услышать их названия.

Я Вас умоляю... для MCS-51 команда CJNE <reg>, #immediate, offset как раз для этого случая. Может, кейл не понимайт, что выражение под свитчем не int, a char ?

Цитата(GetSmart @ Jan 29 2012, 13:15) *
Ну а чего он читая битовую переменную (__bit || __bdata || sfr bit) анализирует её через флаг C, а не сразу в JB bit,label тоже вопрос к гениальным разработчикам.

Ну да, ну да sm.gif А выражение куда девать? И что там с lazy evaluation, если sfr bit у нас volatile? Я думаю, курить их хелп-не перекурить. Или избегать стрёмных ситуаций.
GetSmart
Цитата(_Pasha @ Jan 29 2012, 16:55) *
Может, кейл не понимайт, что выражение под свитчем не int, a char ?

Какой Кейл? Подфорум об ИАРе. И не выражение, а переменная u08. Нету там promotion.

Цитата(_Pasha @ Jan 29 2012, 16:55) *
Ну да, ну да sm.gif А выражение куда девать? И что там с lazy evaluation, если sfr bit у нас volatile? Я думаю, курить их хелп-не перекурить. Или избегать стрёмных ситуаций.

Вот и волатил и неволатил делает одинаково. (Upd. с неволатилом ещё не проверил, оказалось везде был волатил)
lazy evaluation не знаю, куда притянуть.
Я наткнулся на таких и подобных командах
Код
if (SCON0_bit.TI0)
{ SCON_bit.TI0 = 0;     // хорошо хоть в этой команде не сдурил и сделал её битовой в одну команду
                        // а был бы умным, поставил вообще jbc bit,label
_Pasha
Кейл sad.gif огорчил.
_Pasha
Вот ещё что:
Цитата(Xenia @ Jan 29 2012, 11:03) *
Во всех реализациях языков программирования (с которыми я встречалась) switch - это выбор из списка адресов, каковыми могут быть либо адреса безусловных переходов, либо адреса подпрограмм.

А где это так? ПП - это ведь дороговатая операция. Не видел, или не обращал внимания. Может, там где ближние переходы переходят в дальние? Типа для однородности
???
GetSmart
Давно хотел спросить. Xenia, куда замылили ветку с новыми выкидышами от ИАР? sm.gif
Xenia
Цитата(GetSmart @ Jan 29 2012, 17:23) *
Давно хотел спросить. Xenia, куда замылили ветку с новыми выкидышами от ИАР? sm.gif

Она на старом месте - http://electronix.ru/forum/index.php?showt...7015&st=195 в разделе (подфоруме) "Программное обеспечение - Soft, FTP", куда пускают только своих. Вы же его не видите потому, что вы не наш! sm.gif
arttab
iar #pragma optimize=none
GetSmart
Цитата(arttab @ Jan 30 2012, 06:09) *
iar #pragma optimize=none

Делает по-прежнему.
Начинаю думать, что в 7.60 это единственный вариант кодирования свичей. Надо бы на 8-ой проверить.
На картинке вторая часть того, во что ИАР превращает свич из 4-ёх вариантов. Тихий ужас.

Цитата(Xenia @ Jan 30 2012, 01:21) *
...куда пускают только своих. Вы же его не видите потому, что вы не наш! sm.gif

Ага. Кто не с нами, тот против нас. Так и запишем в протокол.
А ведь до НГ я её видел. СОПУ испугались что ли.
_Pasha
Цитата(GetSmart @ Jan 30 2012, 05:48) *
Тихий ужас.

Если все идут не в ногу, значит у Вас - какой-то косяг в определении данных.
scifi
Ну не знаю... Опускаться до таких извращений, чтобы выжать пару байт из кода? ЯВУ не для этого придуманы. Если так сильно надо оптимизировать в этом месте, то следует использовать ассемблер. А если оптимизировать на самом деле не нужно, но очень хочется, то это проблема уже из области психологии.
GetSmart
Цитата(scifi @ Jan 30 2012, 18:05) *
Ну не знаю... Опускаться до таких извращений, чтобы выжать пару байт из кода? ЯВУ не для этого придуманы. Если так сильно надо оптимизировать в этом месте, то следует использовать ассемблер. А если оптимизировать на самом деле не нужно, но очень хочется, то это проблема уже из области психологии.

А по делу? А конструктивно?

А то ведь дойдёт до того, что и квалификаторы static, __data, __bit, __bdata, __code и ещё туча других будут приравнены к извращениям. Я могу и на асме писать, но не хочу, т.к. править что-то в нём долго. Однако я имею право (и компиляторы дают возможность) управлять оптимизацией на усмотрение программиста. Вот и возник простой вопрос без всякого психоанализа - какой кнопкой отключить оптимизацию свича. Нельзя, так нельзя. Спрашивал у знающих людей.

И вообще, настоящий профи знает инструмент с которым работает до малейшего винтика. Будь то компилятор или даже ЯВУ типа С++. Ну а программер мелкого пошиба будет искать любые отмазки и всё делать тяп-ляп. Так что давайте определяться.
xemul
Цитата(GetSmart @ Jan 30 2012, 05:48) *
Делает по-прежнему.

За что Вы так компилятор не любите? (это я про volatile в switch)
имхо, вполне естественное решение:
Код
tmp = uartData.rxPhase;
switch(tmp) {}

А если ещё упростить жисть компилятору, то
Код
/* вместо
tmp = uartData.rxPhase;
switch(tmp)
{
   case A:
   case B:
   case C:
...
}
*/
tmp = uartData.rxPhase ^ A;
if(!tmp) {}
else if(!(tmp ^= A ^ B)) {}
else if(!(tmp ^= B ^ C)) {}
...

(в зависимости от компилятора и архитектуры контроллера) может оказаться короче.
GetSmart
Цитата(xemul @ Jan 30 2012, 19:40) *
За что Вы так компилятор не любите? (это я про volatile в switch)

Ай лов дис компилер sm.gif
Там не было volatile (uartData.rxPhase - обычная переменная) И при этом она постоянно перечитывалась.
Ранее я упоминал волатил касательно работы с битовыми переменными.

Цитата(xemul @ Jan 30 2012, 19:40) *
А если ещё упростить жисть компилятору, то
...
Код
tmp = uartData.rxPhase ^ A;
if(!tmp) {}
else if(!(tmp ^= A ^ B)) {}
else if(!(tmp ^= B ^ C)) {}
...

(в зависимости от компилятора) может оказаться короче.

В зависимости от... Ну Вы же понимаете, когда есть множественный выбор по одной переменной/выражении, то именно для этого придуман свич. Да и с ним грациозней код смотрится sm.gif Ну а до 8051 я сидел на EWARM, который свичи гораздо более навороченные делал через compare-branch. И я до сих пор не понимаю изврата, с которым столкнулся.

Upd.
То, что Вы "сотворили" имхо уже изврат. То есть для ЯВУ некрасиво и менее понятно, чем простые сравнения переменной с тремя-четырьмя константами. Такой экономии мне не надо. Пусть 5 тактов будет лишних. Я за красоту кода и полное и бесприкословное подчинение компилятора sm.gif Но из-за ущербности свича (а он там с полсотни тактов растранжирит и это в прерывании) я всё-таки заменю их на 3 if-а и парочку goto. Остальное в исходнике должно быть красиво. Ваш код должен уметь делать сам компилятор. Это почти элементарно. Но он неумёха в области 8051. А вот в ARM-е он на порядок круче генерит. Там ему большой респект.
GetSmart
Ужжасс.
7.60.1 ещё и глючный.
По адресу 072C надо сдвигать на оригинальное значение bit, а сдвигается на bit-8 (ACC). V1:V0 - что сдвигать, R0 - адрес V1:V0.
GetSmart
Цитата(Xenia @ Jan 29 2012, 13:03) *
Впервые слышу, чтобы switch оптимизировали путем замены на батарею if-ов. Если какие-то компиляторы на это способны, то хотелось бы услышать их названия.

Привожу название: ИАР 8.10.4. Картинка нумбер уан. Причём ни один свич в моей проге больше не делается через то заднее место как раньше.

На картинке нумбер ту исправлен глюк с искажением аккумулятора при сравнении. Но в целом этот кусок стал заметно хуже предыдущего.

Вобщем уровень компиляции ещё очень далек от уровня АРМ-овой версии ИАРа. Грубо говоря в 2 раза компактней можно писать на асме. А в АРМовом грубо раза в 1.2.
GetSmart
А 8.10.4 тоже какие-то приколисты писали. Вобщем видны некоторые улучшения оптимизации. В конце функции вызов другой функции заменяется на LJMP func. Сброс двух битов в одной битовой переменной заменяется на ANL var,mask.

Но есть лишние операции, хоть и не искажающие работу проги. Как буд-то кто-то хотел обмануть, но не срослось sm.gif

До сих пор в отладчике переходы назад отображаются неправильно, на 1 байт ошибается в мнемонике. Хотя команда правильная и исполняется правильно.
Xenia
Цитата(GetSmart @ Feb 11 2012, 07:29) *
А 8.10.4 тоже какие-то приколисты писали. Вобщем видны некоторые улучшения оптимизации.

А у вас какая оптимизация включена? По скорости или по размеру?

Кстати, версия 8.10.4 уже не последняя - вчера вышла 8.11.1. Вот только испытывать ее боюсь из-за новой системы лицензирования. Теперь инсталлятор раздают свободно (тута) и он даже пытается что-то инсталлировать, но чтобы компилить стало, надо регистрировать по интернету. Есть предупреждение, что новая и старая система лицензирования несовместимы на одном компе (ОСе?), вот и трушу проверять, опасаясь, что старые лицензии (на другие платформы) у меня слетят. Впрочем, ожидать заметных подвижек в качестве компиляции от новой версии не приходится, т.к., судя по описанию, смена способа лицензирования - единственное, чем она отличается от своей предшественницы.

Сама же тенденция улучшать качество кода с ростом номера версии довольно хорошо прослеживается. Да и со временем ошибки тоже пользователями выявляются и производителем исправляются. Вот только Startup-код постоянно растет...

Но если за собой знаешь ту болезнь, что постоянно лазишь в код, генерируемый компилятором, и переживаешь по всякому поводу (типа "я написала бы лучше"), то лучше на ассемблере так и оставаться, а на С не переходить - целее нервы будут sm.gif. Со мной тоже такое было, но со временем прошло.
GetSmart
Оптимизация у меня максимальная по размеру. Причём галку "Common subexpression elimination" даже выключил, без неё ещё компактней.

Смотреть код это такая же болезнь как смотреться в зеркало. Вы, как представительница женского пола, не болеете? sm.gif Перестать смотреть не желаете?

Залазя на новый компилятор просто нужно смотреть код. Это привычка старого профессионала. Лет 5 сидел на EWARM 4.20 и смотрел код тщательно первые несколько месяцев. Потом уже узнаёшь его как свои 5 пальцев sm.gif Кроме того, это помогает быстро искать ошибки в скомпиленном коде.

Кто бы ещё быстренько подсказал - какой компилер лучше генерит код ИАР 8.10 или какой-нить последний Кейл или ещё какой.
Xenia
Цитата(GetSmart @ Feb 11 2012, 12:06) *
Кто бы ещё быстренько подсказал - какой компилер лучше генерит код ИАР 8.10 или какой-нить последний Кейл или ещё какой.

Этот вопрос широко рассматривался вот в этой теме - "Какой компилятор выбрать IAR или Keil?, а может GCC?", но с тех пор много воды утекло (появились новые версии компиляторов). Было бы целесообразно реанимировать ту тему (в смысле продолжить), а то в теме про switch этот вопрос вряд ли найдет широкий отклик.

Цитата(GetSmart @ Feb 11 2012, 12:06) *
Лет 5 сидел на EWARM 4.20 и смотрел код тщательно первые несколько месяцев. Потом уже узнаёшь его как свои 5 пальцев sm.gif Кроме того, это помогает быстро искать ошибки в скомпиленном коде.

Вот вы бы этим лично и занялись, как лицо заинтересованное и квалифицированное. Тем более что с IAR вы до конца разобрались. Сравнить, на мой взгляд, стоит только с Keil и GCC, остальные не конкуренты.
GetSmart
Цитата(Xenia @ Feb 11 2012, 13:21) *
Этот вопрос широко рассматривался вот в этой теме - "Какой компилятор выбрать IAR или Keil?, а может GCC?",

2005-2006 годы, платформа ARM. Для 8051 имхо топик должен быть свой.
Dikoy
Цитата(arttab @ Jan 30 2012, 04:09) *
iar #pragma optimize=none

А как назад вернуть как было?
Эта гадина мне вачдог оптимизирует:
WDTCSR = (1 << WDCE) | (1<<WDE);
WDTCSR = (1 << WDE) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0);
Dikoy
Всё, разобрался.
_Артём_
Цитата(Dikoy @ Mar 5 2012, 22:27) *
А как назад вернуть как было?
Эта гадина мне вачдог оптимизирует:
WDTCSR = (1 << WDCE) | (1<<WDE);
WDTCSR = (1 << WDE) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0);

Цитата
Use this pragma directive to decrease the optimization level, or to turn off some specific
optimizations. This pragma directive only affects the function that follows immediately
after the directive.


Разве надо возвращать?
Какой у вас уровень оптимизации установлен?



Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.