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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Инкремент указателя и оптимизация
Rash
сообщение Oct 1 2015, 13:29
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



День добрый.

Столкнулся с проблемой оптимизации, при инкременте указателя когда 2 строчки подряд. Оптимизация макс. по скорости. IAR ARM 7.40.3. Мк STMF4
Код
static void _setup_resp_ready(uint8_t** ppData_rx, bool allow_addr, uint8_t** ppData_tx)
{
  if(allow_addr != false)
    *(*(volatile uint_setup_addr_t**)&(*ppData_tx))++ = setup_addr;
  
  // !!! если NOP нет, то код будет оптимизирован
  __ASM("NOP");
    
   *((*ppData_tx)++) = *((*ppData_rx)++);
  
  return;
}

Прим. uint_setup_addr_t - задаётся тип, на данный момент uint16_t


скрины ассемблера
без оптимизации

макс. оптимизация по скорости

макс. оптимизация по скорости + NOP


Вопрос, возможно ли сделать запись чтобы не оптимизировался инкремент указателя? NOP конечно не критичен, но костыль. Отключить оптимизацию только для ф-ции не рассматриваю, т.к. подобные записи оформил виде макросов и могут быть в разных участках кода
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 1 2015, 13:43
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Многабукаффниасилил.
Я не пойму, жалоба на некорректный код, так как исчез инкремент, который никак не должен исчезать?
Если так, то такой вопрос: а вы уверены, что у вас исходник корректный? Что там, где надо, написано volatile и так далее? Потому что из приведённых отрывков этого совсем не видно.
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 1 2015, 16:50
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



да вроде не так много букв ). Проблема в том, что исчезает инкремент, второй скрин, если между строчками где идёт присваивание по одному и тому же указателю с инкрементом поставить NOP, то всё хорошо, скрин 3 (как и без оптимизации). volatile по типу поставил, хотя он не влияет.

Жалобы нет, т.к. код мой.
А вопрос как написать тоже, но без NOPа?
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 1 2015, 16:53
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Rash @ Oct 1 2015, 19:50) *
А вопрос как написать тоже, но без NOPа?

Зачем?
Ведь нет жалобы:
Цитата(Rash @ Oct 1 2015, 19:50) *
Жалобы нет

То есть всё нормально. Честно, не понимаю.
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 1 2015, 17:08
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



1. Не нравятся костыли в любом виде, в данном случае NOP.
2. Нет гарантии, что в следующий раз я могу что то не учесть, подобной записью.
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 1 2015, 17:43
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Вы не ответили на важный вопрос: "жалоба на некорректный код, так как исчез инкремент, который никак не должен исчезать?"
Да или нет?
От этого многое зависит.
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 1 2015, 17:51
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



жалоба на то, что исчез инкремент, который не должен исчезать
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 1 2015, 18:13
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Rash @ Oct 1 2015, 20:51) *
жалоба на то, что исчез инкремент, который не должен исчезать

Ну наконец-то.
Дальше надо понять, где у вас ошибка в коде (что очень вероятно) или где глючит компилятор (что весьма маловероятно). Потому что какой-то левый NOP - это не исправление ошибки в коде, а танец с бубном. И без понимания происходящего нежелательный сценарий повторится снова в неожиданном месте.
А вот понять, где ошибка, я точно не смогу, потому что приведён мелкий кусочек кода.
Ну а если покажете мегапростыню кода, то не обещаю, что буду в ней разбираться laughing.gif

UPDATE:
Забыл спросить. Жалоба только на то, что код в окне дизассемблера выглядит не так, как хотелось бы? Или реально программа работает не так, как задумано?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 1 2015, 18:31
Сообщение #9


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



да там наверное нездоровый упор на CSE.
просто сделать через добавление локальных переменных - попустит дерево синтаксиса и станет код вменяемым
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 1 2015, 18:41
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(_Pasha @ Oct 1 2015, 21:31) *
да там наверное нездоровый упор на CSE.
просто сделать через добавление локальных переменных - попустит дерево синтаксиса и станет код вменяемым

То есть уже установлено, что компилятор виноват. А если бы были судьёй, то всех расстреливали бы без следствия?
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 1 2015, 19:09
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



Цитата(scifi @ Oct 1 2015, 21:13) *
Жалоба только на то, что код в окне дизассемблера выглядит не так, как хотелось бы? Или реально программа работает не так, как задумано?


Программа работает как задумано, без оптимизации или при добавлении NOP.
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 1 2015, 19:17
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Rash @ Oct 1 2015, 22:09) *
Программа работает как задумано, без оптимизации или при добавлении NOP.

Обычное дело, если не понимать, что такое volatile, и где его нужно применять.
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 1 2015, 19:23
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



естественно, стоит при определении типа на указатель, куда уж не правильней
Go to the top of the page
 
