12.2 ARM
12.2.1 无优化 Keil + ARM模式
main
STMFD SP!, {R4,LR}
MOV R4, #2
B loc_368
; ---------------------------------------------------------------------------
loc_35C ; CODE XREF: main+1C
MOV R0, R4
BL f
ADD R4, R4, #1
loc_368 ; CODE XREF: main+8
CMP R4, #0xA
BLT loc_35C
MOV R0, #0
LDMFD SP!, {R4,PC}
迭代计数器i存储到了R4寄存器中。
MOV R4,#2初始化i。
MOV R0,R4 和 BL f 指令组成循环体,第一个指令为f()准备参数,第二个用来调用它。
ADD R4,R4, #1 指令在每次迭代中为i加一。
CMP R4,#0xA 将i和0xA(10)比较,下一个指令BLT(Branch Less Than,分支小于)将在i<10时跳转。
否则, R0将会被写入0(因为我们的函数返回0),然后函数执行终止。
12.2.2 优化后的 Keil + ARM模式
_main
PUSH {R4,LR}
MOVS R4, #2
loc_132 ; CODE XREF: _main+E
MOVS R0, R4
BL example7_f
ADDS R4, R4, #1
CMP R4, #0xA
BLT loc_132
MOVS R0, #0
POP {R4,PC}
事实上,是一样的。
12.2.3 优化后的 Xcode(LLVM) + thumb-2 模式
_main
PUSH {R4,R7,LR}
MOVW R4, #0x1124 ; "%d
"
MOVS R1, #2
MOVT.W R4, #0
ADD R7, SP, #4
ADD R4, PC
MOV R0, R4
BLX _printf
MOV R0, R4
MOVS R1, #3
BLX _printf
MOV R0, R4
MOVS R1, #4
BLX _printf
MOV R0, R4
MOVS R1, #5
BLX _printf
MOV R0, R4
MOVS R1, #6
BLX _printf
MOV R0, R4
MOVS R1, #7
BLX _printf
MOV R0, R4
MOVS R1, #8
BLX _printf
MOV R0, R4
MOVS R1, #9
BLX _printf
MOVS R0, #0
POP {R4,R7,PC}
事实上,printf是在我的f()函数里调用的:
void f(int i)
{
// do something here
printf ("%d", i);
};
所以,LLVM不仅仅是拆解了(unroll)循环,而且还把我的短函数f()给作为内联函数看待了,这样,它把它的函数体内插了8遍,而不是用一个循环来解决。对于我们这种简短的函数来说,编译器这样做是有可能的。
当前内容版权归 Dennis Yurichev 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 Dennis Yurichev .