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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Рассуждения о _regvar и register, Вынесено из темы "Глюки компилятора.."
Qwertty
сообщение Jan 26 2008, 21:06
Сообщение #31


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(singlskv @ Jan 26 2008, 23:47) *
ну перечитываем тогда что ли пост №68 с которого и началась дискуссия:
так вот gcc его понимает и пользуется им для размещения переменных в регистрах...

Это просто я тогда не понял, о чем идет речь. Вот и спросил о register и IAR. Я тоже сижу на ГЦЦ, и проблем с размещением в регистрах не испытывал. Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра. Документированные грабли и не грабли вовсе, а так, особенности реализации smile.gif
Go to the top of the page
 
+Quote Post
SIA
сообщение Jan 26 2008, 21:17
Сообщение #32


Местный
***

Группа: Свой
Сообщений: 462
Регистрация: 26-06-07
Пользователь №: 28 723



Цитата(Qwertty @ Jan 27 2008, 00:06) *
Это просто я тогда не понял, о чем идет речь. Вот и спросил о register и IAR. Я тоже сижу на ГЦЦ, и проблем с размещением в регистрах не испытывал. Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра. Документированные грабли и не грабли вовсе, а так, особенности реализации smile.gif

Вообще говоря, не понимаю, зачем вообще при написании кода самим создавать себе проблемы - жестко указывать номера регистров для размещения переменных компилятору ? Выгоды практически никакой, а переносимость и надежность могут конкретно пострадать. Можно понять, если регистр особенный и с этой переменной надо что-то специфичное делать, но такой кусочек кода надо бы оформлять маленькой препроцессорной вставочкой/подпрограммкой, и подробно комментить.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 26 2008, 21:19
Сообщение #33


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Qwertty @ Jan 27 2008, 00:06) *
Правда номер регистра жестко не задаю. В документации к avr-libs указывается, что компилятор не контролирует конфликты в случае жесткого указания номера регистра.
Скажем так(насколько я ничего не понимаю...),
R2-R8 можно почти всегда безболезненно,
R9-R15 с контролем листинга,
регистр без указания месторасположения почти не имеет смысла...

по последнему пункту не уверен точно, тк в своих прогах предпочитаю месторасположение
указывать явно...

ЗЫ. конечно R2-R7 и R8-R15 ...
Go to the top of the page
 
+Quote Post
aesok
сообщение Jan 26 2008, 21:22
Сообщение #34


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Используя модификатор register вы просите компилятор разместить переменную в регистрах процессора, предполагая что таким образом получите более оптимальный код, но компилятор вправе игнорировать вашу просьбу, если сочтет генерируемый что код в результате будет хуже.

Используя код:
Код
register unsigned char counter asm("r3");

Вы заставляете компилятор разместить переменную counter в регистре r3 контроллера. И всю ответственность за этот поступок берете на себя.

В GCC полностью безопасно использовать регистры r2..r7 для объявления переменных. (С точки зрения компилятора, если только Вы сами не будете их изменять в ассемблерных вставках.) Возможно использование r8..r15, но эти регистры могут использоваться компилятором для передачи аргументов функций. Тоесть если все функции в проекте не передают в аргументах больше 10 байт, то регистры r8..r15 в вашем распоряжении. Если 12 байт то регистры r8-r9 будут использоваться компилятором, и переменная расположенная в них исказиться.
avr-libc-user-manual FAQ#3:How to permanently bind a variable to a register? и
FAQ#13 What registers are used by the C compiler?

Не используйте модификатор volatile с регистровыми переменными, его работа не гарантируется. К сожалению GCC не дает предупреждения, но это факт.

