[llvm-dev] [MC] Target-Independent Small Data Section Handling

Jack Andersen via llvm-dev llvm-dev at lists.llvm.org
Mon Nov 7 18:48:00 PST 2016


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>


More information about the llvm-dev mailing list