Hallo,
ich habe gerade ein kleines C++-Test-Programm geschrieben und wundere
mich, warum der compilierte Code so merkwürdig aussieht. Offensichtlich
wird in der Init()-Routine der Zugriff auf data in 4 einzelnen
Byte-Zugriffen geschrieben, obwohl die Daten Word-aligned im Speicher
liegen und der Cortex-M3 den str-Befehl auch auf unaligned-Adressen
anwenden könnte.
Hier der C++-Code und der Disassembler-Code (einmal mit -Os und einmal
mit -O3 compiliert). Das zieht sich so durch den ganzen Code durch! Hat
jemand eine Ahnung, wie man dem GCC diese Ineffizienz abgewöhnen kann?
Eigentlich sollte doch ein einziges
ausreichen, oder sehe ich das falsch?
Vielen Dank für Hinweise.
Martin
Compiler-Aufruf (ich verwende Sourcery G++ Lite):
arm-none-eabi-gcc -o test1.o -c -DSTM32F10X_MD_VL -DUSE_STDPERIPH_DRIVER
-Wall -mcpu=cortex-m3 -mthumb -g3 -gdwarf-2 -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -fno-inline
-ffunction-sections -fdata-sections -fno-rtti -fno-exceptions test1.cc
1 | class test1
|
2 | {
|
3 | public:
|
4 | void Init( void );
|
5 | void Cyclic( void );
|
6 | int GetResult( void );
|
7 |
|
8 | private:
|
9 | int data;
|
10 |
|
11 | };
|
12 |
|
13 | void test1::Init( void )
|
14 | {
|
15 | data = 17;
|
16 | }
|
17 | void test1::Cyclic( void )
|
18 | {
|
19 | if( data & 1 )
|
20 | {
|
21 | data = (data >> 1) | 0x1000;
|
22 | } else
|
23 | {
|
24 | data = (data >> 1);
|
25 | }
|
26 | }
|
27 | int test1::GetResult( void )
|
28 | {
|
29 | return data;
|
30 | }
|
Assembler-Code für Init-Routine:
1 | Optimierung -O3:
|
2 | void test1::Init( void )
|
3 | {
|
4 | data = 17;
|
5 | 8000d30: 2300 movs r3, #0
|
6 | 8000d32: 2211 movs r2, #17
|
7 | 8000d34: 7002 strb r2, [r0, #0] <-- hier werden 4 Byte eines int einzeln gespeichert !!!
|
8 | 8000d36: 7043 strb r3, [r0, #1]
|
9 | 8000d38: 7083 strb r3, [r0, #2]
|
10 | 8000d3a: 70c3 strb r3, [r0, #3]
|
11 | }
|
12 | 8000d3c: 4770 bx lr
|
13 | 8000d3e: bf00 nop
|
14 |
|
15 | Optimierung -Os:
|
16 | void test1::Init( void )
|
17 | {
|
18 | data = 17;
|
19 | 80009b0: 2300 movs r3, #0
|
20 | 80009b2: 2211 movs r2, #17
|
21 | 80009b4: 7002 strb r2, [r0, #0] <-- hier werden 4 Byte eines int einzeln gespeichert !!!
|
22 | 80009b6: 7043 strb r3, [r0, #1]
|
23 | 80009b8: 7083 strb r3, [r0, #2]
|
24 | 80009ba: 70c3 strb r3, [r0, #3]
|
25 | }
|
26 | 80009bc: 4770 bx lr
|