I was challenged with rather educational task to extend LLVM in the following way:
- Add register XACC and instructions LRXACC(), SRXACC(arg1), XMAC(arg1,arg2) to the SPARC back-end. Instructions do the following:
LRXACC: load value from XACC,
SRXACC: write to XACC,
XMAC: XACC+=(arg1*arg2)>>31 - Provide builtins in the Clang front-end for all three of them.
My source for testing is:
int main() {
int acc = 0;
__builtin___srxacc(acc);
__builtin___xmac(12345,6789);
acc = __builtin___lrxacc();
return 0;
}
I was able to support conversion of builtins into intrinsic function. IR file I get from clang looks fine:
define i32 @main() #0 {
entry:
%retval = alloca i32, align 4
%acc = alloca i32, align 4
store i32 0, i32* %retval
store i32 0, i32* %acc, align 4
%0 = load i32* %acc, align 4
call void @llvm.sparc.srxacc(i32 %0)
call void @llvm.sparc.xmac(i32 12345, i32 6789)
%1 = call i32 @llvm.sparc.lrxacc()
store i32 %1, i32* %acc, align 4
ret i32 0
}
Issue appears during DAG combining step and final output code looks like that:
.text
.file "file22.ll"
.globl main
.align 4
.type main,@function
main: ! @main
! BB#0: ! %entry
add %sp, -104, %sp
st %g0, [%sp+100]
st %g0, [%sp+96]
lrxacc %xacc, %o0
st %o0, [%sp+96]
sethi 0, %o0
retl
add %sp, 104, %sp
.Ltmp0:
.size main, .Ltmp0-main
.ident "clang version 3.6.0 (trunk)"
DAGCombiner deletes srxacc and xmac instructions as redundant. (In the ::Run method it checks node for use_empty() and deletes it if it's so)
Combiner does that because they store result in the register, so it's not visible from graph, that one of them depends on another.
I would appreciate any suggestions on how to avoid removal of my instructions.
Thank you!
Edit
To simplify and concretize: Instructions, which represented in IR code like that void @llvm.sparc.srxacc(i32 %0) look to combiner like they don't affect computation and corresponding SDNodes receive empty UseList. How to get around that?