реклама на сайте
подробности

 
 
> Компилятор в IAR, ньюансы обращения к переменным
king2
сообщение Nov 22 2006, 02:23
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 255
Регистрация: 17-08-06
Из: Москва
Пользователь №: 19 646



Снова не пойму как IAR работает с переменными...
Оптимизация вся выключена, дабы не влиять излишне.

Имеем такой вот код:

Код
    111                    tmpByte <<= 1;
   \   00000464   9100....           LDS     R16, tmpByte
   \   00000468   0F00               LSL     R16
   \   0000046A   9300....           STS     tmpByte, R16
    112                    tmpByte |= tmp_bit;
   \   0000046E   8108               LD      R16, Y
   \   00000470   ....               LDI     R30, LOW(tmpByte)
   \   00000472   ....               LDI     R31, (tmpByte) >> 8
   \   00000474   8110               LD      R17, Z
   \   00000476   2B10               OR      R17, R16
   \   00000478   8310               ST      Z, R17


Почему компилятор, имея в регистре значение переменной, и следующую операцию с ней же, тем не менее сначала сохраняет ее, а потом загружает? Переменная не volatile.
Почему в первом и втором случае обращение к одной и той же переменной делается по разному??
Как избежать такого извращенного обращения к переменным?

Эквивалентный (нормальный) код:
Код
    114                    tmpByte = (tmpByte<<1) | tmp_bit;
   \   0000047A   9100....           LDS     R16, tmpByte
   \   0000047E   0F00               LSL     R16
   \   00000480   8118               LD      R17, Y
   \   00000482   2B10               OR      R17, R16
   \   00000484   9310....           STS     tmpByte, R17


Спасибо заранее!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
rezident
сообщение Nov 22 2006, 02:42
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



ИМХО потому что запись
Код
tmpByte <<= 1;

на самом деле краткая и обозначает
Код
tmpByte = tmpByte << 1;

Аналогично
Код
tmpByte |= tmp_bit;

обозначает
Код
tmpByte = tmpByte | tmp_bit;

Поскольку tmpByte является и источником-операндом и приемником результата, то компилятор вполне логично каждую команду раскладывает так, как ему предписано. А вот с включенной оптимизацией он возможно соптимизирует код к такому виду, который вы считаете нормальным.
Go to the top of the page
 
+Quote Post
Perepic
сообщение Dec 18 2006, 16:58
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 14-08-06
Пользователь №: 19 528



Цитата(rezident @ Nov 22 2006, 02:42) *
ИМХО потому что запись
Код
tmpByte <<= 1;

на самом деле краткая и обозначает
Код
tmpByte = tmpByte << 1;


Поскольку tmpByte является и источником-операндом и приемником результата, то компилятор вполне логично каждую команду раскладывает так, как ему предписано. А вот с включенной оптимизацией он возможно соптимизирует код к такому виду, который вы считаете нормальным.


Интересно мыслите, однако! Как вам такой пример, я честно говоря до сих пор не понимаю отчего IAR 4.11a так себя ведет. Оптимизация включена на максимум, окромя "cross-call"
Код
UCHAR TimeOut;            // глобальная переменная

__interrupt void TimerInt()
{
    if(TimeOut) TimeOut--;
};

Все это компилится в ледующий код:
Код
     LDS     R16, TimeOut
     TST     R16
     BREQ    0x392
  
    LDI     R30,0x9F
    LDI     R31,0x02
    LD      R16,Z
    DEC     R16
    ST      Z,R16

Сохраниение и восстановление стека я опустил.
Что мы видим? Грузим переменную, проверяем ее, если условие выполняется, опять ее же грузим (ЗАЧЕМ?), причем засоряя адресные регистры, модифицируем и сохраняем. В результате имеем 3 лишних комманды + 4 для сохраниения-восстановления адресных регистров. Более чем в 2 раза, однако! Никак оптимальным такой код не назовешь. Что скажете..?
Go to the top of the page
 
+Quote Post
_Bill
сообщение Dec 19 2006, 23:17
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Perepic @ Dec 18 2006, 16:58) *
Цитата(rezident @ Nov 22 2006, 02:42) *

ИМХО потому что запись
Код
tmpByte <<= 1;

на самом деле краткая и обозначает
Код
tmpByte = tmpByte << 1;


