[llvm-branch-commits] [lld] [lld][LoongArch] Implement TLSDESC GD/LD to IE/LE. (PR #121120)

Zhaoxin Yang via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Dec 25 17:07:04 PST 2024


https://github.com/ylzsx created https://github.com/llvm/llvm-project/pull/121120

Support TLSDESC to initial-exec or local-exec optimizations. Introduce a new hook  RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC and use existing R_RELAX_TLS_GD_TO_IE_ABS to support TLSDESC => IE, while use existing R_RELAX_TLS_GD_TO_LE to support TLSDESC => LE.

Different code models correspond to different TLSDESC code sequences. In normal or medium code model, there are two forms of code sequences:
```
pcalau12i  $a0, %desc_pc_hi20(sym_desc)
addi.d     $a0, $a0, %desc_pc_lo12(sym_desc)
ld.d       $ra, $a0, %desc_ld(sym_desc)
jirl       $ra, $ra, %desc_call(sym_desc)
---
pcaddi     $a0, %desc_pcrel_20(sym_desc)
ld.d       $ra, $a0, %desc_ld(sym_desc)
jirl       $ra, $ra, %desc_call(sym_desc)
```

In extreme code model, there is only one:
```
pcalau12i  $a0, %desc_pc_hi20(sym_desc_large)
addi.d     $a1, $zero, %desc_pc_lo12(sym_desc_large)
lu32i.d    $a1, %desc64_pc_lo20(sym_desc_large)
lu52i.d    $a1, $a1, %desc64_pc_hi12(sym_desc_large)
add.d      $a0, $a0, $a1
ld.d       $ra, $a0, %desc_ld(sym_desc_large)
jirl       $ra, $ra, %desc_call(sym_desc_large)
```

Simplicity, we tend to convert the preceding instructions to NOP in normal or medium code model, due to both forms of code sequence (corresponding to relocation combinations: `R_LARCH_TLS_DESC_PC_HI20+R_LARCH_TLS_DESC_PC_LO12` and `R_LARCH_TLS_DESC_PCREL20_S2`) have same process.

However, for the extreme code model, IE optimization requires a temporary register $a1, which exists in the original preceding code sequence. To avoid additional bookkeeping, in the exterme code model, we convert the last two instructions to NOP. Fortunately, the extreme code model only has one form (donot use `R_LARCH_TLS_DESC_PCREL20_S2` relocation), and it makes this conversion strategy feasible.

>From 30939363f35f367e00bdde74d273c7db9ef76e0b Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Tue, 24 Dec 2024 22:39:15 +0800
Subject: [PATCH 1/2] [lld][LoongArch] Implement TLSDESC GD/LD to IE/LE.

Support TLSDESC to initial-exec or local-exec optimizations.
Introduce a new hook RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC and use
existing R_RELAX_TLS_GD_TO_IE_ABS to support TLSDESC => IE, while use
existing R_RELAX_TLS_GD_TO_LE to support TLSDESC => LE.

Different code models correspond to different TLSDESC code sequences.
In normal or medium code model, there are two forms of code sequences:
```
pcalau12i  $a0, %desc_pc_hi20(sym_desc)
addi.d     $a0, $a0, %desc_pc_lo12(sym_desc)
ld.d       $ra, $a0, %desc_ld(sym_desc)
jirl       $ra, $ra, %desc_call(sym_desc)
---
pcaddi     $a0, %desc_pcrel_20(sym_desc)
ld.d       $ra, $a0, %desc_ld(sym_desc)
jirl       $ra, $ra, %desc_call(sym_desc)
```

In extreme code model, there is only one:
```
pcalau12i  $a0, %desc_pc_hi20(sym_desc_large)
addi.d     $a1, $zero, %desc_pc_lo12(sym_desc_large)
lu32i.d    $a1, %desc64_pc_lo20(sym_desc_large)
lu52i.d    $a1, $a1, %desc64_pc_hi12(sym_desc_large)
add.d      $a0, $a0, $a1
ld.d       $ra, $a0, %desc_ld(sym_desc_large)
jirl       $ra, $ra, %desc_call(sym_desc_large)
```

Simplicity, we tend to convert the preceding instructions to NOP in
normal or medium code model, due to both forms of code sequence
(corresponding to relocation combinations:
`R_LARCH_TLS_DESC_PC_HI20+R_LARCH_TLS_DESC_PC_LO12` and `R_LARCH_TLS_DESC_PCREL20_S2`)
have same process.

However, for the extreme code model, IE optimization requires a
temporary register $a1, which exists in the original preceding code
sequence. To avoid additional bookkeeping, in the exterme code model, we
convert the last two instructions to NOP. Fortunately, the extreme code
model only has one form (donot use `R_LARCH_TLS_DESC_PCREL20_S2` relocation),
and it makes this conversion strategy feasible.
---
 lld/ELF/Arch/LoongArch.cpp | 268 +++++++++++++++++++++++++++++++++++++
 lld/ELF/InputSection.cpp   |   1 +
 lld/ELF/Relocations.cpp    |  21 +--
 lld/ELF/Relocations.h      |   1 +
 4 files changed, 276 insertions(+), 15 deletions(-)

diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 3280c34cb6ed05..6119bda8200a77 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -39,7 +39,15 @@ class LoongArch final : public TargetInfo {
   void relocate(uint8_t *loc, const Relocation &rel,
                 uint64_t val) const override;
   bool relaxOnce(int pass) const override;
+  RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
+  void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
   void finalizeRelax(int passes) const override;
+
+private:
+  void tlsdescToIe(uint8_t *loc, const Relocation &rel, uint64_t val,
+                   bool isExtreme) const;
+  void tlsdescToLe(uint8_t *loc, const Relocation &rel, uint64_t val,
+                   bool isExtreme) const;
 };
 } // end anonymous namespace
 
