Commit Graph

7375 Commits

Author SHA1 Message Date
Rui Ueyama c1835319c9 Parallelize ICF to make LLD's ICF really fast.
ICF is short for Identical Code Folding. It is a size optimization to
identify two or more functions that happened to have the same contents
to merges them. It usually reduces output size by a few percent.

ICF is slow because it is computationally intensive process. I tried
to paralellize it before but failed because I couldn't make a
parallelized version produce consistent outputs. Although it didn't
create broken executables, every invocation of the linker generated
slightly different output, and I couldn't figure out why.

I think I now understand what was going on, and also came up with a
simple algorithm to fix it. So is this patch.

The result is very exciting. Chromium for example has 780,662 input
sections in which 20,774 are reducible by ICF. LLD previously took
7.980 seconds for ICF. Now it finishes in 1.065 seconds.

As a result, LLD can now link a Chromium binary (output size 1.59 GB)
in 10.28 seconds on my machine with ICF enabled. Compared to gold
which takes 40.94 seconds to do the same thing, this is an amazing
number.

From here, I'll describe what we are doing for ICF, what was the
previous problem, and what I did in this patch.

In ICF, two sections are considered identical if they have the same
section flags, section data, and relocations. Relocations are tricky,
becuase two relocations are considered the same if they have the same
relocation type, values, and if they point to the same section _in
terms of ICF_.

Here is an example. If foo and bar defined below are compiled to the
same machine instructions, ICF can (and should) merge the two,
although their relocations point to each other.

  void foo() { bar(); }
  void bar() { foo(); }

This is not an easy problem to solve.

What we are doing in LLD is some sort of coloring algorithm. We color
non-identical sections using different colors repeatedly, and sections
in the same color when the algorithm terminates are considered
identical. Here is the details:

  1. First, we color all sections using their hash values of section
  types, section contents, and numbers of relocations. At this moment,
  relocation targets are not taken into account. We just color
  sections that apparently differ in different colors.

  2. Next, for each color C, we visit sections having color C to see
  if their relocations are the same. Relocations are considered equal
  if their targets have the same color. We then recolor sections that
  have different relocation targets in new colors.

  3. If we recolor some section in step 2, relocations that were
  previously pointing to the same color targets may now be pointing to
  different colors. Therefore, repeat 2 until a convergence is
  obtained.

Step 2 is a heavy operation. For Chromium, the first iteration of step
2 takes 2.882 seconds, and the second iteration takes 1.038 seconds,
and in total it needs 23 iterations.

Parallelizing step 1 is easy because we can color each section
independently. This patch does that.

Parallelizing step 2 is tricky. We could work on each color
independently, but we cannot recolor sections in place, because it
will break the invariance that two possibly-identical sections must
have the same color at any moment.

Consider sections S1, S2, S3, S4 in the same color C, where S1 and S2
are identical, S3 and S4 are identical, but S2 and S3 are not. Thread
A is about to recolor S1 and S2 in C'. After thread A recolor S1 in
C', but before recolor S2 in C', other thread B might observe S1 and
S2. Then thread B will conclude that S1 and S2 are different, and it
will split thread B's sections into smaller groups wrongly. Over-
splitting doesn't produce broken results, but it loses a chance to
merge some identical sections. That was the cause of indeterminism.

To fix the problem, I made sections have two colors, namely current
color and next color. At the beginning of each iteration, both colors
are the same. Each thread reads from current color and writes to next
color. In this way, we can avoid threads from reading partial
results. After each iteration, we flip current and next.

This is a very simple solution and is implemented in less than 50
lines of code.

I tested this patch with Chromium and confirmed that this parallelized
ICF produces the identical output as the non-parallelized one.

Differential Revision: https://reviews.llvm.org/D27247

llvm-svn: 288373
2016-12-01 17:09:04 +00:00
Sean Silva 2eed75926c Add `isRelExprOneOf` helper
In various places in LLD's hot loops, we have expressions of the form
"E == R_FOO || E == R_BAR || ..." (E is a RelExpr).

Some of these expressions are quite long, and even though they usually go just
a very small number of ways and so should be well predicted, they can still
occupy branch predictor resources harming other parts of the code, or they
won't be predicted well if they overflow branch predictor resources or if the
branches are too dense and the branch predictor can't track them all (the
compiler can in theory avoid this, at a cost in text size). And some of these
expressions are so large and executed so frequently that even when
well-predicted they probably still have a nontrivial cost.

