What I am trying to achieve is to avoid constant-folding of some constants (which represent addresses in my code) such as the 100000000
constant below. I need this because later the JIT-compiled code might get patched, which changes the constants due to object relocation.
The code below is my best effort to avoid constant-folding (at all costs). It doesn't work. I end up with constant 100011111
in the instruction stream.
llc -O0 code.ll -print-after-all
reveals that the folding happens at Expand ISel Pseudo-instructions
pass.
; 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 }
I realize that my problem can be solved by adding some intrinsic which at codegen level would unfold to simple movabs reg, imm64
. But I'd like to have a temporary solution for the time being.
The question: is it possible to make an opaque constant in llvm which doesn't get constant-folded?
My llvm version is 3.7.0svn.
No, it's not possible. Your best bet is to use an external global variable as was mentioned in the comments. In fact, for your purposes it might be exactly what you want to do since at that point your jittable code will get a relocation for what you actually want and patched up accordingly at execution time by rtdyld.
If you want an actual constant for the jitted code (e.g. to call a particular address that you know about) then what you're doing is just fine.