之前读过this关于gcc
和clang
中有符号数字模量计算的不同实现的有趣讨论,这对我来说是一个问题(不是在讨论中讨论)。
为什么要执行此操作?
if(num % 2 == 1)
从此开始(在clang
和gcc
上相似):
movl %edi, %eax
shrl $31, %eax
addl %edi, %eax
为什么我们从((num >> 31) + num)
开始?为什么要使用MSB
并将其添加到数字中?这是哪里来的?
答案 0 :(得分:2)
负% 2
的结果是负余数,除法向C舍去为0。& 1
仅适用于正数。
因此,编译器生成的代码将符号位数字相加-实质上将负数加1,这样-1
的最后一位具有0
,然后-2
拥有{{1 }}的最后一位,1
又有了-3
...然后我们将除最后一位之外的所有字符都屏蔽掉,并从结果中减去符号位,例如:
0
它的性能可能比movl %edi, %edx
shrl $31, %edx
leal (%rdi,%rdx), %eax
andl $1, %eax
subl %edx, %eax
指令略强。例如,在Core i7上,具有r32的IDIV的延迟时间为17-28,吞吐量为7-12,而在生成的代码中,所有其他这些代码的延迟均为〜1