关于程序计数器(PC)和条件控制转移 引起的性能差异

关于PC(程序计数器)

冯 ·诺伊曼计算机体系结构的主要内容之一就是“程序预存储,计算机自动执行”! 
处理器要执行的程序(指令序列)都是以二进制代码序列方式预存储在计算机的存储器中,处理器将这些代码逐条地取到处理器中再译码、执行,以完成整个程序的执行。 
为了保证程序能够连续地执行下去,CPU必须具有某些手段来确定下一条取指指令的地址。

程序计数器(PC )正是起到这种作用,所以通常又称之为‘指令计数器’。CPU总是按照PC的指向对指令序列进行取指、译码和执行,也就是说,最终是PC 决定了程序运行流向。故而,程序计数器(PC )属于特别功能寄存器范畴,不能自由地用于存储其他运算数据。

1、在程序开始执行前,将程序指令序列的起始地址,即程序的第一条指令所在的内存单元地址送入PC, 
2、CPU按照PC的指示从内存读取第一条指令(取指)。 
3、当执行指令时,CPU自动地修改PC的内容,即每执行一条指令PC增加一个量,这个量等于指令所含的字节数(指令字节数),使PC总是指向下一条将要取指的指令地址。 
4、由于大多数指令都是按顺序来执行的,所以修改PC的过程通常只是简单的对PC 加“指令字节数”。但是,当遇到转移指令如JMP(跳转、外语全称:JUMP)指令时,后继指令的地址(即PC的内容)必须从指令寄存器中的地址字段取得。在这种情况下,下一条从内存取出的指令将由转移指令来规定,而不像通常一样按顺序来取得。因此程序计数器的结构应当是具有寄存信息和计数两种功能的结构。

5、当程序转移时,转移指令执行的最终结果就是要改变PC的值,此PC值就是转去的目标地址。 
6、处理器总是按照PC指向,取指、译码、执行,以此实现了程序转移。

总之:在CPU控制部件中的程序计数器(PC)的功能是用于存放指令的地址。程序执行时,PC的初值为程序第一条指令的地址,在顺序执行程序时,控制器首先按程序计数器所指出的指令地址从内存中取出一条指令,然后分析和执行该指令,同时将PC的值加1指向下一条要执行的指令


处理器通过使用流水线来获得高性能,在流水线中,一条指令的处理要经过一系列的阶段,每个阶段执行所需操作的一小部分(例如,从内存取指令、确认指令类型、从内存读数据、执行算数运算、向内存或者寄存器写数据、以及更新程序计数器),在取一条指令时候,他可能同时在进行对上一条指令的算术运算。

第五条说明在你用条件控制转移的时候,最终结果就是要改变的PC的值,这么说的话,要等到条件控制转移相关指令执行完毕后才能决定下一条指令的地址。
对于这种情况处理器采用非常精密的分之预测逻辑来猜测每条跳转指令是否会执行(如果不判断的话,就百分百会损失这部分效率)。错误预判会招致处理器丢掉它为该跳转指令后的所有指令已做的工作,然后从正确的位置起始的指令填充流水线。大概会浪费15~30个时钟周期!!

但是如果把条件控制转移换成条件数据传送的话,就能避免错误判断带来效率损失。不论是否传送条件,都不影响他后面的指令进流水线。

举个例子:

long absdiff(long x, long y)
{
  long result;  

  if(x < y)
    result = y - x;
  else
    result = x - y;
  return result;
}

如果我用gcc -O1 来编译

他直接用了comvl指令来代替jump

注意,程序前面已经把a-b和b-a都求出来了,即先求出条件操作的两种结果,然后再根据条件是否满足从而选取一个。 (错错错)
两个都求出来了,把一种放入%rax,然后根据条件是否满足来决定是否更新为另外一种或者保持不变。
总之,条件传送指令使得控制流不依赖于数据(关键是没了jump,不用预测,也可以照常让后面的指令进流水线),流水线也更容易保持满状态。 
原文地址:https://www.cnblogs.com/BMing/p/10514043.html