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.