Clé*_*ent 14 c gcc arm micro-optimization
是什么原因导致ARM上的GCC 7.2.1使用来自memory(lr
)的负载来处理某些常量,以及mov
在某些其他情况下使用immediate()?具体来说,我看到以下内容:
用于ARM的GCC 7.2.1编译:
extern void abc(int);
int test() { abc(1199); return 0; }
Run Code Online (Sandbox Code Playgroud)
......进入那个:
test():
push {r4, lr}
ldr r0, .L4 // ??!
bl abc(int)
mov r0, #0
pop {r4, lr}
bx lr
.L4:
.word 1199
Run Code Online (Sandbox Code Playgroud)
还有这个:
extern void abc(int);
int test() { abc(1200); return 0; }
Run Code Online (Sandbox Code Playgroud)
......进入那个:
test():
push {r4, lr}
mov r0, #1200 // OK
bl abc(int)
mov r0, #0
pop {r4, lr}
bx lr
Run Code Online (Sandbox Code Playgroud)
起初我预计1200会是某种独特的截止,但在1024(1024产生a mov r0, #1024
,而1025使用ldr
)和其他值时还有其他截止值.
为什么GCC会使用内存中的负载来获取常量,而不是使用立即数?
Chr*_*odd 17
这与在ARM指令集中编码常量操作数的方式有关.它们被编码为(无符号)8位常数和4位旋转字段 - 8位值将旋转该4位字段中值的2倍.因此,适合该形式的任何值都可以用作常量参数.
常量1200
为二进制的10010110000,因此可以编码为8位常数01001011和4的旋转.
常量1199
是二进制的10010101111,因此无法将其置于ARM常量操作数中.