0

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?

Dmitri K
  • 331
  • 1
  • 12

1 Answers1

0
  1. You may use chain tokens to represent control dependency between SDNodes. This way you can add fake dependency between two instructions even if the second one doesn't consume any output of the first one.
  2. You may use CopyToRegister and CopyFromRegister to cope with predefined physical registers
  3. You may use Glue to glue several simple instructions into a complex pseudo-instruction.

Consider the following simple example compiled for x86:

int foo(int aa, int bb) {
  return aa / bb;
}

enter image description here

You may want also to investigate more complicated example, though DAG picture is too big to post it here (you can view DAG with -view-sched-dags option):

void foo(int aa, int bb, int *x, int *y, int *z) {
  *x = aa / bb;
  *y = aa % bb;
  *z = aa * bb;
}

Take a look at this post too.

Community
  • 1
  • 1
Nikolai
  • 1,499
  • 12
  • 24
  • I figured my problem a while ago, but thanks for answer. I experimented with Glue, but it raised too much problems. Finally, what helped me was just passing root as first argument everywhere. Registers in my solution are special, so they are not introduced yet at the stage of DAG creation. For anybody, who may be interested, my solution is here: https://bitbucket.org/wf34/hellollvm/ – Dmitri K Nov 15 '14 at 17:56