@@ -53,9 +61,15 @@ enum Op {
   ADDI_W = 0x02800000,
   ADDI_D = 0x02c00000,
   ANDI = 0x03400000,
+  ORI = 0x03800000,
+  LU12I_W = 0x14000000,
+  LU32I_D = 0x16000000,
+  LU52I_D = 0x03000000,
+  PCALAU12I = 0x1a000000,
   PCADDU12I = 0x1c000000,
   LD_W = 0x28800000,
   LD_D = 0x28c00000,
+  LDX_D = 0x380c0000,
   JIRL = 0x4c000000,
 };
 
@@ -63,6 +77,7 @@ enum Reg {
   R_ZERO = 0,
   R_RA = 1,
   R_TP = 2,
+  R_A0 = 4,
   R_T0 = 12,
   R_T1 = 13,
   R_T2 = 14,
@@ -131,6 +146,10 @@ static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
   return begin == 63 ? v >> end : (v & ((1ULL << (begin + 1)) - 1)) >> end;
 }
 
+static uint32_t getD5(uint64_t v) { return extractBits(v, 4, 0); }
+
+static uint32_t getJ5(uint64_t v) { return extractBits(v, 9, 5); }
+
 static uint32_t setD5k16(uint32_t insn, uint32_t imm) {
   uint32_t immLo = extractBits(imm, 15, 0);
   uint32_t immHi = extractBits(imm, 20, 16);
@@ -812,6 +831,255 @@ static bool relax(Ctx &ctx, InputSection &sec) {
   return changed;
 }
 
+// Convert TLSDESC GD/LD to IE.
+// The code sequence obtained in the normal or medium code model is as follows:
+//  * pcalau12i $a0, %ie_pc_hi20(sym_ie)
+//  * ld.[wd]   $a0, $a0, %ie_pc_lo12(sym_ie)
+//
+// The code sequence obtained in the extreme code model is as follows:
+//  * pcalau12i $a0, %ie_pc_hi20(sym_ie_large)
+//  * addi.d    $a1, $r0, %ie_pc_lo12(sym_ie_large)
+//  * lu32i.d   $a1, %ie64_pc_lo20(sym_ie_large)
+//  * lu52i.d   $a1, $a1, %ie64_pc_hi12(sym_ie_large)
+//  * ldx.d     $a0, $a0, $a1
+//
+//  The optimization for tlsdescToIe and tlsdescToLe in the extreme code model
+//  always preserves the preceding code sequence and converts the last
+//  instructions to NOP, while the optimization for the normal or medium code
+//  models of tlsdescToIe and tlsdescToLe do the oppsite. This is because, in
+//  the extreme code model, tlsdescToIe requires a temporary register $a1, and
+//  the preceding unoptimized tls.desc code sequence contains this temporary
+//  register, eliminating additional bookkeeping.
+void LoongArch::tlsdescToIe(uint8_t *loc, const Relocation &rel, uint64_t val,
+                            bool isExtreme) const {
+  if (isExtreme) { // extreme
+    const uint32_t currInsn = read32le(loc);
+    switch (rel.type) {
+    case R_LARCH_TLS_DESC_PC_HI20:
+      write32le(loc, insn(PCALAU12I, R_A0, 0, 0)); // pcalau12i $a0, %ie_pc_hi20
+      relocateNoSym(loc, R_LARCH_TLS_IE_PC_HI20, val);
+      break;
+    case R_LARCH_TLS_DESC_PC_LO12:
+      write32le(loc, insn(ADDI_D, getD5(currInsn), R_ZERO,
+                          0)); // addi.d $a1, $r0, %ie_pc_lo12
+      relocateNoSym(loc, R_LARCH_TLS_IE_PC_LO12, val);
+      break;
+    case R_LARCH_TLS_DESC64_PC_LO20:
+      write32le(loc, insn(LU32I_D, getD5(currInsn), 0,
+                          0)); // lu32i.d $a1, %ie64_pc_lo20
+      relocateNoSym(loc, R_LARCH_TLS_IE64_PC_LO20, val);
+      break;
+    case R_LARCH_TLS_DESC64_PC_HI12:
+      write32le(loc, insn(LU52I_D, getD5(currInsn), getJ5(currInsn),
+                          0)); // lu52i.d $a1, $a1, %ie64_pc_hi12
+      relocateNoSym(loc, R_LARCH_TLS_IE64_PC_HI12, val);
+      write32le(loc + 4, insn(LDX_D, R_A0, R_A0,
+                              getD5(currInsn))); // ldx.d $a0, $a0, $a1
+      break;
+    case R_LARCH_TLS_DESC_LD:
+    case R_LARCH_TLS_DESC_CALL:
+      write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      break;
+    default:
+      llvm_unreachable("unsupported relocation for TLSDESC to IE");
+    }
+  } else { // normal or medium
+    switch (rel.type) {
+    case R_LARCH_TLS_DESC_PC_HI20:
+    case R_LARCH_TLS_DESC_PC_LO12:
+    case R_LARCH_TLS_DESC_PCREL20_S2:
+      write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      break;
+    case R_LARCH_TLS_DESC_LD:
+      write32le(loc, insn(PCALAU12I, R_A0, 0, 0)); // pcalau12i $a0, %ie_pc_hi20
+      relocateNoSym(loc, R_LARCH_TLS_IE_PC_HI20, val);
+      break;
+    case R_LARCH_TLS_DESC_CALL:
+      write32le(loc, insn(ctx.arg.is64 ? LD_D : LD_W, R_A0, R_A0,
+                          0)); // ld.[wd] $a0, $a0, %ie_pc_lo12
+      relocateNoSym(loc, R_LARCH_TLS_IE_PC_LO12, val);
+      break;
+    default:
+      llvm_unreachable("unsupported relocation for TLSDESC to IE");
+    }
+  }
+}
+
+// Convert TLSDESC GD/LD to LE.
+// The code sequence obtained in the normal or medium code model is as follows:
+//  * lu12i.w $a0, %le_hi20(sym_le)  # le_hi20 != 0
+//  * ori $a0 $a0, %le_lo12(sym_le)
+//
+// The code sequence obtained in extreme code model is as follows:
+//  * lu12i.w $a0, %le_hi20(sym_le_large)
+//  * ori     $a0, $a0, %le_lo12(sym_le_large)
+//  * lu32i.d $a0, %le64_lo20(sym_le_large)
+//  * lu52i.d $a0, $a0, %le64_hi20(sym_le_large)
+//
+// Note: In the extreme code model, it is possible for the generated code
+// sequence to include NOPs at both beginning and the end. Likely,
+//  * nop; ori $a0, $r0, %le_lo12; nop; nop
+// This occurs because the four instructions are used to assemble each part of a
+// 64-bit value independently, without affecting each other. Therefore, to
+// obtain an efficient code sequence, NOPs are used as much as possible.
+// Additionally, the extreme code model does not participate in relaxation
+// optimization.
+void LoongArch::tlsdescToLe(uint8_t *loc, const Relocation &rel, uint64_t val,
+                            bool isExtreme) const {
+  if (isExtreme) { // extreme
+    switch (rel.type) {
+    case R_LARCH_TLS_DESC_PC_HI20:
+      if (uint32_t hi20 = extractBits(val, 31, 12))
+        write32le(loc,
+                  insn(LU12I_W, R_A0, hi20, 0)); // lu12i.w $a0, $a0, %le_hi20
+      else
+        write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      break;
+    case R_LARCH_TLS_DESC_PC_LO12:
+      if (extractBits(val, 31, 12))
+        write32le(loc,
+                  insn(ORI, R_A0, R_A0, lo12(val))); // ori $a0, $a0, %le_lo12
+      else
+        write32le(loc,
+                  insn(ORI, R_A0, R_ZERO, lo12(val))); // ori $a0, $r0, %le_lo12
+      break;
+    case R_LARCH_TLS_DESC64_PC_LO20:
+      // If val[31] is 1, lu12i.w will set $a0[51-32]. So, clear it.
+      if (uint32_t lo20 = extractBits(val, 51, 32) || extractBits(val, 31, 31))
+        write32le(loc, insn(LU32I_D, R_A0, lo20, 0)); // lu32i.d $a0, %le64_lo20
+      else
+        write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      break;
+    case R_LARCH_TLS_DESC64_PC_HI12:
+      // If val[31] is 1, lu12i.w will set $a0[63-52]. So, clear it.
+      if (uint32_t hi12 =
+              extractBits(val, 63, 52) || extractBits(val, 31, 31)) {
+        write32le(loc, insn(LU52I_D, R_A0, R_A0,
+                            hi12)); // lu52i.d $a0, $a0, %le64_hi20
+        // Due to add.d does not include relocation, an additional NOP needs to
+        // be generated.
+        write32le(loc + 4, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      } else {
+        write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0));     // nop
+        write32le(loc + 4, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      }
+      break;
+    case R_LARCH_TLS_DESC_LD:
+    case R_LARCH_TLS_DESC_CALL:
+      write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      break;
+    default:
+      llvm_unreachable("unsupported relocation for TLSDESC to LE");
+    }
+  } else { // normal or medium
+    switch (rel.type) {
+    case R_LARCH_TLS_DESC_PC_HI20:
+    case R_LARCH_TLS_DESC_PC_LO12:
+    case R_LARCH_TLS_DESC_PCREL20_S2:
+      write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      break;
+    case R_LARCH_TLS_DESC_LD:
+      if (isUInt<12>(val))
+        write32le(loc, insn(ANDI, R_ZERO, R_ZERO, 0)); // nop
+      else if (isInt<32>(val))
+        write32le(loc, insn(LU12I_W, R_A0, extractBits(val, 31, 12),
+                            0)); // lu12i.w $a0, %le_hi20
+      else
+        Err(ctx) << val
+                 << " exceeds the range of medium code model in tlsdescToLe";
+      break;
+    case R_LARCH_TLS_DESC_CALL:
+      if (isUInt<12>(val))
+        write32le(loc, insn(ORI, R_A0, R_ZERO, val)); // ori $a0, $r0, %le_lo12
+      else if (isInt<32>(val))
+        write32le(loc,
+                  insn(ORI, R_A0, R_A0, lo12(val))); // ori $a0, $a0, %le_lo12
+      else
+        Err(ctx) << val
+                 << " exceeds the range of medium code model in tlsdescToLe";
+      break;
+    default:
+      llvm_unreachable("unsupported relocation for TLSDESC to LE");
+    }
+  }
+}
+
+// During GD_TO_IE, the converted code sequence always includes an instruction
+// related to the Lo12 relocation (ld.[wd] or addi.d). To obtain correct val in
+// `getRelocTargetVA`, expr of this instruction should be adjusted to
+// R_RELAX_TLS_GD_TO_IE_ABS, while expr of other valid instructions (not NOP)
+// should be adjusted to RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC.
+// See the comment in tlsdescToIe for detailed information.
+//
+// Specifically, in the normal or medium code model, the instruction with
+// relocation R_LARCH_TLS_DESC_CALL is the candidate of Lo12 relocation. And in
+// the extreme code model, the instruction with R_LARCH_TLS_DESC_PC_LO12 is the
+// candidate. Meanwhile, in the normal or medium code model, the instruction
+// with R_LARCH_TLS_DESC_PC_LO12 will always be converted to NOP. Similarly, in
+// the extreme code model, the instruction with R_LARCH_TLS_DESC_CALL will be
+// converted to NOP. Therefore, the adjustment of the expr here is safe.
+RelExpr LoongArch::adjustTlsExpr(RelType type, RelExpr expr) const {
+  if (expr == R_RELAX_TLS_GD_TO_IE) {
+    if (type != R_LARCH_TLS_DESC_PC_LO12 && type != R_LARCH_TLS_DESC_CALL)
+      return RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC;
+    return R_RELAX_TLS_GD_TO_IE_ABS;
+  }
+  return expr;
+}
+
+void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+  const unsigned bits = ctx.arg.is64 ? 64 : 32;
+  uint64_t secAddr = sec.getOutputSection()->addr;
+  if (auto *s = dyn_cast<InputSection>(&sec))
+    secAddr += s->outSecOff;
+  else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
+    secAddr += ehIn->getParent()->outSecOff;
+  bool isExtreme = false;
+  const ArrayRef<Relocation> relocs = sec.relocs();
+  for (size_t i = 0, size = relocs.size(); i != size; ++i) {
+    const Relocation &rel = relocs[i];
+    uint8_t *loc = buf + rel.offset;
+    const uint64_t val = SignExtend64(
+        sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), bits);
+
+    switch (rel.expr) {
+    case R_RELAX_HINT:
+      continue;
+    case RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC:
+      if (rel.type == R_LARCH_TLS_DESC_PC_HI20) {
+        // The relocation sequence in the extreme code model is as follows:
+        //
+        //  * i   -- R_LARCH_TLS_DESC_PC_HI20
+        //  * i+1 -- R_LARCH_TLS_DESC_PC_LO12
+        //  * i+2 -- R_LARCH_TLS_DESC64_PC_LO20
+        //  * i+3 -- R_LARCH_TLS_DESC64_PC_HI12
+        isExtreme =
+            (i + 2 < size && relocs[i + 2].type == R_LARCH_TLS_DESC64_PC_LO20);
+      }
+      [[fallthrough]];
+    case R_RELAX_TLS_GD_TO_IE_ABS:
+      tlsdescToIe(loc, rel, val, isExtreme);
+      continue;
+    case R_RELAX_TLS_GD_TO_LE:
+      if (rel.type == R_LARCH_TLS_DESC_PC_HI20) {
+        // The relocation sequence in the extreme code model is as follows:
+        //
+        //  * i   -- R_LARCH_TLS_DESC_PC_HI20
+        //  * i+1 -- R_LARCH_TLS_DESC_PC_LO12
+        //  * i+2 -- R_LARCH_TLS_DESC64_PC_LO20
+        //  * i+3 -- R_LARCH_TLS_DESC64_PC_HI12
+        isExtreme =
+            (i + 2 < size && relocs[i + 2].type == R_LARCH_TLS_DESC64_PC_LO20);
+      }
+      tlsdescToLe(loc, rel, val, isExtreme);
+      continue;
+    default:
+      break;
+    }
+    relocate(loc, rel, val);
+  }
+}
+
 // When relaxing just R_LARCH_ALIGN, relocDeltas is usually changed only once in
 // the absence of a linker script. For call and load/store R_LARCH_RELAX, code
 // shrinkage may reduce displacement and make more relocations eligible for
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index efa7ba3e7cb063..238f64c815df3a 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -825,6 +825,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
   case R_GOTPLT_PC:
     return r.sym->getGotPltVA(ctx) + a - p;
   case RE_LOONGARCH_GOT_PAGE_PC:
+  case RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC:
     if (r.sym->hasFlag(NEEDS_TLSGD))
       return getLoongArchPageDelta(ctx.in.got->getGlobalDynAddr(*r.sym) + a, p,
                                    r.type);
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 77b90172bc1c27..f2af2daa9f5a56 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1316,22 +1316,10 @@ unsigned RelocationScanner::handleTlsRelocation(RelExpr expr, RelType type,
   if (ctx.arg.emachine == EM_MIPS)
     return handleMipsTlsRelocation(ctx, type, sym, *sec, offset, addend, expr);
 
-  // LoongArch does not yet implement transition from TLSDESC to LE/IE, so
-  // generate TLSDESC dynamic relocation for the dynamic linker to handle.
-  if (ctx.arg.emachine == EM_LOONGARCH &&
-      oneof<RE_LOONGARCH_TLSDESC_PAGE_PC, R_TLSDESC, R_TLSDESC_PC,
-            R_TLSDESC_CALL>(expr)) {
-    if (expr != R_TLSDESC_CALL) {
-      sym.setFlags(NEEDS_TLSDESC);
-      sec->addReloc({expr, type, offset, addend, &sym});
-    }
-    return 1;
-  }
-
   bool isRISCV = ctx.arg.emachine == EM_RISCV;
 
   if (oneof<RE_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
-            R_TLSDESC_GOTPLT>(expr) &&
+            R_TLSDESC_GOTPLT, RE_LOONGARCH_TLSDESC_PAGE_PC>(expr) &&
       ctx.arg.shared) {
     // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12_I,CALL} reference a label. Do not
     // set NEEDS_TLSDESC on the label.
@@ -1350,7 +1338,10 @@ unsigned RelocationScanner::handleTlsRelocation(RelExpr expr, RelType type,
   // optimization as well.
   bool execOptimize =
       !ctx.arg.shared && ctx.arg.emachine != EM_ARM &&
-      ctx.arg.emachine != EM_HEXAGON && ctx.arg.emachine != EM_LOONGARCH &&
+      ctx.arg.emachine != EM_HEXAGON &&
+      !(ctx.arg.emachine == EM_LOONGARCH &&
+        expr != RE_LOONGARCH_TLSDESC_PAGE_PC && expr != R_TLSDESC &&
+        expr != R_TLSDESC_PC && expr != R_TLSDESC_CALL) &&
       !(isRISCV && expr != R_TLSDESC_PC && expr != R_TLSDESC_CALL) &&
       !sec->file->ppc64DisableTLSRelax;
 
@@ -1401,7 +1392,7 @@ unsigned RelocationScanner::handleTlsRelocation(RelExpr expr, RelType type,
 
   if (oneof<RE_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
             R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC,
-            RE_LOONGARCH_TLSGD_PAGE_PC>(expr)) {
+            RE_LOONGARCH_TLSGD_PAGE_PC, RE_LOONGARCH_TLSDESC_PAGE_PC>(expr)) {
     if (!execOptimize) {
       sym.setFlags(NEEDS_TLSGD);
       sec->addReloc({expr, type, offset, addend, &sym});
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index fde25a230b72e6..ae0852ea2e9f84 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -128,6 +128,7 @@ enum RelExpr {
   RE_LOONGARCH_GOT,
   RE_LOONGARCH_GOT_PAGE_PC,
   RE_LOONGARCH_TLSGD_PAGE_PC,
+  RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC,
   RE_LOONGARCH_TLSDESC_PAGE_PC,
 };
 

>From 21c9e68ed51661b1370b06be193227fa7e691310 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Wed, 25 Dec 2024 16:29:28 +0800
Subject: [PATCH 2/2] modify tests.

---
 lld/test/ELF/loongarch-tlsdesc-extreme.s    | 156 ++++++++++++++++----
 lld/test/ELF/loongarch-tlsdesc-pcrel20-s2.s |  75 +++++++---
 lld/test/ELF/loongarch-tlsdesc.s            |  83 ++++++++---
 3 files changed, 240 insertions(+), 74 deletions(-)

diff --git a/lld/test/ELF/loongarch-tlsdesc-extreme.s b/lld/test/ELF/loongarch-tlsdesc-extreme.s
index 84427152ba36da..493a8358f5ead2 100644
--- a/lld/test/ELF/loongarch-tlsdesc-extreme.s
+++ b/lld/test/ELF/loongarch-tlsdesc-extreme.s
@@ -11,14 +11,15 @@
 # RUN: ld.lld -shared -z now a.64.o c.64.o -o rel.64.so -z rel
 # RUN: llvm-readobj -r -x .got rel.64.so | FileCheck --check-prefix=GD64-REL %s
 
-## FIXME: The transition frome TLSDESC to IE/LE has not yet been implemented.
-## Keep the dynamic relocations and hand them over to dynamic linker.
+## Transition from TLSDESC to IE/LE.
 
 # RUN: ld.lld -e 0 -z now a.64.o c.64.o -o a.64.le
-# RUN: llvm-readobj -r -x .got a.64.le | FileCheck --check-prefix=LE64-RELA %s
+# RUN: llvm-readelf -r a.64.le | FileCheck --check-prefix=NOREL %s
+# RUN: llvm-objdump --no-show-raw-insn -h -d a.64.le | FileCheck %s --check-prefix=LE64
 
 # RUN: ld.lld -e 0 -z now a.64.o c.64.so -o a.64.ie
 # RUN: llvm-readobj -r -x .got a.64.ie | FileCheck --check-prefix=IE64-RELA %s
+# RUN: llvm-objdump --no-show-raw-insn -h -d a.64.ie | FileCheck %s --check-prefix=IE64
 
 # GD64-RELA:      .rela.dyn {
 # GD64-RELA-NEXT:   0x20568 R_LARCH_TLS_DESC64 - 0x1000
@@ -114,37 +115,132 @@
 # GD64-NEXT:          jirl $ra, $ra, 0
 # GD64-NEXT:          add.d $a6, $a0, $tp
 
-# LE64-RELA:      .rela.dyn {
-# LE64-RELA-NEXT:   0x30318 R_LARCH_TLS_DESC64 - 0x8
-# LE64-RELA-NEXT:   0x30328 R_LARCH_TLS_DESC64 - 0x7FFFFFFF
-# LE64-RELA-NEXT:   0x30338 R_LARCH_TLS_DESC64 - 0x80000000
-# LE64-RELA-NEXT:   0x30348 R_LARCH_TLS_DESC64 - 0x100000000
-# LE64-RELA-NEXT:   0x30358 R_LARCH_TLS_DESC64 - 0x10000000000000
-# LE64-RELA-NEXT:   0x30368 R_LARCH_TLS_DESC64 - 0x1000
-# LE64-RELA-NEXT: }
-# LE64-RELA:      Hex dump of section '.got':
-# LE64-RELA-NEXT: 0x00030318 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030328 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030338 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030348 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030358 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030368 00000000 00000000 00000000 00000000 .
+# NOREL: no relocations
+
+# LE64-LABEL: <.text>:
+## st_value(a) = 8
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 8
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         add.d   $a1, $a0, $tp
+## st_value(b) = 0x1000
+# LE64-NEXT:         lu12i.w $a0, 1
+# LE64-NEXT:         ori     $a0, $a0, 0
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         add.d   $a2, $a0, $tp
+## st_value(c) = 0x7fffffff
+# LE64-NEXT:         lu12i.w $a0, 524287
+# LE64-NEXT:         ori	   $a0, $a0, 4095
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         add.d   $a3, $a0, $tp
+## st_value(d) = 0x8000,0000
+# LE64-NEXT:         lu12i.w $a0, -524288
+# LE64-NEXT:         ori	   $a0, $a0, 0
+# LE64-NEXT:         lu32i.d $a0, 1
+# LE64-NEXT:         lu52i.d $a0, $a0, 1
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         add.d   $a4, $a0, $tp
+## st_value(e) = 0x1,0000,0000
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori	   $a0, $zero, 0
+# LE64-NEXT:         lu32i.d $a0, 1
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         add.d   $a5, $a0, $tp
+## st_value(f) = 0x10,0000,0000,0000
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 0
+# LE64-NEXT:         nop
+# LE64-NEXT:         lu52i.d $a0, $a0, 1
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         add.d   $a6, $a0, $tp
 
 # IE64-RELA:      .rela.dyn {
-# IE64-RELA-NEXT:   0x30508 R_LARCH_TLS_DESC64 - 0x8
-# IE64-RELA-NEXT:   0x30558 R_LARCH_TLS_DESC64 - 0x1000
-# IE64-RELA-NEXT:   0x30518 R_LARCH_TLS_DESC64 c 0x0
-# IE64-RELA-NEXT:   0x30528 R_LARCH_TLS_DESC64 d 0x0
-# IE64-RELA-NEXT:   0x30538 R_LARCH_TLS_DESC64 e 0x0
-# IE64-RELA-NEXT:   0x30548 R_LARCH_TLS_DESC64 f 0x0
+# IE64-RELA-NEXT:   0x304D8 R_LARCH_TLS_TPREL64 c 0x0
+# IE64-RELA-NEXT:   0x304E0 R_LARCH_TLS_TPREL64 d 0x0
+# IE64-RELA-NEXT:   0x304E8 R_LARCH_TLS_TPREL64 e 0x0
+# IE64-RELA-NEXT:   0x304F0 R_LARCH_TLS_TPREL64 f 0x0
 # IE64-RELA-NEXT: }
 # IE64-RELA:      Hex dump of section '.got':
-# IE64-RELA-NEXT: 0x00030508 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030518 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030528 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030538 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030548 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030558 00000000 00000000 00000000 00000000 .
+# IE64-RELA-NEXT: 0x000304d8 00000000 00000000 00000000 00000000 .
+# IE64-RELA-NEXT: 0x000304e8 00000000 00000000 00000000 00000000 .
+
+# IE64:       .got     00000020 00000000000304d8
+
+## a and b are optimized to use LE. c, d, e and f are optimized to IE.
+# IE64-LABEL: <.text>:
+## st_value(a) = 8
+# IE64-NEXT:         nop
+# IE64-NEXT:         ori     $a0, $zero, 8
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         add.d   $a1, $a0, $tp
+## st_value(b) = 0x1000
+# IE64-NEXT:         lu12i.w $a0, 1
+# IE64-NEXT:         ori     $a0, $a0, 0
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         add.d   $a2, $a0, $tp
+## &.got[c]-. = 0x304d8 - 0x20378: 0x10 pages, page offset 0x4d8
+# IE64-NEXT:  20378: pcalau12i $a0, 16
+# IE64-NEXT:         addi.d    $t0, $zero, 1240
+# IE64-NEXT:         lu32i.d	 $t0, 0
+# IE64-NEXT:         lu52i.d	 $t0, $t0, 0
+# IE64-NEXT:         ldx.d     $a0, $a0, $t0
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         add.d   $a3, $a0, $tp
+## &.got[d]-. = 0x304d8+8 - 0x20398: 0x10 pages, page offset 0x4e0
+# IE64-NEXT:  20398: pcalau12i $a0, 16
+# IE64-NEXT:         addi.d    $t0, $zero, 1248
+# IE64-NEXT:         lu32i.d	 $t0, 0
+# IE64-NEXT:         lu52i.d	 $t0, $t0, 0
+# IE64-NEXT:         ldx.d     $a0, $a0, $t0
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         add.d   $a4, $a0, $tp
+## &.got[e]-. = 0x304d8+16 - 0x203b8: 0x10 pages, page offset 0x4e8
+# IE64-NEXT:  203b8: pcalau12i $a0, 16
+# IE64-NEXT:         addi.d    $t0, $zero, 1256
+# IE64-NEXT:         lu32i.d	 $t0, 0
+# IE64-NEXT:         lu52i.d	 $t0, $t0, 0
+# IE64-NEXT:         ldx.d     $a0, $a0, $t0
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         add.d   $a5, $a0, $tp
+## &.got[f]-. = 0x304d8+32 - 0x203e8: 0x10 pages, page offset 0x4f0
+# IE64-NEXT:  203d8: pcalau12i $a0, 16
+# IE64-NEXT:         addi.d    $t0, $zero, 1264
+# IE64-NEXT:         lu32i.d	 $t0, 0
+# IE64-NEXT:         lu52i.d	 $t0, $t0, 0
+# IE64-NEXT:         ldx.d     $a0, $a0, $t0
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         add.d   $a6, $a0, $tp
 
 #--- a.s
 la.tls.desc $a0, $t0, a
diff --git a/lld/test/ELF/loongarch-tlsdesc-pcrel20-s2.s b/lld/test/ELF/loongarch-tlsdesc-pcrel20-s2.s
index 122cd9d042d91d..5dbf1e5febf5cc 100644
--- a/lld/test/ELF/loongarch-tlsdesc-pcrel20-s2.s
+++ b/lld/test/ELF/loongarch-tlsdesc-pcrel20-s2.s
@@ -14,14 +14,15 @@
 # RUN: ld.lld -shared -z now a.64.o c.64.o -o rel.64.so -z rel
 # RUN: llvm-readobj -r -x .got rel.64.so | FileCheck --check-prefix=GD64-REL %s
 
-## FIXME: The transition frome TLSDESC to IE/LE has not yet been implemented.
-## Keep the dynamic relocations and hand them over to dynamic linker.
+## Transition from TLSDESC to IE/LE.
 
 # RUN: ld.lld -e 0 -z now a.64.o c.64.o -o a.64.le
-# RUN: llvm-readobj -r -x .got a.64.le | FileCheck --check-prefix=LE64-RELA %s
+# RUN: llvm-readelf -r a.64.le | FileCheck --check-prefix=NOREL %s
+# RUN: llvm-objdump --no-show-raw-insn -h -d a.64.le | FileCheck %s --check-prefix=LE64
 
 # RUN: ld.lld -e 0 -z now a.64.o c.64.so -o a.64.ie
 # RUN: llvm-readobj -r -x .got a.64.ie | FileCheck --check-prefix=IE64-RELA %s
+# RUN: llvm-objdump --no-show-raw-insn -h -d a.64.ie | FileCheck %s --check-prefix=IE64
 
 ## 32-bit code is mostly the same. We only test a few variants.
 
@@ -78,29 +79,59 @@
 # GD64-NEXT:          jirl $ra, $ra, 0
 # GD64-NEXT:          add.d $a4, $a0, $tp
 
-# LE64-RELA:      .rela.dyn {
-# LE64-RELA-NEXT:   0x30268 R_LARCH_TLS_DESC64 - 0x8
-# LE64-RELA-NEXT:   0x30278 R_LARCH_TLS_DESC64 - 0x800
-# LE64-RELA-NEXT:   0x30288 R_LARCH_TLS_DESC64 - 0x1000
-# LE64-RELA-NEXT:   0x30298 R_LARCH_TLS_DESC64 - 0x7FF
-# LE64-RELA-NEXT: }
-# LE64-RELA:      Hex dump of section '.got':
-# LE64-RELA-NEXT: 0x00030268 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030278 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030288 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030298 00000000 00000000 00000000 00000000 .
+# NOREL: no relocations
+
+# LE64-LABEL: <.text>:
+## st_value(a) = 8
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 8
+# LE64-NEXT:         add.d   $a1, $a0, $tp
+## st_value(b) = 2047
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 2047
+# LE64-NEXT:         add.d   $a2, $a0, $tp
+## st_value(c) = 2048
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 2048
+# LE64-NEXT:         add.d   $a3, $a0, $tp
+## st_value(d) = 4096
+# LE64-NEXT:         nop
+# LE64-NEXT:         lu12i.w $a0, 1
+# LE64-NEXT:         ori     $a0, $a0, 0
+# LE64-NEXT:         add.d   $a4, $a0, $tp
 
 # IE64-RELA:      .rela.dyn {
-# IE64-RELA-NEXT:   0x30418 R_LARCH_TLS_DESC64 - 0x8
-# IE64-RELA-NEXT:   0x30448 R_LARCH_TLS_DESC64 - 0x7FF
-# IE64-RELA-NEXT:   0x30428 R_LARCH_TLS_DESC64 c 0x0
-# IE64-RELA-NEXT:   0x30438 R_LARCH_TLS_DESC64 d 0x0
+# IE64-RELA-NEXT:   0x303E8 R_LARCH_TLS_TPREL64 c 0x0
+# IE64-RELA-NEXT:   0x303F0 R_LARCH_TLS_TPREL64 d 0x0
 # IE64-RELA-NEXT: }
 # IE64-RELA:      Hex dump of section '.got':
-# IE64-RELA-NEXT: 0x00030418 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030428 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030438 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030448 00000000 00000000 00000000 00000000 .
+# IE64-RELA-NEXT: 0x000303e8 00000000 00000000 00000000 00000000 .
+
+# IE64:       .got     00000010 00000000000303e8
+
+## a and b are optimized to use LE. c and d are optimized to IE.
+# IE64-LABEL: <.text>:
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         ori     $a0, $zero, 8
+# IE64-NEXT:         add.d   $a1, $a0, $tp
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         ori     $a0, $zero, 2047
+# IE64-NEXT:         add.d   $a2, $a0, $tp
+## &.got[c]-. = 0x303e8 - 0x202ec: 0x10 pages, page offset 0x3e8
+# IE64-NEXT:         nop
+# IE64-NEXT:  202ec: pcalau12i $a0, 16
+# IE64-NEXT:         ld.d      $a0, $a0, 1000
+# IE64-NEXT:         add.d   $a3, $a0, $tp
+## &.got[d]-. = 0x303e8+8 - 0x202fc: 0x10 pages, page offset 0x3f0
+# IE64-NEXT:         nop
+# IE64-NEXT:  202fc: pcalau12i $a0, 16
+# IE64-NEXT:         ld.d      $a0, $a0, 1008
+# IE64-NEXT:         add.d   $a4, $a0, $tp
 
 # GD32-REL:      .rel.dyn {
 # GD32-REL-NEXT:    0x202A4 R_LARCH_TLS_DESC32 -
diff --git a/lld/test/ELF/loongarch-tlsdesc.s b/lld/test/ELF/loongarch-tlsdesc.s
index 8c49ab31320275..7759d9312d1080 100644
--- a/lld/test/ELF/loongarch-tlsdesc.s
+++ b/lld/test/ELF/loongarch-tlsdesc.s
@@ -14,14 +14,15 @@
 # RUN: ld.lld -shared -z now a.64.o c.64.o -o rel.64.so -z rel
 # RUN: llvm-readobj -r -x .got rel.64.so | FileCheck --check-prefix=GD64-REL %s
 
-## FIXME: The transition frome TLSDESC to IE/LE has not yet been implemented.
-## Keep the dynamic relocations and hand them over to dynamic linker.
+## Transition from TLSDESC to IE/LE.
 
 # RUN: ld.lld -e 0 -z now a.64.o c.64.o -o a.64.le
-# RUN: llvm-readobj -r -x .got a.64.le | FileCheck --check-prefix=LE64-RELA %s
+# RUN: llvm-readelf -r a.64.le | FileCheck --check-prefix=NOREL %s
+# RUN: llvm-objdump --no-show-raw-insn -h -d a.64.le | FileCheck %s --check-prefix=LE64
 
 # RUN: ld.lld -e 0 -z now a.64.o c.64.so -o a.64.ie
 # RUN: llvm-readobj -r -x .got a.64.ie | FileCheck --check-prefix=IE64-RELA %s
+# RUN: llvm-objdump --no-show-raw-insn -h -d a.64.ie | FileCheck %s --check-prefix=IE64
 
 ## 32-bit code is mostly the same. We only test a few variants.
 
@@ -82,29 +83,67 @@
 # GD64-NEXT:          jirl $ra, $ra, 0
 # GD64-NEXT:          add.d $a4, $a0, $tp
 
-# LE64-RELA:      .rela.dyn {
-# LE64-RELA-NEXT:   0x30278 R_LARCH_TLS_DESC64 - 0x8
-# LE64-RELA-NEXT:   0x30288 R_LARCH_TLS_DESC64 - 0x800
-# LE64-RELA-NEXT:   0x30298 R_LARCH_TLS_DESC64 - 0x1000
-# LE64-RELA-NEXT:   0x302A8 R_LARCH_TLS_DESC64 - 0x7FF
-# LE64-RELA-NEXT: }
-# LE64-RELA:      Hex dump of section '.got':
-# LE64-RELA-NEXT: 0x00030278 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030288 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x00030298 00000000 00000000 00000000 00000000 .
-# LE64-RELA-NEXT: 0x000302a8 00000000 00000000 00000000 00000000 .
+# NOREL: no relocations
+
+# LE64-LABEL: <.text>:
+## st_value(a) = 8
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 8
+# LE64-NEXT:         add.d   $a1, $a0, $tp
+## st_value(b) = 2047
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 2047
+# LE64-NEXT:         add.d   $a2, $a0, $tp
+## st_value(c) = 2048
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         ori     $a0, $zero, 2048
+# LE64-NEXT:         add.d   $a3, $a0, $tp
+## st_value(d) = 4096
+# LE64-NEXT:         nop
+# LE64-NEXT:         nop
+# LE64-NEXT:         lu12i.w $a0, 1
+# LE64-NEXT:         ori     $a0, $a0, 0
+# LE64-NEXT:         add.d   $a4, $a0, $tp
 
 # IE64-RELA:      .rela.dyn {
-# IE64-RELA-NEXT:   0x30428 R_LARCH_TLS_DESC64 - 0x8
-# IE64-RELA-NEXT:   0x30458 R_LARCH_TLS_DESC64 - 0x7FF
-# IE64-RELA-NEXT:   0x30438 R_LARCH_TLS_DESC64 c 0x0
-# IE64-RELA-NEXT:   0x30448 R_LARCH_TLS_DESC64 d 0x0
+# IE64-RELA-NEXT:   0x303F8 R_LARCH_TLS_TPREL64 c 0x0
+# IE64-RELA-NEXT:   0x30400 R_LARCH_TLS_TPREL64 d 0x0
 # IE64-RELA-NEXT: }
 # IE64-RELA:      Hex dump of section '.got':
-# IE64-RELA-NEXT: 0x00030428 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030438 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030448 00000000 00000000 00000000 00000000 .
-# IE64-RELA-NEXT: 0x00030458 00000000 00000000 00000000 00000000 .
+# IE64-RELA-NEXT: 0x000303f8 00000000 00000000 00000000 00000000 .
+
+# IE64:       .got     00000010 00000000000303f8
+
+## a and b are optimized to use LE. c and d are optimized to IE.
+# IE64-LABEL: <.text>:
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         ori     $a0, $zero, 8
+# IE64-NEXT:         add.d   $a1, $a0, $tp
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:         ori     $a0, $zero, 2047
+# IE64-NEXT:         add.d   $a2, $a0, $tp
+## &.got[c]-. = 0x303f8 - 0x202f8: 0x10 pages, page offset 0x3f8
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:  202f8: pcalau12i $a0, 16
+# IE64-NEXT:         ld.d      $a0, $a0, 1016
+# IE64-NEXT:         add.d   $a3, $a0, $tp
+## &.got[d]-. = 0x303f8+8 - 0x2030c: 0x10 pages, page offset 0x400
+# IE64-NEXT:         nop
+# IE64-NEXT:         nop
+# IE64-NEXT:  2030c: pcalau12i $a0, 16
+# IE64-NEXT:         ld.d      $a0, $a0, 1024
+# IE64-NEXT:         add.d   $a4, $a0, $tp
 
 # GD32-REL:      .rel.dyn {
 # GD32-REL-NEXT:    0x202B4 R_LARCH_TLS_DESC32 -



More information about the llvm-branch-commits mailing list