This speedup should be pretty portable. The cost of these simple bit tests is
independent of:

- the target we are linking for
- the distribution of RelExpr's for a given link (which can depend on how the
  input files were compiled)
- what compiler was used to compile LLD (it is just a simple bit test;
  hopefully the compiler gets it right!)
- adding new target-dependent relocations (e.g. needsPlt doesn't pay any extra
  cost checking R_PPC_PLT_OPD on x86-64 builds)

I did some rough measurements on clang-fsds and this patch gives over about 4%
speedup for a regular -O1 link, about 2.5% for -O3 --gc-sections and over 5%
for -O0. Sorry, I don't have my current machine set up for doing really
accurate measurements right now.

This also is just a bit cleaner. Thanks for Joerg for suggesting for
this approach.

Differential Revision: https://reviews.llvm.org/D27156

llvm-svn: 288314
2016-12-01 05:43:48 +00:00
Rui Ueyama 10091b0ac2 Simplify ScriptParser.
- Rename currentBuffer -> getCurrentMB to start it with verb.
 - Simplify containsString.
 - Add llvm_unreachable at end of getCurrentMB.

llvm-svn: 288310
2016-12-01 04:36:54 +00:00
Rui Ueyama 3cd22d3104 Do not name a variable Ret which is not a return value.
llvm-svn: 288309
2016-12-01 04:36:51 +00:00
Rui Ueyama b5f1c3ec0c Make get{Line,Column}Number members of StringParser.
This patch also renames currentLocation getCurrentLocation.

llvm-svn: 288308
2016-12-01 04:36:49 +00:00
Rui Ueyama 50fb82743e Split getPos into getLineNumber and getColumnNumber.
llvm-svn: 288306
2016-12-01 03:56:27 +00:00
Rui Ueyama c5cb737584 Dump Codeview type information correctly.
llvm-svn: 288298
2016-12-01 01:22:48 +00:00
Rui Ueyama 9dedfb1fa8 Change how we manage groups in ICF.
Previously, on each iteration in ICF, we scan the entire vector of
input sections to find boundaries of groups having the same ID.

This patch changes the algorithm so that we now have a vector of ranges.
Each range contains a starting index and an ending index of the group.
So we no longer have to search boundaries on each iteration.

Performance-wise, this seems neutral. Instead of searching boundaries,
we now have to maintain ranges. But I think this is more readable
than the previous implementation.

Moreover, this makes easy to parallelize the main loop of ICF,
which I'll do in a follow-up patch.

llvm-svn: 288228
2016-11-30 01:50:03 +00:00
Rui Ueyama 84e65a7ca1 Use StringRefZ explicitly instead of const char *.
This patch is to avoid an implicit conversion from const char * to
StringRefZ, to make it apparent where we are using StringRefZ.

llvm-svn: 288182
2016-11-29 19:11:39 +00:00
Rui Ueyama a13efc2a73 Introduce StringRefZ class to represent null-terminated strings.
StringRefZ is a class to represent a null-terminated string. String
length is computed lazily, so it's more efficient than StringRef to
represent strings in string table.

The motivation of defining this new class is to merge functions
that only differ in string types; we have many constructors that takes
`const char *` or `StringRef`. With StringRefZ, we can merge them.

Differential Revision: https://reviews.llvm.org/D27037

llvm-svn: 288172
2016-11-29 18:05:04 +00:00
Peter Smith de3e73880e [ELF] Add support for static TLS to ARM
The module index dynamic relocation R_ARM_DTPMOD32 is always 1 for an
executable. When static linking and when we know that we are not a shared
object we can resolve the module index relocation statically.
    
The logic in handleNoRelaxTlsRelocation remains the same for Mips as it
has its own custom GOT writing code. For ARM we add the module index
relocation to the GOT when it can be resolved statically.
    
In addition the type of the RelExpr for the static resolution of TlsGotRel
should be R_TLS and not R_ABS as we need to include the size of
the thread control block in the calculation.
    
Addresses the TLS part of PR30218.

Differential revision: https://reviews.llvm.org/D27213

llvm-svn: 288153
2016-11-29 16:23:50 +00:00
George Rimar 9b3ae73fc8 [ELF] - Disable emiting multiple output sections when merging is disabled.
When -O0 is specified, we do not do section merging.
Though before this patch several sections were generated instead
of single, what is useless.

Differential revision: https://reviews.llvm.org/D27041

llvm-svn: 288151
2016-11-29 16:11:09 +00:00
George Rimar 3fb5a6dc9e [ELF] - Add support of proccessing of the rest allocatable synthetic sections from linkerscript.
This change continues what was started by D27040
Now all allocatable synthetics should be available from script side.

Differential revision: https://reviews.llvm.org/D27131

llvm-svn: 288150
2016-11-29 16:05:27 +00:00
Simon Atanasyan 160bf723f5 [ELF][MIPS] Make stable an order of GOT page address entries
llvm-svn: 288137
2016-11-29 13:26:04 +00:00
Simon Atanasyan 198dd205e6 [ELF][MIPS] Add new check to the test case in attempt to investigate Windows build-bot failure
llvm-svn: 288132
2016-11-29 11:19:47 +00:00
Simon Atanasyan 9705ff74ed [ELF][MIPS] Restore Config->Threads for MIPS targets
llvm-svn: 288130
2016-11-29 10:24:00 +00:00
Simon Atanasyan 9fae3b8a2c [ELF][MIPS] Do not change MipsGotSection state in the getPageEntryOffset method
The MipsGotSection::getPageEntryOffset calculates index of GOT entry
with a "page" address. Previously this method changes the state
of MipsGotSection because it modifies PageIndexMap field. That leads
to the unpredictable results if getPageEntryOffset called from multiple threads.

The patch makes getPageEntryOffset constant. To do so it calculates GOT
entry index but does not update PageIndexMap field. Later in the
MipsGotSection::writeTo method linker calculates "page" addresses and
writes them to the output.

llvm-svn: 288129
2016-11-29 10:23:56 +00:00
Simon Atanasyan a0efc4268c [ELF][MIPS] Replace the magic number of GOT header entries by constant. NFC
llvm-svn: 288128
2016-11-29 10:23:50 +00:00
Simon Atanasyan 80f3d9ce93 [ELF][MIPS] Fix calculation of GOT "page address" entries number
If output section which referenced by R_MIPS_GOT_PAGE or R_MIPS_GOT16
relocations is small (less that 0x10000 bytes) and occupies two adjacent
0xffff-bytes pages, current formula gives incorrect number of required "page"
GOT entries. The problem is that in time of calculation we do not know
the section address and so we cannot calculate number of 0xffff-bytes
pages exactly.

This patch fix the formula. Now it gives a correct number of pages in
the worst case when "small" section intersects 0xffff-bytes page
boundary. From the other side, sometimes it adds one more redundant GOT
entry for each output section. But usually number of output sections
referenced by GOT relocations is small.

llvm-svn: 288127
2016-11-29 10:23:46 +00:00
George Rimar 595a763f38 [ELF] - Implemented -N (-omagic) command line option.
-N (-omagic)
  Set the text and data sections to be readable and writable. 
  Also, do not page-align the data segment.

Differential revision: https://reviews.llvm.org/D26888

llvm-svn: 288123
2016-11-29 09:43:51 +00:00
Eugene Leviant 84569e6caa [ELF] Refactor target error messages
Differential revision: https://reviews.llvm.org/D27097

llvm-svn: 288114
2016-11-29 08:05:44 +00:00
Rui Ueyama bf4ddeb97c Style fix.
llvm-svn: 288113
2016-11-29 04:22:57 +00:00
Rui Ueyama c910bc7e19 Simplify "missing argument" error message.
llvm-svn: 288112
2016-11-29 04:17:31 +00:00
Rui Ueyama e5e407beb4 Add comments.
llvm-svn: 288111
2016-11-29 04:17:30 +00:00
Rui Ueyama bd2a812ff0 Print error message header in red.
llvm-svn: 288110
2016-11-29 04:09:08 +00:00
Rafael Espindola f1e245315b Use relocations to fill statically known got entries.
Right now we just remember a SymbolBody for each got entry and
duplicate a bit of logic to decide what value, if any, should be
written for that SymbolBody.

With ARM there will be more complicated values, and it seems better to
just use the relocation code to fill the got entries. This makes it
clear that each entry is filled by the dynamic linker or by the static
linker.

