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

 
 
5 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> "Оптимизация" в WinAVR и как с этим бороться
MaxiMuz
сообщение Nov 16 2011, 18:07
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Перейдя с ассемблера на WinAVR, невольно стал обращать на размер кода. Когда стал разбираться в конкретике генерируемого кода , хваленный на многих сайтах WinAVR обнажил свое несовершенство.
Короче, программка :
Код
#include <avr/io.h>
#include <inttypes.h>

#define Btn1 PB2
#define Btn2 PB3

#define  KeyMask (1<<Btn1)|(1<<Btn2)
#define sbi(p,b) (p |= (1<<b)) //Установить бит

volatile register int8_t Cnt asm("r19");    // фоновый счетчик
volatile register int8_t a asm ("r16");

int main (void)
{
asm("nop");
a = 1;

while(1)
{
if (~(PINB)&(KeyMask))
    {
    a |= 0x01;
    }
if ((--Cnt)==0)
    {
    if (a==1 )
        {
        a=0;
        sbi (PINB,PB2);
        }
    }
}
}

Соответственно , полученный код:
Код
a = 1;
     ldi    r16, 0x01

while(1)
{
[color="#FF00FF"]if (~(PINB)&(KeyMask))
     in     r24, 0x16
     ldi    r25, 0x00
     com    r24
     com    r25
     andi    r24, 0x0C
     andi    r25, 0x00
     or     r24, r25
     breq    .+2[/color]
{
a |= 0x01;
}
     ori    r16, 0x01

[color="#FF0000"]if ((--Cnt)==0)
     mov    r24, r19
     subi    r24, 0x01
     mov    r19, r24[/color]
     brne    .-26    
{
    if (a==1 )
     cpi    r16, 0x01
     brne    .-30
{
        a=0;
     ldi    r16, 0x00

sbi (PINB,PB2);
     sbi    0x16, 2
     rjmp    .-36

Конструкцию if ((--Cnt)==0) выделенную крас.цветом может заменить всего одна машинная команда: dec r19!
Вопрос: как заставить компилятор это делать ?

Во втором случае: if (~(PINB)&(KeyMask)) , невижу смысла во втором парном регистре r25. Можно использовать "tst r24". Можно как нибудь с этим бороться ?!
Не хочеться чтобы потом код получался неоправданно раздутым!
Может быть стоит подождать другую версию компилятора (пользуюсь WinAVR-20100110) или уже пререходить на совсем другой ?
Go to the top of the page
 
+Quote Post
Палыч
сообщение Nov 16 2011, 18:45
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(MaxiMuz @ Nov 16 2011, 22:07) *
хваленный на многих сайтах WinAVR обнажил свое несовершенство.
В большенстве трансляторов с ЯВУ можно найти "несовершенство"...

Цитата(MaxiMuz @ Nov 16 2011, 22:07) *
Во втором случае: if (~(PINB)&(KeyMask)) , невижу смысла во втором парном регистре r25. Можно использовать "tst r24". Можно как нибудь с этим бороться ?!
А, вот тут - "неча на зеркало пенять..." (т.е. не нужно "мешать" восьми- и шестнадцатибитные операнды).
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 16 2011, 19:19
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(Палыч @ Nov 16 2011, 21:45) *
А, вот тут - "неча на зеркало пенять..." (т.е. не нужно "мешать" восьми- и шестнадцатибитные операнды).

а где вы увидели 16ти битные операнды ?
PINB читается как 8ми битные
KeyMask тоже 8мь бит !
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 16 2011, 19:58
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(MaxiMuz @ Nov 17 2011, 00:07) *
Перейдя с ассемблера на WinAVR, невольно стал обращать на размер кода.

И зря. Если код помещается в чип и успевает сделать то, что должен, то какая разница, какого он размера?
Цитата(MaxiMuz @ Nov 17 2011, 00:07) *
Конструкцию if ((--Cnt)==0) выделенную крас.цветом может заменить всего одна машинная команда: dec r19!

Вам же написали, что volatile register писать нельзя. Какие претензии?
Что касается второго, то целочисленные константы по умолчанию имеют тип int. Попробуйте написать if (~(PINB)&((unsigned char)KeyMask)).

ЗЫ. Выделение цветом не работает в блоке code, если сильно надо, то пользуйтесь блоком codebox - там вроде работает.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Палыч
сообщение Nov 16 2011, 20:10
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(MaxiMuz @ Nov 16 2011, 23:19) *
KeyMask тоже 8мь бит !
Почему? Обоснуйте.
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 16 2011, 21:06
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(Палыч @ Nov 16 2011, 23:10) *
Почему? Обоснуйте.

смотрите по коду, предпоследния команда:
or r24, r25
я не думаю что старший байт с младшим компилятор сталбы склеивать !
Кстати , можно проверить по присваиванию
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 16 2011, 21:19
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MaxiMuz @ Nov 17 2011, 01:06) *
or r24, r25
я не думаю что старший байт с младшим компилятор сталбы склеивать !

Это обычная проверка пары регистров на 0.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 16 2011, 21:53
Сообщение #8


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(MaxiMuz @ Nov 16 2011, 20:07) *
Код
#define  KeyMask (1<<Btn1)|(1<<Btn2)
KeyMask - результат вычисления выражения (пусть и в compile-time).
По стандарту языка С имеет тип как минимум int.
Дальше у gcc недооптимизация, спору нет. Но он обязан был сначала всё делать в int-ах и только потом натравить оптимизатор.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Nov 17 2011, 01:30
Сообщение #9


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

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Код
#define  KeyMask (1<<Btn1)|(1<<Btn2)


А скобочки для защиты от подводных граблей не хотите поставить?

Назначение регистров для переменных ОЧЕНЬ сильно мешает оптимизации.
Go to the top of the page
 
+Quote Post
neiver
сообщение Nov 17 2011, 08:19
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Мда, можно вытащить ассемблерщика из ассемблера, но...
По поводу регистровых переменных. В них практически никогда нет реальной необходимости, особенно в достаточно сложных программах. Мнимая выгода из-за отсутствий-загрузок выгрузок из/в память, с лихвой перекрываются необходимостью тасовать и сохранять регистры, например, для вызова функций и тупяками компилятора из-за того, что он не может использовать регистры, занятые под эти переменные, так как умеет. Модификатор volatile с регистровыми переменными, как уже сказали, не работает. Если возникает реальзая ситуация, когда программа относительно проста и нехватает нескользих тактов для выполнения критического участка, то наверное имеет смысл переписать этот критический участок, а то и всю программу на ассемблере.
Код
if (~(PINB)&(KeyMask))

В Си есть такая штука - целочисленное расширение называется (integer propagation). Рекомендую погуглить и почитать, что это такое, многоя станет понятно.

Go to the top of the page
 
+Quote Post
Палыч
сообщение Nov 17 2011, 09:27
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(neiver @ Nov 17 2011, 12:19) *
integer propagation

Integer promotion
Но, в данном случае - это не оно. Имеет место банальное использование в выражении операндов двух разных типов, "меньший" из которых приводится к "большему".
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Nov 17 2011, 15:19
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658



Цитата(aaarrr @ Nov 17 2011, 00:19) *
Это обычная проверка пары регистров на 0.

Как это компилятор резервирует старший байт , а потом проверяет младший со старшим ?
Как то не логично получается !

AHTOXA, Пробывал я выражение : if (~(PINB)&((unsigned char)KeyMask))
- Результат абсолютно тот же, и скобки как говорили в #define я поставил, один хрен !

Попробывал предварительное присваивание константы в регистр :
Код
volatile register int8_t Cnt asm("r19");    // фоновый счетчик
volatile register int8_t a asm ("r16");
volatile register int8_t b asm ("r17");

int main (void)
{
asm("nop");
a = 1;
b=KeyMask;

while(1)
{
if (~(PINB)&(b))
    {
    a |= 0x01;
    }
if ((--Cnt)==0)
    {
    if (a==1 )
        {
        a=0;
        b |= 0x08;
        sbi (PINB,PB2);
        }
    }
}
}

Тут Вообще "Оптимизатор" показал чудеса !!! sm.gif

Цитата(Genadi Zawidowski @ Nov 17 2011, 04:30) *
Назначение регистров для переменных ОЧЕНЬ сильно мешает оптимизации.

Если рассуждать как вы , то можно сказать и любая программа написанная в Си мешает оптимизации!!!
Вы еще бы посоветовали на Ассемблере писать sm.gif

Цитата(AHTOXA @ Nov 16 2011, 22:58) *
И зря. Если код помещается в чип и успевает сделать то, что должен, то какая разница, какого он размера?

А если не помещается, и делает с большими задержками по времяни ?


Цитата(AHTOXA @ Nov 16 2011, 22:58) *
ЗЫ. Выделение цветом не работает в блоке code, если сильно надо, то пользуйтесь блоком codebox - там вроде работает.

Кстати , а что за блок codebox ?
я про него ничего не слышал

Во втором случае, все просто ! sm.gif Я заранее знал решение, и хотел посмотреть что вы скажите (может чего новое)
Проблемка решается заменой конструкции:
if (~(PINB)&(KeyMask))

на несколько команд:
b=~(PINB);
b&=KeyMask;
if (cool.gif
{ ......}

Код сокращается всего лишь до:
Код
IN      R24,0x16
COM     R24          
ANDI    R24,0x0C
BREQ    PC+0x02


А вот с первой проблемой мусорных присваиваний , похоже все мрачно ! sad.gif
Go to the top of the page
 
+Quote Post
Палыч
сообщение Nov 17 2011, 17:42
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(MaxiMuz @ Nov 17 2011, 19:19) *
... похоже все мрачно !
Если Вы считали, что компилятор выдаст точную копию Вашей программы на ассемблере, то, разочарую Вас, - такого не будет: компилятор всё-таки действует по некоему шаблону, что не всегда даёт "хороший" код. Иногда компилятору можно в его работе помочь. Atmel по этому поводу выпустил AppNote AVR035.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 17 2011, 17:47
Сообщение #14


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(MaxiMuz @ Nov 17 2011, 21:19) *
А если не помещается, и делает с большими задержками по времяни ?
Вот когда упрётесь в такую ситуацию, тогда и начинайте оптимизацию sm.gif
Цитата(MaxiMuz @ Nov 17 2011, 21:19) *
Кстати , а что за блок codebox ?
я про него ничего не слышал

У меня он слева, под смайликами. Хотя можно и просто руками поменять [соde]lalala[/соde] на [соdebox]lalala[/соdebox]. Хотя это наверное зависит от применяемого редактора (правая верхняя кнопка : ).


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
neiver
сообщение Nov 18 2011, 05:25
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Я к чему, тут про целочисленное расширение намекаю? Компилятор в данном случае делает ровно, то, что ему сказано. В вашем выражении нужна не битовая инверсия, а логическая:
Код
#define  KeyMask ((1<<Btn1)|(1<<Btn2))
...
if( ! (PINB & KeyMask) )
{
        ...
}

Посмотрите, и почувствуйте разницу.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 10th June 2024 - 23:22
Рейтинг@Mail.ru


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