[llvm-dev] Expanding a PseudoOp and accessing the DAG
Phil Tomson via llvm-dev
llvm-dev at lists.llvm.org
Fri Jan 15 10:49:19 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". 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)>;
>
I'm not entirely sure what to replace 'load' with in the patterns above.
I notice that we have these defm's in our XSTGInstrInfo.td file:
defm LOADI64 : LoadOp< 0b1001010, "load", OpInfo_I64, II_LOAD1 >;
defm LOADF64 : LoadOp< 0b1001010, "load", OpInfo_F64, II_LOAD1 >;
defm LOADI32 : LoadOp< 0b1001010, "load", OpInfo_I32, II_LOAD1 >;
defm LOADF32 : LoadOp< 0b1001010, "load", OpInfo_F32, II_LOAD1 >;
defm LOADI16 : LoadOp< 0b1001010, "load", OpInfo_I16, II_LOAD1 >;
defm LOADI8 : LoadOp< 0b1001010, "load", OpInfo_I8, II_LOAD1 >;
I tried replacing 'load' with 'LOADI64' in the patter, like this:
def: Pat<(LOADI64 (XSTGADDR_NORMAL tglobaladdr:$addr)),
(LOADI64 tglobaladdr:$addr, 0)>;
But that resulted in:
XSTGInstrPatterns.td:619:11: error: Variable not defined: 'LOADI64'
def: Pat<(LOADI64 (XSTGADDR_NORMAL tglobaladdr:$addr)),
> 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/20160115/cff29843/attachment.html>
More information about the llvm-dev
mailing list