如何使用编译器优化此功能?

| 我一直在学习有关编译器和工具的课程(本学期)。我阅读了直到生成中间代码,并且还看到了DAG表示的最优性。编译器很明显的一点是,无论生成了什么中间代码,都必须将其映射到系统的指令集,以便我们可以运行程序。 假设我有一个针对特定体系结构(例如A)的编译器,其中两个数字之间的加法是ADD R1,R2,R3(来自A \'s指令集),其中R1-是目标R2 ,R3是来源。而且我已经映射了这些指令,也就是说,当我想添加两个用中间代码表示的数字(不管类型如何,为了简单起见)时,我将运行ADD操作码! 假设新架构已经进入市场,其中两个数字的加法具有不同的指令集,例如AD R1,R2,R3。现在显然我的编译器不会添加数字! 现在我的问题是,当我为我的编程语言编写编译器时,我必须添加所有体系结构及其指令集,以便我的编译器正确执行所需的工作?如果是这样,那么有什么方法可以优化这种效果?因为添加所有指令集几乎会降低我的性能。 正确如果我错了!     
已邀请:
您为特定的指令集构建编译器,该指令集是所选“指令集体系结构(ISA)”的子集。 (许多指令集都有I / O指令,但是编译器几乎从未生成这些指令)。 可能会有几种不同的处理器设计执行此“指令集体系结构” 将与您选择的特定指令子集一起使用。 在实践中发生了三种进化事件。 您确定如果使用ISA的更多说明,则编译器会更好。例如,您可能认为MULTIPLY指令将使您的编译器生成比您过去用于乘法的子例程调用更快的代码。在这种情况下,您可以稍微扩展编译器。 ISA的所有者(英特尔,AMD,IBM等)向ISA添加了全新的说明集。例如,对数据高速缓存行(“ SIMD指令”)进行数据并行操作。您可以决定将其中一些添加到编译器中。由于新的指令系列通常对数据的布局和处理方式做出不同的假设,因此此事件可能会很困难。 您找到了一些您要处理的完全不同的ISA。在这种情况下,由于指令集在存在什么寄存器,如何使用寄存器等方面完全不同,因此您将重建编译器的后端。 编译器构建器通常将编译器构建为分阶段运行。生成实际机器代码之前的最后一个阶段通常将程序表示为具有相当标准的抽象操作(ADD,MULTIPLY,COMPARE,JUMP,对相当低级别的数据的抽象操作集(例如,对固定字长值的操作))调用,存储,加载...),它们对实际的ISA没有任何承诺(特别是没有关于寄存器或特定机器指令的承诺)。这样,可以独立于ISA进行更高级别的优化。只需将其视为良好的模块化即可。最后几个阶段专门针对ISA。通常在阶段分配寄存器,然后在阶段将模式与抽象指令匹配实际指令。 整本书中都包含有关更高级别的优化的书籍,而其他书籍则是有关最终代码生成状态的书籍(并且经常在单独的章节中介绍这两个书籍)。 [Aho&Ullman Dragon书籍和Torczon的Engineering a Compiler都是关于这两个主题的不错的书籍)。有很多技术可以让人们写下最终的指令集和寄存器布局,并且可以生成大部分的最后阶段。海湾合作委员会有这样的。这种技术很复杂,不适合这句话。最好去看书。 一旦让编译器以这种方式为第一个ISA工作,就可以使用相同的技术来构建变体。您最终得到两个物理编译器,每个ISA一个。他们共享所有前端逻辑和抽象代码的生成和优化。在最后阶段,它们完全不同。 您应该了解的是,构建编译器以利用指令集是一个复杂的过程。     
这完全取决于变化有多大。假设您有ISA X 1.0,指令为ADD R1,R2,R3。如果您获得新的X 1.1版本,用AD R1,R2,R3代替指令ADD R1,R2,R3,则更改很小。本质上,您具有相同的指令,但名称不同。您可以使用标志cc -arch X1.1来适应此更改,该标志将发出\“ AD \”而不是\“ ADD \”。 如果变化较大,如AD R1,R2(R2 <-R1 + R2),则新指令与旧ADD不同。在这种情况下,您需要更改代码生成器,并将此指令包括在一组可用指令中。同样,cc -arch X1.1应该让生成器知道此指令可用。 如果变化更大,例如将编译器重新定位为ISA Y,则您需要更改代码生成器生成的所有指令。那可能是很多工作。 现在,现有的低级编译器优化是否可以与新目标一起使用还值得怀疑。通常,定义良好的后端(如gcc)可以支持许多ISA。它使用的是低级中间表示(IR),其中您的指令具有多种属性,包括操作码名称(\“ ADD \”或\“ AD \”)。但是,低级优化器与该指令的其他属性一样,对名称的关注并不多,即它有多少个操作数?读/写什么操作数?它会访问内存吗?它会改变程序流程吗?等等 如果您可以将目标体系结构调整到编译器框架中,则可以成功利用现有的优化。     

要回复问题请先登录注册