erzeugter Code von ICCAVR ineffizient

Gast #51470
Lesenswert?
• ▲
▼
Hallo,

ich teste gerade die Codequalität der Demoversion von Imagecraft C
v6.29.

Hier ein Resultat:

///////////////////////////////////
// PORTB bit constants
#define LED_GREEN     4
#define LED_YELLOW     5
#define LED_RED       6

#pragma interrupt_handler uart0_rx_isr:iv_UART_RX
void uart0_rx_isr(void)
{
 char data = UDR;

 switch(data)
 {
 case LED_GREEN_ON:
  PORTD &= ~BIT(LED_GREEN);
  break;
 case LED_GREEN_OFF:
  PORTD |= BIT(LED_GREEN);
  break;
 case LED_YELLOW_ON:
  PORTD &= ~BIT(LED_YELLOW);
  break;
 case LED_YELLOW_OFF:
  PORTD |= BIT(LED_YELLOW);
  break;
 case LED_RED_ON:
  PORTD &= ~BIT(LED_RED);
  break;
 case LED_RED_OFF:
  PORTD |= BIT(LED_RED);
  break;
 }

 if(data == LED_GREEN_ON)
  PORTD &= ~BIT(LED_GREEN);
}
///////////////////////////////////
   *00000043:uart0_rx_isr
   +00000043: 930A      ST      -Y,R16
   +00000044: 932A      ST      -Y,R18
   +00000045: 933A      ST      -Y,R19
   +00000046: 93EA      ST      -Y,R30
   +00000047: B70F      IN      R16,0x3F
   +00000048: 930A      ST      -Y,R16
   +00000049: B10C      IN      R16,0xC
   +0000004A: 2F20      MOV     R18,R16
   +0000004B: 2733      CLR     R19
   +0000004C: 3021      CPI     R18,0x01          ; 0x01 = 0b00000001 =
1
   +0000004D: E0E0      LDI     R30,0x00          ; 0x00 = 0b00000000 =
0
   +0000004E: 073E      CPC     R19,R30
   +0000004F: F0A9      BREQ    +0x15             ; Destination:
0x000065
   +00000050: 3022      CPI     R18,0x02          ; 0x02 = 0b00000010 =
2
   +00000051: E0E0      LDI     R30,0x00          ; 0x00 = 0b00000000 =
0
   +00000052: 073E      CPC     R19,R30
   +00000053: F099      BREQ    +0x13             ; Destination:
0x000067
   +00000054: 3023      CPI     R18,0x03          ; 0x03 = 0b00000011 =
3
   +00000055: E0E0      LDI     R30,0x00          ; 0x00 = 0b00000000 =
0
   +00000056: 073E      CPC     R19,R30
   +00000057: F089      BREQ    +0x11             ; Destination:
0x000069
   +00000058: 3024      CPI     R18,0x04          ; 0x04 = 0b00000100 =
4
   +00000059: E0E0      LDI     R30,0x00          ; 0x00 = 0b00000000 =
0
   +0000005A: 073E      CPC     R19,R30
   +0000005B: F079      BREQ    +0x0F             ; Destination:
0x00006B
   +0000005C: 3025      CPI     R18,0x05          ; 0x05 = 0b00000101 =
5
   +0000005D: E0E0      LDI     R30,0x00          ; 0x00 = 0b00000000 =
0
   +0000005E: 073E      CPC     R19,R30
   +0000005F: F069      BREQ    +0x0D             ; Destination:
0x00006D
   +00000060: 3026      CPI     R18,0x06          ; 0x06 = 0b00000110 =
6
   +00000061: E0E0      LDI     R30,0x00          ; 0x00 = 0b00000000 =
0
   +00000062: 073E      CPC     R19,R30
   +00000063: F059      BREQ    +0x0B             ; Destination:
0x00006F
   +00000064: C00B      RJMP    +0x000B           ; Destination:
0x000070
   +00000065: 9894      CBI     0x12,4
   +00000066: C009      RJMP    +0x0009           ; Destination:
0x000070
   +00000067: 9A94      SBI     0x12,4
   +00000068: C007      RJMP    +0x0007           ; Destination:
