I’m running some performance experiments on a x86-64 linux system, where I’ve modified LLVM to reserve a register, and I’d like to use that register in my code. Currently, I’m using %r12d, which is callee save, so I don’t need to worry about compatibility with existing libraries or system calls. For security reasons, the generated binaries need to be position independent.
To access the register, I need to use inline assembly; either for all dependent computations, or just for moving the register value into a C++ variable. Since the latter results in a second register allocation, I’m just doing assembly for everything. So, I have a function
foo that contains some inline assembly.
The problem is that its input arguments can sometimes be pointers to constant data, and after function inlining, the result may no longer link because R_X86_64_32S relocations are not permitted. I need to get LLVM to introduce a load-effective address (
lea) to move the pointer into a register, if applicable, but I haven’t found a method that both works and is performant. I could modify LLVM locally to make this happen, but this seems pretty deep in the X86 backend and not straightforward?
- Make the input argument
volatileor introduce a
volatilevariable. Works, but adds two moves to and from the stack.
- Introduce a
registervariable equal to the input argument. Results in an error with C++17, and doesn’t seem to work otherwise.
- Only use inline assembly to move %r12d into a C variable. Mostly works, but the variable isn’t incremented afterwards, requires an extra register, and adds multiple extra moves.
- Use the local register variable extension to force a C variable to %r12d. Not supported by Clang/LLVM.