llvm-svn: 288107
2016-11-29 03:45:36 +00:00
Rafael Espindola d3b32df3de Sort. NFC.
llvm-svn: 288102
2016-11-29 03:36:30 +00:00
Rafael Espindola 5498ba38df Add a test.
It would have found a missing case in another patch.

llvm-svn: 288101
2016-11-29 03:30:07 +00:00
George Rimar 1642c5d871 [ELF] - Do not put non exec sections first when -no-rosegment
That unifies handling cases when we have SECTIONS and when
-no-rosegment is given in compareSectionsNonScript()

Now Config->SingleRoRx is used for check, testcase is provided.

llvm-svn: 288022
2016-11-28 10:26:21 +00:00
George Rimar 18a3096282 [ELF] - Set Config->SingleRoRx differently. NFC.
Previously Config->SingleRoRx was set in
createFiles() and used HasSections.

This change moves it to readConfigs at place of
common flags handling, and adds logic that sets
this flag separatelly from ScriptParser if SECTIONS present.

llvm-svn: 288021
2016-11-28 10:11:10 +00:00
George Rimar 63bf011003 [ELF] - Implemented -no-rosegment.
--no-rosegment: Do not put read-only non-executable sections in their own segment

Differential revision: https://reviews.llvm.org/D26889

llvm-svn: 288020
2016-11-28 10:05:20 +00:00
Eugene Leviant ed30ce7ae4 [ELF] Print file:line for 'undefined section' errors
Differential revision: https://reviews.llvm.org/D27108

llvm-svn: 288019
2016-11-28 09:58:04 +00:00
Rafael Espindola 8e67000f1a Always create a PT_ARM_EXIDX if needed.
Unfortunatelly PT_ARM_EXIDX is special. There is no way to create it
from linker scripts, so we have to create it even if PHDRS is used.

This matches bfd and is required for the lld output to survive bfd's strip.

llvm-svn: 288012
2016-11-28 00:40:21 +00:00
Rui Ueyama 1dd86a664f Add paralell_for and use it where appropriate.
When we iterate over numbers as opposed to iterable elements,
parallel_for fits better than parallel_for_each.

llvm-svn: 288002
2016-11-27 19:28:32 +00:00
Rafael Espindola 5fcc99c27d Also skip regular symbol assignment at the start of a script.
Unfortunatelly some scripts look like

kernphys = ...
. = ....

and the expectation in that every orphan section is after the
assignment.

llvm-svn: 287996
2016-11-27 09:44:45 +00:00
Rafael Espindola 7fe4ec9b3a Don't put an orphan before the first . assignment.
This is an horrible special case, but seems to match bfd's behaviour
and is important for avoiding placing an orphan section before the
expected start of the file.

llvm-svn: 287994
2016-11-27 07:39:45 +00:00
Rui Ueyama e8a077badf Change return types of split{Non,}Strings.
They return new vectors, but at the same time they mutate other vectors,
so returning values doesn't make much sense. We should just mutate two
vectors.

llvm-svn: 287979
2016-11-26 15:15:11 +00:00
Rui Ueyama 72b1ee2533 Make getColorDiagnostics return a boolean value instead of an enum.
Config->ColorDiagnostics was of type enum before. Now it is just a
boolean flag. Thanks Rafael for suggestion.

llvm-svn: 287978
2016-11-26 15:10:01 +00:00
Rui Ueyama 1880bbed39 Split MergeOutputSection::finalize.
llvm-svn: 287977
2016-11-26 15:09:58 +00:00
Rafael Espindola f93b8c29c8 Create sections with just assignments as STT_NOBITS.
This matches the behaviour of bfd ld. Using 0 was causing problems
with strip, which would remove these sections.

llvm-svn: 287969
2016-11-26 06:55:35 +00:00
Davide Italiano 3bfa081aa9 [ELF] Be compliant with LLVM and rename Lto into LTO. NFCI.
llvm-svn: 287967
2016-11-26 05:37:04 +00:00
Rui Ueyama d873e3a694 Fix buildbots.
llvm-svn: 287952
2016-11-25 20:42:39 +00:00
Rui Ueyama 1df9316922 Fix typo.
llvm-svn: 287951
2016-11-25 20:41:45 +00:00
Rui Ueyama c01321c6b8 Do not print out ARGV0 in white because it's unreadable on white background.
llvm-svn: 287950
2016-11-25 20:37:16 +00:00
Rui Ueyama 8c8818a58c Support -color-diagnostics={auto,always,never}.
-color-diagnostics=auto is default because that's the same as
Clang's default. When color is enabled, error or warning messages
are colored like this.

  error:
  <bold>ld.lld</bold> <red>error:</red> foo.o: no such file

  warning:
  <bold>ld.lld</bold> <magenta>warning:</magenta> foo.o: no such file

