[PATCH] D125036: [RISCV] Alignment relaxation

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu May 19 20:04:43 PDT 2022


MaskRay added a comment.

On lld/ELF/Relocations.cpp:1439, R_RELAX_HINT should not trigger `sym.hasDirectReloc = true;`, otherwise an ifunc may unnecessarily be converted to a canonical PLT. You may read `*-ifunc-nonpreemptible*.s` tests for what they do. I have some notes on https://maskray.me/blog/2021-01-18-gnu-indirect-function#address-significance



================
Comment at: lld/ELF/Arch/RISCV.cpp:40
                 uint64_t val) const override;
+  void finalizeSections() const override;
 };
----------------
The name is unnecessarily the same as `Writer::finalizeSections`. `relaxSections` may be a better name.


================
Comment at: lld/ELF/Arch/RISCV.cpp:488
+constexpr int alignNopBytesWidth = 16;
+constexpr int alignNopBytesMask = ((1 << alignNopBytesWidth) - 1);
+
----------------



================
Comment at: lld/ELF/Arch/RISCV.cpp:520
+  r.addend = (r.addend & ~alignNopBytesMask) | newNopBytes;
+  int incr = newNopBytes - oldNopBytes;
+  if (incr) {
----------------



================
Comment at: lld/ELF/Arch/RISCV.cpp:522
+  if (incr) {
+    adjustRanges.push_back({r.offset, incr});
+    delta += incr;
----------------
emplace_back


================
Comment at: lld/ELF/Arch/RISCV.cpp:573
+
+      AdjustRanges adjustRanges;
+      int64_t delta = 0;
----------------
The variable and the member function have the same name. Rename the variable to `ranges`?

Move it outside the outer loop and use a `ranges.clear()` here. Try avoiding constructing/destructing a vector in a loop.


================
Comment at: lld/ELF/Arch/RISCV.cpp:576
+      for (Relocation &r : isec->relocations)
+        if (r.type == R_RISCV_ALIGN && r.addend)
+          relaxAlign(isec, r, delta, adjustRanges);
----------------
r.addend is guaranteed to be non-zero


================
Comment at: lld/ELF/Arch/RISCV.cpp:591
+void RISCV::finalizeSections() const {
+  // Can't perform relaxation if it is not a final link.
+  if (config->relocatable)
----------------
Don't perform relaxation for a relocatable link.


================
Comment at: lld/ELF/InputSection.cpp:156
+// we can inspect and adjust individually.
+class SymbolAddr {
+public:
----------------
struct


================
Comment at: lld/ELF/InputSection.cpp:188
+  SmallVector<SymbolAddr, 0> symbolAddrs;
+  for (Symbol *sym : file->getSymbols())
+    if (Defined *d = dyn_cast<Defined>(sym))
----------------
If a file compiled with -ffunction-sections has N text sections/function symbols, this takes O(N^2). I think we should build a map to decrease the time complexity. You can add a map to `InputFile`. It's unfortunate to increase the size of `InputFile` which it is acceptable.


================
Comment at: lld/ELF/InputSection.cpp:191
+      if (d->section == this) {
+        symbolAddrs.push_back({d->value, d});
+        symbolAddrs.push_back({d->value + d->size, d});
----------------
emplace_back


================
Comment at: lld/ELF/InputSection.cpp:194
+      }
+  llvm::sort(symbolAddrs, [](const SymbolAddr &a, const SymbolAddr &b) {
+    return a.offset < b.offset;
----------------
stable_sort

Two symbols may be defined at the same offset. 


================
Comment at: lld/ELF/InputSection.cpp:223
+  const auto *ar = ranges.begin();
+  for (auto &r : relocations) {
+    for (; ar != ranges.end() && ar->offset < r.offset; ++ar)
----------------



================
Comment at: lld/ELF/InputSection.cpp:238
+    size_t length = srcN - src0;
+    if (dest < src0)
+      std::copy_backward(src0, srcN, dest + length);
----------------
The condition isn't correct. It may trigger the undefined behavior src0 < dest+length < srcN.

---

We should avoid `std::copy` when

> The behavior is undefined if d_first is within the range [first, last)

Otherwise we should use `std::copy`.

---

I am not sure the code works with adding bytes. In that case we need to get the NOP pattern.


================
Comment at: lld/ELF/InputSection.h:170
 
+  MutableArrayRef<uint8_t> mutableData() const {
+    if (!copiedData) {
----------------
Then remove `mutable` from `copiedData`


================
Comment at: lld/ELF/InputSection.h:172
+    if (!copiedData) {
+      size_t size = data().size();
+      uint8_t *mutData = context().bAlloc.Allocate<uint8_t>(size);
----------------



================
Comment at: lld/test/ELF/riscv-relax-align-rvc.s:38
+  c.add a0, a1
+.balign 16
+  c.add s0, s1
----------------
The test needs many `.balign {8,16}` directives to test `InputSectionBase::adjustRanges`.

The current `InputSectionBase::adjustRanges` is flawed but the tests aren't able to detect that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125036



More information about the llvm-commits mailing list