[LLVMdev] Overlapping register classes

Jakob Stoklund Olesen stoklund at 2pi.dk
Sun Mar 15 14:02:50 PDT 2009


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




More information about the llvm-dev mailing list