Optimization 嵌套函数的LLVM IR优化

Optimization 嵌套函数的LLVM IR优化,optimization,nested,llvm,llvm-ir,Optimization,Nested,Llvm,Llvm Ir,我正在通过生成LLVM IR代码为一种玩具函数式语言编写编译器。但是,我在使用嵌套函数优化案例时遇到了一些问题 函数和运算符是通用的,因此y=10+20作为f=plus(10)执行;y=f(20)。到目前为止,LLVM优化过程已经足够智能,可以将上述内容优化为仅reti32 30 一旦我添加了对嵌套函数的支持(通过lambda提升,为自由标识符添加了一个env参数),LLVM就再也不能优化上面这样的简单示例了 以下是嵌套函数的工作方式:调用嵌套函数时,它所需的每个自由变量都会写入指针数组(env

我正在通过生成LLVM IR代码为一种玩具函数式语言编写编译器。但是,我在使用嵌套函数优化案例时遇到了一些问题

函数和运算符是通用的,因此
y=10+20
作为
f=plus(10)执行;y=f(20)
。到目前为止,LLVM优化过程已经足够智能,可以将上述内容优化为仅
reti32 30

一旦我添加了对嵌套函数的支持(通过lambda提升,为自由标识符添加了一个
env
参数),LLVM就再也不能优化上面这样的简单示例了

以下是嵌套函数的工作方式:调用嵌套函数时,它所需的每个自由变量都会写入指针数组(
env
)并传递给嵌套函数。嵌套函数加载
env
,并将每个索引读入本地寄存器。我希望优化器能够在线调用,然后消除
env
的冗余存储和重新加载。优化器将调用内联,但无法消除
env
s

下面是原始和优化代码的一个最小示例:

declare i8* @malloc(i32)

@x = private constant i32 42

define i32 @main() {
  %env_pass = insertvalue [1 x i32*] zeroinitializer, i32* @x, 0
  %env_pass_ptr = call i8* @malloc(i32 8)
  %env_pass_cast = bitcast i8* %env_pass_ptr to [1 x i32*]*
  store [1 x i32*] %env_pass, [1 x i32*]* %env_pass_cast
  %res = call i32 @nested_func(i8* %env_pass_ptr)
  ret i32 %res
}

define private i32 @nested_func(i8* %env) {
  %env_ptr = bitcast i8* %env to [1 x i32*]*
  %env_val = load [1 x i32*]* %env_ptr
  %my_x = extractvalue [1 x i32*] %env_val, 0
  %val = load i32* %my_x
  ret i32 %val
}
优化到:

@x = private constant i32 42

declare noalias i8* @malloc(i32) #0

define i32 @main() #0 {
  %env_pass_ptr = tail call i8* @malloc(i32 8)
  %env_pass_cast = bitcast i8* %env_pass_ptr to [1 x i32*]*
  store [1 x i32*] [i32* @x], [1 x i32*]* %env_pass_cast
  %1 = getelementptr inbounds [1 x i32*]* %env_pass_cast, i32 0, i32 0
  %2 = load i32** %1
  %val.i = load i32* %2
  ret i32 %val.i
}

attributes #0 = { nounwind }
这个例子应该减少到只
reti32 42
。我怀疑问题出在优化器生成的
getelementptr

下面是表达式
10+20
的完整原始和优化代码的一些粘贴:


在这种情况下,我可以选择不在环境中传递'add'函数,因为它是一个全局函数。但是,我仍然希望这个示例能够正确地进行优化。

我发现,如果我使用
getelementptr
直接写入索引,而不是使用
insertvalue
的话,问题就会得到缓解。这是在发现另一个问题后发生的


在使用
getelementptr
之后,上面的示例简化为
reti32 42
,现在我的语言中更基本的算法简化为常量。使用多个运算符的方法(例如
(10+20)*5
)仍然不能完全减少。您的示例缺少数据布局字符串。没有这一点,许多优化器就无法产生令人满意的结果——他们无法知道指针的大小,等等

有关更多信息,请参阅。我建议首先抓取平台上由clang生成的数据布局字符串并粘贴到.ll中