Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.96/68: Рейтинг темы: голосов - 68, средняя оценка - 4.96
vystor.s
0 / 0 / 0
Регистрация: 01.03.2012
Сообщений: 168
1

IAR 1.31 - Оптимизация

07.11.2012, 19:38. Просмотров 12295. Ответов 28
Метки нет (Все метки)

Написал простой кусок кода - вывод значения на 7-ми сегментный индикатор.
Включил максимальную оптимизацию и посмотрел что получилось.


Честно говоря, я ожидал примерно следующего - грузим число в аккумулятор, сдвигаем его через перенос и в зависимости от переноса устанавливаем нужный бит нужного порта.
Получилось, конечно, очень похоже, но я не понимаю 2 момента:
1. Зачем для каждого пина сдвигать и аккумулятор и память?
Почему не что-то одно (лучше аккум), а потом просто скопировать, если уж сильно хочется?
А почему вообще должно хотется при выходе из функции иметь где-то последнее значение value - оно же явно больше нигде не используется.

2. Что это за манипуляции в конце функции перед RET?

Ну и основной вопрос - посоветуйте как переписать код (на C, на асме я и сам знаю), что бы он таки скомпилился правильно.

Спасибо!

P.S. Уже перепробовал кучу разных, полностью равнозначных с точки зрения С, вариантов реализации этого куска кода.
Изначально ожидал что хороший оптимизатор сгенерит одинаковый (самый оптимальный) ассемблерный код.
Но нет, почти любой изменение приводит к разному результату компиляции.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.11.2012, 19:38
Ответы с готовыми решениями:

IAR
Люди, у кого ИАР версии 5.20.4 или выше, выложите пожалуйста папки config и yms в архиве.

IAR Internal Error: нужна помощь по IAR и по C++
Просьба к тем, у кого есть IAR AVR версии выше, чем 5.11B/W32 (5.11.2.5): не могли бы вы...

Типы оптимизация: черная оптимизация, серая оптимизация и белая оптимизация
Много много лет назад, на заре становления профессии "оптимизатора" в какой то умной книжке был...

Оптимизация методом Ньютона (нахождение точки минимума). Оптимизация кода
MATLAB только начал осваивать. Попытался реализовать нахождение точки минимума методом Ньютона...

IAR
IAR asm: что значит знак # перед чиислами? например #0280h

28
dork_usir
0 / 0 / 0
Регистрация: 03.10.2012
Сообщений: 783
07.11.2012, 20:38 2
ИАР всегда отличался присущим только ему извращённым уёбством...
В случае с STM8 ИАР в этом превзошёл сам себя... Уже только за такое можно на ИАРе поставить жирный крест... раз и навсегда...
Что делать:
1. Юзать ИАР и дальше... как есть... плюя на всё и закрывая глаза... "лучше что-то, чем ничего"...
2. Юзать Космик... это порядочно сбережёт нервы и время...
3. Забить нах на STM8 вообще... как забила на него сама ST... и, похоже, многие другие...
0
dosykus_2
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 4,017
07.11.2012, 21:14 3
Цитата Сообщение от dork_usir
2. Юзать Космик... это порядочно сбережёт нервы и время...
Ну вот я проапгрейдил летом, еще год могу жить спокойно. А дальше ?
0
PRS
0 / 0 / 0
Регистрация: 12.07.2011
Сообщений: 3
07.11.2012, 21:22 4
Иар при работе с стм8 используют так называемые "виртуальные" регистры. Т.к. одного аккумулятора и 2 индексных несколько маловато. Отсюда и дублирование операций. Как минус - при простых действиях возникает избыточность.
А еще он не знает про команду инкремента:)
0
dork_usir
0 / 0 / 0
Регистрация: 03.10.2012
Сообщений: 783
07.11.2012, 21:23 5
Цитата Сообщение от dosykus_2
А дальше ?
А дальше... (1) или (3)...
Изменеий к лучшему то... и не намечается... )))
0
dork_usir
0 / 0 / 0
Регистрация: 03.10.2012
Сообщений: 783
07.11.2012, 21:25 6
Цитата Сообщение от PRS
А еще он не знает про команду инкремента:)
А ещё... если не изменяет память... с инверсией бита... жопа...
0
PRS
0 / 0 / 0
Регистрация: 12.07.2011
Сообщений: 3
07.11.2012, 21:30 7
Да и хер с этим. Все равно стм8 получше авр будет:)
0
dork_usir
0 / 0 / 0
Регистрация: 03.10.2012
Сообщений: 783
07.11.2012, 21:35 8
А что... АВР ещё производят??? ))))))
По ядру... плюс-минус лапоть... по периферии - STM8 получше... однозначно... камень то... поновее будет...
0
Bytt
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
08.11.2012, 00:41 9
Цитата Сообщение от vystor.s
Написал простой кусок кода - вывод значения на 7-ми сегментный индикатор.
Включил максимальную оптимизацию и посмотрел что получилось.
Вложение:
IAR.png

