eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaProblem lekko OT, ale w WinAVR ;-)Re: Problem lekko OT, ale w WinAVR ;-)
  • Data: 2009-06-12 07:54:41
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl> szukaj wiadomości tego autora
    [ pokaż wszystkie nagłówki ]

    T.M.F. pisze:

    > No zagladam dosyc czesto przy okazji debuggowania tego co napisalem.
    > Jakis koszmarnych brakow optymalizacji nie zauwazylem. Mozesz podac
    > konkretny przyklad w C, ktory jest zle optymalizowany? To zawsze mozna
    > zglosic jako bug.

    To zależy co kto uważa za koszmarne. Poniżej parę przykładów, ale
    wątpię, żeby komuś chciało się to czytać.

    Wszystkie przykłady były optymalizowane na rozmiar.


    ----------------------------------------------------
    -----
    Testowanie warunków logicznych:

    #define PIN1_IS_LOW (!(PINB & (1<<PINB7)))
    #define PIN2_IS_LOW (!(PINB & (1<<PINB6)))

    volatile uint8_t a;
    asm volatile(";start");
    a = (PIN1_IS_LOW || PIN2_IS_LOW);
    asm volatile(";stop");

    Kod wynikowy:

    32 ;start
    33 ; 0 "" 2
    34 .LSM2:
    35 /* #NOAPP */
    36 000a 1F99 sbic 35-32,7
    37 000c 00C0 rjmp .L2
    38 000e 81E0 ldi r24,lo8(1)
    39 0010 90E0 ldi r25,hi8(1)
    40 0012 00C0 rjmp .L3
    41 .L2:
    42 0014 83B1 in r24,35-32
    43 0016 90E0 ldi r25,lo8(0)
    44 0018 26E0 ldi r18,6
    45 001a 9695 1: lsr r25
    46 001c 8795 ror r24
    47 001e 2A95 dec r18
    48 0020 01F4 brne 1b
    49 0022 8095 com r24
    50 0024 9095 com r25
    51 0026 8170 andi r24,lo8(1)
    52 0028 9070 andi r25,hi8(1)
    53 .L3:
    54 002a 8983 std Y+1,r24
    55 .LVL0:
    56 .LSM3:
    57 /* #APP */
    58 ; 96 "main.c" 1
    59 ;stop

    Pomijając już tą nieszczęsną promocję do inta, to najbardziej w tym
    kodzie rozwaliło mnie wyłuskiwanie 6 bitu.

    Delikatna modyfikacja kodu:

    if (PIN1_IS_LOW || PIN2_IS_LOW) a = true;
    else a = false;


    daje już coś takiego:

    62 /* #NOAPP */
    63 002c 1F9B sbis 35-32,7
    64 002e 00C0 rjmp .L4
    65 0030 1E99 sbic 35-32,6
    66 0032 00C0 rjmp .L5
    67 .L4:
    68 0034 81E0 ldi r24,lo8(1)
    69 0036 8983 std Y+1,r24
    70 .LVL1:
    71 0038 00C0 rjmp .L6
    72 .L5:
    73 .LSM5:
    74 003a 1982 std Y+1,__zero_reg__
    75 .LVL2:
    76 .L6:


    ----------------------------------------------------
    ------
    Przygotowanie ramki na stosie dla 5 parametrów 16-bitowych:

    1637 0068 ADB7 in r26,__SP_L__
    1638 006a BEB7 in r27,__SP_H__
    1639 006c 1A97 sbiw r26,10
    1640 006e 0FB6 in __tmp_reg__,__SREG__
    1641 0070 F894 cli
    1642 0072 BEBF out __SP_H__,r27
    1643 0074 0FBE out __SREG__,__tmp_reg__
    1644 0076 ADBF out __SP_L__,r26

    Przy dwóch parametrach:

    1751 010e 00D0 rcall .
    1752 0110 00D0 rcall .

    Łatwo policzyć, że poniżej 8 parametrów bardziej opłaca się wersja z
    rcall (program optymalizowany na rozmiar).



    ----------------------------------------------------
    -------
    Adresowanie struktur i pobieranie adresów z flasha:

    typedef struct{
    const prog_char * a;
    const prog_char * b;
    const prog_char * c;
    const prog_char * d;
    }Aqq;

    prog_char s[] = "Aqq";

    Aqq PROGMEM tab[]={
    {s,s,s,s},
    {s,s,s,s},
    {s,s,s,s},
    {s,s,s,s},
    };

    asm volatile (";start");
    for (uint8_t i = 0; i < tab_size(tab); i++){
    blabla( pgm_read_word( &tab[i].a ), pgm_read_word( &tab[i].b ),
    pgm_read_word( &tab[i].c ), pgm_read_word( &tab[i].d ) );
    }
    asm volatile (";stop");


    Pierwszy problem to wyliczanie adresu w flashu:

    69 .LBB24:
    70 0024 F901 movw r30,r18
    71 .LVL4:
    72 0026 E050 subi r30,lo8(-(tab+4))
    73 0028 F040 sbci r31,hi8(-(tab+4))
    74 /* #APP */
    75 ; 106 "main.c" 1
    76 002a 4591 lpm r20, Z+
    77 002c 5491 lpm r21, Z
    78
    79 ; 0 "" 2

    Pomimo, że jest (czy raczej mogłoby być) użyte adresowanie z
    postinkrementacją, to adresy kolejnych elementów są i tak przed każdym
    pobraniem na nowo wyliczane. W przykładzie, który podałem daje to 12
    niepotrzebnych instrukcji w każdym obiegu tej krótkiej pętli i dodatkowo
    zajętą parę rejestrów R19:R18.

    Drugi problem, to wyliczanie od początku adresu komórki w tablicy przy
    każdym obiegu pętli:

    27 ;start
    28 ; 0 "" 2
    29 /* #NOAPP */
    30 0000 C0E0 ldi r28,lo8(0)
    31 0002 D0E0 ldi r29,hi8(0)
    32 .L2:
    33 .LBB21:
    34 .LBB22:
    35 .LSM2:
    36 0004 9E01 movw r18,r28
    37 0006 83E0 ldi r24,3
    38 0008 220F 1: lsl r18
    39 000a 331F rol r19
    40 000c 8A95 dec r24
    41 000e 01F4 brne 1b
    42 0010 F901 movw r30,r18
    43 .LVL0:

    [...]

    96 .LBE25:
    97 0038 0E94 0000 call blabla
    98 .LVL8:
    99 003c 2196 adiw r28,1
    100 .LSM3:
    101 003e C430 cpi r28,4
    102 0040 D105 cpc r29,__zero_reg__
    103 0042 01F4 brne .L2
    104 .LBE21:
    105 .LSM4:
    106 /* #APP */
    107 ; 108 "main.c" 1
    108 ;stop


    Wystarczy prosty myk ze wskaźnikiem i pętla się skraca:

    asm volatile (";start");
    for (uint8_t i = 0; i < tab_size(tab); i++){
    const Aqq * p = &tab[i];
    blabla( pgm_read_word( &p->a ), pgm_read_word( &p->b ), pgm_read_word(
    &p->c ), pgm_read_word( &p->d ) );
    }
    asm volatile (";stop");


    27 ;start
    28 ; 0 "" 2
    29 /* #NOAPP */
    30 0000 C0E0 ldi r28,lo8(tab)
    31 0002 D0E0 ldi r29,hi8(tab)

    [...]

    87 0022 0E94 0000 call blabla
    88 .LVL8:
    89 0026 2896 adiw r28,8
    90 .LBE23:
    91 .LSM3:
    92 0028 80E0 ldi r24,hi8(tab+32)
    93 002a C030 cpi r28,lo8(tab+32)
    94 002c D807 cpc r29,r24
    95 002e 01F4 brne .L2
    96 .LBE22:
    97 .LSM4:
    98 /* #APP */
    99 ; 109 "main.c" 1
    100 ;stop
    1

    A podobno gcc ma super optymalizator do pętli (widocznie moja wersja
    gdzieś go zgubiła).

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: