Thanks for the reply Jakob, good to know that my assumption that LLVM would split regs into smaller subregs is confirmed to be too optimistic. It would be nice if this case could be handled by LLVM, basically trying to split regs and see if patterns match with the splitted regs before giving an error. About the transformation you mentioned in the selection DAG phase, that was my initial question, how to do it. I dont know if you meant to customize each arithmetic and logical operation with setOperationAction() or if there is way to just split regs and let LLVM handle the rest, so if you could expand a bit more on how to do it that would be great :) I havent seen any other backend doing this because they all have instructions that are able to work with their widest regs, but my case is different because im working with register pairs and machine instructions can only work with the pair parts. Thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100901/e435dfff/attachment.html>
Jakob Stoklund Olesen
2010-Sep-01 22:30 UTC
[LLVMdev] Register design decision for backend
On Sep 1, 2010, at 8:57 AM, Borja Ferrer wrote:> Thanks for the reply Jakob, good to know that my assumption that LLVM would split regs into smaller subregs is confirmed to be too optimistic. It would be nice if this case could be handled by LLVM, basically trying to split regs and see if patterns match with the splitted regs before giving an error. > > About the transformation you mentioned in the selection DAG phase, that was my initial question, how to do it. I dont know if you meant to customize each arithmetic and logical operation with setOperationAction() or if there is way to just split regs and let LLVM handle the rest, so if you could expand a bit more on how to do it that would be great :) > I havent seen any other backend doing this because they all have instructions that are able to work with their widest regs, but my case is different because im working with register pairs and machine instructions can only work with the pair parts.First of all, note that if you don't tell TargetLowering about your i16 register class with addRegisterClass(), it synthesizes i16 and i32 operations just fine. The register splitting, you are talking about is already there. If you do add your i16 register class, TargetLowering is going to assume that it supports normal operations like add and sub. You must tell it that they are not available for i16 using setOperationAction(). Do some experiments with trivial functions, and see what happens. /jakob
Indeed, if you remove the i16 regs registration by removing the call to addRegisterClass() it works as expected. But that implies some other problems: You cannot pass i16/32/64 arguments to functions or return data using the register pairs (atm i've only implemented LowerReturn and LowerFormalArgs for testing trivial functions). Passing arguments in i8 regs work as expected, BUT, LLVM wont match potential 16bit instruction patterns because data is contained in 8 bit regs making code twice as big. For example, one 16 bit instruction is copying between reg pairs, so as result of this you get 2 8bit moves instead of 1 16bit move. I guess i could fold this manually, but i would have to do this for every other 16bit instructions, so i find this a bit inefficient. From these results i find that once you remove the addRegisterClass() call the i16 reg class becomes useless. On the other side, the original problem again: If i receive input args inside register pairs LLVM cant expand the i16 add into an add/adde combination. I could only work with 8 bit regs and fold somehow patterns into a 16 bit instr but replicated for every 16 bit instruction, but i want to know if there's a better solution for this since i find it too hacky and artificial. Thanks for your patience. (PS: sorry for the dup, but i sent the reply to your personal account instead of to the list.) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100902/fc0dfd6b/attachment-0001.html>
Hello Jakob, as mentioned in my previous email i'm unable to work with register pairs and let LLVM split i16 data into two i8 regs. If you know a way of doing it without heavy customization for each operation please let me know. As an alternative i could work only with i8 regs so that LLVM is able to split types, this the only way i've found so far. Doing this would imply the following changes: 1) store i16 or wider data in odd:even reg pairs (r5:r4 and not r4:r3), achieved with a register allocation hint? 2) convert all reg to reg moves that work on register pairs to one 16bit move. Thus folding two 8bit moves into one 16bit move. I'm a bit uncertain if this is possible to do by only working with 8 bit regs. I thought that maybe this could be done with some "Function Pass" before register allocation? One important thing to notice is that it's not guaranteed that the 2 moves come in a row, they could come out of order or have other instructions in between, thats why i prefer doing it before reg allocation. Since reg to reg moves are handled in a different way than the rest of instructions is this manageable? 3) load/store functions only work with register pairs. Here i think it would have to be handled in the selectionDAG? Thanks for the help. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100908/342e373b/attachment-0001.html>