[LLVMdev] Instructions working on 64bit registers without true support for 64bit operations

Fabian Scheler
Wed, 18 Jul 2012 11:45:17 -0000

Hello Tom,

> I took a look at lib/CodeGen/SelectionDAG/LegalizeDAG.cpp and it
> doesn't look like there is an Expand operation implemented for
> ISD::Constant.  I think you'll either need implement Expand for
> ISD::Constant or Custom lower it in your backend.

thank you for that information. This exactly is what I feared. Well I
did some more mostly unguided hacking and these are the opportunities
I found/was pointed to:

1. Implement custom lowering in the backend

(cf. eg. SDNode *PPCDAGToDAGISel::Select(SDNode *N))

It is not a big issue to split the constant in the 32 higher and lower
bits and to load these fragments separately. However, I don't know how
to ensure that these fragments are put into the proper subregisters of
the register pair forming the 64bit register. For the PPC-backend this
is no problem as it has true 64bit register, this however is not the
case for the TriCore. So I need to get the vritual register (pair)
that will be used to store the 64bit value to access its subregisters.

2. Use a pattern consisting of INSERT_SUBREG-nodes

A colleague of mine (who originally implemented the TriCore-backend)
suggested to use a pattern that replaces 64bit-constants by tow
INSERT_SUBREG-nodes. I ended up having the following pattern:

def : Pat<(i64 imm:$imm),
          (INSERT_SUBREG
	    (INSERT_SUBREG
	      (i64 (IMPLICIT_DEF)),
	      (i32 (LO32 imm:$imm)),
	      sub_even),
	    (i32 (HI32 imm:$imm)),
	    sub_odd)>;

OK, this leaves a DAG where all i64-Constant-nodes are replaced by to
nested INSERT_SUBREG-nodes, but how do I get rid of that
INSERT_SUBREG-stuff. Do I have to lower it separately? Should there be
some magic that eliminates those nodes for me?

Maybe, I just have to make clear that (LO32 imm:$imm) yields a
32bit-Constant (How can I do this?), as there is another pattern to
load a 32bit-Constant into a register.

Is there some documentation how all this INSERT_SUBREG-stuff should be
used and how it should work? I didn't find anything helpful here. Is
INSERT_SUBREG suitable to solve that kind of problem? In an older
post, INSERT_SUBREG was envisaged to load an i16-Value into a pair of
8bit-registers in the PIC-backend, however the outcome of this was not
mentioned. I also didn't not find any INSERT_SUBREG-stuff in the
PIC-backend in LLVM 2.7. Maybe, someone else knows something about it,
the post is here:
http://lists.cs.uiuc.edu/pipermail/llvmdev/2008-October/017443.html

I really whish I could force TypeLegalization to expand i64 although
adding a 64bit-Register class ...

> Also, why is your frontend generating 64-bit constants?

Well, using clang to translate to following piece of code:

unsigned long long do_something(unsigned long long);

unsigned long long myfunc(unsigned long long param) {
  unsigned long long b = 4500000;
  unsigned long long c = b + param;
  return c + do_something(5);
}

yields an LLVM-assembly file containing 64bit constants as follows:

define i64 @myfunc(i64 %param) nounwind uwtable {
  %1 = alloca i64, align 8
  %b = alloca i64, align 8
  %c = alloca i64, align 8
  store i64 %param, i64* %1, align 8
  store i64 4500000, i64* %b, align 8
  %2 = load i64* %b, align 8
  %3 = load i64* %1, align 8
  %4 = add i64 %2, %3
  store i64 %4, i64* %c, align 8
  %5 = load i64* %c, align 8
  %6 = call i64 @do_something(i64 5)
  %7 = add i64 %5, %6
  ret i64 %7
}

declare i64 @do_something(i64)

Ciao, Fabian