Skip to content

[lld][LoongArch] Support relaxation during IE to LE conversion #123702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 11, 2025

Conversation

ylzsx
Copy link
Contributor

@ylzsx ylzsx commented Jan 21, 2025

Complement #123680. When relaxation enable, remove redundant NOPs.

@llvmbot
Copy link
Member

llvmbot commented Jan 21, 2025

@llvm/pr-subscribers-backend-loongarch
@llvm/pr-subscribers-lld-elf

@llvm/pr-subscribers-lld

Author: Zhaoxin Yang (ylzsx)

Changes

Complement #123680. When relaxation enable, remove redundant NOPs.


Full diff: https://github.com/llvm/llvm-project/pull/123702.diff

2 Files Affected:

  • (modified) lld/ELF/Arch/LoongArch.cpp (+11-2)
  • (modified) lld/test/ELF/loongarch-relax-tls-ie.s (+26-4)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index dc98dbec872c0c..ef25e741901d93 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -975,6 +975,11 @@ static bool relax(Ctx &ctx, InputSection &sec) {
       if (relaxable(relocs, i))
         relaxTlsLe(ctx, sec, i, loc, r, remove);
       break;
+    case R_LARCH_TLS_IE_PC_HI20:
+      if (relaxable(relocs, i) && r.expr == R_RELAX_TLS_IE_TO_LE &&
+          isUInt<12>(r.sym->getVA(ctx, r.addend)))
+        remove = 4;
+      break;
     }
 
     // For all anchors whose offsets are <= r.offset, they are preceded by
@@ -1049,7 +1054,7 @@ void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
     secAddr += s->outSecOff;
   else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
     secAddr += ehIn->getParent()->outSecOff;
-  bool isExtreme = false;
+  bool isExtreme = false, isRelax = false;
   const MutableArrayRef<Relocation> relocs = sec.relocs();
   for (size_t i = 0, size = relocs.size(); i != size; ++i) {
     Relocation &rel = relocs[i];
@@ -1077,8 +1082,12 @@ void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
         val = SignExtend64(sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset),
                            bits);
         relocateNoSym(loc, rel.type, val);
-      } else
+      } else {
+        isRelax = relaxable(relocs, i);
+        if (isRelax && rel.type == R_LARCH_TLS_IE_PC_HI20 && isUInt<12>(val))
+          continue;
         tlsIeToLe(loc, rel, val);
+      }
       continue;
     default:
       break;
diff --git a/lld/test/ELF/loongarch-relax-tls-ie.s b/lld/test/ELF/loongarch-relax-tls-ie.s
index f5375ae3a3b400..2c95a342251f20 100644
--- a/lld/test/ELF/loongarch-relax-tls-ie.s
+++ b/lld/test/ELF/loongarch-relax-tls-ie.s
@@ -3,11 +3,10 @@
 
 # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.o
 
-## FIXME: IE relaxation has not yet been implemented.
-## --relax/--no-relax has the same result. Also check --emit-relocs.
-# RUN: ld.lld --emit-relocs %t.o -o %t
+## Also check --emit-relocs.
+# RUN: ld.lld --emit-relocs --relax %t.o -o %t
 # RUN: llvm-readelf -x .got %t 2>&1 | FileCheck --check-prefix=LE-GOT %s
-# RUN: llvm-objdump -dr --no-show-raw-insn %t | FileCheck --check-prefixes=LE %s
+# RUN: llvm-objdump -dr --no-show-raw-insn %t | FileCheck --check-prefixes=LER %s
 
 # RUN: ld.lld --emit-relocs --no-relax %t.o -o %t.norelax
 # RUN: llvm-readelf -x .got %t.norelax 2>&1 | FileCheck --check-prefix=LE-GOT %s
@@ -42,6 +41,29 @@
 # LE-NEXT:        add.d   $a2, $a2, $tp
 # LE-NEXT:        add.d   $a3, $a3, $tp
 
+# LER:      20158: ori     $a0, $zero, 4095
+# LER-NEXT:          R_LARCH_TLS_IE_PC_HI20 a
+# LER-NEXT:          R_LARCH_RELAX   *ABS*
+# LER-NEXT:          R_LARCH_TLS_IE_PC_LO12 a
+# LER-NEXT:          R_LARCH_RELAX   *ABS*
+# LER-NEXT:        add.d   $a0, $a0, $tp
+# LER-NEXT: 20160: lu12i.w $a1, 1
+# LER-NEXT:          R_LARCH_TLS_IE_PC_HI20 b
+# LER-NEXT:        ori     $a1, $a1, 0
+# LER-NEXT:          R_LARCH_TLS_IE_PC_LO12 b
+# LER-NEXT:        add.d   $a1, $a1, $tp
+# LER-NEXT: 2016c: lu12i.w $a3, 1
+# LER-NEXT:          R_LARCH_TLS_IE_PC_HI20 a
+# LER-NEXT:          R_LARCH_RELAX   *ABS*
+# LER-NEXT:          R_LARCH_TLS_IE_PC_HI20 b
+# LER-NEXT:          R_LARCH_RELAX   *ABS*
+# LER-NEXT:        ori     $a2, $zero, 4095
+# LER-NEXT:          R_LARCH_TLS_IE_PC_LO12 a
+# LER-NEXT:        ori     $a3, $a3, 0
+# LER-NEXT:          R_LARCH_TLS_IE_PC_LO12 b
+# LER-NEXT:        add.d   $a2, $a2, $tp
+# LER-NEXT:        add.d   $a3, $a3, $tp
+
 la.tls.ie $a0, a    # relax
 add.d $a0, $a0, $tp
 

@ylzsx ylzsx changed the title [lld][LoongArch] Support relaxation during IE to LE conversion. [lld][LoongArch] Support relaxation during IE to LE conversion Jan 22, 2025
@SixWeining
Copy link
Contributor

cc @xen0n

ylzsx added 6 commits March 11, 2025 14:38
Original code sequence:
 * 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)

Cannot convert to LE/IE, but relax:
 * pcaddi     $a0, %desc_pcrel_20(sym_desc)
 * ld.d       $ra, $a0, %desc_ld(sym_desc)
 * jirl       $ra, $ra, %desc_call(sym_desc)

TODO: The conversion of TLSDESC GD/LD to LE/IE will implement in a
future patch.
Original code sequence:
 * pcalau12i $a0, %ie_pc_hi20(sym)
 * ld.d      $a0, $a0, %ie_pc_lo12(sym)

The code sequence converted is as follows:
 * lu12i.w   $a0, %ie_pc_hi20(sym)  # le_hi20 != 0, otherwise NOP
 * ori $a0   $a0, %ie_pc_lo12(sym)

FIXME: When relaxation enables, redundant NOP can be removed. This will
be implemented in a future patch.

Note: In the normal or medium code model, original code sequence with
relocations can appear interleaved, because converted code sequence
calculates the absolute offset. However, in extreme code model, to
identify the current code model, the first four instructions with
relocations must appear consecutively.
@ylzsx ylzsx force-pushed the users/ylzsx/r-tls-ie-to-le-norelax branch from 31a9dab to 5dafc66 Compare March 11, 2025 07:01
@ylzsx ylzsx force-pushed the users/ylzsx/r-tls-ie-to-le-relax branch from 9d99de8 to d6e02ed Compare March 21, 2025 03:26
Base automatically changed from users/ylzsx/r-tls-ie-to-le-norelax to main April 7, 2025 11:58
@ylzsx ylzsx merged commit 8a351f1 into main Apr 11, 2025
11 checks passed
@ylzsx ylzsx deleted the users/ylzsx/r-tls-ie-to-le-relax branch April 11, 2025 08:56
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants