Johnny Val
2014-Oct-21 16:15 UTC
[LLVMdev] Question regarding getElementPtr/Addressing modes in backend
Hi, I am writing a backend and having issues with properly lowering the result of getElementPtr ( specifically the add node that it generates). If we take this IR: %struct.rectangle = type { i24, i24 } ; Function Attrs: nounwind readonly define i24 @area(%struct.rectangle* nocapture readonly %r) #0 { entry: %width = getelementptr inbounds %struct.rectangle* %r, i16 0, i32 0 %0 = load i24* %width, align 4, !tbaa !1 %height = getelementptr inbounds %struct.rectangle* %r, i16 0, i32 1 %1 = load i24* %height, align 4, !tbaa !6 %mul = mul nsw i24 %1, %0 ret i24 %mul } The DAG before isel would look like isel.png. I would then pattern match the load nodes with: [(set i24:$val, (load addr:$addr))] Where addr is a complex pattern. This is fine for the 0th element in the struct, as there is no offset so the resultant assembly would be (which works fine): r0 = *(i0) The issue I have is with the second load. I need the result to be: m0 = 4 r1 = *(i0 += m0) (offset is stored in a register(m0), and modifies the original pointer) rather than r1 = *(i0 + 4) (immediate) (The specific registers numbers don't matter). I'm not sure how to achieve that. Currently addr gets matched in SelectAddr in XYZISelDAGToDAG.cpp. It will match the add node and "combine" (I'm not sure this is the correct terminology) it into my LDR node. The result of this can be seen sched.png So instead of that TargetConst<4> I need a something that copies 4 into an M register, and then LDR uses that. I'm not sure if I should put logic in SelectAddr to create a virtual register and create a series of copyfromreg/copytoreg to copy the constant into an M register and then pass that to the node? I feel like that is fairly ugly (as no other back-end does this), but I'm not sure what a better way would be. I have tried looking through other backends for an example, but couldn't find something similar. That could be due to me not knowing where to look. Thanks in advance for any help. Johnny -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141021/49867573/attachment.html> -------------- next part -------------- A non-text attachment was scrubbed... Name: isel.png Type: image/png Size: 46608 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141021/49867573/attachment.png> -------------- next part -------------- A non-text attachment was scrubbed... Name: sched.png Type: image/png Size: 45591 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141021/49867573/attachment-0001.png>
Steve Montgomery
2014-Oct-23 11:23 UTC
[LLVMdev] Question regarding getElementPtr/Addressing modes in backend
You might need to modify selectAddr so it doesn't fold the add node but instead returns two operands: one for the pointer and one for the offset. You can control the register classes for the two components of the address using MIOperandInfo so your base pointer can be IClass and the offset MClass. See SparcInstrInfo.td (and probably others) for examples. I'm assuming you meant r1 = *(i0 + m0) rather than r1 = *(i0 += m0)? I don't know how you'd achieve that latter. Steve Montgomery On 21 Oct 2014, at 17:15, Johnny Val <johnnydval at gmail.com> wrote:> Hi, > > I am writing a backend and having issues with properly lowering the result of getElementPtr ( specifically the add node that it generates). > > If we take this IR: > > %struct.rectangle = type { i24, i24 } > > ; Function Attrs: nounwind readonly > define i24 @area(%struct.rectangle* nocapture readonly %r) #0 { > entry: > %width = getelementptr inbounds %struct.rectangle* %r, i16 0, i32 0 > %0 = load i24* %width, align 4, !tbaa !1 > %height = getelementptr inbounds %struct.rectangle* %r, i16 0, i32 1 > %1 = load i24* %height, align 4, !tbaa !6 > %mul = mul nsw i24 %1, %0 > ret i24 %mul > } > > The DAG before isel would look like isel.png. > > I would then pattern match the load nodes with: > > [(set i24:$val, (load addr:$addr))] > > Where addr is a complex pattern. This is fine for the 0th element in the struct, as there is no offset so the resultant assembly would be (which works fine): > > r0 = *(i0) > > The issue I have is with the second load. I need the result to be: > > m0 = 4 > r1 = *(i0 += m0) (offset is stored in a register(m0), and modifies the original pointer) > > rather than > > r1 = *(i0 + 4) (immediate) > > (The specific registers numbers don't matter). > > I'm not sure how to achieve that. Currently addr gets matched in SelectAddr in XYZISelDAGToDAG.cpp. It will match the add node and "combine" (I'm not sure this is the correct terminology) it into my LDR node. The result of this can be seen sched.png > > So instead of that TargetConst<4> I need a something that copies 4 into an M register, and then LDR uses that. > > I'm not sure if I should put logic in SelectAddr to create a virtual register and create a series of copyfromreg/copytoreg to copy the constant into an M register and then pass that to the node? I feel like that is fairly ugly (as no other back-end does this), but I'm not sure what a better way would be. > > I have tried looking through other backends for an example, but couldn't find something similar. That could be due to me not knowing where to look. > > Thanks in advance for any help. > > Johnny > <isel.png><sched.png>_______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Johnny Val
2014-Oct-23 12:30 UTC
[LLVMdev] Question regarding getElementPtr/Addressing modes in backend
Hi Steve, Thanks for the tip regarding MIOperandInfo, I didn't think of that part of the tablegen description. Sadly, I did actually mean: r1 = *(i0 += m0). So increment i0 by m0. Read memory the memory location "pointed" to by i0. Store in r1. Sadly I am not too familiar with compiler terminology, so I don't know if there is a proper term for such a load. On Thu, Oct 23, 2014 at 12:23 PM, Steve Montgomery < stephen.montgomery3 at btinternet.com> wrote:> You might need to modify selectAddr so it doesn't fold the add node but > instead returns two operands: one for the pointer and one for the offset. > You can control the register classes for the two components of the address > using MIOperandInfo so your base pointer can be IClass and the offset > MClass. See SparcInstrInfo.td (and probably others) for examples. > > I'm assuming you meant r1 = *(i0 + m0) rather than r1 = *(i0 += m0)? I > don't know how you'd achieve that latter. > > Steve Montgomery > > On 21 Oct 2014, at 17:15, Johnny Val <johnnydval at gmail.com> wrote: > > > Hi, > > > > I am writing a backend and having issues with properly lowering the > result of getElementPtr ( specifically the add node that it generates). > > > > If we take this IR: > > > > %struct.rectangle = type { i24, i24 } > > > > ; Function Attrs: nounwind readonly > > define i24 @area(%struct.rectangle* nocapture readonly %r) #0 { > > entry: > > %width = getelementptr inbounds %struct.rectangle* %r, i16 0, i32 0 > > %0 = load i24* %width, align 4, !tbaa !1 > > %height = getelementptr inbounds %struct.rectangle* %r, i16 0, i32 1 > > %1 = load i24* %height, align 4, !tbaa !6 > > %mul = mul nsw i24 %1, %0 > > ret i24 %mul > > } > > > > The DAG before isel would look like isel.png. > > > > I would then pattern match the load nodes with: > > > > [(set i24:$val, (load addr:$addr))] > > > > Where addr is a complex pattern. This is fine for the 0th element in the > struct, as there is no offset so the resultant assembly would be (which > works fine): > > > > r0 = *(i0) > > > > The issue I have is with the second load. I need the result to be: > > > > m0 = 4 > > r1 = *(i0 += m0) (offset is stored in a register(m0), and modifies the > original pointer) > > > > rather than > > > > r1 = *(i0 + 4) (immediate) > > > > (The specific registers numbers don't matter). > > > > I'm not sure how to achieve that. Currently addr gets matched in > SelectAddr in XYZISelDAGToDAG.cpp. It will match the add node and "combine" > (I'm not sure this is the correct terminology) it into my LDR node. The > result of this can be seen sched.png > > > > So instead of that TargetConst<4> I need a something that copies 4 into > an M register, and then LDR uses that. > > > > I'm not sure if I should put logic in SelectAddr to create a virtual > register and create a series of copyfromreg/copytoreg to copy the constant > into an M register and then pass that to the node? I feel like that is > fairly ugly (as no other back-end does this), but I'm not sure what a > better way would be. > > > > I have tried looking through other backends for an example, but couldn't > find something similar. That could be due to me not knowing where to look. > > > > Thanks in advance for any help. > > > > Johnny > > <isel.png><sched.png>_______________________________________________ > > LLVM Developers mailing list > > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141023/c54c5316/attachment.html>