Честно говоря, я ожидал примерно следующего - грузим число в аккумулятор, сдвигаем его через перенос и в зависимости от переноса устанавливаем нужный бит нужного порта.
Получилось, конечно, очень похоже, но я не понимаю 2 момента:
1. Зачем для каждого пина сдвигать и аккумулятор и память?
Почему не что-то одно (лучше аккум), а потом просто скопировать, если уж сильно хочется?
А почему вообще должно хотется при выходе из функции иметь где-то последнее значение value - оно же явно больше нигде не используется.

2. Что это за манипуляции в конце функции перед RET?

Ну и основной вопрос - посоветуйте как переписать код (на C, на асме я и сам знаю), что бы он таки скомпилился правильно.

Спасибо!

P.S. Уже перепробовал кучу разных, полностью равнозначных с точки зрения С, вариантов реализации этого куска кода.
Изначально ожидал что хороший оптимизатор сгенерит одинаковый (самый оптимальный) ассемблерный код.
Но нет, почти любой изменение приводит к разному результату компиляции.А что такое SIT_PIN?
0
tid_fom
0 / 0 / 0
Регистрация: 21.10.2011
Сообщений: 1,861
08.11.2012, 00:47 10
Цитата Сообщение от Bytt
А что такое SIT_PIN?
бля.
0
dork_usir
0 / 0 / 0
Регистрация: 03.10.2012
Сообщений: 783
08.11.2012, 01:01 11
Цитата Сообщение от tid_fom
бля.
Не блякай... ))))
Bytt просто так бы спрашивать не стал... вопрос резонный...
0
vystor.s
0 / 0 / 0
Регистрация: 01.03.2012
Сообщений: 168
08.11.2012, 02:12 12
Цитата Сообщение от Bytt
А что такое SIT_PIN?
SIT_PIN задефайнен вот так:
Код
#define SIT_PIN(...) SIT_PIN_(__VA_ARGS__)
#define SIT_PIN_(PORT, PIN, VOT)  P ## PORT ## _ODR_ODR ## PIN = (VOT)
Пины сегментов задефайнены вот так:
Код
#define seg_a_pin   C, 3
#define seg_b_pin   C, 5
#define seg_c_pin   C, 7
#define seg_d_pin   D, 2
#define seg_e_pin   D, 3
#define seg_f_pin   C, 4
#define seg_g_pin   C, 6
#define seg_dp_pin  D, 1
После препроцессора (поставил галку Preprocessor outpu to file) вот такой вот код:
Код
static void show_digit(unsykned char value) {
PC_ODR_ODR3 = (value & 1); // Просто для сравнения

SIT_PIN(seg_a_pin, value & 1);
value >>= 1;
SIT_PIN(seg_b_pin, value & 1);
value >>= 1;
SIT_PIN(seg_c_pin, value & 1);
value >>= 1;
SIT_PIN(seg_d_pin, value & 1);
value >>= 1;
SIT_PIN(seg_e_pin, value & 1);
value >>= 1;
SIT_PIN(seg_f_pin, value & 1);
value >>= 1;
SIT_PIN(seg_g_pin, value & 1);
value >>= 1;
SIT_PIN(seg_dp_pin, value & 1);
}
выглядит вот так:
Код
static void show_digit(unsykned char value) {
PC_ODR_bit . ODR3 = (value & 1); // Просто для сравнения

PC_ODR_bit . ODR3 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR5 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR7 = (value & 1);
value >>= 1;
PD_ODR_bit . ODR2 = (value & 1);
value >>= 1;
PD_ODR_bit . ODR3 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR4 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR6 = (value & 1);
value >>= 1;
PD_ODR_bit . ODR1 = (value & 1);
}
Вроде бы все честно...
0
Omkit5o
0 / 0 / 0
Регистрация: 01.02.2011
Сообщений: 219
08.11.2012, 20:27 13
присвойте value локальной регистровой переменной. От двойних сдвигов должно помочь.
Концовка функции хз - не до вниканий.
0
Bytt
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
08.11.2012, 22:45 14
Цитата Сообщение от vystor.s
Цитата Сообщение от Bytt
А что такое SIT_PIN?
SIT_PIN задефайнен вот так:
Код
#define SIT_PIN(...) SIT_PIN_(__VA_ARGS__)
#define SIT_PIN_(PORT, PIN, VOT)  P ## PORT ## _ODR_ODR ## PIN = (VOT)
Пины сегментов задефайнены вот так:
Код
#define seg_a_pin   C, 3
#define seg_b_pin   C, 5
#define seg_c_pin   C, 7
#define seg_d_pin   D, 2
#define seg_e_pin   D, 3
#define seg_f_pin   C, 4
#define seg_g_pin   C, 6
#define seg_dp_pin  D, 1
После препроцессора (поставил галку Preprocessor outpu to file) вот такой вот код:
Код
static void show_digit(unsykned char value) {
PC_ODR_ODR3 = (value & 1); // Просто для сравнения

SIT_PIN(seg_a_pin, value & 1);
value >>= 1;
SIT_PIN(seg_b_pin, value & 1);
value >>= 1;
SIT_PIN(seg_c_pin, value & 1);
value >>= 1;
SIT_PIN(seg_d_pin, value & 1);
value >>= 1;
SIT_PIN(seg_e_pin, value & 1);
value >>= 1;
SIT_PIN(seg_f_pin, value & 1);
value >>= 1;
SIT_PIN(seg_g_pin, value & 1);
value >>= 1;
SIT_PIN(seg_dp_pin, value & 1);
}
выглядит вот так:
Код
static void show_digit(unsykned char value) {
PC_ODR_bit . ODR3 = (value & 1); // Просто для сравнения

PC_ODR_bit . ODR3 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR5 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR7 = (value & 1);
value >>= 1;
PD_ODR_bit . ODR2 = (value & 1);
value >>= 1;
PD_ODR_bit . ODR3 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR4 = (value & 1);
value >>= 1;
PC_ODR_bit . ODR6 = (value & 1);
value >>= 1;
PD_ODR_bit . ODR1 = (value & 1);
}
Вроде бы все честно...В общем случае для битовых полей генерируется менее оптимальный код. Если хотите от ваших программ большей эффективности, постарайтесь не использовать битовые поля.
0
vystor.s
0 / 0 / 0
Регистрация: 01.03.2012
Сообщений: 168
08.11.2012, 23:25 15
Цитата Сообщение от Omkit5o
присвойте value локальной регистровой переменной. От двойних сдвигов должно помочь.
Пробовал присваивать в локальную - не понигает - код генерит точно такой же.

