📜  在代码生成中注册分配

📅  最后修改于: 2021-06-28 15:03:47             🧑  作者: Mango

寄存器是内存层次结构中最快的位置。但是不幸的是,这种资源是有限的。它属于目标处理器最受限制的资源。寄存器分配是一个NP完全问题。但是,可以将此问题简化为图形着色以实现分配和分配。因此,好的寄存器分配器可以为难题解决有效的近似解决方案。

图–输入输出

寄存器分配器确定哪些值将驻留在寄存器中,以及哪个寄存器将保存每个这些值。它以一个具有任意数量寄存器的程序作为输入,并生成一个具有有限寄存器集的程序,该程序可以适合目标机器。 (查看图片)

分配与分配:

分配–
将无限的名称空间映射到目标计算机的该寄存器集。

  • Reg。注册模型:将虚拟寄存器映射到物理寄存器,但将过多的数量溢出到内存中。
  • 嗯给Mem。型号:将存储器位置的某些子集映射到一组名称,以对物理寄存器集进行建模。

分配可确保代码适合目标计算机的reg。在每条指令上设置。
任务 –
将分配的名称集映射到目标计算机的物理寄存器集。

  • 假设已经完成分配,以便代码可以放入物理寄存器集中。
  • 寄存器中最多指定“ k”个值,其中“ k”为否。物理寄存器。

通用寄存器分配是NP的完整问题:

  • 当(所需寄存器数)<=(可用物理寄存器数)时,用多项式时间求解。
  • 可以使用间隔图着色在线性时间内生成分配。

本地寄存器分配和分配:
在基本块内部分配的方法称为Local Reg。分配。本地注册的两种方法。分配:自上而下的方法和自下而上的方法。

自上而下的方法是一种基于“频率计数”的简单方法。确定应保存在寄存器中以及应保存在存储器中的值。

算法:

  1. 计算每个虚拟寄存器的优先级。
  2. 按优先级对寄存器进行排序。
  3. 按优先级分配寄存器。
  4. 重写代码。

超越单个块:

  • 由于控制流程进入画面,因此更加复杂。
  • 活动范围和活动范围:活动范围由彼此相关的一组定义和使用组成,因为它们即在这对指令/数据对中没有单个寄存器是通用的。

以下是在块中找出实时范围的一种方法。有效范围表示为间隔[i,j],其中i是定义,j是最后一次使用。

全局寄存器分配和分配:
1.寄存器分配器的主要问题是最大程度地减少溢出代码的影响;

  • 溢出代码的执行时间。
  • 溢出操作的代码空间。
  • 溢出值的数据空间。

2.全局分配不能保证溢出代码执行时间的最佳解决方案。
3.本地和全局分配之间的主要区别:

  • 自然而然,全球范围的结构要比本地范围复杂。
  • 在全局有效范围内,不同的引用可能执行不同的次数。 (当基本块形成循环时)

4.为了做出有关分配和分配的决定,全局分配器通常通过构建干扰图来使用图着色。
5.然后,寄存器分配器尝试为该图构造k色,其中“ k”为否。物理寄存器。

  • 万一编译器无法直接为该图构造k色,它会通过将一些值溢出到内存来修改基础代码,然后重试。
  • 溢出实际上简化了该图,从而确保算法将停止。

6. Global Allocator使用几种方法,但是,我们将看到自上而下和自下而上的分配策略。与上述方法相关的子问题。

  • 发现全球直播范围。
  • 估计泄漏成本。
  • 建立干涉图。

发现全球直播范围:
如何发现变量的实时范围?

图–在单个块中发现有效范围

上图正确解释了所有内容。让我们以Rarp为例,它是在程序点1初始化的,最后一次使用是在程序点11的。因此,Rarp的实时撕裂即Larp为[1,11]。同样,其他人也跟进。

图–发现活动范围

估算全球泄漏成本:

  • 做出溢出决定所必需的,包括-地址计算,内存操作成本和估计的执行频率。
  • 为了提高性能,通常将这些溢出值保留在激活记录中。
  • 一些嵌入式处理器提供ScratchPad内存来保存这些溢出的值。
  • 负溢出成本:单个地址的连续负载存储需要增加负担,因此需要删除,因此会产生负溢出成本。
  • 无限溢出成本:如果在定义和使用之间没有其他有效范围结束,则实时范围应具有无限溢出成本。

干扰和干扰图:

图–实时范围内的建筑物干扰图

从上图可以看出,有效范围LRa在第一个基本块中开始,在最后一个基本块中结束。因此,它将与其他所有活动范围(即Lrb,Lrc,Lrd)共享一条边。但是,Lrb,Lrc,Lrd与其他活动范围样本Lra不重叠,因此它们仅与Lra共享一条优势。

构建分配器:

  • 请注意,k可着色图查找是一个NP完全问题,因此我们需要对此进行近似估算。
  • 尝试将实时范围拆分为一些不重要的块(最常用的块)。

自上而下的着色

  1. 尝试按一些排名功能(即基于优先级)确定的顺序为实时范围上色。
  2. 如果没有颜色可用于活动范围,则分配器将调用溢出或拆分以处理未着色的颜色。
  3. 具有k个或更多邻居的实时范围称为受约束节点,并且难以处理。
  4. 无约束的节点比较容易处理。
  5. 处理泄漏:如果在某些使用范围内未发现任何颜色,则需要进行泄漏,但这当然不是最终/最终的解决方案。
  6. 实时范围拆分:对于未着色的范围,请将实时范围拆分为多个子范围,这些范围可能比原始范围的干扰少,因此至少可以对其中一些进行着色。

柴廷的想法:

  • 选择(度
  • 从图中删除该节点及其所有边缘。 (这可能会降低其他一些节点的度数,并导致更多节点的度数为k,因此必须溢出某些节点。
  • 如果不需要溢出任何顶点,请依次将顶点弹出堆栈,并以邻居不使用的颜色对其进行着色。 (尽可能重用颜色)。

合并副本以降低程度:
编译器可以使用干涉图来合并两个有效范围。因此,通过合并,您可以获得哪种类型的收益?

图–合并活动范围

比较自上而下和自下而上的分配器:

  • 自上而下的分配器可以采用自下而上的分配器中使用的“溢出和迭代”哲学。
  • “溢出和迭代”将额外的编译时间换为可能使用较少溢出代码的分配。
  • 自上而下使用优先级排序对所有约束节点进行排序。 (但是,它会以任意顺序为不受约束的节点上色)
  • 自下而上构造了一个顺序,在该顺序中,大多数节点在图中不受约束地着色。

图–合并活动范围