+Quote Post
Valentine Logino...
сообщение Oct 2 2015, 06:52
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 78
Регистрация: 7-04-10
Из: Пушкино
Пользователь №: 56 462



Вам бы не полениться и сделать код читаемым, как например ввести дополнительные переменные. Оптимизация всё уберет, зато сам код и дизасм читать легче станет.
Очень очень очень некрасивый код:
Цитата
*((*ppData_tx)++) = *((*ppData_rx)++);
Go to the top of the page
 
+Quote Post
megajohn
сообщение Oct 2 2015, 07:16
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(Rash @ Oct 1 2015, 23:23) *
естественно, стоит при определении типа на указатель, куда уж не правильней

я так понимаю: указатель1->указатель2->данные и ваш volatile относится к данным, а не к указателям
Но могу ошибаться


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 2 2015, 07:27
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Кстати, безотносительно к тому, есть ли там volatile и в правильных ли местах, важно следующее:
У вас в программе есть прерывания и/или многопоточность (т.н. RTOS)? Потому что volatile только в этом случае имеет значение.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 2 2015, 08:12
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (Rash @ Oct 1 2015, 16:29) *
*(*(volatile uint_setup_addr_t**)&(*ppData_tx))++ = setup_addr;

Эта строчка есть абсолютный говнокод. Рассуждать, как компилятор должен говнокод компилировать, можно бесконечно.
Но без потытки сбить оптимизацию квалификатором volatile, любые инкременты переменной по указателю должны безусловно выбрасываться, как бесполезные. Что и сделано.
С volatile оптимизация может быть порушена.
Напишите, что надо делать компилятору четко. Но начните с попытки объяснить СЕБЕ.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Valentine Logino...
сообщение Oct 2 2015, 10:27
Сообщение #18


Частый гость
**

Группа: Участник
Сообщений: 78
Регистрация: 7-04-10
Из: Пушкино
Пользователь №: 56 462



Цитата(megajohn @ Oct 2 2015, 10:16) *
я так понимаю: указатель1->указатель2->данные и ваш volatile относится к данным, а не к указателям
Но могу ошибаться

К данным. Читается справа налево. Указатель на волатайл переменную типа бла-бла.
Цитата
volatile uint_setup_addr_t*
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Oct 2 2015, 11:06
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



*((*ppData_tx)++) = *((*ppData_rx)++);
Вообще это изменение одной переменной между двумя точками следования. Это в свою очередь UB. Поэтому компилятор прав, вы - нет. Пишите подобное с временной переменной. Это работает в отладке потому что там компилятор что видит, то и поёт. С нопом это работает по счастливой случайности, из-за особенностей оптимизации конкретным компилятором.

Сообщение отредактировал Kabdim - Oct 2 2015, 11:08
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 2 2015, 11:07
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



многопоточности нет (RTOS тоже), раньше код был с разделением взятия переменной и инкрементом указателя, работало с оптимизацией и без. решил записать всё в одну строчку, для компактности и чтобы сделать макрос. Нет проблемы записать по другому с доп. переменной и т.п., хотелось записать одной строчкой.

По поводу говнокода, каждому своё, тогда и DSP Lib от ARM тоже говнокод, там такие записи встречаются.
Найти ошибку будет сложнее, но эта запись как результат сворачивая из нескольких записей на уже отлаженном коде.

Цитата(Kabdim @ Oct 2 2015, 14:06) *
*((*ppData_tx)++) = *((*ppData_rx)++);
Вообще это изменение одной переменной между двумя точками следования. Это в свою очередь UB. Поэтому компилятор прав, вы - нет. Пишите подобное с временной переменной. Это работает в отладке потому что там компилятор что видит, то и поёт. С нопом это работает по счастливой случайности, из-за особенностей оптимизации конкретным компилятором.


переменная тут не меняется, она копируется из _rx в _tx, а адреса буферов меняются

переменные нигде не меняются, меняется (инкрементируется) только указатель на входные буфера
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Oct 2 2015, 11:12
Сообщение #21


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(Rash @ Oct 2 2015, 14:07) *
переменная тут не меняется, она копируется из _rx в _tx, а адреса буферов меняются

Прошу прощения, проглядел.
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 2 2015, 11:43
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Rash @ Oct 2 2015, 14:07) *
многопоточности нет (RTOS тоже)

Тогда зачем там volatile? Взаимодействие с аппаратными регистрами?

Чтобы сделать вывод, что это компилятор виноват, в идеале хорошо бы попытаться получить минимальную программу (легко обозримую), в которой проблема по-прежнему проявляется. Потому что всё-таки гораздо чаще оказывается, что виноват автор кода, а не компилятор.
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 2 2015, 11:56
Сообщение #23


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



