原始代码产生在使用gcc -O3
进行编译时遵循64位汇编:
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
(加载有效地址)instruciton经常被“滥用”,因为它能够计算简单的线性组合,如reg1 + size*reg2 + offset
除非你的编译器死脑筋,否则几乎肯定会比单纯的凡人优化得更好:-) – paxdiablo 2012-07-27 08:49:35
为什么你认为你甚至需要“优化”这个特定的函数?你有没有对其进行分析并确定性能问题? – 2012-07-27 08:55:27
“优化”是什么意思?如果你的意思是提高运行时间,我怀疑你正在试图解决错误的问题,并且你会比编译器开关更好地运行,而不是试图微调函数。也就是说,如果你真的想优化这个功能,我怀疑你最好的选择是潜入汇编代码并在那里优化;你可能会修剪掉一两个多余的操作。您可能还会发现重构对生成的汇编代码没有任何影响。 – 2012-07-27 09:05:01