编译到程序集

时间:2016-09-21 09:49:23

标签: assembly compilation compiler-construction

假设我们已经将一些程序编译成一些抽象的中间语言:我们的程序是一系列操作和决策(分支),下一步要执行的操作(基本上是一棵树)。例如:

a();
if (bla) then c();
else b(); d();
e();

现在我们需要将这个序列“打包”到我们的线性内存中,通过这样做,我们的代码必须分支(有条件而不是)。例如,可能性之一:

      CALL A
      TEST bla
      BRANCH else
      CALL C
      JMP esc
else: CALL B
      CALL D
esc:  CALL E

当然,如何在线性存储器中排列这些块有多种可能性,它们的分支/跳跃量都不同。我们的目标是尽量减少它们 问题:
 a)如何调用此问题?它有一般的名称吗? (它是BDD构造的一个例子吗?)
 b)这种问题的复杂性是什么(找到一个块的排列,使跳跃/分支的数量最小)?

1 个答案:

答案 0 :(得分:6)

你所拥有的是一堆基本块,它们在每个基本块的末尾将控制从一个传递到另一个。

您可以使用有向图轻松地对此进行建模。节点是基本块。从一个节点到另一个节点的定向弧表示(wlog)从一个块到另一个块的条件分支(有时条件为“真”)。您应该将引发的异常视为分支,并将处理程序作为块捕获。

线性化一系列块实际上是选择一系列弧。这样的序列以不带分支的块结束(例如,函数返回或应用程序退出)。

你想要做的是选择一组弧线序列(想象你将这些蓝色着色),这样剩下的弧线(想象这些弧线)是最小的。

我不知道复杂性是什么,但是因为你可以说每个节点有两个选择,所以它似乎是指数级的难度。 (在最坏的情况下,你可以有一个完全连接的图。通常推理这些图是非常昂贵的。)

我希望人们可以用贪婪的方案实现这一点,并获得相当不错的结果:重复找到最长的弧序列,将其着色为蓝色。

最大顺序化可能不是你真正想要的。想象一下,我们根据分析数据,算法知识,假设异常很少,因此概率很低,或甚至程序员提供的提示,将概率附加到每个弧。现在你想要的是具有最大概率的长链弧;这样的路径在文献中被称为“痕迹”。这可确保代码中的热路径在内存中是顺序的,从而最大化指令高速缓存的价值。以这种方式定义的非序列分支是低概率的,例如冷路径。

您仍然选择相同的复杂性。但是贪婪的方案可能会更好:通过简单地从序列中已经存在的每个节点中选择最高概率弧来形成序列。

弧色序列着色后,很容易以“正确”的顺序生成代码。

这个paper更正式地讨论了使用跟踪的“代码放置”,特别是为了降低缓存未命中的成本。它讨论了一个贪婪的选择过程,它产生了非常好的结果,以及一个更复杂但相当昂贵的时间“本地搜索”方案,可以产生出色的结果。