<div dir="ltr">Thank you for all the help. <br><br>I feel like I am pretty close to getting this working for my architecture. The issue I am having right now is that I cannot get the DAGCombiner to lower/combine a load/store into a pre-indexed load/store.<br><br>I believe the "issue" is with this code(DAGCombiner.cpp:7841):<br><br>  // If the pointer is not an add/sub, or if it doesn't have multiple uses, bail<br>  // out.  There is no reason to make this a preinc/predec.<br>  if ((Ptr.getOpcode() != ISD::ADD && Ptr.getOpcode() != ISD::SUB) ||<br>      Ptr.getNode()->hasOneUse())<br>    return false;<br><br><br>Specifically the "Ptr.GetNode()->hasOneUse()" statement. It seems like a fair assumption to make as most architectures probably have the option for "normal" loads as well as preinc/predec loads. Sadly my architecture only supports preinc addressing when accessing memory.<br><br>What would you suggest to do in this case? Create custom lowering for ISD::STORE/LOAD in my backend? Or do you think it's better to patch DAGCombiner.cpp to allow targets to disable that check?<br><br>Cheers,<br><br>Johnny<br><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 23, 2014 at 7:19 PM, Hal Finkel <span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">----- Original Message -----<br>
> From: "Bruce Hoult" <<a href="mailto:bruce@hoult.org">bruce@hoult.org</a>><br>
> To: "Johnny Val" <<a href="mailto:johnnydval@gmail.com">johnnydval@gmail.com</a>><br>
> Cc: "<<a href="mailto:llvmdev@cs.uiuc.edu">llvmdev@cs.uiuc.edu</a>>" <<a href="mailto:llvmdev@cs.uiuc.edu">llvmdev@cs.uiuc.edu</a>><br>
> Sent: Thursday, October 23, 2014 8:31:35 AM<br>
> Subject: Re: [LLVMdev] Question regarding getElementPtr/Addressing modes in   backend<br>
><br>
> Many CPU instruction sets have "autoincrement" / "postincrement"<br>
> (pop) / "predecrement" (push) instructions that dereference a<br>
> pointer register and also alter it by the size of the load or store.<br>
><br>
><br>
> The PowerPC has "load byte/short/word with update" instructions that<br>
> add an arbitrary positive or negative literal offset (unrelated to<br>
> the load/store size) to the pointer register BEFORE the load or<br>
> store, and update the register with the final address.<br>
><br>
> So maybe the PowerPC back end is worth looking at?<br>
<br>
</span>Yes, and so it ARM (which has both pre- and post-increment loads/stores).<br>
<br>
For PowerPC, for example, this works as follows:<br>
<br>
In PPCISelLowering.cpp, we have this:<br>
<br>
  // PowerPC has pre-inc load and store's.<br>
  setIndexedLoadAction(ISD::PRE_INC, MVT::i1, Legal);<br>
  setIndexedLoadAction(ISD::PRE_INC, MVT::i8, Legal);<br>
  setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal);<br>
  setIndexedLoadAction(ISD::PRE_INC, MVT::i32, Legal);<br>
  setIndexedLoadAction(ISD::PRE_INC, MVT::i64, Legal);<br>
  setIndexedStoreAction(ISD::PRE_INC, MVT::i1, Legal);<br>
  setIndexedStoreAction(ISD::PRE_INC, MVT::i8, Legal);<br>
  setIndexedStoreAction(ISD::PRE_INC, MVT::i16, Legal);<br>
  setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal);<br>
  setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal);<br>
