[lld] [lld][LoongArch] Fix relaxation for R_LARCH_GOT_PC_{HI20, LO12} (PR #151264)

Zhaoxin Yang via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 30 00:19:22 PDT 2025


https://github.com/ylzsx updated https://github.com/llvm/llvm-project/pull/151264

>From 3a3dd03b662b1e05348e0e3d43bdbea54aa01932 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Tue, 29 Jul 2025 15:48:57 +0800
Subject: [PATCH 1/2] [lld][LoongArch] Fix relaxation for
 R_LARCH_GOT_PC_{HI20,LO12}

We could relax codes when the addends of both relocations are zero.

Note: For `ld.bfd`, GOT references with non-zero addends will trigger
an assert in LoongArch, but `lld` handles these cases without any
errors.
```
ld.bfd: BFD (GNU Binutils) 2.44.0 assertion fail
/usr/src/debug/binutils/binutils-gdb/bfd/elfnn-loongarch.c:4248
```
---
 lld/ELF/Arch/LoongArch.cpp                  |  9 ++++---
 lld/test/ELF/loongarch-relax-pc-hi20-lo12.s | 28 ++++++++++++++++++---
 2 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 15dcddb13baf7..a14553018fc36 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -809,10 +809,13 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
   // address.
   // Meanwhile skip undefined, preemptible and STT_GNU_IFUNC symbols, because
   // these symbols may be resolve in runtime.
+  // Moreover, relaxation can only occur if the addends of both relocations are
+  // zero for GOT references.
   if (rHi20.type == R_LARCH_GOT_PC_HI20 &&
-      (!rHi20.sym->isDefined() || rHi20.sym->isPreemptible ||
-       rHi20.sym->isGnuIFunc() ||
-       (ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section)))
+      (!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() ||
+       rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc() ||
+       (ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section) ||
+       rHi20.addend != 0 || rLo12.addend != 0))
     return;
 
   uint64_t dest = 0;
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
index a417d89e9fa2e..d5bec595bbfd7 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -1,12 +1,12 @@
 # REQUIRES: loongarch
 
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax --defsym ELF32=1 %s -o %t.32.o
 # RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o
 
 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32
 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -o %t.64
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX,RELAX32 %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX,RELAX64 %s
 
 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -shared -o %t.32s
 # RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -shared -o %t.64s
@@ -25,6 +25,11 @@
 # RELAX-NEXT:              pcaddi $a0, 4094
 # RELAX-NEXT:              pcaddi $a0, 4093
 
+# RELAX32-NEXT:            pcalau12i $a0, 4
+# RELAX32-NEXT:            ld.w      $a0, $a0, 8
+# RELAX64-NEXT:            pcalau12i $a0, 4
+# RELAX64-NEXT:            ld.d      $a0, $a0, 12
+
 # NORELAX32-LABEL: <_start>:
 ## offset exceed range of pcaddi
 ## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0
@@ -36,6 +41,8 @@
 # NORELAX32-NEXT:          addi.w        $a0, $a0, 0
 # NORELAX32-NEXT:          pcalau12i     $a0, 1024
 # NORELAX32-NEXT:          ld.w          $a0, $a0, 4
+# NORELAX32-NEXT:          pcalau12i     $a0, 1024
+# NORELAX32-NEXT:          ld.w          $a0, $a0, 8
 
 # NORELAX64-LABEL: <_start>:
 ## offset exceed range of pcaddi
@@ -48,6 +55,16 @@
 # NORELAX64-NEXT:          addi.d        $a0, $a0, 0
 # NORELAX64-NEXT:          pcalau12i     $a0, 1024
 # NORELAX64-NEXT:          ld.d          $a0, $a0, 8
+# NORELAX64-NEXT:          pcalau12i     $a0, 1024
+# NORELAX64-NEXT:          ld.d          $a0, $a0, 12
+
+.macro ld dst, src1, src2
+.ifdef ELF32
+ld.w \dst, \src1, \src2
+.else
+ld.d \dst, \src1, \src2
+.endif
+.endm
 
 .section .text
 .global _start
@@ -57,6 +74,11 @@ _start:
   la.pcrel  $a0, sym
   la.got    $a0, sym
 
+  pcalau12i $a0, %got_pc_hi20(sym+4)
+    .reloc .-4, R_LARCH_RELAX, 0
+  ld        $a0, $a0, %got_pc_lo12(sym+4)
+    .reloc .-4, R_LARCH_RELAX, 0
+
 .section .data
 sym:
   .zero 4

>From 74b941543cbf59370cf51b3928be0f98101384d3 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Wed, 30 Jul 2025 11:17:32 +0800
Subject: [PATCH 2/2] fixes for reviews.

---
 lld/test/ELF/loongarch-relax-pc-hi20-lo12.s | 77 ++++++++++++---------
 1 file changed, 43 insertions(+), 34 deletions(-)

diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
index d5bec595bbfd7..a33f866506e13 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -1,22 +1,23 @@
 # REQUIRES: loongarch
+# RUN: rm -rf %t && split-file %s %t && cd %t
 
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax --defsym ELF32=1 %s -o %t.32.o
-# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax a.s -o a.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax a.s -o a.64.o
 
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -o %t.64
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX,RELAX32 %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX,RELAX64 %s
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -o a.32
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.64.o -o a.64
+# RUN: llvm-objdump -td --no-show-raw-insn a.32 | FileCheck --check-prefixes=RELAX %s
+# RUN: llvm-objdump -td --no-show-raw-insn a.64 | FileCheck --check-prefixes=RELAX %s
 
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -shared -o %t.32s
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -shared -o %t.64s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32s | FileCheck --check-prefixes=RELAX %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64s | FileCheck --check-prefixes=RELAX %s
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -shared -o a.32s
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.64.o -shared -o a.64s
+# RUN: llvm-objdump -td --no-show-raw-insn a.32s | FileCheck --check-prefixes=RELAX %s
+# RUN: llvm-objdump -td --no-show-raw-insn a.64s | FileCheck --check-prefixes=RELAX %s
 
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 %t.32.o -o %t.32o
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 %t.64.o -o %t.64o
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32o | FileCheck --check-prefixes=NORELAX32 %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64o | FileCheck --check-prefixes=NORELAX64 %s
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 a.32.o -o a.32o
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 a.64.o -o a.64o
+# RUN: llvm-objdump -td --no-show-raw-insn a.32o | FileCheck --check-prefixes=NORELAX32 %s
+# RUN: llvm-objdump -td --no-show-raw-insn a.64o | FileCheck --check-prefixes=NORELAX64 %s
 
 # RELAX-LABEL: <_start>:
 ## offset = 0x14000 - 0x10000 = 4096<<2
@@ -25,11 +26,6 @@
 # RELAX-NEXT:              pcaddi $a0, 4094
 # RELAX-NEXT:              pcaddi $a0, 4093
 
-# RELAX32-NEXT:            pcalau12i $a0, 4
-# RELAX32-NEXT:            ld.w      $a0, $a0, 8
-# RELAX64-NEXT:            pcalau12i $a0, 4
-# RELAX64-NEXT:            ld.d      $a0, $a0, 12
-
 # NORELAX32-LABEL: <_start>:
 ## offset exceed range of pcaddi
 ## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0
@@ -41,8 +37,6 @@
 # NORELAX32-NEXT:          addi.w        $a0, $a0, 0
 # NORELAX32-NEXT:          pcalau12i     $a0, 1024
 # NORELAX32-NEXT:          ld.w          $a0, $a0, 4
-# NORELAX32-NEXT:          pcalau12i     $a0, 1024
-# NORELAX32-NEXT:          ld.w          $a0, $a0, 8
 
 # NORELAX64-LABEL: <_start>:
 ## offset exceed range of pcaddi
@@ -55,17 +49,26 @@
 # NORELAX64-NEXT:          addi.d        $a0, $a0, 0
 # NORELAX64-NEXT:          pcalau12i     $a0, 1024
 # NORELAX64-NEXT:          ld.d          $a0, $a0, 8
-# NORELAX64-NEXT:          pcalau12i     $a0, 1024
-# NORELAX64-NEXT:          ld.d          $a0, $a0, 12
 
-.macro ld dst, src1, src2
-.ifdef ELF32
-ld.w \dst, \src1, \src2
-.else
-ld.d \dst, \src1, \src2
-.endif
-.endm
 
+## GOT references with non-zero addends. No relaxation.
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax nonzero.s -o nonzero.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax nonzero.s -o nonzero.64.o
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.32.o -o nonzero.32
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.64.o -o nonzero.64
+# RUN: llvm-objdump -td --no-show-raw-insn nonzero.32 | FileCheck --check-prefixes=NONZERO32 %s
+# RUN: llvm-objdump -td --no-show-raw-insn nonzero.64 | FileCheck --check-prefixes=NONZERO64 %s
+
+# NONZERO32-LABEL: <_start>:
+# NONZERO32-NEXT:      10000:  pcalau12i $a0, 4
+# NONZERO32-NEXT:              ld.w      $a0, $a0, 8
+
+# NONZERO64-LABEL: <_start>:
+# NONZERO64-NEXT:      10000:  pcalau12i $a0, 4
+# NONZERO64-NEXT:              ld.d      $a0, $a0, 12
+
+
+#--- a.s
 .section .text
 .global _start
 _start:
@@ -74,10 +77,16 @@ _start:
   la.pcrel  $a0, sym
   la.got    $a0, sym
 
-  pcalau12i $a0, %got_pc_hi20(sym+4)
-    .reloc .-4, R_LARCH_RELAX, 0
-  ld        $a0, $a0, %got_pc_lo12(sym+4)
-    .reloc .-4, R_LARCH_RELAX, 0
+.section .data
+sym:
+  .zero 4
+
+
+#--- nonzero.s
+.section .text
+.global _start
+_start:
+  la.got    $a0, sym+4
 
 .section .data
 sym:



More information about the llvm-commits mailing list