我不知道gcc和java jit是否能够识别SHIFT和OR运算符序列可以简化为ROTATE指令,这很有趣。
g ++编译器展开循环,使用
SHIFT immediate和
ROTATE immediate指令(因为您按常数移动和旋转)。
这是在TimeShift循环展开情况下重复的六个指令序列:
movq %rax, %rbxsalq $13, %rbxleaq (%rbp,%rbx), %rbxmovq %rdi, %rbpsarq $27, %rbpxorq %rbx, %rdx
这是在TimeRotate循环展开情况下重复的六个指令序列:
movq %rdx, %rbxrorq $45, %rbxleaq (%rbp,%rbx), %rbxmovq %r8, %rbprorq $49, %rbpxorq %rbx, %r9
它们的主要区别在于salq / sarq forSHIFT和rorq for的用法不同,ROTATE
因此您想知道为什么时间不同是正确的。
答案深在Sandy Bridge(您的Core i5
处理器)的微体系结构中,可在INTEL®64和IA-32处理器体系结构
优化参考
手册中找到。Order Number: 248966-026 April 2012
SHIFT无论使用by 1操作码
还是,该指令都有1个周期的延迟by immediate。可以调度从任一Port 0或者Port 1和用于
这个原因具有0.5周期的吞吐量-处理器可以分派和退休
2点SHIFT immediate每一周期的指令。如果ROTATE需要
条件标志的结果(它们不在
gcc生成的代码中),则该指令需要三个微操作;如果不需要,则需要两个微操作(在
您的情况下为两个微操作)。ROTATE但是,该指令只能从中分派
Port 1,因此具有1个周期的吞吐量-处理器每个周期
只能分派和退出一个ROTATE immediate。
我已经复制了下面的相关图像和部分。
3.5.1.5按位旋转
按位旋转可以在CL
寄存器中指定的计数旋转,立即数和1位之间进行选择。通常,
立即旋转和寄存器旋转指令比旋转1位要慢。
旋转1指令的延迟与移位相同。
汇编/编译器编码规则35。(ML影响,L通用)避免通过
寄存器进行ROTATE或通过立即指令进行ROTATE。如果可能,用“
ROTATE by 1”指令代替。在英特尔微体系结构代码名称Sandy Bridge中,
按立即数进行的ROL / ROR具有1个周期的吞吐量,按立即数使用与
源和目标相同的寄存器的SHLD / SHRD具有1个周期的吞吐量
具有0.5个周期吞吐量的延迟。“ ROL / ROR reg,imm8”指令具有两个
微操作
,如果使用,其旋转寄存器结果的延迟为1个周期,标志的延迟为2个周期。在英特尔微体系结构代码名称Ivy
Bridge中,
使用溢出标志结果时,立即大于1的“ ROL / ROR reg,imm8”指令是一个微循环,具有一个周期的延迟。
当立即数为1时,后续指令对ROL / ROR溢出标志结果的依赖性将使ROL / ROR指令具有两个周期的
延迟。
2.4.4.2执行单元和发布端口
在每个周期,核心可以将µops调度到四个发布端口中的一个或多个。
在微体系结构级别,存储操作进一步分为两
部分:存储数据和存储地址操作。 图2-6
中显示了将μop分配到执行单元以及进行加载和存储操作的四个端口。一些端口每个时钟可以调度两个µop。这些
执行单元标记为Double Speed。
端口0。在周期的前半部分,端口0可以调度一个浮点移动µop(浮点堆栈移动,浮点交换
或浮点存储数据)或一个算术逻辑单元(ALU)µop(算术,逻辑,分支或存储数据)。在周期的后半部分,它
可以派出一个类似的ALU µop。
端口1。在周期的前半部分,端口1可以调度一个浮点执行(除移动,所有SIMD操作外的所有浮点操作)μop或一个正常速度整数(乘,移位和旋转)μop或1个ALU(算术)µop。在周期的后半部分,它可以派出
一个类似的ALU µop。
端口2。此端口支持每个周期调度一次装载操作。
端口3。此端口支持每个周期分派一个存储地址操作。
每个周期的总发行带宽范围为零到六微欧。每个管道包含几个执行单元。µop将被分派到
与正确操作类型相对应的管道。例如,整数算术逻辑单元和浮点执行单元(加法器,乘法器和除法器)可以共享管线。



