[clang-tools-extra] [RISCV][LLD] Add RISCV zcmt optimise in linker relaxation (PR #68551)

via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 8 21:09:58 PDT 2023


https://github.com/Xinlong-Wu created https://github.com/llvm/llvm-project/pull/68551

This patch is moved from https://reviews.llvm.org/D134600

This patch implements optimizations for the zcmt extension in lld.

A new TableJumpSectio has been added.

Scans each R_RISCV_CALL/R_RISCV_CALL_PLT relocType in each section before the linker relaxation, recording the name of the symbol.

In finalizeContents the recorded symbol names are sorted in descending order by the number of jumps.

Optimise and insert a new cm.jt/cm.jalt during the relax process. in the process, we reused the`R_RISCV_JAL` relocType

co-author: @ScottEgerton

>From 24d9339ec73516c2b229954665dee2a92182b1ea 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/35] 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 d0d75118e30ddd7..37f9a3ec6aa3f29 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);
@@ -340,6 +359,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;
@@ -606,10 +628,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;
+      }
+    }
   }
 }
 
@@ -828,10 +865,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 6a094c4c0ad8241..d22680885054205 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 6272276e94b2d35..e1d16fcdc16ff70 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 9a23f48350644a0..03fca5ac8b16fbf 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 0f7ebf9d7ba840b..a5baf8a1281455e 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 ce72189015348a4..e6a9de9d0776944 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -454,6 +454,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>();
@@ -1647,6 +1656,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)
@@ -2105,6 +2123,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());
@@ -2900,8 +2919,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 8a2f65e8f681ebb85490acfeaa30c532e5146ddf 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/35] 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 37f9a3ec6aa3f29..e122f37b84a8476 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) {
@@ -359,9 +356,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;
@@ -393,6 +387,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);
 
@@ -643,10 +640,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;
       }
     }
+
   }
 }
 
@@ -865,26 +870,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 c47e4e16acc664504a59eef340f4ed86e769473f 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/35] 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 e122f37b84a8476..e335b1c0f2fbfa6 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -645,13 +645,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;
       }
     }
-
   }
 }
 
@@ -870,16 +871,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 a6c3a74857c11a9beba25bf7f2c6bfbf8812fa22 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/35] 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 a5baf8a1281455e..df61d6def58d58d 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 f2986a0c3d4b899b2d654f88784b468ec7119e3e 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/35] 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 e335b1c0f2fbfa6..de0abb487ce379f 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -387,7 +387,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);
@@ -633,7 +633,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)
@@ -876,7 +876,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 d22680885054205..f686e94aff70c4e 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 e1d16fcdc16ff70..e0bc36050875c0a 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 03fca5ac8b16fbf..2537e0594154430 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 df61d6def58d58d..de46e1b83c2aba4 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 e6a9de9d0776944..e4948bdf227c010 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -454,7 +454,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);
 
@@ -2921,7 +2921,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 8f2c97f6efe091817b691e3a16994d6c87a84f8b 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/35] 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 de46e1b83c2aba4..4d97596a73e83d6 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 7871f6236e3f912f3909bf3a142b4de4c2fdfcc7 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/35] 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 e0bc36050875c0a..ff6270f05b4955f 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 f69ef87621cb108f34ea2b159e3ef2185dc583c8 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/35] 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 4f9c4142353373de1579137bc2347f5e1249b79d 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/35] 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 de0abb487ce379f..6cd5c36a2918511 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -626,33 +626,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 849c5ba437af2b2d46c4ef3f9ee8bae5fcf83a8c 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/35] 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 4d97596a73e83d6..1127f63f2f159ce 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 e4948bdf227c010..30b1bf72736ac8a 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -459,7 +459,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 4d3d304b3ec4cb5cd557983461f0144a40a1fe68 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/35] 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 6cd5c36a2918511..bc5be8afe7bc8af 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -628,9 +628,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 1127f63f2f159ce..18dd7a48915d074 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 8120ff952681b2dbf420d008297a340e413c6f2f 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/35] 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 bc5be8afe7bc8af..1fcb0ad17352943 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -634,8 +634,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 18dd7a48915d074..b04929b02a8201c 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 30b1bf72736ac8a..bde75f28b03ca53 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -458,9 +458,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 6d614b5e486f27dc4aebdf1fdfce269d2ac85f8b 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/35] 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 3f6e94830913c294a919a5a54f94e3bd23ada839 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/35] 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 2537e0594154430..67c9597e8499441 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 b04929b02a8201c..caee0c11589e805 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 e827f97bdcc82d65f1e102de5816cd8f48ed39aa 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/35] 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 1fcb0ad17352943..681792134a12e19 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -605,6 +605,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) {
@@ -625,23 +651,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;
   }
 }
 
@@ -740,6 +753,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 caee0c11589e805..e44371ffbc8675b 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 bde75f28b03ca53..81e269e60d01f56 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -458,7 +458,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()});
@@ -1657,15 +1657,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)
@@ -1690,6 +1681,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)
@@ -2124,7 +2128,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 bb8ff53264234adcf994fa76414b7247c8987729 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/35] 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 abcb62ef43f5d993aa3cb84e988275a62fc56e48 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/35] 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 681792134a12e19..3cd2f3d14409a44 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -611,7 +611,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 e44371ffbc8675b..8d15d7e1caf43a3 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 81e269e60d01f56..f7d76f4b63ad7bf 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -458,7 +458,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()});
@@ -1685,7 +1685,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 0ca415657bce926005f8022ede3270b0e21de918 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/35] 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 3cd2f3d14409a44..4d156e8fdca1ea9 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -605,26 +605,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;
   }
@@ -651,7 +649,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 8d15d7e1caf43a3..28210ba90c69d54 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 f7d76f4b63ad7bf..b023bc27fd5d436 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -458,10 +458,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>();
@@ -1681,9 +1680,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 ce76624700a3b4e2e5b6a35f6f20e78924a9fd3d 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/35] 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 28210ba90c69d54..3d5578ee39d1402 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 a5c34fc3a1ea5897d872d38613a9a6155c1e6e7a 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/35] 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 3d5578ee39d1402..ea6e99c045116c6 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 2931ba97f34c3d489a57c76258f043a0acea86ad 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/35] 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 4d156e8fdca1ea9..47f2ef5cd49899e 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -334,9 +334,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;
 
@@ -387,9 +391,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);
 
@@ -620,7 +621,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;
@@ -881,22 +885,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 67c9597e8499441..2a200ac8bb208a1 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 b023bc27fd5d436..8731f7e5e5b1a57 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2924,11 +2924,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 fbfacad7ff7a13b087f134915341111eacd447f7 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/35] 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 47f2ef5cd49899e..973b52dd492c120 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -621,7 +621,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;
@@ -885,8 +885,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 &&
@@ -901,8 +901,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 919c6f4725910351a89c3efe8e3de49294c7278e 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/35] 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 973b52dd492c120..fdf805cdd2fecfe 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -612,7 +612,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);
@@ -1134,3 +1134,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 ea6e99c045116c6..9f24cf5eedeb4ee 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 fa84e92e0c1ddebc3c23fa833ca01d8b260b5b2e 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/35] 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 fdf805cdd2fecfe..5fd3917333c69a0 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -612,7 +612,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);
@@ -1204,7 +1204,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 269e07576f49be01d193bcce13821b7a22126fe4 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/35] 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 5fd3917333c69a0..af5b815f1f6e5c2 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1145,7 +1145,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) {
@@ -1154,7 +1154,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(
@@ -1177,13 +1177,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()) {
@@ -1195,20 +1194,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);
     }
     }
@@ -1220,38 +1227,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
@@ -1268,23 +1317,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 8731f7e5e5b1a57..be287d7f8749573 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2128,7 +2128,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 e4b586f976dc15f359ca060933563b0fc7222f34 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/35] 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 af5b815f1f6e5c2..5e55538f97dea44 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1145,7 +1145,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) {
@@ -1154,7 +1155,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(
@@ -1199,7 +1202,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:
@@ -1228,19 +1231,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;
       }
     }
@@ -1252,51 +1256,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) {
@@ -1319,13 +1332,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 68f2af93016d1b5641d989a3250b5a81dccaf5b3 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/35] 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 2d98ef69a8ae6c1f34a080401655b52ea7973bfb 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/35] 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 5e55538f97dea44..1c8687760b17e8f 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -615,9 +615,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) {
@@ -1139,21 +1139,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)
@@ -1161,34 +1161,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;
     }
   }
@@ -1217,9 +1205,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);
     }
     }
   }
@@ -1255,16 +1243,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));
@@ -1273,7 +1261,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);
 
@@ -1323,34 +1311,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 33d272df0aab0d5332cdb05ac5549905d0466836 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/35] 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 1c8687760b17e8f..f592b86e3d8e263 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1161,8 +1161,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;
 }
 
@@ -1244,13 +1244,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;
@@ -1261,9 +1260,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 8f1e8342260f43c7d83f5357a32ab8755e98b06c 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/35] 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 2b91711abba3d14..a41f1da17b9ec00 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -404,7 +404,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 3870c704c7bad8ea6cb0518081b62114df92382d 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/35] 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 f592b86e3d8e263..c1c18529db4174a 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 {
@@ -334,12 +336,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;
@@ -625,7 +627,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;
@@ -890,14 +892,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 72fae25fd6996d2810a6c97bfe4d6b7711c1ceb8 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/35] 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 c1c18529db4174a..dd7badd941a0b5e 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -608,7 +608,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;
@@ -655,7 +655,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;
@@ -757,11 +757,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;
     }
 
@@ -1185,7 +1184,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 9f24cf5eedeb4ee..0f7ebf9d7ba840b 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 be287d7f8749573..3f489f3f83bd57a 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1686,7 +1686,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 7b0182ed2b9c28cc8c767ef08be34b9e4cfe7850 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/35] 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 dd7badd941a0b5e..859dcdb10fd8be0 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;
 
@@ -336,13 +335,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;
 
@@ -478,6 +473,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;
@@ -623,11 +621,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;
@@ -878,6 +873,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;
@@ -890,24 +891,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 068f2ce753b4c5524e553d4c710e895ca8a17f17 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/35] 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 a41f1da17b9ec00..2b91711abba3d14 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -404,7 +404,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
 



More information about the cfe-commits mailing list