如何避免LLVM代码生成器执行不希望的常量折叠?

时间:2015-08-03 17:23:17

标签: compiler-construction garbage-collection llvm relocation llc

我想要实现的是避免一些常量(代表我的代码中的地址)的常量折叠,例如下面的100000000常量。我需要这个,因为稍后JIT编译的代码可能会被修补,这会因对象重定位而改变常量。

以下代码是我尽最大努力避免不断折叠(不惜一切代价)。它不起作用。我最终在指令流中使用常量100011111

llc -O0 code.ll -print-after-all显示折叠发生在Expand ISel Pseudo-instructions次传递。

; ModuleID = '0'
target triple = "x86_64-unknown-linux-gnu"

define  i64 @"0"() {
BlockEntry0:
  %cell = alloca i64, align 8
  store volatile i64 0, i64* %cell, align 8
  %volatile_zero3 = load volatile i64, i64* %cell, align 8
  %base = add i64 %volatile_zero3, 100000000
  %volatile_zero4 = load volatile i64, i64* %cell, align 8
  %opaque_offset = add i64 %volatile_zero4, 11111
  %casted_base = inttoptr i64 %base to i8*
  %gep = getelementptr i8, i8* %casted_base, i64 %opaque_offset
  %as_ptr = bitcast i8* %gep to i64*
  %loaded = load i64, i64* %as_ptr, align 4
  %as_function = inttoptr i64 %loaded to i64 (i64)*
  %ret_val = tail call i64 %as_function(i64 0)
  ret i64 %ret_val
}

attributes #0 = { nounwind }

我意识到我的问题可以通过在codegen级别添加一些内在的简单movabs reg, imm64来解决。但我想暂时有一个临时解决方案。

问题:是否有可能在llvm中创建一个不透明的常量?它不会得到常量折叠?

我的llvm版本是3.7.0svn。

1 个答案:

答案 0 :(得分:2)

不,这是不可能的。您最好的选择是使用评论中提到的外部全局变量。实际上,出于您的目的,它可能正是您想要做的事情,因为此时您的jittable代码将获得您实际需要的重定位,并在执行时由rtdyld进行相应的修补。

如果你想要一个jitted代码的实际常量(例如,调用你知道的特定地址)那么你正在做的就好了。