Поскольку tmpByte является и источником-операндом и приемником результата, то компилятор вполне логично каждую команду раскладывает так, как ему предписано. А вот с включенной оптимизацией он возможно соптимизирует код к такому виду, который вы считаете нормальным.


Интересно мыслите, однако! Как вам такой пример, я честно говоря до сих пор не понимаю отчего IAR 4.11a так себя ведет. Оптимизация включена на максимум, окромя "cross-call"
Код
UCHAR TimeOut;            // глобальная переменная

__interrupt void TimerInt()
{
    if(TimeOut) TimeOut--;
};

Все это компилится в ледующий код:
Код
     LDS     R16, TimeOut
     TST     R16
     BREQ    0x392
  
    LDI     R30,0x9F
    LDI     R31,0x02
    LD      R16,Z
    DEC     R16
    ST      Z,R16

Сохраниение и восстановление стека я опустил.
Что мы видим? Грузим переменную, проверяем ее, если условие выполняется, опять ее же грузим (ЗАЧЕМ?), причем засоряя адресные регистры, модифицируем и сохраняем. В результате имеем 3 лишних комманды + 4 для сохраниения-восстановления адресных регистров. Более чем в 2 раза, однако! Никак оптимальным такой код не назовешь. Что скажете..?

Попробуйте так:
Код
     if (TimeOut)
           TimeOut -= 1;
Go to the top of the page
 
+Quote Post
Perepic
сообщение Dec 20 2006, 08:16
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 14-08-06
Пользователь №: 19 528



Цитата(_Bill @ Dec 19 2006, 23:17) *
Попробуйте так:
Код
     if (TimeOut)
           TimeOut -= 1;

Попробовал. Никакой разницы. Да оно в общем-то и понятно. Было бы удивительно, ведь с точки зрения "С" а--; и а -= 1; абсолютно идентичны.
Go to the top of the page
 
+Quote Post
_Bill
сообщение Dec 20 2006, 11:50
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Perepic @ Dec 20 2006, 08:16) *
Цитата(_Bill @ Dec 19 2006, 23:17) *

Попробуйте так:
Код
     if (TimeOut)
           TimeOut -= 1;

Попробовал. Никакой разницы. Да оно в общем-то и понятно. Было бы удивительно, ведь с точки зрения "С" а--; и а -= 1; абсолютно идентичны.

Все правильно. Только компиляторы разные семантически одинаковые конструкции иногда транслируют по-разному. Поэтому всегда имеет смысл "повертеть" такую конструкцию с тем, чтобы увидеть в каких случаях компилятор сгенерирует наиболее оптимальный код. Если, конечно, есть в этом необходимость.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Dec 21 2006, 02:12
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(_Bill @ Dec 20 2006, 11:50) *
Все правильно. Только компиляторы разные семантически одинаковые конструкции иногда транслируют по-разному. Поэтому всегда имеет смысл "повертеть" такую конструкцию с тем, чтобы увидеть в каких случаях компилятор сгенерирует наиболее оптимальный код. Если, конечно, есть в этом необходимость.


И вот на этой приятной ноте и хочется спросить, - а стоит ли применять такие методы?

Полазайте по форуму и Вы найдёте массу примеров таких ухищрений. Но в такой ситуации всегда остаётся вероятность того, что при смене версии компилятора или просто немного изменив окружающие операторы Вы, в следующей трансляции опять потеряете "золотую нить". Получается программирование на СИ с элементами ASMа. В том смысле что прога привязана к кристалу, сама к себе, к компилятору.

Например высказывание одного человека в форуме (примерно так) "... я групирую и увязываю связанные данные в структуры и в п/п передаю указатель на структуру... ...С массивами вообще не работаю... .... получается очень эффективно...". Я совершенно согласен с автором. Ничего сложного в этом нет. Понятно что можно обратится к элементу байтового массива Arr[i] или *(Arr[0]+i), но где у этого край??? Можно и умножение сдвигами заменить и двинутся дальше.

По идее эффективность работы с массивами должна после трансляции быть такой же как и при работе с указателями. Но этого нет. При больших массивах выигрыш от встроенной функции копирования или очистки массивов (приведенных выше) в разы! Очень существено. Хотя тот же компилятор запросто мог бы применить аналогичный приём!


