Mikrocontroller und Digitale Elektronik
›
Thread
erzeugter Code von ICCAVR ineffizient
F
Fiffi
Gast
25.10.2003 04:03
#51470
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 ?
PD
Peter D.
(peda)
25.10.2003 15:16
#51471
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
F
Fiffi
Gast
25.10.2003 15:22
#51472
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
F
Fiffi
Gast
25.10.2003 15:27
#51473
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
JW
Joerg Wunsch
Gast
25.10.2003 17:25
#51474
Gemäß dem C-Standard berechnen viele Compiler die switch()-Ausdrücke
als Typ `int'.
if then else
könnte ggf. besseren Code erzeugen.
M
Michael
Gast
25.10.2003 17:55
#51475
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
F
Fiffi
Gast
25.10.2003 18:35
#51476
Hallo Michael,
vielen Dank, daß du den Code mit IAR übersetzt hast.
Das Ergebnis ist beeindruckend !
T
thkais
Gast
25.10.2003 18:38
#51477
Wenn die Compiler ineffizient sind, programmiert man halt gleich in
Assembler. Man kann eben nicht alles haben ;)
F
Fiffi
Gast
25.10.2003 19:31
#51478
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.
M
Michael
Gast
25.10.2003 20:41
#51479
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.
S
Stefan
Gast
26.10.2003 00:35
#51480
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
↑ Nach oben
← Zurück zu Mikrocontroller und Digitale Elektronik
Antwort schreiben