Jack Andersen via llvm-dev
2016-Nov-08 02:48 UTC
[llvm-dev] [MC] Target-Independent Small Data Section Handling
I've prepared a preliminary patch with the intention of implementing PPC-EABI subtarget features for applications that run in a standalone embedded environment. https://reviews.llvm.org/D26344 The most significant difference compared with the SVR4 ABI is the use of SDA (small data area). This allows full-word constants and data to be grouped into small-data sections accessed using relocated addresses; calculated relative to the non-volatile values loaded into base registers r13 and r2 by the runtime init (similar to gp_rel on MIPS). Only a single load/store instruction is needed to contain the relocated address. The MIPS target already has a solid approach for handling small global variables in its TargetLoweringObjectFile subclass. Also, the clang driver responds to the `-G <bytes>` flag so the user can define a cutoff size other than 8 (or 0 to disable small data altogether). It seems the Hexagon and Lanai targets duplicate much of the IsGlobalInSmallSection handling from the MIPS target, but perform the same basic classification tasks: 1. Pass GlobalObject to target-declared IsGlobalInSmallSection. If it's a declaration, skip to step 4. 2. Pass GlobalObject to target-independent TargetLoweringObjectFile::getKindForGlobal. 3. Ensure the returned SectionKind is Data, BSS or Common. 4. Pass GlobalObject to target-specific IsGlobalInSmallSectionImpl, which scrutinizes the object's type for the specific architecture. I believe this redundant implementation between targets can be reduced by giving SectionKind an 'isSmallKind' bit (OR'd with 0x80). This provides a much clearer (and cached) predicate that ISel lowering can take advantage of when a small data load/store must be generated. The existing predicates in SectionKind may be modified to use the underlying Kind (AND-ing with 0x7f), so existing ISel behaviors are mostly unchanged. The proposed target-independent small data classification has 2 usage avenues depending on the context: For all GlobalObjects: 1. Pass GlobalObject to target-independent TargetLoweringObjectFile::isGlobalInSmallSection. If it's a declaration, make a virtual call to a new method named TargetLoweringObjectFile::isGlobalInSmallSectionKind (doing target-specific scrutiny) and return the result early. 2. Pass to TargetLoweringObjectFile::getKindForGlobal. If the Kind is Data, BSS or Common, make a virtual call to TargetLoweringObjectFile::isGlobalInSmallSectionKind just before returning the SectionKind. If true is returned, set the 'isSmallKind' bit in the returned SectionKind. 3. Return the result of the isSmallKind() predicate from isGlobalInSmallSection If the GlobalObject is known to be a definition, the process is even simpler: 1. Pass GlobalObject to TargetLoweringObjectFile::getKindForGlobal (which calls isGlobalInSmallSectionKind in turn). 2. Act on isSmallKind() predicate (and conveniently get the SectionKind at the same time). I feel that the SectionKind modification is the best route, since it's already used to uniquely classify constant merge sections. Even though small data sections are linked in the same manner as their 'regular' counterparts, there must be a clear distinction when producing memory access code (and obviously selecting the target section to allocate in). I'd like some input from PowerPC, MIPS, Hexagon and Lanai maintainers to ensure this approach accommodates their targets appropriately. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161107/8006227b/attachment.html>
Simon Dardis via llvm-dev
2016-Nov-08 17:21 UTC
[llvm-dev] [MC] Target-Independent Small Data Section Handling
Hi Jack, Thanks for working on this, I think you have the right approach by making this more general. I've been looking at your posted patch and I'll post some comments there. Thanks, Simon From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of Jack Andersen via llvm-dev Sent: 08 November 2016 02:48 To: llvm-dev Subject: [llvm-dev] [MC] Target-Independent Small Data Section Handling I've prepared a preliminary patch with the intention of implementing PPC-EABI subtarget features for applications that run in a standalone embedded environment. https://reviews.llvm.org/D26344 The most significant difference compared with the SVR4 ABI is the use of SDA (small data area). This allows full-word constants and data to be grouped into small-data sections accessed using relocated addresses; calculated relative to the non-volatile values loaded into base registers r13 and r2 by the runtime init (similar to gp_rel on MIPS). Only a single load/store instruction is needed to contain the relocated address. The MIPS target already has a solid approach for handling small global variables in its TargetLoweringObjectFile subclass. Also, the clang driver responds to the `-G <bytes>` flag so the user can define a cutoff size other than 8 (or 0 to disable small data altogether). It seems the Hexagon and Lanai targets duplicate much of the IsGlobalInSmallSection handling from the MIPS target, but perform the same basic classification tasks: 1. Pass GlobalObject to target-declared IsGlobalInSmallSection. If it's a declaration, skip to step 4. 2. Pass GlobalObject to target-independent TargetLoweringObjectFile::getKindForGlobal. 3. Ensure the returned SectionKind is Data, BSS or Common. 4. Pass GlobalObject to target-specific IsGlobalInSmallSectionImpl, which scrutinizes the object's type for the specific architecture. I believe this redundant implementation between targets can be reduced by giving SectionKind an 'isSmallKind' bit (OR'd with 0x80). This provides a much clearer (and cached) predicate that ISel lowering can take advantage of when a small data load/store must be generated. The existing predicates in SectionKind may be modified to use the underlying Kind (AND-ing with 0x7f), so existing ISel behaviors are mostly unchanged. The proposed target-independent small data classification has 2 usage avenues depending on the context: For all GlobalObjects: 1. Pass GlobalObject to target-independent TargetLoweringObjectFile::isGlobalInSmallSection. If it's a declaration, make a virtual call to a new method named TargetLoweringObjectFile::isGlobalInSmallSectionKind (doing target-specific scrutiny) and return the result early. 2. Pass to TargetLoweringObjectFile::getKindForGlobal. If the Kind is Data, BSS or Common, make a virtual call to TargetLoweringObjectFile::isGlobalInSmallSectionKind just before returning the SectionKind. If true is returned, set the 'isSmallKind' bit in the returned SectionKind. 3. Return the result of the isSmallKind() predicate from isGlobalInSmallSection If the GlobalObject is known to be a definition, the process is even simpler: 1. Pass GlobalObject to TargetLoweringObjectFile::getKindForGlobal (which calls isGlobalInSmallSectionKind in turn). 2. Act on isSmallKind() predicate (and conveniently get the SectionKind at the same time). I feel that the SectionKind modification is the best route, since it's already used to uniquely classify constant merge sections. Even though small data sections are linked in the same manner as their 'regular' counterparts, there must be a clear distinction when producing memory access code (and obviously selecting the target section to allocate in). I'd like some input from PowerPC, MIPS, Hexagon and Lanai maintainers to ensure this approach accommodates their targets appropriately.
Jack Andersen via llvm-dev
2016-Nov-08 22:33 UTC
[llvm-dev] [MC] Target-Independent Small Data Section Handling
Oh, one thing I forgot to mention: ReadOnly objects are also counted as small data globals on PPC (on top of BSS, Data, Common). That's what the r2 base is for (.sdata2, defined to be constant data). 32-bit immediate loads take 2 ops minimum on PPC, so even constant loading benefits from small data. It'd be handy to add a third argument containing what kind would normally be returned: isGlobalInSmallSectionKind(GO, TM, <nominal-kind-expr>) If a ReadOnly global is better emitted as instruction immediates, then the target can return `false` right then and there.> On Nov 8, 2016, at 07:21, Simon Dardis <Simon.Dardis at imgtec.com> wrote: > > isGlobalInSmallSectionKind
Jack Andersen via llvm-dev
2016-Nov-17 04:39 UTC
[llvm-dev] [MC] Target-Independent Small Data Section Handling
Just pinging this patch for review, particularly from PPC maintainers: https://reviews.llvm.org/D26344 It's now rebased for the latest master commits, `check-all` test results match those of the upstream base. There is also a clang driver patch, extending PPC target support for the `-G` flag: https://reviews.llvm.org/D26345 And lld patch implementing the _SDA_BASE_ symbols and includes an end-to-end test for small data relocations: https://reviews.llvm.org/D26346 I don't have commit access either, so I could use some help with that when ready. Thanks, Jack> On 8 Nov 2016, at 07:21, Simon Dardis <Simon.Dardis at imgtec.com> wrote: > > Hi Jack, > > Thanks for working on this, I think you have the right approach by making this more general. > > I've been looking at your posted patch and I'll post some comments there. > > Thanks, > Simon > > > From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of Jack Andersen via llvm-dev > Sent: 08 November 2016 02:48 > To: llvm-dev > Subject: [llvm-dev] [MC] Target-Independent Small Data Section Handling > > I've prepared a preliminary patch with the intention of implementing PPC-EABI subtarget features for applications that run in a standalone embedded environment. > > https://reviews.llvm.org/D26344 > > The most significant difference compared with the SVR4 ABI is the use of SDA (small data area). This allows full-word constants and data to be grouped into small-data sections accessed using relocated addresses; calculated relative to the non-volatile values loaded into base registers r13 and r2 by the runtime init (similar to gp_rel on MIPS). Only a single load/store instruction is needed to contain the relocated address. > > The MIPS target already has a solid approach for handling small global variables in its TargetLoweringObjectFile subclass. Also, the clang driver responds to the `-G <bytes>` flag so the user can define a cutoff size other than 8 (or 0 to disable small data altogether). > > It seems the Hexagon and Lanai targets duplicate much of the IsGlobalInSmallSection handling from the MIPS target, but perform the same basic classification tasks: > > 1. Pass GlobalObject to target-declared IsGlobalInSmallSection. > If it's a declaration, skip to step 4. > 2. Pass GlobalObject to target-independent > TargetLoweringObjectFile::getKindForGlobal. > 3. Ensure the returned SectionKind is Data, BSS or Common. > 4. Pass GlobalObject to target-specific IsGlobalInSmallSectionImpl, > which scrutinizes the object's type for the specific architecture. > > I believe this redundant implementation between targets can be reduced by giving SectionKind an 'isSmallKind' bit (OR'd with 0x80). This provides a much clearer (and cached) predicate that ISel lowering can take advantage of when a small data load/store must be generated. The existing predicates in SectionKind may be modified to use the underlying Kind (AND-ing with 0x7f), so existing ISel behaviors are mostly unchanged. > > The proposed target-independent small data classification has 2 usage avenues depending on the context: > > For all GlobalObjects: > > 1. Pass GlobalObject to target-independent > TargetLoweringObjectFile::isGlobalInSmallSection. If it's a > declaration, make a virtual call to a new method named > TargetLoweringObjectFile::isGlobalInSmallSectionKind (doing > target-specific scrutiny) and return the result early. > 2. Pass to TargetLoweringObjectFile::getKindForGlobal. > If the Kind is Data, BSS or Common, make a virtual call to > TargetLoweringObjectFile::isGlobalInSmallSectionKind just before > returning the SectionKind. If true is returned, set the 'isSmallKind' > bit in the returned SectionKind. > 3. Return the result of the isSmallKind() predicate from > isGlobalInSmallSection > > If the GlobalObject is known to be a definition, the process is even simpler: > > 1. Pass GlobalObject to TargetLoweringObjectFile::getKindForGlobal > (which calls isGlobalInSmallSectionKind in turn). > 2. Act on isSmallKind() predicate (and conveniently get the > SectionKind at the same time). > > I feel that the SectionKind modification is the best route, since it's already used to uniquely classify constant merge sections. Even though small data sections are linked in the same manner as their 'regular' counterparts, there must be a clear distinction when producing memory access code (and obviously selecting the target section to allocate in). > > I'd like some input from PowerPC, MIPS, Hexagon and Lanai maintainers to ensure this approach accommodates their targets appropriately.