This is an archive of the discontinued LLVM Phabricator instance.

Reverse the order of allocation of return value registers to be compatible with MSPGCC
AbandonedPublic

Authored by jobnoorman on Jun 26 2013, 9:20 AM.

Details

Reviewers
asl
Summary

LLVM uses the exact reverse order of return registers as MSPGCC. This patch fixes this.

Note that I did not find a clean way to do this using tablegen so the method I used might look like a hack :-)

Diff Detail

Event Timeline

asl requested changes to this revision.Jun 26 2013, 11:03 AM

The register allocation order is defined by RetCC_MSP430 entry inside MSP430CallingConv.td

jobnoorman requested a review of this revision.Jun 27 2013, 2:23 AM

Yes, I have been playing around with the calling convention definitions but I think there is no way to match MSPGCC's return value convention. Let me try to explain what I think the problem is.

First and for all, before the ISel phase even begins, all values larger than i16 are lowered (is that the correct terminology?) to a number of i16 values. This means using something like

CCIfType<[i64], CCAssignToReg<[R12W, R13W, R14W, R15W]>>

doesn't do anything since i64 types simply do not exist any more at this point.

So returning a value larger than i16 will result in returning multiple i16 values and I have found no way to convince tablegen to put those in the correct registers.

Here is MSPGCC's return value calling convention (I'll use little endian ordering of the registers):

TypeRegisters
i16r15
i32r15:r14
i64r15:r14:r13:r12

Currently, LLVM uses the following rule:

CCIfType<[i16], CCAssignToReg<[R15W, R14W, R13W, R12W]>>

which produces this register assignment:

TypeRegisters
i16r15
i32r14:r15
i64r12:r13:r14:r15

Although this is the exact reverse of what MSPGCC does, we cannot simply reverse the tablegen rule to become

CCIfType<[i16], CCAssignToReg<[R12W, R13W, R14W, R15W]>>

since this will produce the following register assignment:

TypeRegisters
i16r12
i32r13:r12
i64r15:r14:r13:r12

Therefore, my patch will simply reverse the order of allocated registers after the tablegen rule has been applied which always does the correct thing.

asl requested changes to this revision.Jun 27 2013, 11:27 AM

This is hackish solution, because it seems to the fix outcome of the problem, but not the problem by itself. It looks like we need to change the splitting of i32 / i64 here. Because otherwise the difference might be seen in other places.... (what's about e.g. i32 stores?)

jobnoorman requested a review of this revision.Jun 28 2013, 7:12 AM

I completely agree this is a hackish solution and we need something better. However, I do not think there is a problem with the splitting of i32/i64 since it mostly does what it should do. For example, loads/stores of these values work correctly since codegen knows we are little endian.

Also, for the calling convention, I think codegen is doing the "logical" thing. Return values are assigned to R15-R12 and codegen assigns the return value in little endian byte order to these registers (R15=LSB, r12=MSB). The thing is that the calling convention used by MSPGCC is kind of weird: registers should also be picked in the order R15-R12 but then the actual return value should be assigned to these registers in big endian byte order (R15=MSB, R12=LSB). Also note that exactly the same happens for i32/i64 arguments. This is actually a bigger problem since my hack won't work for arguments :-)

After looking a bit longer at the code, I don't really see a clean way to solve this problem. Do you think it it might be a good option to implement the calling convention "by hand"? That is, without using tablegen.

jobnoorman abandoned this revision.Jul 3 2013, 7:44 AM

This revision is obsoleted by D1086.