<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 15, 2016 at 10:49 AM, Phil Tomson <span dir="ltr"><<a href="mailto:phil.a.tomson@gmail.com" target="_blank">phil.a.tomson@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Thu, Jan 14, 2016 at 6:05 AM, Krzysztof Parzyszek <span dir="ltr"><<a href="mailto:kparzysz@codeaurora.org" target="_blank">kparzysz@codeaurora.org</a>></span> wrote:<br></span><div><div class="h5"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span>On 1/13/2016 4:47 PM, Phil Tomson wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
First off, I got this idea from the LLVM Cookbook chapter 8: Writing an<br>
LLVM Backend: Lowering to multiple instructions. (now I'm having my<br>
doubts as to whether this is the right approach)<br>
</blockquote>
<br></span>
There is a pass "ExpandISelPseudos", which handles instructions with custom inserters.  You can mark instructions as having custom inserters in the .td files and then override the EmitInstrWithCustomInserter function to deal with them.<div><div><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Let me explain at the assembly level what I'm trying to accomplish.<br>
<br>
We're trying to make position independent executables, so we intend to<br>
have a switch like -fPIE. In that case we've designated some registers<br>
to be pointers to various address spaces (and our processor is rather<br>
complicated so there are several address spaces).<br>
<br>
Right now,  given a global variable called 'answer' in C we end up with<br>
the following in the .s file:<br>
<br>
   movimm    r1, %rel(answer) # r1 <- offset to 'answer' symbol<br>
   load    r1, r1, 0                     # r1<-mem[r1+0]<br>
<br>
This isn't correct because it should be relative to the GRP register if<br>
the PIE mode is chosen, what I'd like to get is either:<br>
<br>
   movimm   r1, %rel(answer)<br>
   addI         r1, GRP              # r1 <- r1 + GRP<br>
   load         r1, r1, 0               # r1 <- mem[r1+0]<br>
<br>
Or even better:<br>
<br>
   movimm   r1, %rel(answer)<br>
   load         r1, r1, GRP      # r1 <- mem[r1+GRP]<br>
<br>
What I'm getting at the moment is just this part:<br>
<br>
   load        r1, r1, GRP<br>
<br>
So the movimm is missing. That's because I've added the Pseudo<br>
instruction RelAddr and GlobalAddress nodes get converted to RelAddr<br>
nodes in LowerGlobalAddress.... They used to get converted to the MVINI<br>
node type there prior to adding the RelAddr pseudo inst.<br>
<br>
It feels like more of this needs to be done in the LowerGlobalAddress<br>
function, but I have no idea how to do it there - you seem to only be<br>
able to get one instruction out of a lowering like that, not multiple<br>
instructions. It also seems like (as you point out) the expansion phase<br>
is too late to be doing it.<br>
</blockquote>
<br></div></div>
Here's what I would do (based on what I understand about your target so far):<br>
<br>
Define two additional ISD opcodes, specific to your target. One to denote a "normal" address, the other to mean "address using GRP".  For example (you can invent better names for them): XSTGISD::ADDR_NORMAL and XSGTISD::ADDR_USE_GRP. Each of them will take a global address as an operand and return an address, and their only function will be to serve as a "tag" for the instruction selection algorithm to be able to apply different selection patterns to them.<br>
<br>
In the .td file, define SDNodes corresponding to these opcodes, e.g. "addr_normal" and "addr_use_grp".  Then, you can have these patterns for loads:<br>
<br>
// Match a load from a non-relocatable address to a simple load<br>
// instruction (with offset 0):<br>
def: Pat<(load (addr_normal tglobaladdr:$addr)),<br>
         (load tglobaladdr:$addr, 0)>;<br>
// Match load from a relocatable address to a load with GRP:<br>
def: Pat<(load (addr_use_grp tglobaladdr:$addr)),<br>
         (load (movimm tglobaladdr:$addr), GRP)>;<br></blockquote><div><br></div></div></div><div>I'm not entirely sure what to replace 'load' with in the patterns above.<br><br></div><div>I notice that we have these defm's in our XSTGInstrInfo.td file:<br><br>defm LOADI64 : LoadOp< 0b1001010, "load", OpInfo_I64, II_LOAD1 >;<br>defm LOADF64 : LoadOp< 0b1001010, "load", OpInfo_F64, II_LOAD1 >;<br>defm LOADI32 : LoadOp< 0b1001010, "load", OpInfo_I32, II_LOAD1 >;<br>defm LOADF32 : LoadOp< 0b1001010, "load", OpInfo_F32, II_LOAD1 >;<br>defm LOADI16 : LoadOp< 0b1001010, "load", OpInfo_I16, II_LOAD1 >;<br>defm LOADI8  : LoadOp< 0b1001010, "load", OpInfo_I8,  II_LOAD1 >;<br><br></div><div>I tried replacing 'load' with 'LOADI64' in the patter, like this:<br><br>def: Pat<(LOADI64 (XSTGADDR_NORMAL tglobaladdr:$addr)),<br>         (LOADI64 tglobaladdr:$addr, 0)>;<br><br></div><div>But that resulted in: <br><br>XSTGInstrPatterns.td:619:11: error: Variable not defined: 'LOADI64'<br>def: Pat<(LOADI64 (XSTGADDR_NORMAL tglobaladdr:$addr)),<br></div><span class=""><div><br></div></span></div></div></div></blockquote><div><br></div><div>Ah, I see, the defm is a multi-class so I needed to change it to:<br><br> def: Pat<(load (XSTGADDR_NORMAL tglobaladdr:$addr)),<br>         (LOADI64_RI tglobaladdr:$addr, 0)>;<br>// Match load from a relocatable address to a load with GRP:<br>def: Pat<(load (XSTGADDR_USE_GRP tglobaladdr:$addr)),<br>         (LOADI64_RI (MOVIMMZ_I64 tglobaladdr:$addr), GRP)>;<br><br></div><div>...at least that gets through TableGen.<br><br><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
The patterns above should use tglobaladdr, because you will still need custom LowerGlobalAddress to generate them first, and it may need to attach special "target flags" to these addresses.<br>
<br>
Finally, in LowerGlobalAddress, you can check the relocation model, compilation options, etc. to see if you need to have relocatable addresses, or not:<br>
<br>
SDValue XSTGISelLowering::LowerGlobalAddress(SDValue Addr, SelectionDAG &DAG) {<br>
  ...<br>
  if (NeedGRP) {<br>
    SpecialTargetFlags = ...;<br>
    SDValue TAddr = DAG.getTargetGlobalAddress(..., SpecialTargetFlags);<br>
    return DAG.getNode(XSTGISD::ADDR_USE_GRP, ..., TAddr);<br>
  }<br>
<br>
  // Non-relocatable address:<br>
  SDValue NAddr = DAG.getTargetGlobalAddress(...);<br>
  return DAG.getNode(XSTGISD::ADDR_NORMAL, ..., NAddr);<div><div><br>
}<br>
<br>
<br>
-Krzysztof<br>
<br>
-- <br>
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation<br>
</div></div></blockquote></span></div><br></div></div>
</blockquote></div><br></div></div>