Hi, I am working on a new back-end for LLVM. This architecture has two register types, data(A) and accumulator(B). A registers are i32 where as B registers are i64. This is causing me some headaches, as far as I can tell, it's not really possible to mix the two using tablegen? In the hardware, every instruction can either take an A register or a B register, in tablegen (as far as I can understand) this is not possible. I ended up creating instructions like MOV32ri (register immediate) MOV32rr (register register) MOV64rr, MOV64ri etc. I've done this for essentially every instruction. This kind of works, but there are issues. It results in unneeded copies between A registers and B registers. If a value is in an A register and the other is in a B, LLVM will do a copy between registers to make sure both registers are the same "type"(same bank) before doing the operation. Is there any way around this? Also is it really necessary to define a different instruction for each register type (even though it's the same instruction in hardware, with the same encoding etc). Another issue is that when multiplying, the result must always be stored in a B (accumulator register). So I did some custom lowering for the MUL node, and got the instruction to always write the result to a B register. The problem is that later on LLVM will move it from a B register to an A register which means the result getting truncated (64 bit -> 32 bit). I am also unsure how to deal with this. I just want to confirm that I'm doing this somewhat correctly and there isn't a much more obvious and better way of doing this. Kind Regards, Jonathan -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140902/69216c4d/attachment.html>
On Tue, Sep 02, 2014 at 11:12:23AM +0100, Johnny Val wrote:> Hi, > > I am working on a new back-end for LLVM. This architecture has two register > types, data(A) and accumulator(B). > > A registers are i32 where as B registers are i64. This is causing me some > headaches, as far as I can tell, it's not really possible to mix the two > using tablegen? > > In the hardware, every instruction can either take an A register or a B > register, in tablegen (as far as I can understand) this is not possible. > > I ended up creating instructions like > > MOV32ri (register immediate) > MOV32rr (register register) > MOV64rr, MOV64ri etc. > > I've done this for essentially every instruction. This kind of works, but > there are issues. > > It results in unneeded copies between A registers and B registers. If a > value is in an A register and the other is in a B, LLVM will do a copy > between registers to make sure both registers are the same "type"(same > bank) before doing the operation. >Is it legal to have to mix register classes in an instruction? For example, ADD AReg, BReg? If so you will need add more instruction variants e.g. ADD3264rr, ADD6432rr.> Is there any way around this? Also is it really necessary to define a > different instruction for each register type (even though it's the same > instruction in hardware, with the same encoding etc). >There is not really a good way around this, but it is not so bad if you use multiclasses.> Another issue is that when multiplying, the result must always be stored in > a B (accumulator register). So I did some custom lowering for the MUL node, > and got the instruction to always write the result to a B register. >How are you defining your MUL instruction? If you define the MUL instruction in tablegen with a B register as destination register, then it should always output to a B register. -Tom> The problem is that later on LLVM will move it from a B register to an A > register which means the result getting truncated (64 bit -> 32 bit). I am > also unsure how to deal with this. > > I just want to confirm that I'm doing this somewhat correctly and there > isn't a much more obvious and better way of doing this. > > Kind Regards, > > Jonathan> _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
On Tue, Sep 2, 2014 at 3:38 PM, Tom Stellard <tom at stellard.net> wrote:> > On Tue, Sep 02, 2014 at 11:12:23AM +0100, Johnny Val wrote: > > Hi, > > > > I am working on a new back-end for LLVM. This architecture has tworegister> > types, data(A) and accumulator(B). > > > > A registers are i32 where as B registers are i64. This is causing mesome> > headaches, as far as I can tell, it's not really possible to mix the two > > using tablegen? > > > > In the hardware, every instruction can either take an A register or a B > > register, in tablegen (as far as I can understand) this is not possible. > > > > I ended up creating instructions like > > > > MOV32ri (register immediate) > > MOV32rr (register register) > > MOV64rr, MOV64ri etc. > > > > I've done this for essentially every instruction. This kind of works,but> > there are issues. > > > > It results in unneeded copies between A registers and B registers. If a > > value is in an A register and the other is in a B, LLVM will do a copy > > between registers to make sure both registers are the same "type"(same > > bank) before doing the operation. > > > > Is it legal to have to mix register classes in an instruction? Forexample,> ADD AReg, BReg? > > If so you will need add more instruction variants e.g. > ADD3264rr, ADD6432rr.This is what I attempted to do. I get errors such as: "Type inference contradiction found, merging 'i32' into 'i64' " Which is where I got the idea that mixing types in the tablegen instructions was not allowed.> > Is there any way around this? Also is it really necessary to define a > > different instruction for each register type (even though it's the same > > instruction in hardware, with the same encoding etc). > > > > There is not really a good way around this, but it is not so bad if > you use multiclasses. > > > Another issue is that when multiplying, the result must always bestored in> > a B (accumulator register). So I did some custom lowering for the MULnode,> > and got the instruction to always write the result to a B register. > > > > How are you defining your MUL instruction? If you define the MUL > instruction in tablegen with a B register as destination register, > then it should always output to a B register. >I did do that, and that is indeed what happens. My C++ lowering code, quite literally, just replaces ISD::MUL nodes with my target specific MUL node. I leave the pattern empty in the tablegen description of the instruction to avoid the previously described error. Is this the correct way of solving this problem?> -Tom > > > The problem is that later on LLVM will move it from a B register to an A > > register which means the result getting truncated (64 bit -> 32 bit). Iam> > also unsure how to deal with this. > > > > I just want to confirm that I'm doing this somewhat correctly and there > > isn't a much more obvious and better way of doing this. > > > > Kind Regards, > > > > Jonathan > > > _______________________________________________ > > LLVM Developers mailing list > > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdevThanks for the help! -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140902/96d12860/attachment.html>
Reasonably Related Threads
- [LLVMdev] Adding a stack probe function attribute
- [LLVMdev] Adding a stack probe function attribute
- [LLVMdev] Codegen/Register allocation question.
- [LLVMdev] What does this error mean: psuedo instructions should be removed before code emission?
- [LLVMdev] Codegen/Register allocation question.