[LLVMdev] Overlapping register classes

someguy just.s0m3.guy+llvmdev at gmail.com
Mon Mar 16 00:33:49 PDT 2009


I don't know if there is a 'real' solution to your issue, but you
might consider implementing some pseudo instructions for conversions
between register classes. This should help alleviate the issue you are
currently getting, as (with the right patterns) the generator should
automatically insert the conversion instructions when needed.

Alternatively, you could kill your 'joint' register class, and simply
use multiple patterns on those instructions which can use all
registers. This is  probably the right way to go.

Lastly, you could use a single 'joint' register class, and some
predicates in your .td to make sure that only specific registers in
the class are used for a given pattern.

In any case, I recommend you come hang out on the IRC channel. I've
just struggled through a lot of the backend target stuff, and may be
able to help you avoid the pitfalls I hit. (I also know a little
blackfin ;)).

On Sun, Mar 15, 2009 at 11:02 PM, Jakob Stoklund Olesen <stoklund at 2pi.dk> wrote:
> Hi,
>
> I am writing a backend for the Blackfin processor from Analog Devices. I
> just started so I still have a lot to learn about the code generator. So
> far, I can compile test/CodeGen/Generic/BasicInstrs.ll correctly, but
> that is about it.
>
> The Blackfin 32-bit registers divide naturally into several classes. I
> have modelled these register classes without knowing anything about what
> the code generator expects.
>
> There are data and pointer registers:
>
> def D : RegisterClass<"Bfin", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]>;
> def P : RegisterClass<"Bfin", [i32], 32, [P0, P1, P2, P3, P4, P5, SP, FP]>;
>
> For instance, a zero-extending byte load needs the address in a P-reg
> and can only load a D-reg:
>
> def LOAD32p_8z: F1<(outs D:$dst), (ins P:$ptr),
>                   "$dst = B[$ptr] (Z);",
>                   [(set D:$dst, (zextloadi8 P:$ptr))]>;
>
> Some instructions work on all registers:
>
> def GR : RegisterClass<"Bfin", [i32], 32,
>    [R0, R1, R2, R3, R4, R5, R6, R7,
>     P0, P1, P2, P3, P4, P5, SP, FP,
>     I0, I1, I2, I3, M0, M1, M2, M3,
>     B0, B1, B2, B3, L0, L1, L2, L3]>;
>
> For instance, I can load an arbitrary 32-bit constant or
> globaladdr/externalsym into any register:
>
> def LOAD32imm: Pseudo<(outs GR:$dst), (ins i32imm:$src),
>                      "$dst.H = HI($src); $dst.L = LO($src);",
>                      [(set GR:$dst, imm:$src)]>;
>
> I think I am stretching the code generator beyond its capability by
> doing this. As far as I can tell, instruction selection is done purely
> based on value types. Register classes are not considered.
>
> I get in trouble when I try to compile this function:
>
> @i1_l = external global i1
> @i1_s = external global i1
>
> define void @i1_ls() nounwind  {
>        %tmp = load i1* @i1_l
>        store i1 %tmp, i1* @i1_s
>        ret void
> }
>
> Instruction selection works correctly, but the scheduling step fails
> with "Register class of operand and regclass of use don't agree!" in
> ScheduleDAGSDNodes::AddOperand. The selected DAG contains:
>
>    (LOAD32p_8z (LOAD32imm (tglobaladdr "i1_l")))
>
> LOAD32imm produces a GR-class vreg, and LOAD32p_8z expects a P-class
> vreg, hence the error. But P is a subclass of GR, so if the vreg class
> were changed to P everything would work.
>
> The solution is not always that simple. There could be multiple uses
> with different regclasses, or the def and use regclasses could be
> disjoint so a reg-to-reg copy would be necessary.
>
> Am I misusing register classes, or is this simply functionality that has
> not been written yet? The existing backends seem to have only one
> register class per machine value type.
>
> Regards,
> /stoklund
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>




More information about the llvm-dev mailing list