Phil Tomson via llvm-dev
2016-Jan-15 18:49 UTC
[llvm-dev] Expanding a PseudoOp and accessing the DAG
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>
Phil Tomson via llvm-dev
2016-Jan-15 19:08 UTC
[llvm-dev] Expanding a PseudoOp and accessing the DAG
On Fri, Jan 15, 2016 at 10:49 AM, Phil Tomson <phil.a.tomson at gmail.com> wrote:> > > 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)), > >Ah, I see, the defm is a multi-class so I needed to change it to: def: Pat<(load (XSTGADDR_NORMAL tglobaladdr:$addr)), (LOADI64_RI tglobaladdr:$addr, 0)>; // Match load from a relocatable address to a load with GRP: def: Pat<(load (XSTGADDR_USE_GRP tglobaladdr:$addr)), (LOADI64_RI (MOVIMMZ_I64 tglobaladdr:$addr), GRP)>; ...at least that gets through TableGen.> >> 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/950b7e74/attachment.html>
Krzysztof Parzyszek via llvm-dev
2016-Jan-15 20:10 UTC
[llvm-dev] Expanding a PseudoOp and accessing the DAG
On 1/15/2016 1:08 PM, Phil Tomson wrote:> > Ah, I see, the defm is a multi-class so I needed to change it to: > > def: Pat<(load (XSTGADDR_NORMAL tglobaladdr:$addr)), > (LOADI64_RI tglobaladdr:$addr, 0)>; > // Match load from a relocatable address to a load with GRP: > def: Pat<(load (XSTGADDR_USE_GRP tglobaladdr:$addr)), > (LOADI64_RI (MOVIMMZ_I64 tglobaladdr:$addr), GRP)>;Right.> ...at least that gets through TableGen.Excellent. -Krzysztof -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation