[LLVMdev] Pointer vs. integer: backend troubles

Jakob Stoklund Olesen stoklund at 2pi.dk
Wed May 6 10:47:26 PDT 2009


On 06/05/2009, at 10.58, Christoph Erhardt wrote:
[...]
> Unfortunately, this does not hold true for the TriCore architecture,
> which strictly differentiates between "normal" integer values and
> pointer values. The register set is split into two subsets: 16
> general-purpose registers %d0..%d15 for 32-bit integers and floats,  
> and
> 16 address registers %a0..%a15 for 32-bit pointers, with separate
> instructions.

Hi Christoph,

I am working on a back end for the blackfin DSP. It also has two  
register sets: data and pointers, so the architectures are similar. I  
am using a lot of register classes to represent the many instruction  
constraints. The code generator support for weird register classes has  
improved a lot recently.

The instruction selector does not know about register classes - it  
only uses value types when pattern matching. That is probably a good  
idea; it can be hard to tell what is a pointer and what is an integer  
beforehand.

After instruction selection is complete, each virtual register is  
assigned to a register class (A or D, say). Currently, the defining  
instruction determines the register class. Sometimes it is necessary  
to insert extra copy instructions before instructions that require an  
incompatible register class. Enabling -join-cross-class-copies will  
clean up a lot of these copies afterwards.

I have a patch in my own tree that will do register class inference  
instead: It tries to choose a register class for a virtual register  
based on all interested instructions, rather than just the defining  
one. This causes less copies to be emitted only to be removed later.  
The end result is similar, so it is mostly an optimisation.

There are some unsolved problems:

1. Virtual registers from PHI nodes are created before instruction  
selection, so there is no way of giving them a proper register class.  
Instead, TargetLowering::getRegClassFor() is used, fingers crossed. It  
may be that -join-cross-class-copies is able to clean up here too. I  
have not tested that. Ideally, I would like  
TargetLowering::getRegClassFor() to go away entirely.

2. There is no way of using alternative instructions with different  
operand classes. For instance, TriCore can subtract two D registers  
(SUB), or two A registers (SUB.A). You can only have one pattern for  
i32 subtraction, so the SUB.A instruction will not be used. We need a  
way of replacing SUB with SUB.A when it makes sense. Calculating when  
it makes sense is the hard part.

You can produce correct code without solving these problems - you will  
just have some extra copies between A and D registers.

> Moreover, the ABI requires that pointer arguments to (and
> pointer results from) functions be passed in address registers instead
> of general-purpose registers.

You should treat this as a separate issue from register allocation.  
The ABI requirements must be followed exactly, and you need some kind  
of annotation as Dan described. For register allocation you can be  
less exact, and that can be an advantage. Pointer and integer  
arithmetic is sometimes mixed, and it can be an advantage to keep an  
integer in a pointer register and vice versa.

HTH
/jakob




More information about the llvm-dev mailing list