Анатолий.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 26 2008, 21:34
Сообщение #35


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(SIA @ Jan 27 2008, 00:17) *
Вообще говоря, не понимаю, зачем вообще при написании кода самим создавать себе проблемы - жестко указывать номера регистров для размещения переменных компилятору ? Выгоды практически никакой, а переносимость и надежность могут конкретно пострадать.
Выгода может быть в разы, в 2-3 раза легко...
О переносимости такого кода речи нет, это используется только на самом низком уровне и только
при условии что ты знаешь что делаешь.
Цитата
Можно понять, если регистр особенный и с этой переменной надо что-то специфичное делать, но такой кусочек кода надо бы оформлять маленькой препроцессорной вставочкой/подпрограммкой, и подробно комментить.
Вот пример моих коментариев из реального проекта:
Код
//-------------------------------------------------------------------
// Прерывание системного таймера
//   используются только регистровые переменные
//   никакие регистры не сохраняются
//   SREG не сохраняется
//   ОБЯЗАТЕЛЬНО ПРОВЕРИТЬ СГЕНЕРИРОВАННЫЙ КОД !!!!!!!!!!!!!!!!!!!!!
//-------------------------------------------------------------------

там всего 8 команд + reti
Но я точно знаю что я делаю.

Вы можете спросить почему это не написано на асм.
Потому что в качестве бонуса я получаю возможность обращаться к регистровым переменным
как к обычным С переменным в обычном С коде...
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Jan 26 2008, 21:38
Сообщение #36


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(singlskv @ Jan 27 2008, 00:19) *
регистр без указания месторасположения почти не имеет смысла...

по последнему пункту не уверен точно, тк в своих прогах предпочитаю месторасположение
указывать явно...

Имеет, хотя ГЦЦ и сам достаточно умный и может разместить переменную в регистре даже без указания.
Правда к глобальным это не относится, во всяком случае я такого не видел ни разу. А насчет смысла - например указатель выгодно хранить в регистре, тогда его изменении (++ или --) проходят гораздо быстрее. А так как такие операции обычно происходят в циклах, которые являются узким местом в программе, то использование регистров дает возможность сильно уменьшить время. При этом мне совсем не важно, в каких конкретно регистрах находится указатель. Правда оптимизатор и так обычно такой указатель разместит в регистрах smile.gif А вот явное месторасположение имеет смысл в основном для встроенного ассемблера.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 26 2008, 21:48
Сообщение #37


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Qwertty @ Jan 27 2008, 00:38) *
А насчет смысла - например указатель выгодно хранить в регистре, тогда его изменении (++ или --) проходят гораздо быстрее. А так как такие операции обычно происходят в циклах, которые являются узким местом в программе, то использование регистров дает возможность сильно уменьшить время.
Вот как раз для такой оптимизации использование register абслоютно беcсмысленно
и может даже(в принципе) помешать компилятору....
Для таких кусков кода нужно грамотно использовать локальные переменные.
Если хотите примеров, покажите кусок кода где register дал выигрыш, и я покажу
как нужно было написать просто с локальными переменными.
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Jan 26 2008, 21:55
Сообщение #38


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(singlskv @ Jan 27 2008, 00:34) *
Вы можете спросить почему это не написано на асм.
Потому что в качестве бонуса я получаю возможность обращаться к регистровым переменным
как к обычным С переменным в обычном С коде...

В свете того, что выше написал aesok о регистровых переменных и квалификаторе volatile, возможность обращаться к регистровым переменным, модифицируемым в прерывании, из С кода весьма сомнительна.

Цитата(singlskv @ Jan 27 2008, 00:48) *
Вот как раз для такой оптимизации использование register абслоютно беcсмысленно
и может даже(в принципе) помешать компилятору....
Для таких кусков кода нужно грамотно использовать локальные переменные.
Если хотите примеров, покажите кусок кода где register дал выигрыш, и я покажу
как нужно было написать просто с локальными переменными.

Это и есть локальная переменная. Я выше писал, что не объявляю глобальных переменных регистровыми. Сам по себе register даст выигрыщ только если локальных переменных много, тогда это будет подсказка оптимизатору о том, какие размещать в регистрах в первую очередь. Если локальная переменная одна, то она станет регистровой сама по себе smile.gif И перестанет показывать свое значение в студии sad.gif А вот помешать компилятору вряд-ли удастся, он просто молча проигнорирует register и все, даже варнинга не даст.
Go to the top of the page
 