Differential Revision: https://reviews.llvm.org/D27117

llvm-svn: 287949
2016-11-25 20:27:32 +00:00
Rui Ueyama 6066641423 We shouldn't call parallle_for_each if -no-thread is given.
llvm-svn: 287948
2016-11-25 20:20:57 +00:00
Rui Ueyama 2555952ba8 Parallelize uncompress() and splitIntoPieces().
Uncompressing section contents and spliting mergeable section contents
into smaller chunks are heavy tasks. They scan entire section contents
and do CPU-intensive tasks such as uncompressing zlib-compressed data
or computing a hash value for each section piece.

Luckily, these tasks are independent to each other, so we can do that
in parallel_for_each. The number of input sections is large (as opposed
to the number of output sections), so there's a large parallelism here.

Actually the current design to call uncompress() and splitIntoPieces()
in batch was chosen with doing this in mind. Basically what we need to
do here is to replace `for` with `parallel_for_each`.

It seems this patch improves latency significantly if linked programs
contain debug info (which in turn contain lots of mergeable strings.)
For example, the latency to link Clang (debug build) improved by 20% on
my machine as shown below. Note that ld.gold took 19.2 seconds to do
the same thing.

Before:
    30801.782712 task-clock (msec)         #    3.652 CPUs utilized            ( +-  2.59% )
         104,084 context-switches          #    0.003 M/sec                    ( +-  1.02% )
           5,063 cpu-migrations            #    0.164 K/sec                    ( +- 13.66% )
       2,528,130 page-faults               #    0.082 M/sec                    ( +-  0.47% )
  85,317,809,130 cycles                    #    2.770 GHz                      ( +-  2.62% )
  67,352,463,373 stalled-cycles-frontend   #   78.94% frontend cycles idle     ( +-  3.06% )
 <not supported> stalled-cycles-backend
  44,295,945,493 instructions              #    0.52  insns per cycle
                                           #    1.52  stalled cycles per insn  ( +-  0.44% )
   8,572,384,877 branches                  #  278.308 M/sec                    ( +-  0.66% )
     141,806,726 branch-misses             #    1.65% of all branches          ( +-  0.13% )

     8.433424003 seconds time elapsed                                          ( +-  1.20% )

After:
    35523.764575 task-clock (msec)         #    5.265 CPUs utilized            ( +-  2.67% )
         159,107 context-switches          #    0.004 M/sec                    ( +-  0.48% )
           8,123 cpu-migrations            #    0.229 K/sec                    ( +- 23.34% )
       2,372,483 page-faults               #    0.067 M/sec                    ( +-  0.36% )
  98,395,342,152 cycles                    #    2.770 GHz                      ( +-  2.62% )
  79,294,670,125 stalled-cycles-frontend   #   80.59% frontend cycles idle     ( +-  3.03% )
 <not supported> stalled-cycles-backend
  46,274,151,813 instructions              #    0.47  insns per cycle
                                           #    1.71  stalled cycles per insn  ( +-  0.47% )
   8,987,621,670 branches                  #  253.003 M/sec                    ( +-  0.60% )
     148,900,624 branch-misses             #    1.66% of all branches          ( +-  0.27% )

     6.747548004 seconds time elapsed                                          ( +-  0.40% )

llvm-svn: 287946
2016-11-25 20:05:08 +00:00
Rui Ueyama 623b36e358 Move typedefs inside a class definition.
llvm-svn: 287945
2016-11-25 18:51:56 +00:00
Rui Ueyama 22375f2406 Remove a parameter from ScriptParser.
llvm-svn: 287944
2016-11-25 18:51:54 +00:00
Rui Ueyama da06bfb794 Move getLocation from Relocations.cpp to InputSection.cpp.
The function was used only within Relocations.cpp, but now we are
using it in many places, so this patch moves it to a file that fits
to the functionality.

llvm-svn: 287943
2016-11-25 18:51:53 +00:00