高性能的CPU都是speculative out of order执行的,如果发现比如分支预测失误或者memory consistency之类的问题,或者是通过checkpoint进行瞬间的恢复,或者是等到retire时,利用retire map进行恢复。恢复时,会从失败的指令处彻底的刷新掉,重新执行。这时候的代价还是比较大的,那么我们是否可以利用之前错误路径上的指令的结果呢?这篇论文给出了解决方法。
首先是指令A执行时,如果完成,则将指令A的pc,源物理寄存器和目标物理寄存器进行保存到Integration Table(简称IT)中。在刷新重新执行之后,将在正确路径上执行,如果又执行到了指令A,则将A的PC地址在IT中进行索引,如果此时的指令所利用的物理寄存器和IT中保存的物理寄存器相同,那么就意味此时指令A与之前错误路径上的A所使用的物理寄存器是相同的,因此可以直接复用上一次指令的目标寄存器,也就意味着当前的指令不必执行,直接复用了上次的结果。
我们看一下作者解释的工作flow:
上图中Dynamic Inst即为动态指令流,MAP Table即为寄存器映射表,Intergation Table即为新设计的table,用于利用PC地址进行索引,寄存器进行匹配。
指令A1→A8执行,可以看出每次架构寄存器被重新赋值的时候,MAP Table中的都重新分配了物理寄存器。比如A1对X赋值为0,X映射到寄存器50,A4再次对X进行赋值时,X映射到了新的寄存器52。
需要注意的是其中存在分支A3,如果A8执行完毕时,发现A3预测错误,按照传统的工作流程,会recover后彻底的从A3处彻底执行,将A3之后分配的物理寄存器都释放掉,但是在新的设计中,在发生分支预测错误时:
- 按照常规的walk back,利用ROB中保存的映射关系,将MAP Table恢复为分支时的MAP Table,并将之前的指令的所使用的寄存器保存在IT中,比如A5指令,利用的Y的源物理寄存器为51,目标物理寄存器为53,保存在了IT中。A8指令,使用的X和Y分别为54和53,也保存在IT中;
- 重新执行时,执行到A5指令,发现利用的源物理寄存器依旧为51,因此可以直接将目标物理寄存器映射到53,bypass execution
单元,省去了++的操作; - 执行到A6时,X++,之前的A5利用的源物理寄存器为51,而此时映射到的是50,因此不能复用,因此释放之前的目标寄存器,并将X++分配到新的物理寄存器;
- 后续的W=Y*Y,依旧里用的是相同的源物理寄存器,因此可以bypass execution 单元,省去乘法操作。但是A8因为X的寄存器变了,所以仍然需要真正的执行。
最终IT在整体结构中的位置如下图所示。简而言之,IT保留了错误路径上的指令以及寄存器的映射关系,在resync时,在新的路径的指令进入流水线后,在重命名时工作,如果match则直接利用之前的寄存器的值,bypass 执行单元,直接拿到结果。
欢迎关注我的公众号《处理器与AI芯片》