Questions for new Backend

Hi,

I am trying to do a backend to a very simple microcontroller. I have some
questions.

1) I have instruction which do "r1 <- r1 op r2", from what I have ssen I
must declare them like:

let isTwoAddress = 1 in
def ADD : FopRR< 0b01010,
                   (outs CPURegs:$sX), (ins CPURegs:$isX, CPURegs:$sY),
                   "ADD $sX, $sY"),
                   [(set CPURegs:$sX, (add CPURegs:$isX, CPURegs:$sY))]>;

Where CPURegs is my class of register. I suppose that the pass
TwoAddressInstructionPass will make the $sX and $isX register the same (it
unify the out reg and the first in reg?) ?

When should I set isConvertibleToThreeAddress to 1? When I have another form
of the instruction which take a three addresses?

2) Instr class contain the following properties. I suppose they must be set
correctly for? I have some question on them. If only '?' I don't understand
at all, if no comment then I think I understand.
  int CodeSize = 0; // in bits? Or bytes?
  int AddedComplexity = 0; // ?
  bit isReturn = 0;
  bit isBranch = 0;
  bit isIndirectBranch = 0;
  bit isBarrier = 0; // ? memory barrier?
  bit isCall = 0;
  bit isSimpleLoad = 0; // simple?
  bit mayLoad = 0;
  bit mayStore = 0;
  bit isTwoAddress = 0; // see question 1
  bit isConvertibleToThreeAddress = 0; // see question 1
  bit isCommutable = 0; // see rq1 below
  bit isTerminator = 0; // terminate what? A BB, A function, or the
program
  bit isReMaterializable = 0; // ?
  bit isPredicable = 0;
  bit hasDelaySlot = 0;
  bit usesCustomDAGSchedInserter = 0;
  bit hasCtrlDep = 0; // ?
  bit isNotDuplicable = 0; // ?
  bit hasSideEffects = 0;
  bit mayHaveSideEffects = 0; // how is this different from has side effect?
  bit neverHasSideEffects = 1;

Rq1: If I have a instruction 'add reg, imm' and don't have 'add imm, reg' I
suppose the instruction isn't commutable?

3) For conditional jump:
the architecture use the flags carry and zero to do conditional jump (ex:
jump if carry set) and most arithmetic operation set these flags. I was
wondering how to handle this. I have seen some CC (condition code) in some
backend but it is not clear. Or I could model precisely the flag but then
the operations would have more than on output and it seems this isn't
supported at least in the tablegen? Could you give me some pointer

4) IO: on this µC, the IO aren't mapped in the main address space and use a
separate set of load/store. I was thinking of using the new functionality of
multiple address space. But should the separation be done in the
legalization phase or in the instruction selection phase?

This is all for the moment :wink:

Regards,

Hi,

I am trying to do a backend to a very simple microcontroller. I have some
questions.

Ok.

1) I have instruction which do "r1 <- r1 op r2", from what I have ssen I
must declare them like:

let isTwoAddress = 1 in
def ADD : FopRR< 0b01010,
                  (outs CPURegs:$sX), (ins CPURegs:$isX, CPURegs:$sY),
                  "ADD $sX, $sY"),
                  [(set CPURegs:$sX, (add CPURegs:$isX, CPURegs:$sY))]>;

Where CPURegs is my class of register. I suppose that the pass
TwoAddressInstructionPass will make the $sX and $isX register the same (it
unify the out reg and the first in reg?) ?

Yes. 'isTwoAddress' is just shorthand for saying that Xs and isX are constrainted to be tied together. You can constrain any two registers of the same class with 'Constraints = "$src = $dst"'.

When should I set isConvertibleToThreeAddress to 1? When I have another form
of the instruction which take a three addresses?

Yes. This is useful when the two address form is more efficient than the three address form in some way. This will cause the codegen to prefer the two address form, but fall back to the 3-addr one when it would otherwise have to insert a copy.

2) Instr class contain the following properties. I suppose they must be set
correctly for? I have some question on them. If only '?' I don't understand
at all, if no comment then I think I understand.

Take a look at lib/Target/*.td for comments on each of these fields.

int AddedComplexity = 0; // ?

This is optional, used to tweak instruction selection priority.

bit isReMaterializable = 0; // ?

Conservatively safe to leave as zero. This will hopefully go away in the future.

Rq1: If I have a instruction 'add reg, imm' and don't have 'add imm, reg' I
suppose the instruction isn't commutable?

'add' (in the target independent sense) is a commutable operation, so the code generator will always canonicalize the immediate to the RHS of the operator. Commutative *instruction* must have two input register operands, so 'reg,imm' doesn't make sense to be commutative.

3) For conditional jump:
the architecture use the flags carry and zero to do conditional jump (ex:
jump if carry set) and most arithmetic operation set these flags. I was
wondering how to handle this. I have seen some CC (condition code) in some
backend but it is not clear. Or I could model precisely the flag but then
the operations would have more than on output and it seems this isn't
supported at least in the tablegen? Could you give me some pointer

We don't have wonderful ways of modeling this (i.e. taking advantage of flags set by random operations) yet, but X86 works the same way. I'd look at how its backend works.

4) IO: on this µC, the IO aren't mapped in the main address space and use a
separate set of load/store. I was thinking of using the new functionality of
multiple address space. But should the separation be done in the
legalization phase or in the instruction selection phase?

Instruction selection should match on the address space qualifier of the pointer value in the SrcValue for the load or store.

Ps: the µC I target is Picoblaze of xilinx:
Documentation Portal
I know that having a compiler for a µC this small isn't useful (asm is
better in this case) but my goal is more too learn how to do a backend that
to really do it.
And I know there is no indirect jump on this architecture so not all llvm
code can be legalized.
In fact I would like to have a template backend for small 8/16 bits µC to be
able to target custom FPGA embedded µC really easily.

This would be an interesting target to add to mainline llvm. It seems like a great example of a small architecture. We don't have any 8/16 bit arch's and nothing that uses ASI's in mainline yet. It would be great to have an example.

-Chris

Hi Cedric, Chris,

I had a similar thought, namely that having a simple 16/8-bit arch in clang+LLVM would be a great instructional tool. I’m currently whipping up a quick back end for the 16-bit LC-3 instructional architecture (http://en.wikipedia.org/wiki/LC-3). I thought it’d be a good example because it is both extremely simple, but also quite functionally complete, and it has free assemblers and simulators available (not to mention that it’s used to teach basic architecture and tools at a number of universities).

If you think this would be useful let me know and I can commit back to the repo sooner rather than later.

That would be very nifty.

-Chris