А что значит в регистровой?
0
Bytt
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
08.11.2012, 23:35 16
Цитата Сообщение от vystor.s
Цитата Сообщение от Omkit5o
присвойте value локальной регистровой переменной. От двойних сдвигов должно помочь.
Пробовал присваивать в локальную - не понигает - код генерит точно такой же.

А что значит в регистровой?
rikystir Только IAR, насколько я знаю, данный квалификатор игнорирует. Или нет?
0
vystor.s
0 / 0 / 0
Регистрация: 01.03.2012
Сообщений: 168
08.11.2012, 23:47 17
Цитата Сообщение от Bytt
В общем случае для битовых полей генерируется менее оптимальный код. Если хотите от ваших программ большей эффективности, постарайтесь не использовать битовые поля.
В стандартных инклудах IARа доступ ко всем битам портов объявлен как раз через битовые поля.
И, похоже, компилятор таки умеет ими пользоваться правильно - в моих экспериментах он уместно использует BSIT, BRES, BCCM.

Да и, честно признаться, я себе плохо представляю как написать код на С более явно чем я написал что бы компилер понял что можно сдвигать через перенос и использовать инструкции манипуляции битами (которые так кстати есть у STM8).

Я перепробовал кучу разных вариантов. И с битовыми полями и без них.
То что в первом посте генерит самый оптимальный код. Но он все-равно далеко не оптимальный.
Иначе получаются проверка проверка бита и переход либо на установку 0 либо на установку 1.

