Skip to content
  1. Dec 02, 2016
    • Rui Ueyama's avatar
      Fix undefined behavior. · 395859bd
      Rui Ueyama authored
      New items can be added to Ranges here, and that invalidates
      an iterater that previously pointed the end of the vector.
      
      llvm-svn: 288443
      395859bd
  2. Dec 01, 2016
    • Rui Ueyama's avatar
      Add an assert instead of ignoring an impossible condition. · a6cd5fe4
      Rui Ueyama authored
      llvm-svn: 288419
      a6cd5fe4
    • Rui Ueyama's avatar
      Updates file comments and variable names. · 91ae861a
      Rui Ueyama authored
      Use "color" instead of "group id" to describe the ICF algorithm.
      
      llvm-svn: 288409
      91ae861a
    • Rui Ueyama's avatar
      Parallelize ICF to make LLD's ICF really fast. · c1835319
      Rui Ueyama authored
      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
      c1835319
    • Sean Silva's avatar
      Add `isRelExprOneOf` helper · 2eed7592
      Sean Silva authored
      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
      2eed7592
    • Rui Ueyama's avatar
      Simplify ScriptParser. · 10091b0a
      Rui Ueyama authored
       - Rename currentBuffer -> getCurrentMB to start it with verb.
       - Simplify containsString.
       - Add llvm_unreachable at end of getCurrentMB.
      
      llvm-svn: 288310
      10091b0a
    • Rui Ueyama's avatar
      Do not name a variable Ret which is not a return value. · 3cd22d31
      Rui Ueyama authored
      llvm-svn: 288309
      3cd22d31
    • Rui Ueyama's avatar
      Make get{Line,Column}Number members of StringParser. · b5f1c3ec
      Rui Ueyama authored
      This patch also renames currentLocation getCurrentLocation.
      
      llvm-svn: 288308
      b5f1c3ec
    • Rui Ueyama's avatar
      Split getPos into getLineNumber and getColumnNumber. · 50fb8274
      Rui Ueyama authored
      llvm-svn: 288306
      50fb8274
  3. Nov 30, 2016
    • Rui Ueyama's avatar
      Change how we manage groups in ICF. · 9dedfb1f
      Rui Ueyama authored
      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
      9dedfb1f
  4. Nov 29, 2016
  5. Nov 28, 2016
  6. Nov 27, 2016
  7. Nov 26, 2016
  8. Nov 25, 2016
Loading