[PATCH] D77694: [WIP][RISCV][ELF] Linker relaxation support

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 7 18:32:40 PDT 2020


MaskRay added a comment.

Interestingly, I was thinking about the same thing on Saturday!  I wanted to
add `optimizeBasicBlockJumps()` in a proper place (D68065 <https://reviews.llvm.org/D68065>; basic block
sections; ok, they got impatient and committed it anyway).  The current place
is wrong for a thunk target (e.g. AArch64). I did not write code because I am
still unsure how to properly do linker relaxations.

Title: It should mention R_RISCV_ALIGN.

I believe the current framework can only handle the BFD counterpart of
relax_pass==2 (_bfd_riscv_relax_align). Other instruction rewriting may require
intertwined scanRelocations and finalizeAddressDependentContent. The relocation
scanning pass may have to be split, but I don't know whether the boundary is.

It has occurred to me that splitting the relocation scanning pass may be good for

- copy relocations and canonical PLT entries
- non-preemptible IFUNC
- .plt.got (https://bugs.llvm.org/show_bug.cgi?id=32938)
- RISC-V linker relaxations

The above is basically limitation of a linker with one-pass relocation scanning. To have a complete support we may have to bite the bullet. More bookkeeping may
be needed. InputSectionBase::relocations will not be sufficient.
finalizeSynthetic() may be called more than once.

An incomplete list of passes we do after `scanRelocations`:

  forEachRelSec(scanRelocations<ELFT>);
  add symbols to in.symTab and partitions[*].dynSymTab
  removeUnusedSyntheticSections()
  sortSections()
  finalizeSynthetic(in.*)
  fixSectionAlignments()
  finalizeAddressDependentContext // 
  finalizeSynthetic(in.symTab)
  finalizeSynthetic(in.ppc64LongBranchTarget) // conceptually it should be done after thunks are finalized

We need to move scanRelocations() as late as possible and move some passes (including finalizeSynthetic()) into finalizeAddressDependentContent(). These passes need to refactored to work if called more than once.

The finalizeAddressDependentContent() should be changed to several rounds of iterations (relax_pass). The last round handles `R_RISCV_ALIGN`.

A bit off-topic. For RISC-V's (ab)use of linker relaxations, my feeling is still complex. It is indeed a very convenient approach toward a good balance of code size/speed/convenience, but if we want to achieve more, some post-link time optimization frameworks may be more suitable. I don't really have enough experience with link time optimization but my understanding is that we currently use the term link time optimization (especially in the LLVM context) for optimizations performed on the LLVM IR level. Those low-level machine representations are not categorized as LTO.



================
Comment at: lld/ELF/Arch/RISCV.cpp:551
+  }
+  isec->relocations.resize(dest - brel);
+
----------------
llvm::erase_if


================
Comment at: lld/ELF/Writer.cpp:1674
+  // code to increase in size and potentially invalidate some relaxations.
+  for (int pass : target->relaxPasses) {
+    assignPasses = 0;
----------------
This loop should be merged with the previous for loop.


================
Comment at: lld/ELF/Writer.cpp:1679
+      for (OutputSection *osec : outputSections)
+        for (InputSection *isec : getInputSections(osec))
+          changed |= target->relaxSection(isec, pass);
----------------
Check `SHF_EXECINSTR`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77694/new/

https://reviews.llvm.org/D77694





More information about the llvm-commits mailing list