LLVM和优化的未来

And*_*ott 14 compiler-construction optimization gcc llvm compiler-optimization

我意识到LLVM还有很长的路要走,但从理论上讲,可以在GCC/ICC /等中进行优化.个别语言应用于LLVM字节代码?如果是这样,这是否意味着编译为LLVM字节代码的任何语言都有可能同样快速?或者是特定于语言的优化(在LLVM字节码阶段之前)将始终在优化任何特定程序中发挥重要作用.

我不太了解编译器或优化(只是危险),所以如果这个问题没有明确定义我会道歉.

Die*_*Epp 21

一般来说,没有.

例如,在Haskell中,常见的优化是严格性分析,它允许编译器确定哪些变量始终处于头部正常形式,因此可以强制+内联而不改变程序语义.LLVM无法实现这一点.

说明:在Haskell中,函数(Int, Int) -> Int或多或少等同于C中的类型:

typedef int (*returns_int)();
struct pair { returns_int first, second};
typedef struct pair *(*returns_pair)();

int function(returns_pair arg);
Run Code Online (Sandbox Code Playgroud)

编译器可以分析function并确定它总是计算其参数并始终提取内容,将函数转换为:

int function(int x, int y); // note that it takes *two* arguments now
Run Code Online (Sandbox Code Playgroud)

这远远超出了LLVM的能力.也许,在未来,有一些非常繁重的过程间优化......但实际上,这在可预见的未来不会发生.

示例2:有些Java VM可以将虚函数调用转换为直接函数调用.但是,这不是LLVM可以执行的操作 - 因为如果加载另一个实现相同接口的类,则必须动态撤消此转换.

通常,当您将程序编译为LLVM时,会丢失有关原始程序的大部分语义信息.LLVM字节码能够表示任何代码,但其类型系统相当有限 - 您选择的类型系统会影响您可以执行的优化.

  • 你可以说LLVM是优化高级语言的不良选择,因为语义信息的丢失,但值得注意的是,具有程序的所有语义信息的高级表示是一个不好的地方执行低级别优化.往往会发生的是,当程序被编译时,它会转换为几个逐渐降低级别的IR.LLVM对于像Haskell这样的高级语言仍然有用,而不是优化器中的第一步. (3认同)
  • 也许你应该复习C typedefs?类型的名称是`returns_int`,它是一个返回`int`的函数.在C中编写它的方法是`typedef int(*returns_int)(void);`这种定义经常在库中用于回调函数. (2认同)

Abh*_*uch 10

除了Dietrich的优秀答案之外,我认为重要的是要认识到编程语言的速度不仅仅是编译器.除了给定语言可能允许/禁止的各种优化之外,还有如何使用各种编程语言执行某些任务以及语言允许您执行的操作.

例如,优化C代码以最大化缓存效率(减少从内存的慢读取)相对容易,而在Haskell中这要困难得多.在Java中,指针黑客是不可能的.分配大量内存并手动分配的策略也是如此.

因此,某些语言总是会变慢,因为它们不允许相同级别的优化.请注意,我并不一定说这是一件坏事,因为这种缓慢会带来非常强大的结构.

我认为更好的方法是查看它,LLVM将允许将一组优化应用于编译到它的所有语言.因此,尽管它做出这样的语言更快,它不会使他们也同样快.

编辑:Haskell中的指针黑客攻击.这么多的可能性......


Mat*_* M. 5

这是一个有趣的问题,但我担心你缺乏编译器所做的一些概念.

在编译器中总会有几个优化阶段.

  • 一些优化依赖于语言规则,例如在C++中,您可以优化一些复制/移动构造函数调用.
  • 一些优化可广泛使用(循环变换,尾调用)
  • 一些优化取决于硬件(SSE,MMX)

LLVM编译器应用所有3 ...但从LLVM IR开始,而不是从C或Java或其他.

提供合适的LLVM IR是前端的工作.

例如,正如@Dietrich Epp所指出的,IR并不适合功能语言.因此,必须将表示降低到IR 之前执行许多Haskell优化.

另一个非优化的来源是特定的运行时可能随语言一起提供.Haskell具有复杂的运行时,具有火花池,轻量级线程,系统调用之前的抢占,工作窃取等...... IR不适合代表这种丰富的环境,并且不对该组织进行优化.