一种针对混合长度指令集的寄存器分配方法.pdf

上传人:00****42 文档编号:975366 上传时间:2018-03-22 格式:PDF 页数:12 大小:528.87KB
返回 下载 相关 举报
摘要
申请专利号:

CN201110333460.2

申请日:

2011.10.28

公开号:

CN102360280A

公开日:

2012.02.22

当前法律状态:

授权

有效性:

有权

法律详情:

授权|||实质审查的生效IPC(主分类):G06F 9/30申请日:20111028|||公开

IPC分类号:

G06F9/30; G06F9/318

主分类号:

G06F9/30

申请人:

浙江大学

发明人:

李莹; 闫卫斌; 吴朝晖; 尹建伟; 邓水光; 吴健

地址:

310027 浙江省杭州市西湖区浙大路38号

优先权:

专利代理机构:

杭州裕阳专利事务所(普通合伙) 33221

代理人:

江助菊

PDF下载: PDF下载
内容摘要

本发明公开了一种针对混合长度指令集的寄存器分配方法,通过对传统的图着色寄存器分配方法上进行少量的修改,即可充分利用混编指令集的特点,生成代码密度更高的代码,具有简单实用,可靠性强的特点。

权利要求书

1: 一种针对混合长度指令集的寄存器分配方法, 其特征在于, 包括如下步骤 : 1) 查找函数中的所有生命周期, 通过设置标志位是否置位来判断设该生命期为 A 类生 命期还是 B 类生命期 ; 2)执 行 图 着 色 寄 存 器 分 配 方 法 的 Renumber1、 build1、 coalesce1、 spill cost1、 和 simplify1 五个过程, 为所有 A 类生命期分配 lo-regs 寄存器, 得到未进行任何溢出操作的 冲突图 G1 ; 3) 计算空闲 lo-regs 寄存器数 m, 如果所述冲突图 G1 非空, 则空闲 lo-regs 寄存器数 m 为 0, 如果所述冲突图 G1 为空图, 则执行图着色寄存器分配方法的 select1 过程, 并根据生 成的寄存器分配方案计算空闲的 lo-regs 寄存器数 m, 并记录空闲寄存器信息 ; 4)执行图着色寄存器分配方法的 Renumber2、 build2、 coalesce2、 simplify2 、 spill code2 和 select2 过程, 为 B 类生命期分配 hi-regs 寄存器和 m 个空闲的 lo-regs 寄存器, 并根据生成的分配方案计算空闲的 hi-regs 寄存器数量 n, 并记录空闲寄存器信息 ; 5) 执行图着色寄存器分配方法的 spill code1 和 select1 过程, 如果 select1 过程已经 在步骤 3) 执行则结束所有步骤, 如果没有, 则重复执行 spill code1 、 Renumber1、 build1、 coalesce1、 spill cost1、 simplify1 过程直到所述冲突图 G1 为空, 然后执行 select1 过程 为 A 类生命期生成寄存器分配方案 ; Renumber1、 build1、 coalesce1、 spill cost1、 simplify1 、 spill code1 、 select1、 Renumber2、 build2、 coalesce2、 spill cost2、 simplify2 、 spill code2 和 select2 过程均为 图着色寄存器分配方法的步骤 ; 所述图着色寄存器分配方法包括如下步骤 : 11) Renumber : 在数据流分析的基础上, 找到函数中的所有生命期, 并为其分配唯一的 编号, 其中一个生命期从一个变量的一次定值开始, 到对该值的最后一次使用结束 ; 12) build: 建立冲突图 G, 所述冲突图 G 中的结点为生命期, 边则表示通过其相连的两 个生命期有冲突, 不能为它们分配同一个寄存器 ; 13) coalesce : 判断是否需要合并生命期, 如需要则通过合并生命期删除不必要的复制 语句, 合并后返回, 重新执行步骤 12) , 如不需要合并, 则执行步骤 14) ; 14) spill cost : 计算每个生命期的溢出代价 ; 15) simplify : 对所述冲突图 G 进行简化, 反复地检查图 G, 删除 G 中度数小于可用寄存 器数 k 的节点, 删除的同时将该节点压入栈 s ; 16) spill code : 当所述冲突图 G 中所有节点的度都大于等于 k 时, 需要将溢出代价最 小的生命期溢出, 即删除其节点, 将其压入栈 s, 并将其标记为溢出, 溢出一个生命期之后返 回执行步骤 11) ; 17) select : 当所述冲突图 G 为空时, 将栈 s 中的生命期弹出, 为其分配寄存器, 并为标 记为溢出的生命期插入溢出代码 ; 所述 lo-regs 寄存器为短指令可寻址的寄存器, 剩下的为所述 hi-regs 寄存器, 所述标 志位是否置位的标准为 : 将有 A 类指令引用的生命期设为置位, 将只有 B 类指令引用的生命 期设为不置位 ; 所述 A 类指令为一条指令最终生成的机器指令是长指令还是短指令取决于其分配到 的寄存器 ; 2 所述 B 类指令为不论其寄存器操作数分配到哪个寄存器, 其必然生成一条长指令, 或 者必然生成一条短指令。
2: 根据权利要求 1 所述的一种针对混合长度指令集的寄存器分配方法, 其特征在于, 所述标志位设于记录生命期信息的结构体中。
3: 根据权利要求 1 所述的一种针对混合长度指令集的寄存器分配方法, 其特征在于, 所述步骤 5) 中 spill code1 的过程包括如下步骤 : 31) 在构造所述冲突图 G1 保存一个所述冲突图 G1 的备份冲突图 G1-backup ; 32) 每次 simplify1 决定溢出某个生命期 l 时, 首先判断是否有空闲的 hi-regs 寄存 器可用于溢出, 如果有, 那么在 l 的每次赋值后和使用前插入 move 指令, 并记录生命期 l 溢 出到 hi-regs 寄存器的信息 ; 并且当每个 hi-regs 寄存器都已经有关联的溢出生命期时, 根 据所述备份冲突图 G1-backup 判断是否有寄存器关联的所有溢出生命期都不与当前要溢出 的生命期 l 冲突, 如果有这样的寄存器, 那么它可用于 l 的溢出, 如果没有空闲的 hi-regs 用于溢出, 那么 spill code1 使用 load/store 指令将生命期溢出到存储器。

说明书


一种针对混合长度指令集的寄存器分配方法

    【技术领域】
     本发明涉及一种编译技术, 尤其涉及一种针对混合长度指令集的寄存器分配方法。 背景技术
     嵌入式系统常采用 RISC 架构, 其指令集一般为定长指令集, 即只具有单一长度的 指令。指令长度一般为整数个字节, 例如, 16 位指令, 32 位指令。较长的指令长度可以编码 更多的操作数, 寻址更多的寄存器, 或者可使用更大的立即数等, 故一般具有更好的性能 ; 而较短的指令长度可以使得编译生成的可执行程序更小。 为了在具有长指令高性能的同时 具有短指令的高代码密度, 现代的 RISC 处理器开始采用两种或者两种以上不同长度指令 混合编码的指令集。例如, ARM 的 thumb2 指令集和中天微公司的 cskyv2 指令集都是 16 位 与 32 位指令混合编码的指令集 (以下简称 “混编指令集” ) 。 在混编指令集中, 短指令相比长指令而言, 寻址的操作数个数少, 可编码的立即 数范围小, 或者单个地址只可使用部分寄存器。例如, 在 cskyv2 指令集中, 长指令可使用 R0~R31 全部共 32 个通用寄存器, 而绝大多数短指令只可使用 R0~R15 共 16 个通用寄存器 ; 长指令一般具有 3 操作数, 而短指令最多只有 2 操作数。短指令在功能上是长指令的一个 子集。通常, 编译器按照长指令的功能来生成汇编指令, 而汇编器生成机器指令时, 会根据 指令的类型和其操作数来决定生成长指令还是短指令。
     以 cskyv2 为例, 如果一条指令的某个寄存器操作数被分配了 R16~R31 的寄存 器, 那么该指令将生成一条长指令 (个别指令除外, 下外将介绍) ; 但一条指令即使只使用 R0~R15 的寄存器, 它也并不一定生成短指令, 因为它可能使用了超出短指令可编码范围的 立即数, 或者使用了 3 个不同的操作数等等。以 cskyv2 为例, 如果一条指令的某个寄存器 操作数被分配了 R16~R31 的寄存器, 那么该指令将生成一条长指令 (个别指令除外, 下外将 介绍) ; 但一条指令即使只使用 R0~R15 的寄存器, 它也并不一定生成短指令, 因为它可能使 用了超出短指令可编码范围的立即数, 或者使用了 3 个不同的操作数, 等等。如果一条指令 最终生成的机器指令是长指令还是短指令取决于其分配到的寄存器 (以下简称 A 类指令) ; 反之, 如果不论其寄存器操作数分配到哪个寄存器, 其必然生成一条长指令, 或者必然生成 一条短指令 (以下简称 B 类指令) 。 如何以较小的代价使得所有的 A 类指令最终生成的机器 指令为短指令, 是技术人员需要克服的难点。
     发明内容
     针对上述技术难点, 本发明的提出一种针对混合长度指令集的寄存器分配方法。
     为了解决上述技术问题, 本发明的技术方案如下 : 一种针对混合长度指令集的寄存器分配方法, 包括如下步骤 : 1) 查找函数中的所有生命周期, 通过设置标志位是否置位来判断设该生命期为 A 类 生命期还是 B 类生命期 ;2) 执行图着色寄存器分配方法的 Renumber1、 build1、 coalesce1、 spill cost1、 和 simplify1 五个过程, 为所有 A 类生命期分配 lo-regs 寄存器, 得到未进行任何溢出操作的 冲突图 G1 ; 3) 计算空闲 lo-regs 寄存器数 m, 如果所述冲突图 G1 非空, 则空闲 lo-regs 寄存器数 m 为 0, 如果所述冲突图 G1 为空图, 则执行图着色寄存器分配方法的 select1 过程, 并根据生 成的寄存器分配方案计算空闲的 lo-regs 寄存器数 m, 并记录空闲寄存器信息 ; 4) 执行图着色寄存器分配方法的 Renumber2、 build2、 coalesce2、 simplify2 、 spill code2 和 select2 过程, 为 B 类生命期分配 hi-regs 寄存器和 m 个空闲的 lo-regs 寄存器, 并根据生成的分配方案计算空闲的 hi-regs 寄存器数量 n, 并记录空闲寄存器信息 ; 5) 执行图着色寄存器分配方法的 spill code1 和 select1 过程, 如果 select1 过程已 经在 步骤 3)执行, 则步骤结束, 如果没有, 重复执行 spill code1 、 Renumber1、 build1、 coalesce1、 spill cost1、 simplify1 过程直到所述冲突图 G1 为空, 然后执行 select1 过程 为 A 类生命期生成寄存器分配方案 ; Renumber1、 build1、 coalesce1、 spill cost1、 simplify1 、 spill code1 、 select1、 Renumber2、 build2、 coalesce2、 spill cost2、 simplify2 、 spill code2 和 select2 过程均为 图着色寄存器分配方法的步骤 ; 所述图着色寄存器分配方法包括如下步骤 : 11) Renumber : 在数据流分析的基础上, 找到函数中的所有生命期, 并为其分配唯一的 编号, 其中一个生命期从一个变量的一次定值开始, 到对该值的最后一次使用结束 ; 12) build: 建立冲突图 G, 所述冲突图 G 中的结点为生命期, 边则表示通过其相连的两 个生命期有冲突, 不能为它们分配同一个寄存器 ; 13) coalesce : 判断是否需要合并生命期, 如需要则通过合并生命期删除不必要的复制 语句, 合并后返回, 重新执行步骤 12) , 如不需要合并, 则执行步骤 14) ; 14) spill cost : 计算每个生命期的溢出代价 ; 15) simplify : 对所述冲突图 G 进行简化, 反复地检查图 G, 删除 G 中度数小于可用寄存 器数 k 的节点, 删除的同时将该节点压入栈 s ; 16) spill code : 当所述冲突图 G 中所有节点的度都大于等于 k 时, 需要将溢出代价最 小的生命期溢出, 即删除其节点, 将其压入栈 s, 并将其标记为溢出, 溢出一个生命期之后返 回执行步骤 11) ; 17) select : 当所述冲突图 G 为空时, 将栈 s 中的生命期弹出, 为其分配寄存器, 并为标 记为溢出的生命期插入溢出代码 ; 所述 lo-regs 寄存器为短指令可寻址的寄存器, 剩下的为所述 hi-regs 寄存器, 所述标 志位是否置位的标准为 : 将有 A 类指令引用的生命期设为置位, 将只有 B 类指令引用的生命 期设为不置位 ; 所述 A 类指令为一条指令最终生成的机器指令是长指令还是短指令取决于其分配到 的寄存器 ; 所述 B 类指令为不论其寄存器操作数分配到哪个寄存器, 其必然生成一条长指令, 或 者必然生成一条短指令。进一步的, 所述标志位设于记录生命期信息的结构体中。
     进一步的, 所述步骤 5) 中 spill code1 的过程包括如下步骤 : 31) 在构造所述冲突图 G1 保存一个所述冲突图 G1 的备份冲突图 G1-backup ; 32) 每次 simplify1 决定溢出某个生命期 l 时, 首先判断是否有空闲的 hi-regs 寄存 器可用于溢出, 如果有, 那么在 l 的每次赋值后和使用前插入 move 指令, 并记录生命期 l 溢 出到 hi-regs 寄存器的信息 ; 并且当每个 hi-regs 寄存器都已经有关联的溢出生命期时, 根 据所述备份冲突图 G1-backup 判断是否有寄存器关联的所有溢出生命期都不与当前要溢出 的生命期 l 冲突, 如果有这样的寄存器, 那么它可用于 l 的溢出, 如果没有空闲的 hi-regs 用于溢出, 那么 spill code1 使用 load/store 指令将生命期溢出到存储器。
     本发明的有益效果在于 : 适用于具有两种或两种以上不同长度指令, 并且其中较 短指令可访问寄存器的集合为较长指令可访问寄存器的集合的子集的指令集, 本发明可提 高生成代码的指令密度, 并且简单实用, 可靠性强, 最终以较小的代价使得所有的 A 类指令 最终生成的机器指令为短指令。 附图说明
     图 1 为图着色寄存器分配方法的基本流程图 ; 图 2 为本发明的具体实施流程图 ; 图 3 为标记生命期类型流程图 ; 图 4 为 spill code1 流程图 ; 图 5 为备份的冲突图的部分图。具体实施方式
     下面将结合附图和具体实施方式对本发明做进一步的说明。
     本发明是一种在图着色寄存器分配法基础上进行改进的寄存器分配方法。 图着色 是传统的, 也是最为常用的寄存器分配方法, 其基本流程如图 1 所示, 各阶段的简要说明如 下: 重命名 (Renumber) : 在本阶段之前, 中间代码可以引用数目无限的 “虚拟寄存器” 。本 阶段在数据流分析的基础上, 找到函数中的所有生命期, 并为其分配唯一的编号。 一个生命 期从一个变量的一次定值开始, 到对该值的最后一次使用结束。
     构造冲突图 (Build): 本阶段建立 “冲突图 G” , G 中的结点为生命期, 边则表示通 过其相连的两个生命期有冲突, 即它们在某条指令处同时活跃, 故不能为它们分配同一个 寄存器。
     合并生命期 (Coalesce): 本阶段通过合并生命期来删除不必要的复制语句。 合并 生命期改变了冲突图, 故合并之后需要重新执行 “Build” 过程。
     溢出代价分析 (Spill cost): 本阶段用于计算每个生命期的溢出代价。
     简化冲突图 (Simplify): 本阶段中对冲突图 G 进行简化, 反复地检查图 G, 删除 G 中度数小于可用寄存器数 k 的节点, 删除的同时将该节点压入栈 s。
     插 入 溢 出 代 码 (Spill code): 当 图 G 中 所 有 节 点 的 度 都 大 于 等 于 k 时, “Simplify” 过程无法继续。此时, 需要将溢出代价最小的生命期溢出, 即删除其节点, 将其 压入栈 s, 并将其标记为溢出。溢出一个生命期之后需要从 “重命名” 阶段重新开始执行图着色算法。
     着色 (Select): 图 G 最终会被简化为一个空图, 此时将栈 s 中的生命期弹出, 为其 分配寄存器, 并为标记为溢出的生命期插入溢出代码。
     首先将寄存器进行分类, 其中大多数短指令可寻址的寄存器称为 lo-regs, 而其余 的寄存器称为 hi-regs。然后为每个生命期增加一个标志位, 标记其是否曾被 A 类指令引 用, 将只有 B 类指令引用的生命期称为 “B 类生命期” ; 而将有 A 类指令引用的生命期称为 “A 类生命期” , 并通过扫描整个函数的指令流为每个生命期设置该标记。
     接 着 执 行 两 个 图 着 色 过 程, 为 A 类 生 命 期 分 配 lo-regs, 为 B 类生命期分配 hi-regs ; 如果 lo-regs、 hi-regs 分别足够 A 类生命期、 B 类生命期使用, 或者两个图着色 过程寄存器都不足, 都需要溢出生命期, 那么这两个图着色过程独立进行。如果 lo-regs 足 够 A 类生命期分配且有空闲, 但 hi-regs 不够 B 类生命期分配, 那么将 lo-regs 中空闲的寄 存器和 hi-regs 寄存器一起分配给 B 类生命期。反之, 如果 hi-regs 有空闲而 lo-regs 不 足, 那么在 lo-regs 分配过程中生成溢出代码时, 优先将生命期溢出到空闲的 hi-regs, 当 无 hi-regs 寄存器可进行溢出时才溢出到存储器。
     本方法的具体实现流程如图 2 所示, 具体步骤如下 : 一、 生命期标记。 本阶段查找函数中的所有生命期 ; 并通过扫描当前函数的所有指令对 每个生命期的类型进行标记。 二、 Renumber1、 build1、 coalesce1、 spill cost1、 和 simplify1。本步骤执行图着色 算法流程中的前 5 个阶段, 为所有 A 类生命期分配 lo-regs 寄存器。本步骤执行结束后, 将 得到未进行任何溢出操作的冲突图 G1。
     三、 计算空闲 lo-regs 寄存器数。本步骤计算空闲的 lo-regs 寄存器数 m, 如果 G1 非空, 那么 m 为 0 ; 反之, 如果 G1 为空图, 那么我们执行 select1 过程, 并根据生成的寄存器 分配方案计算空闲的 lo-regs 寄存器数, 并记录空闲寄存器信息。
     四、 Renumber2、 build2、 coalesce2、 spill cost2、 simplify2 、 spill code2 和 select2。本步骤是一个完整的传统图着色寄存器分配过程。我们使用这一过程为 B 类生 命期分配 hi-regs 寄存器和 m 个空闲的 lo-regs 寄存器。并根据生成的分配方案计算空闲 的 hi-regs 寄存器数量 n, 并记录空闲寄存器信息。
     五、 spill code1 和 select1。如果 G1 为空, 那么 select1 已在步骤三中执行, 整 个算法结束 ; 否则, 重复执行 spill code1 、 Renumber1、 build1、 coalesce1、 spill cost1、 simplify1 过程, 直到 G1 为空, 然后 select1 为 A 类生命期生成寄存器分配方案。本步骤的 特殊之处在于, 如果 n>0, 那么在执行插入 spill code1 时, 我们优先将生命期溢出到空闲的 hi-regs 寄存器, 只有当无 hi-regs 寄存器可用时, 才将生命期溢出到存储器。这样做的优 点在于使用 move 指令生成的将生命期溢出到空闲的 hi-regs 寄存器的代码, 其执行速度一 般要快于使用 load/store 执行生成的将生命期溢出到存储器的代码。
     另外, 混编指令集通常提供特殊的短指令—— move, 它是一条短指令, 但可以寻址 所有的寄存器。此时, 使用 move 指令生成的将生命期溢出到空闲 hi-regs 寄存器的代码相 比溢出到存储器将更加高效 (使用了短指令进行溢出, 而不是通常的长指令) 。
     本方法只需要在传统的图着色寄存器分配方法上进行少量的修改, 即可充分利用 混编指令集的特点, 生成代码密度更高的代码, 具有简单实用, 可靠性强的特点。
     下面结合具体实例进行更加详细的说明 : 首先, 在记录生命期信息的结构体中增加一个标志位 flag_short, 如果该标志位置位, 则说明该生命期是一个 A 类生命期, 否则其为一个 B 类生命期。在 “生命期识别” 过程结束 后, 增加一个 “标记生命期类型” 的过程, 如图 3 所示。该过程通过依次扫描当前函数中的 每一条指令, 为每一个生命期设置 flag_short 标志。
     然后, 需要执行两个图着色过程。其中 select1 为所有 A 类生命期分配 lo-regs 寄存器 ; select2 为所有 B 类生命期分配 hi-regs 寄存器以及可能的空闲 lo-regs 寄存器。 并且 select2 可能在 select1 完成之后执行, 也可能在 select1 的第一次简化冲突图 G1 过 程后执行, 如图 2 所示。这取决于 lo-regs 是否足够 A 类生命期分配, 如果足够使用, 那么 select1 首先执行完毕, 这样剩余的空闲 lo-regs 能够提供给 select2 阶段进行分配 ; 否则, select1 在执行第一次 simplify1 过程后, 执行整个 select2 流程, 这样如果 select2 过程有 空闲的 hi-regs 的话, 它们可以用于 select1 的插入 spill code1 阶段。总之, 我们使用了 select1、 select2 两个图着色过程, 其中 select1 为所有 flag_short 为 true 的生命期分配 lo-regs 寄存器 ; select2 为所有 flag_short 为 false 的生命期分配 hi-regs 寄存器和可 能的空闲 lo-regs 寄存器。这两个图着色过程中, 本发明只需要在传统的图着色算法中增 加一个对生命期的 flag_short 标志的判断, 使 select1、 select2 分别处理 flag_short 为 true、 false 的生命期, 并简单的重新组织 select1、 select2 的执行流程即可。
     最后, 本发明还可以修改传统图着色算法的溢出过程插入 spill code1, 其流程如 图 4 所示。首先, 在执行构造冲突图 G1 过程时, 需要保存一个备份的冲突图 G1-backup ; 然 后在每次简化冲突图 G1 决定溢出某个生命期 l 时, 首先判断是否有空闲的 hi-regs 可用 于溢出, 如果有, 那么在 l 的每次赋值后和使用前插入 move 指令, 并记录生命期 l 溢出到 hi-regs 的信息。需要注意的是, 当每个 hi-regs 都已经有关联的溢出生命期时, 并不意味 着没有 hi-regs 可用于溢出 ; 这时, 需要根据 G1-backup 判断是否有某个寄存器, 其关联的 所有溢出生命期都不与当前要溢出的生命期 l 冲突, 如果有这样的寄存器, 那么它可用于 l 的溢出。如果没有空闲的 hi-regs 用于溢出, 那么 spill code1 执行与传统图着色算法同 样的过程, 即使用 load/store 指令将生命期溢出到存储器。
     以下是一个溢出到寄存器的例子, 首先给出在构造冲突图 G1 执行结束后备份的 G1-backup, 如下图所示 (为了简化说明, 示意图中只包括 4 个生命期, 可以认为是冲突图的 一小部分) : 假设有两个空闲的 hi-regs 寄存器 R1, R2 可用于溢出, 现在需要溢出生命期 3, 而之前 的溢出操作对 hi-regs 的使用情况如下表 :hi-regs 寄存器 R1 R2 已溢出的生命期 1 2表hi-regs 寄存器溢出情况记录如流程图 4 所示, 首先得到第一个可用于溢出的 hi-regs 寄存器 R1, 并且根据上表 可知, 生命期 1 已经溢出到了 R1, 而当前要溢出生命期 3, 根据备份的冲突图 G1-backup, 可知生命期 1、 3 有冲突, 故 R1 不能用于溢出生命期 3。接下来, 得到第二个可用于溢出的 hi-regs 寄存器 R2, 根据 G1-backup 可知, 生命期 2、 3 无冲突, 说明生命期 3 活跃的时间段内, 生命期 2 已经不再使用, 故可以将生命期 3 溢出到 R2, 将该信息填入表 1, 并在需要使用 生命期 2 的地方插入 move 指令将其值从 R2 拷贝到相应的 lo-regs 寄存器, 在使用结束之 后插入 move 指令将其值从相应的 lo-regs 寄存器拷贝到 R2。
     以上所述仅是本发明的优选实施方式, 应当指出, 对于本技术领域的普通技术人 员, 在不脱离本发明构思的前提下, 还可以做出若干改进和润饰, 这些改进和润饰也应视为 本发明保护范围内。

一种针对混合长度指令集的寄存器分配方法.pdf_第1页
第1页 / 共12页
一种针对混合长度指令集的寄存器分配方法.pdf_第2页
第2页 / 共12页
一种针对混合长度指令集的寄存器分配方法.pdf_第3页
第3页 / 共12页
点击查看更多>>
资源描述

《一种针对混合长度指令集的寄存器分配方法.pdf》由会员分享,可在线阅读,更多相关《一种针对混合长度指令集的寄存器分配方法.pdf(12页珍藏版)》请在专利查询网上搜索。

1、10申请公布号CN102360280A43申请公布日20120222CN102360280ACN102360280A21申请号201110333460222申请日20111028G06F9/30200601G06F9/31820060171申请人浙江大学地址310027浙江省杭州市西湖区浙大路38号72发明人李莹闫卫斌吴朝晖尹建伟邓水光吴健74专利代理机构杭州裕阳专利事务所普通合伙33221代理人江助菊54发明名称一种针对混合长度指令集的寄存器分配方法57摘要本发明公开了一种针对混合长度指令集的寄存器分配方法,通过对传统的图着色寄存器分配方法上进行少量的修改,即可充分利用混编指令集的特点,生成。

2、代码密度更高的代码,具有简单实用,可靠性强的特点。51INTCL19中华人民共和国国家知识产权局12发明专利申请权利要求书2页说明书6页附图3页CN102360297A1/2页21一种针对混合长度指令集的寄存器分配方法,其特征在于,包括如下步骤1)查找函数中的所有生命周期,通过设置标志位是否置位来判断设该生命期为A类生命期还是B类生命期;2)执行图着色寄存器分配方法的RENUMBER1、BUILD1、COALESCE1、SPILLCOST1、和SIMPLIFY1五个过程,为所有A类生命期分配LOREGS寄存器,得到未进行任何溢出操作的冲突图G1;3)计算空闲LOREGS寄存器数M,如果所述冲突。

3、图G1非空,则空闲LOREGS寄存器数M为0,如果所述冲突图G1为空图,则执行图着色寄存器分配方法的SELECT1过程,并根据生成的寄存器分配方案计算空闲的LOREGS寄存器数M,并记录空闲寄存器信息;4)执行图着色寄存器分配方法的RENUMBER2、BUILD2、COALESCE2、SIMPLIFY2、SPILLCODE2和SELECT2过程,为B类生命期分配HIREGS寄存器和M个空闲的LOREGS寄存器,并根据生成的分配方案计算空闲的HIREGS寄存器数量N,并记录空闲寄存器信息;5)执行图着色寄存器分配方法的SPILLCODE1和SELECT1过程,如果SELECT1过程已经在步骤3)。

4、执行则结束所有步骤,如果没有,则重复执行SPILLCODE1、RENUMBER1、BUILD1、COALESCE1、SPILLCOST1、SIMPLIFY1过程直到所述冲突图G1为空,然后执行SELECT1过程为A类生命期生成寄存器分配方案;RENUMBER1、BUILD1、COALESCE1、SPILLCOST1、SIMPLIFY1、SPILLCODE1、SELECT1、RENUMBER2、BUILD2、COALESCE2、SPILLCOST2、SIMPLIFY2、SPILLCODE2和SELECT2过程均为图着色寄存器分配方法的步骤;所述图着色寄存器分配方法包括如下步骤11)RENUMBE。

5、R在数据流分析的基础上,找到函数中的所有生命期,并为其分配唯一的编号,其中一个生命期从一个变量的一次定值开始,到对该值的最后一次使用结束;12BUILD建立冲突图G,所述冲突图G中的结点为生命期,边则表示通过其相连的两个生命期有冲突,不能为它们分配同一个寄存器;13)COALESCE判断是否需要合并生命期,如需要则通过合并生命期删除不必要的复制语句,合并后返回,重新执行步骤12),如不需要合并,则执行步骤14);14)SPILLCOST计算每个生命期的溢出代价;15)SIMPLIFY对所述冲突图G进行简化,反复地检查图G,删除G中度数小于可用寄存器数K的节点,删除的同时将该节点压入栈S;16)。

6、SPILLCODE当所述冲突图G中所有节点的度都大于等于K时,需要将溢出代价最小的生命期溢出,即删除其节点,将其压入栈S,并将其标记为溢出,溢出一个生命期之后返回执行步骤11);17)SELECT当所述冲突图G为空时,将栈S中的生命期弹出,为其分配寄存器,并为标记为溢出的生命期插入溢出代码;所述LOREGS寄存器为短指令可寻址的寄存器,剩下的为所述HIREGS寄存器,所述标志位是否置位的标准为将有A类指令引用的生命期设为置位,将只有B类指令引用的生命期设为不置位;所述A类指令为一条指令最终生成的机器指令是长指令还是短指令取决于其分配到的寄存器;权利要求书CN102360280ACN102360。

7、297A2/2页3所述B类指令为不论其寄存器操作数分配到哪个寄存器,其必然生成一条长指令,或者必然生成一条短指令。2根据权利要求1所述的一种针对混合长度指令集的寄存器分配方法,其特征在于,所述标志位设于记录生命期信息的结构体中。3根据权利要求1所述的一种针对混合长度指令集的寄存器分配方法,其特征在于,所述步骤5)中SPILLCODE1的过程包括如下步骤31)在构造所述冲突图G1保存一个所述冲突图G1的备份冲突图G1BACKUP;32)每次SIMPLIFY1决定溢出某个生命期L时,首先判断是否有空闲的HIREGS寄存器可用于溢出,如果有,那么在L的每次赋值后和使用前插入MOVE指令,并记录生命期。

8、L溢出到HIREGS寄存器的信息;并且当每个HIREGS寄存器都已经有关联的溢出生命期时,根据所述备份冲突图G1BACKUP判断是否有寄存器关联的所有溢出生命期都不与当前要溢出的生命期L冲突,如果有这样的寄存器,那么它可用于L的溢出,如果没有空闲的HIREGS用于溢出,那么SPILLCODE1使用LOAD/STORE指令将生命期溢出到存储器。权利要求书CN102360280ACN102360297A1/6页4一种针对混合长度指令集的寄存器分配方法技术领域0001本发明涉及一种编译技术,尤其涉及一种针对混合长度指令集的寄存器分配方法。背景技术0002嵌入式系统常采用RISC架构,其指令集一般为定。

9、长指令集,即只具有单一长度的指令。指令长度一般为整数个字节,例如,16位指令,32位指令。较长的指令长度可以编码更多的操作数,寻址更多的寄存器,或者可使用更大的立即数等,故一般具有更好的性能;而较短的指令长度可以使得编译生成的可执行程序更小。为了在具有长指令高性能的同时具有短指令的高代码密度,现代的RISC处理器开始采用两种或者两种以上不同长度指令混合编码的指令集。例如,ARM的THUMB2指令集和中天微公司的CSKYV2指令集都是16位与32位指令混合编码的指令集(以下简称“混编指令集”)。0003在混编指令集中,短指令相比长指令而言,寻址的操作数个数少,可编码的立即数范围小,或者单个地址只。

10、可使用部分寄存器。例如,在CSKYV2指令集中,长指令可使用R0R31全部共32个通用寄存器,而绝大多数短指令只可使用R0R15共16个通用寄存器;长指令一般具有3操作数,而短指令最多只有2操作数。短指令在功能上是长指令的一个子集。通常,编译器按照长指令的功能来生成汇编指令,而汇编器生成机器指令时,会根据指令的类型和其操作数来决定生成长指令还是短指令。0004以CSKYV2为例,如果一条指令的某个寄存器操作数被分配了R16R31的寄存器,那么该指令将生成一条长指令(个别指令除外,下外将介绍);但一条指令即使只使用R0R15的寄存器,它也并不一定生成短指令,因为它可能使用了超出短指令可编码范围的。

11、立即数,或者使用了3个不同的操作数等等。以CSKYV2为例,如果一条指令的某个寄存器操作数被分配了R16R31的寄存器,那么该指令将生成一条长指令(个别指令除外,下外将介绍);但一条指令即使只使用R0R15的寄存器,它也并不一定生成短指令,因为它可能使用了超出短指令可编码范围的立即数,或者使用了3个不同的操作数,等等。如果一条指令最终生成的机器指令是长指令还是短指令取决于其分配到的寄存器(以下简称A类指令);反之,如果不论其寄存器操作数分配到哪个寄存器,其必然生成一条长指令,或者必然生成一条短指令(以下简称B类指令)。如何以较小的代价使得所有的A类指令最终生成的机器指令为短指令,是技术人员需要。

12、克服的难点。发明内容0005针对上述技术难点,本发明的提出一种针对混合长度指令集的寄存器分配方法。0006为了解决上述技术问题,本发明的技术方案如下一种针对混合长度指令集的寄存器分配方法,包括如下步骤1)查找函数中的所有生命周期,通过设置标志位是否置位来判断设该生命期为A类生命期还是B类生命期;说明书CN102360280ACN102360297A2/6页52)执行图着色寄存器分配方法的RENUMBER1、BUILD1、COALESCE1、SPILLCOST1、和SIMPLIFY1五个过程,为所有A类生命期分配LOREGS寄存器,得到未进行任何溢出操作的冲突图G1;3)计算空闲LOREGS寄存。

13、器数M,如果所述冲突图G1非空,则空闲LOREGS寄存器数M为0,如果所述冲突图G1为空图,则执行图着色寄存器分配方法的SELECT1过程,并根据生成的寄存器分配方案计算空闲的LOREGS寄存器数M,并记录空闲寄存器信息;4)执行图着色寄存器分配方法的RENUMBER2、BUILD2、COALESCE2、SIMPLIFY2、SPILLCODE2和SELECT2过程,为B类生命期分配HIREGS寄存器和M个空闲的LOREGS寄存器,并根据生成的分配方案计算空闲的HIREGS寄存器数量N,并记录空闲寄存器信息;5)执行图着色寄存器分配方法的SPILLCODE1和SELECT1过程,如果SELECT。

14、1过程已经在步骤3)执行,则步骤结束,如果没有,重复执行SPILLCODE1、RENUMBER1、BUILD1、COALESCE1、SPILLCOST1、SIMPLIFY1过程直到所述冲突图G1为空,然后执行SELECT1过程为A类生命期生成寄存器分配方案;RENUMBER1、BUILD1、COALESCE1、SPILLCOST1、SIMPLIFY1、SPILLCODE1、SELECT1、RENUMBER2、BUILD2、COALESCE2、SPILLCOST2、SIMPLIFY2、SPILLCODE2和SELECT2过程均为图着色寄存器分配方法的步骤;所述图着色寄存器分配方法包括如下步骤11。

15、)RENUMBER在数据流分析的基础上,找到函数中的所有生命期,并为其分配唯一的编号,其中一个生命期从一个变量的一次定值开始,到对该值的最后一次使用结束;12BUILD建立冲突图G,所述冲突图G中的结点为生命期,边则表示通过其相连的两个生命期有冲突,不能为它们分配同一个寄存器;13)COALESCE判断是否需要合并生命期,如需要则通过合并生命期删除不必要的复制语句,合并后返回,重新执行步骤12),如不需要合并,则执行步骤14);14)SPILLCOST计算每个生命期的溢出代价;15)SIMPLIFY对所述冲突图G进行简化,反复地检查图G,删除G中度数小于可用寄存器数K的节点,删除的同时将该节点。

16、压入栈S;16)SPILLCODE当所述冲突图G中所有节点的度都大于等于K时,需要将溢出代价最小的生命期溢出,即删除其节点,将其压入栈S,并将其标记为溢出,溢出一个生命期之后返回执行步骤11);17)SELECT当所述冲突图G为空时,将栈S中的生命期弹出,为其分配寄存器,并为标记为溢出的生命期插入溢出代码;所述LOREGS寄存器为短指令可寻址的寄存器,剩下的为所述HIREGS寄存器,所述标志位是否置位的标准为将有A类指令引用的生命期设为置位,将只有B类指令引用的生命期设为不置位;所述A类指令为一条指令最终生成的机器指令是长指令还是短指令取决于其分配到的寄存器;所述B类指令为不论其寄存器操作数分。

17、配到哪个寄存器,其必然生成一条长指令,或者必然生成一条短指令。说明书CN102360280ACN102360297A3/6页60007进一步的,所述标志位设于记录生命期信息的结构体中。0008进一步的,所述步骤5)中SPILLCODE1的过程包括如下步骤31)在构造所述冲突图G1保存一个所述冲突图G1的备份冲突图G1BACKUP;32)每次SIMPLIFY1决定溢出某个生命期L时,首先判断是否有空闲的HIREGS寄存器可用于溢出,如果有,那么在L的每次赋值后和使用前插入MOVE指令,并记录生命期L溢出到HIREGS寄存器的信息;并且当每个HIREGS寄存器都已经有关联的溢出生命期时,根据所述备。

18、份冲突图G1BACKUP判断是否有寄存器关联的所有溢出生命期都不与当前要溢出的生命期L冲突,如果有这样的寄存器,那么它可用于L的溢出,如果没有空闲的HIREGS用于溢出,那么SPILLCODE1使用LOAD/STORE指令将生命期溢出到存储器。0009本发明的有益效果在于适用于具有两种或两种以上不同长度指令,并且其中较短指令可访问寄存器的集合为较长指令可访问寄存器的集合的子集的指令集,本发明可提高生成代码的指令密度,并且简单实用,可靠性强,最终以较小的代价使得所有的A类指令最终生成的机器指令为短指令。附图说明0010图1为图着色寄存器分配方法的基本流程图;图2为本发明的具体实施流程图;图3为标。

19、记生命期类型流程图;图4为SPILLCODE1流程图;图5为备份的冲突图的部分图。具体实施方式0011下面将结合附图和具体实施方式对本发明做进一步的说明。0012本发明是一种在图着色寄存器分配法基础上进行改进的寄存器分配方法。图着色是传统的,也是最为常用的寄存器分配方法,其基本流程如图1所示,各阶段的简要说明如下重命名(RENUMBER)在本阶段之前,中间代码可以引用数目无限的“虚拟寄存器”。本阶段在数据流分析的基础上,找到函数中的所有生命期,并为其分配唯一的编号。一个生命期从一个变量的一次定值开始,到对该值的最后一次使用结束。0013构造冲突图BUILD本阶段建立“冲突图G”,G中的结点为生。

20、命期,边则表示通过其相连的两个生命期有冲突,即它们在某条指令处同时活跃,故不能为它们分配同一个寄存器。0014合并生命期COALESCE本阶段通过合并生命期来删除不必要的复制语句。合并生命期改变了冲突图,故合并之后需要重新执行“BUILD”过程。0015溢出代价分析SPILLCOST本阶段用于计算每个生命期的溢出代价。0016简化冲突图SIMPLIFY本阶段中对冲突图G进行简化,反复地检查图G,删除G中度数小于可用寄存器数K的节点,删除的同时将该节点压入栈S。0017插入溢出代码SPILLCODE当图G中所有节点的度都大于等于K时,“SIMPLIFY”过程无法继续。此时,需要将溢出代价最小的生。

21、命期溢出,即删除其节点,将其压入栈S,并将其标记为溢出。溢出一个生命期之后需要从“重命名”阶段重新开始执行图说明书CN102360280ACN102360297A4/6页7着色算法。0018着色SELECT图G最终会被简化为一个空图,此时将栈S中的生命期弹出,为其分配寄存器,并为标记为溢出的生命期插入溢出代码。0019首先将寄存器进行分类,其中大多数短指令可寻址的寄存器称为LOREGS,而其余的寄存器称为HIREGS。然后为每个生命期增加一个标志位,标记其是否曾被A类指令引用,将只有B类指令引用的生命期称为“B类生命期”;而将有A类指令引用的生命期称为“A类生命期”,并通过扫描整个函数的指令流。

22、为每个生命期设置该标记。0020接着执行两个图着色过程,为A类生命期分配LOREGS,为B类生命期分配HIREGS;如果LOREGS、HIREGS分别足够A类生命期、B类生命期使用,或者两个图着色过程寄存器都不足,都需要溢出生命期,那么这两个图着色过程独立进行。如果LOREGS足够A类生命期分配且有空闲,但HIREGS不够B类生命期分配,那么将LOREGS中空闲的寄存器和HIREGS寄存器一起分配给B类生命期。反之,如果HIREGS有空闲而LOREGS不足,那么在LOREGS分配过程中生成溢出代码时,优先将生命期溢出到空闲的HIREGS,当无HIREGS寄存器可进行溢出时才溢出到存储器。002。

23、1本方法的具体实现流程如图2所示,具体步骤如下一、生命期标记。本阶段查找函数中的所有生命期;并通过扫描当前函数的所有指令对每个生命期的类型进行标记。0022二、RENUMBER1、BUILD1、COALESCE1、SPILLCOST1、和SIMPLIFY1。本步骤执行图着色算法流程中的前5个阶段,为所有A类生命期分配LOREGS寄存器。本步骤执行结束后,将得到未进行任何溢出操作的冲突图G1。0023三、计算空闲LOREGS寄存器数。本步骤计算空闲的LOREGS寄存器数M,如果G1非空,那么M为0;反之,如果G1为空图,那么我们执行SELECT1过程,并根据生成的寄存器分配方案计算空闲的LORE。

24、GS寄存器数,并记录空闲寄存器信息。0024四、RENUMBER2、BUILD2、COALESCE2、SPILLCOST2、SIMPLIFY2、SPILLCODE2和SELECT2。本步骤是一个完整的传统图着色寄存器分配过程。我们使用这一过程为B类生命期分配HIREGS寄存器和M个空闲的LOREGS寄存器。并根据生成的分配方案计算空闲的HIREGS寄存器数量N,并记录空闲寄存器信息。0025五、SPILLCODE1和SELECT1。如果G1为空,那么SELECT1已在步骤三中执行,整个算法结束;否则,重复执行SPILLCODE1、RENUMBER1、BUILD1、COALESCE1、SPILL。

25、COST1、SIMPLIFY1过程,直到G1为空,然后SELECT1为A类生命期生成寄存器分配方案。本步骤的特殊之处在于,如果N0,那么在执行插入SPILLCODE1时,我们优先将生命期溢出到空闲的HIREGS寄存器,只有当无HIREGS寄存器可用时,才将生命期溢出到存储器。这样做的优点在于使用MOVE指令生成的将生命期溢出到空闲的HIREGS寄存器的代码,其执行速度一般要快于使用LOAD/STORE执行生成的将生命期溢出到存储器的代码。0026另外,混编指令集通常提供特殊的短指令MOVE,它是一条短指令,但可以寻址所有的寄存器。此时,使用MOVE指令生成的将生命期溢出到空闲HIREGS寄存器。

26、的代码相比溢出到存储器将更加高效(使用了短指令进行溢出,而不是通常的长指令)。0027本方法只需要在传统的图着色寄存器分配方法上进行少量的修改,即可充分利用混编指令集的特点,生成代码密度更高的代码,具有简单实用,可靠性强的特点。说明书CN102360280ACN102360297A5/6页80028下面结合具体实例进行更加详细的说明首先,在记录生命期信息的结构体中增加一个标志位FLAG_SHORT,如果该标志位置位,则说明该生命期是一个A类生命期,否则其为一个B类生命期。在“生命期识别”过程结束后,增加一个“标记生命期类型”的过程,如图3所示。该过程通过依次扫描当前函数中的每一条指令,为每一个。

27、生命期设置FLAG_SHORT标志。0029然后,需要执行两个图着色过程。其中SELECT1为所有A类生命期分配LOREGS寄存器;SELECT2为所有B类生命期分配HIREGS寄存器以及可能的空闲LOREGS寄存器。并且SELECT2可能在SELECT1完成之后执行,也可能在SELECT1的第一次简化冲突图G1过程后执行,如图2所示。这取决于LOREGS是否足够A类生命期分配,如果足够使用,那么SELECT1首先执行完毕,这样剩余的空闲LOREGS能够提供给SELECT2阶段进行分配;否则,SELECT1在执行第一次SIMPLIFY1过程后,执行整个SELECT2流程,这样如果SELECT2。

28、过程有空闲的HIREGS的话,它们可以用于SELECT1的插入SPILLCODE1阶段。总之,我们使用了SELECT1、SELECT2两个图着色过程,其中SELECT1为所有FLAG_SHORT为TRUE的生命期分配LOREGS寄存器;SELECT2为所有FLAG_SHORT为FALSE的生命期分配HIREGS寄存器和可能的空闲LOREGS寄存器。这两个图着色过程中,本发明只需要在传统的图着色算法中增加一个对生命期的FLAG_SHORT标志的判断,使SELECT1、SELECT2分别处理FLAG_SHORT为TRUE、FALSE的生命期,并简单的重新组织SELECT1、SELECT2的执行流程。

29、即可。0030最后,本发明还可以修改传统图着色算法的溢出过程插入SPILLCODE1,其流程如图4所示。首先,在执行构造冲突图G1过程时,需要保存一个备份的冲突图G1BACKUP;然后在每次简化冲突图G1决定溢出某个生命期L时,首先判断是否有空闲的HIREGS可用于溢出,如果有,那么在L的每次赋值后和使用前插入MOVE指令,并记录生命期L溢出到HIREGS的信息。需要注意的是,当每个HIREGS都已经有关联的溢出生命期时,并不意味着没有HIREGS可用于溢出;这时,需要根据G1BACKUP判断是否有某个寄存器,其关联的所有溢出生命期都不与当前要溢出的生命期L冲突,如果有这样的寄存器,那么它可用。

30、于L的溢出。如果没有空闲的HIREGS用于溢出,那么SPILLCODE1执行与传统图着色算法同样的过程,即使用LOAD/STORE指令将生命期溢出到存储器。0031以下是一个溢出到寄存器的例子,首先给出在构造冲突图G1执行结束后备份的G1BACKUP,如下图所示(为了简化说明,示意图中只包括4个生命期,可以认为是冲突图的一小部分)假设有两个空闲的HIREGS寄存器R1,R2可用于溢出,现在需要溢出生命期3,而之前的溢出操作对HIREGS的使用情况如下表HIREGS寄存器已溢出的生命期R11R22表HIREGS寄存器溢出情况记录如流程图4所示,首先得到第一个可用于溢出的HIREGS寄存器R1,并。

31、且根据上表可知,生命期1已经溢出到了R1,而当前要溢出生命期3,根据备份的冲突图G1BACKUP,可知生命期1、3有冲突,故R1不能用于溢出生命期3。接下来,得到第二个可用于溢出的HIREGS寄存器R2,根据G1BACKUP可知,生命期2、3无冲突,说明生命期3活跃的时间段说明书CN102360280ACN102360297A6/6页9内,生命期2已经不再使用,故可以将生命期3溢出到R2,将该信息填入表1,并在需要使用生命期2的地方插入MOVE指令将其值从R2拷贝到相应的LOREGS寄存器,在使用结束之后插入MOVE指令将其值从相应的LOREGS寄存器拷贝到R2。0032以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员,在不脱离本发明构思的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明保护范围内。说明书CN102360280ACN102360297A1/3页10图1图2说明书附图CN102360280ACN102360297A2/3页11图3说明书附图CN102360280ACN102360297A3/3页12图4图5说明书附图CN102360280A。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 物理 > 计算;推算;计数


copyright@ 2017-2020 zhuanlichaxun.net网站版权所有
经营许可证编号:粤ICP备2021068784号-1