+Quote Post
SIA
сообщение Jan 26 2008, 22:00
Сообщение #39


Местный
***

Группа: Свой
Сообщений: 462
Регистрация: 26-06-07
Пользователь №: 28 723



Код
//-------------------------------------------------------------------
// Прерывание системного таймера
//   используются только регистровые переменные
//   никакие регистры не сохраняются
//   SREG не сохраняется
//   ОБЯЗАТЕЛЬНО ПРОВЕРИТЬ СГЕНЕРИРОВАННЫЙ КОД !!!!!!!!!!!!!!!!!!!!!
//-------------------------------------------------------------------

там всего 8 команд + reti
Но я точно знаю что я делаю.


Так нельзя делать даже из самых лучших побуждений.
Код, работающий по прерыванию и при этом портящий регистры и статус процессора - нонсенс, т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных. Не говоря уже о том, что уменьшение числа регистров, доступных компилятору, ухудшает оптимизацию, и дополнительные загрузки-выгрузки легко съедят весь эффект, полученный в частной подпрограмме.

Я однажды еще на ассемблере делал системный таймер в регистре процессора для системы быстрой регистрации, но код отработки прерывания не изменял в процессоре НИЧЕГО, кроме регистра таймера.

Если хочется сэкономить такты - практичнее подумать над алгоритмом в целом или поменять МК, если экономится память - это вообще нонсенс, т.к. цена версий МК с разной памятью не сильно отличается. Чтобы окупить затраты на отладку такого "кода", потребуются многотысячные тиражи, и то не факт, что это рационально - резервов для апгрейда не останется.
Еще для ускорения при отработке прерываний можно использовать теневой банк регистров (дополнительные банки есть у многих МК, от 8051 и Z80 до PIC32).
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Jan 26 2008, 22:03
Сообщение #40


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(SIA @ Jan 27 2008, 01:00) *
т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных.

У AVR этого никогда не произойдет smile.gif
Я видел один раз похожий прием, правда на ассемблере - на Телесисах лежит проект генератора Л.И. Ридико. Там обработчик вообще начинается с адреса вектора и самая короткая ветка не сохраняет SREG. Но это сделано для того, чтобы выжать из контроллера все что можно и видимо такие задачи крайне редки. Хотя тоже имеют право на жизнь.

Сообщение отредактировал Qwertty - Jan 26 2008, 22:10
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 26 2008, 22:07
Сообщение #41


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Qwertty @ Jan 27 2008, 00:55) *
В свете того, что выше написал aesok о регистровых переменных и квалификаторе volatile, возможность обращаться к регистровым переменным, модифицируемым в прерывании, из С кода весьма сомнительна.
По большому счету, квалификаторы register и volatile одновременно не применимы.
При "жестком" расположении переменной в регистре volatile просто теряет смысл...
Я не знаю примеров в которых "жестко" заданная регистровая переменная может портиться.
Цитата
Это и есть локальная переменная. Я выше писал, что не объявляю глобальных переменных регистровыми. Сам по себе register даст выигрыщ только если локальных переменных много, тогда это будет подсказка оптимизатору о том, какие размещать в регистрах в первую очередь. Если локальная переменная одна, то она станет регистровой сама по себе smile.gif И перестанет показывать свое значение в студии sad.gif А вот помешать компилятору вряд-ли удастся, он просто молча проигнорирует register и все, даже варнинга не даст.
В таком варианте, согласен.
Go to the top of the page
 
+Quote Post
aesok
сообщение Jan 26 2008, 22:13
Сообщение #42


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(singlskv @ Jan 27 2008, 01:07) *
По большому счету, квалификаторы register и volatile одновременно не применимы.
При "жестком" расположении переменной в регистре volatile просто теряет смысл...
Я не знаю примеров в которых "жестко" заданная регистровая переменная может портиться.
В таком варианте, согласен.


Почитайте пост, там описана проблема:
http://electronix.ru/forum/index.php?showtopic=42140

GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть.

Анатолий.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jan 26 2008, 22:29
Сообщение #43


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(SIA @ Jan 27 2008, 01:00) *
Так нельзя делать даже из самых лучших побуждений.
Код, работающий по прерыванию и при этом портящий регистры и статус процессора - нонсенс, т.к. его исполнение может оказаться прервано другим таким же с большим приоритетом - с соответствующей порчей данных.
Может конечно и нельзя .... 07.gif
Но я точно знаю что я делаю.
используются только зарезервированные регистры и регистры переферии,
код написан таким образом что SREG просто не меняется,
напоминание "ПРОВЕРИТЬ КОД" именно про то, чтобы проверить что компилятор не начудил
и не вставил инструкции меняющие SREG.


Цитата(aesok @ Jan 27 2008, 01:13) *
Почитайте пост, там описана проблема:
http://electronix.ru/forum/index.php?showtopic=42140
GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть.
Я не только читал но и писал в той ветке...
Про проблемы с повтором констант я знаю, более того примерно с год назад я поднимал
этот вопрос на форуме (ссылку лень искать сейчас, что то типа"Проблемы оптимизации WinAVR").
У меня все проблемы сводились к тому что код оказывался просто очень не оптимальным.
У Вас есть пример кода для GCC который будет в такой ситуации некорректным ?
Go to the top of the page
 
+Quote Post
SIA
сообщение Jan 26 2008, 22:31
Сообщение #44


Местный
***

Группа: Свой
Сообщений: 462
Регистрация: 26-06-07
Пользователь №: 28 723



Цитата(singlskv @ Jan 27 2008, 01:17) *
Может конечно и нельзя .... 07.gif
Но я точно знаю что я делаю.
используются только зарезервированные регистры и регистры переферии,
код написан таким образом что SREG просто не меняется,
напоминание "ПРОВЕРИТЬ КОД" именно про то, чтобы проверить что компилятор не начудил
и не вставил инструкции меняющие SREG.

IMHO, это приемлемо только для очень маленького проекта, строк на 300-500. Более крупный при использовании таких методов становится слишком непрактичным.

p.s. Эпоху, когда экономили каждый такт, я еще застал. Но не думаю, что сейчас это правильно - проще взять более мощный процессор, они сейчас недороги.
Go to the top of the page
 
+Quote Post
aesok
сообщение Jan 26 2008, 23:39
Сообщение #45


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(singlskv @ Jan 27 2008, 01:29) *
Цитата
Почитайте пост, там описана проблема:
http://electronix.ru/forum/index.php?showtopic=42140
GCC ведет себя также. До веррсии 4.1 он выдавал предупреждение, потом перестал. Есть ключик чтобы его включть.

У Вас есть пример кода для GCC который будет в такой ситуации некорректным ?


Да нашел на www.avrfreaks.net.

Код
volatile register uint16_t s1 asm("r2");
ISR(INT0_vect)
{

   if(bit_is_set(PINC,0))    s1++;
   else            s1--;
}

int main{
//...
      sei();
   OCR0+=10;
   while(s1<10);
//...
}


Регистровая переменная объявлена как volatile, код на уровне оптимизации -Os:
Код

205:         sei();
SEI
208:         OCR0+=10;
IN      R24,0x31
SUBI    R24,0xF6
OUT     0x31,R24
MOVW    R24,R2  //!!!
209:         while(s3<10);
CPI     R24,0x0A
CPC     R25,R1  
BRCS    PC-0x02


Происходит копирование R2:R3 в R24:R25, и в цикле анализируеться копия переменой s1 в R24:R25, а не она сама в R2:R3.

Так что не используйте в GCC 'volatile register' переменые и добавте в свои макефайлы ключик '-Wvolatile-register-var'.

Если интересно почему GCC так работает то, можно почитать здесь: http://gcc.gnu.org/ml/gcc-patches/2005-11/msg00657.html

Анатолий.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th July 2025 - 14:16
Рейтинг@Mail.ru


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