使用以下代码编译时,原始代码会生成以下 64 位程序集gcc -O3
:
movl %edi, %eax
leal -18(%rax), %ecx
movl %ecx, %edx
sarl $31, %edx
shrl $29, %edx
addl %edx, %ecx
andl $7, %ecx
subl %edx, %ecx
je .L2
addl $8, %eax
subl %ecx, %eax
.L2:
rep
正如对您问题的评论中所建议的,将参数更改为unsigned int
允许更大的优化并导致以下程序集:
leal -18(%rdi), %edx
movl %edi, %eax
andl $7, %edx
je .L3
leal 8(%rdi), %eax
subl %edx, %eax
.L3:
rep
8
可以通过添加7
和屏蔽来执行向上舍入到的倍数~7
。它的工作原理是这样的:如果最后三位不全为零,则将7
进位添加到第 4 位,否则不发生进位。所以你的功能可以简化为:
return (((length - 18) + 7) & ~7) + 18;
或更简单:
return ((length - 11) & ~7) + 18;
GCC 将最后一行简单地编译为:
leal -11(%rdi), %eax
andl $-8, %eax
addl $18, %eax
请注意,lea
(加载有效地址)指令经常被“滥用”,因为它能够计算简单的线性组合,如reg1 + size*reg2 + offset