[LLVMdev] Question regarding getElementPtr/Addressing modes in backend

Hal Finkel hfinkel at anl.gov
Thu Oct 23 11:19:53 PDT 2014


----- Original Message -----
> From: "Bruce Hoult" <bruce at hoult.org>
> To: "Johnny Val" <johnnydval at gmail.com>
> Cc: "<llvmdev at cs.uiuc.edu>" <llvmdev at cs.uiuc.edu>
> Sent: Thursday, October 23, 2014 8:31:35 AM
> Subject: Re: [LLVMdev] Question regarding getElementPtr/Addressing modes in	backend
> 
> Many CPU instruction sets have "autoincrement" / "postincrement"
> (pop) / "predecrement" (push) instructions that dereference a
> pointer register and also alter it by the size of the load or store.
> 
> 
> The PowerPC has "load byte/short/word with update" instructions that
> add an arbitrary positive or negative literal offset (unrelated to
> the load/store size) to the pointer register BEFORE the load or
> store, and update the register with the final address.
> 
> So maybe the PowerPC back end is worth looking at?

Yes, and so it ARM (which has both pre- and post-increment loads/stores).

For PowerPC, for example, this works as follows:

In PPCISelLowering.cpp, we have this:

  // PowerPC has pre-inc load and store's.
  setIndexedLoadAction(ISD::PRE_INC, MVT::i1, Legal);
  setIndexedLoadAction(ISD::PRE_INC, MVT::i8, Legal);
  setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal);
  setIndexedLoadAction(ISD::PRE_INC, MVT::i32, Legal);
  setIndexedLoadAction(ISD::PRE_INC, MVT::i64, Legal);
  setIndexedStoreAction(ISD::PRE_INC, MVT::i1, Legal);
  setIndexedStoreAction(ISD::PRE_INC, MVT::i8, Legal);
  setIndexedStoreAction(ISD::PRE_INC, MVT::i16, Legal);
  setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal);
  setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal);

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.

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.

>From your formula below, it looks like you have a pre-increment load.

 -Hal

> 
> 
> On Fri, Oct 24, 2014 at 1:30 AM, Johnny Val < johnnydval at gmail.com >
> wrote:
> 
> 
> 
> 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
> 
> 
> 
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> 
> 
> 
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-dev mailing list