有趣的编译器项目

时间:2008-10-08 17:24:44

标签: compiler-construction

我目前正在选择一个项目,以便在接下来的8周内完成毕业级编译器课程。我想做一些与优化相关的事情,因为我以前在那个领域没有多少工作,但是该领域的任何事情都是合理的。

你做过的最有趣的编译器相关项目是什么?你从中学到了什么?


修改:谢谢大家的好建议。我很抱歉没有更新这件事。

我最终做的项目是在LLVM上进行简单的自动向量化优化。 LLVM有矢量类型,但似乎没有任何方法可以在不支持前端的情况下利用它们。此优化将普通标量代码转换为矢量代码。

由于自动矢量化是一项相当难以实现的优化,因此我们尽可能地限制了我们的范围。首先,为了在代码中公开指令级并行性,我们寻找符合我们标准的单块循环,然后将它们展开特定次数,以便它们可以方便地进行矢量化。然后,我们实施了Larsen和Amarasinghe在Exploiting Superword Level Parallelism with Multimedia Instruction Sets中列出的打包算法。

即使是这种优化的简化版本也非常复杂。有很多限制;例如,您不希望对存在于循环之外的变量进行矢量化,因为程序的其余部分期望它是标量。我们在过去几周里花了很多时间。虽然这个项目很有趣,但我们学到了很多东西。

18 个答案:

答案 0 :(得分:13)

在8周的时间范围内,您需要注意“范围蔓延”。这不是太野心勃勃,尤其是如果这个项目包括编译器构造的其他方面(lexing / parsing),或者你还在学习工具(调试器,yacc)和中间数据结构(DAG)。

那就是说,我的第一个建议是尝试一些实时变量分析。这些算法非常成熟,因此您只需要根据数据结构对其进行编码等。

这将允许您执行有限形式的死代码删除。也就是说,如果您检测到某个变量已声明但从未使用过,请不要为其分配空间。如果检测到某个值已设置但从未读取过,请不要生成该集。

实时变量分析也可以帮助注册分配,所以如果有时间你也可以解决这个问题,你应该可以重新使用你为死代码删除构建的一些内容。

答案 1 :(得分:8)

几年前,我设计了一个DSL并为我公司生产的产品编写了编译器。 DSL使用了声明规则,事件驱动逻辑和组合继承的奇怪组合。这是一个非常有趣的项目,我学到了很多东西。

它真的引起了我对解析器的兴趣。编译器,所以我试图跟上编译器技术的有趣新发展。

关于优化,这是我去年读到的一篇有趣的文章:

http://theory.stanford.edu/~aiken/publications/papers/asplos06.pdf

在本文中,作者描述了一种自动发现窥视孔优化的技术(超过了几个流行的C ++编译器后端的性能),而专家不必编写一堆特殊情况代码。他们的技术使用无监督学习算法来发现高价值的窥视孔替换。

在阅读之后,我发现他们的方法可以通过为算法提供“机器描述”来增强,该“机器描述”列出目标处理器体系结构支持的所有指令(及其主要效果和副作用)。然后,求解器不是使用强力方法来寻找等效的指令序列,而是可以更容易地找到这些序列。

机器学习算法仍将使用经验观察来确定最有效的指令序列(因为缓存效应,微操作和流水线几乎需要经验时序数据),但结果等价可以使用代数定理来预测-prover,在机器描述上运行。

在论文中,他们讨论了他们的优化器如何只发现两个或三个指令的窥视孔替换序列(因为,否则,蛮力搜索将花费太长时间并消耗太多内存)。将智能求解器放在算法中的正确位置可以使其能够使用更长的替换序列。

Anyhoo ...当你完成那个项目时让我知道!别忘了在“致谢”栏目中提及我! ; - )

答案 2 :(得分:7)

我认为编写自己的简单嵌入式脚本语言是我所做过的最有趣的编译器相关项目之一。它教会了我从设计到概念的过程的每个方面,因为我从头开始,我可以使它像我需要的那样简单或复杂,这使我能够理解具有大量噪音的概念,修改既定的项目可能有。

答案 3 :(得分:7)

如果您对优化感兴趣,使用SSE和MMX指令集进行循环矢量化可能会很有趣。

答案 4 :(得分:5)

对于学习编译器,端到端的做法是最好的主意。使用一个简单的后端机器,而不是一个x86,而是选择一些简单的机器,如一个简单的MIPS。我完成了针对PDP-11模拟器的本科编译器项目,这是一个很好的目标,因为它使事情变得非常简单。感谢一些示例代码,我们可以在大约四周内完成一个简单的命令式语言编译器。在C!

今天,使用像ML这样强大的语言,编写编译器应该会容易得多。

你所做的事情应该真正取决于你的兴趣所在。如果是在优化中,找到某种简单的框架,你需要关注的就是这些。

我认为今天最富有成效的领域是编译线程目标或即时编译。

答案 5 :(得分:4)

我曾编写过一种编程语言和一台虚拟机来运行它。该语言能够与16位Windows上的DLL(这是在OLE自动化之前)中包含的专门编写的函数接口。

完成从前到后的整个过程让我对两端的语言有了很好的理解。我当时读过各种编译器书籍(比如臭名昭着的龙书),但在我写出具体内容之前,它从未真正沉入其中。现在,多年以来,我所做的工作让我对Java VM和CLR等工作有了更丰富的认识和理解。

答案 6 :(得分:4)

了解帮助Shed Skin项目,它将Python编译为C ++。我想在整个夏天都会打电话求助。确定改进编译为C ++的方法将为python程序提供非凡的优化!

http://code.google.com/p/shedskin/

答案 7 :(得分:4)

除了“龙书”建议外,我还强烈推荐Steven S. Muchnick撰写的“高级编译器设计与实现”,重点介绍中间表示,代码生成和优化技术。

答案 8 :(得分:4)

考虑现有动态类型语言的类型推断。

答案 9 :(得分:4)

在我的本科编译器类中,我们首先从头开始为类似Pascal的语言编写一个递归下降(自上而下)解析器:词法分析器,解析器,所有内容。

关于学期中期,我们转向解析器/扫描仪生成器,如lex / yacc或flex / bison。我们构建了一个编译器,它将接受我们的Pascal子集并将其编译为我们给出的堆栈机器的汇编(堆栈机器非常简单,但原理仍然相同)。

如果您对编译器感兴趣,我不能高度推荐Dragon Book。它旨在用于一个学期的本科课程,下半部分用于研究生课程,并涵盖您所希望的理论和优化的每一点。甚至乔尔likes it。 =)

干杯

答案 10 :(得分:3)

这是另一个想法......虽然它仍然有点模糊:

大多数优化都是在编译时完成的(JIT编译器除外,它们在运行时进行优化)。但是在链接时和安装时也有很多优化机会。

我对一个平台的想法特别感兴趣,在安装时你不需要进行链接。但是在安装时间链接过程中,您采取了积极的优化策略,因为您了解了有关机器架构的大量详细信息,并且可以做出更细微,更明智的优化决策。

答案 11 :(得分:2)

你可以为IronScheme编写一个优化器,因为除了一些“内在”函数之外,它目前还有很好的效果。 :)

答案 12 :(得分:2)

其他有趣的项目可能包括:

  • 向开源Sun JVM添加尾调用优化。

  • 将命名返回值优化(NRVO)添加到Python或Ruby VM中。

  • 为您喜爱的目标添加即时正则表达式到字节码编译(.Net已经拥有它。我非常确定Java没有。)

答案 13 :(得分:2)

虽然编写自己的语言是一项有趣且传统的学术活动,但已经存在太多实施不当的编译器相关项目。此外,8周时间还不足以完成一个完整的语言实施。

如果您对“与优化相关的内容”感兴趣,请选择已有的语言或VM,并针对性能,大小或两者进行优化。这将使您不必重新发明整个语言实现,让您专注于优化问题,产生对其他人有用的产品,而不仅仅是另一个学术练习,甚至可以用来找工作。

我相信Parrot字节码解释器和各种.Net铁语言解析器甚至可以从简单的优化中受益。

答案 14 :(得分:2)

循环检测和参数化展开应该足够难以让它变得有趣。不是很性感,但是在8周内过于性感会使你陷入困境。

答案 15 :(得分:2)

我在自己的教学中做到了这一点“回归的时候”。我不会非常重视其他方面的优化,例如类型推断或JIT或字节编码或对象格式/调试支持。

只要你也传达它比人们想象的重要得多,那么专注于优化是没有害处的。只在代码中才重要:

  • 在调用堆栈底部的紧密循环中运行(即,不显式或隐式地调用函数)
  • 实际占用应用程序时间的很大一部分(即如果代码很少运行,优化它将无济于事。)

这只是编译器将看到的所有代码的一小部分。

编辑:可悲的是,我无法摆脱使用Fortran编译器的问题,这些编译器无情地加密代码,使调试变得非常困难,同时对性能产生影响。

答案 16 :(得分:1)

使用针对大小/速度权衡的启发式测试自动生成内联代码。

答案 17 :(得分:0)

B :: CC perl编译器将从添加和分析类型中受益。我还没有足够的时间。

最近有足够的时间。 http://blogs.perl.org/users/rurban/2011/02/use-types.html