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(*rHi20.sym).section))) + (!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() || + rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc() || + (ctx.arg.isPic && !cast(*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..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 %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 %s -# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX %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 @@ -49,6 +50,25 @@ # NORELAX64-NEXT: pcalau12i $a0, 1024 # NORELAX64-NEXT: ld.d $a0, $a0, 8 + +## 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: @@ -60,3 +80,14 @@ _start: .section .data sym: .zero 4 + + +#--- nonzero.s +.section .text +.global _start +_start: + la.got $a0, sym+4 + +.section .data +sym: + .zero 4