компилятор я нигде не обвинял, а только спрашивал, что не так, в расчёте, что укажут на ошибку или я смогу понять где она. С volatile или без результат одинаковый, предполагал, что он относится к указателю, а не к значению. Позже попробую другие вариации попроще.
Go to the top of the page
 
+Quote Post
scifi
сообщение Oct 2 2015, 14:20
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Rash @ Oct 2 2015, 14:56) *
компилятор я нигде не обвинял

А можно было бы. Изредка и он виноват. Я сталкивался не единожды.

Цитата(Rash @ Oct 2 2015, 14:56) *
спрашивал, что не так, в расчёте, что укажут на ошибку или я смогу понять где она

Увы, не получится. Вы привели очень маленький кусок кода, собака легко могла порыться совсем в другом месте программы.

Цитата(Rash @ Oct 2 2015, 14:56) *
С volatile или без результат одинаковый...

А всё-таки, поясните, зачем там volatile? Если нет RTOS, прерываний и аппаратных регистров, то volatile ничего не изменит.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 2 2015, 15:51
Сообщение #25


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



rolleyes.gif я правильно перевел с птичьего языка на норм.?
Код
static void _setup_resp_ready(uint8_t** ppData_rx, bool allow_addr, uint8_t** ppData_tx)
{

uint8_t *ptx = *ppData_tx;
uint8_t *prx = *ppData_rx;
  if(allow_addr != false)
       *(volatile uint_setup_addr_t *)ptx++ = setup_addr;
   *ptx++ = *prx++;  
return;
}


Цитата(scifi @ Oct 1 2015, 21:41) *
То есть уже установлено, что компилятор виноват. А если бы были судьёй, то всех расстреливали бы без следствия?

???
Go to the top of the page
 
+Quote Post
Rash
сообщение Oct 2 2015, 20:09
Сообщение #26


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



scifi, мне интересно, что вас задел этот volatile или слово жалоба? через volatile объявляю только приведение типов по указателю, в книжках читал про это. Прерывание есть, какая реальная программа без прерываний. Ещё на время отладки volatile объявляю float, чтобы watch отображался.

_Pasha, ну на птичий язык не совсем тянет, хотя запись с указателями перегружена для непосвящённых biggrin.gif
По записи вроде всё верно, хотя не проверял, до понедельника не на чем. Но смысл не постоянно писать такими громоздкими записями, а завернуть их в макросы или для противников макросов в inline функции и использовать
это макрос один
Код
*(*(volatile uint_setup_addr_t**)&(*ppData_tx))++ = setup_addr;

это второй
Код
*((*ppData_tx)++)

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

немного OFFTOP:
Другой случай где понадобился NOP, это для анализатора стека. При максимальной оптимизации по скорости (на других не пробовал) в switch вызывались различные ф-ции в зависимости значение case. Все вызовы ф-ций при этом подменялись с CALL на JMP (это на AVR) и анализатор выдавал предупреждение о косвенном вызове и не мог составить дерево вызовов. Причём ни прагмой, ни описанием в файле конфигурации, я так и не смог указать правильное дерево вызовов для данного случая. Но если в конце перед выходом из ф-ции (после switch) поставить NOP такой подмены не происходит и анализатор нормально работает.
Естественно, на работоспособность программы это не влияет, но анализатор хорошая штука чего б не использовать.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 3 2015, 05:48
Сообщение #27


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Rash @ Oct 2 2015, 23:09) *
По записи вроде всё верно, хотя не проверял, до понедельника не на чем. Но смысл не постоянно писать такими громоздкими записями, а завернуть их в макросы или для противников макросов в inline функции и использовать

1. Не все там верно, нужно же отразить модификацию собственно указателей, т.е. в конце добавить
Код
*ppData_tx = ptx;
*ppData_rx = prx;


2. Ход мыслей понятен, но имхо такое, что нет смысла бояться локальных переменных даже в таком случае.
Т.е. в случае с макросом - обернуть его в do{}while(0) и создавать столько локальных перем. сколько нужно.

3. Не все компиляторы, что существуют, - одинаково хорошие sm.gif и если даже такой не сильно тяжелой строкой удалось вогнать его в багу, - повод задуматься, стоит ли так закручивать сюжет. Если создание лишних сущностей отдать на откуп компилю, совсем не факт, что он справится с этим.
я недавно написал под SDCC, типа поиграться решил
Код
crc = (crc >> 1)^((crc & 1)? 0x8C:0);

так там вообще неправильный код сгенерировался.
пришлось исправить на
Код
crc = ((crc & 1)? 0x8C:0) ^ (crc >> 1);

вот те на, CSE smile3046.gif
но то sdcc. милость к падшим тсз нада проявлять biggrin.gif
Go to the top of the page
 
+Quote Post

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

 


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


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