|
Компилятор в IAR, ньюансы обращения к переменным |
|
|
|
Nov 22 2006, 02:23
|
Местный
  
Группа: Свой
Сообщений: 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 Спасибо заранее!
|
|
|
|
|
 |
Ответов
|
Nov 22 2006, 02:42
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
ИМХО потому что запись Код tmpByte <<= 1; на самом деле краткая и обозначает Код tmpByte = tmpByte << 1; Аналогично Код tmpByte |= tmp_bit; обозначает Код tmpByte = tmpByte | tmp_bit; Поскольку tmpByte является и источником-операндом и приемником результата, то компилятор вполне логично каждую команду раскладывает так, как ему предписано. А вот с включенной оптимизацией он возможно соптимизирует код к такому виду, который вы считаете нормальным.
|
|
|
|
|
Dec 18 2006, 16:58
|
Участник

Группа: Участник
Сообщений: 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 раза, однако! Никак оптимальным такой код не назовешь. Что скажете..?
|
|
|
|
|
Dec 19 2006, 23:17
|
Местный
  
Группа: Участник
Сообщений: 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;
|
|
|
|
|
Dec 20 2006, 08:16
|
Участник

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

|
Цитата(_Bill @ Dec 19 2006, 23:17)  Попробуйте так: Код if (TimeOut) TimeOut -= 1; Попробовал. Никакой разницы. Да оно в общем-то и понятно. Было бы удивительно, ведь с точки зрения "С" а--; и а -= 1; абсолютно идентичны.
|
|
|
|
|
Dec 20 2006, 11:50
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(Perepic @ Dec 20 2006, 08:16)  Цитата(_Bill @ Dec 19 2006, 23:17)  Попробуйте так: Код if (TimeOut) TimeOut -= 1; Попробовал. Никакой разницы. Да оно в общем-то и понятно. Было бы удивительно, ведь с точки зрения "С" а--; и а -= 1; абсолютно идентичны. Все правильно. Только компиляторы разные семантически одинаковые конструкции иногда транслируют по-разному. Поэтому всегда имеет смысл "повертеть" такую конструкцию с тем, чтобы увидеть в каких случаях компилятор сгенерирует наиболее оптимальный код. Если, конечно, есть в этом необходимость.
|
|
|
|
|
Dec 21 2006, 02:12
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(_Bill @ Dec 20 2006, 11:50)  Все правильно. Только компиляторы разные семантически одинаковые конструкции иногда транслируют по-разному. Поэтому всегда имеет смысл "повертеть" такую конструкцию с тем, чтобы увидеть в каких случаях компилятор сгенерирует наиболее оптимальный код. Если, конечно, есть в этом необходимость. И вот на этой приятной ноте и хочется спросить, - а стоит ли применять такие методы? Полазайте по форуму и Вы найдёте массу примеров таких ухищрений. Но в такой ситуации всегда остаётся вероятность того, что при смене версии компилятора или просто немного изменив окружающие операторы Вы, в следующей трансляции опять потеряете "золотую нить". Получается программирование на СИ с элементами ASMа. В том смысле что прога привязана к кристалу, сама к себе, к компилятору. Например высказывание одного человека в форуме (примерно так) "... я групирую и увязываю связанные данные в структуры и в п/п передаю указатель на структуру... ...С массивами вообще не работаю... .... получается очень эффективно...". Я совершенно согласен с автором. Ничего сложного в этом нет. Понятно что можно обратится к элементу байтового массива Arr[i] или *(Arr[0]+i), но где у этого край??? Можно и умножение сдвигами заменить и двинутся дальше. По идее эффективность работы с массивами должна после трансляции быть такой же как и при работе с указателями. Но этого нет. При больших массивах выигрыш от встроенной функции копирования или очистки массивов (приведенных выше) в разы! Очень существено. Хотя тот же компилятор запросто мог бы применить аналогичный приём! И ещё никто не ответил мне на следующий вопрос. Почему при совершенно свободной Flash памяти и установленном максимальном уровне оптимизации по скорости компилятор генерит такое значительное колличество вспомогательных подпрограмм? Что я делаю не так и как этого избежать. Я же на них inline поставить не могу. Где это задаётся? Мой пост прошу не относить к критическим в адрес компилятора. Компилятор мне нравится и претензий у меня к нему, фактически нет. Просто хочу лучше узнать его. И проанализировать разные подходы людей к программированию. Особенно учитывая Ваш опыт. С уважением.
|
|
|
|
|
Dec 21 2006, 12:07
|
Участник

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

|
Цитата(SasaVitebsk @ Dec 21 2006, 02:12)  И ещё никто не ответил мне на следующий вопрос. Почему при совершенно свободной Flash памяти и установленном максимальном уровне оптимизации по скорости компилятор генерит такое значительное колличество вспомогательных подпрограмм? Что я делаю не так и как этого избежать. Я же на них inline поставить не могу. Где это задаётся? Речь как я понял идет о перекрестных вызоывах. Полезная штука, кстати сказать, при незначительной потери в скорости, получается выигрыш от 10% и выше по объему кода. Одинаковые куски кода заменяются на подпрограммы. На этапе отладки я обычно отключаю. Ищите галочку "cross call" в закладке C++ -> Optimization.
|
|
|
|
|
Dec 26 2006, 11:15
|

Шаман
     
Группа: Модераторы
Сообщений: 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, то это относится к пользовательским функциям. Если компилятор сочтёт их достаточно короткими, то он их инлайнит.
|
|
|
|
Сообщений в этой теме
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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|