This page goes through the optimization process for the ARM RealView compilation tool, "RVCTB" ( RealView Compilation Tool for BREW v 1.2 ) enabling faster and smaller BREW applications.
ARM RealView Compilation Tools for BREW V1.2
Example of Constant Numbers (List 1)
* List 1 : Constant class
class my_rect {
private:
int _x;
int _y;
int _width;
int _height;
public:
my_rect(void);
my_rect(int x, int y, int width, int height);
};
my_rect::my_rect(void)
{
return;
}
my_rect::my_rect(int x, int y, int width, int height)
: _x(x), _y(y), _width(width), _height(height)
{
return;
}
int func(my_rect const &rect)
{
return reinterpret_cast<int>(&rect);
}
int main(void)
{
my_rect const rect(0, 0, 100, 100);
return func(rect);
}
List 1 is the code for a rectangle class. The code is simple, but contains unnecessary parts.
Figure 1 is the compiled code of list 1. (Compile options are set to the default RVCTB settings)
Figuer 1 : List 1 compiled
; generated by ARM C++ Compiler, ADS1.2 [Build 848]
; commandline [-O2 -S -apcs /ropi -fs "-IC:\ARM\RVCT_BREWv1_2\INCLUDE"]
CODE32
AREA ||.text||, CODE, READONLY
__ct__7my_rectFv PROC ; my_rect::my_rect()
;;;13 my_rect::my_rect(void)
;;;14 {
000000 e3500000 CMP r0,#0
000004 03a00010 MOVEQ r0,#0x10
000008 0afffffe BEQ __nw__FUi
00000c e1a0f00e MOV pc,lr
;;;15 return;
;;;16 }
ENDP
__ct__7my_rectFiN31 PROC ; my_rect::my_rect(int, int, int, int)
;;;18 my_rect::my_rect(int x, int y, int width, int height)
;;;19 : _x(x), _y(y), _width(width), _height(height)
000010 e92d40f8 STMFD sp!,{r3-r7,lr}
000014 e59d4018 LDR r4,[sp,#0x18]
000018 e1a07003 MOV r7,r3
00001c e1a06002 MOV r6,r2
000020 e1a05001 MOV r5,r1
000024 e3500000 CMP r0,#0
000028 1a000003 BNE |L1.60|
00002c e3a00010 MOV r0,#0x10
000030 ebfffffe BL __nw__FUi
000034 e3500000 CMP r0,#0
000038 0a000001 BEQ |L1.68|
;;;20 {
|L1.60|
00003c e580400c STR r4,[r0,#0xc]
000040 e88000e0 STMIA r0,{r5-r7}
;;;21 return;
|L1.68|
000044 e8bd80f8 LDMFD sp!,{r3-r7,pc}
;;;22 }
ENDP
func__FRC7my_rect PROC ; func(const my_rect&)
;;;24 int func(my_rect const& rect)
;;;25 {
000048 e1a0f00e MOV pc,lr
;;;26 return reinterpret_cast<int>(&rect);
;;;27 }
ENDP
main PROC
;;;29 int main(void)
;;;30 {
00004c e92d400f STMFD sp!,{r0-r3,lr}
000050 e3a00000 MOV r0,#0 ;20
000054 e58d0000 STR r0,[sp,#0] ;20
000058 e58d0004 STR r0,[sp,#4] ;20
00005c e3a00064 MOV r0,#0x64 ;20
000060 e58d0008 STR r0,[sp,#8] ;20
000064 e58d000c STR r0,[sp,#0xc] ;20
000068 e1a0000d MOV r0,sp ;26
;;;31 my_rect const rect(0, 0, 100, 100);
;;;32
;;;33 return func(rect);
00006c e28dd010 ADD sp,sp,#0x10
000070 e49df004 LDR pc,[sp],#4
;;;34 }
ENDP
END
In C++, the constructor my_rect const rect (0, 0, 100, 100) will be called during execution even if the class is declared as constant.
Example of Constant POD Structure (List 2)
* List 2 : constant POD structure
struct pod_rect {
int x;
int y;
int width;
int height;
};
int func(pod_rect const& rect)
{
return reinterpret_cast<int>(&rect);
}
int main(void)
{
pod_rect const rect = {0, 0, 100, 100};
return func(rect);
}
Figure 2 : List 2 compiled
; generated by ARM C++ Compiler, ADS1.2 [Build 848]
; commandline [-O2 -S -apcs /ropi -fs "-IC:\ARM\RVCT_BREWv1_2\INCLUDE"]
CODE32
AREA ||.text||, CODE, READONLY
func__FRC8pod_rect PROC ; func(const pod_rect&)
;;;8 int func(pod_rect const& rect)
;;;9 {
000000 e1a0f00e MOV pc,lr
;;;10 return reinterpret_cast<int>(&rect);
;;;11 }
ENDP
main PROC
;;;13 int main(void)
;;;14 {
000004 e92d400f STMFD sp!,{r0-r3,lr}
;;;15 pod_rect const rect = {0, 0, 100, 100};
000008 e59f1014 LDR r1,|L1.36|
00000c e08f1001 ADD r1,pc,r1
000010 e1a0000d MOV r0,sp
000014 e891500c LDMIA r1,{r2,r3,r12,lr}
000018 e880500c STMIA r0,{r2,r3,r12,lr}
;;;16
;;;17 return func(rect);
00001c e28dd010 ADD sp,sp,#0x10
000020 e49df004 LDR pc,[sp],#4
|L1.36|
000024 00000010 DCD ||.constdata$1|| + 16 - {PC}
;;;18 }
ENDP
AREA ||.constdata||, DATA, READONLY, ALIGN=2
||.constdata$1||
DCD 0x00000000
DCD 0x00000000
DCD 0x00000064
DCD 0x00000064
END
List 2 is better than list 1 in both size and speed.
When initialization is done in POD type ( compatible with C ), a constant is stored in the constants area.
* Constructers can not be defined in this case.
Example of Class Supporting POD Type Initialization (List 3)
* List 3 : Class that supports POD type initialization
class my_rect {
public:
struct atom {
int x;
int y;
int width;
int height;
operator my_rect&(void);
operator my_rect const&(void) const;
};
private:
int _x;
int _y;
int _width;
int _height;
public:
my_rect(void);
my_rect(int x, int y, int width, int height);
};
my_rect::my_rect(void)
{
return;
}
my_rect::my_rect(int x, int y, int width, int height)
: _x(x), _y(y), _width(width), _height(height)
{
return;
}
inline my_rect::atom::operator my_rect&(void)
{
return *reinterpret_cast<my_rect*>(this);
}
inline my_rect::atom::operator my_rect const&(void) const
{
return *reinterpret_cast<my_rect const*>(this);
}
int func(my_rect const& rect)
{
return reinterpret_cast<int>(&rect);
}
int main(void)
{
my_rect::atom const rect = {0, 0, 100, 100};
return func(rect);
}
List 3 defines both the rectangle class and a POD type structure, but does the initialization as a POD type.
The object "rect" declared as a POD type structure ( "atom" in List 3 ) may be treated as a class object thanks to cast operators like my_rect&() defined in the "atom" structure. Class functions that accept arguments of type my_rect&, such as "func", can act upon this object.
The reinterpret_cast operator is used in cast operations. If the class does not contain any virtual functions or any virtual inheritance, then it is compatible with the POD type.
Figure 3 : List 3 compiled
; generated by ARM C++ Compiler, ADS1.2 [Build 848]
; commandline [-O2 -S -apcs /ropi -fs "-IC:\ARM\RVCT_BREWv1_2\INCLUDE"]
CODE32
AREA ||.text||, CODE, READONLY
__ct__7my_rectFv PROC ; my_rect::my_rect()
;;;23 my_rect::my_rect(void)
;;;24 {
000000 e3500000 CMP r0,#0
000004 03a00010 MOVEQ r0,#0x10
000008 0afffffe BEQ __nw__FUi
00000c e1a0f00e MOV pc,lr
;;;25 return;
;;;26 }
ENDP
__ct__7my_rectFiN31 PROC ; my_rect::my_rect(int, int, int, int)
;;;28 my_rect::my_rect(int x, int y, int width, int height)
;;;29 : _x(x), _y(y), _width(width), _height(height)
000010 e92d40f8 STMFD sp!,{r3-r7,lr}
000014 e59d4018 LDR r4,[sp,#0x18]
000018 e1a07003 MOV r7,r3
00001c e1a06002 MOV r6,r2
000020 e1a05001 MOV r5,r1
000024 e3500000 CMP r0,#0
000028 1a000003 BNE |L1.60|
00002c e3a00010 MOV r0,#0x10
000030 ebfffffe BL __nw__FUi
000034 e3500000 CMP r0,#0
000038 0a000001 BEQ |L1.68|
;;;30 {
|L1.60|
00003c e580400c STR r4,[r0,#0xc]
000040 e88000e0 STMIA r0,{r5-r7}
;;;31 return;
|L1.68|
000044 e8bd80f8 LDMFD sp!,{r3-r7,pc}
;;;32 }
ENDP
func__FRC7my_rect PROC ; func(const my_rect&)
;;;44 int func(my_rect const& rect)
;;;45 {
000048 e1a0f00e MOV pc,lr
;;;46 return reinterpret_cast<int>(&rect);
;;;47 }
ENDP
main PROC
;;;49 int main(void)
;;;50 {
00004c e92d400f STMFD sp!,{r0-r3,lr}
;;;51 my_rect::atom const rect = {0, 0, 100, 100};
000050 e59f1014 LDR r1,|L1.108|
000054 e08f1001 ADD r1,pc,r1
000058 e1a0000d MOV r0,sp
00005c e891500c LDMIA r1,{r2,r3,r12,lr}
000060 e880500c STMIA r0,{r2,r3,r12,lr}
;;;52
;;;53 return func(rect);
000064 e28dd010 ADD sp,sp,#0x10
000068 e49df004 LDR pc,[sp],#4
|L1.108|
00006c 00000010 DCD ||.constdata$1|| + 16 - {PC}
;;;54 }
ENDP
AREA ||.constdata||, DATA, READONLY, ALIGN=2
||.constdata$1||
DCD 0x00000000
DCD 0x00000000
DCD 0x00000064
DCD 0x00000064
END
The number of instructions in the main function has decreased. ( Caution: the ARM processer it not 1 instruction 1 cycle)
Example of Static Variables (List 4)
Variables of constants classes cannot be regarded as constant static variables, because the constructor will called. But if the value of a constant static variable does not change within the application, it can be used ( see "Practical Development with BREW using C++" ).
If the initialization of the constant class variable of is done in POD type, it can be regarded as a static constant variable. ( See List 4 )
* List 4 : Using static variable
int main(void)
{
static my_rect::atom const rect = {0, 0, 100, 100};
return func(rect);
}
As shown in figure 4, the use of "static" in the code, greatly reduces the size of the main function.
Figure 4 : List 4 compiled (main function is extracted)
; generated by ARM C++ Compiler, ADS1.2 [Build 848]
; commandline [-O2 -S -apcs /ropi -fs "-IC:\ARM\RVCT_BREWv1_2\INCLUDE"]
CODE32
AREA ||.text||, CODE, READONLY
__ct__7my_rectFv PROC ; my_rect::my_rect()
;;;23 my_rect::my_rect(void)
;;;24 {
000000 e3500000 CMP r0,#0
000004 03a00010 MOVEQ r0,#0x10
000008 0afffffe BEQ __nw__FUi
00000c e1a0f00e MOV pc,lr
;;;25 return;
;;;26 }
ENDP
__ct__7my_rectFiN31 PROC ; my_rect::my_rect(int, int, int, int)
;;;28 my_rect::my_rect(int x, int y, int width, int height)
;;;29 : _x(x), _y(y), _width(width), _height(height)
000010 e92d40f8 STMFD sp!,{r3-r7,lr}
000014 e59d4018 LDR r4,[sp,#0x18]
000018 e1a07003 MOV r7,r3
00001c e1a06002 MOV r6,r2
000020 e1a05001 MOV r5,r1
000024 e3500000 CMP r0,#0
000028 1a000003 BNE |L1.60|
00002c e3a00010 MOV r0,#0x10
000030 ebfffffe BL __nw__FUi
000034 e3500000 CMP r0,#0
000038 0a000001 BEQ |L1.68|
;;;30 {
|L1.60|
00003c e580400c STR r4,[r0,#0xc]
000040 e88000e0 STMIA r0,{r5-r7}
;;;31 return;
|L1.68|
000044 e8bd80f8 LDMFD sp!,{r3-r7,pc}
;;;32 }
ENDP
func__FRC7my_rect PROC ; func(const my_rect&)
;;;44 int func(my_rect const& rect)
;;;45 {
000048 e1a0f00e MOV pc,lr
;;;46 return reinterpret_cast<int>(&rect);
;;;47 }
ENDP
main PROC
;;;49 int main(void)
;;;50 {
00004c e59f0004 LDR r0,|L1.88|
000050 e08f0000 ADD r0,pc,r0 ;41
;;;51 static my_rect::atom const rect = {0, 0, 100, 100};
;;;52
;;;53 return func(rect);
000054 e1a0f00e MOV pc,lr
|L1.88|
000058 00000000 DCD ||.constdata$1|| - {PC}
;;;54 }
ENDP
AREA ||.constdata||, DATA, READONLY, ALIGN=2
||.constdata$1||
||rect@main_0||
DCD 0x00000000
DCD 0x00000000
DCD 0x00000064
DCD 0x00000064
END
*The tricks for optimizing constanst classes may be used for character-string constants as well.














