1

LLVM MISched 指令调度程序使用处理器功能单元、管道和延迟的声明性 TableGen 描述。想象一下,试图从这些声明中确定与英特尔优化参考手册中的编码指南等效的情况。

从广义上讲,静态调度 OOO 处理器的目标/技术是什么?对于OOO处理器,它什么时候会在B之前调度指令A,什么时候在B之后调度A?

超标量处理器一次可以执行多条指令。有序处理器将只考虑原始顺序中的指令。乱序(OOO)处理器可以乱序执行指令,然后按顺序提交结果。推测对于这个问题并不重要,但我认为这些处理器是流水线的。想想 A53(有序)和 Haswell(OOO)。

OOO 处理器接下来将执行哪条指令是处理器在运行时做出的调度决策。所以这通常被称为动态调度。顺序处理器执行哪条指令是由编译器在编译程序时决定的。因此,这通常称为静态调度。

然而,编译器也静态地定位/调度 OOO 处理器。在有序和 OOO 情况下,编译器可以查看大窗口的指令;编译器必须处理寄存器压力;在这两种情况下,编译器都希望使功能单元保持忙碌。OOO 处理器通常还可以重命名寄存器,从而减少寄存器压力。

鉴于 OOO 处理器动态调度指令,提前编译器应该做些什么来帮助这一点?

4

2 回答 2

3

您通常是正确的,但编译时调度仍然可以稍微提高执行速度。发生这种情况是因为编译器可以以更优化的方式重新排列指令以加快解码速度(只有当序列满足某些约束时,x86 的旧变体才能并行解码多条指令)或将它们更紧密地打包在处理器的指令缓冲区中。引用 Robert Morgan 的“构建优化编译器”:

The compiler should schedule the insns as if the processor were
not an out-of-order execution processor.  The more effective this
schedule is, the larger the size of the effective insns buffer.

在实践中,胜利通常很小(百分之几)。

于 2020-06-01T18:07:01.443 回答
1

这实际上不是一个调度决策本身,而是一个优化。基本上,查看 LLVM 的 addILPOpts() 为 OOO 超标量后端添加的通道可以很好地了解什么是可能的。早期的 if 转换正在生成将并行运行的代码并避免必须串行运行的代码。

LLVM 具有适用于 OOO 超标量的 EarlyIfConverter 通行证。它被 PowerPC、X86、AMDGPU、SystemZ 和 AArch64 后端使用。EarlyIfConverter 并行计算两个表达式并插入一个选择以选择一个: TII->insertSelect(...)

 // Early if-conversion is for out-of-order CPUs that don't have a lot of
 // predicable instructions. The goal is to eliminate conditional branches that
 // may mispredict.
 //
 // Instructions from both sides of the branch are executed speculatively, and a
 // cmov instruction selects the result.

此 pass 由后端在 addILPOpts() 中添加。它使用ILP 并行评估两个备选方案,而不是有条件地评估一个然后另一个。

于 2020-10-24T18:09:39.613 回答