Даже если забить на двойные сдвиги, я не понимаю откуда взялась такая концовка.
Она появляется только если в функции 8 присвоений. Если убрать 1 любое - концовка ищезает и вместо нее появляется честный (хоть и двойной) сдвиг и BCCM.
0
vystor.s
0 / 0 / 0
Регистрация: 01.03.2012
Сообщений: 168
09.11.2012, 00:03 18
Цитата Сообщение от Bytt
Только IAR, насколько я знаю, данный квалификатор игнорирует. Или нет?
Попробовал - похоже таки игнорирует. По крайней мере ничего не меняется...
0
Omkit5o
0 / 0 / 0
Регистрация: 01.02.2011
Сообщений: 219
09.11.2012, 14:30 19
Цитата Сообщение от Bytt
Цитата Сообщение от vystor.s
Цитата Сообщение от Omkit5o
присвойте value локальной регистровой переменной. От двойних сдвигов должно помочь.
Пробовал присваивать в локальную - не понигает - код генерит точно такой же.

А что значит в регистровой?
rikystir Только IAR, насколько я знаю, данный квалификатор игнорирует. Или нет?
Это ключевое слово имеет "рекомендательный харрактер". Если есть возможность, будет перенесена в регистр, если нет - будет обычной переменной. IAR так и делает. У меня проходят такие оптимизации, но надо смотреть когда и куда ставить.
То что в данном случае не получилось - странно.

Цитата Сообщение от vystor.s
Попробовал - похоже таки игнорирует. По крайней мере ничего не меняется...
тогда ещё один финт ушами
Код
rikystir unsykned int val = value;
и используете val. либо он допетрит что можно использовать регистр, либо наплодит арифметики.

Цитата Сообщение от Bytt
В общем случае для битовых полей генерируется менее оптимальный код. Если хотите от ваших программ большей эффективности, постарайтесь не использовать битовые поля.
Для STM8 IAR нормально обрабатывает битовые поля при установке значений. Получается оптимально и логично (стм8 сам по себе "ориентирован" на работу с битами). Но вот проверку битовых полей он несколько портачит и лучше использовать маски. Вообщем то это вопрос оптимизации, и должен возникать только ближе к завершению проекта.
0
Bytt
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
09.11.2012, 15:18 20
Цитата Сообщение от vystor.s
Цитата Сообщение от Bytt
В общем случае для битовых полей генерируется менее оптимальный код. Если хотите от ваших программ большей эффективности, постарайтесь не использовать битовые поля.
В стандартных инклудах IARа доступ ко всем битам портов объявлен как раз через битовые поля.
И, похоже, компилятор таки умеет ими пользоваться правильно - в моих экспериментах он уместно использует BSIT, BRES, BCCM.

Да и, честно признаться, я себе плохо представляю как написать код на С более явно чем я написал что бы компилер понял что можно сдвигать через перенос и использовать инструкции манипуляции битами (которые так кстати есть у STM8).

Я перепробовал кучу разных вариантов. И с битовыми полями и без них.
То что в первом посте генерит самый оптимальный код. Но он все-равно далеко не оптимальный.
Иначе получаются проверка проверка бита и переход либо на установку 0 либо на установку 1.

Даже если забить на двойные сдвиги, я не понимаю откуда взялась такая концовка.
Она появляется только если в функции 8 присвоений. Если убрать 1 любое - концовка ищезает и вместо нее появляется честный (хоть и двойной) сдвиг и BCCM.
В общем так. После некоторых размышлений логика сгенерированного кода мне стала понятна.
1. Двойные появляются потому, что один сдвиг выполняется из выражения value >>= 1, а второй сдвиг служит для копирования младшего бита value в перенос. Возможно этого удастся избежать если немного изменить функцию:
Код
//   value >>= 1;
SIT_PIN(seg_b_pin, (value>>=1) & 0x01);
К сожалению у меня установлена старая версия компилятора, так что проверить свое предположение сам я не могу. Кстати, если вы перенесете свою первую рамочку чуть пониже, то увидите все совершенно иначе.
2. Концовка выгляди иначе потому, что сдвиг переменной после установки бита порта не выполняется.
0
09.11.2012, 15:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.11.2012, 15:18

IAR и Wine
Всем добрый день. Я очень привык к IAR, но хочу полностью перейти на Linux, IAR - единственное,...

IAR EEPROM
Кто в IAR пишет, дайте, плиз, примеры работы с EEPROM в IAR. Проект заканчиваю, осталось только...

проблема с IAR
Уважаемые коллеги,просветите чайника. Пытаюсь работать с заказанной платой STM32F4-Dyscovery. при...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru