[0051]指令间的数据依赖关系的枚举类型:包括数据读写数据依赖关系类型和访存数据依赖关系类型,此外,也可包括由体系结构决定的其他隐式数据依赖关系类型。
[0052]执行单元的枚举类型:包括物理执行单元的枚举值、扩展的起辅助作用的组合执行单元的枚举值。枚举值从O开始增长,先是所有的物理执行单元的枚举,然后才是扩展的辅助执行单元的枚举。该枚举类型定义在处理器的体系结构类中,枚举值是连续变化的,每一个功能单元都对应一个唯一的枚举值,对于扩展的辅助执行单元,需要考虑所有可能的组合。
[0053]实时的有效指令组数量(effectivelnstnGroupNum):该值为一个非负整数,用于保存在某个时刻依赖网格中仍然保存了有效指令的行数。由于在某些代码优化过程中依赖网格中的指令会逐步移除,因而某个网格中的某些指令会要移动到优先级更高的同列网格中,从而使得保存着有效指令的行数减少。
[0054]在面向对象语言程序中,数据和相关的功能模块都封装在类中。本实施例中,基本块和基本块中的指令的基本信息保存在基本块类对象和指令类对象之中,指定执行相应指令的候选功能单元信息包含在指令模板信息中并保存在指令模板类的对象中,各指令对象具有确定的指令模板;体系结构的基本信息保存在体系结构类对象中,通过指针或者全局变量名进行访问。
[0055]步骤1:指令的数据依赖优先级值计算
获取到指令间的数据依赖关系后,进行指令间的数据依赖关系分析,计算指令间的数据依赖优先级值,划分数据依赖优先级,步骤如下:
①将指令的数据依赖优先级值表中的元素个数设计为与指令数量相同,并将各元素的值初始化为O ;
②通过循环正序遍历基本块内的各指令,每次循环处理的指令设为curlnstn,循环执行步骤③?⑩查找依赖指令;
③形成curlnstn涉及的源变量集合和目标变量集合,然后,为每个变量设置一个依赖关系解除标识,当变量依赖解除标识的状态和访存依赖解除标识的状态都为解除时,结束对curlnstn的依赖指令的寻找;
④将变量依赖关系解除标识置为未解除状态,并根据指令是否为访存类指令来设置访存依赖关系解除标识的状态为解除(针对非访存类指令)或未解除(针对访存类指令);
⑤从curlnstn的前一条指令开始,通过循环向基本块的首指令逆序遍历各指令,每次循环处理的指令设为prelnstn,并执行步骤⑥;
⑥分析curlnstn对prelnstn的数据依赖类型的组合,当存储数据依赖时,生成prelnstn的源变量集合和目标变量集合,并且,如果依赖类型中是否含有写后写和写后读及类似的依赖,设置删除变量标识deleteVarFlag为真,否则为假,转入执行步骤⑦;否则,将prelnstn切换为前一条指令,重新执行本步骤;
⑦如果curlnstn和prelnstn都是访存指令,并且对存储器具有写后读或写后写类型,则令访存依赖解除标识为解除状态,否则维持原来状态;
⑧描述curlnstn和prelnstn之间的依赖关系,当curlnstn的数据依赖优先级值不大于prelnstn时,修改curlnstn的数据依赖优先级值为prelnstn的数据依赖优先级值加I ;
⑨从curlnstn的源变量集合和目标变量集合中删除写后写、写后读这类依赖相关的寄存器名,对由体系结构造成的特殊数据依赖关系类型,则将依赖相关的寄存器名从两个集合中删去;
⑩判断curlnstn的源变量集合和目标变量集合是否都被清空,如果为空则将curlnstn的变量依赖解除标识的状态置为解除,返回执行步骤③。
[0056]步骤2:依赖网格建立步骤2.1:指令组划分
本步骤即是将具有相同数据依赖优先级值的那些指令集中到相同的组中,得到按数据依赖优先级值升序排列的多个指令对象指针集合构成的指令组,步骤如下:
①用一个循环依次遍历各指令,找出它们的数据依赖优先级值的最大值maxDataDepPr1rityVal,此值即基本块的硬件无关执行延迟时间;
②根据所得的maxDataDepPr1rityVal值来确定保存各指令组的数组指令组序列instnGroups的大小,指令组对应的数组元素的下标与数据依赖优先级值相同;
③用一个循环依次遍历各指令,在循环体内,先获得指令的数据依赖优先级值,再将指令填写到与此值相应的指令组中。
[0057]步骤2.2:指令子组划分
步骤2.1中确定了不考虑硬件的执行单元数量限制的情况下逻辑上哪些指令可以在同一个节拍中同时发射,以及执行基本块内的所有指令所需的逻辑执行延时。本步骤则是根据指令组划分的结果,进一步建立指令组中各指令与功能单元的对应关系,并根据处理器的物理执行单元数量和指令集特征将一个指令组划分成多个指令子组,由指令对应的指令模板即可获得指令可以在哪些执行单元中执行。
[0058]步骤2.2的详细步骤如下:
①用指令组序列instnGroups的数组元素个数和总执行单元数Nteu,分别作为指令子组二维表instnGroupsForUnits的的第一维和第二维的长度的初始值,用表的行数作为整型变量实时的有效指令组数量effectivelnstnGroupNum的初始值;
②用一个二重循环遍历每个指令组中的每条指令,外层循环依次遍历各指令组,内层循环依次遍历一个指令组内的各指令对象,在内层循环中循环执行步骤③~⑤;
③如果指令源代码中已经指定执行的功能单元,则令指令的可能执行单元代号和最终执行单元代号都定为指定的这个执行单元的代号,并将指令添加到此功能单元对应网格的指令子组中;否则执行步骤④;
④如果指令只能在某一个功能单元中执行,令指令的可能执行单元代号和最终执行单元代号都定为这个功能单元的代号,并将指令添加到此功能单元对应网格的指令子组中;否则执行步骤⑤;
⑤根据指令的指令模板对象中保存的候选执行单元类别信息,按确定组合功能单元时的规则确定相应的扩展执行单元代号,将指令的可能执行单元代号定为这个代号,并将指令添加到此扩展执行单元对应网格的指令子组中。
[0059]步骤3:并行性识别
在涉及代码调度或代码变换的优化中一般需要知道相关的并行性信息,作为优化的依据,本实施例根据获得的依赖网格可实现多种并行性信息识别以及关联状态,包括:
识别指令的逻辑并行性:定义保存所需指令信息的集合S,然后遍历依赖网格中与逻辑时间点对应的那一行中的各个单元格,将其中的各指令信息添加到集合S中,集合S中即为所需的基本块内某个逻辑时间点的候选指令集合。
[0060]获取指定功能单元某个逻辑时间点的候选指令集合:定义保存所需指令信息的集合S,通过逻辑时间点找到依赖网格中对应的行号,通过功能单元号找到对应的列号,将行号和列号对应的单元格中保存的信息复制到集合S中,集合S中即为指定功能单元某个逻辑时间点的候选指令集合。
[0061]获取各执行单元的工作量:通过遍历依赖网格中的各单元格对单元格中的指令计数,然后遍历依赖网格的各列,计算出列的指令总数,即可获得各逻辑节拍上各执行单元的工作量以及总的工作量。
[0062]获取某个功能单元因某条候选指令而与其他功能单元产生的关联关系:通过依赖网格中对指令所从属的功能单元的描述,可以直接确定由数据依赖相关联的两个功能单元,在此基础上,通过对各候选指令所引起的关联单元计数,可以获得它们所引起的关联单元的数量信息,进而计算出与之有关的关联单元数。
[0063]预测下一拍关联单元的可能状态:在指令调度时,找出依赖网格某个关联单元对应的列的第一行和第二行的单元格中的指令集合SI和S2。如果集合SI是空的,如果集合S2中某条指令所依赖的指令在本拍都能够发射,那么可以预测在下一拍一定能够发射该指令。
[0064]除上述并行性识别方法外,对于某些更激进的代码优化技术,也可能根据优化的需求从依赖网格中识别出更具前瞻性的并行性。
[0065]步骤4:依赖网格内容动态调整
本步骤用于在依赖网格第一行的某些指令被移除后,重新调整相关指令在依赖网格表格(指令子组二维表)中位置,步骤如下:
①如果实时的有效指令组数量effectivelnstnGroupNum的值小于I,表明已经没有指令保存在依赖网格中了,则结束