И ещё никто не ответил мне на следующий вопрос. Почему при совершенно свободной Flash памяти и установленном максимальном уровне оптимизации по скорости компилятор генерит такое значительное колличество вспомогательных подпрограмм? Что я делаю не так и как этого избежать. Я же на них inline поставить не могу. Где это задаётся?

Мой пост прошу не относить к критическим в адрес компилятора. Компилятор мне нравится и претензий у меня к нему, фактически нет. Просто хочу лучше узнать его. И проанализировать разные подходы людей к программированию. Особенно учитывая Ваш опыт.

С уважением.
Go to the top of the page
 
+Quote Post
Perepic
сообщение Dec 21 2006, 12:07
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 14-08-06
Пользователь №: 19 528



Цитата(SasaVitebsk @ Dec 21 2006, 02:12) *
И ещё никто не ответил мне на следующий вопрос. Почему при совершенно свободной Flash памяти и установленном максимальном уровне оптимизации по скорости компилятор генерит такое значительное колличество вспомогательных подпрограмм? Что я делаю не так и как этого избежать. Я же на них inline поставить не могу. Где это задаётся?

Речь как я понял идет о перекрестных вызоывах. Полезная штука, кстати сказать, при незначительной потери в скорости, получается выигрыш от 10% и выше по объему кода. Одинаковые куски кода заменяются на подпрограммы. На этапе отладки я обычно отключаю. Ищите галочку "cross call" в закладке C++ -> Optimization.
Go to the top of the page
 
+Quote Post
HARMHARM
сообщение Dec 21 2006, 18:48
Сообщение #9


читатель даташитов
****

Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999



Цитата(Perepic @ Dec 21 2006, 11:07) *
Цитата(SasaVitebsk @ Dec 21 2006, 02:12) *

И ещё никто не ответил мне на следующий вопрос. Почему при совершенно свободной Flash памяти и установленном максимальном уровне оптимизации по скорости компилятор генерит такое значительное колличество вспомогательных подпрограмм? Что я делаю не так и как этого избежать. Я же на них inline поставить не могу. Где это задаётся?

Речь как я понял идет о перекрестных вызоывах. Полезная штука, кстати сказать, при незначительной потери в скорости, получается выигрыш от 10% и выше по объему кода. Одинаковые куски кода заменяются на подпрограммы. На этапе отладки я обычно отключаю. Ищите галочку "cross call" в закладке C++ -> Optimization.


Я могу ошибаться, но речь идет о Function Inlining. Cross Call делает как раз "обратную" операцию - выносит из функций общие блоки в отдельные вызовы.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Dec 26 2006, 11:15
Сообщение #10


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(HARMHARM @ Dec 21 2006, 17:48) *
Цитата(Perepic @ Dec 21 2006, 11:07) *

Цитата(SasaVitebsk @ Dec 21 2006, 02:12) *

И ещё никто не ответил мне на следующий вопрос. Почему при совершенно свободной Flash памяти и установленном максимальном уровне оптимизации по скорости компилятор генерит такое значительное колличество вспомогательных подпрограмм? Что я делаю не так и как этого избежать. Я же на них inline поставить не могу. Где это задаётся?

Речь как я понял идет о перекрестных вызоывах. Полезная штука, кстати сказать, при незначительной потери в скорости, получается выигрыш от 10% и выше по объему кода. Одинаковые куски кода заменяются на подпрограммы. На этапе отладки я обычно отключаю. Ищите галочку "cross call" в закладке C++ -> Optimization.


Я могу ошибаться, но речь идет о Function Inlining. Cross Call делает как раз "обратную" операцию - выносит из функций общие блоки в отдельные вызовы.

Вы действительно ошибаетесь.
Речь была о том, что cross call оптимизацию предлагается отключить, чтобы компилятор не создавал много вложенных функций. При максимальном уровне оптимизации эта опция включена по умолчанию.
Что касается Function Inlining, то это относится к пользовательским функциям. Если компилятор сочтёт их достаточно короткими, то он их инлайнит.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- king2   Компилятор в IAR   Nov 22 2006, 02:23
|- - king2   А почему оно в одном случае загружает переменную и...   Nov 22 2006, 03:26
||- - IgorKossak   Цитата(king2 @ Nov 22 2006, 02:26) А поче...   Nov 22 2006, 10:50
||- - dxp   ЦитатаЦитата(king2 @ Nov 22 2006, 02:26) ...   Nov 22 2006, 11:57
||- - _Bill   Цитата(SasaVitebsk @ Dec 21 2006, 02:12) ...   Dec 21 2006, 16:30
|- - Rst7   Цитата(Perepic @ Dec 18 2006, 15:58) Инте...   Dec 26 2006, 16:09
|- - zltigo   Цитата(Rst7 @ Dec 26 2006, 15:09) Имеет с...   Dec 26 2006, 16:27
||- - Rst7   Цитата(zltigo @ Dec 26 2006, 15:27) Цитат...   Dec 26 2006, 16:31
||- - _Bill   Цитата(zltigo @ Dec 26 2006, 16:27) Цитат...   Dec 27 2006, 10:27
||- - IgorKossak   Цитата(_Bill @ Dec 27 2006, 09:27) Вообще...   Dec 27 2006, 14:18
||- - dxp   Цитата(IgorKossak @ Dec 27 2006, 17:18) Ц...   Dec 27 2006, 14:48
||- - zltigo   Цитата(dxp @ Dec 27 2006, 13:48) Иными сл...   Dec 27 2006, 15:41
|||- - Сергей Борщ   Цитата(zltigo @ Dec 27 2006, 14:41) Цитат...   Jan 7 2007, 01:33
|||- - zltigo   Цитата(Сергей Борщ @ Jan 7 2007, 00:33) P...   Jan 7 2007, 02:03
||- - _Bill   Цитата(dxp @ Dec 27 2006, 14:48) Цитата(I...   Dec 27 2006, 19:03
||- - dxp   Цитата(_Bill @ Dec 27 2006, 22:03) Это не...   Dec 28 2006, 07:32
||- - zltigo   Цитата(dxp @ Dec 28 2006, 06:32) И как, н...   Dec 28 2006, 12:13
|||- - IgorKossak   Цитата(dxp @ Dec 28 2006, 06:32) И как, н...   Dec 28 2006, 12:29
||- - _Bill   Цитата(dxp @ Dec 28 2006, 07:32) И как, н...   Jan 2 2007, 22:33
||- - SasaVitebsk   Цитата(dxp @ Dec 28 2006, 08:32) Борланд ...   Jan 4 2007, 00:22
||- - _Bill   Цитата(SasaVitebsk @ Jan 4 2007, 00:22) Ц...   Jan 4 2007, 23:20
||- - SasaVitebsk   Цитата(_Bill @ Jan 5 2007, 00:20) Не стои...   Jan 5 2007, 03:58
|- - Perepic   Цитата(Rst7 @ Dec 26 2006, 16:09) В принц...   Dec 27 2006, 08:44
- - SasaVitebsk   На этот раз для меня не понятный момент. До этого ...   Dec 7 2006, 23:06
|- - rezident   Цитата(SasaVitebsk @ Dec 8 2006, 01:06) С...   Dec 8 2006, 01:01
|- - zltigo   Цитата(rezident @ Dec 8 2006, 00:01) заме...   Dec 8 2006, 02:52
- - SasaVitebsk   Информация к размышлению. Объявление не менял. Пом...   Dec 8 2006, 03:12
|- - _Bill   Цитата(SasaVitebsk @ Dec 8 2006, 03:12) И...   Dec 8 2006, 12:16
|- - SasaVitebsk   Цитата(_Bill @ Dec 8 2006, 12:16) Все пра...   Dec 8 2006, 13:24
|- - _Bill   Цитата(SasaVitebsk @ Dec 8 2006, 13:24) В...   Dec 8 2006, 17:31
- - SasaVitebsk   Спасибо, разъяснили доступно. Извините за наглость...   Dec 11 2006, 21:34
|- - zltigo   Цитата(SasaVitebsk @ Dec 11 2006, 20:34) ...   Dec 11 2006, 22:38
- - Perepic   Или вот еще, тоже шедевр. Блин, чем больше в дизас...   Dec 18 2006, 18:01
|- - dxp   Цитата(Perepic @ Dec 18 2006, 21:01) Или ...   Dec 19 2006, 09:52
|- - Perepic   Цитата(dxp @ Dec 19 2006, 09:52) Код, кот...   Dec 19 2006, 11:29
- - SasaVitebsk   Тем не менее местами просто сказка и песня! ...   Dec 18 2006, 23:36


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 21:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.01535 секунд с 7
ELECTRONIX ©2004-2016