<br>
Then the DAGCombiner calls into the backend using the function PPCTargetLowering::getPreIndexedAddressParts, which tells DAGCombine when it can combine the the load and the increment into a singe pre/post-increment load or store.<br>
<br>
The pre-increment stores are instruction-selected in PPCInstrInfo.td (look for the pre_store patterns). The pre-increment loads are selected in PPCISelDAGToDAG.cpp (TableGen can't yet handle instructions returning multiple outputs), look for the code just after ISD::PRE_INC around line 1060.<br>
<br>
>From your formula below, it looks like you have a pre-increment load.<br>
<br>
 -Hal<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
><br>
> On Fri, Oct 24, 2014 at 1:30 AM, Johnny Val < <a href="mailto:johnnydval@gmail.com">johnnydval@gmail.com</a> ><br>
> wrote:<br>
><br>
><br>
><br>
> Hi Steve,<br>
><br>
> Thanks for the tip regarding MIOperandInfo, I didn't think of that<br>
> part of the tablegen description.<br>
><br>
> Sadly, I did actually mean: r1 = *(i0 += m0).<br>
><br>
> So increment i0 by m0. Read memory the memory location "pointed" to<br>
> by i0. Store in r1. Sadly I am not too familiar with compiler<br>
> terminology, so I don't know if there is a proper term for such a<br>
> load.<br>
><br>
><br>
><br>
><br>
><br>
><br>
> On Thu, Oct 23, 2014 at 12:23 PM, Steve Montgomery <<br>
> <a href="mailto:stephen.montgomery3@btinternet.com">stephen.montgomery3@btinternet.com</a> > wrote:<br>
><br>
><br>
> You might need to modify selectAddr so it doesn't fold the add node<br>
> but instead returns two operands: one for the pointer and one for<br>
> the offset. You can control the register classes for the two<br>
> components of the address using MIOperandInfo so your base pointer<br>
> can be IClass and the offset MClass. See SparcInstrInfo.td (and<br>
> probably others) for examples.<br>
><br>
> I'm assuming you meant r1 = *(i0 + m0) rather than r1 = *(i0 += m0)?<br>
> I don't know how you'd achieve that latter.<br>
><br>
> Steve Montgomery<br>
><br>
> On 21 Oct 2014, at 17:15, Johnny Val < <a href="mailto:johnnydval@gmail.com">johnnydval@gmail.com</a> > wrote:<br>
><br>
><br>
><br>
> > Hi,<br>
> ><br>
> > I am writing a backend and having issues with properly lowering the<br>
> > result of getElementPtr ( specifically the add node that it<br>
> > generates).<br>
> ><br>
> > If we take this IR:<br>
> ><br>
> > %struct.rectangle = type { i24, i24 }<br>
> ><br>
> > ; Function Attrs: nounwind readonly<br>
> > define i24 @area(%struct.rectangle* nocapture readonly %r) #0 {<br>
> > entry:<br>
> > %width = getelementptr inbounds %struct.rectangle* %r, i16 0, i32 0<br>
> > %0 = load i24* %width, align 4, !tbaa !1<br>
> > %height = getelementptr inbounds %struct.rectangle* %r, i16 0, i32<br>
> > 1<br>
> > %1 = load i24* %height, align 4, !tbaa !6<br>
> > %mul = mul nsw i24 %1, %0<br>
> > ret i24 %mul<br>
> > }<br>
> ><br>
> > The DAG before isel would look like isel.png.<br>
> ><br>
> > I would then pattern match the load nodes with:<br>
> ><br>
> > [(set i24:$val, (load addr:$addr))]<br>
> ><br>
> > Where addr is a complex pattern. This is fine for the 0th element<br>
> > in the struct, as there is no offset so the resultant assembly<br>
> > would be (which works fine):<br>
> ><br>
> > r0 = *(i0)<br>
> ><br>
> > The issue I have is with the second load. I need the result to be:<br>
> ><br>
> > m0 = 4<br>
> > r1 = *(i0 += m0) (offset is stored in a register(m0), and modifies<br>
> > the original pointer)<br>
> ><br>
> > rather than<br>
> ><br>
> > r1 = *(i0 + 4) (immediate)<br>
> ><br>
> > (The specific registers numbers don't matter).<br>
> ><br>
> > I'm not sure how to achieve that. Currently addr gets matched in<br>
> > SelectAddr in XYZISelDAGToDAG.cpp. It will match the add node and<br>
> > "combine" (I'm not sure this is the correct terminology) it into<br>
> > my LDR node. The result of this can be seen sched.png<br>
> ><br>
> > So instead of that TargetConst<4> I need a something that copies 4<br>
> > into an M register, and then LDR uses that.<br>
> ><br>
> > I'm not sure if I should put logic in SelectAddr to create a<br>
> > virtual register and create a series of copyfromreg/copytoreg to<br>
> > copy the constant into an M register and then pass that to the<br>
> > node? I feel like that is fairly ugly (as no other back-end does<br>
> > this), but I'm not sure what a better way would be.<br>
> ><br>
> > I have tried looking through other backends for an example, but<br>
> > couldn't find something similar. That could be due to me not<br>
> > knowing where to look.<br>
> ><br>
> > Thanks in advance for any help.<br>
> ><br>
> > Johnny<br>
><br>
><br>
> > <isel.png><sched.png>_______________________________________________<br>
> > LLVM Developers mailing list<br>
> > <a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
> > <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
><br>
><br>
><br>
> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a> <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
><br>
><br>
><br>
> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
><br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">--<br>
Hal Finkel<br>
Assistant Computational Scientist<br>
Leadership Computing Facility<br>
Argonne National Laboratory<br>
</font></span></blockquote></div><br></div>