[llvm-dev] Expanding a PseudoOp and accessing the DAG

Phil Tomson via llvm-dev llvm-dev at lists.llvm.org
Thu Jan 14 17:34:14 PST 2016


On Thu, Jan 14, 2016 at 6:05 AM, Krzysztof Parzyszek <
kparzysz at codeaurora.org> wrote:

> On 1/13/2016 4:47 PM, Phil Tomson wrote:
>
>>
>> First off, I got this idea from the LLVM Cookbook chapter 8: Writing an
>> LLVM Backend: Lowering to multiple instructions. (now I'm having my
>> doubts as to whether this is the right approach)
>>
>
> 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.
>
>
>
> Let me explain at the assembly level what I'm trying to accomplish.
>>
>> We're trying to make position independent executables, so we intend to
>> have a switch like -fPIE. In that case we've designated some registers
>> to be pointers to various address spaces (and our processor is rather
>> complicated so there are several address spaces).
>>
>> Right now,  given a global variable called 'answer' in C we end up with
>> the following in the .s file:
>>
>>    movimm    r1, %rel(answer) # r1 <- offset to 'answer' symbol
>>    load    r1, r1, 0                     # r1<-mem[r1+0]
>>
>> This isn't correct because it should be relative to the GRP register if
>> the PIE mode is chosen, what I'd like to get is either:
>>
>>    movimm   r1, %rel(answer)
>>    addI         r1, GRP              # r1 <- r1 + GRP
>>    load         r1, r1, 0               # r1 <- mem[r1+0]
>>
>> Or even better:
>>
>>    movimm   r1, %rel(answer)
>>    load         r1, r1, GRP      # r1 <- mem[r1+GRP]
>>
>> What I'm getting at the moment is just this part:
>>
>>    load        r1, r1, GRP
>>
>> So the movimm is missing. That's because I've added the Pseudo
>> instruction RelAddr and GlobalAddress nodes get converted to RelAddr
>> nodes in LowerGlobalAddress.... They used to get converted to the MVINI
>> node type there prior to adding the RelAddr pseudo inst.
>>
>> It feels like more of this needs to be done in the LowerGlobalAddress
>> function, but I have no idea how to do it there - you seem to only be
>> able to get one instruction out of a lowering like that, not multiple
>> instructions. It also seems like (as you point out) the expansion phase
>> is too late to be doing it.
>>
>
> Here's what I would do (based on what I understand about your target so
> far):
>
> 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.
>
> In the .td file, define SDNodes corresponding to these opcodes, e.g.
> "addr_normal" and "addr_use_grp".


I'm guessing these would be Pseudo Instr nodes?

Initially I had this:

def SDT_XSTGADDR_NORMAL     : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def XSTGADDR_NORMAL         : SDNode<"XSTGISD::ADDR_NORMAL",
SDT_XSTGADDR_NORMAL>;


def addr_normal             : XSTGPseudo< (outs),
                                          (ins i64imm:$addr),
                                          "! ADDR_NORMAL $addr",
                                          [(XSTGADDR_NORMAL i64:$addr)]>;


But then TableGen gave me:
utils/TableGen/DAGISelMatcherGen.cpp:893: void
{anonymous}::MatcherGen::EmitResultInstructionAsOperand(const
llvm::TreePatternNode*, llvm::SmallVectorImpl<unsigned int>&): Assertion
`(!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) && "Node has no
result"' failed.

This is apparently because (outs) is empty. So looks like I either need
SDNPOutGlue or SDNPHasChain based on the assertion message.

This seems to work:

def SDT_XSTGADDR_NORMAL     : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def XSTGADDR_NORMAL         : SDNode<"XSTGISD::ADDR_NORMAL",
SDT_XSTGADDR_NORMAL,[SDNPOutGlue]>;


def addr_normal             : XSTGPseudo< (outs),
                                          (ins i64imm:$addr),
                                          "! ADDR_NORMAL $addr",
                                          [(XSTGADDR_NORMAL i64:$addr)]>;

...but I'm not entirely sure if that's the right definition.





> Then, you can have these patterns for loads:
>
> // Match a load from a non-relocatable address to a simple load
> // instruction (with offset 0):
> def: Pat<(load (addr_normal tglobaladdr:$addr)),
>          (load tglobaladdr:$addr, 0)>;
> // Match load from a relocatable address to a load with GRP:
> def: Pat<(load (addr_use_grp tglobaladdr:$addr)),
>          (load (movimm tglobaladdr:$addr), GRP)>;
>
> 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.
>
> Finally, in LowerGlobalAddress, you can check the relocation model,
> compilation options, etc. to see if you need to have relocatable addresses,
> or not:
>
> SDValue XSTGISelLowering::LowerGlobalAddress(SDValue Addr, SelectionDAG
> &DAG) {
>   ...
>   if (NeedGRP) {
>     SpecialTargetFlags = ...;
>     SDValue TAddr = DAG.getTargetGlobalAddress(..., SpecialTargetFlags);
>     return DAG.getNode(XSTGISD::ADDR_USE_GRP, ..., TAddr);
>   }
>
>   // Non-relocatable address:
>   SDValue NAddr = DAG.getTargetGlobalAddress(...);
>   return DAG.getNode(XSTGISD::ADDR_NORMAL, ..., NAddr);
>
> }
>
>
> -Krzysztof
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted
> by The Linux Foundation
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160114/da5ec919/attachment.html>


More information about the llvm-dev mailing list