0x000070
   +00000069: 9895      CBI     0x12,5
   +0000006A: C005      RJMP    +0x0005           ; Destination:
0x000070
   +0000006B: 9A95      SBI     0x12,5
   +0000006C: C003      RJMP    +0x0003           ; Destination:
0x000070
   +0000006D: 9896      CBI     0x12,6
   +0000006E: C001      RJMP    +0x0001           ; Destination:
0x000070
   +0000006F: 9A96      SBI     0x12,6
   +00000070: 3001      CPI     R16,0x01          ; 0x01 = 0b00000001 =
1
   +00000071: F409      BRNE    +0x01             ; Destination:
0x000073
   +00000072: 9894      CBI     0x12,4
   +00000073: 9109      LD      R16,Y+
   +00000074: BF0F      OUT     0x3F,R16
   +00000075: 91E9      LD      R30,Y+
   +00000076: 9139      LD      R19,Y+
   +00000077: 9129      LD      R18,Y+
   +00000078: 9109      LD      R16,Y+
   +00000079: 9518      RETI
///////////////////////////////////
Das Setzen/Rücksetzen der Port-Bits hat er richtig übersetzt.
Aber die switch() Anweisung ?:
   +00000050: 3022      CPI     R18,0x02          ; 0x02 = 0b00000010 =
2
   +00000051: E0E0      LDI     R30,0x00          ; 0x00 = 0b00000000 =
0
   +00000052: 073E      CPC     R19,R30
   +00000053: F099      BREQ    +0x13             ; Destination:
0x000067
Die If Anweisung hat er auch richtig übersetzt, warum dann nicht bei
der switch() Anweisung ?:
   +00000070: 3001      CPI     R16,0x01          ; 0x01 = 0b00000001 =
1
   +00000071: F409      BRNE    +0x01             ; Destination:
0x000073
   +00000072: 9894      CBI     0x12,4


Habt ihr ähnliche Erfahrungen ?
#51471
Lesenswert?
• ▲
▼
Ohne einen vollständigen Code kann das keiner sagen:

error: `LED_GREEN_ON' undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)
warning: implicit declaration of function `BIT'
error: `LED_GREEN_OFF' undeclared (first use in this function)
error: `LED_YELLOW_ON' undeclared (first use in this function)
error: `LED_YELLOW_OFF' undeclared (first use in this function)
error: `LED_RED_ON' undeclared (first use in this function)
error: `LED_RED_OFF' undeclared (first use in this function)


Peter
Gast #51472
Lesenswert?
• ▲
▼
Hallo Peter,

entschuldige bitte, hier sind die defines:

#define LED_GREEN_ON   1
#define LED_GREEN_OFF  2
#define LED_YELLOW_ON  3
#define LED_YELLOW_OFF 4
#define LED_RED_ON     5
#define LED_RED_OFF    6
Gast #51473
Lesenswert?
• ▲
▼
Hallo,

der von AVRGCC 20030913 erzeugte Code sieht auch nicht besser aus:

INTERRUPT(SIG_UART_RECV)
{
  76:  78 94         sei
  78:  1f 92         push  r1
  7a:  0f 92         push  r0
  7c:  0f b6         in  r0, 0x3f  ; 63
  7e:  0f 92         push  r0
  80:  11 24         eor  r1, r1
  82:  2f 93         push  r18
  84:  8f 93         push  r24
  86:  9f 93         push  r25
 char data = UDR;
  88:  2c b1         in  r18, 0x0c  ; 12

 switch(data)
  8a:  82 2f         mov  r24, r18
  8c:  99 27         eor  r25, r25
  8e:  83 30         cpi  r24, 0x03  ; 3
  90:  91 05         cpc  r25, r1
  92:  b1 f0         breq  .+44       ; 0xc0
  94:  84 30         cpi  r24, 0x04  ; 4
  96:  91 05         cpc  r25, r1
  98:  34 f4         brge  .+12       ; 0xa6
  9a:  81 30         cpi  r24, 0x01  ; 1
  9c:  91 05         cpc  r25, r1
  9e:  61 f0         breq  .+24       ; 0xb8
  a0:  02 97         sbiw  r24, 0x02  ; 2
  a2:  61 f0         breq  .+24       ; 0xbc
  a4:  15 c0         rjmp  .+42       ; 0xd0
  a6:  85 30         cpi  r24, 0x05  ; 5
  a8:  91 05         cpc  r25, r1
  aa:  79 f0         breq  .+30       ; 0xca
  ac:  85 30         cpi  r24, 0x05  ; 5
  ae:  91 05         cpc  r25, r1
  b0:  4c f0         brlt  .+18       ; 0xc4
  b2:  06 97         sbiw  r24, 0x06  ; 6
  b4:  61 f0         breq  .+24       ; 0xce
  b6:  0c c0         rjmp  .+24       ; 0xd0
 {
 case LED_GREEN_ON:
  PORTD &= ~_BV(LED_GREEN);
  b8:  94 98         cbi  0x12, 4  ; 18
  break;
  ba:  0a c0         rjmp  .+20       ; 0xd0
 case LED_GREEN_OFF:
  PORTD |= _BV(LED_GREEN);
  bc:  94 9a         sbi  0x12, 4  ; 18
  break;
  be:  08 c0         rjmp  .+16       ; 0xd0
 case LED_YELLOW_ON:
  PORTD &= ~_BV(LED_YELLOW);
  c0:  95 98         cbi  0x12, 5  ; 18
  break;
  c2:  06 c0         rjmp  .+12       ; 0xd0
 case LED_YELLOW_OFF:
  PORTD |= _BV(LED_YELLOW);
  c4:  95 9a         sbi  0x12, 5  ; 18
  PORTD |= 0x04;
  c6:  92 9a         sbi  0x12, 2  ; 18
  break;
  c8:  03 c0         rjmp  .+6        ; 0xd0
 case LED_RED_ON:
  PORTD &= ~_BV(LED_RED);
  ca:  96 98         cbi  0x12, 6  ; 18
  break;
  cc:  01 c0         rjmp  .+2        ; 0xd0
 case LED_RED_OFF:
  PORTD |= _BV(LED_RED);
  ce:  96 9a         sbi  0x12, 6  ; 18
  break;
 }

 if(data == LED_GREEN_ON)
  d0:  21 30         cpi  r18, 0x01  ; 1
  d2:  09 f4         brne  .+2        ; 0xd6
  PORTD &= ~_BV(LED_GREEN);
  d4:  94 98         cbi  0x12, 4  ; 18
}
  d6:  9f 91         pop  r25
  d8:  8f 91         pop  r24
  da:  2f 91         pop  r18
  dc:  0f 90         pop  r0
  de:  0f be         out  0x3f, r0  ; 63
  e0:  0f 90         pop  r0
  e2:  1f 90         pop  r1
  e4:  18 95         reti
Gast #51475
Lesenswert?
• ▲
▼
Ich habe Deine Quelle mit IAR übersetzt. Ich hoffe, es fehlt nichts.

    45          __interrupt  void uart0_rx_isr(void)
     46          {
   \   __nearfunc __interrupt void uart0_rx_isr();
   \                     uart0_rx_isr:
   \   00000000   932A                       ST      -Y,R18
   \   00000002   931A                       ST      -Y,R17
   \   00000004   930A                       ST      -Y,R16
   \   00000006   B72F                       IN      R18,0x3F
     47           char data = UDR;
   \   00000008   B10C                       IN      R16,0x0C
     48
     49           switch(data)
   \   0000000A   2F10                       MOV     R17,R16
   \   0000000C   951A                       DEC     R17
   \   0000000E   F059                       BREQ    ??uart0_rx_isr_0
   \   00000010   951A                       DEC     R17
   \   00000012   F059                       BREQ    ??uart0_rx_isr_1
   \   00000014   951A                       DEC     R17
   \   00000016   F059                       BREQ    ??uart0_rx_isr_2
   \   00000018   951A                       DEC     R17
   \   0000001A   F059                       BREQ    ??uart0_rx_isr_3
   \   0000001C   951A                       DEC     R17
   \   0000001E   F059                       BREQ    ??uart0_rx_isr_4
   \   00000020   951A                       DEC     R17
   \   00000022   F059                       BREQ    ??uart0_rx_isr_5
   \   00000024   C00B                       RJMP    ??uart0_rx_isr_6
     50           {
     51           case LED_GREEN_ON:
     52            PORTD &= ~BIT(LED_GREEN);
   \                     ??uart0_rx_isr_0:
   \   00000026   9894                       CBI     0x12,0x04
   \   00000028   C009                       RJMP    ??uart0_rx_isr_6
     53            break;
     54           case LED_GREEN_OFF:
     55            PORTD |= BIT(LED_GREEN);
   \                     ??uart0_rx_isr_1:
   \   0000002A   9A94                       SBI     0x12,0x04
   \   0000002C   C007                       RJMP    ??uart0_rx_isr_6
     56            break;
     57           case LED_YELLOW_ON:
     58            PORTD &= ~BIT(LED_YELLOW);
   \                     ??uart0_rx_isr_2:
   \   0000002E   9895                       CBI     0x12,0x05
   \   00000030   C005                       RJMP    ??uart0_rx_isr_6
     59            break;
     60           case LED_YELLOW_OFF:
     61            PORTD |= BIT(LED_YELLOW);
   \                     ??uart0_rx_isr_3:
   \   00000032   9A95                       SBI     0x12,0x05
   \   00000034   C003                       RJMP    ??uart0_rx_isr_6
     62            break;
     63           case LED_RED_ON:
     64            PORTD &= ~BIT(LED_RED);
   \                     ??uart0_rx_isr_4:
   \   00000036   9896                       CBI     0x12,0x06
   \   00000038   C001                       RJMP    ??uart0_rx_isr_6
     65            break;
     66           case LED_RED_OFF:
     67            PORTD |= BIT(LED_RED);
   \                     ??uart0_rx_isr_5:
   \   0000003A   9A96                       SBI     0x12,0x06
     68            break;
     69           }
     70
     71           if(data == LED_GREEN_ON)
   \                     ??uart0_rx_isr_6:
   \   0000003C   3001                       CPI     R16,1
   \   0000003E   F409                       BRNE    ??uart0_rx_isr_7
     72            PORTD &= ~BIT(LED_GREEN);
   \   00000040   9894                       CBI     0x12,0x04
     73          }
   \                     ??uart0_rx_isr_7:
   \   00000042   BF2F                       OUT     0x3F,R18
   \   00000044   9109                       LD      R16,Y+
   \   00000046   9119                       LD      R17,Y+
   \   00000048   9129                       LD      R18,Y+
   \   0000004A   9518                       RETI
Gast #51478
Lesenswert?
• ▲
▼
Hallo,

ich habe nun eine ganze Datei unter den verschiedenen Compilern
compiliert.
Diese habe ich ein wenig optimiert (if() anstatt switch() ...).

Das Ergebnis (Codegröße):

WinAVR 20030913:               302 Byte
Codevision Demoversion 1.23.9: 348 Byte
Imagecraft Demoversion 6.29:   382 Byte

@Michael
Ich wäre dir dankbar, wenn du die Datei mal an IAR anpassen und
compilieren könnte.
Angehängte Dateien:
Gast #51479
Lesenswert?
• ▲
▼
Hallo Fiffi,

anbei das 'Compilatius' tastatur.lst, ohne es gelinkt zu haben. Es
müßte auch nur der Stackpointer gesetzt werden, wenn ich nicht etwas
übersehen habe. Optimierung auf höchste Ausführungsgeschwindigkeit
'-s9'; 220 Byte sind angesagt. Wenn man schnelle Interrupts braucht,
ist es vorteilhafter, dort keine Calls zu machen, da sonst viele
Register gerettet werden müssen.
Angehängte Dateien:
Gast #51480
Lesenswert?
• ▲
▼
Beim gcc ist die Initialisierung (Memory nullsetzen etc) bereits mit
drin, das fehlt beim IAR-Listing.
Ohne die Initialisierung komme ich bei gcc auf 240 Bytes.

Ohne die Funktionsaufrufe im IR wirds sowohl bei IAR als auch bei gcc
noch ein gutes Stück weniger.

Die switch-Anweisung hast Du Dir totoptimiert, jetzt werden jedesmal
alle 6 ifs getestet. Nimmst Du if ... else, dann sparst Du viel Zeit
zur Laufzeit.

Stefan

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren