Datum:
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
str r2, [r0, #0] |
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
class test1
{
public:
void Init( void );
void Cyclic( void );
int GetResult( void );
private:
int data;
};
void test1::Init( void )
{
data = 17;
}
void test1::Cyclic( void )
{
if( data & 1 )
{
data = (data >> 1) | 0x1000;
} else
{
data = (data >> 1);
}
}
int test1::GetResult( void )
{
return data;
}
|
Assembler-Code für Init-Routine:
Optimierung -O3:
void test1::Init( void )
{
data = 17;
8000d30: 2300 movs r3, #0
8000d32: 2211 movs r2, #17
8000d34: 7002 strb r2, [r0, #0] <-- hier werden 4 Byte eines int einzeln gespeichert !!!
8000d36: 7043 strb r3, [r0, #1]
8000d38: 7083 strb r3, [r0, #2]
8000d3a: 70c3 strb r3, [r0, #3]
}
8000d3c: 4770 bx lr
8000d3e: bf00 nop
Optimierung -Os:
void test1::Init( void )
{
data = 17;
80009b0: 2300 movs r3, #0
80009b2: 2211 movs r2, #17
80009b4: 7002 strb r2, [r0, #0] <-- hier werden 4 Byte eines int einzeln gespeichert !!!
80009b6: 7043 strb r3, [r0, #1]
80009b8: 7083 strb r3, [r0, #2]
80009ba: 70c3 strb r3, [r0, #3]
}
80009bc: 4770 bx lr
|
Datum:
sinnvoller dürfte das sein:
void test1::Init( void ) : data(17) { } |
schaum mal ob sich da etwas ändert.
Datum:
Das geht nicht, da Init() kein Constructor ist. Init() war hier auch nur als einfaches Beispiel gedacht -- alle Word-Zugriffe werden als 4 einzelne Byte-Zugriffe übersetzt, was einfach ineffizient ist.
Datum:
Hallo, ohne -fpack-struct wird daraus bei mir (Sourcery gcc version 4.6.1):
movs r3, #17 str r3, [r0, #0] |
mit -fpack-struct erhalte ich das selbe Ergebniss wie du.
Datum:
So einfach ist das also -- und schon sieht der Assembler-Code vernünftig aus! Danke!!!