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

 
 
> Компилятор в 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
_Bill
сообщение Dec 21 2006, 16:30
Сообщение #8


Местный
***

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



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

Все правильно. Только компиляторы разные семантически одинаковые конструкции иногда транслируют по-разному. Поэтому всегда имеет смысл "повертеть" такую конструкцию с тем, чтобы увидеть в каких случаях компилятор сгенерирует наиболее оптимальный код. Если, конечно, есть в этом необходимость.


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

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

Тут нельзя сказать однозначно. Во-первых, мы так или иначе привязаны как контроллеру, с одной стороны, так и к инстументам для его программирования. И то, и другое нужно знать как можно лучше. Поэтому всякие эксперименты, позволяющие лучше узнать то, с чем работаешь, безусловно необходимы. Но...
Есть машинно-независимые способы оптимизации программ. Они всем известны. Это, прежде всего, более оптимальный алгоритм. Далее, выбор наиболее подходящей организации данных. Это и оптимизация программ на уровне ЯВУ. Опять же, понимание того, как компилятор генерирует код для тех или иных конструкций языка, даст возможность создать более оптимальную программу. Например, использование оператора do while является более оптимальным по сравнению с оператором while. Сравнение с нулем даст более оптимальный код, чем сравнении с константой. То есть
Код
      while (--i != 0) ...

более эффективно, чем
Код
      while (++i != CONST) ...

Таких примеров можно привести сколько угодно. Однако, эффективные программы часто получаются менее понятными и читабельными, особенно для посторонних людей. И если мы в погоне за оптимальностью напишем такой код, который будет труден для понимания и сопровождения, и (возможно) для переноса на другую платформу, а выигрыш даст лишь пару-другую инструкций, или пару микросекунд, то стоит ли тратить на это время? Если же скорость работы программы или ее размер являются критичными, то может лучше написать критичные по этим параметрам модули на ассемблере? И такие модули могут быть более понятными, поскольку программист использует все возможности архитектуры процессора. Ему не надо становиться на уши, чтобы описать с помощью инструкций процессора то, чего средствами Си описать или очень трудно, или вообще невозможно. Использование же всяких ассемблерных вставок, как правило, не дает той эффективности, какую желают получить, а программа становится бесформенной, трудной для понимания и сопровождения.
Короче говоря, во всем нужна мера.
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
||- - Perepic   Цитата(SasaVitebsk @ Dec 21 2006, 02:12) ...   Dec 21 2006, 12:07
|||- - HARMHARM   Цитата(Perepic @ Dec 21 2006, 11:07) Цита...   Dec 21 2006, 18:48
|||- - IgorKossak   Цитата(HARMHARM @ Dec 21 2006, 17:48) Цит...   Dec 26 2006, 11:15
|- - 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 Текстовая версия Сейчас: 24th July 2025 - 01:58
Рейтинг@Mail.ru


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