[lld] [RISCV][LLD] Add RISCV zcmt optimise in linker relaxation (PR #77884)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 25 05:23:13 PST 2024


https://github.com/Xinlong-Wu updated https://github.com/llvm/llvm-project/pull/77884

>From 4846c450db20deea44be33e3dc0ea12ea06f59a4 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 20 Sep 2022 13:06:25 +0800
Subject: [PATCH 01/46] Add tablejump support in lld linker relaxation

---
 lld/ELF/Arch/RISCV.cpp           |  62 +++++++++++++--
 lld/ELF/Config.h                 |   1 +
 lld/ELF/Driver.cpp               |   1 +
 lld/ELF/Options.td               |   3 +
 lld/ELF/SyntheticSections.cpp    | 132 +++++++++++++++++++++++++++++++
 lld/ELF/SyntheticSections.h      |  46 +++++++++++
 lld/ELF/Target.h                 |   2 +
 lld/ELF/Writer.cpp               |  24 +++++-
 lld/test/ELF/riscv-tbljal-call.s |  93 ++++++++++++++++++++++
 lld/test/ELF/riscv-tbljal-syms.s |  32 ++++++++
 10 files changed, 389 insertions(+), 7 deletions(-)
 create mode 100644 lld/test/ELF/riscv-tbljal-call.s
 create mode 100644 lld/test/ELF/riscv-tbljal-syms.s

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index a556d89c36400d3..e543ff3f4125f4b 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -38,6 +38,8 @@ class RISCV final : public TargetInfo {
   void writePltHeader(uint8_t *buf) const override;
   void writePlt(uint8_t *buf, const Symbol &sym,
                 uint64_t pltEntryAddr) const override;
+  void writeTableJumpHeader(uint8_t *buf) const override;
+  void writeTableJump(uint8_t *buf, const uint64_t symbol) const override;
   RelType getDynRel(RelType type) const override;
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
@@ -87,6 +89,9 @@ static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
 static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
   return op | (rd << 7) | (imm << 12);
 }
+static uint16_t tbljumptype(uint8_t imm) {
+  return 0b10 | (imm << 2) | (0b101 << 13);
+}
 
 // Extract bits v[begin:end], where range is inclusive, and begin must be < 63.
 static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
@@ -246,6 +251,20 @@ void RISCV::writePlt(uint8_t *buf, const Symbol &sym,
   write32le(buf + 12, itype(ADDI, 0, 0, 0));
 }
 
+void RISCV::writeTableJumpHeader(uint8_t *buf) const {
+  if (config->is64)
+    write64le(buf, mainPart->dynamic->getVA());
+  else
+    write32le(buf, mainPart->dynamic->getVA());
+}
+
+void RISCV::writeTableJump(uint8_t *buf, const uint64_t address) const {
+  if (config->is64)
+    write64le(buf, address);
+  else
+    write32le(buf, address);
+}
+
 RelType RISCV::getDynRel(RelType type) const {
   return type == target->symbolicRel ? type
                                      : static_cast<RelType>(R_RISCV_NONE);
@@ -342,6 +361,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_RVC_JUMP: {
+    if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
+      return;
+
     checkInt(loc, val, 12, rel);
     checkAlignment(loc, val, 2, rel);
     uint16_t insn = read16le(loc) & 0xE003;
@@ -608,10 +630,25 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
     sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
     sec.relaxAux->writes.push_back(0x2001); // c.jal
     remove = 6;
-  } else if (isInt<21>(displace)) {
-    sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
-    sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
-    remove = 4;
+  } else {
+    if (isInt<21>(displace)) {
+      sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+      sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
+      remove = 4;
+    }
+
+    int tblEntryIndex = -1;
+    if (config->zce_tbljal) {
+      if (rd == 0)
+        tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+      else if (rd == X_RA)
+        tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+
+      if (tblEntryIndex >= 0) {
+        sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
+        remove = 6;
+      }
+    }
   }
 }
 
@@ -830,10 +867,23 @@ void elf::riscvFinalizeRelax(int passes) {
           case R_RISCV_RELAX:
             // Used by relaxTlsLe to indicate the relocation is ignored.
             break;
-          case R_RISCV_RVC_JUMP:
+          case R_RISCV_RVC_JUMP: {
+            const uint32_t rd =
+                extractBits(read32le(old.data() + r.offset + 4), 11, 7);
+            int tblEntryIndex = -1;
+            if (config->zce_tbljal && rd == 0)
+              tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+            else if (config->zce_tbljal && rd == X_RA)
+              tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+
             skip = 2;
-            write16le(p, aux.writes[writesIdx++]);
+            if (config->zce_tbljal && tblEntryIndex >= 0) {
+              write16le(p, tbljumptype(tblEntryIndex));
+            } else {
+              write16le(p, aux.writes[writesIdx++]);
+            }
             break;
+          }
           case R_RISCV_JAL:
             skip = 4;
             write32le(p, aux.writes[writesIdx++]);
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 56229334f9a44ae..0d456cbde458015 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -301,6 +301,7 @@ struct Config {
   bool writeAddends;
   bool zCombreloc;
   bool zCopyreloc;
+  bool zce_tbljal;
   bool zForceBti;
   bool zForceIbt;
   bool zGlobal;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 6290880c43d3b95..c98e42efd770fdd 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,6 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->whyExtract = args.getLastArgValue(OPT_why_extract);
   config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
   config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
+  config->zce_tbljal = args.hasArg(OPT_zce_tbljal);
   config->zForceBti = hasZOption(args, "force-bti");
   config->zForceIbt = hasZOption(args, "force-ibt");
   config->zGlobal = hasZOption(args, "global");
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index c2c9cabc92a4da4..0ec8157cbe2e8ff 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,6 +340,9 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
     "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
     "Use SHT_RELR / DT_RELR* tags (default)">;
 
+def zce_tbljal: F<"zce-tbljal">,
+  HelpText<"(RISCV only) Enable table jump instructions from the Zce extension">;
+
 def pic_veneer: F<"pic-veneer">,
   HelpText<"Always generate position independent thunks (veneers)">;
 
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2b32eb3a0fe3558..01c4580f8489a66 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1171,6 +1171,138 @@ bool GotPltSection::isNeeded() const {
   return !entries.empty() || hasGotPltOffRel;
 }
 
+TableJumpSection::TableJumpSection()
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_RISCV_ATTRIBUTES,
+                       config->wordsize, ".tbljalentries") {}
+
+void TableJumpSection::addEntryZero(const Symbol &symbol) {
+  addEntry(symbol, entriesZero);
+}
+
+int TableJumpSection::getEntryZero(const Symbol &symbol) {
+  uint32_t index = getEntry(symbol, finalizedEntriesZero);
+  return index < maxSizeZero ? (int)(startZero + index) : -1;
+}
+
+void TableJumpSection::addEntryRa(const Symbol &symbol) {
+  addEntry(symbol, entriesRa);
+}
+
+int TableJumpSection::getEntryRa(const Symbol &symbol) {
+  uint32_t index = getEntry(symbol, finalizedEntriesRa);
+  return index < maxSizeRa ? (int)(startRa + index) : -1;
+}
+
+void TableJumpSection::addEntry(const Symbol &symbol,
+                                std::map<std::string, int> &entriesList) {
+  if (entriesList.count(symbol.getName().str()) == 0) {
+    entriesList[symbol.getName().str()] = 1;
+  } else {
+    entriesList[symbol.getName().str()] += 1;
+  }
+}
+
+uint32_t TableJumpSection::getEntry(
+    const Symbol &symbol,
+    std::vector<std::pair<std::string, int>> &entriesList) {
+  // Prevent adding duplicate entries
+  uint32_t i = 0;
+  for (; i < entriesList.size(); ++i) {
+    // If this is a duplicate addition, do not add it and return the address
+    // offset of the original entry.
+    if (symbol.getName().compare(entriesList[i].first) == 0) {
+      return i;
+    }
+  }
+  return i;
+}
+
+void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
+  for (auto [i, r] : llvm::enumerate(sec.relocations)) {
+    switch (r.type) {
+    // auipc + jalr pair
+    case R_RISCV_CALL:
+    case R_RISCV_CALL_PLT: {
+      const auto jalr = sec.data()[r.offset + 4];
+      const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
+      if (rd == 0)
+        in.riscvTableJumpSection->addEntryZero(*r.sym);
+      else if (rd == 1)
+        in.riscvTableJumpSection->addEntryRa(*r.sym);
+      else
+        return; // Unknown link register, do not modify.
+    }
+    }
+  }
+}
+
+void TableJumpSection::finalizeContents() {
+  auto cmp = [](const std::pair<std::string, int> &p1,
+                const std::pair<std::string, int> &p2) {
+    return p1.second > p2.second;
+  };
+
+  std::copy(entriesZero.begin(), entriesZero.end(),
+            std::back_inserter(finalizedEntriesZero));
+  std::sort(finalizedEntriesZero.begin(), finalizedEntriesZero.end(), cmp);
+  std::copy(entriesRa.begin(), entriesRa.end(),
+            std::back_inserter(finalizedEntriesRa));
+  std::sort(finalizedEntriesRa.begin(), finalizedEntriesRa.end(), cmp);
+}
+
+size_t TableJumpSection::getSize() const {
+  if (size == 0)
+    return 256 * xlen; // TODO: This is the maximum size shrink this. This is
+                       // being caused by getSize being called to allocate space
+                       // for the section before the tbljal optimisation is
+                       // performed to add entries to the table.
+  if (!entriesRa.empty()) {
+    return (startRa + entriesRa.size()) * xlen;
+  }
+  return (startZero + entriesZero.size()) * xlen;
+}
+
+void TableJumpSection::writeTo(uint8_t *buf) {
+  target->writeTableJumpHeader(buf);
+  writeEntries(buf + startZero, finalizedEntriesZero);
+  padUntil(buf + ((startZero + finalizedEntriesZero.size()) * xlen),
+           startRa * xlen);
+  writeEntries(buf + startRa, finalizedEntriesRa);
+}
+
+void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
+  for (size_t i = 0; i < address; ++i) {
+    if (config->is64)
+      write64le(buf, 0);
+    else
+      write32le(buf, 0);
+  }
+}
+
+void TableJumpSection::writeEntries(
+    uint8_t *buf, std::vector<std::pair<std::string, int>> &entriesList) {
+  for (const auto &symbolName : entriesList) {
+    // Use the symbol from in.symTab to ensure we have the final adjusted
+    // symbol.
+    for (const auto &symbol : in.symTab->getSymbols()) {
+      if (symbol.sym->getName() != symbolName.first)
+        continue;
+      // Only process defined symbols.
+      auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+      if (!definedSymbol)
+        continue;
+      target->writeTableJump(buf, definedSymbol->getVA());
+      buf += config->wordsize;
+    }
+  }
+}
+
+bool TableJumpSection::isNeeded() const {
+  // TODO: Make this function correctly. Currently discards section with
+  // entries.
+  return getSize() != 0;
+}
+
 static StringRef getIgotPltName() {
   // On ARM the IgotPltSection is part of the GotSection.
   if (config->emachine == EM_ARM)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 3a9f4ba886f6bbb..f6d4739a60adfb6 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -31,6 +31,7 @@
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/Threading.h"
+#include <map>
 
 namespace lld::elf {
 class Defined;
@@ -368,6 +369,50 @@ class GotPltSection final : public SyntheticSection {
   SmallVector<const Symbol *, 0> entries;
 };
 
+class TableJumpSection final : public SyntheticSection {
+public:
+  TableJumpSection();
+  size_t getSize() const override;
+  void writeTo(uint8_t *buf) override;
+  bool isNeeded() const override;
+  void finalizeContents() override;
+
+  void addEntryZero(const Symbol &symbol);
+  int getEntryZero(const Symbol &symbol);
+  void addEntryRa(const Symbol &symbol);
+  int getEntryRa(const Symbol &symbol);
+  void scanTableJumpEntrys(const InputSection &sec) const;
+
+  // Flag to force TableJump to be in output if we have relocations
+  // that relies on its address.
+  bool hasTableJumpOffRel = false;
+
+protected:
+  uint64_t size = 0;
+
+private:
+  void addEntry(const Symbol &symbol, std::map<std::string, int> &entriesList);
+  uint32_t getEntry(const Symbol &symbol,
+                    std::vector<std::pair<std::string, int>> &entriesList);
+  void writeEntries(uint8_t *buf,
+                    std::vector<std::pair<std::string, int>> &entriesList);
+  void padUntil(uint8_t *buf, const uint8_t index);
+
+  const size_t xlen = config->is64 ? 64 : 32;
+
+  std::map<std::string, int> entriesZero;
+  std::vector<std::pair<std::string, int>> finalizedEntriesZero;
+  std::map<std::string, int> entriesRa;
+  std::vector<std::pair<std::string, int>> finalizedEntriesRa;
+
+  // TODO: Make use of these in cost function.
+  const size_t maxSizeZero = 64;
+  const size_t maxSizeRa = 192;
+
+  const size_t startZero = 0;
+  const size_t startRa = 64;
+};
+
 // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
 // Symbols that will be relocated by Target->IRelativeRel.
 // On most Targets the IgotPltSection will immediately follow the GotPltSection
@@ -1346,6 +1391,7 @@ struct InStruct {
   std::unique_ptr<RelroPaddingSection> relroPadding;
   std::unique_ptr<SyntheticSection> armCmseSGSection;
   std::unique_ptr<PPC64LongBranchTargetSection> ppc64LongBranchTarget;
+  std::unique_ptr<TableJumpSection> riscvTableJumpSection;
   std::unique_ptr<SyntheticSection> mipsAbiFlags;
   std::unique_ptr<MipsGotSection> mipsGot;
   std::unique_ptr<SyntheticSection> mipsOptions;
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 6264ab1a3da74a7..d34fc73e7914496 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -36,6 +36,8 @@ class TargetInfo {
   virtual void writeGotPltHeader(uint8_t *buf) const {}
   virtual void writeGotHeader(uint8_t *buf) const {}
   virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
+  virtual void writeTableJumpHeader(uint8_t *buf) const {};
+  virtual void writeTableJump(uint8_t *buf, const uint64_t symbol) const {};
   virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
   virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
   virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index a84e4864ab0e5a5..2cd0a9f181fa542 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,6 +502,15 @@ template <class ELFT> void elf::createSyntheticSections() {
     add(*in.ppc64LongBranchTarget);
   }
 
+  if (config->emachine == EM_RISCV && config->zce_tbljal) {
+    in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
+    add(*in.riscvTableJumpSection);
+
+    symtab->addSymbol(Defined{
+        /*file=*/nullptr, ".tbljalentries", STB_WEAK, STT_NOTYPE, STT_NOTYPE,
+        /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
+  }
+
   in.gotPlt = std::make_unique<GotPltSection>();
   add(*in.gotPlt);
   in.igotPlt = std::make_unique<IgotPltSection>();
@@ -1692,6 +1701,15 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   if (config->emachine == EM_HEXAGON)
     hexagonTLSSymbolUpdate(outputSections);
 
+  // scan all R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
+  if (in.riscvTableJumpSection) {
+    for (InputSectionBase *inputSection : inputSections) {
+      in.riscvTableJumpSection->scanTableJumpEntrys(
+          cast<InputSection>(*inputSection));
+    }
+    in.riscvTableJumpSection->finalizeContents();
+  }
+
   uint32_t pass = 0, assignPasses = 0;
   for (;;) {
     bool changed = target->needsThunks ? tc.createThunks(pass, outputSections)
@@ -2159,6 +2177,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     finalizeSynthetic(in.mipsGot.get());
     finalizeSynthetic(in.igotPlt.get());
     finalizeSynthetic(in.gotPlt.get());
+    finalizeSynthetic(in.riscvTableJumpSection.get());
     finalizeSynthetic(in.relaIplt.get());
     finalizeSynthetic(in.relaPlt.get());
     finalizeSynthetic(in.plt.get());
@@ -2954,8 +2973,11 @@ template <class ELFT> void Writer<ELFT>::openFile() {
 template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
   parallel::TaskGroup tg;
   for (OutputSection *sec : outputSections)
-    if (sec->flags & SHF_ALLOC)
+    if (sec->flags & SHF_ALLOC) {
       sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
+      if (config->emachine == EM_RISCV && config->zce_tbljal)
+        in.riscvTableJumpSection->writeTo(Out::bufferStart + sec->offset);
+    }
 }
 
 static void fillTrap(uint8_t *i, uint8_t *end) {
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
new file mode 100644
index 000000000000000..5913577266ded75
--- /dev/null
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -0,0 +1,93 @@
+# REQUIRES: riscv
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+
+# tbljal conversion
+# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+30 -o %t.rv32
+# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+30 -o %t.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
+# TBLJAL:      cm.jalt 66
+# TBLJAL-NEXT: cm.jt   2
+# TBLJAL-NEXT: cm.jalt 67
+# TBLJAL-NEXT: cm.jalt 65
+# TBLJAL-NEXT: cm.jalt 65
+# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jt   3
+# TBLJAL-NEXT: cm.jt   1
+# TBLJAL-NEXT: cm.jt   1
+# TBLJAL-NEXT: cm.jt   0
+# TBLJAL-NEXT: cm.jt   0
+# TBLJAL-NEXT: cm.jt   0
+
+# Check the bounds of what would be out of range (for the first call) for other jump types.
+# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
+# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
+# OLDBOUNDARY:      auipc  ra, 256
+# OLDBOUNDARY-NEXT: jalr   ra, 0(ra)
+# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo>
+# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_1>
+# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_1>
+# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_2>
+# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
+# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
+# BOUNDARY:      cm.jalt 66
+# BOUNDARY-NEXT: cm.jt   2
+# BOUNDARY-NEXT: cm.jalt 67
+# BOUNDARY-NEXT: cm.jalt 65
+# BOUNDARY-NEXT: cm.jalt 65
+# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jt   3
+# BOUNDARY-NEXT: cm.jt   1
+# BOUNDARY-NEXT: cm.jt   1
+# BOUNDARY-NEXT: cm.jt   0
+# BOUNDARY-NEXT: cm.jt   0
+# BOUNDARY-NEXT: cm.jt   0
+
+# Check relaxation works across output sections
+#  echo 'SECTIONS { .text 0x100000 : { *(.text) } .foo : ALIGN(8) { foo = .; } }' > %t-cross-section.lds
+#  ld.lld %t.rv32c.o %t-cross-section.lds -o %t-cross-section.rv32
+#  ld.lld %t.rv64c.o %t-cross-section.lds -o %t-cross-section.rv64
+
+.global _start
+.p2align 3
+_start:
+  call foo
+  tail foo
+
+  call foo_1
+  call foo_2
+  call foo_2
+  call foo_3
+  call foo_3
+  call foo_3
+  tail foo_1
+  tail foo_2
+  tail foo_2
+  tail foo_3
+  tail foo_3
+  tail foo_3
+
+foo_1:
+  nop
+
+foo_2:
+  nop
+
+foo_3:
+  nop
+
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
new file mode 100644
index 000000000000000..f708984c6025c21
--- /dev/null
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -0,0 +1,32 @@
+# REQUIRES: riscv
+
+// Check that relaxation correctly adjusts symbol addresses and sizes.
+
+#TODO: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+#TODO: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv64.o -o %t.rv64
+
+#TODO: llvm-readelf -s %t.rv32 | FileCheck %s
+# RUN: llvm-readelf -s %t.rv64 | FileCheck %s
+
+# CHECK: 100000     4 NOTYPE  LOCAL  DEFAULT     1 a
+# CHECK: 100000     6 NOTYPE  LOCAL  DEFAULT     1 b
+# CHECK: 100004     2 NOTYPE  LOCAL  DEFAULT     1 c
+# CHECK: 100004     6 NOTYPE  LOCAL  DEFAULT     1 d
+# CHECK: 100000    10 NOTYPE  GLOBAL DEFAULT     1 _start
+
+.global _start
+_start:
+a:
+b:
+  add  a0, a1, a2
+.size a, . - a
+c:
+d:
+  call _start
+.size b, . - b
+.size c, . - c
+  add a0, a1, a2
+.size d, . - d
+.size _start, . - _start

>From 0d7cccc3176fa9971257899fd215238e44d2fd77 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 14:02:47 +0800
Subject: [PATCH 02/46] reuse reloc type R_RISCV_JAL

---
 lld/ELF/Arch/RISCV.cpp | 46 ++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index e543ff3f4125f4b..9725a26e961c270 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -89,9 +89,6 @@ static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
 static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
   return op | (rd << 7) | (imm << 12);
 }
-static uint16_t tbljumptype(uint8_t imm) {
-  return 0b10 | (imm << 2) | (0b101 << 13);
-}
 
 // Extract bits v[begin:end], where range is inclusive, and begin must be < 63.
 static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
@@ -361,9 +358,6 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_RVC_JUMP: {
-    if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
-      return;
-
     checkInt(loc, val, 12, rel);
     checkAlignment(loc, val, 2, rel);
     uint16_t insn = read16le(loc) & 0xE003;
@@ -395,6 +389,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_JAL: {
+    if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
+      return;
+
     checkInt(loc, val, 21, rel);
     checkAlignment(loc, val, 2, rel);
 
@@ -645,10 +642,18 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
         tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
 
       if (tblEntryIndex >= 0) {
-        sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
+        sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+
+        // remove > 0 means the inst has been write to jal
+        // rewrite the last item.
+        if (remove)
+          sec.relaxAux->writes.back() = (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+        else
+          sec.relaxAux->writes.push_back(0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
         remove = 6;
       }
     }
+
   }
 }
 
@@ -867,26 +872,19 @@ void elf::riscvFinalizeRelax(int passes) {
           case R_RISCV_RELAX:
             // Used by relaxTlsLe to indicate the relocation is ignored.
             break;
-          case R_RISCV_RVC_JUMP: {
-            const uint32_t rd =
-                extractBits(read32le(old.data() + r.offset + 4), 11, 7);
-            int tblEntryIndex = -1;
-            if (config->zce_tbljal && rd == 0)
-              tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
-            else if (config->zce_tbljal && rd == X_RA)
-              tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
-
+          case R_RISCV_RVC_JUMP: 
             skip = 2;
-            if (config->zce_tbljal && tblEntryIndex >= 0) {
-              write16le(p, tbljumptype(tblEntryIndex));
-            } else {
-              write16le(p, aux.writes[writesIdx++]);
-            }
+            write16le(p, aux.writes[writesIdx++]);
             break;
-          }
           case R_RISCV_JAL:
-            skip = 4;
-            write32le(p, aux.writes[writesIdx++]);
+            if (config->zce_tbljal && (aux.writes[writesIdx] & 0xfc03) == 0xa002){
+              skip = 2;
+              write16le(p, aux.writes[writesIdx++]);
+            }
+            else{
+              skip = 4;
+              write32le(p, aux.writes[writesIdx++]);
+            }
             break;
           case R_RISCV_32:
             // Used by relaxTlsLe to write a uint32_t then suppress the handling

>From a57d85387e2282ff8e013495b61cf3dc53df185f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 14:04:24 +0800
Subject: [PATCH 03/46] format

---
 lld/ELF/Arch/RISCV.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 9725a26e961c270..9634ac54d410d44 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -647,13 +647,14 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
         // remove > 0 means the inst has been write to jal
         // rewrite the last item.
         if (remove)
-          sec.relaxAux->writes.back() = (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+          sec.relaxAux->writes.back() =
+              (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
         else
-          sec.relaxAux->writes.push_back(0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+          sec.relaxAux->writes.push_back(
+              0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
         remove = 6;
       }
     }
-
   }
 }
 
@@ -872,16 +873,16 @@ void elf::riscvFinalizeRelax(int passes) {
           case R_RISCV_RELAX:
             // Used by relaxTlsLe to indicate the relocation is ignored.
             break;
-          case R_RISCV_RVC_JUMP: 
+          case R_RISCV_RVC_JUMP:
             skip = 2;
             write16le(p, aux.writes[writesIdx++]);
             break;
           case R_RISCV_JAL:
-            if (config->zce_tbljal && (aux.writes[writesIdx] & 0xfc03) == 0xa002){
+            if (config->zce_tbljal &&
+                (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
               skip = 2;
               write16le(p, aux.writes[writesIdx++]);
-            }
-            else{
+            } else {
               skip = 4;
               write32le(p, aux.writes[writesIdx++]);
             }

>From 50502dad520a8e2b73ab0dfaae731bddc4432bdb Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 16:08:51 +0800
Subject: [PATCH 04/46] fix TODO

---
 lld/ELF/SyntheticSections.cpp    | 14 ++++++--------
 lld/ELF/SyntheticSections.h      |  2 +-
 lld/test/ELF/riscv-tbljal-syms.s |  6 +++---
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 01c4580f8489a66..4a3aece2db990e6 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1245,17 +1245,17 @@ void TableJumpSection::finalizeContents() {
   std::copy(entriesZero.begin(), entriesZero.end(),
             std::back_inserter(finalizedEntriesZero));
   std::sort(finalizedEntriesZero.begin(), finalizedEntriesZero.end(), cmp);
+  if (finalizedEntriesZero.size() > maxSizeZero)
+    finalizedEntriesZero.resize(maxSizeZero);
+
   std::copy(entriesRa.begin(), entriesRa.end(),
             std::back_inserter(finalizedEntriesRa));
   std::sort(finalizedEntriesRa.begin(), finalizedEntriesRa.end(), cmp);
+  if (finalizedEntriesRa.size() > maxSizeRa)
+    finalizedEntriesRa.resize(maxSizeRa);
 }
 
 size_t TableJumpSection::getSize() const {
-  if (size == 0)
-    return 256 * xlen; // TODO: This is the maximum size shrink this. This is
-                       // being caused by getSize being called to allocate space
-                       // for the section before the tbljal optimisation is
-                       // performed to add entries to the table.
   if (!entriesRa.empty()) {
     return (startRa + entriesRa.size()) * xlen;
   }
@@ -1298,9 +1298,7 @@ void TableJumpSection::writeEntries(
 }
 
 bool TableJumpSection::isNeeded() const {
-  // TODO: Make this function correctly. Currently discards section with
-  // entries.
-  return getSize() != 0;
+  return config->zce_tbljal;
 }
 
 static StringRef getIgotPltName() {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index f6d4739a60adfb6..e27d884af9d275a 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -405,7 +405,7 @@ class TableJumpSection final : public SyntheticSection {
   std::map<std::string, int> entriesRa;
   std::vector<std::pair<std::string, int>> finalizedEntriesRa;
 
-  // TODO: Make use of these in cost function.
+  // used in finalizeContents function.
   const size_t maxSizeZero = 64;
   const size_t maxSizeRa = 192;
 
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index f708984c6025c21..b98c9ad8b60cccb 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -2,12 +2,12 @@
 
 // Check that relaxation correctly adjusts symbol addresses and sizes.
 
-#TODO: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
-#TODO: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
 # RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv64.o -o %t.rv64
 
-#TODO: llvm-readelf -s %t.rv32 | FileCheck %s
+# RUN: llvm-readelf -s %t.rv32 | FileCheck %s
 # RUN: llvm-readelf -s %t.rv64 | FileCheck %s
 
 # CHECK: 100000     4 NOTYPE  LOCAL  DEFAULT     1 a

>From a7545d8b4763109243f24c714548e46b314e3cc5 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 16:34:11 +0800
Subject: [PATCH 05/46] fix name

---
 lld/ELF/Arch/RISCV.cpp           | 6 +++---
 lld/ELF/Config.h                 | 2 +-
 lld/ELF/Driver.cpp               | 2 +-
 lld/ELF/Options.td               | 2 +-
 lld/ELF/SyntheticSections.cpp    | 2 +-
 lld/ELF/Writer.cpp               | 4 ++--
 lld/test/ELF/riscv-tbljal-call.s | 8 ++++----
 lld/test/ELF/riscv-tbljal-syms.s | 4 ++--
 8 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 9634ac54d410d44..33a8a8f94f479e0 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -389,7 +389,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_JAL: {
-    if (config->zce_tbljal && (read16le(loc) & 0xfc03) == 0xa002)
+    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
       return;
 
     checkInt(loc, val, 21, rel);
@@ -635,7 +635,7 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
     }
 
     int tblEntryIndex = -1;
-    if (config->zce_tbljal) {
+    if (config->riscvTbljal) {
       if (rd == 0)
         tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
       else if (rd == X_RA)
@@ -878,7 +878,7 @@ void elf::riscvFinalizeRelax(int passes) {
             write16le(p, aux.writes[writesIdx++]);
             break;
           case R_RISCV_JAL:
-            if (config->zce_tbljal &&
+            if (config->riscvTbljal &&
                 (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
               skip = 2;
               write16le(p, aux.writes[writesIdx++]);
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 0d456cbde458015..01cb9cbc4fb0d27 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -275,6 +275,7 @@ struct Config {
   bool relocatable;
   bool relrGlibc = false;
   bool relrPackDynRelocs = false;
+  bool riscvTbljal;
   llvm::DenseSet<llvm::StringRef> saveTempsArgs;
   llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
   bool singleRoRx;
@@ -301,7 +302,6 @@ struct Config {
   bool writeAddends;
   bool zCombreloc;
   bool zCopyreloc;
-  bool zce_tbljal;
   bool zForceBti;
   bool zForceIbt;
   bool zGlobal;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index c98e42efd770fdd..a1d80919447b211 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,7 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->whyExtract = args.getLastArgValue(OPT_why_extract);
   config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
   config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
-  config->zce_tbljal = args.hasArg(OPT_zce_tbljal);
+  config->riscvTbljal = args.hasArg(OPT_riscv_bljal);
   config->zForceBti = hasZOption(args, "force-bti");
   config->zForceIbt = hasZOption(args, "force-ibt");
   config->zGlobal = hasZOption(args, "global");
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 0ec8157cbe2e8ff..b52002f4325c9f8 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,7 +340,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
     "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
     "Use SHT_RELR / DT_RELR* tags (default)">;
 
-def zce_tbljal: F<"zce-tbljal">,
+def riscv_tbljal: F<"riscv-tbljal">,
   HelpText<"(RISCV only) Enable table jump instructions from the Zce extension">;
 
 def pic_veneer: F<"pic-veneer">,
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 4a3aece2db990e6..14842105d89ec79 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1298,7 +1298,7 @@ void TableJumpSection::writeEntries(
 }
 
 bool TableJumpSection::isNeeded() const {
-  return config->zce_tbljal;
+  return config->riscvTbljal;
 }
 
 static StringRef getIgotPltName() {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 2cd0a9f181fa542..c49f96bcdb71cc7 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,7 +502,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     add(*in.ppc64LongBranchTarget);
   }
 
-  if (config->emachine == EM_RISCV && config->zce_tbljal) {
+  if (config->emachine == EM_RISCV && config->riscvTbljal) {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
     add(*in.riscvTableJumpSection);
 
@@ -2975,7 +2975,7 @@ template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
   for (OutputSection *sec : outputSections)
     if (sec->flags & SHF_ALLOC) {
       sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
-      if (config->emachine == EM_RISCV && config->zce_tbljal)
+      if (config->emachine == EM_RISCV && config->riscvTbljal)
         in.riscvTableJumpSection->writeTo(Out::bufferStart + sec->offset);
     }
 }
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 5913577266ded75..6bca2d295ce01a2 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,8 +4,8 @@
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
 
 # tbljal conversion
-# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+30 -o %t.rv32
-# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+30 -o %t.rv64
+# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv32
+# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
 # TBLJAL:      cm.jalt 66
@@ -24,8 +24,8 @@
 # TBLJAL-NEXT: cm.jt   0
 
 # Check the bounds of what would be out of range (for the first call) for other jump types.
-# RUN: ld.lld %t.rv32.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
-# RUN: ld.lld %t.rv64.o -zce-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
+# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
 # OLDBOUNDARY:      auipc  ra, 256
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index b98c9ad8b60cccb..579ea8245fa1d43 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -4,8 +4,8 @@
 
 # RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
-# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv32.o -o %t.rv32
-# RUN: ld.lld -Ttext=0x100000 -zce-tbljal %t.rv64.o -o %t.rv64
+# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv64.o -o %t.rv64
 
 # RUN: llvm-readelf -s %t.rv32 | FileCheck %s
 # RUN: llvm-readelf -s %t.rv64 | FileCheck %s

>From 9153af3dc8a38f7247efd8c2da6636fa866abb4d Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 16:35:34 +0800
Subject: [PATCH 06/46] format

---
 lld/ELF/SyntheticSections.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 14842105d89ec79..9033a0220e8de38 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1297,9 +1297,7 @@ void TableJumpSection::writeEntries(
   }
 }
 
-bool TableJumpSection::isNeeded() const {
-  return config->riscvTbljal;
-}
+bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }
 
 static StringRef getIgotPltName() {
   // On ARM the IgotPltSection is part of the GotSection.

>From 1b39df25acdef8a6c0594f10ea1409260469b3e2 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 24 Sep 2022 18:07:44 +0800
Subject: [PATCH 07/46] fix compile erroe

---
 lld/ELF/Driver.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index a1d80919447b211..5319261c363a03a 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,7 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->whyExtract = args.getLastArgValue(OPT_why_extract);
   config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
   config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
-  config->riscvTbljal = args.hasArg(OPT_riscv_bljal);
+  config->riscvTbljal = args.hasArg(OPT_riscv_tbljal);
   config->zForceBti = hasZOption(args, "force-bti");
   config->zForceIbt = hasZOption(args, "force-ibt");
   config->zGlobal = hasZOption(args, "global");

>From 59111f46384afab404ed1ac6d681f386a59d4c2d Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sun, 25 Sep 2022 19:18:45 +0800
Subject: [PATCH 08/46] add testcase

---
 lld/test/ELF/riscv-tbljal-call.s | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 6bca2d295ce01a2..d4db5e3cd323913 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -26,8 +26,12 @@
 # Check the bounds of what would be out of range (for the first call) for other jump types.
 # RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
 # RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv32
+# RUN: ld.lld %t.rv64.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv32 | FileCheck --check-prefix=OLDBOUNDARY %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv64 | FileCheck --check-prefix=OLDBOUNDARY %s
 # OLDBOUNDARY:      auipc  ra, 256
 # OLDBOUNDARY-NEXT: jalr   ra, 0(ra)
 # OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo>

>From d0c5fcf802e166886823812d2bbdb4c0dc3f1583 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 19:56:01 +0800
Subject: [PATCH 09/46] change the priority order of cm.jt/cm.jalt relax

---
 lld/ELF/Arch/RISCV.cpp | 35 ++++++++++++-----------------------
 1 file changed, 12 insertions(+), 23 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 33a8a8f94f479e0..27d335709bc4055 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -628,33 +628,22 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
     sec.relaxAux->writes.push_back(0x2001); // c.jal
     remove = 6;
   } else {
-    if (isInt<21>(displace)) {
+    int tblEntryIndex = -1;
+    if (config->riscvTbljal && rd == 0)
+      tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+    else if (config->riscvTbljal && rd == X_RA)
+      tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+
+    if (tblEntryIndex >= 0) {
+      sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+      sec.relaxAux->writes.push_back(
+            0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+      remove = 6;
+    } else if (isInt<21>(displace)) {
       sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
       sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
       remove = 4;
     }
-
-    int tblEntryIndex = -1;
-    if (config->riscvTbljal) {
-      if (rd == 0)
-        tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
-      else if (rd == X_RA)
-        tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
-
-      if (tblEntryIndex >= 0) {
-        sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
-
-        // remove > 0 means the inst has been write to jal
-        // rewrite the last item.
-        if (remove)
-          sec.relaxAux->writes.back() =
-              (0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
-        else
-          sec.relaxAux->writes.push_back(
-              0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
-        remove = 6;
-      }
-    }
   }
 }
 

>From 99e08c8c3c605290d007f495d88b3324ca606ee6 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 20:03:10 +0800
Subject: [PATCH 10/46] address comments

---
 lld/ELF/SyntheticSections.cpp | 10 +++-------
 lld/ELF/Writer.cpp            |  2 +-
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 9033a0220e8de38..2e8c7bec71cdc7e 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1172,8 +1172,8 @@ bool GotPltSection::isNeeded() const {
 }
 
 TableJumpSection::TableJumpSection()
-    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_RISCV_ATTRIBUTES,
-                       config->wordsize, ".tbljalentries") {}
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
+                       config->wordsize, "__tbljalvec_base$") {}
 
 void TableJumpSection::addEntryZero(const Symbol &symbol) {
   addEntry(symbol, entriesZero);
@@ -1195,11 +1195,7 @@ int TableJumpSection::getEntryRa(const Symbol &symbol) {
 
 void TableJumpSection::addEntry(const Symbol &symbol,
                                 std::map<std::string, int> &entriesList) {
-  if (entriesList.count(symbol.getName().str()) == 0) {
-    entriesList[symbol.getName().str()] = 1;
-  } else {
-    entriesList[symbol.getName().str()] += 1;
-  }
+  ++entriesList[symbol.getName().str()];
 }
 
 uint32_t TableJumpSection::getEntry(
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c49f96bcdb71cc7..10ef841935997d8 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -507,7 +507,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     add(*in.riscvTableJumpSection);
 
     symtab->addSymbol(Defined{
-        /*file=*/nullptr, ".tbljalentries", STB_WEAK, STT_NOTYPE, STT_NOTYPE,
+        /*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
         /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
   }
 

>From adbd7f47f936deb4d0427430187122133195226c Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 21:04:32 +0800
Subject: [PATCH 11/46] fix part of comments

---
 lld/ELF/Arch/RISCV.cpp        |  4 +--
 lld/ELF/SyntheticSections.cpp | 58 +++++++++++++++++------------------
 lld/ELF/SyntheticSections.h   | 24 +++++++--------
 3 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 27d335709bc4055..08c7e7845391b91 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -630,9 +630,9 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
   } else {
     int tblEntryIndex = -1;
     if (config->riscvTbljal && rd == 0)
-      tblEntryIndex = in.riscvTableJumpSection->getEntryZero(*r.sym);
+      tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
     else if (config->riscvTbljal && rd == X_RA)
-      tblEntryIndex = in.riscvTableJumpSection->getEntryRa(*r.sym);
+      tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
 
     if (tblEntryIndex >= 0) {
       sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2e8c7bec71cdc7e..cb3cc42e0525e8b 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1175,22 +1175,22 @@ TableJumpSection::TableJumpSection()
     : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
                        config->wordsize, "__tbljalvec_base$") {}
 
-void TableJumpSection::addEntryZero(const Symbol &symbol) {
-  addEntry(symbol, entriesZero);
+void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol) {
+  addEntry(symbol, CMJTEntryCandidates);
 }
 
-int TableJumpSection::getEntryZero(const Symbol &symbol) {
-  uint32_t index = getEntry(symbol, finalizedEntriesZero);
-  return index < maxSizeZero ? (int)(startZero + index) : -1;
+int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
+  uint32_t index = getEntry(symbol, finalizedCMJTEntries);
+  return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
 }
 
-void TableJumpSection::addEntryRa(const Symbol &symbol) {
-  addEntry(symbol, entriesRa);
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol) {
+  addEntry(symbol, CMJALTEntryCandidates);
 }
 
-int TableJumpSection::getEntryRa(const Symbol &symbol) {
-  uint32_t index = getEntry(symbol, finalizedEntriesRa);
-  return index < maxSizeRa ? (int)(startRa + index) : -1;
+int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
+  uint32_t index = getEntry(symbol, finalizedCMJALTEntries);
+  return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
 }
 
 void TableJumpSection::addEntry(const Symbol &symbol,
@@ -1222,9 +1222,9 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
       const auto jalr = sec.data()[r.offset + 4];
       const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
       if (rd == 0)
-        in.riscvTableJumpSection->addEntryZero(*r.sym);
+        in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym);
       else if (rd == 1)
-        in.riscvTableJumpSection->addEntryRa(*r.sym);
+        in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym);
       else
         return; // Unknown link register, do not modify.
     }
@@ -1238,32 +1238,32 @@ void TableJumpSection::finalizeContents() {
     return p1.second > p2.second;
   };
 
-  std::copy(entriesZero.begin(), entriesZero.end(),
-            std::back_inserter(finalizedEntriesZero));
-  std::sort(finalizedEntriesZero.begin(), finalizedEntriesZero.end(), cmp);
-  if (finalizedEntriesZero.size() > maxSizeZero)
-    finalizedEntriesZero.resize(maxSizeZero);
+  std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
+            std::back_inserter(finalizedCMJTEntries));
+  std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
+  if (finalizedCMJTEntries.size() > maxCMJTEntrySize)
+    finalizedCMJTEntries.resize(maxCMJTEntrySize);
 
-  std::copy(entriesRa.begin(), entriesRa.end(),
-            std::back_inserter(finalizedEntriesRa));
-  std::sort(finalizedEntriesRa.begin(), finalizedEntriesRa.end(), cmp);
-  if (finalizedEntriesRa.size() > maxSizeRa)
-    finalizedEntriesRa.resize(maxSizeRa);
+  std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
+            std::back_inserter(finalizedCMJALTEntries));
+  std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
+  if (finalizedCMJALTEntries.size() > maxCMJALTEntrySize)
+    finalizedCMJALTEntries.resize(maxCMJALTEntrySize);
 }
 
 size_t TableJumpSection::getSize() const {
-  if (!entriesRa.empty()) {
-    return (startRa + entriesRa.size()) * xlen;
+  if (!CMJALTEntryCandidates.empty()) {
+    return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
   }
-  return (startZero + entriesZero.size()) * xlen;
+  return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
 }
 
 void TableJumpSection::writeTo(uint8_t *buf) {
   target->writeTableJumpHeader(buf);
-  writeEntries(buf + startZero, finalizedEntriesZero);
-  padUntil(buf + ((startZero + finalizedEntriesZero.size()) * xlen),
-           startRa * xlen);
-  writeEntries(buf + startRa, finalizedEntriesRa);
+  writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+  padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+           startCMJALTEntryIdx * xlen);
+  writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
 }
 
 void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index e27d884af9d275a..cf964839371ec8b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -377,10 +377,10 @@ class TableJumpSection final : public SyntheticSection {
   bool isNeeded() const override;
   void finalizeContents() override;
 
-  void addEntryZero(const Symbol &symbol);
-  int getEntryZero(const Symbol &symbol);
-  void addEntryRa(const Symbol &symbol);
-  int getEntryRa(const Symbol &symbol);
+  void addCMJTEntryCandidate(const Symbol &symbol);
+  int getCMJTEntryIndex(const Symbol &symbol);
+  void addCMJALTEntryCandidate(const Symbol &symbol);
+  int getCMJALTEntryIndex(const Symbol &symbol);
   void scanTableJumpEntrys(const InputSection &sec) const;
 
   // Flag to force TableJump to be in output if we have relocations
@@ -400,17 +400,17 @@ class TableJumpSection final : public SyntheticSection {
 
   const size_t xlen = config->is64 ? 64 : 32;
 
-  std::map<std::string, int> entriesZero;
-  std::vector<std::pair<std::string, int>> finalizedEntriesZero;
-  std::map<std::string, int> entriesRa;
-  std::vector<std::pair<std::string, int>> finalizedEntriesRa;
+  std::map<std::string, int> CMJTEntryCandidates;
+  std::vector<std::pair<std::string, int>> finalizedCMJTEntries;
+  std::map<std::string, int> CMJALTEntryCandidates;
+  std::vector<std::pair<std::string, int>> finalizedCMJALTEntries;
 
   // used in finalizeContents function.
-  const size_t maxSizeZero = 64;
-  const size_t maxSizeRa = 192;
+  const size_t maxCMJTEntrySize = 64;
+  const size_t maxCMJALTEntrySize = 192;
 
-  const size_t startZero = 0;
-  const size_t startRa = 64;
+  const size_t startCMJTEntryIdx = 0;
+  const size_t startCMJALTEntryIdx = 64;
 };
 
 // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc

>From 726883a2b79371d72ba2faf4dd34b660947b0f75 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 21:07:59 +0800
Subject: [PATCH 12/46] fmt

---
 lld/ELF/Arch/RISCV.cpp        | 4 ++--
 lld/ELF/SyntheticSections.cpp | 4 ++--
 lld/ELF/Writer.cpp            | 7 ++++---
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 08c7e7845391b91..855ff76ca6fce2a 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -636,8 +636,8 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
 
     if (tblEntryIndex >= 0) {
       sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
-      sec.relaxAux->writes.push_back(
-            0xa002 | (tblEntryIndex << 2)); // cm.jt or cm.jalt
+      sec.relaxAux->writes.push_back(0xa002 |
+                                     (tblEntryIndex << 2)); // cm.jt or cm.jalt
       remove = 6;
     } else if (isInt<21>(displace)) {
       sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index cb3cc42e0525e8b..0bf5a0e14057a72 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1172,8 +1172,8 @@ bool GotPltSection::isNeeded() const {
 }
 
 TableJumpSection::TableJumpSection()
-    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
-                       config->wordsize, "__tbljalvec_base$") {}
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
+                       "__tbljalvec_base$") {}
 
 void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol) {
   addEntry(symbol, CMJTEntryCandidates);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 10ef841935997d8..f214bae52106848 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,9 +506,10 @@ template <class ELFT> void elf::createSyntheticSections() {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
     add(*in.riscvTableJumpSection);
 
-    symtab->addSymbol(Defined{
-        /*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
-        /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
+    symtab->addSymbol(Defined{/*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL,
+                              STT_NOTYPE, STT_NOTYPE,
+                              /*value=*/0, /*size=*/0,
+                              in.riscvTableJumpSection.get()});
   }
 
   in.gotPlt = std::make_unique<GotPltSection>();

>From 98792056ce5a50ebcef8bf592e1d5e21b2fa7e92 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 26 Sep 2022 21:59:49 +0800
Subject: [PATCH 13/46] tmp

---
 lld/ELF/SyntheticSections.h      |  6 +++---
 lld/test/ELF/riscv-tbljal-call.s | 28 ++++++++++++++--------------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index cf964839371ec8b..8eb662f98b5d47b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -406,11 +406,11 @@ class TableJumpSection final : public SyntheticSection {
   std::vector<std::pair<std::string, int>> finalizedCMJALTEntries;
 
   // used in finalizeContents function.
-  const size_t maxCMJTEntrySize = 64;
-  const size_t maxCMJALTEntrySize = 192;
+  const size_t maxCMJTEntrySize = 32;
+  const size_t maxCMJALTEntrySize = 224;
 
   const size_t startCMJTEntryIdx = 0;
-  const size_t startCMJALTEntryIdx = 64;
+  const size_t startCMJALTEntryIdx = 32;
 };
 
 // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index d4db5e3cd323913..8851d95a0f71b2c 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -8,14 +8,14 @@
 # RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
-# TBLJAL:      cm.jalt 66
+# TBLJAL:      cm.jalt 34
 # TBLJAL-NEXT: cm.jt   2
-# TBLJAL-NEXT: cm.jalt 67
-# TBLJAL-NEXT: cm.jalt 65
-# TBLJAL-NEXT: cm.jalt 65
-# TBLJAL-NEXT: cm.jalt 64
-# TBLJAL-NEXT: cm.jalt 64
-# TBLJAL-NEXT: cm.jalt 64
+# TBLJAL-NEXT: cm.jalt 35
+# TBLJAL-NEXT: cm.jalt 33
+# TBLJAL-NEXT: cm.jalt 33
+# TBLJAL-NEXT: cm.jalt 32
+# TBLJAL-NEXT: cm.jalt 32
+# TBLJAL-NEXT: cm.jalt 32
 # TBLJAL-NEXT: cm.jt   3
 # TBLJAL-NEXT: cm.jt   1
 # TBLJAL-NEXT: cm.jt   1
@@ -47,14 +47,14 @@
 # OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
 # OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
 # OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
-# BOUNDARY:      cm.jalt 66
+# BOUNDARY:      cm.jalt 34
 # BOUNDARY-NEXT: cm.jt   2
-# BOUNDARY-NEXT: cm.jalt 67
-# BOUNDARY-NEXT: cm.jalt 65
-# BOUNDARY-NEXT: cm.jalt 65
-# BOUNDARY-NEXT: cm.jalt 64
-# BOUNDARY-NEXT: cm.jalt 64
-# BOUNDARY-NEXT: cm.jalt 64
+# BOUNDARY-NEXT: cm.jalt 35
+# BOUNDARY-NEXT: cm.jalt 33
+# BOUNDARY-NEXT: cm.jalt 33
+# BOUNDARY-NEXT: cm.jalt 32
+# BOUNDARY-NEXT: cm.jalt 32
+# BOUNDARY-NEXT: cm.jalt 32
 # BOUNDARY-NEXT: cm.jt   3
 # BOUNDARY-NEXT: cm.jt   1
 # BOUNDARY-NEXT: cm.jt   1

>From b912fefa20a49769850d29167d8ddaac10779bb2 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Thu, 27 Oct 2022 14:15:52 +0800
Subject: [PATCH 14/46] update option start with `--` use `DenseMap` and
 `CachedHashStringRef`

---
 lld/ELF/Options.td            |  4 +--
 lld/ELF/SyntheticSections.cpp | 59 ++++++++++++++++-------------------
 lld/ELF/SyntheticSections.h   | 25 +++++++--------
 3 files changed, 41 insertions(+), 47 deletions(-)

diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index b52002f4325c9f8..dde5f4087b34a3f 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,8 +340,8 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
     "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
     "Use SHT_RELR / DT_RELR* tags (default)">;
 
-def riscv_tbljal: F<"riscv-tbljal">,
-  HelpText<"(RISCV only) Enable table jump instructions from the Zce extension">;
+def riscv_tbljal: FF<"riscv-tbljal">,
+  HelpText<"(RISC-V only) Enable table jump instructions from the Zce extension">;
 
 def pic_veneer: F<"pic-veneer">,
   HelpText<"Always generate position independent thunks (veneers)">;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 0bf5a0e14057a72..0077a8e448ca5d0 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1194,19 +1194,18 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
 }
 
 void TableJumpSection::addEntry(const Symbol &symbol,
-                                std::map<std::string, int> &entriesList) {
-  ++entriesList[symbol.getName().str()];
+                                llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList) {
+  ++entriesList[llvm::CachedHashStringRef(symbol.getName().str())];
 }
 
-uint32_t TableJumpSection::getEntry(
-    const Symbol &symbol,
-    std::vector<std::pair<std::string, int>> &entriesList) {
+uint32_t TableJumpSection::getEntry(const Symbol &symbol,
+                    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList){
   // Prevent adding duplicate entries
   uint32_t i = 0;
   for (; i < entriesList.size(); ++i) {
     // If this is a duplicate addition, do not add it and return the address
     // offset of the original entry.
-    if (symbol.getName().compare(entriesList[i].first) == 0) {
+    if (symbol.getName().compare(entriesList[i].first.val()) == 0) {
       return i;
     }
   }
@@ -1233,22 +1232,18 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
 }
 
 void TableJumpSection::finalizeContents() {
-  auto cmp = [](const std::pair<std::string, int> &p1,
-                const std::pair<std::string, int> &p2) {
+  auto cmp = [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
+                const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
     return p1.second > p2.second;
   };
 
   std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
             std::back_inserter(finalizedCMJTEntries));
   std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
-  if (finalizedCMJTEntries.size() > maxCMJTEntrySize)
-    finalizedCMJTEntries.resize(maxCMJTEntrySize);
 
   std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
             std::back_inserter(finalizedCMJALTEntries));
   std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
-  if (finalizedCMJALTEntries.size() > maxCMJALTEntrySize)
-    finalizedCMJALTEntries.resize(maxCMJALTEntrySize);
 }
 
 size_t TableJumpSection::getSize() const {
@@ -1259,11 +1254,11 @@ size_t TableJumpSection::getSize() const {
 }
 
 void TableJumpSection::writeTo(uint8_t *buf) {
-  target->writeTableJumpHeader(buf);
-  writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
-  padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
-           startCMJALTEntryIdx * xlen);
-  writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+  // target->writeTableJumpHeader(buf);
+  // writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+  // padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+  //          startCMJALTEntryIdx * xlen);
+  // writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
 }
 
 void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
@@ -1276,21 +1271,21 @@ void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
 }
 
 void TableJumpSection::writeEntries(
-    uint8_t *buf, std::vector<std::pair<std::string, int>> &entriesList) {
-  for (const auto &symbolName : entriesList) {
-    // Use the symbol from in.symTab to ensure we have the final adjusted
-    // symbol.
-    for (const auto &symbol : in.symTab->getSymbols()) {
-      if (symbol.sym->getName() != symbolName.first)
-        continue;
-      // Only process defined symbols.
-      auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
-      if (!definedSymbol)
-        continue;
-      target->writeTableJump(buf, definedSymbol->getVA());
-      buf += config->wordsize;
-    }
-  }
+    uint8_t *buf, SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList) {
+  // for (const auto &symbolName : entriesList) {
+  //   // Use the symbol from in.symTab to ensure we have the final adjusted
+  //   // symbol.
+  //   for (const auto &symbol : in.symTab->getSymbols()) {
+  //     if (symbol.sym->getName() != symbolName.first)
+  //       continue;
+  //     // Only process defined symbols.
+  //     auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+  //     if (!definedSymbol)
+  //       continue;
+  //     target->writeTableJump(buf, definedSymbol->getVA());
+  //     buf += config->wordsize;
+  //   }
+  // }
 }
 
 bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 8eb662f98b5d47b..e3ad82cdc754f63 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -31,7 +31,6 @@
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/Threading.h"
-#include <map>
 
 namespace lld::elf {
 class Defined;
@@ -391,26 +390,26 @@ class TableJumpSection final : public SyntheticSection {
   uint64_t size = 0;
 
 private:
-  void addEntry(const Symbol &symbol, std::map<std::string, int> &entriesList);
+  void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList);
   uint32_t getEntry(const Symbol &symbol,
-                    std::vector<std::pair<std::string, int>> &entriesList);
+                    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
   void writeEntries(uint8_t *buf,
-                    std::vector<std::pair<std::string, int>> &entriesList);
+                    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
   void padUntil(uint8_t *buf, const uint8_t index);
 
   const size_t xlen = config->is64 ? 64 : 32;
 
-  std::map<std::string, int> CMJTEntryCandidates;
-  std::vector<std::pair<std::string, int>> finalizedCMJTEntries;
-  std::map<std::string, int> CMJALTEntryCandidates;
-  std::vector<std::pair<std::string, int>> finalizedCMJALTEntries;
-
   // used in finalizeContents function.
-  const size_t maxCMJTEntrySize = 32;
-  const size_t maxCMJALTEntrySize = 224;
+  static const size_t maxCMJTEntrySize = 32;
+  static const size_t maxCMJALTEntrySize = 224;
+
+  static const size_t startCMJTEntryIdx = 0;
+  static const size_t startCMJALTEntryIdx = 32;
 
-  const size_t startCMJTEntryIdx = 0;
-  const size_t startCMJALTEntryIdx = 32;
+  llvm::DenseMap<llvm::CachedHashStringRef, int> CMJTEntryCandidates;
+  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJTEntries;
+  llvm::DenseMap<llvm::CachedHashStringRef, int> CMJALTEntryCandidates;
+  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJALTEntries;
 };
 
 // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc

>From 192f5012e934b98c2779de6879a63dc774707769 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 10:40:07 +0800
Subject: [PATCH 15/46] reimplement Zcmt relax

---
 lld/ELF/Arch/RISCV.cpp           | 52 +++++++++++++++++++++-----------
 lld/ELF/SyntheticSections.cpp    | 51 +++++++++++++++++++------------
 lld/ELF/SyntheticSections.h      | 13 +++-----
 lld/ELF/Writer.cpp               | 26 +++++++++-------
 lld/test/ELF/riscv-tbljal-call.s |  4 +--
 lld/test/ELF/riscv-tbljal-syms.s |  4 +--
 6 files changed, 91 insertions(+), 59 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 855ff76ca6fce2a..d8b55b7eb30dbb1 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -607,6 +607,32 @@ static void initSymbolAnchors() {
   }
 }
 
+
+static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
+                      Relocation &r, uint32_t &remove){
+  if(!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
+    return false;
+  
+  const auto jalr = sec.data()[r.offset + 4];
+  const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
+  int tblEntryIndex = -1;
+  if (rd == 0){
+    tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
+  }
+  else if(rd == X_RA){
+    tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
+  }
+
+  if (tblEntryIndex >= 0){
+    sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+    sec.relaxAux->writes.push_back(0xa002 |
+                                  (tblEntryIndex << 2)); // cm.jt or cm.jalt
+    remove = 6;
+    return true;
+  }
+  return false;
+}
+
 // Relax R_RISCV_CALL/R_RISCV_CALL_PLT auipc+jalr to c.j, c.jal, or jal.
 static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
                       Relocation &r, uint32_t &remove) {
@@ -627,23 +653,10 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
     sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
     sec.relaxAux->writes.push_back(0x2001); // c.jal
     remove = 6;
-  } else {
-    int tblEntryIndex = -1;
-    if (config->riscvTbljal && rd == 0)
-      tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
-    else if (config->riscvTbljal && rd == X_RA)
-      tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
-
-    if (tblEntryIndex >= 0) {
-      sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
-      sec.relaxAux->writes.push_back(0xa002 |
-                                     (tblEntryIndex << 2)); // cm.jt or cm.jalt
-      remove = 6;
-    } else if (isInt<21>(displace)) {
-      sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
-      sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
-      remove = 4;
-    }
+  } else if(!relaxZcmt(sec,i,loc,r,remove) && isInt<21>(displace)) {
+    sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+    sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
+    remove = 4;
   }
 }
 
@@ -742,6 +755,11 @@ static bool relax(InputSection &sec) {
       if (i + 1 != sec.relocs().size() &&
           sec.relocs()[i + 1].type == R_RISCV_RELAX)
         relaxHi20Lo12(sec, i, loc, r, remove);
+
+    case R_RISCV_JAL:
+      if (i + 1 != sec.relocations.size() &&
+          sec.relocations[i + 1].type == R_RISCV_RELAX)
+        relaxZcmt(sec, i, loc, r, remove);
       break;
     }
 
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 0077a8e448ca5d0..da009c9d99c7086 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -39,7 +39,7 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/TimeProfiler.h"
-#include <cstdlib>
+#include <iostream>
 
 using namespace llvm;
 using namespace llvm::dwarf;
@@ -1172,40 +1172,47 @@ bool GotPltSection::isNeeded() const {
 }
 
 TableJumpSection::TableJumpSection()
-    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
-                       "__tbljalvec_base$") {}
+    : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, config->wordsize,
+                       ".riscv.jvt") {}
 
-void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol) {
-  addEntry(symbol, CMJTEntryCandidates);
+void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
+  addEntry(symbol, CMJTEntryCandidates, gain);
 }
 
 int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
-  uint32_t index = getEntry(symbol, finalizedCMJTEntries);
+  uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
   return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
 }
 
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol) {
-  addEntry(symbol, CMJALTEntryCandidates);
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
+  addEntry(symbol, CMJALTEntryCandidates, gain);
 }
 
 int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
-  uint32_t index = getEntry(symbol, finalizedCMJALTEntries);
+  uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
   return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
 }
 
 void TableJumpSection::addEntry(const Symbol &symbol,
-                                llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList) {
-  ++entriesList[llvm::CachedHashStringRef(symbol.getName().str())];
+                                llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
+  if(symbol.file)
+    entriesList[llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str())] += gain;
+  else
+    entriesList[llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str())] += gain;
 }
 
-uint32_t TableJumpSection::getEntry(const Symbol &symbol,
+uint32_t TableJumpSection::getEntry(const Symbol &symbol, uint32_t maxSize,
                     SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList){
   // Prevent adding duplicate entries
   uint32_t i = 0;
-  for (; i < entriesList.size(); ++i) {
+  llvm::CachedHashStringRef symName = llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str());;
+  if(symbol.file)
+    symName = llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str());
+
+  for (; i < entriesList.size() && i <= maxSize; ++i) {
     // If this is a duplicate addition, do not add it and return the address
     // offset of the original entry.
-    if (symbol.getName().compare(entriesList[i].first.val()) == 0) {
+    if (symName.hash() == entriesList[i].first.hash()) {
       return i;
     }
   }
@@ -1215,23 +1222,29 @@ uint32_t TableJumpSection::getEntry(const Symbol &symbol,
 void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
   for (auto [i, r] : llvm::enumerate(sec.relocations)) {
     switch (r.type) {
-    // auipc + jalr pair
+    case R_RISCV_JAL:
     case R_RISCV_CALL:
     case R_RISCV_CALL_PLT: {
+      int gain = 6;
+      if(r.type == R_RISCV_JAL)
+        gain = 2;
+
       const auto jalr = sec.data()[r.offset + 4];
       const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
       if (rd == 0)
-        in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym);
+        in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
       else if (rd == 1)
-        in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym);
-      else
-        return; // Unknown link register, do not modify.
+        in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
     }
     }
   }
 }
 
 void TableJumpSection::finalizeContents() {
+  if(isFinalized)
+    return;
+  isFinalized = true;
+
   auto cmp = [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
                 const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
     return p1.second > p2.second;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index e3ad82cdc754f63..f6daa481180d878 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -376,22 +376,19 @@ class TableJumpSection final : public SyntheticSection {
   bool isNeeded() const override;
   void finalizeContents() override;
 
-  void addCMJTEntryCandidate(const Symbol &symbol);
+  void addCMJTEntryCandidate(const Symbol &symbol, int gain);
   int getCMJTEntryIndex(const Symbol &symbol);
-  void addCMJALTEntryCandidate(const Symbol &symbol);
+  void addCMJALTEntryCandidate(const Symbol &symbol, int gain);
   int getCMJALTEntryIndex(const Symbol &symbol);
   void scanTableJumpEntrys(const InputSection &sec) const;
 
-  // Flag to force TableJump to be in output if we have relocations
-  // that relies on its address.
-  bool hasTableJumpOffRel = false;
-
+  bool isFinalized = false;
 protected:
   uint64_t size = 0;
 
 private:
-  void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList);
-  uint32_t getEntry(const Symbol &symbol,
+  void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain);
+  uint32_t getEntry(const Symbol &symbol, uint32_t maxSize,
                     SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
   void writeEntries(uint8_t *buf,
                     SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index f214bae52106848..8e73f280bd399e4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,7 +506,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
     add(*in.riscvTableJumpSection);
 
-    symtab->addSymbol(Defined{/*file=*/nullptr, "__tbljalvec_base$", STB_GLOBAL,
+    symtab->addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
                               STT_NOTYPE, STT_NOTYPE,
                               /*value=*/0, /*size=*/0,
                               in.riscvTableJumpSection.get()});
@@ -1702,15 +1702,6 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   if (config->emachine == EM_HEXAGON)
     hexagonTLSSymbolUpdate(outputSections);
 
-  // scan all R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
-  if (in.riscvTableJumpSection) {
-    for (InputSectionBase *inputSection : inputSections) {
-      in.riscvTableJumpSection->scanTableJumpEntrys(
-          cast<InputSection>(*inputSection));
-    }
-    in.riscvTableJumpSection->finalizeContents();
-  }
-
   uint32_t pass = 0, assignPasses = 0;
   for (;;) {
     bool changed = target->needsThunks ? tc.createThunks(pass, outputSections)
@@ -1735,6 +1726,19 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
         script->assignAddresses();
       changed |= a32p.createFixes();
     }
+    if (config->riscvTbljal){
+      if(!changed){
+        // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
+        if (in.riscvTableJumpSection) {
+          for (InputSectionBase *inputSection : inputSections) {
+            in.riscvTableJumpSection->scanTableJumpEntrys(
+                cast<InputSection>(*inputSection));
+          }
+          in.riscvTableJumpSection->finalizeContents();
+          changed |= target->relaxOnce(pass);
+        }
+      }
+    }
 
     finalizeSynthetic(in.got.get());
     if (in.mipsGot)
@@ -2178,7 +2182,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     finalizeSynthetic(in.mipsGot.get());
     finalizeSynthetic(in.igotPlt.get());
     finalizeSynthetic(in.gotPlt.get());
-    finalizeSynthetic(in.riscvTableJumpSection.get());
+    // finalizeSynthetic(in.riscvTableJumpSection.get());
     finalizeSynthetic(in.relaIplt.get());
     finalizeSynthetic(in.relaPlt.get());
     finalizeSynthetic(in.plt.get());
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 8851d95a0f71b2c..b546cb18d5cd818 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,8 +4,8 @@
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
 
 # tbljal conversion
-# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv32
-# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+30 -o %t.rv64
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
 # TBLJAL:      cm.jalt 34
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 579ea8245fa1d43..995cb20857f79ba 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -4,8 +4,8 @@
 
 # RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
-# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv32.o -o %t.rv32
-# RUN: ld.lld -Ttext=0x100000 -riscv-tbljal %t.rv64.o -o %t.rv64
+# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv64.o -o %t.rv64
 
 # RUN: llvm-readelf -s %t.rv32 | FileCheck %s
 # RUN: llvm-readelf -s %t.rv64 | FileCheck %s

>From 74cf6271c4709d8717b44797c78cab0d1535d31f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 11:47:29 +0800
Subject: [PATCH 16/46] fix testcase

---
 lld/test/ELF/riscv-tbljal-call.s | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index b546cb18d5cd818..7e4809b75ad1796 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -24,8 +24,8 @@
 # TBLJAL-NEXT: cm.jt   0
 
 # Check the bounds of what would be out of range (for the first call) for other jump types.
-# RUN: ld.lld %t.rv32.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
-# RUN: ld.lld %t.rv64.o -riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
 # RUN: ld.lld %t.rv32.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv32
 # RUN: ld.lld %t.rv64.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s

>From 96d0f361a26a1440c3b941fbb2c22f001fabce61 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 13:10:00 +0800
Subject: [PATCH 17/46] rebase & update

---
 lld/ELF/Arch/RISCV.cpp        | 2 +-
 lld/ELF/SyntheticSections.cpp | 2 +-
 lld/ELF/Writer.cpp            | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index d8b55b7eb30dbb1..88757bbf33aa8e4 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -613,7 +613,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
   if(!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
     return false;
   
-  const auto jalr = sec.data()[r.offset + 4];
+  const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
   const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
   int tblEntryIndex = -1;
   if (rd == 0){
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index da009c9d99c7086..870dca75e994ef3 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1229,7 +1229,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
       if(r.type == R_RISCV_JAL)
         gain = 2;
 
-      const auto jalr = sec.data()[r.offset + 4];
+      const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
       const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
       if (rd == 0)
         in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 8e73f280bd399e4..f28670aeff8d6b2 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,7 +506,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
     add(*in.riscvTableJumpSection);
 
-    symtab->addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
+    symtab.addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
                               STT_NOTYPE, STT_NOTYPE,
                               /*value=*/0, /*size=*/0,
                               in.riscvTableJumpSection.get()});
@@ -1730,7 +1730,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
       if(!changed){
         // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
         if (in.riscvTableJumpSection) {
-          for (InputSectionBase *inputSection : inputSections) {
+          for (InputSectionBase *inputSection : ctx.inputSections) {
             in.riscvTableJumpSection->scanTableJumpEntrys(
                 cast<InputSection>(*inputSection));
           }

>From 3e79817edb88b47564ccae7f8e06efaa79ba840c Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 14:01:51 +0800
Subject: [PATCH 18/46] git format

---
 lld/ELF/Arch/RISCV.cpp        | 18 ++++++-------
 lld/ELF/SyntheticSections.cpp | 51 ++++++++++++++++++++++-------------
 lld/ELF/SyntheticSections.h   | 23 +++++++++++-----
 lld/ELF/Writer.cpp            | 14 +++++-----
 4 files changed, 63 insertions(+), 43 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 88757bbf33aa8e4..26fc052f9b43cfb 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -607,26 +607,24 @@ static void initSymbolAnchors() {
   }
 }
 
-
 static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
-                      Relocation &r, uint32_t &remove){
-  if(!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
+                      Relocation &r, uint32_t &remove) {
+  if (!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
     return false;
-  
+
   const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
   const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
   int tblEntryIndex = -1;
-  if (rd == 0){
+  if (rd == 0) {
     tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
-  }
-  else if(rd == X_RA){
+  } else if (rd == X_RA) {
     tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
   }
 
-  if (tblEntryIndex >= 0){
+  if (tblEntryIndex >= 0) {
     sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
     sec.relaxAux->writes.push_back(0xa002 |
-                                  (tblEntryIndex << 2)); // cm.jt or cm.jalt
+                                   (tblEntryIndex << 2)); // cm.jt or cm.jalt
     remove = 6;
     return true;
   }
@@ -653,7 +651,7 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
     sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
     sec.relaxAux->writes.push_back(0x2001); // c.jal
     remove = 6;
-  } else if(!relaxZcmt(sec,i,loc,r,remove) && isInt<21>(displace)) {
+  } else if (!relaxZcmt(sec, i, loc, r, remove) && isInt<21>(displace)) {
     sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
     sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
     remove = 4;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 870dca75e994ef3..b91afd450105ced 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1172,8 +1172,8 @@ bool GotPltSection::isNeeded() const {
 }
 
 TableJumpSection::TableJumpSection()
-    : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, config->wordsize,
-                       ".riscv.jvt") {}
+    : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
+                       config->wordsize, ".riscv.jvt") {}
 
 void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
   addEntry(symbol, CMJTEntryCandidates, gain);
@@ -1193,21 +1193,31 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
   return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
 }
 
-void TableJumpSection::addEntry(const Symbol &symbol,
-                                llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
-  if(symbol.file)
-    entriesList[llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str())] += gain;
+void TableJumpSection::addEntry(
+    const Symbol &symbol,
+    llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
+  if (symbol.file)
+    entriesList[llvm::CachedHashStringRef(
+        symbol.file->mb.getBufferIdentifier().str() + ":" +
+        symbol.getName().str())] += gain;
   else
-    entriesList[llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str())] += gain;
+    entriesList[llvm::CachedHashStringRef("<unknown>:" +
+                                          symbol.getName().str())] += gain;
 }
 
-uint32_t TableJumpSection::getEntry(const Symbol &symbol, uint32_t maxSize,
-                    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList){
+uint32_t TableJumpSection::getEntry(
+    const Symbol &symbol, uint32_t maxSize,
+    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+        &entriesList) {
   // Prevent adding duplicate entries
   uint32_t i = 0;
-  llvm::CachedHashStringRef symName = llvm::CachedHashStringRef("<unknown>:" +symbol.getName().str());;
-  if(symbol.file)
-    symName = llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() + ":" +symbol.getName().str());
+  llvm::CachedHashStringRef symName =
+      llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
+  ;
+  if (symbol.file)
+    symName =
+        llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
+                                  ":" + symbol.getName().str());
 
   for (; i < entriesList.size() && i <= maxSize; ++i) {
     // If this is a duplicate addition, do not add it and return the address
@@ -1226,7 +1236,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
     case R_RISCV_CALL:
     case R_RISCV_CALL_PLT: {
       int gain = 6;
-      if(r.type == R_RISCV_JAL)
+      if (r.type == R_RISCV_JAL)
         gain = 2;
 
       const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
@@ -1241,14 +1251,15 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
 }
 
 void TableJumpSection::finalizeContents() {
-  if(isFinalized)
+  if (isFinalized)
     return;
   isFinalized = true;
 
-  auto cmp = [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
-                const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
-    return p1.second > p2.second;
-  };
+  auto cmp =
+      [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
+         const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
+        return p1.second > p2.second;
+      };
 
   std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
             std::back_inserter(finalizedCMJTEntries));
@@ -1284,7 +1295,9 @@ void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
 }
 
 void TableJumpSection::writeEntries(
-    uint8_t *buf, SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList) {
+    uint8_t *buf,
+    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+        &entriesList) {
   // for (const auto &symbolName : entriesList) {
   //   // Use the symbol from in.symTab to ensure we have the final adjusted
   //   // symbol.
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index f6daa481180d878..c507e1970995116 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -383,15 +383,22 @@ class TableJumpSection final : public SyntheticSection {
   void scanTableJumpEntrys(const InputSection &sec) const;
 
   bool isFinalized = false;
+
 protected:
   uint64_t size = 0;
 
 private:
-  void addEntry(const Symbol &symbol, llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain);
-  uint32_t getEntry(const Symbol &symbol, uint32_t maxSize,
-                    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
-  void writeEntries(uint8_t *buf,
-                    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> &entriesList);
+  void addEntry(const Symbol &symbol,
+                llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
+                int gain);
+  uint32_t getEntry(
+      const Symbol &symbol, uint32_t maxSize,
+      SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+          &entriesList);
+  void writeEntries(
+      uint8_t *buf,
+      SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+          &entriesList);
   void padUntil(uint8_t *buf, const uint8_t index);
 
   const size_t xlen = config->is64 ? 64 : 32;
@@ -404,9 +411,11 @@ class TableJumpSection final : public SyntheticSection {
   static const size_t startCMJALTEntryIdx = 32;
 
   llvm::DenseMap<llvm::CachedHashStringRef, int> CMJTEntryCandidates;
-  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJTEntries;
+  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+      finalizedCMJTEntries;
   llvm::DenseMap<llvm::CachedHashStringRef, int> CMJALTEntryCandidates;
-  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> finalizedCMJALTEntries;
+  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+      finalizedCMJALTEntries;
 };
 
 // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index f28670aeff8d6b2..007483fe1d823ba 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,10 +506,9 @@ template <class ELFT> void elf::createSyntheticSections() {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
     add(*in.riscvTableJumpSection);
 
-    symtab.addSymbol(Defined{/*file=*/nullptr, "__jvt_base$", STB_GLOBAL,
-                              STT_NOTYPE, STT_NOTYPE,
-                              /*value=*/0, /*size=*/0,
-                              in.riscvTableJumpSection.get()});
+    symtab.addSymbol(Defined{
+        /*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
+        /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
   }
 
   in.gotPlt = std::make_unique<GotPltSection>();
@@ -1726,9 +1725,10 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
         script->assignAddresses();
       changed |= a32p.createFixes();
     }
-    if (config->riscvTbljal){
-      if(!changed){
-        // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt Jump table.
+    if (config->riscvTbljal) {
+      if (!changed) {
+        // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt
+        // Jump table.
         if (in.riscvTableJumpSection) {
           for (InputSectionBase *inputSection : ctx.inputSections) {
             in.riscvTableJumpSection->scanTableJumpEntrys(

>From 451a817f466b41184fa7358e88d28ee39d2e9694 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 16:07:41 +0800
Subject: [PATCH 19/46] write table entry to .riscv.jvt section

---
 lld/ELF/SyntheticSections.cpp | 45 +++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b91afd450105ced..df447c5defa7a88 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -39,7 +39,6 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/TimeProfiler.h"
-#include <iostream>
 
 using namespace llvm;
 using namespace llvm::dwarf;
@@ -1278,11 +1277,11 @@ size_t TableJumpSection::getSize() const {
 }
 
 void TableJumpSection::writeTo(uint8_t *buf) {
-  // target->writeTableJumpHeader(buf);
-  // writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
-  // padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
-  //          startCMJALTEntryIdx * xlen);
-  // writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+  target->writeTableJumpHeader(buf);
+  writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+  padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+           startCMJALTEntryIdx * xlen);
+  writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
 }
 
 void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
@@ -1298,20 +1297,26 @@ void TableJumpSection::writeEntries(
     uint8_t *buf,
     SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
         &entriesList) {
-  // for (const auto &symbolName : entriesList) {
-  //   // Use the symbol from in.symTab to ensure we have the final adjusted
-  //   // symbol.
-  //   for (const auto &symbol : in.symTab->getSymbols()) {
-  //     if (symbol.sym->getName() != symbolName.first)
-  //       continue;
-  //     // Only process defined symbols.
-  //     auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
-  //     if (!definedSymbol)
-  //       continue;
-  //     target->writeTableJump(buf, definedSymbol->getVA());
-  //     buf += config->wordsize;
-  //   }
-  // }
+  for (const auto &symbolName : entriesList) {
+    if(symbolName.second == 0)
+      continue;
+    // Use the symbol from in.symTab to ensure we have the final adjusted
+    // symbol.
+    for (const auto &symbol : in.symTab->getSymbols()) {
+      llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" +symbol.sym->getName().str());;
+      if(symbol.sym->file)
+        sym = llvm::CachedHashStringRef(symbol.sym->file->mb.getBufferIdentifier().str() + ":" +symbol.sym->getName().str());
+
+      if (sym.hash() != symbolName.first.hash())
+        continue;
+      // Only process defined symbols.
+      auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+      if (!definedSymbol)
+        continue;
+      target->writeTableJump(buf, definedSymbol->getVA());
+      buf += config->wordsize;
+    }
+  }
 }
 
 bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }

>From e5f78dab17354e62204421bc56b49a61bbb78382 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 16:09:17 +0800
Subject: [PATCH 20/46] format

---
 lld/ELF/SyntheticSections.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index df447c5defa7a88..f8a8b67b481c81a 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1298,14 +1298,18 @@ void TableJumpSection::writeEntries(
     SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
         &entriesList) {
   for (const auto &symbolName : entriesList) {
-    if(symbolName.second == 0)
+    if (symbolName.second == 0)
       continue;
     // Use the symbol from in.symTab to ensure we have the final adjusted
     // symbol.
     for (const auto &symbol : in.symTab->getSymbols()) {
-      llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" +symbol.sym->getName().str());;
-      if(symbol.sym->file)
-        sym = llvm::CachedHashStringRef(symbol.sym->file->mb.getBufferIdentifier().str() + ":" +symbol.sym->getName().str());
+      llvm::CachedHashStringRef sym =
+          llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
+      ;
+      if (symbol.sym->file)
+        sym = llvm::CachedHashStringRef(
+            symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
+            symbol.sym->getName().str());
 
       if (sym.hash() != symbolName.first.hash())
         continue;

>From a7d74e92eeced9a2e0f9e2e3440fdd74e2d90e81 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 6 Jan 2023 21:27:57 +0800
Subject: [PATCH 21/46] address comments

---
 lld/ELF/Arch/RISCV.cpp | 33 ++++++++++++++++++++++-----------
 lld/ELF/Options.td     |  2 +-
 lld/ELF/Writer.cpp     |  5 +----
 3 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 26fc052f9b43cfb..135e1beb785e907 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -336,9 +336,13 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
 
   switch (rel.type) {
   case R_RISCV_32:
+    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+      return;
     write32le(loc, val);
     return;
   case R_RISCV_64:
+    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+      return;
     write64le(loc, val);
     return;
 
@@ -389,9 +393,6 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_JAL: {
-    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
-      return;
-
     checkInt(loc, val, 21, rel);
     checkAlignment(loc, val, 2, rel);
 
@@ -622,7 +623,10 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
   }
 
   if (tblEntryIndex >= 0) {
-    sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+    if(config->is64)
+      sec.relaxAux->relocTypes[i] = R_RISCV_64;
+    else
+      sec.relaxAux->relocTypes[i] = R_RISCV_32;
     sec.relaxAux->writes.push_back(0xa002 |
                                    (tblEntryIndex << 2)); // cm.jt or cm.jalt
     remove = 6;
@@ -883,22 +887,29 @@ void elf::riscvFinalizeRelax(int passes) {
             write16le(p, aux.writes[writesIdx++]);
             break;
           case R_RISCV_JAL:
+              skip = 4;
+              write32le(p, aux.writes[writesIdx++]);
+            break;
+          case R_RISCV_64:
+            if (config->riscvTbljal &&
+                (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
+              skip = 2;
+              write16le(p, aux.writes[writesIdx++]);
+            }
+            break;
+          case R_RISCV_32:
             if (config->riscvTbljal &&
                 (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
               skip = 2;
               write16le(p, aux.writes[writesIdx++]);
             } else {
+              // Used by relaxTlsLe to write a uint32_t then suppress the handling
+              // in relocateAlloc.
               skip = 4;
               write32le(p, aux.writes[writesIdx++]);
+              aux.relocTypes[i] = R_RISCV_NONE;
             }
             break;
-          case R_RISCV_32:
-            // Used by relaxTlsLe to write a uint32_t then suppress the handling
-            // in relocateAlloc.
-            skip = 4;
-            write32le(p, aux.writes[writesIdx++]);
-            aux.relocTypes[i] = R_RISCV_NONE;
-            break;
           default:
             llvm_unreachable("unsupported type");
           }
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index dde5f4087b34a3f..659e37db737cde5 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -341,7 +341,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
     "Use SHT_RELR / DT_RELR* tags (default)">;
 
 def riscv_tbljal: FF<"riscv-tbljal">,
-  HelpText<"(RISC-V only) Enable table jump instructions from the Zce extension">;
+  HelpText<"(RISC-V only) Enable table jump instructions from the Zcmt extension">;
 
 def pic_veneer: F<"pic-veneer">,
   HelpText<"Always generate position independent thunks (veneers)">;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 007483fe1d823ba..3b881a9406452f8 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2978,11 +2978,8 @@ template <class ELFT> void Writer<ELFT>::openFile() {
 template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
   parallel::TaskGroup tg;
   for (OutputSection *sec : outputSections)
-    if (sec->flags & SHF_ALLOC) {
+    if (sec->flags & SHF_ALLOC)
       sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
-      if (config->emachine == EM_RISCV && config->riscvTbljal)
-        in.riscvTableJumpSection->writeTo(Out::bufferStart + sec->offset);
-    }
 }
 
 static void fillTrap(uint8_t *i, uint8_t *end) {

>From c116a182f0bf0a8eb3cf7442d92290240f8e7999 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Jan 2023 10:51:40 +0800
Subject: [PATCH 22/46] format

---
 lld/ELF/Arch/RISCV.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 135e1beb785e907..03f76387abb5b4e 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -623,7 +623,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
   }
 
   if (tblEntryIndex >= 0) {
-    if(config->is64)
+    if (config->is64)
       sec.relaxAux->relocTypes[i] = R_RISCV_64;
     else
       sec.relaxAux->relocTypes[i] = R_RISCV_32;
@@ -887,8 +887,8 @@ void elf::riscvFinalizeRelax(int passes) {
             write16le(p, aux.writes[writesIdx++]);
             break;
           case R_RISCV_JAL:
-              skip = 4;
-              write32le(p, aux.writes[writesIdx++]);
+            skip = 4;
+            write32le(p, aux.writes[writesIdx++]);
             break;
           case R_RISCV_64:
             if (config->riscvTbljal &&
@@ -903,8 +903,8 @@ void elf::riscvFinalizeRelax(int passes) {
               skip = 2;
               write16le(p, aux.writes[writesIdx++]);
             } else {
-              // Used by relaxTlsLe to write a uint32_t then suppress the handling
-              // in relocateAlloc.
+              // Used by relaxTlsLe to write a uint32_t then suppress the
+              // handling in relocateAlloc.
               skip = 4;
               write32le(p, aux.writes[writesIdx++]);
               aux.relocTypes[i] = R_RISCV_NONE;

>From 51b7fd322f2c50c5539157b74647f61d0030a9dc Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Jan 2023 11:06:25 +0800
Subject: [PATCH 23/46] move TableJumpSection to Arch/RISCV.cpp

---
 lld/ELF/Arch/RISCV.cpp        | 156 +++++++++++++++++++++++++++++++++-
 lld/ELF/SyntheticSections.cpp | 155 ---------------------------------
 lld/ELF/SyntheticSections.h   |   1 -
 3 files changed, 155 insertions(+), 157 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 03f76387abb5b4e..402af4372808fce 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -614,7 +614,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
     return false;
 
   const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
-  const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
+  const uint8_t rd = extractBits(jalr,11,7);
   int tblEntryIndex = -1;
   if (rd == 0) {
     tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
@@ -1136,3 +1136,157 @@ TargetInfo *elf::getRISCVTargetInfo() {
   static RISCV target;
   return ⌖
 }
+
+TableJumpSection::TableJumpSection()
+    : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
+                       config->wordsize, ".riscv.jvt") {}
+
+void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
+  addEntry(symbol, CMJTEntryCandidates, gain);
+}
+
+int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
+  uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
+  return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
+}
+
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
+  addEntry(symbol, CMJALTEntryCandidates, gain);
+}
+
+int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
+  uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
+  return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
+}
+
+void TableJumpSection::addEntry(
+    const Symbol &symbol,
+    llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
+  if (symbol.file)
+    entriesList[llvm::CachedHashStringRef(
+        symbol.file->mb.getBufferIdentifier().str() + ":" +
+        symbol.getName().str())] += gain;
+  else
+    entriesList[llvm::CachedHashStringRef("<unknown>:" +
+                                          symbol.getName().str())] += gain;
+}
+
+uint32_t TableJumpSection::getEntry(
+    const Symbol &symbol, uint32_t maxSize,
+    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+        &entriesList) {
+  // Prevent adding duplicate entries
+  uint32_t i = 0;
+  llvm::CachedHashStringRef symName =
+      llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
+  ;
+  if (symbol.file)
+    symName =
+        llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
+                                  ":" + symbol.getName().str());
+
+  for (; i < entriesList.size() && i <= maxSize; ++i) {
+    // If this is a duplicate addition, do not add it and return the address
+    // offset of the original entry.
+    if (symName.hash() == entriesList[i].first.hash()) {
+      return i;
+    }
+  }
+  return i;
+}
+
+void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
+  for (auto [i, r] : llvm::enumerate(sec.relocations)) {
+    switch (r.type) {
+    case R_RISCV_JAL:
+    case R_RISCV_CALL:
+    case R_RISCV_CALL_PLT: {
+      int gain = 6;
+      if (r.type == R_RISCV_JAL)
+        gain = 2;
+
+      const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
+      const uint8_t rd = extractBits(jalr,11,7);
+
+      if (rd == 0)
+        in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
+      else if (rd == 1)
+        in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
+    }
+    }
+  }
+}
+
+void TableJumpSection::finalizeContents() {
+  if (isFinalized)
+    return;
+  isFinalized = true;
+
+  auto cmp =
+      [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
+         const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
+        return p1.second > p2.second;
+      };
+
+  std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
+            std::back_inserter(finalizedCMJTEntries));
+  std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
+
+  std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
+            std::back_inserter(finalizedCMJALTEntries));
+  std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
+}
+
+size_t TableJumpSection::getSize() const {
+  if (!CMJALTEntryCandidates.empty()) {
+    return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
+  }
+  return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
+}
+
+void TableJumpSection::writeTo(uint8_t *buf) {
+  target->writeTableJumpHeader(buf);
+  writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
+  padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
+           startCMJALTEntryIdx * xlen);
+  writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+}
+
+void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
+  for (size_t i = 0; i < address; ++i) {
+    if (config->is64)
+      write64le(buf, 0);
+    else
+      write32le(buf, 0);
+  }
+}
+
+void TableJumpSection::writeEntries(
+    uint8_t *buf,
+    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+        &entriesList) {
+  for (const auto &symbolName : entriesList) {
+    if (symbolName.second == 0)
+      continue;
+    // Use the symbol from in.symTab to ensure we have the final adjusted
+    // symbol.
+    for (const auto &symbol : in.symTab->getSymbols()) {
+      llvm::CachedHashStringRef sym =
+          llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
+      ;
+      if (symbol.sym->file)
+        sym = llvm::CachedHashStringRef(
+            symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
+            symbol.sym->getName().str());
+
+      if (sym.hash() != symbolName.first.hash())
+        continue;
+      // Only process defined symbols.
+      auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
+      if (!definedSymbol)
+        continue;
+      target->writeTableJump(buf, definedSymbol->getVA());
+      buf += config->wordsize;
+    }
+  }
+}
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index f8a8b67b481c81a..2755ad85bf2645a 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1170,161 +1170,6 @@ bool GotPltSection::isNeeded() const {
   return !entries.empty() || hasGotPltOffRel;
 }
 
-TableJumpSection::TableJumpSection()
-    : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
-                       config->wordsize, ".riscv.jvt") {}
-
-void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
-  addEntry(symbol, CMJTEntryCandidates, gain);
-}
-
-int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
-  uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
-  return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
-}
-
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
-  addEntry(symbol, CMJALTEntryCandidates, gain);
-}
-
-int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
-  uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
-  return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
-}
-
-void TableJumpSection::addEntry(
-    const Symbol &symbol,
-    llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
-  if (symbol.file)
-    entriesList[llvm::CachedHashStringRef(
-        symbol.file->mb.getBufferIdentifier().str() + ":" +
-        symbol.getName().str())] += gain;
-  else
-    entriesList[llvm::CachedHashStringRef("<unknown>:" +
-                                          symbol.getName().str())] += gain;
-}
-
-uint32_t TableJumpSection::getEntry(
-    const Symbol &symbol, uint32_t maxSize,
-    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
-        &entriesList) {
-  // Prevent adding duplicate entries
-  uint32_t i = 0;
-  llvm::CachedHashStringRef symName =
-      llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
-  ;
-  if (symbol.file)
-    symName =
-        llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
-                                  ":" + symbol.getName().str());
-
-  for (; i < entriesList.size() && i <= maxSize; ++i) {
-    // If this is a duplicate addition, do not add it and return the address
-    // offset of the original entry.
-    if (symName.hash() == entriesList[i].first.hash()) {
-      return i;
-    }
-  }
-  return i;
-}
-
-void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
-  for (auto [i, r] : llvm::enumerate(sec.relocations)) {
-    switch (r.type) {
-    case R_RISCV_JAL:
-    case R_RISCV_CALL:
-    case R_RISCV_CALL_PLT: {
-      int gain = 6;
-      if (r.type == R_RISCV_JAL)
-        gain = 2;
-
-      const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
-      const uint8_t rd = (jalr & ((1ULL << (11 + 1)) - 1)) >> 7;
-      if (rd == 0)
-        in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
-      else if (rd == 1)
-        in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
-    }
-    }
-  }
-}
-
-void TableJumpSection::finalizeContents() {
-  if (isFinalized)
-    return;
-  isFinalized = true;
-
-  auto cmp =
-      [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
-         const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
-        return p1.second > p2.second;
-      };
-
-  std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
-            std::back_inserter(finalizedCMJTEntries));
-  std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
-
-  std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
-            std::back_inserter(finalizedCMJALTEntries));
-  std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
-}
-
-size_t TableJumpSection::getSize() const {
-  if (!CMJALTEntryCandidates.empty()) {
-    return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
-  }
-  return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
-}
-
-void TableJumpSection::writeTo(uint8_t *buf) {
-  target->writeTableJumpHeader(buf);
-  writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
-  padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
-           startCMJALTEntryIdx * xlen);
-  writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
-}
-
-void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
-  for (size_t i = 0; i < address; ++i) {
-    if (config->is64)
-      write64le(buf, 0);
-    else
-      write32le(buf, 0);
-  }
-}
-
-void TableJumpSection::writeEntries(
-    uint8_t *buf,
-    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
-        &entriesList) {
-  for (const auto &symbolName : entriesList) {
-    if (symbolName.second == 0)
-      continue;
-    // Use the symbol from in.symTab to ensure we have the final adjusted
-    // symbol.
-    for (const auto &symbol : in.symTab->getSymbols()) {
-      llvm::CachedHashStringRef sym =
-          llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
-      ;
-      if (symbol.sym->file)
-        sym = llvm::CachedHashStringRef(
-            symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
-            symbol.sym->getName().str());
-
-      if (sym.hash() != symbolName.first.hash())
-        continue;
-      // Only process defined symbols.
-      auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
-      if (!definedSymbol)
-        continue;
-      target->writeTableJump(buf, definedSymbol->getVA());
-      buf += config->wordsize;
-    }
-  }
-}
-
-bool TableJumpSection::isNeeded() const { return config->riscvTbljal; }
-
 static StringRef getIgotPltName() {
   // On ARM the IgotPltSection is part of the GotSection.
   if (config->emachine == EM_ARM)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index c507e1970995116..b78fc626b062256 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -373,7 +373,6 @@ class TableJumpSection final : public SyntheticSection {
   TableJumpSection();
   size_t getSize() const override;
   void writeTo(uint8_t *buf) override;
-  bool isNeeded() const override;
   void finalizeContents() override;
 
   void addCMJTEntryCandidate(const Symbol &symbol, int gain);

>From 5aff069bee31a05891f65828532c2ea2eb3b5537 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Jan 2023 11:06:59 +0800
Subject: [PATCH 24/46] format

---
 lld/ELF/Arch/RISCV.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 402af4372808fce..7def22161ff7ce1 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -614,7 +614,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
     return false;
 
   const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
-  const uint8_t rd = extractBits(jalr,11,7);
+  const uint8_t rd = extractBits(jalr, 11, 7);
   int tblEntryIndex = -1;
   if (rd == 0) {
     tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
@@ -1206,7 +1206,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
         gain = 2;
 
       const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
-      const uint8_t rd = extractBits(jalr,11,7);
+      const uint8_t rd = extractBits(jalr, 11, 7);
 
       if (rd == 0)
         in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);

>From 51be21513e187c3d2a39a4608dd54e40715b7115 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 24 Mar 2023 17:41:39 +0800
Subject: [PATCH 25/46] stop relax to cm.jalt if it has negative

---
 lld/ELF/Arch/RISCV.cpp           | 126 ++++++++++++++++++++++---------
 lld/ELF/SyntheticSections.h      |   9 +--
 lld/ELF/Writer.cpp               |   1 -
 lld/test/ELF/riscv-tbljal-call.s | 125 ++++++++++++++----------------
 lld/test/ELF/riscv-tbljal-syms.s |  10 +--
 5 files changed, 154 insertions(+), 117 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 7def22161ff7ce1..7de98f5affae446 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1147,7 +1147,7 @@ void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
 
 int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
   uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
-  return index < maxCMJTEntrySize ? (int)(startCMJTEntryIdx + index) : -1;
+  return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index) : -1;
 }
 
 void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
@@ -1156,7 +1156,7 @@ void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
 
 int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
   uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
-  return index < maxCMJALTEntrySize ? (int)(startCMJALTEntryIdx + index) : -1;
+  return index < finalizedCMJALTEntries.size() ? (int)(startCMJALTEntryIdx + index) : -1;
 }
 
 void TableJumpSection::addEntry(
@@ -1179,13 +1179,12 @@ uint32_t TableJumpSection::getEntry(
   uint32_t i = 0;
   llvm::CachedHashStringRef symName =
       llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
-  ;
   if (symbol.file)
     symName =
         llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
                                   ":" + symbol.getName().str());
 
-  for (; i < entriesList.size() && i <= maxSize; ++i) {
+  for (; i < entriesList.size() && i <= maxSize; i++) {
     // If this is a duplicate addition, do not add it and return the address
     // offset of the original entry.
     if (symName.hash() == entriesList[i].first.hash()) {
@@ -1197,20 +1196,28 @@ uint32_t TableJumpSection::getEntry(
 
 void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
   for (auto [i, r] : llvm::enumerate(sec.relocations)) {
+    Defined *definedSymbol = dyn_cast<Defined>(r.sym);
+    if (!definedSymbol)
+      continue;
+    if (i + 1 == sec.relocs().size() ||
+        sec.relocs()[i + 1].type != R_RISCV_RELAX)
+        continue;
     switch (r.type) {
     case R_RISCV_JAL:
     case R_RISCV_CALL:
     case R_RISCV_CALL_PLT: {
-      int gain = 6;
-      if (r.type == R_RISCV_JAL)
-        gain = 2;
-
       const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
       const uint8_t rd = extractBits(jalr, 11, 7);
 
+      int gain = 6;
+      if (sec.relaxAux->relocTypes[i] == R_RISCV_RVC_JUMP)
+        continue;
+      else if (sec.relaxAux->relocTypes[i] == R_RISCV_JAL)
+        gain = 2;
+
       if (rd == 0)
         in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
-      else if (rd == 1)
+      else if (rd == X_RA)
         in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
     }
     }
@@ -1222,38 +1229,80 @@ void TableJumpSection::finalizeContents() {
     return;
   isFinalized = true;
 
-  auto cmp =
+  finalizedCMJTEntries = finalizeEntry(CMJTEntryCandidates, maxCMJTEntrySize);
+  finalizedCMJALTEntries = finalizeEntry(CMJALTEntryCandidates, maxCMJALTEntrySize);
+  CMJTEntryCandidates.clear();
+  CMJALTEntryCandidates.clear();
+
+  if (finalizedCMJALTEntries.size() > 0){
+    int gainRequired = maxCMJTEntrySize * config->wordsize;
+    for (auto entry : finalizedCMJTEntries){
+      gainRequired -= entry.second;
+    }
+    if(gainRequired > 0){
+      for (auto entry : finalizedCMJALTEntries){
+        gainRequired -= (entry.second - config->wordsize) ;
+        if(gainRequired <= 0)
+          break;
+      }
+    }
+
+    // Stop relax to cm.jalt if there will be negative effect
+    if (gainRequired > 0)
+      finalizedCMJALTEntries.clear();
+  }
+}
+
+SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+    TableJumpSection::finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize){
+      auto cmp =
       [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
          const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
         return p1.second > p2.second;
       };
 
-  std::copy(CMJTEntryCandidates.begin(), CMJTEntryCandidates.end(),
-            std::back_inserter(finalizedCMJTEntries));
-  std::sort(finalizedCMJTEntries.begin(), finalizedCMJTEntries.end(), cmp);
-
-  std::copy(CMJALTEntryCandidates.begin(), CMJALTEntryCandidates.end(),
-            std::back_inserter(finalizedCMJALTEntries));
-  std::sort(finalizedCMJALTEntries.begin(), finalizedCMJALTEntries.end(), cmp);
+      SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> tempEntryVector;
+      std::copy(EntryMap.begin(), EntryMap.end(),
+                std::back_inserter(tempEntryVector));
+      std::sort(tempEntryVector.begin(), tempEntryVector.end(), cmp);
+
+      auto finalizedVector = tempEntryVector;
+      if (tempEntryVector.size() >= maxSize)
+        finalizedVector = SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>(tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
+
+      // drop the item which has negitive effect
+      while (finalizedVector.size()){
+        if (finalizedVector.rbegin()->second < config->wordsize)
+          finalizedVector.pop_back();
+        else
+          break;
+      }
+      return finalizedVector;
 }
 
 size_t TableJumpSection::getSize() const {
-  if (!CMJALTEntryCandidates.empty()) {
-    return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * xlen;
+  if (isFinalized){
+    if (!finalizedCMJALTEntries.empty())
+      return (startCMJALTEntryIdx + finalizedCMJALTEntries.size()) * config->wordsize;
+    return (startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize;
+  }
+  else{
+    if (!CMJALTEntryCandidates.empty())
+      return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * config->wordsize;
+    return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * config->wordsize;
   }
-  return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * xlen;
 }
 
 void TableJumpSection::writeTo(uint8_t *buf) {
   target->writeTableJumpHeader(buf);
-  writeEntries(buf + startCMJTEntryIdx, finalizedCMJTEntries);
-  padUntil(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * xlen),
-           startCMJALTEntryIdx * xlen);
-  writeEntries(buf + startCMJALTEntryIdx, finalizedCMJALTEntries);
+  writeEntries(buf + startCMJTEntryIdx * config->wordsize, finalizedCMJTEntries);
+  padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize),
+           startCMJALTEntryIdx);
+  writeEntries(buf + (startCMJALTEntryIdx * config->wordsize), finalizedCMJALTEntries);
 }
 
-void TableJumpSection::padUntil(uint8_t *buf, const uint8_t address) {
-  for (size_t i = 0; i < address; ++i) {
+void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
+  for (size_t i = 0; i < maxWordCount; ++i) {
     if (config->is64)
       write64le(buf, 0);
     else
@@ -1270,23 +1319,26 @@ void TableJumpSection::writeEntries(
       continue;
     // Use the symbol from in.symTab to ensure we have the final adjusted
     // symbol.
+    Defined *definedSymbol;
     for (const auto &symbol : in.symTab->getSymbols()) {
-      llvm::CachedHashStringRef sym =
-          llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
-      ;
+      llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
       if (symbol.sym->file)
         sym = llvm::CachedHashStringRef(
             symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
             symbol.sym->getName().str());
 
-      if (sym.hash() != symbolName.first.hash())
-        continue;
-      // Only process defined symbols.
-      auto *definedSymbol = dyn_cast<Defined>(symbol.sym);
-      if (!definedSymbol)
-        continue;
-      target->writeTableJump(buf, definedSymbol->getVA());
-      buf += config->wordsize;
+      if (sym.hash() == symbolName.first.hash()){
+        definedSymbol = dyn_cast<Defined>(symbol.sym);
+        // Only process defined symbols.
+        if (!definedSymbol)
+          continue;
+
+        break;
+      }
     }
+    if (!definedSymbol)
+      continue;
+    target->writeTableJump(buf, definedSymbol->getVA());
+    buf += config->wordsize;
   }
 }
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index b78fc626b062256..04e4a3d9984559b 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -383,10 +383,9 @@ class TableJumpSection final : public SyntheticSection {
 
   bool isFinalized = false;
 
-protected:
-  uint64_t size = 0;
-
 private:
+  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+      finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize);
   void addEntry(const Symbol &symbol,
                 llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
                 int gain);
@@ -398,9 +397,7 @@ class TableJumpSection final : public SyntheticSection {
       uint8_t *buf,
       SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
           &entriesList);
-  void padUntil(uint8_t *buf, const uint8_t index);
-
-  const size_t xlen = config->is64 ? 64 : 32;
+  void padWords(uint8_t *buf, const uint8_t maxWordCount);
 
   // used in finalizeContents function.
   static const size_t maxCMJTEntrySize = 32;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 3b881a9406452f8..32f73a81c1e2f36 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2182,7 +2182,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     finalizeSynthetic(in.mipsGot.get());
     finalizeSynthetic(in.igotPlt.get());
     finalizeSynthetic(in.gotPlt.get());
-    // finalizeSynthetic(in.riscvTableJumpSection.get());
     finalizeSynthetic(in.relaIplt.get());
     finalizeSynthetic(in.relaPlt.get());
     finalizeSynthetic(in.plt.get());
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 7e4809b75ad1796..b50aea69562072a 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,87 +4,76 @@
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
 
 # tbljal conversion
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+30 -o %t.rv64
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL %s
-# TBLJAL:      cm.jalt 34
-# TBLJAL-NEXT: cm.jt   2
-# TBLJAL-NEXT: cm.jalt 35
-# TBLJAL-NEXT: cm.jalt 33
-# TBLJAL-NEXT: cm.jalt 33
-# TBLJAL-NEXT: cm.jalt 32
-# TBLJAL-NEXT: cm.jalt 32
-# TBLJAL-NEXT: cm.jalt 32
-# TBLJAL-NEXT: cm.jt   3
-# TBLJAL-NEXT: cm.jt   1
-# TBLJAL-NEXT: cm.jt   1
-# TBLJAL-NEXT: cm.jt   0
-# TBLJAL-NEXT: cm.jt   0
-# TBLJAL-NEXT: cm.jt   0
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
+# TBLJAL32:      cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jalt 32
+# TBLJAL32-NEXT: cm.jt   2
+# TBLJAL32-NEXT: cm.jt   2
+# TBLJAL32-NEXT: cm.jt   1
+# TBLJAL32-NEXT: cm.jt   1
+# TBLJAL32-NEXT: cm.jt   0
+# TBLJAL32-NEXT: cm.jt   0
+# TBLJAL32-NEXT: cm.jt   0
+# TBLJAL32-NEXT: cm.jt   0
 
-# Check the bounds of what would be out of range (for the first call) for other jump types.
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x100000 -o %t-boundary.rv64
-# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv32
-# RUN: ld.lld %t.rv64.o --defsym foo=_start+0x100000 -o %t-oldboundary.rv64
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv32 | FileCheck --check-prefix=BOUNDARY %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-boundary.rv64 | FileCheck --check-prefix=BOUNDARY %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv32 | FileCheck --check-prefix=OLDBOUNDARY %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t-oldboundary.rv64 | FileCheck --check-prefix=OLDBOUNDARY %s
-# OLDBOUNDARY:      auipc  ra, 256
-# OLDBOUNDARY-NEXT: jalr   ra, 0(ra)
-# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo>
-# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_1>
-# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal    ra, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_1>
-# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_2>
-# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
-# OLDBOUNDARY-NEXT: jal    zero, {{.*}} <foo_3>
-# BOUNDARY:      cm.jalt 34
-# BOUNDARY-NEXT: cm.jt   2
-# BOUNDARY-NEXT: cm.jalt 35
-# BOUNDARY-NEXT: cm.jalt 33
-# BOUNDARY-NEXT: cm.jalt 33
-# BOUNDARY-NEXT: cm.jalt 32
-# BOUNDARY-NEXT: cm.jalt 32
-# BOUNDARY-NEXT: cm.jalt 32
-# BOUNDARY-NEXT: cm.jt   3
-# BOUNDARY-NEXT: cm.jt   1
-# BOUNDARY-NEXT: cm.jt   1
-# BOUNDARY-NEXT: cm.jt   0
-# BOUNDARY-NEXT: cm.jt   0
-# BOUNDARY-NEXT: cm.jt   0
+# TBLJAL64:      cm.jt   0
+# TBLJAL64-NEXT: cm.jt   0
+# TBLJAL64-NEXT: cm.jt   0
+# TBLJAL64-NEXT: cm.jt   0
 
-# Check relaxation works across output sections
-#  echo 'SECTIONS { .text 0x100000 : { *(.text) } .foo : ALIGN(8) { foo = .; } }' > %t-cross-section.lds
-#  ld.lld %t.rv32c.o %t-cross-section.lds -o %t-cross-section.rv32
-#  ld.lld %t.rv64c.o %t-cross-section.lds -o %t-cross-section.rv64
 
 .global _start
 .p2align 3
 _start:
   call foo
-  tail foo
-
-  call foo_1
-  call foo_2
-  call foo_2
-  call foo_3
-  call foo_3
-  call foo_3
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  call foo
+  tail foo_1
   tail foo_1
   tail foo_2
   tail foo_2
   tail foo_3
   tail foo_3
   tail foo_3
+  tail foo_3
 
 foo_1:
   nop
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 995cb20857f79ba..781faf3ec7f4dac 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -10,11 +10,11 @@
 # RUN: llvm-readelf -s %t.rv32 | FileCheck %s
 # RUN: llvm-readelf -s %t.rv64 | FileCheck %s
 
-# CHECK: 100000     4 NOTYPE  LOCAL  DEFAULT     1 a
-# CHECK: 100000     6 NOTYPE  LOCAL  DEFAULT     1 b
-# CHECK: 100004     2 NOTYPE  LOCAL  DEFAULT     1 c
-# CHECK: 100004     6 NOTYPE  LOCAL  DEFAULT     1 d
-# CHECK: 100000    10 NOTYPE  GLOBAL DEFAULT     1 _start
+# CHECK: 00100000     4 NOTYPE  LOCAL  DEFAULT     1 a
+# CHECK: 00100000     8 NOTYPE  LOCAL  DEFAULT     1 b
+# CHECK: 00100004     4 NOTYPE  LOCAL  DEFAULT     1 c
+# CHECK: 00100004     8 NOTYPE  LOCAL  DEFAULT     1 d
+# CHECK: 00100000    12 NOTYPE  GLOBAL DEFAULT     1 _start
 
 .global _start
 _start:

>From d3179494122c1c4b85c366e4789c9cdfb84b43d5 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 24 Mar 2023 17:43:24 +0800
Subject: [PATCH 26/46] format

---
 lld/ELF/Arch/RISCV.cpp      | 92 +++++++++++++++++++++----------------
 lld/ELF/SyntheticSections.h |  3 +-
 2 files changed, 55 insertions(+), 40 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 7de98f5affae446..a78ce13518f3a3d 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1147,7 +1147,8 @@ void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
 
 int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
   uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
-  return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index) : -1;
+  return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index)
+                                             : -1;
 }
 
 void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
@@ -1156,7 +1157,9 @@ void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
 
 int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
   uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
-  return index < finalizedCMJALTEntries.size() ? (int)(startCMJALTEntryIdx + index) : -1;
+  return index < finalizedCMJALTEntries.size()
+             ? (int)(startCMJALTEntryIdx + index)
+             : -1;
 }
 
 void TableJumpSection::addEntry(
@@ -1201,7 +1204,7 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
       continue;
     if (i + 1 == sec.relocs().size() ||
         sec.relocs()[i + 1].type != R_RISCV_RELAX)
-        continue;
+      continue;
     switch (r.type) {
     case R_RISCV_JAL:
     case R_RISCV_CALL:
@@ -1230,19 +1233,20 @@ void TableJumpSection::finalizeContents() {
   isFinalized = true;
 
   finalizedCMJTEntries = finalizeEntry(CMJTEntryCandidates, maxCMJTEntrySize);
-  finalizedCMJALTEntries = finalizeEntry(CMJALTEntryCandidates, maxCMJALTEntrySize);
+  finalizedCMJALTEntries =
+      finalizeEntry(CMJALTEntryCandidates, maxCMJALTEntrySize);
   CMJTEntryCandidates.clear();
   CMJALTEntryCandidates.clear();
 
-  if (finalizedCMJALTEntries.size() > 0){
+  if (finalizedCMJALTEntries.size() > 0) {
     int gainRequired = maxCMJTEntrySize * config->wordsize;
-    for (auto entry : finalizedCMJTEntries){
+    for (auto entry : finalizedCMJTEntries) {
       gainRequired -= entry.second;
     }
-    if(gainRequired > 0){
-      for (auto entry : finalizedCMJALTEntries){
-        gainRequired -= (entry.second - config->wordsize) ;
-        if(gainRequired <= 0)
+    if (gainRequired > 0) {
+      for (auto entry : finalizedCMJALTEntries) {
+        gainRequired -= (entry.second - config->wordsize);
+        if (gainRequired <= 0)
           break;
       }
     }
@@ -1254,51 +1258,60 @@ void TableJumpSection::finalizeContents() {
 }
 
 SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
-    TableJumpSection::finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize){
-      auto cmp =
+TableJumpSection::finalizeEntry(
+    llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize) {
+  auto cmp =
       [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
          const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
         return p1.second > p2.second;
       };
 
-      SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0> tempEntryVector;
-      std::copy(EntryMap.begin(), EntryMap.end(),
-                std::back_inserter(tempEntryVector));
-      std::sort(tempEntryVector.begin(), tempEntryVector.end(), cmp);
-
-      auto finalizedVector = tempEntryVector;
-      if (tempEntryVector.size() >= maxSize)
-        finalizedVector = SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>(tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
-
-      // drop the item which has negitive effect
-      while (finalizedVector.size()){
-        if (finalizedVector.rbegin()->second < config->wordsize)
-          finalizedVector.pop_back();
-        else
-          break;
-      }
-      return finalizedVector;
+  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+      tempEntryVector;
+  std::copy(EntryMap.begin(), EntryMap.end(),
+            std::back_inserter(tempEntryVector));
+  std::sort(tempEntryVector.begin(), tempEntryVector.end(), cmp);
+
+  auto finalizedVector = tempEntryVector;
+  if (tempEntryVector.size() >= maxSize)
+    finalizedVector =
+        SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>,
+                    0>(tempEntryVector.begin(),
+                       tempEntryVector.begin() + maxSize);
+
+  // drop the item which has negitive effect
+  while (finalizedVector.size()) {
+    if (finalizedVector.rbegin()->second < config->wordsize)
+      finalizedVector.pop_back();
+    else
+      break;
+  }
+  return finalizedVector;
 }
 
 size_t TableJumpSection::getSize() const {
-  if (isFinalized){
+  if (isFinalized) {
     if (!finalizedCMJALTEntries.empty())
-      return (startCMJALTEntryIdx + finalizedCMJALTEntries.size()) * config->wordsize;
+      return (startCMJALTEntryIdx + finalizedCMJALTEntries.size()) *
+             config->wordsize;
     return (startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize;
-  }
-  else{
+  } else {
     if (!CMJALTEntryCandidates.empty())
-      return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) * config->wordsize;
+      return (startCMJALTEntryIdx + CMJALTEntryCandidates.size()) *
+             config->wordsize;
     return (startCMJTEntryIdx + CMJTEntryCandidates.size()) * config->wordsize;
   }
 }
 
 void TableJumpSection::writeTo(uint8_t *buf) {
   target->writeTableJumpHeader(buf);
-  writeEntries(buf + startCMJTEntryIdx * config->wordsize, finalizedCMJTEntries);
-  padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) * config->wordsize),
+  writeEntries(buf + startCMJTEntryIdx * config->wordsize,
+               finalizedCMJTEntries);
+  padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
+                  config->wordsize),
            startCMJALTEntryIdx);
-  writeEntries(buf + (startCMJALTEntryIdx * config->wordsize), finalizedCMJALTEntries);
+  writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
+               finalizedCMJALTEntries);
 }
 
 void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
@@ -1321,13 +1334,14 @@ void TableJumpSection::writeEntries(
     // symbol.
     Defined *definedSymbol;
     for (const auto &symbol : in.symTab->getSymbols()) {
-      llvm::CachedHashStringRef sym = llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
+      llvm::CachedHashStringRef sym =
+          llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
       if (symbol.sym->file)
         sym = llvm::CachedHashStringRef(
             symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
             symbol.sym->getName().str());
 
-      if (sym.hash() == symbolName.first.hash()){
+      if (sym.hash() == symbolName.first.hash()) {
         definedSymbol = dyn_cast<Defined>(symbol.sym);
         // Only process defined symbols.
         if (!definedSymbol)
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 04e4a3d9984559b..232e39ffa99683f 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -385,7 +385,8 @@ class TableJumpSection final : public SyntheticSection {
 
 private:
   SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
-      finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize);
+  finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap,
+                uint32_t maxSize);
   void addEntry(const Symbol &symbol,
                 llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
                 int gain);

>From 14a988bdbcb59484f9fc0a2b4a8719a0da602da4 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 24 Mar 2023 19:22:53 +0800
Subject: [PATCH 27/46] fix testcase

---
 lld/test/ELF/riscv-tbljal-call.s | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index b50aea69562072a..39ba3521c8aa803 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -32,6 +32,7 @@
 # TBLJAL32-NEXT: cm.jt   2
 # TBLJAL32-NEXT: cm.jt   1
 # TBLJAL32-NEXT: cm.jt   1
+# TBLJAL32-NEXT: cm.jt   1
 # TBLJAL32-NEXT: cm.jt   0
 # TBLJAL32-NEXT: cm.jt   0
 # TBLJAL32-NEXT: cm.jt   0
@@ -70,6 +71,7 @@ _start:
   tail foo_1
   tail foo_2
   tail foo_2
+  tail foo_2
   tail foo_3
   tail foo_3
   tail foo_3

>From 48be3d12af3fc8b04903a38356fb65dc5bc415aa Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 3 Apr 2023 16:06:03 +0800
Subject: [PATCH 28/46] store symbol instade of symbol name

---
 lld/ELF/Arch/RISCV.cpp      | 80 ++++++++++++-------------------------
 lld/ELF/SyntheticSections.h | 30 +++++++-------
 2 files changed, 40 insertions(+), 70 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index a78ce13518f3a3d..0744af755804f45 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -617,9 +617,9 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
   const uint8_t rd = extractBits(jalr, 11, 7);
   int tblEntryIndex = -1;
   if (rd == 0) {
-    tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(*r.sym);
+    tblEntryIndex = in.riscvTableJumpSection->getCMJTEntryIndex(r.sym);
   } else if (rd == X_RA) {
-    tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(*r.sym);
+    tblEntryIndex = in.riscvTableJumpSection->getCMJALTEntryIndex(r.sym);
   }
 
   if (tblEntryIndex >= 0) {
@@ -1141,21 +1141,21 @@ TableJumpSection::TableJumpSection()
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
                        config->wordsize, ".riscv.jvt") {}
 
-void TableJumpSection::addCMJTEntryCandidate(const Symbol &symbol, int gain) {
+void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int gain) {
   addEntry(symbol, CMJTEntryCandidates, gain);
 }
 
-int TableJumpSection::getCMJTEntryIndex(const Symbol &symbol) {
+int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
   uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
   return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index)
                                              : -1;
 }
 
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol &symbol, int gain) {
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int gain) {
   addEntry(symbol, CMJALTEntryCandidates, gain);
 }
 
-int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
+int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
   uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
   return index < finalizedCMJALTEntries.size()
              ? (int)(startCMJALTEntryIdx + index)
@@ -1163,34 +1163,22 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol &symbol) {
 }
 
 void TableJumpSection::addEntry(
-    const Symbol &symbol,
-    llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList, int gain) {
-  if (symbol.file)
-    entriesList[llvm::CachedHashStringRef(
-        symbol.file->mb.getBufferIdentifier().str() + ":" +
-        symbol.getName().str())] += gain;
-  else
-    entriesList[llvm::CachedHashStringRef("<unknown>:" +
-                                          symbol.getName().str())] += gain;
+    const Symbol * symbol,
+    llvm::DenseMap<const Symbol *, int> &entriesList, int gain) {
+  entriesList[symbol] += gain;
 }
 
 uint32_t TableJumpSection::getEntry(
-    const Symbol &symbol, uint32_t maxSize,
-    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+    const Symbol *symbol, uint32_t maxSize,
+    SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
         &entriesList) {
   // Prevent adding duplicate entries
   uint32_t i = 0;
-  llvm::CachedHashStringRef symName =
-      llvm::CachedHashStringRef("<unknown>:" + symbol.getName().str());
-  if (symbol.file)
-    symName =
-        llvm::CachedHashStringRef(symbol.file->mb.getBufferIdentifier().str() +
-                                  ":" + symbol.getName().str());
 
   for (; i < entriesList.size() && i <= maxSize; i++) {
     // If this is a duplicate addition, do not add it and return the address
     // offset of the original entry.
-    if (symName.hash() == entriesList[i].first.hash()) {
+    if (symbol == entriesList[i].first) {
       return i;
     }
   }
@@ -1219,9 +1207,9 @@ void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
         gain = 2;
 
       if (rd == 0)
-        in.riscvTableJumpSection->addCMJTEntryCandidate(*r.sym, gain);
+        in.riscvTableJumpSection->addCMJTEntryCandidate(r.sym, gain);
       else if (rd == X_RA)
-        in.riscvTableJumpSection->addCMJALTEntryCandidate(*r.sym, gain);
+        in.riscvTableJumpSection->addCMJALTEntryCandidate(r.sym, gain);
     }
     }
   }
@@ -1257,16 +1245,16 @@ void TableJumpSection::finalizeContents() {
   }
 }
 
-SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
 TableJumpSection::finalizeEntry(
-    llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap, uint32_t maxSize) {
+    llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize) {
   auto cmp =
-      [](const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p1,
-         const llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int> &p2) {
+      [](const llvm::detail::DenseMapPair<const Symbol *, int> &p1,
+         const llvm::detail::DenseMapPair<const Symbol *, int> &p2) {
         return p1.second > p2.second;
       };
 
-  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+  SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
       tempEntryVector;
   std::copy(EntryMap.begin(), EntryMap.end(),
             std::back_inserter(tempEntryVector));
@@ -1275,7 +1263,7 @@ TableJumpSection::finalizeEntry(
   auto finalizedVector = tempEntryVector;
   if (tempEntryVector.size() >= maxSize)
     finalizedVector =
-        SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>,
+        SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
                     0>(tempEntryVector.begin(),
                        tempEntryVector.begin() + maxSize);
 
@@ -1325,34 +1313,16 @@ void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
 
 void TableJumpSection::writeEntries(
     uint8_t *buf,
-    SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+    SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
         &entriesList) {
-  for (const auto &symbolName : entriesList) {
-    if (symbolName.second == 0)
+  for (const auto &entry : entriesList) {
+    if (entry.second == 0)
       continue;
     // Use the symbol from in.symTab to ensure we have the final adjusted
     // symbol.
-    Defined *definedSymbol;
-    for (const auto &symbol : in.symTab->getSymbols()) {
-      llvm::CachedHashStringRef sym =
-          llvm::CachedHashStringRef("<unknown>:" + symbol.sym->getName().str());
-      if (symbol.sym->file)
-        sym = llvm::CachedHashStringRef(
-            symbol.sym->file->mb.getBufferIdentifier().str() + ":" +
-            symbol.sym->getName().str());
-
-      if (sym.hash() == symbolName.first.hash()) {
-        definedSymbol = dyn_cast<Defined>(symbol.sym);
-        // Only process defined symbols.
-        if (!definedSymbol)
-          continue;
-
-        break;
-      }
-    }
-    if (!definedSymbol)
+    if (!entry.first->isDefined())
       continue;
-    target->writeTableJump(buf, definedSymbol->getVA());
+    target->writeTableJump(buf, entry.first->getVA());
     buf += config->wordsize;
   }
 }
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 232e39ffa99683f..b49576a8982dd89 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -375,28 +375,28 @@ class TableJumpSection final : public SyntheticSection {
   void writeTo(uint8_t *buf) override;
   void finalizeContents() override;
 
-  void addCMJTEntryCandidate(const Symbol &symbol, int gain);
-  int getCMJTEntryIndex(const Symbol &symbol);
-  void addCMJALTEntryCandidate(const Symbol &symbol, int gain);
-  int getCMJALTEntryIndex(const Symbol &symbol);
+  void addCMJTEntryCandidate(const Symbol *symbol, int gain);
+  int getCMJTEntryIndex(const Symbol *symbol);
+  void addCMJALTEntryCandidate(const Symbol *symbol, int gain);
+  int getCMJALTEntryIndex(const Symbol *symbol);
   void scanTableJumpEntrys(const InputSection &sec) const;
 
   bool isFinalized = false;
 
 private:
-  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
-  finalizeEntry(llvm::DenseMap<llvm::CachedHashStringRef, int> EntryMap,
+  SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
+  finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
                 uint32_t maxSize);
-  void addEntry(const Symbol &symbol,
-                llvm::DenseMap<llvm::CachedHashStringRef, int> &entriesList,
+  void addEntry(const Symbol *symbol,
+                llvm::DenseMap<const Symbol *, int> &entriesList,
                 int gain);
   uint32_t getEntry(
-      const Symbol &symbol, uint32_t maxSize,
-      SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+      const Symbol *symbol, uint32_t maxSize,
+      SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
           &entriesList);
   void writeEntries(
       uint8_t *buf,
-      SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+      SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
           &entriesList);
   void padWords(uint8_t *buf, const uint8_t maxWordCount);
 
@@ -407,11 +407,11 @@ class TableJumpSection final : public SyntheticSection {
   static const size_t startCMJTEntryIdx = 0;
   static const size_t startCMJALTEntryIdx = 32;
 
-  llvm::DenseMap<llvm::CachedHashStringRef, int> CMJTEntryCandidates;
-  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+  llvm::DenseMap<const Symbol *, int> CMJTEntryCandidates;
+  SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
       finalizedCMJTEntries;
-  llvm::DenseMap<llvm::CachedHashStringRef, int> CMJALTEntryCandidates;
-  SmallVector<llvm::detail::DenseMapPair<llvm::CachedHashStringRef, int>, 0>
+  llvm::DenseMap<const Symbol *, int> CMJALTEntryCandidates;
+  SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
       finalizedCMJALTEntries;
 };
 

>From f9b6db975b9b0e7375b07be552073ea91ea5abb3 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 4 Apr 2023 10:48:26 +0800
Subject: [PATCH 29/46] format

---
 lld/ELF/Arch/RISCV.cpp      | 22 ++++++++++------------
 lld/ELF/SyntheticSections.h | 20 ++++++++------------
 2 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 0744af755804f45..8bc292d52669238 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1163,8 +1163,8 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
 }
 
 void TableJumpSection::addEntry(
-    const Symbol * symbol,
-    llvm::DenseMap<const Symbol *, int> &entriesList, int gain) {
+    const Symbol *symbol, llvm::DenseMap<const Symbol *, int> &entriesList,
+    int gain) {
   entriesList[symbol] += gain;
 }
 
@@ -1246,13 +1246,12 @@ void TableJumpSection::finalizeContents() {
 }
 
 SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
-TableJumpSection::finalizeEntry(
-    llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize) {
-  auto cmp =
-      [](const llvm::detail::DenseMapPair<const Symbol *, int> &p1,
-         const llvm::detail::DenseMapPair<const Symbol *, int> &p2) {
-        return p1.second > p2.second;
-      };
+TableJumpSection::finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
+                                uint32_t maxSize) {
+  auto cmp = [](const llvm::detail::DenseMapPair<const Symbol *, int> &p1,
+                const llvm::detail::DenseMapPair<const Symbol *, int> &p2) {
+    return p1.second > p2.second;
+  };
 
   SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
       tempEntryVector;
@@ -1263,9 +1262,8 @@ TableJumpSection::finalizeEntry(
   auto finalizedVector = tempEntryVector;
   if (tempEntryVector.size() >= maxSize)
     finalizedVector =
-        SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
-                    0>(tempEntryVector.begin(),
-                       tempEntryVector.begin() + maxSize);
+        SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>(
+            tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
 
   // drop the item which has negitive effect
   while (finalizedVector.size()) {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index b49576a8982dd89..fc3f7e3f63617b8 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -385,19 +385,15 @@ class TableJumpSection final : public SyntheticSection {
 
 private:
   SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
-  finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
-                uint32_t maxSize);
+  finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize);
   void addEntry(const Symbol *symbol,
-                llvm::DenseMap<const Symbol *, int> &entriesList,
-                int gain);
-  uint32_t getEntry(
-      const Symbol *symbol, uint32_t maxSize,
-      SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
-          &entriesList);
-  void writeEntries(
-      uint8_t *buf,
-      SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
-          &entriesList);
+                llvm::DenseMap<const Symbol *, int> &entriesList, int gain);
+  uint32_t getEntry(const Symbol *symbol, uint32_t maxSize,
+                    SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
+                                0> &entriesList);
+  void writeEntries(uint8_t *buf,
+                    SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
+                                0> &entriesList);
   void padWords(uint8_t *buf, const uint8_t maxWordCount);
 
   // used in finalizeContents function.

>From 6f0743050acd60dc529c22e5413bf787a6122a94 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 24 Apr 2023 15:22:53 +0800
Subject: [PATCH 31/46] Revert "extend sizeof InputSection"

This reverts commit 813619411facd893e71c24437668ff1f6e29e9bb.
---
 lld/ELF/InputSection.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index fbaea57bd586b00..0b1002171c745ad 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -407,7 +407,7 @@ class InputSection : public InputSectionBase {
   template <class ELFT> void copyShtGroup(uint8_t *buf);
 };
 
-static_assert(sizeof(InputSection) <= 160, "InputSection is too big");
+static_assert(sizeof(InputSection) <= 152, "InputSection is too big");
 
 class SyntheticSection : public InputSection {
 public:

>From 9c4e5fa703235ebb6415c69d79d187614bb646f8 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 27 Jun 2023 16:51:42 +0800
Subject: [PATCH 32/46] use define instead of magic num

---
 lld/ELF/Arch/RISCV.cpp | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 8bc292d52669238..011171d6c561ad2 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -55,6 +55,8 @@ class RISCV final : public TargetInfo {
 #define INTERNAL_R_RISCV_GPREL_I 256
 #define INTERNAL_R_RISCV_GPREL_S 257
 
+#define INTERNAL_CMJT 0xA002
+
 const uint64_t dtpOffset = 0x800;
 
 enum Op {
@@ -336,12 +338,12 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
 
   switch (rel.type) {
   case R_RISCV_32:
-    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
       return;
     write32le(loc, val);
     return;
   case R_RISCV_64:
-    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == 0xa002)
+    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
       return;
     write64le(loc, val);
     return;
@@ -627,7 +629,7 @@ static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
       sec.relaxAux->relocTypes[i] = R_RISCV_64;
     else
       sec.relaxAux->relocTypes[i] = R_RISCV_32;
-    sec.relaxAux->writes.push_back(0xa002 |
+    sec.relaxAux->writes.push_back(INTERNAL_CMJT |
                                    (tblEntryIndex << 2)); // cm.jt or cm.jalt
     remove = 6;
     return true;
@@ -892,14 +894,14 @@ void elf::riscvFinalizeRelax(int passes) {
             break;
           case R_RISCV_64:
             if (config->riscvTbljal &&
-                (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
+                (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
               skip = 2;
               write16le(p, aux.writes[writesIdx++]);
             }
             break;
           case R_RISCV_32:
             if (config->riscvTbljal &&
-                (aux.writes[writesIdx] & 0xfc03) == 0xa002) {
+                (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
               skip = 2;
               write16le(p, aux.writes[writesIdx++]);
             } else {

>From 29d11b631111e2877cdb11fbf30997d9bcda4d62 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 27 Jun 2023 17:28:20 +0800
Subject: [PATCH 33/46] address comments

---
 lld/ELF/Arch/RISCV.cpp        | 9 ++++-----
 lld/ELF/SyntheticSections.cpp | 1 +
 lld/ELF/SyntheticSections.h   | 2 +-
 lld/ELF/Writer.cpp            | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 011171d6c561ad2..cc4e7dabcffa8f0 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -610,7 +610,7 @@ static void initSymbolAnchors() {
   }
 }
 
-static bool relaxZcmt(const InputSection &sec, size_t i, uint64_t loc,
+static bool relaxTableJump(const InputSection &sec, size_t i, uint64_t loc,
                       Relocation &r, uint32_t &remove) {
   if (!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
     return false;
@@ -657,7 +657,7 @@ static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
     sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
     sec.relaxAux->writes.push_back(0x2001); // c.jal
     remove = 6;
-  } else if (!relaxZcmt(sec, i, loc, r, remove) && isInt<21>(displace)) {
+  } else if (!relaxTableJump(sec, i, loc, r, remove) && isInt<21>(displace)) {
     sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
     sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
     remove = 4;
@@ -759,11 +759,10 @@ static bool relax(InputSection &sec) {
       if (i + 1 != sec.relocs().size() &&
           sec.relocs()[i + 1].type == R_RISCV_RELAX)
         relaxHi20Lo12(sec, i, loc, r, remove);
-
     case R_RISCV_JAL:
       if (i + 1 != sec.relocations.size() &&
           sec.relocations[i + 1].type == R_RISCV_RELAX)
-        relaxZcmt(sec, i, loc, r, remove);
+        relaxTableJump(sec, i, loc, r, remove);
       break;
     }
 
@@ -1187,7 +1186,7 @@ uint32_t TableJumpSection::getEntry(
   return i;
 }
 
-void TableJumpSection::scanTableJumpEntrys(const InputSection &sec) const {
+void TableJumpSection::scanTableJumpEntries(const InputSection &sec) const {
   for (auto [i, r] : llvm::enumerate(sec.relocations)) {
     Defined *definedSymbol = dyn_cast<Defined>(r.sym);
     if (!definedSymbol)
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2755ad85bf2645a..2b32eb3a0fe3558 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -39,6 +39,7 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/TimeProfiler.h"
+#include <cstdlib>
 
 using namespace llvm;
 using namespace llvm::dwarf;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index fc3f7e3f63617b8..34ebfaeee5705e9 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -379,7 +379,7 @@ class TableJumpSection final : public SyntheticSection {
   int getCMJTEntryIndex(const Symbol *symbol);
   void addCMJALTEntryCandidate(const Symbol *symbol, int gain);
   int getCMJALTEntryIndex(const Symbol *symbol);
-  void scanTableJumpEntrys(const InputSection &sec) const;
+  void scanTableJumpEntries(const InputSection &sec) const;
 
   bool isFinalized = false;
 
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 32f73a81c1e2f36..1755980f215a178 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1731,7 +1731,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
         // Jump table.
         if (in.riscvTableJumpSection) {
           for (InputSectionBase *inputSection : ctx.inputSections) {
-            in.riscvTableJumpSection->scanTableJumpEntrys(
+            in.riscvTableJumpSection->scanTableJumpEntries(
                 cast<InputSection>(*inputSection));
           }
           in.riscvTableJumpSection->finalizeContents();

>From 18d4a8117000d473ef32b51b64e99f3d1bbf6672 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Thu, 7 Sep 2023 08:15:29 +0800
Subject: [PATCH 34/46] use INTERNAL_ relocation type for Zcmt

---
 lld/ELF/Arch/RISCV.cpp | 44 ++++++++++++++++--------------------------
 1 file changed, 17 insertions(+), 27 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index cc4e7dabcffa8f0..167cdb67a6daa1f 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -54,8 +54,7 @@ class RISCV final : public TargetInfo {
 // of the psABI spec.
 #define INTERNAL_R_RISCV_GPREL_I 256
 #define INTERNAL_R_RISCV_GPREL_S 257
-
-#define INTERNAL_CMJT 0xA002
+#define INTERNAL_R_RISCV_TBJAL 258
 
 const uint64_t dtpOffset = 0x800;
 
@@ -338,13 +337,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
 
   switch (rel.type) {
   case R_RISCV_32:
-    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
-      return;
     write32le(loc, val);
     return;
   case R_RISCV_64:
-    if (config->riscvTbljal && (read16le(loc) & 0xfc03) == INTERNAL_CMJT)
-      return;
     write64le(loc, val);
     return;
 
@@ -480,6 +475,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     return;
   }
 
+  case INTERNAL_R_RISCV_TBJAL:
+    return;
+
   case R_RISCV_ADD8:
     *loc += val;
     return;
@@ -625,11 +623,8 @@ static bool relaxTableJump(const InputSection &sec, size_t i, uint64_t loc,
   }
 
   if (tblEntryIndex >= 0) {
-    if (config->is64)
-      sec.relaxAux->relocTypes[i] = R_RISCV_64;
-    else
-      sec.relaxAux->relocTypes[i] = R_RISCV_32;
-    sec.relaxAux->writes.push_back(INTERNAL_CMJT |
+    sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_TBJAL;
+    sec.relaxAux->writes.push_back(0xA002 |
                                    (tblEntryIndex << 2)); // cm.jt or cm.jalt
     remove = 6;
     return true;
@@ -880,6 +875,12 @@ void elf::riscvFinalizeRelax(int passes) {
           case INTERNAL_R_RISCV_GPREL_I:
           case INTERNAL_R_RISCV_GPREL_S:
             break;
+          case INTERNAL_R_RISCV_TBJAL:
+            assert(config->riscvTbljal);
+            assert((aux.writes[writesIdx] & 0xfc03) == 0xA002);
+            skip = 2;
+            write16le(p, aux.writes[writesIdx++]);
+            break;
           case R_RISCV_RELAX:
             // Used by relaxTlsLe to indicate the relocation is ignored.
             break;
@@ -892,24 +893,13 @@ void elf::riscvFinalizeRelax(int passes) {
             write32le(p, aux.writes[writesIdx++]);
             break;
           case R_RISCV_64:
-            if (config->riscvTbljal &&
-                (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
-              skip = 2;
-              write16le(p, aux.writes[writesIdx++]);
-            }
             break;
           case R_RISCV_32:
-            if (config->riscvTbljal &&
-                (aux.writes[writesIdx] & 0xfc03) == INTERNAL_CMJT) {
-              skip = 2;
-              write16le(p, aux.writes[writesIdx++]);
-            } else {
-              // Used by relaxTlsLe to write a uint32_t then suppress the
-              // handling in relocateAlloc.
-              skip = 4;
-              write32le(p, aux.writes[writesIdx++]);
-              aux.relocTypes[i] = R_RISCV_NONE;
-            }
+            // Used by relaxTlsLe to write a uint32_t then suppress the
+            // handling in relocateAlloc.
+            skip = 4;
+            write32le(p, aux.writes[writesIdx++]);
+            aux.relocTypes[i] = R_RISCV_NONE;
             break;
           default:
             llvm_unreachable("unsupported type");

>From 565e67986e7d576c3163c30fdaed471b12c69bfa Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Sat, 7 Oct 2023 19:46:18 +0800
Subject: [PATCH 35/46] fix error

---
 lld/ELF/InputSection.h           |  2 +-
 lld/test/ELF/riscv-tbljal-call.s | 12 ++++++------
 lld/test/ELF/riscv-tbljal-syms.s |  4 ++--
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index 0b1002171c745ad..fbaea57bd586b00 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -407,7 +407,7 @@ class InputSection : public InputSectionBase {
   template <class ELFT> void copyShtGroup(uint8_t *buf);
 };
 
-static_assert(sizeof(InputSection) <= 152, "InputSection is too big");
+static_assert(sizeof(InputSection) <= 160, "InputSection is too big");
 
 class SyntheticSection : public InputSection {
 public:
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 39ba3521c8aa803..a04b7223dd20b9f 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -1,13 +1,13 @@
 # REQUIRES: riscv
 
-# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
-# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
 
 # tbljal conversion
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=_start+0x150000 -o %t.rv64
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
-# RUN: llvm-objdump -d -M no-aliases --mattr=+experimental-zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
+# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv64
+# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
+# RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
 # TBLJAL32:      cm.jalt 32
 # TBLJAL32-NEXT: cm.jalt 32
 # TBLJAL32-NEXT: cm.jalt 32
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 781faf3ec7f4dac..24ab515eb349bc8 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -2,8 +2,8 @@
 
 // Check that relaxation correctly adjusts symbol addresses and sizes.
 
-# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv32.o
-# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=+experimental-zcmt %s -o %t.rv64.o
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
 # RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv32.o -o %t.rv32
 # RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv64.o -o %t.rv64
 

>From 1927643ee52be4b52535c81ec19edf5effd73aa7 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 27 Nov 2023 16:55:30 +0800
Subject: [PATCH 36/46] rename getEntry -> getIndex

---
 lld/ELF/Arch/RISCV.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 167cdb67a6daa1f..a3c493cb4c42490 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1137,7 +1137,7 @@ void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int gain) {
 }
 
 int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
-  uint32_t index = getEntry(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
+  uint32_t index = getIndex(symbol, maxCMJTEntrySize, finalizedCMJTEntries);
   return index < finalizedCMJTEntries.size() ? (int)(startCMJTEntryIdx + index)
                                              : -1;
 }
@@ -1147,7 +1147,7 @@ void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int gain) {
 }
 
 int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
-  uint32_t index = getEntry(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
+  uint32_t index = getIndex(symbol, maxCMJALTEntrySize, finalizedCMJALTEntries);
   return index < finalizedCMJALTEntries.size()
              ? (int)(startCMJALTEntryIdx + index)
              : -1;
@@ -1159,7 +1159,7 @@ void TableJumpSection::addEntry(
   entriesList[symbol] += gain;
 }
 
-uint32_t TableJumpSection::getEntry(
+uint32_t TableJumpSection::getIndex(
     const Symbol *symbol, uint32_t maxSize,
     SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
         &entriesList) {

>From ff7981b35809347ce337fbf550e8cef55ac3e85f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Mon, 27 Nov 2023 17:00:46 +0800
Subject: [PATCH 37/46] refactor getIndex

---
 lld/ELF/Arch/RISCV.cpp | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index a3c493cb4c42490..96e4fb64540b748 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1163,17 +1163,18 @@ uint32_t TableJumpSection::getIndex(
     const Symbol *symbol, uint32_t maxSize,
     SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
         &entriesList) {
-  // Prevent adding duplicate entries
-  uint32_t i = 0;
-
-  for (; i < entriesList.size() && i <= maxSize; i++) {
-    // If this is a duplicate addition, do not add it and return the address
-    // offset of the original entry.
-    if (symbol == entriesList[i].first) {
-      return i;
-    }
-  }
-  return i;
+  // Find this symbol in the ordered list of entries if it exists.
+  assert(maxSize >= entriesList.size() &&
+       "Finalized vector of entries exceeds maximum");
+  auto idx = std::find_if(
+    entriesList.begin(), entriesList.end(),
+    [symbol](llvm::detail::DenseMapPair<const Symbol *, int> &e) {
+      return e.first == symbol;
+    });
+
+  if (idx == entriesList.end())
+    return entriesList.size();
+  return idx - entriesList.begin();
 }
 
 void TableJumpSection::scanTableJumpEntries(const InputSection &sec) const {

>From aeb18bc47ff740f0511834293e29b079ebfef9c0 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 28 Nov 2023 09:43:29 +0800
Subject: [PATCH 38/46] address comments

---
 lld/ELF/Arch/RISCV.cpp           | 80 ++++++++++++++++++--------------
 lld/ELF/Options.td               |  2 +-
 lld/ELF/SyntheticSections.h      |  9 ++--
 lld/ELF/Target.h                 |  2 +-
 lld/test/ELF/riscv-tbljal-call.s | 33 +++++++++++++
 5 files changed, 86 insertions(+), 40 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 96e4fb64540b748..f07c6096ca33dae 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -39,7 +39,7 @@ class RISCV final : public TargetInfo {
   void writePlt(uint8_t *buf, const Symbol &sym,
                 uint64_t pltEntryAddr) const override;
   void writeTableJumpHeader(uint8_t *buf) const override;
-  void writeTableJump(uint8_t *buf, const uint64_t symbol) const override;
+  void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const override;
   RelType getDynRel(RelType type) const override;
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
@@ -256,7 +256,7 @@ void RISCV::writeTableJumpHeader(uint8_t *buf) const {
     write32le(buf, mainPart->dynamic->getVA());
 }
 
-void RISCV::writeTableJump(uint8_t *buf, const uint64_t address) const {
+void RISCV::writeTableJumpEntry(uint8_t *buf, const uint64_t address) const {
   if (config->is64)
     write64le(buf, address);
   else
@@ -754,6 +754,7 @@ static bool relax(InputSection &sec) {
       if (i + 1 != sec.relocs().size() &&
           sec.relocs()[i + 1].type == R_RISCV_RELAX)
         relaxHi20Lo12(sec, i, loc, r, remove);
+        break;
     case R_RISCV_JAL:
       if (i + 1 != sec.relocations.size() &&
           sec.relocations[i + 1].type == R_RISCV_RELAX)
@@ -1132,8 +1133,8 @@ TableJumpSection::TableJumpSection()
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
                        config->wordsize, ".riscv.jvt") {}
 
-void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int gain) {
-  addEntry(symbol, CMJTEntryCandidates, gain);
+void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int csReduction) {
+  addEntry(symbol, CMJTEntryCandidates, csReduction);
 }
 
 int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
@@ -1142,8 +1143,8 @@ int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
                                              : -1;
 }
 
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int gain) {
-  addEntry(symbol, CMJALTEntryCandidates, gain);
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int csReduction) {
+  addEntry(symbol, CMJALTEntryCandidates, csReduction);
 }
 
 int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
@@ -1155,8 +1156,8 @@ int TableJumpSection::getCMJALTEntryIndex(const Symbol *symbol) {
 
 void TableJumpSection::addEntry(
     const Symbol *symbol, llvm::DenseMap<const Symbol *, int> &entriesList,
-    int gain) {
-  entriesList[symbol] += gain;
+    int csReduction) {
+  entriesList[symbol] += csReduction;
 }
 
 uint32_t TableJumpSection::getIndex(
@@ -1192,16 +1193,16 @@ void TableJumpSection::scanTableJumpEntries(const InputSection &sec) const {
       const auto jalr = sec.contentMaybeDecompress().data()[r.offset + 4];
       const uint8_t rd = extractBits(jalr, 11, 7);
 
-      int gain = 6;
+      int csReduction = 6;
       if (sec.relaxAux->relocTypes[i] == R_RISCV_RVC_JUMP)
         continue;
       else if (sec.relaxAux->relocTypes[i] == R_RISCV_JAL)
-        gain = 2;
+        csReduction = 2;
 
       if (rd == 0)
-        in.riscvTableJumpSection->addCMJTEntryCandidate(r.sym, gain);
+        in.riscvTableJumpSection->addCMJTEntryCandidate(r.sym, csReduction);
       else if (rd == X_RA)
-        in.riscvTableJumpSection->addCMJALTEntryCandidate(r.sym, gain);
+        in.riscvTableJumpSection->addCMJALTEntryCandidate(r.sym, csReduction);
     }
     }
   }
@@ -1218,25 +1219,17 @@ void TableJumpSection::finalizeContents() {
   CMJTEntryCandidates.clear();
   CMJALTEntryCandidates.clear();
 
-  if (finalizedCMJALTEntries.size() > 0) {
-    int gainRequired = maxCMJTEntrySize * config->wordsize;
-    for (auto entry : finalizedCMJTEntries) {
-      gainRequired -= entry.second;
-    }
-    if (gainRequired > 0) {
-      for (auto entry : finalizedCMJALTEntries) {
-        gainRequired -= (entry.second - config->wordsize);
-        if (gainRequired <= 0)
-          break;
-      }
-    }
-
+  if (finalizedCMJALTEntries.size() > 0 && getSizeReduction() <= 0) {
     // Stop relax to cm.jalt if there will be negative effect
-    if (gainRequired > 0)
-      finalizedCMJALTEntries.clear();
+    finalizedCMJALTEntries.clear();
   }
 }
 
+// Sort the map in decreasing order of the amount of code reduction provided
+// by the entries. Drop any entries that can't fit in the map from the tail
+// end since they provide less code reduction. Drop any entries that cause
+// an increase in code size (i.e. the reduction from instruction conversion
+// does not cover the code size gain from adding a table entry).
 SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
 TableJumpSection::finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
                                 uint32_t maxSize) {
@@ -1257,7 +1250,7 @@ TableJumpSection::finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap,
         SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>(
             tempEntryVector.begin(), tempEntryVector.begin() + maxSize);
 
-  // drop the item which has negitive effect
+  // Drop any items that have a negative effect (i.e. increase code size).
   while (finalizedVector.size()) {
     if (finalizedVector.rbegin()->second < config->wordsize)
       finalizedVector.pop_back();
@@ -1281,15 +1274,35 @@ size_t TableJumpSection::getSize() const {
   }
 }
 
+size_t TableJumpSection::getSizeReduction(){
+  // The total reduction in code size is J + JA - JTS - JAE.
+  // Where:
+  // J = number of bytes saved for all the cm.jt instructions emitted
+  // JA = number of bytes saved for all the cm.jalt instructions emitted
+  // JTS = size of the part of the table for cm.jt jumps (i.e. 32 x wordsize)
+  // JAE = number of entries emitted for the cm.jalt jumps x wordsize
+
+  size_t sizeReduction = - getSize();
+  for (auto entry : finalizedCMJTEntries) {
+    sizeReduction += entry.second;
+  }
+  for (auto entry : finalizedCMJALTEntries) {
+    sizeReduction += entry.second;
+  }
+  return sizeReduction;
+}
+
 void TableJumpSection::writeTo(uint8_t *buf) {
   target->writeTableJumpHeader(buf);
   writeEntries(buf + startCMJTEntryIdx * config->wordsize,
                finalizedCMJTEntries);
-  padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
+  if (finalizedCMJALTEntries.size() > 0){
+    padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
                   config->wordsize),
            startCMJALTEntryIdx);
-  writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
-               finalizedCMJALTEntries);
+    writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
+                finalizedCMJALTEntries);
+  }
 }
 
 void TableJumpSection::padWords(uint8_t *buf, const uint8_t maxWordCount) {
@@ -1306,13 +1319,12 @@ void TableJumpSection::writeEntries(
     SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
         &entriesList) {
   for (const auto &entry : entriesList) {
-    if (entry.second == 0)
-      continue;
+    assert (entry.second > 0);
     // Use the symbol from in.symTab to ensure we have the final adjusted
     // symbol.
     if (!entry.first->isDefined())
       continue;
-    target->writeTableJump(buf, entry.first->getVA());
+    target->writeTableJumpEntry(buf, entry.first->getVA());
     buf += config->wordsize;
   }
 }
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 659e37db737cde5..e10462d911ab26d 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -341,7 +341,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
     "Use SHT_RELR / DT_RELR* tags (default)">;
 
 def riscv_tbljal: FF<"riscv-tbljal">,
-  HelpText<"(RISC-V only) Enable table jump instructions from the Zcmt extension">;
+  HelpText<"Enable conversion of call instructions to table jump instruction from the Zcmt extension for frequently called functions (RISC-V only)">;
 
 def pic_veneer: F<"pic-veneer">,
   HelpText<"Always generate position independent thunks (veneers)">;
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 34ebfaeee5705e9..855c85327bf6f07 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -375,9 +375,10 @@ class TableJumpSection final : public SyntheticSection {
   void writeTo(uint8_t *buf) override;
   void finalizeContents() override;
 
-  void addCMJTEntryCandidate(const Symbol *symbol, int gain);
+  size_t getSizeReduction();
+  void addCMJTEntryCandidate(const Symbol *symbol, int csReduction);
   int getCMJTEntryIndex(const Symbol *symbol);
-  void addCMJALTEntryCandidate(const Symbol *symbol, int gain);
+  void addCMJALTEntryCandidate(const Symbol *symbol, int csReduction);
   int getCMJALTEntryIndex(const Symbol *symbol);
   void scanTableJumpEntries(const InputSection &sec) const;
 
@@ -387,8 +388,8 @@ class TableJumpSection final : public SyntheticSection {
   SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
   finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize);
   void addEntry(const Symbol *symbol,
-                llvm::DenseMap<const Symbol *, int> &entriesList, int gain);
-  uint32_t getEntry(const Symbol *symbol, uint32_t maxSize,
+                llvm::DenseMap<const Symbol *, int> &entriesList, int csReduction);
+  uint32_t getIndex(const Symbol *symbol, uint32_t maxSize,
                     SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
                                 0> &entriesList);
   void writeEntries(uint8_t *buf,
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index d34fc73e7914496..8ab409a7472a082 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,7 +37,7 @@ class TargetInfo {
   virtual void writeGotHeader(uint8_t *buf) const {}
   virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
   virtual void writeTableJumpHeader(uint8_t *buf) const {};
-  virtual void writeTableJump(uint8_t *buf, const uint64_t symbol) const {};
+  virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {};
   virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
   virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
   virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index a04b7223dd20b9f..14e71aa315a36a5 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -8,6 +8,11 @@
 # RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
 # RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
+
+# jump table
+# RUN: llvm-objdump -j .riscv.jvt -s %t.rv32 | FileCheck --check-prefix=JUMPTABLE32 %s
+# RUN: llvm-objdump -j .riscv.jvt -s %t.rv64 | FileCheck --check-prefix=JUMPTABLE64 %s
+
 # TBLJAL32:      cm.jalt 32
 # TBLJAL32-NEXT: cm.jalt 32
 # TBLJAL32-NEXT: cm.jalt 32
@@ -44,6 +49,34 @@
 # TBLJAL64-NEXT: cm.jt   0
 
 
+# JUMPTABLE32:      f6100100 f4100100 f2100100 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE32-NEXT: 00001500
+
+# JUMPTABLE64:      68110100 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
+# JUMPTABLE64-NEXT: 00001500 00000000
+
 .global _start
 .p2align 3
 _start:

>From 18f35de91fa161bc321a4deb8a615b143c906c6c Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 28 Nov 2023 10:45:48 +0800
Subject: [PATCH 39/46] fmt

---
 lld/ELF/Arch/RISCV.cpp      | 32 +++++++++++++++++---------------
 lld/ELF/SyntheticSections.h |  3 ++-
 lld/ELF/Target.h            |  3 ++-
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index f07c6096ca33dae..cd9ea653ad12018 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -754,7 +754,7 @@ static bool relax(InputSection &sec) {
       if (i + 1 != sec.relocs().size() &&
           sec.relocs()[i + 1].type == R_RISCV_RELAX)
         relaxHi20Lo12(sec, i, loc, r, remove);
-        break;
+      break;
     case R_RISCV_JAL:
       if (i + 1 != sec.relocations.size() &&
           sec.relocations[i + 1].type == R_RISCV_RELAX)
@@ -1133,7 +1133,8 @@ TableJumpSection::TableJumpSection()
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
                        config->wordsize, ".riscv.jvt") {}
 
-void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol, int csReduction) {
+void TableJumpSection::addCMJTEntryCandidate(const Symbol *symbol,
+                                             int csReduction) {
   addEntry(symbol, CMJTEntryCandidates, csReduction);
 }
 
@@ -1143,7 +1144,8 @@ int TableJumpSection::getCMJTEntryIndex(const Symbol *symbol) {
                                              : -1;
 }
 
-void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol, int csReduction) {
+void TableJumpSection::addCMJALTEntryCandidate(const Symbol *symbol,
+                                               int csReduction) {
   addEntry(symbol, CMJALTEntryCandidates, csReduction);
 }
 
@@ -1166,12 +1168,12 @@ uint32_t TableJumpSection::getIndex(
         &entriesList) {
   // Find this symbol in the ordered list of entries if it exists.
   assert(maxSize >= entriesList.size() &&
-       "Finalized vector of entries exceeds maximum");
+         "Finalized vector of entries exceeds maximum");
   auto idx = std::find_if(
-    entriesList.begin(), entriesList.end(),
-    [symbol](llvm::detail::DenseMapPair<const Symbol *, int> &e) {
-      return e.first == symbol;
-    });
+      entriesList.begin(), entriesList.end(),
+      [symbol](llvm::detail::DenseMapPair<const Symbol *, int> &e) {
+        return e.first == symbol;
+      });
 
   if (idx == entriesList.end())
     return entriesList.size();
@@ -1274,7 +1276,7 @@ size_t TableJumpSection::getSize() const {
   }
 }
 
-size_t TableJumpSection::getSizeReduction(){
+size_t TableJumpSection::getSizeReduction() {
   // The total reduction in code size is J + JA - JTS - JAE.
   // Where:
   // J = number of bytes saved for all the cm.jt instructions emitted
@@ -1282,7 +1284,7 @@ size_t TableJumpSection::getSizeReduction(){
   // JTS = size of the part of the table for cm.jt jumps (i.e. 32 x wordsize)
   // JAE = number of entries emitted for the cm.jalt jumps x wordsize
 
-  size_t sizeReduction = - getSize();
+  size_t sizeReduction = -getSize();
   for (auto entry : finalizedCMJTEntries) {
     sizeReduction += entry.second;
   }
@@ -1296,12 +1298,12 @@ void TableJumpSection::writeTo(uint8_t *buf) {
   target->writeTableJumpHeader(buf);
   writeEntries(buf + startCMJTEntryIdx * config->wordsize,
                finalizedCMJTEntries);
-  if (finalizedCMJALTEntries.size() > 0){
+  if (finalizedCMJALTEntries.size() > 0) {
     padWords(buf + ((startCMJTEntryIdx + finalizedCMJTEntries.size()) *
-                  config->wordsize),
-           startCMJALTEntryIdx);
+                    config->wordsize),
+             startCMJALTEntryIdx);
     writeEntries(buf + (startCMJALTEntryIdx * config->wordsize),
-                finalizedCMJALTEntries);
+                 finalizedCMJALTEntries);
   }
 }
 
@@ -1319,7 +1321,7 @@ void TableJumpSection::writeEntries(
     SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
         &entriesList) {
   for (const auto &entry : entriesList) {
-    assert (entry.second > 0);
+    assert(entry.second > 0);
     // Use the symbol from in.symTab to ensure we have the final adjusted
     // symbol.
     if (!entry.first->isDefined())
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 855c85327bf6f07..dad3b2cc071d9e5 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -388,7 +388,8 @@ class TableJumpSection final : public SyntheticSection {
   SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>, 0>
   finalizeEntry(llvm::DenseMap<const Symbol *, int> EntryMap, uint32_t maxSize);
   void addEntry(const Symbol *symbol,
-                llvm::DenseMap<const Symbol *, int> &entriesList, int csReduction);
+                llvm::DenseMap<const Symbol *, int> &entriesList,
+                int csReduction);
   uint32_t getIndex(const Symbol *symbol, uint32_t maxSize,
                     SmallVector<llvm::detail::DenseMapPair<const Symbol *, int>,
                                 0> &entriesList);
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 8ab409a7472a082..739903ba86b3b5c 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,7 +37,8 @@ class TargetInfo {
   virtual void writeGotHeader(uint8_t *buf) const {}
   virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
   virtual void writeTableJumpHeader(uint8_t *buf) const {};
-  virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {};
+  virtual void writeTableJumpEntry(uint8_t *buf,
+                                   const uint64_t symbol) const {};
   virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
   virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
   virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }

>From 9f59bab283ce73da74c085ecbbb00c15a55b39aa Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Wed, 6 Dec 2023 18:27:15 +0800
Subject: [PATCH 40/46] fix symble of __jvt_base$

---
 lld/ELF/Writer.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 1755980f215a178..d1774c4fad52898 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -506,9 +506,10 @@ template <class ELFT> void elf::createSyntheticSections() {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
     add(*in.riscvTableJumpSection);
 
-    symtab.addSymbol(Defined{
+    Symbol *s = symtab.addSymbol(Defined{
         /*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
         /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
+    s->isUsedInRegularObj = true;
   }
 
   in.gotPlt = std::make_unique<GotPltSection>();

>From 0e48c4381b422448939dd8a992df46682f62896e Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Wed, 6 Dec 2023 19:24:13 +0800
Subject: [PATCH 41/46] add a warning when SizeReduction <= 0

---
 lld/ELF/Writer.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index d1774c4fad52898..608408974c03d96 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1730,14 +1730,12 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
       if (!changed) {
         // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt
         // Jump table.
-        if (in.riscvTableJumpSection) {
-          for (InputSectionBase *inputSection : ctx.inputSections) {
-            in.riscvTableJumpSection->scanTableJumpEntries(
-                cast<InputSection>(*inputSection));
-          }
-          in.riscvTableJumpSection->finalizeContents();
-          changed |= target->relaxOnce(pass);
+        for (InputSectionBase *inputSection : ctx.inputSections) {
+          in.riscvTableJumpSection->scanTableJumpEntries(
+              cast<InputSection>(*inputSection));
         }
+        in.riscvTableJumpSection->finalizeContents();
+        changed |= target->relaxOnce(pass);
       }
     }
 
@@ -1770,6 +1768,9 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   if (!config->relocatable && config->emachine == EM_RISCV)
     riscvFinalizeRelax(pass);
 
+  if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() <= 0)
+    warn("Table Jump Relaxation didn't got any reduction for code size.");
+
   if (config->relocatable)
     for (OutputSection *sec : outputSections)
       sec->addr = 0;

>From e562d319e9715d9f54c13cfa39cf204f80ac2d7f Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 8 Dec 2023 17:12:50 +0800
Subject: [PATCH 42/46] add riscvTableJumpSection only when SizeReduction > 0

---
 lld/ELF/Writer.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 608408974c03d96..865e0340e0c0641 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,15 +502,15 @@ template <class ELFT> void elf::createSyntheticSections() {
     add(*in.ppc64LongBranchTarget);
   }
 
-  if (config->emachine == EM_RISCV && config->riscvTbljal) {
+  if (config->emachine == EM_RISCV && config->riscvTbljal){
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
-    add(*in.riscvTableJumpSection);
 
     Symbol *s = symtab.addSymbol(Defined{
         /*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
         /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
     s->isUsedInRegularObj = true;
   }
+    
 
   in.gotPlt = std::make_unique<GotPltSection>();
   add(*in.gotPlt);
@@ -1768,8 +1768,8 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   if (!config->relocatable && config->emachine == EM_RISCV)
     riscvFinalizeRelax(pass);
 
-  if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() <= 0)
-    warn("Table Jump Relaxation didn't got any reduction for code size.");
+  if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() > 0)
+    ctx.inputSections.push_back(&(*in.riscvTableJumpSection));
 
   if (config->relocatable)
     for (OutputSection *sec : outputSections)

>From 750f493484149f32633b2407dec0b2ac9000a458 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Fri, 8 Dec 2023 17:17:02 +0800
Subject: [PATCH 43/46] fmt

---
 lld/ELF/Writer.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 865e0340e0c0641..fd3b07fb9870214 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,7 +502,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     add(*in.ppc64LongBranchTarget);
   }
 
-  if (config->emachine == EM_RISCV && config->riscvTbljal){
+  if (config->emachine == EM_RISCV && config->riscvTbljal) {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
 
     Symbol *s = symtab.addSymbol(Defined{
@@ -510,7 +510,6 @@ template <class ELFT> void elf::createSyntheticSections() {
         /*value=*/0, /*size=*/0, in.riscvTableJumpSection.get()});
     s->isUsedInRegularObj = true;
   }
-    
 
   in.gotPlt = std::make_unique<GotPltSection>();
   add(*in.gotPlt);

>From 2d5ca0f94a740ffa28e7bf58825311548fafc592 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 16 Jan 2024 14:10:25 +0800
Subject: [PATCH 44/46] format the patch

---
 lld/ELF/Arch/RISCV.cpp | 2 +-
 lld/ELF/Target.h       | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index cd9ea653ad12018..b4c67bcdb7d449c 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -609,7 +609,7 @@ static void initSymbolAnchors() {
 }
 
 static bool relaxTableJump(const InputSection &sec, size_t i, uint64_t loc,
-                      Relocation &r, uint32_t &remove) {
+                           Relocation &r, uint32_t &remove) {
   if (!in.riscvTableJumpSection || !in.riscvTableJumpSection->isFinalized)
     return false;
 
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 739903ba86b3b5c..50215cbdf953b8b 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,8 +37,8 @@ class TargetInfo {
   virtual void writeGotHeader(uint8_t *buf) const {}
   virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
   virtual void writeTableJumpHeader(uint8_t *buf) const {};
-  virtual void writeTableJumpEntry(uint8_t *buf,
-                                   const uint64_t symbol) const {};
+  virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {
+  };
   virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
   virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
   virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }

>From f0be958ea3ff6613ae580630e881206e731c7ee1 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Tue, 16 Jan 2024 14:21:03 +0800
Subject: [PATCH 45/46] format patch again

---
 lld/ELF/Target.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 50215cbdf953b8b..739903ba86b3b5c 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -37,8 +37,8 @@ class TargetInfo {
   virtual void writeGotHeader(uint8_t *buf) const {}
   virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
   virtual void writeTableJumpHeader(uint8_t *buf) const {};
-  virtual void writeTableJumpEntry(uint8_t *buf, const uint64_t symbol) const {
-  };
+  virtual void writeTableJumpEntry(uint8_t *buf,
+                                   const uint64_t symbol) const {};
   virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
   virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
   virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }

>From f69a0a0b2b9a9eaa3e5726d8d07818180ae72785 Mon Sep 17 00:00:00 2001
From: WuXinlong <821408745 at qq.com>
Date: Thu, 25 Jan 2024 20:23:30 +0800
Subject: [PATCH 46/46] rename riscv-tbljal -> relax-tbljal, use int32_t to
 allow negative effect

---
 lld/ELF/Arch/RISCV.cpp              | 17 ++++++++----
 lld/ELF/Config.h                    |  2 +-
 lld/ELF/Driver.cpp                  |  2 +-
 lld/ELF/Options.td                  |  2 +-
 lld/ELF/SyntheticSections.h         |  2 +-
 lld/ELF/Writer.cpp                  |  8 +++---
 lld/test/ELF/riscv-no-tbljal-call.s | 33 +++++++++++++++++++++++
 lld/test/ELF/riscv-tbljal-call.s    | 42 ++++++++++++-----------------
 lld/test/ELF/riscv-tbljal-syms.s    |  4 +--
 9 files changed, 71 insertions(+), 41 deletions(-)
 create mode 100644 lld/test/ELF/riscv-no-tbljal-call.s

diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index b4c67bcdb7d449c..56b626c13373dbe 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -877,7 +877,7 @@ void elf::riscvFinalizeRelax(int passes) {
           case INTERNAL_R_RISCV_GPREL_S:
             break;
           case INTERNAL_R_RISCV_TBJAL:
-            assert(config->riscvTbljal);
+            assert(config->relaxTbljal);
             assert((aux.writes[writesIdx] & 0xfc03) == 0xA002);
             skip = 2;
             write16le(p, aux.writes[writesIdx++]);
@@ -896,8 +896,8 @@ void elf::riscvFinalizeRelax(int passes) {
           case R_RISCV_64:
             break;
           case R_RISCV_32:
-            // Used by relaxTlsLe to write a uint32_t then suppress the
-            // handling in relocateAlloc.
+            // Used by relaxTlsLe to write a uint32_t then suppress the handling
+            // in relocateAlloc.
             skip = 4;
             write32le(p, aux.writes[writesIdx++]);
             aux.relocTypes[i] = R_RISCV_NONE;
@@ -1225,6 +1225,11 @@ void TableJumpSection::finalizeContents() {
     // Stop relax to cm.jalt if there will be negative effect
     finalizedCMJALTEntries.clear();
   }
+  // if table jump still got negative effect, give up.
+  if (getSizeReduction() <= 0){
+    warn("Table Jump Relaxation didn't got any reduction for code size.");
+    finalizedCMJTEntries.clear();
+  }
 }
 
 // Sort the map in decreasing order of the amount of code reduction provided
@@ -1276,7 +1281,7 @@ size_t TableJumpSection::getSize() const {
   }
 }
 
-size_t TableJumpSection::getSizeReduction() {
+int32_t TableJumpSection::getSizeReduction() {
   // The total reduction in code size is J + JA - JTS - JAE.
   // Where:
   // J = number of bytes saved for all the cm.jt instructions emitted
@@ -1284,7 +1289,7 @@ size_t TableJumpSection::getSizeReduction() {
   // JTS = size of the part of the table for cm.jt jumps (i.e. 32 x wordsize)
   // JAE = number of entries emitted for the cm.jalt jumps x wordsize
 
-  size_t sizeReduction = -getSize();
+  int32_t sizeReduction = -getSize();
   for (auto entry : finalizedCMJTEntries) {
     sizeReduction += entry.second;
   }
@@ -1295,6 +1300,8 @@ size_t TableJumpSection::getSizeReduction() {
 }
 
 void TableJumpSection::writeTo(uint8_t *buf) {
+  if (getSizeReduction() <= 0)
+    return;
   target->writeTableJumpHeader(buf);
   writeEntries(buf + startCMJTEntryIdx * config->wordsize,
                finalizedCMJTEntries);
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 01cb9cbc4fb0d27..66cef438d062294 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -275,7 +275,7 @@ struct Config {
   bool relocatable;
   bool relrGlibc = false;
   bool relrPackDynRelocs = false;
-  bool riscvTbljal;
+  bool relaxTbljal;
   llvm::DenseSet<llvm::StringRef> saveTempsArgs;
   llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
   bool singleRoRx;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 5319261c363a03a..6e088d454e4f4c2 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1443,7 +1443,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->whyExtract = args.getLastArgValue(OPT_why_extract);
   config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
   config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
-  config->riscvTbljal = args.hasArg(OPT_riscv_tbljal);
+  config->relaxTbljal = args.hasArg(OPT_relax_tbljal);
   config->zForceBti = hasZOption(args, "force-bti");
   config->zForceIbt = hasZOption(args, "force-ibt");
   config->zGlobal = hasZOption(args, "global");
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index e10462d911ab26d..48c8d2dd12cd09a 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -340,7 +340,7 @@ defm use_android_relr_tags: BB<"use-android-relr-tags",
     "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
     "Use SHT_RELR / DT_RELR* tags (default)">;
 
-def riscv_tbljal: FF<"riscv-tbljal">,
+def relax_tbljal: FF<"relax-tbljal">,
   HelpText<"Enable conversion of call instructions to table jump instruction from the Zcmt extension for frequently called functions (RISC-V only)">;
 
 def pic_veneer: F<"pic-veneer">,
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index dad3b2cc071d9e5..aa46941a2e1b192 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -375,7 +375,7 @@ class TableJumpSection final : public SyntheticSection {
   void writeTo(uint8_t *buf) override;
   void finalizeContents() override;
 
-  size_t getSizeReduction();
+  int32_t getSizeReduction();
   void addCMJTEntryCandidate(const Symbol *symbol, int csReduction);
   int getCMJTEntryIndex(const Symbol *symbol);
   void addCMJALTEntryCandidate(const Symbol *symbol, int csReduction);
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index fd3b07fb9870214..12c4224246ca61f 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -502,8 +502,9 @@ template <class ELFT> void elf::createSyntheticSections() {
     add(*in.ppc64LongBranchTarget);
   }
 
-  if (config->emachine == EM_RISCV && config->riscvTbljal) {
+  if (config->emachine == EM_RISCV && config->relaxTbljal) {
     in.riscvTableJumpSection = std::make_unique<TableJumpSection>();
+    add(*in.riscvTableJumpSection);
 
     Symbol *s = symtab.addSymbol(Defined{
         /*file=*/nullptr, "__jvt_base$", STB_GLOBAL, STT_NOTYPE, STT_NOTYPE,
@@ -1725,7 +1726,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
         script->assignAddresses();
       changed |= a32p.createFixes();
     }
-    if (config->riscvTbljal) {
+    if (config->relaxTbljal) {
       if (!changed) {
         // scan all R_RISCV_JAL, R_RISCV_CALL/R_RISCV_CALL_PLT for RISCV Zcmt
         // Jump table.
@@ -1767,9 +1768,6 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   if (!config->relocatable && config->emachine == EM_RISCV)
     riscvFinalizeRelax(pass);
 
-  if (config->riscvTbljal && in.riscvTableJumpSection->getSizeReduction() > 0)
-    ctx.inputSections.push_back(&(*in.riscvTableJumpSection));
-
   if (config->relocatable)
     for (OutputSection *sec : outputSections)
       sec->addr = 0;
diff --git a/lld/test/ELF/riscv-no-tbljal-call.s b/lld/test/ELF/riscv-no-tbljal-call.s
new file mode 100644
index 000000000000000..d63362995c586bb
--- /dev/null
+++ b/lld/test/ELF/riscv-no-tbljal-call.s
@@ -0,0 +1,33 @@
+# REQUIRES: riscv
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
+
+# tbljal conversion
+# RUN: ld.lld %t.rv32.o --relax-tbljal --defsym foo=0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --relax-tbljal --defsym foo=0x150000 -o %t.rv64
+
+# jump table
+# RUN: llvm-objdump -h %t.rv32 | FileCheck --check-prefix=JUMPTABLE32 %s
+# RUN: llvm-objdump -h %t.rv64 | FileCheck --check-prefix=JUMPTABLE64 %s
+
+# JUMPTABLE32:  2 .riscv.jvt    00000000 000110d4 TEXT
+# JUMPTABLE64:  2 .riscv.jvt    00000000 0000000000011140 TEXT
+
+.global _start
+.p2align 3
+_start:
+  call foo
+  tail foo_1
+  tail foo_2
+  tail foo_3
+
+foo_1:
+  nop
+
+foo_2:
+  nop
+
+foo_3:
+  nop
+
diff --git a/lld/test/ELF/riscv-tbljal-call.s b/lld/test/ELF/riscv-tbljal-call.s
index 14e71aa315a36a5..cfb56baa564a9f4 100644
--- a/lld/test/ELF/riscv-tbljal-call.s
+++ b/lld/test/ELF/riscv-tbljal-call.s
@@ -4,8 +4,8 @@
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
 
 # tbljal conversion
-# RUN: ld.lld %t.rv32.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv32
-# RUN: ld.lld %t.rv64.o --riscv-tbljal --defsym foo=0x150000 -o %t.rv64
+# RUN: ld.lld %t.rv32.o --relax-tbljal --defsym foo=0x150000 -o %t.rv32
+# RUN: ld.lld %t.rv64.o --relax-tbljal --defsym foo=0x150000 -o %t.rv64
 # RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv32 | FileCheck --check-prefix=TBLJAL32 %s
 # RUN: llvm-objdump -d -M no-aliases --mattr=zcmt --no-show-raw-insn %t.rv64 | FileCheck --check-prefix=TBLJAL64 %s
 
@@ -33,23 +33,30 @@
 # TBLJAL32-NEXT: cm.jalt 32
 # TBLJAL32-NEXT: cm.jalt 32
 # TBLJAL32-NEXT: cm.jalt 32
-# TBLJAL32-NEXT: cm.jt   2
-# TBLJAL32-NEXT: cm.jt   2
 # TBLJAL32-NEXT: cm.jt   1
 # TBLJAL32-NEXT: cm.jt   1
 # TBLJAL32-NEXT: cm.jt   1
+# TBLJAL32-NEXT: cm.jt   1
+# TBLJAL32-NEXT: cm.jt   0
+# TBLJAL32-NEXT: jal     zero, 0x110f8
 # TBLJAL32-NEXT: cm.jt   0
 # TBLJAL32-NEXT: cm.jt   0
 # TBLJAL32-NEXT: cm.jt   0
 # TBLJAL32-NEXT: cm.jt   0
 
-# TBLJAL64:      cm.jt   0
+# TBLJAL64:      cm.jt   1
+# TBLJAL64-NEXT: cm.jt   1
+# TBLJAL64-NEXT: cm.jt   1
+# TBLJAL64-NEXT: cm.jt   1
+# TBLJAL64-NEXT: cm.jt   0
+# TBLJAL64-NEXT: jal     zero, 0x111d8
+# TBLJAL64-NEXT: cm.jt   0
 # TBLJAL64-NEXT: cm.jt   0
 # TBLJAL64-NEXT: cm.jt   0
 # TBLJAL64-NEXT: cm.jt   0
 
 
-# JUMPTABLE32:      f6100100 f4100100 f2100100 00000000
+# JUMPTABLE32:      fa100100 f6100100 00000000 00000000
 # JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
 # JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
 # JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
@@ -59,23 +66,7 @@
 # JUMPTABLE32-NEXT: 00000000 00000000 00000000 00000000
 # JUMPTABLE32-NEXT: 00001500
 
-# JUMPTABLE64:      68110100 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00000000 00000000 00000000 00000000
-# JUMPTABLE64-NEXT: 00001500 00000000
+# JUMPTABLE64:      da110100 00000000 d6110100 00000000
 
 .global _start
 .p2align 3
@@ -102,8 +93,9 @@ _start:
   call foo
   tail foo_1
   tail foo_1
-  tail foo_2
-  tail foo_2
+  tail foo_1
+  tail foo_1
+  tail foo_3
   tail foo_2
   tail foo_3
   tail foo_3
diff --git a/lld/test/ELF/riscv-tbljal-syms.s b/lld/test/ELF/riscv-tbljal-syms.s
index 24ab515eb349bc8..c2f355bd74c8b1b 100644
--- a/lld/test/ELF/riscv-tbljal-syms.s
+++ b/lld/test/ELF/riscv-tbljal-syms.s
@@ -4,8 +4,8 @@
 
 # RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax -mattr=zcmt %s -o %t.rv32.o
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax -mattr=zcmt %s -o %t.rv64.o
-# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv32.o -o %t.rv32
-# RUN: ld.lld -Ttext=0x100000 --riscv-tbljal %t.rv64.o -o %t.rv64
+# RUN: ld.lld -Ttext=0x100000 --relax-tbljal %t.rv32.o -o %t.rv32
+# RUN: ld.lld -Ttext=0x100000 --relax-tbljal %t.rv64.o -o %t.rv64
 
 # RUN: llvm-readelf -s %t.rv32 | FileCheck %s
 # RUN: llvm-readelf -s %t.rv64 | FileCheck %s



More information about the llvm-commits mailing list