[lld] [lld][LoongArch] Relax TLS LE/GD/LD (PR #123600)
Zhaoxin Yang via llvm-commits
llvm-commits at lists.llvm.org
Sun Mar 9 20:58:44 PDT 2025
https://github.com/ylzsx updated https://github.com/llvm/llvm-project/pull/123600
>From ea9fea20110021eb5095564f5c4b46e07974deeb Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 27 Dec 2024 15:32:34 +0800
Subject: [PATCH 01/20] Relax PCHi20Lo12.
Support relaxation optimization for two types of code sequences.
```
From:
pcalau12i $a0, %pc_hi20(sym)
R_LARCH_PCALA_HI20, R_LARCH_RELAX
addi.w/d $a0, $a0, %pc_lo12(sym)
R_LARCH_PCALA_LO12, R_LARCH_RELAX
To:
pcaddi $a0, %pc_lo12(sym)
R_LARCH_PCREL20_S2
From:
pcalau12i $a0, %got_pc_hi20(sym_got)
R_LARCH_GOT_PC_HI20, R_LARCH_RELAX
ld.w/d $a0, $a0, %got_pc_lo12(sym_got)
R_LARCH_GOT_PC_LO12, R_LARCH_RELAX
To:
pcaddi $a0, %got_pc_hi20(sym_got)
R_LARCH_PCREL20_S2
```
---
lld/ELF/Arch/LoongArch.cpp | 110 ++++++++++++++++++++++++++++++++++++-
1 file changed, 108 insertions(+), 2 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 3280c34cb6ed0..07ca66700f648 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -53,6 +53,7 @@ enum Op {
ADDI_W = 0x02800000,
ADDI_D = 0x02c00000,
ANDI = 0x03400000,
+ PCADDI = 0x18000000,
PCADDU12I = 0x1c000000,
LD_W = 0x28800000,
LD_D = 0x28c00000,
@@ -131,6 +132,8 @@ 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 setD5k16(uint32_t insn, uint32_t imm) {
uint32_t immLo = extractBits(imm, 15, 0);
uint32_t immHi = extractBits(imm, 20, 16);
@@ -743,6 +746,84 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
}
}
+static bool relaxable(ArrayRef<Relocation> relocs, size_t i) {
+ return i + 1 < relocs.size() && relocs[i + 1].type == R_LARCH_RELAX;
+}
+
+static bool isPairRelaxable(ArrayRef<Relocation> relocs, size_t i) {
+ return relaxable(relocs, i) && relaxable(relocs, i + 2) &&
+ relocs[i].offset + 4 == relocs[i + 2].offset;
+}
+
+// Relax code sequence.
+// From:
+// pcalau12i $a0, %pc_hi20(sym)
+// addi.w/d $a0, $a0, %pc_lo12(sym)
+// To:
+// pcaddi $a0, %pc_lo12(sym)
+//
+// From:
+// pcalau12i $a0, %got_pc_hi20(sym_got)
+// ld.w/d $a0, $a0, %got_pc_lo12(sym_got)
+// To:
+// pcaddi $a0, %got_pc_hi20(sym_got)
+static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
+ uint64_t loc, Relocation &rHi20, Relocation &rLo12,
+ uint32_t &remove) {
+ // check if the relocations are relaxable sequences.
+ if (!((rHi20.type == R_LARCH_PCALA_HI20 &&
+ rLo12.type == R_LARCH_PCALA_LO12) ||
+ (rHi20.type == R_LARCH_GOT_PC_HI20 &&
+ rLo12.type == R_LARCH_GOT_PC_LO12)))
+ return;
+
+ // GOT references to absolute symbols can't be relaxed to use pcaddi in
+ // position-independent code, because these instructions produce a relative
+ // address.
+ // Meanwhile skip undefined, preemptible and STT_GNU_IFUNC symbols, because
+ // these symbols may be resolve in runtime.
+ 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)))
+ return;
+
+ uint64_t symBase = 0;
+ if (rHi20.expr == RE_LOONGARCH_PLT_PAGE_PC)
+ symBase = rHi20.sym->getPltVA(ctx);
+ else if (rHi20.expr == RE_LOONGARCH_PAGE_PC ||
+ rHi20.expr == RE_LOONGARCH_GOT_PAGE_PC)
+ symBase = rHi20.sym->getVA(ctx);
+ else {
+ Err(ctx) << getErrorLoc(ctx, (const uint8_t *)loc) << "unknown expr ("
+ << rHi20.expr << ") against symbol " << rHi20.sym
+ << "in relaxPCHi20Lo12";
+ return;
+ }
+ const uint64_t symLocal = symBase + rHi20.addend;
+
+ const int64_t distance = symLocal - loc;
+ // Check if the distance aligns 4 bytes or exceeds the range of pcaddi.
+ if ((distance & 0x3) != 0 || !isInt<22>(distance))
+ return;
+
+ // Note: If we can ensure that the .o files generated by LLVM only contain
+ // relaxable instruction sequences with R_LARCH_RELAX, then we do not need to
+ // decode instructions. The relaxable instruction sequences imply the
+ // following constraints:
+ // * For relocation pairs related to got_pc, the opcodes of instructions
+ // must be pcalau12i + ld.w/d. In other cases, the opcodes must be pcalau12i +
+ // addi.w/d.
+ // * The destination register of pcalau12i is guaranteed to be used only by
+ // the immediately following instruction.
+ const uint32_t nextInsn = read32le(sec.content().data() + rLo12.offset);
+
+ sec.relaxAux->relocTypes[i] = R_LARCH_RELAX;
+ sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
+ sec.relaxAux->writes.push_back(insn(PCADDI, getD5(nextInsn), 0, 0));
+ remove = 4;
+}
+
static bool relax(Ctx &ctx, InputSection &sec) {
const uint64_t secAddr = sec.getVA();
const MutableArrayRef<Relocation> relocs = sec.relocs();
@@ -781,6 +862,12 @@ static bool relax(Ctx &ctx, InputSection &sec) {
}
break;
}
+ case R_LARCH_PCALA_HI20:
+ case R_LARCH_GOT_PC_HI20:
+ // The overflow check for i+2 will be carried out in isPairRelaxable.
+ if (isPairRelaxable(relocs, i))
+ relaxPCHi20Lo12(ctx, sec, i, loc, r, relocs[i + 2], remove);
+ break;
}
// For all anchors whose offsets are <= r.offset, they are preceded by
@@ -851,6 +938,7 @@ void LoongArch::finalizeRelax(int passes) const {
MutableArrayRef<Relocation> rels = sec->relocs();
ArrayRef<uint8_t> old = sec->content();
size_t newSize = old.size() - aux.relocDeltas[rels.size() - 1];
+ size_t writesIdx = 0;
uint8_t *p = ctx.bAlloc.Allocate<uint8_t>(newSize);
uint64_t offset = 0;
int64_t delta = 0;
@@ -867,11 +955,29 @@ void LoongArch::finalizeRelax(int passes) const {
continue;
// Copy from last location to the current relocated location.
- const Relocation &r = rels[i];
+ Relocation &r = rels[i];
uint64_t size = r.offset - offset;
memcpy(p, old.data() + offset, size);
p += size;
- offset = r.offset + remove;
+
+ int64_t skip = 0;
+ if (RelType newType = aux.relocTypes[i]) {
+ switch (newType) {
+ case R_LARCH_RELAX:
+ break;
+ case R_LARCH_PCREL20_S2:
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
+ // RelExpr is needed for relocating.
+ r.expr = r.sym->hasFlag(NEEDS_PLT) ? R_PLT_PC : R_PC;
+ break;
+ default:
+ llvm_unreachable("unsupported type");
+ }
+ }
+
+ p += skip;
+ offset = r.offset + skip + remove;
}
memcpy(p, old.data() + offset, old.size() - offset);
>From 95f454086ea7766adeef4ae1e65b7689824ec7df Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Tue, 24 Dec 2024 08:57:29 +0800
Subject: [PATCH 02/20] la.pcrel relax test modify.
---
lld/test/ELF/loongarch-relax-align.s | 115 ++++++++++++++-------
lld/test/ELF/loongarch-relax-emit-relocs.s | 41 +++++---
2 files changed, 101 insertions(+), 55 deletions(-)
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s
index ab61e15d5caca..9eaff9144d85e 100644
--- a/lld/test/ELF/loongarch-relax-align.s
+++ b/lld/test/ELF/loongarch-relax-align.s
@@ -6,56 +6,91 @@
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o --no-relax -o %t.32n
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o --no-relax -o %t.64n
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32n | FileCheck %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64n | FileCheck %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX,NOOLD %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX,NOOLD %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32n | FileCheck --check-prefixes=NORELAX,NOOLD %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64n | FileCheck --check-prefixes=NORELAX,NOOLD %s
## Test the R_LARCH_ALIGN without symbol index.
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.o64.o --defsym=old=1
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.o64.o -o %t.o64
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.o64.o --no-relax -o %t.o64n
-# RUN: llvm-objdump -td --no-show-raw-insn %t.o64 | FileCheck %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.o64 | FileCheck --check-prefixes=RELAX,OLD %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck --check-prefixes=NORELAX,OLD %s
## -r keeps section contents unchanged.
# RUN: ld.lld -r %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr --no-show-raw-insn %t.64.r | FileCheck %s --check-prefix=CHECKR
-# CHECK-DAG: {{0*}}10000 l .text {{0*}}44 .Ltext_start
-# CHECK-DAG: {{0*}}10038 l .text {{0*}}0c .L1
-# CHECK-DAG: {{0*}}10040 l .text {{0*}}04 .L2
-# CHECK-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
-
-# CHECK: <.Ltext_start>:
-# CHECK-NEXT: break 1
-# CHECK-NEXT: break 2
-# CHECK-NEXT: nop
-# CHECK-NEXT: nop
-# CHECK-NEXT: break 3
-# CHECK-NEXT: break 4
-# CHECK-NEXT: nop
-# CHECK-NEXT: nop
-# CHECK-NEXT: pcalau12i $a0, 0
-# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# CHECK-NEXT: pcalau12i $a0, 0
-# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 56
-# CHECK-NEXT: pcalau12i $a0, 0
-# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 64
-# CHECK-EMPTY:
-# CHECK-NEXT: <.L1>:
-# CHECK-NEXT: nop
-# CHECK-NEXT: nop
-# CHECK-EMPTY:
-# CHECK-NEXT: <.L2>:
-# CHECK-NEXT: break 5
-
-# CHECK: <.Ltext2_start>:
-# CHECK-NEXT: pcalau12i $a0, 0
-# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# CHECK-NEXT: nop
-# CHECK-NEXT: nop
-# CHECK-NEXT: break 6
+# NOOLD: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
+# OLD: {{0*}}00001 l *ABS* {{0*}}00 old
+
+# NORELAX-DAG: {{0*}}10000 l .text {{0*}}44 .Ltext_start
+# NORELAX-DAG: {{0*}}10038 l .text {{0*}}0c .L1
+# NORELAX-DAG: {{0*}}10040 l .text {{0*}}04 .L2
+# NORELAX-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
+
+# NORELAX: <.Ltext_start>:
+# NORELAX-NEXT: break 1
+# NORELAX-NEXT: break 2
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: break 3
+# NORELAX-NEXT: break 4
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: pcalau12i $a0, 0
+# NORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# NORELAX-NEXT: pcalau12i $a0, 0
+# NORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 56
+# NORELAX-NEXT: pcalau12i $a0, 0
+# NORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 64
+# NORELAX-EMPTY:
+# NORELAX-NEXT: <.L1>:
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: nop
+# NORELAX-EMPTY:
+# NORELAX-NEXT: <.L2>:
+# NORELAX-NEXT: break 5
+
+# NORELAX: <.Ltext2_start>:
+# NORELAX-NEXT: pcalau12i $a0, 0
+# NORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: break 6
+
+
+# RELAX-DAG: {{0*}}10000 l .text {{0*}}34 .Ltext_start
+# RELAX-DAG: {{0*}}1002c l .text {{0*}}08 .L1
+# RELAX-DAG: {{0*}}10030 l .text {{0*}}04 .L2
+# RELAX-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
+
+# RELAX: <.Ltext_start>:
+# RELAX-NEXT: break 1
+# RELAX-NEXT: break 2
+# RELAX-NEXT: nop
+# RELAX-NEXT: nop
+# RELAX-NEXT: break 3
+# RELAX-NEXT: break 4
+# RELAX-NEXT: nop
+# RELAX-NEXT: nop
+# RELAX-NEXT: pcaddi $a0, -8
+# RELAX-NEXT: pcaddi $a0, 2
+# RELAX-NEXT: pcaddi $a0, 2
+# RELAX-EMPTY:
+# RELAX-NEXT: <.L1>:
+# RELAX-NEXT: nop
+# RELAX-EMPTY:
+# RELAX-NEXT: <.L2>:
+# RELAX-NEXT: break 5
+
+# RELAX: <.Ltext2_start>:
+# RELAX-NEXT: pcaddi $a0, 0
+# RELAX-NEXT: nop
+# RELAX-NEXT: nop
+# RELAX-NEXT: nop
+# RELAX-NEXT: break 6
# CHECKR: <.Ltext2_start>:
# CHECKR-NEXT: pcalau12i $a0, 0
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index ba414e8c93f0f..7bc1f2d29c319 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -5,29 +5,40 @@
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.32.o -o %t.32
# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
-# RUN: llvm-objdump -dr %t.32 | FileCheck %s
-# RUN: llvm-objdump -dr %t.64 | FileCheck %s
+# RUN: llvm-objdump -dr %t.32 | FileCheck %s --check-prefix=RELAX
+# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
## -r should keep original relocations.
# RUN: ld.lld -r %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
## --no-relax should keep original relocations.
-## TODO Due to R_LARCH_RELAX is not relaxed, it plays same as --relax now.
# RUN: ld.lld -Ttext=0x10000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
-# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s
+# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
-# CHECK: 00010000 <_start>:
-# CHECK-NEXT: pcalau12i $a0, 0
-# CHECK-NEXT: R_LARCH_PCALA_HI20 _start
-# CHECK-NEXT: R_LARCH_RELAX *ABS*
-# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# CHECK-NEXT: R_LARCH_PCALA_LO12 _start
-# CHECK-NEXT: R_LARCH_RELAX *ABS*
-# CHECK-NEXT: nop
-# CHECK-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# CHECK-NEXT: nop
-# CHECK-NEXT: ret
+# RELAX: 00010000 <_start>:
+# RELAX-NEXT: pcaddi $a0, 0
+# RELAX-NEXT: R_LARCH_RELAX _start
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: nop
+# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# RELAX-NEXT: nop
+# RELAX-NEXT: nop
+# RELAX-NEXT: ret
+
+# NORELAX: <_start>:
+# NORELAX-NEXT: pcalau12i $a0, 0
+# NORELAX-NEXT: R_LARCH_PCALA_HI20 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: addi.d $a0, $a0, 0
+# NORELAX-NEXT: R_LARCH_PCALA_LO12 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: ret
# CHECKR: <_start>:
# CHECKR-NEXT: pcalau12i $a0, 0
>From 7b133c25913598143b2975553cf119b6bee97af2 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 27 Dec 2024 17:33:47 +0800
Subject: [PATCH 03/20] Add test for PCHi20Lo12
---
lld/test/ELF/loongarch-relax-emit-relocs.s | 33 ++++++++---
lld/test/ELF/loongarch-relax-pc-hi20-lo12.s | 62 +++++++++++++++++++++
2 files changed, 86 insertions(+), 9 deletions(-)
create mode 100644 lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index 7bc1f2d29c319..9f3206b7ce54c 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -3,8 +3,8 @@
# 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: ld.lld -Ttext=0x10000 --emit-relocs %t.32.o -o %t.32
-# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
+# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.32.o -o %t.32
+# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.64.o -o %t.64
# RUN: llvm-objdump -dr %t.32 | FileCheck %s --check-prefix=RELAX
# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
@@ -13,7 +13,7 @@
# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
## --no-relax should keep original relocations.
-# RUN: ld.lld -Ttext=0x10000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
+# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
# RELAX: 00010000 <_start>:
@@ -22,31 +22,45 @@
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: pcaddi $a0, -1
+# RELAX-NEXT: R_LARCH_RELAX _start
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: nop
# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
# RELAX-NEXT: nop
-# RELAX-NEXT: nop
# RELAX-NEXT: ret
# NORELAX: <_start>:
# NORELAX-NEXT: pcalau12i $a0, 0
# NORELAX-NEXT: R_LARCH_PCALA_HI20 _start
# NORELAX-NEXT: R_LARCH_RELAX *ABS*
-# NORELAX-NEXT: addi.d $a0, $a0, 0
+# NORELAX-NEXT: addi.d $a0, $a0, 0
# NORELAX-NEXT: R_LARCH_PCALA_LO12 _start
# NORELAX-NEXT: R_LARCH_RELAX *ABS*
-# NORELAX-NEXT: nop
-# NORELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# NORELAX-NEXT: nop
+# NORELAX-NEXT: pcalau12i $a0, 16
+# NORELAX-NEXT: R_LARCH_GOT_PC_HI20 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: ld.d $a0, $a0, 0
+# NORELAX-NEXT: R_LARCH_GOT_PC_LO12 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
# NORELAX-NEXT: ret
+# NORELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
# CHECKR: <_start>:
# CHECKR-NEXT: pcalau12i $a0, 0
# CHECKR-NEXT: R_LARCH_PCALA_HI20 _start
# CHECKR-NEXT: R_LARCH_RELAX *ABS*
-# CHECKR-NEXT: addi.d $a0, $a0, 0
+# CHECKR-NEXT: addi.d $a0, $a0, 0
# CHECKR-NEXT: R_LARCH_PCALA_LO12 _start
# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: pcalau12i $a0, 0
+# CHECKR-NEXT: R_LARCH_GOT_PC_HI20 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: ld.d $a0, $a0, 0
+# CHECKR-NEXT: R_LARCH_GOT_PC_LO12 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
# CHECKR-NEXT: nop
# CHECKR-NEXT: R_LARCH_ALIGN *ABS*+0xc
# CHECKR-NEXT: nop
@@ -56,5 +70,6 @@
.global _start
_start:
la.pcrel $a0, _start
+ la.got $a0, _start
.p2align 4
ret
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
new file mode 100644
index 0000000000000..a417d89e9fa2e
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -0,0 +1,62 @@
+# REQUIRES: loongarch
+
+# 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: 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 %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=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
+
+# RELAX-LABEL: <_start>:
+## offset = 0x14000 - 0x10000 = 4096<<2
+# RELAX-NEXT: 10000: pcaddi $a0, 4096
+# RELAX-NEXT: pcaddi $a0, 4095
+# RELAX-NEXT: pcaddi $a0, 4094
+# RELAX-NEXT: pcaddi $a0, 4093
+
+# NORELAX32-LABEL: <_start>:
+## offset exceed range of pcaddi
+## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0
+# NORELAX32-NEXT: 10000: pcalau12i $a0, 1024
+# 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: addi.w $a0, $a0, 0
+# NORELAX32-NEXT: pcalau12i $a0, 1024
+# NORELAX32-NEXT: ld.w $a0, $a0, 4
+
+# NORELAX64-LABEL: <_start>:
+## offset exceed range of pcaddi
+## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0
+# NORELAX64-NEXT: 10000: pcalau12i $a0, 1024
+# 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: addi.d $a0, $a0, 0
+# NORELAX64-NEXT: pcalau12i $a0, 1024
+# NORELAX64-NEXT: ld.d $a0, $a0, 8
+
+.section .text
+.global _start
+_start:
+ la.local $a0, sym
+ la.global $a0, sym
+ la.pcrel $a0, sym
+ la.got $a0, sym
+
+.section .data
+sym:
+ .zero 4
>From abc1a458c7edc2d44e4f9295aa6654b4cd6ac9d8 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Mon, 30 Dec 2024 19:29:43 +0800
Subject: [PATCH 04/20] Add test for got symbols relaxation.
Similar to aarch64-adrp-ldr-got-symbols.s.
---
...loongarch-relax-pc-hi20-lo12-got-symbols.s | 90 +++++++++++++++++++
1 file changed, 90 insertions(+)
create mode 100644 lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
new file mode 100644
index 0000000000000..bafb631bccb91
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
@@ -0,0 +1,90 @@
+## This test verifies that the pair pcalau12i + ld.w/d is relaxed/not relaxed
+## depending on the target symbol properties.
+
+# REQUIRES: loongarch
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax symbols.s -o symbols.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax symbols.s -o symbols.64.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax abs.s -o abs.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax abs.s -o abs.64.o
+
+# RUN: ld.lld --shared -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so
+# RUN: ld.lld --shared -Tlinker.t symbols.64.o abs.64.o -o symbols.64.so
+# RUN: llvm-objdump -d --no-show-raw-insn symbols.32.so | FileCheck --check-prefixes=LIB %s
+# RUN: llvm-objdump -d --no-show-raw-insn symbols.64.so | FileCheck --check-prefixes=LIB %s
+
+# RUN: ld.lld -Tlinker.t -z undefs symbols.32.o abs.32.o -o symbols.32
+# RUN: ld.lld -Tlinker.t -z undefs symbols.64.o abs.64.o -o symbols.64
+# RUN: llvm-objdump -d --no-show-raw-insn symbols.32 | FileCheck --check-prefixes=EXE %s
+# RUN: llvm-objdump -d --no-show-raw-insn symbols.64 | FileCheck --check-prefixes=EXE %s
+
+
+## Symbol 'hidden_sym' is nonpreemptible, the relaxation should be applied.
+LIB: pcaddi $a0, {{[0-9]+}}
+## Symbol 'global_sym' is preemptible, no relaxations should be applied.
+LIB-NEXT: pcalau12i $a1, 4
+LIB-NEXT: ld.{{[wd]}} $a1, $a1, {{[0-9]+}}
+## Symbol 'undefined_sym' is undefined, no relaxations should be applied.
+LIB-NEXT: pcalau12i $a2, 4
+LIB-NEXT: ld.{{[wd]}} $a2, $a2, {{[0-9]+}}
+## Symbol 'ifunc_sym' is STT_GNU_IFUNC, no relaxations should be applied.
+LIB-NEXT: pcalau12i $a3, 4
+LIB-NEXT: ld.{{[wd]}} $a3, $a3, {{[0-9]+}}
+## Symbol 'abs_sym' is absolute, no relaxations should be applied.
+LIB-NEXT: pcalau12i $a4, 4
+LIB-NEXT: ld.{{[wd]}} $a4, $a4, {{[0-9]+}}
+
+
+## Symbol 'hidden_sym' is nonpreemptible, the relaxation should be applied.
+EXE: pcaddi $a0, {{[0-9]+}}
+## Symbol 'global_sym' is nonpreemptible, the relaxation should be applied.
+EXE-NEXT: pcaddi $a1, {{[0-9]+}}
+## Symbol 'undefined_sym' is undefined, no relaxations should be applied.
+EXE-NEXT: pcalau12i $a2, 4
+EXE-NEXT: ld.{{[wd]}} $a2, $a2, {{[0-9]+}}
+## Symbol 'ifunc_sym' is STT_GNU_IFUNC, no relaxations should be applied.
+EXE-NEXT: pcalau12i $a3, 4
+EXE-NEXT: ld.{{[wd]}} $a3, $a3, {{[0-9]+}}
+## Symbol 'abs_sym' is absolute, relaxations may be applied in -no-pie mode.
+EXE-NEXT: pcaddi $a4, -{{[0-9]+}}
+
+
+## The linker script ensures that .rodata and .text are near (>4M) so that
+## the pcalau12i+ld.w/d pair can be relaxed to pcaddi.
+#--- linker.t
+SECTIONS {
+ .text 0x10000: { *(.text) }
+ .rodata 0x14000: { *(.rodata) }
+}
+
+# This symbol is defined in a separate file to prevent the definition from
+# being folded into the instructions that reference it.
+#--- abs.s
+.global abs_sym
+.hidden abs_sym
+abs_sym = 0x1000
+
+#--- symbols.s
+.rodata
+.hidden hidden_sym
+hidden_sym:
+.word 10
+
+.global global_sym
+global_sym:
+.word 10
+
+.text
+.type ifunc_sym STT_GNU_IFUNC
+.hidden ifunc_sym
+ifunc_sym:
+ nop
+
+.global _start
+_start:
+ la.got $a0, hidden_sym
+ la.got $a1, global_sym
+ la.got $a2, undefined_sym
+ la.got $a3, ifunc_sym
+ la.got $a4, abs_sym
>From 1b1804e3e26970cdf92ff1998d33a3f6ec59581d Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Wed, 15 Jan 2025 13:56:26 +0800
Subject: [PATCH 05/20] Modify test. NFC
Dependency on https://github.com/llvm/llvm-project/pull/123017
---
lld/test/ELF/loongarch-relax-align.s | 14 +++++++-------
lld/test/ELF/loongarch-relax-emit-relocs.s | 8 ++++----
.../ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s | 8 ++++----
lld/test/ELF/loongarch-relax-pc-hi20-lo12.s | 12 ++++++------
4 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s
index 9eaff9144d85e..66a8ed3abf71e 100644
--- a/lld/test/ELF/loongarch-relax-align.s
+++ b/lld/test/ELF/loongarch-relax-align.s
@@ -2,10 +2,10 @@
# 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: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o -o %t.32
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o --no-relax -o %t.32n
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o --no-relax -o %t.64n
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --relax %t.32.o -o %t.32
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --relax %t.64.o -o %t.64
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.32.o -o %t.32n
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.64.o -o %t.64n
# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX,NOOLD %s
# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX,NOOLD %s
# RUN: llvm-objdump -td --no-show-raw-insn %t.32n | FileCheck --check-prefixes=NORELAX,NOOLD %s
@@ -13,13 +13,13 @@
## Test the R_LARCH_ALIGN without symbol index.
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.o64.o --defsym=old=1
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.o64.o -o %t.o64
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.o64.o --no-relax -o %t.o64n
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --relax %t.o64.o -o %t.o64
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.o64.o -o %t.o64n
# RUN: llvm-objdump -td --no-show-raw-insn %t.o64 | FileCheck --check-prefixes=RELAX,OLD %s
# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck --check-prefixes=NORELAX,OLD %s
## -r keeps section contents unchanged.
-# RUN: ld.lld -r %t.64.o -o %t.64.r
+# RUN: ld.lld -r --relax %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr --no-show-raw-insn %t.64.r | FileCheck %s --check-prefix=CHECKR
# NOOLD: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index 9f3206b7ce54c..a02cd272aba5b 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -3,13 +3,13 @@
# 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: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.32.o -o %t.32
-# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.64.o -o %t.64
+# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.32.o -o %t.32
+# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.64.o -o %t.64
# RUN: llvm-objdump -dr %t.32 | FileCheck %s --check-prefix=RELAX
# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
## -r should keep original relocations.
-# RUN: ld.lld -r %t.64.o -o %t.64.r
+# RUN: ld.lld --relax -r %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
## --no-relax should keep original relocations.
@@ -58,7 +58,7 @@
# CHECKR-NEXT: pcalau12i $a0, 0
# CHECKR-NEXT: R_LARCH_GOT_PC_HI20 _start
# CHECKR-NEXT: R_LARCH_RELAX *ABS*
-# CHECKR-NEXT: ld.d $a0, $a0, 0
+# CHECKR-NEXT: ld.d $a0, $a0, 0
# CHECKR-NEXT: R_LARCH_GOT_PC_LO12 _start
# CHECKR-NEXT: R_LARCH_RELAX *ABS*
# CHECKR-NEXT: nop
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
index bafb631bccb91..0a75d2289209c 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
@@ -9,13 +9,13 @@
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax abs.s -o abs.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax abs.s -o abs.64.o
-# RUN: ld.lld --shared -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so
-# RUN: ld.lld --shared -Tlinker.t symbols.64.o abs.64.o -o symbols.64.so
+# RUN: ld.lld --shared --relax -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so
+# RUN: ld.lld --shared --relax -Tlinker.t symbols.64.o abs.64.o -o symbols.64.so
# RUN: llvm-objdump -d --no-show-raw-insn symbols.32.so | FileCheck --check-prefixes=LIB %s
# RUN: llvm-objdump -d --no-show-raw-insn symbols.64.so | FileCheck --check-prefixes=LIB %s
-# RUN: ld.lld -Tlinker.t -z undefs symbols.32.o abs.32.o -o symbols.32
-# RUN: ld.lld -Tlinker.t -z undefs symbols.64.o abs.64.o -o symbols.64
+# RUN: ld.lld --relax -Tlinker.t -z undefs symbols.32.o abs.32.o -o symbols.32
+# RUN: ld.lld --relax -Tlinker.t -z undefs symbols.64.o abs.64.o -o symbols.64
# RUN: llvm-objdump -d --no-show-raw-insn symbols.32 | FileCheck --check-prefixes=EXE %s
# RUN: llvm-objdump -d --no-show-raw-insn symbols.64 | FileCheck --check-prefixes=EXE %s
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
index a417d89e9fa2e..760fe77d774e3 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -3,18 +3,18 @@
# 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: 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: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 --relax %t.32.o -o %t.32
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 --relax %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 %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: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 --relax %t.32.o -shared -o %t.32s
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 --relax %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=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: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 --relax %t.32.o -o %t.32o
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 --relax %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
>From 30cb3827458cf4fc585aa72f62f77971d8b47a36 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Mon, 20 Jan 2025 08:51:15 +0800
Subject: [PATCH 06/20] Add check for register.
---
lld/ELF/Arch/LoongArch.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 07ca66700f648..b999e7fd27ae9 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -134,6 +134,8 @@ static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t 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);
@@ -816,7 +818,11 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
// addi.w/d.
// * The destination register of pcalau12i is guaranteed to be used only by
// the immediately following instruction.
+ const uint32_t currInsn = read32le(sec.content().data() + rHi20.offset);
const uint32_t nextInsn = read32le(sec.content().data() + rLo12.offset);
+ // Check if use the same register.
+ if (getD5(currInsn) != getJ5(nextInsn) || getJ5(nextInsn) != getD5(nextInsn))
+ return;
sec.relaxAux->relocTypes[i] = R_LARCH_RELAX;
sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
>From f1f995b5fc8e90126b5825d52b9c75cd45d27cfc Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Thu, 26 Dec 2024 11:32:33 +0800
Subject: [PATCH 07/20] Relax call36/tail36.
Instructions with relocation `R_LARCH_CALL36` may be relax as follows:
```
From:
pcaddu18i $dest, %call36(foo)
R_LARCH_CALL36, R_LARCH_RELAX
jirl $r, $dest, 0
To:
b/bl foo # bl if r=$ra, b if r=$zero
R_LARCH_B26
```
---
lld/ELF/Arch/LoongArch.cpp | 41 ++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index b999e7fd27ae9..0aa0cf5b657a0 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -58,6 +58,8 @@ enum Op {
LD_W = 0x28800000,
LD_D = 0x28c00000,
JIRL = 0x4c000000,
+ B = 0x50000000,
+ BL = 0x54000000,
};
enum Reg {
@@ -830,6 +832,37 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
remove = 4;
}
+// Relax code sequence.
+// From:
+// pcaddu18i $ra, %call36(foo)
+// jirl $ra, $ra, 0
+// To:
+// b/bl foo
+static void relaxCall36(Ctx &ctx, const InputSection &sec, size_t i,
+ uint64_t loc, Relocation &r, uint32_t &remove) {
+ const uint64_t symLocal =
+ (r.expr == R_PLT_PC ? r.sym->getPltVA(ctx) : r.sym->getVA(ctx)) +
+ r.addend;
+
+ const int64_t distance = symLocal - loc;
+ // Check if the distance aligns 4 bytes or exceeds the range of b[l].
+ if ((distance & 0x3) != 0 || !isInt<28>(distance))
+ return;
+
+ const uint32_t nextInsn = read32le(sec.content().data() + r.offset + 4);
+ if (getD5(nextInsn) == R_RA) {
+ // convert jirl to bl
+ sec.relaxAux->relocTypes[i] = R_LARCH_B26;
+ sec.relaxAux->writes.push_back(insn(BL, 0, 0, 0));
+ remove = 4;
+ } else if (getD5(nextInsn) == R_ZERO) {
+ // convert jirl to b
+ sec.relaxAux->relocTypes[i] = R_LARCH_B26;
+ sec.relaxAux->writes.push_back(insn(B, 0, 0, 0));
+ remove = 4;
+ }
+}
+
static bool relax(Ctx &ctx, InputSection &sec) {
const uint64_t secAddr = sec.getVA();
const MutableArrayRef<Relocation> relocs = sec.relocs();
@@ -874,6 +907,10 @@ static bool relax(Ctx &ctx, InputSection &sec) {
if (isPairRelaxable(relocs, i))
relaxPCHi20Lo12(ctx, sec, i, loc, r, relocs[i + 2], remove);
break;
+ case R_LARCH_CALL36:
+ if (relaxable(relocs, i))
+ relaxCall36(ctx, sec, i, loc, r, remove);
+ break;
}
// For all anchors whose offsets are <= r.offset, they are preceded by
@@ -977,6 +1014,10 @@ void LoongArch::finalizeRelax(int passes) const {
// RelExpr is needed for relocating.
r.expr = r.sym->hasFlag(NEEDS_PLT) ? R_PLT_PC : R_PC;
break;
+ case R_LARCH_B26:
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
+ break;
default:
llvm_unreachable("unsupported type");
}
>From f227ae532236e20148a872c811721a8de4e16318 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 27 Dec 2024 14:37:40 +0800
Subject: [PATCH 08/20] modify test for call36/tail36.
---
lld/test/ELF/loongarch-relax-call36-2.s | 63 +++++++++
lld/test/ELF/loongarch-relax-call36.s | 135 +++++++++++++++++++
lld/test/ELF/loongarch-relax-emit-relocs-2.s | 61 +++++++++
3 files changed, 259 insertions(+)
create mode 100644 lld/test/ELF/loongarch-relax-call36-2.s
create mode 100644 lld/test/ELF/loongarch-relax-call36.s
create mode 100644 lld/test/ELF/loongarch-relax-emit-relocs-2.s
diff --git a/lld/test/ELF/loongarch-relax-call36-2.s b/lld/test/ELF/loongarch-relax-call36-2.s
new file mode 100644
index 0000000000000..1c216a9bdc35e
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-call36-2.s
@@ -0,0 +1,63 @@
+# REQUIRES: loongarch
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.o
+
+# RUN: ld.lld -T lds a.o -o a
+# RUN: llvm-objdump -d --no-show-raw-insn a | FileCheck %s --check-prefixes=RELAX,RELAX-MID
+
+## Unsure whether this needs a diagnostic. GNU ld allows this.
+# RUN: ld.lld -T lds -pie a.o -o a.pie
+# RUN: llvm-objdump -d --no-show-raw-insn a.pie | FileCheck %s --check-prefixes=RELAX,RELAX-MID
+
+# RUN: ld.lld -T lds -pie -z notext -z ifunc-noplt a.o -o a.ifunc-noplt
+# RUN: llvm-objdump -d --no-show-raw-insn a.ifunc-noplt | FileCheck %s --check-prefixes=RELAX,NORELAX-MID
+
+# RELAX-LABEL: <_start>:
+## offset = 0x10000000 - 0x8000000 = 0x8000000(134217728), hi=512, lo18=0
+# RELAX-NEXT: 8000000: pcaddu18i $ra, 512
+# RELAX-NEXT: jirl $ra, $ra, 0
+# RELAX-NEXT: bl 134217720
+# RELAX-NEXT: bl -134217728
+## offset = 12 - 0x8000010 = -0x8000004(-134217732), hi=512, lo18=-4
+# RELAX-NEXT: 8000010: pcaddu18i $ra, -512
+# RELAX-NEXT: jirl $ra, $ra, -4
+# RELAX-EMPTY:
+
+# RELAX-MID-LABEL: <.mid>:
+## offset = 0x8010000 - 0x8008000 = 32768
+# RELAX-MID-NEXT: 8008000: bl 32768
+# RELAX-MID-NEXT: b 32764
+# RELAX-MID-EMPTY:
+
+# NORELAX-MID-LABEL: <.mid>:
+# NORELAX-MID-NEXT: 8008000: pcaddu18i $ra, 0
+# NORELAX-MID-NEXT: jirl $ra, $ra, 0
+# NORELAX-MID-NEXT: pcaddu18i $t0, 0
+# NORELAX-MID-NEXT: jr $t0
+# NORELAX-MID-EMPTY:
+
+#--- a.s
+.global _start, ifunc
+_start:
+ call36 pos # exceed positive range (.text+0x7fffffc), not relaxed
+ call36 pos # relaxed
+ call36 neg # relaxed
+ call36 neg # exceed negative range (.text+16-0x8000000), not relaxed
+
+.section .mid,"ax", at progbits
+.balign 16
+ call36 ifunc at plt # enable ifunc, not relaxed
+ tail36 $t0, ifunc at plt # enable ifunc, not relaxed
+
+.type ifunc, @gnu_indirect_function
+ifunc:
+ ret
+
+#--- lds
+SECTIONS {
+ .text 0x8000000 : { *(.text) }
+ .mid 0x8008000 : { *(.mid) }
+ .iplt 0x8010000 : { *(.iplt) }
+}
+neg = 12;
+pos = 0x10000000;
diff --git a/lld/test/ELF/loongarch-relax-call36.s b/lld/test/ELF/loongarch-relax-call36.s
new file mode 100644
index 0000000000000..57ed214c9eb2e
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-call36.s
@@ -0,0 +1,135 @@
+# REQUIRES: loongarch
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.64.o
+# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax b.s -o b.64.o
+# RUN: ld.lld -shared -soname=b.so b.64.o -o b.64.so
+# RUN: ld.lld -T lds a.64.o b.64.so -o 64
+# RUN: llvm-objdump -td --no-show-raw-insn 64 | FileCheck %s --check-prefix=RELAX
+
+## --no-relax disables relaxation.
+# RUN: ld.lld -T lds a.64.o b.64.so --no-relax -o 64.norelax
+# RUN: llvm-objdump -td --no-show-raw-insn 64.norelax | FileCheck %s --check-prefix=NORELAX
+
+# RELAX: {{0*}}00010000 g .text {{0*}}0000001c _start
+# RELAX: {{0*}}0001001c g .text {{0*}}00000000 _start_end
+# RELAX: {{0*}}00010808 g .mid {{0*}}00000000 mid_end
+# RELAX: {{0*}}10010010 g .high {{0*}}00000000 high_end
+
+# RELAX-LABEL: <_start>:
+## offset = 0x10018 - 0x10000 = 24
+# RELAX-NEXT: 10000: bl 24 <a>
+# RELAX-NEXT: b 20 <a>
+# RELAX-NEXT: nop
+# RELAX-NEXT: nop
+## offset = .plt(0x10400)+32 - 0x10010 = 1040
+# RELAX-NEXT: 10010: bl 1040 <bar+0x10420>
+# RELAX-NEXT: b 1036 <bar+0x10420>
+# RELAX-EMPTY:
+# RELAX-NEXT: <a>:
+# RELAX-NEXT: 10018: ret
+# RELAX-EMPTY:
+
+# RELAX-LABEL: <.mid>:
+## offset = 0x10000 - 0x10800 = -2048
+# RELAX-NEXT: 10800: bl -2048 <_start>
+# RELAX-NEXT: b -2052 <_start>
+# RELAX-EMPTY:
+
+# RELAX-LABEL: <.mid2>:
+## offset = 0x10000 - 0x1010000 = -16777216
+# RELAX-NEXT: 1010000: bl -16777216 <_start>
+# RELAX-NEXT: b -16777220 <_start>
+# RELAX-EMPTY:
+
+# RELAX-LABEL: <.high>:
+## offset = 0x10000 - 0x10010000 = -0x10000000, hi=-1024, lo18=0
+# RELAX-NEXT: 10010000: pcaddu18i $ra, -1024
+# RELAX-NEXT: jirl $ra, $ra, 0
+# RELAX-NEXT: pcaddu18i $t0, -1024
+# RELAX-NEXT: jirl $zero, $t0, -8
+# RELAX-EMPTY:
+
+
+# NORELAX-LABEL: <_start>:
+## offset = 0x10020 - 0x10000 = 0x20, hi=0, lo18=32
+# NORELAX-NEXT: 10000: pcaddu18i $ra, 0
+# NORELAX-NEXT: jirl $ra, $ra, 32
+## offset = 0x10020 - 0x10008 = 0x18, hi=0, lo18=24
+# NORELAX-NEXT: 10008: pcaddu18i $t0, 0
+# NORELAX-NEXT: jirl $zero, $t0, 24
+## offset = .plt(0x10400)+32 - 0x10010 = 0x410, hi=0, lo18=1040
+# NORELAX-NEXT: 10010: pcaddu18i $ra, 0
+# NORELAX-NEXT: jirl $ra, $ra, 1040
+## offset = .plt(0x10400)+32 - 0x10018 = 0x408, hi=0, lo18=1032
+# NORELAX-NEXT: 10018: pcaddu18i $t0, 0
+# NORELAX-NEXT: jirl $zero, $t0, 1032
+# NORELAX-EMPTY:
+# NORELAX-NEXT: <a>:
+# NORELAX-NEXT: 10020: ret
+# NORELAX-EMPTY:
+
+# NORELAX-LABEL: <.mid>:
+## offset = 0x10000 - 0x10800 = -0x800, hi=0, lo18=-2048
+# NORELAX-NEXT: 10800: pcaddu18i $ra, 0
+# NORELAX-NEXT: jirl $ra, $ra, -2048
+# NORELAX-NEXT: pcaddu18i $t0, 0
+# NORELAX-NEXT: jirl $zero, $t0, -2056
+# NORELAX-EMPTY:
+
+# NORELAX-LABEL: <.mid2>:
+## offset = 0x10000 - 0x1010000 = -0x1000000, hi=-64, lo18=0
+# NORELAX-NEXT: 1010000: pcaddu18i $ra, -64
+# NORELAX-NEXT: jirl $ra, $ra, 0
+# NORELAX-NEXT: pcaddu18i $t0, -64
+# NORELAX-NEXT: jirl $zero, $t0, -8
+# NORELAX-EMPTY:
+
+# NORELAX-LABEL: <.high>:
+## offset = 0x10000 - 0x10010000 = -0x10000000, hi=-1024, lo18=0
+# NORELAX-NEXT: 10010000: pcaddu18i $ra, -1024
+# NORELAX-NEXT: jirl $ra, $ra, 0
+# NORELAX-NEXT: pcaddu18i $t0, -1024
+# NORELAX-NEXT: jirl $zero, $t0, -8
+# NORELAX-EMPTY:
+
+#--- a.s
+.global _start, _start_end
+_start:
+ call36 a # relaxed. la64: bl
+ tail36 $t0, a at plt # relaxed. la64: b
+.balign 16
+ call36 bar # PLT call36 can be relaxed. la64: bl
+ tail36 $t0, bar # PLT tail36 can be relaxed. la64: bl
+
+a:
+ ret
+.size _start, . - _start
+_start_end:
+
+.section .mid,"ax", at progbits
+ call36 _start at plt # relaxed. la64: bl
+ tail36 $t0, _start at plt # relaxed. la64: b
+
+.section .mid2,"ax", at progbits
+ call36 _start at plt # relaxed. la64: bl
+ tail36 $t0, _start at plt # relaxed. la64: b
+
+.section .high,"ax", at progbits
+ call36 _start at plt # exceed range, not relaxed
+ tail36 $t0,_start at plt # exceed range, not relaxed
+
+#--- b.s
+.globl bar
+bar:
+ ret
+
+#--- lds
+SECTIONS {
+ .text 0x10000 : { *(.text) }
+ .plt 0x10400 : { *(.plt) }
+ .mid 0x10800 : { *(.mid); mid_end = .; }
+ .mid2 0x1010000 : { *(.mid2) }
+ .high 0x10010000 : { *(.high); high_end = .; }
+}
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs-2.s b/lld/test/ELF/loongarch-relax-emit-relocs-2.s
new file mode 100644
index 0000000000000..31cae939eca71
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-emit-relocs-2.s
@@ -0,0 +1,61 @@
+# REQUIRES: loongarch
+## Test that we can handle --emit-relocs while relaxing.
+## Call36 and tail36 need LA64 basic integer, so they donot have 32-bit version.
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
+# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
+
+## -r should keep original relocations.
+# RUN: ld.lld -r %t.64.o -o %t.64.r
+# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
+
+## --no-relax should keep original relocations.
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
+# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
+
+# RELAX: 00010000 <_start>:
+# RELAX-NEXT: bl 0
+# RELAX-NEXT: R_LARCH_B26 _start
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: b -4
+# RELAX-NEXT: R_LARCH_B26 _start
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: nop
+# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# RELAX-NEXT: nop
+# RELAX-NEXT: ret
+
+# CHECKR: <_start>:
+# CHECKR-NEXT: pcaddu18i $ra, 0
+# CHECKR-NEXT: R_LARCH_CALL36 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: jirl $ra, $ra, 0
+# CHECKR-NEXT: pcaddu18i $t0, 0
+# CHECKR-NEXT: R_LARCH_CALL36 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: jr $t0
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: ret
+
+# NORELAX: <_start>:
+# NORELAX-NEXT: pcaddu18i $ra, 0
+# NORELAX-NEXT: R_LARCH_CALL36 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: jirl $ra, $ra, 0
+# NORELAX-NEXT: pcaddu18i $t0, 0
+# NORELAX-NEXT: R_LARCH_CALL36 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: jirl $zero, $t0, -8
+# NORELAX-NEXT: ret
+# NORELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
+
+.global _start
+_start:
+ call36 _start
+ tail36 $t0, _start
+ .p2align 4
+ ret
>From f2aae15f701863d03edd32657824a97f66696e8d Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Thu, 16 Jan 2025 21:50:14 +0800
Subject: [PATCH 09/20] Modify test. Add the option --relax.
---
lld/test/ELF/loongarch-relax-call36-2.s | 6 +++---
lld/test/ELF/loongarch-relax-call36.s | 6 +++---
lld/test/ELF/loongarch-relax-emit-relocs-2.s | 6 +++---
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/lld/test/ELF/loongarch-relax-call36-2.s b/lld/test/ELF/loongarch-relax-call36-2.s
index 1c216a9bdc35e..71650aefe9432 100644
--- a/lld/test/ELF/loongarch-relax-call36-2.s
+++ b/lld/test/ELF/loongarch-relax-call36-2.s
@@ -2,14 +2,14 @@
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.o
-# RUN: ld.lld -T lds a.o -o a
+# RUN: ld.lld --relax -T lds a.o -o a
# RUN: llvm-objdump -d --no-show-raw-insn a | FileCheck %s --check-prefixes=RELAX,RELAX-MID
## Unsure whether this needs a diagnostic. GNU ld allows this.
-# RUN: ld.lld -T lds -pie a.o -o a.pie
+# RUN: ld.lld --relax -T lds -pie a.o -o a.pie
# RUN: llvm-objdump -d --no-show-raw-insn a.pie | FileCheck %s --check-prefixes=RELAX,RELAX-MID
-# RUN: ld.lld -T lds -pie -z notext -z ifunc-noplt a.o -o a.ifunc-noplt
+# RUN: ld.lld --relax -T lds -pie -z notext -z ifunc-noplt a.o -o a.ifunc-noplt
# RUN: llvm-objdump -d --no-show-raw-insn a.ifunc-noplt | FileCheck %s --check-prefixes=RELAX,NORELAX-MID
# RELAX-LABEL: <_start>:
diff --git a/lld/test/ELF/loongarch-relax-call36.s b/lld/test/ELF/loongarch-relax-call36.s
index 57ed214c9eb2e..bda0c4f05da91 100644
--- a/lld/test/ELF/loongarch-relax-call36.s
+++ b/lld/test/ELF/loongarch-relax-call36.s
@@ -4,12 +4,12 @@
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.64.o
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax b.s -o b.64.o
-# RUN: ld.lld -shared -soname=b.so b.64.o -o b.64.so
-# RUN: ld.lld -T lds a.64.o b.64.so -o 64
+# RUN: ld.lld --relax -shared -soname=b.so b.64.o -o b.64.so
+# RUN: ld.lld --relax -T lds a.64.o b.64.so -o 64
# RUN: llvm-objdump -td --no-show-raw-insn 64 | FileCheck %s --check-prefix=RELAX
## --no-relax disables relaxation.
-# RUN: ld.lld -T lds a.64.o b.64.so --no-relax -o 64.norelax
+# RUN: ld.lld --no-relax -T lds a.64.o b.64.so -o 64.norelax
# RUN: llvm-objdump -td --no-show-raw-insn 64.norelax | FileCheck %s --check-prefix=NORELAX
# RELAX: {{0*}}00010000 g .text {{0*}}0000001c _start
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs-2.s b/lld/test/ELF/loongarch-relax-emit-relocs-2.s
index 31cae939eca71..eddfc46b1ad08 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs-2.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs-2.s
@@ -3,15 +3,15 @@
## Call36 and tail36 need LA64 basic integer, so they donot have 32-bit version.
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
-# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
+# RUN: ld.lld --relax -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
## -r should keep original relocations.
-# RUN: ld.lld -r %t.64.o -o %t.64.r
+# RUN: ld.lld --relax -r %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
## --no-relax should keep original relocations.
-# RUN: ld.lld -Ttext=0x10000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
+# RUN: ld.lld --no-relax -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64.norelax
# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
# RELAX: 00010000 <_start>:
>From 7993434e2973437b010034051003f8c03d8eff71 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 27 Dec 2024 19:29:32 +0800
Subject: [PATCH 10/20] Relax TLS LE/GD/LD.
In local-exec form, the code sequence is converted as follows:
```
From:
lu12i.w $rd, %le_hi20_r(sym)
R_LARCH_TLS_LE_HI20_R, R_LARCH_RELAX
add.w/d $rd, $rd, $tp, %le_add_r(sym)
R_LARCH_TLS_LE_ADD_R, R_LARCH_RELAX
addi/ld/st.w/d $rd, $rd, %le_lo12_r(sym)
R_LARCH_TLS_LE_LO12_R, R_LARCH_RELAX
To:
addi/ld/st.w/d $rd, $tp, %le_lo12_r(sym)
R_LARCH_TLS_LE_LO12_R
```
In global-dynamic or local-dynamic, the code sequence is converted as
follows:
```
From:
pcalau12i $a0, %ld_pc_hi20(sym) | %gd_pc_hi20(sym)
R_LARCH_TLS_GD_PC_HI20 | R_LARCH_TLS_LD_PC_HI20, R_LARCH_RELAX
addi.w/d $a0, $a0, %got_pc_lo12(sym) | %got_pc_lo12(sym)
R_LARCH_GOT_PC_LO12, R_LARCH_RELAX
To:
pcaddi $a0, %got_pc_lo12(sym) | %got_pc_lo12(sym)
R_LARCH_TLS_GD_PCREL20_S2 | R_LARCH_TLS_LD_PCREL20_S2
```
Note: For initial-exec form, since it involves the conversion from IE to
LE, we will implement it in a future patch.
---
lld/ELF/Arch/LoongArch.cpp | 68 +++++++++++++++++++++++++++++++++++---
1 file changed, 64 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 0aa0cf5b657a0..2d6d86d2ca63b 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -761,10 +761,10 @@ static bool isPairRelaxable(ArrayRef<Relocation> relocs, size_t i) {
// Relax code sequence.
// From:
-// pcalau12i $a0, %pc_hi20(sym)
-// addi.w/d $a0, $a0, %pc_lo12(sym)
+// pcalau12i $a0, %pc_hi20(sym) | %ld_pc_hi20(sym) | %gd_pc_hi20(sym)
+// addi.w/d $a0, $a0, %pc_lo12(sym) | %got_pc_lo12(sym) | %got_pc_lo12(sym)
// To:
-// pcaddi $a0, %pc_lo12(sym)
+// pcaddi $a0, %pc_lo12(sym) | %got_pc_lo12(sym) | %got_pc_lo12(sym)
//
// From:
// pcalau12i $a0, %got_pc_hi20(sym_got)
@@ -778,6 +778,10 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
if (!((rHi20.type == R_LARCH_PCALA_HI20 &&
rLo12.type == R_LARCH_PCALA_LO12) ||
(rHi20.type == R_LARCH_GOT_PC_HI20 &&
+ rLo12.type == R_LARCH_GOT_PC_LO12) ||
+ (rHi20.type == R_LARCH_TLS_GD_PC_HI20 &&
+ rLo12.type == R_LARCH_GOT_PC_LO12) ||
+ (rHi20.type == R_LARCH_TLS_LD_PC_HI20 &&
rLo12.type == R_LARCH_GOT_PC_LO12)))
return;
@@ -798,6 +802,8 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
else if (rHi20.expr == RE_LOONGARCH_PAGE_PC ||
rHi20.expr == RE_LOONGARCH_GOT_PAGE_PC)
symBase = rHi20.sym->getVA(ctx);
+ else if (rHi20.expr == RE_LOONGARCH_TLSGD_PAGE_PC)
+ symBase = ctx.in.got->getGlobalDynAddr(*rHi20.sym);
else {
Err(ctx) << getErrorLoc(ctx, (const uint8_t *)loc) << "unknown expr ("
<< rHi20.expr << ") against symbol " << rHi20.sym
@@ -827,7 +833,12 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
return;
sec.relaxAux->relocTypes[i] = R_LARCH_RELAX;
- sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
+ if (rHi20.type == R_LARCH_TLS_GD_PC_HI20)
+ sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_GD_PCREL20_S2;
+ else if (rHi20.type == R_LARCH_TLS_LD_PC_HI20)
+ sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_LD_PCREL20_S2;
+ else
+ sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
sec.relaxAux->writes.push_back(insn(PCADDI, getD5(nextInsn), 0, 0));
remove = 4;
}
@@ -863,6 +874,35 @@ static void relaxCall36(Ctx &ctx, const InputSection &sec, size_t i,
}
}
+// Relax code sequence.
+// From:
+// lu12i.w $rd, %le_hi20_r(sym)
+// add.w/d $rd, $rd, $tp, %le_add_r(sym)
+// addi/ld/st.w/d $rd, $rd, %le_lo12_r(sym)
+// To:
+// addi/ld/st.w/d $rd, $tp, %le_lo12_r(sym)
+static void relaxTlsLe(Ctx &ctx, const InputSection &sec, size_t i,
+ uint64_t loc, Relocation &r, uint32_t &remove) {
+ uint64_t val = r.sym->getVA(ctx, r.addend);
+ // Check if the val exceeds the range of addi/ld/st.
+ if (!isInt<12>(val))
+ return;
+ uint32_t currInsn = read32le(sec.content().data() + r.offset);
+ switch (r.type) {
+ case R_LARCH_TLS_LE_HI20_R:
+ case R_LARCH_TLS_LE_ADD_R:
+ sec.relaxAux->relocTypes[i] = R_LARCH_RELAX;
+ remove = 4;
+ break;
+ case R_LARCH_TLS_LE_LO12_R:
+ currInsn =
+ insn(extractBits(currInsn, 31, 22) << 22, getD5(currInsn), R_TP, 0);
+ sec.relaxAux->writes.push_back(currInsn);
+ sec.relaxAux->relocTypes[i] = R_LARCH_TLS_LE_LO12_R;
+ break;
+ }
+}
+
static bool relax(Ctx &ctx, InputSection &sec) {
const uint64_t secAddr = sec.getVA();
const MutableArrayRef<Relocation> relocs = sec.relocs();
@@ -903,6 +943,8 @@ static bool relax(Ctx &ctx, InputSection &sec) {
}
case R_LARCH_PCALA_HI20:
case R_LARCH_GOT_PC_HI20:
+ case R_LARCH_TLS_GD_PC_HI20:
+ case R_LARCH_TLS_LD_PC_HI20:
// The overflow check for i+2 will be carried out in isPairRelaxable.
if (isPairRelaxable(relocs, i))
relaxPCHi20Lo12(ctx, sec, i, loc, r, relocs[i + 2], remove);
@@ -911,6 +953,12 @@ static bool relax(Ctx &ctx, InputSection &sec) {
if (relaxable(relocs, i))
relaxCall36(ctx, sec, i, loc, r, remove);
break;
+ case R_LARCH_TLS_LE_HI20_R:
+ case R_LARCH_TLS_LE_ADD_R:
+ case R_LARCH_TLS_LE_LO12_R:
+ if (relaxable(relocs, i))
+ relaxTlsLe(ctx, sec, i, loc, r, remove);
+ break;
}
// For all anchors whose offsets are <= r.offset, they are preceded by
@@ -1015,8 +1063,20 @@ void LoongArch::finalizeRelax(int passes) const {
r.expr = r.sym->hasFlag(NEEDS_PLT) ? R_PLT_PC : R_PC;
break;
case R_LARCH_B26:
+ case R_LARCH_TLS_LE_LO12_R:
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
+ break;
+ case R_LARCH_TLS_GD_PCREL20_S2:
+ // Note: R_LARCH_TLS_LD_PCREL20_S2 must also use R_TLSGD_PC instead
+ // of R_TLSLD_PC because the processing of relocation
+ // R_LARCH_TLS_LD_PC_HI20 is the same as R_LARCH_TLS_GD_PC_HI20. If
+ // not, the value obtained from getRelocTargetVA will be unexpected
+ // and lead to error.
+ case R_LARCH_TLS_LD_PCREL20_S2:
skip = 4;
write32le(p, aux.writes[writesIdx++]);
+ r.expr = R_TLSGD_PC;
break;
default:
llvm_unreachable("unsupported type");
>From 1e9aa529f34dbe6d61295980593c894d3074a7b2 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Sun, 29 Dec 2024 17:02:09 +0800
Subject: [PATCH 11/20] Add test for TLSLD/TLSGD when relax enabled.
---
lld/test/ELF/loongarch-tls-gd.s | 43 +++++++++++++++++++++++++++++++--
lld/test/ELF/loongarch-tls-ld.s | 40 ++++++++++++++++++++++++++++--
2 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/lld/test/ELF/loongarch-tls-gd.s b/lld/test/ELF/loongarch-tls-gd.s
index 2aecb44c17a34..27d9fdb7ee701 100644
--- a/lld/test/ELF/loongarch-tls-gd.s
+++ b/lld/test/ELF/loongarch-tls-gd.s
@@ -1,14 +1,17 @@
# REQUIRES: loongarch
# RUN: rm -rf %t && split-file %s %t
-## LoongArch psABI doesn't specify TLS relaxation. Though the code sequences are not
-## relaxed, dynamic relocations can be omitted for GD->LE relaxation.
+## LoongArch psABI doesn't specify TLS relaxation. It can be handled the same way as gcc:
+## (a) code sequence can be converted from `pcalau12i+addi.[wd]` to `pcaddi`.
+## (b) dynamic relocations can be omitted for LD->LE relaxation.
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/a.s -o %t/a.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %t/a.s -o %t/a.32.relax.o
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/bc.s -o %t/bc.32.o
# RUN: ld.lld -shared -soname=bc.so %t/bc.32.o -o %t/bc.32.so
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -o %t/a.64.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/a.s -mattr=+relax -o %t/a.64.relax.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/bc.s -o %t/bc.64.o
# RUN: ld.lld -shared -soname=bc.so %t/bc.64.o -o %t/bc.64.so
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/tga.s -o %t/tga.64.o
@@ -17,6 +20,9 @@
# RUN: ld.lld -shared %t/a.32.o %t/bc.32.o -o %t/gd.32.so
# RUN: llvm-readobj -r %t/gd.32.so | FileCheck --check-prefix=GD32-REL %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.32.so | FileCheck --check-prefix=GD32 %s
+# RUN: ld.lld -shared %t/a.32.relax.o %t/bc.32.o -o %t/gd.32.relax.so
+# RUN: llvm-readobj -r %t/gd.32.relax.so | FileCheck --check-prefix=GD32-REL-RELAX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.32.relax.so | FileCheck --check-prefix=GD32-RELAX %s
## LA32 GD -> LE
# RUN: ld.lld %t/a.32.o %t/bc.32.o %t/tga.32.o -o %t/le.32
@@ -35,6 +41,9 @@
# RUN: ld.lld -shared %t/a.64.o %t/bc.64.o -o %t/gd.64.so
# RUN: llvm-readobj -r %t/gd.64.so | FileCheck --check-prefix=GD64-REL %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.64.so | FileCheck --check-prefix=GD64 %s
+# RUN: ld.lld -shared %t/a.64.relax.o %t/bc.64.o -o %t/gd.64.relax.so
+# RUN: llvm-readobj -r %t/gd.64.relax.so | FileCheck --check-prefix=GD64-REL-RELAX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.64.relax.so | FileCheck --check-prefix=GD64-RELAX %s
## LA64 GD -> LE
# RUN: ld.lld %t/a.64.o %t/bc.64.o %t/tga.64.o -o %t/le.64
@@ -66,6 +75,21 @@
# GD32-NEXT: addi.w $a0, $a0, 792
# GD32-NEXT: bl 44
+# GD32-REL-RELAX: .rela.dyn {
+# GD32-REL-RELAX-NEXT: 0x20300 R_LARCH_TLS_DTPMOD32 a 0x0
+# GD32-REL-RELAX-NEXT: 0x20304 R_LARCH_TLS_DTPREL32 a 0x0
+# GD32-REL-RELAX-NEXT: 0x20308 R_LARCH_TLS_DTPMOD32 b 0x0
+# GD32-REL-RELAX-NEXT: 0x2030C R_LARCH_TLS_DTPREL32 b 0x0
+# GD32-REL-RELAX-NEXT: }
+
+## &DTPMOD(a) - . = 0x20300 - 0x10250 = 16428<<2
+# GD32-RELAX: 10250: pcaddi $a0, 16428
+# GD32-RELAX-NEXT: bl 44
+
+## &DTPMOD(b) - . = 0x20308 - 0x10258 = 16428<<2
+# GD32-RELAX: 10258: pcaddi $a0, 16428
+# GD32-RELAX-NEXT: bl 36
+
# GD64-REL: .rela.dyn {
# GD64-REL-NEXT: 0x204C0 R_LARCH_TLS_DTPMOD64 a 0x0
# GD64-REL-NEXT: 0x204C8 R_LARCH_TLS_DTPREL64 a 0x0
@@ -83,6 +107,21 @@
# GD64-NEXT: addi.d $a0, $a0, 1232
# GD64-NEXT: bl 36
+# GD64-REL-RELAX: .rela.dyn {
+# GD64-REL-RELAX-NEXT: 0x204C0 R_LARCH_TLS_DTPMOD64 a 0x0
+# GD64-REL-RELAX-NEXT: 0x204C8 R_LARCH_TLS_DTPREL64 a 0x0
+# GD64-REL-RELAX-NEXT: 0x204D0 R_LARCH_TLS_DTPMOD64 b 0x0
+# GD64-REL-RELAX-NEXT: 0x204D8 R_LARCH_TLS_DTPREL64 b 0x0
+# GD64-REL-RELAX-NEXT: }
+
+## &DTPMOD(a) - . = 0x204c0 - 0x10398 = 16458<<2
+# GD64-RELAX: 10398: pcaddi $a0, 16458
+# GD64-RELAX-NEXT: bl 52
+
+## &DTPMOD(b) - . = 0x204d0 - 0x103a0 = 16460<<2
+# GD64-RELAX: 103a0: pcaddi $a0, 16460
+# GD64-RELAX-NEXT: bl 44
+
# NOREL: no relocations
## .got contains pre-populated values: [a at dtpmod, a at dtprel, b at dtpmod, b at dtprel]
diff --git a/lld/test/ELF/loongarch-tls-ld.s b/lld/test/ELF/loongarch-tls-ld.s
index a5be3ad905b76..27adb1e17702a 100644
--- a/lld/test/ELF/loongarch-tls-ld.s
+++ b/lld/test/ELF/loongarch-tls-ld.s
@@ -1,12 +1,15 @@
# REQUIRES: loongarch
# RUN: rm -rf %t && split-file %s %t
-## LoongArch psABI doesn't specify TLS relaxation. Though the code sequences are not
-## relaxed, dynamic relocations can be omitted for LD->LE relaxation.
+## LoongArch psABI doesn't specify TLS relaxation. It can be handled the same way as gcc:
+## (a) code sequence can be converted from `pcalau12i+addi.[wd]` to `pcaddi`.
+## (b) dynamic relocations can be omitted for LD->LE relaxation.
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent %t/a.s -o %t/a.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --position-independent -mattr=+relax %t/a.s -o %t/a.32.relax.o
# RUN: llvm-mc --filetype=obj --triple=loongarch32 %t/tga.s -o %t/tga.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --position-independent %t/a.s -o %t/a.64.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --position-independent -mattr=+relax %t/a.s -o %t/a.64.relax.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/tga.s -o %t/tga.64.o
## LA32 LD
@@ -14,24 +17,34 @@
# RUN: llvm-readobj -r %t/ld.32.so | FileCheck --check-prefix=LD32-REL %s
# RUN: llvm-readelf -x .got %t/ld.32.so | FileCheck --check-prefix=LD32-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.32.so | FileCheck --check-prefixes=LD32 %s
+# RUN: ld.lld -shared %t/a.32.relax.o -o %t/ld.32.relax.so
+# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.32.relax.so | FileCheck --check-prefixes=LD32-RELAX %s
## LA32 LD -> LE
# RUN: ld.lld %t/a.32.o %t/tga.32.o -o %t/le.32
# RUN: llvm-readelf -r %t/le.32 | FileCheck --check-prefix=NOREL %s
# RUN: llvm-readelf -x .got %t/le.32 | FileCheck --check-prefix=LE32-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.32 | FileCheck --check-prefixes=LE32 %s
+# RUN: ld.lld %t/a.32.relax.o %t/tga.32.o -o %t/le.32.relax
+# RUN: llvm-readelf -x .got %t/le.32.relax | FileCheck --check-prefix=LE32-GOT-RELAX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t/le.32.relax | FileCheck --check-prefixes=LE32-RELAX %s
## LA64 LD
# RUN: ld.lld -shared %t/a.64.o -o %t/ld.64.so
# RUN: llvm-readobj -r %t/ld.64.so | FileCheck --check-prefix=LD64-REL %s
# RUN: llvm-readelf -x .got %t/ld.64.so | FileCheck --check-prefix=LD64-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.64.so | FileCheck --check-prefixes=LD64 %s
+# RUN: ld.lld -shared %t/a.64.relax.o -o %t/ld.64.relax.so
+# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.64.relax.so | FileCheck --check-prefixes=LD64-RELAX %s
## LA64 LD -> LE
# RUN: ld.lld %t/a.64.o %t/tga.64.o -o %t/le.64
# RUN: llvm-readelf -r %t/le.64 | FileCheck --check-prefix=NOREL %s
# RUN: llvm-readelf -x .got %t/le.64 | FileCheck --check-prefix=LE64-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.64 | FileCheck --check-prefixes=LE64 %s
+# RUN: ld.lld %t/a.64.relax.o %t/tga.64.o -o %t/le.64.relax
+# RUN: llvm-readelf -x .got %t/le.64.relax | FileCheck --check-prefix=LE64-GOT-RELAX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t/le.64.relax | FileCheck --check-prefixes=LE64-RELAX %s
## a at dtprel = st_value(a) = 0 is a link-time constant.
# LD32-REL: .rela.dyn {
@@ -56,6 +69,14 @@
# LD64-NEXT: addi.d $a0, $a0, 1024
# LD64-NEXT: bl 40
+## LA32: &DTPMOD(a) - . = 0x20280 - 0x101cc = 16429<<2
+# LD32-RELAX: 101cc: pcaddi $a0, 16429
+# LD32-RELAX-NEXT: bl 48
+
+## LA64: &DTPMOD(a) - . = 0x20400 - 0x102e0 = 16456<<2
+# LD64-RELAX: 102e0: pcaddi $a0, 16456
+# LD64-RELAX-NEXT: bl 44
+
# NOREL: no relocations
## a is local - its DTPMOD/DTPREL slots are link-time constants.
@@ -66,6 +87,12 @@
# LE64-GOT: section '.got':
# LE64-GOT-NEXT: 0x000301d8 01000000 00000000 00000000 00000000
+# LE32-GOT-RELAX: section '.got':
+# LE32-GOT-RELAX-NEXT: 0x0003011c 01000000 00000000
+
+# LE64-GOT-RELAX: section '.got':
+# LE64-GOT-RELAX-NEXT: 0x000301d0 01000000 00000000 00000000 00000000
+
## LA32: DTPMOD(.LANCHOR0) - . = 0x30120 - 0x20114: 0x10 pages, page offset 0x120
# LE32: 20114: pcalau12i $a0, 16
# LE32-NEXT: addi.w $a0, $a0, 288
@@ -76,6 +103,15 @@
# LE64-NEXT: addi.d $a0, $a0, 472
# LE64-NEXT: bl 4
+## LA32: DTPMOD(.LANCHOR0) - . = 0x3011c - 0x20114 = 16386<<2
+# LE32-RELAX: 20114: pcaddi $a0, 16386
+# LE32-RELAX-NEXT: bl 4
+
+## LA64: DTPMOD(.LANCHOR0) - . = 0x301d0 - 0x201c8 = 16386<<2
+# LE64-RELAX: 201c8: pcaddi $a0, 16386
+# LE64-RELAX-NEXT: bl 4
+
+
#--- a.s
la.tls.ld $a0, .LANCHOR0
bl %plt(__tls_get_addr)
>From 91da25ea973556fc3a9f4dd2af06af0371cc4d36 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Tue, 31 Dec 2024 20:00:17 +0800
Subject: [PATCH 12/20] Modify test for TLSLE when relax enabled.
---
lld/test/ELF/loongarch-tls-le.s | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/lld/test/ELF/loongarch-tls-le.s b/lld/test/ELF/loongarch-tls-le.s
index 394c60f67bce8..981baa6fd726f 100644
--- a/lld/test/ELF/loongarch-tls-le.s
+++ b/lld/test/ELF/loongarch-tls-le.s
@@ -1,14 +1,20 @@
# REQUIRES: loongarch
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --defsym ELF32=1 %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --defsym ELF32=1 -mattr=+relax %s -o %t.32.relax.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t.64.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.relax.o
# RUN: ld.lld %t.32.o -o %t.32
# RUN: llvm-nm -p %t.32 | FileCheck --check-prefixes=NM %s
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE,LE32 %s
+# RUN: ld.lld %t.32.relax.o -o %t.32.relax
+# RUN: llvm-objdump -d --no-show-raw-insn %t.32.relax | FileCheck --check-prefixes=LE,LE32-RELAX %s
# RUN: ld.lld %t.64.o -o %t.64
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE,LE64 %s
+# RUN: ld.lld %t.64.relax.o -o %t.64.relax
+# RUN: llvm-objdump -d --no-show-raw-insn %t.64.relax | FileCheck --check-prefixes=LE,LE64-RELAX %s
# RUN: not ld.lld -shared %t.32.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
@@ -37,12 +43,22 @@
# LE32-NEXT: add.w $a0, $a0, $tp
# LE32-NEXT: addi.w $a0, $a0, -2048
+# LE32-RELAX: addi.w $a0, $tp, 8
+# LE32-RELAX-NEXT: lu12i.w $a0, 1
+# LE32-RELAX-NEXT: add.w $a0, $a0, $tp
+# LE32-RELAX-NEXT: addi.w $a0, $a0, -2048
+
# LE64: add.d $a0, $a0, $tp
# LE64-NEXT: addi.d $a0, $a0, 8
# LE64-NEXT: lu12i.w $a0, 1
# LE64-NEXT: add.d $a0, $a0, $tp
# LE64-NEXT: addi.d $a0, $a0, -2048
+# LE64-RELAX: addi.d $a0, $tp, 8
+# LE64-RELAX-NEXT: lu12i.w $a0, 1
+# LE64-RELAX-NEXT: add.d $a0, $a0, $tp
+# LE64-RELAX-NEXT: addi.d $a0, $a0, -2048
+
# LE-EMPTY:
.macro add dst, src1, src2, src3
>From 2066c5f7cc3eecfdd76216378efbfb8376fa4262 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Tue, 31 Dec 2024 14:49:40 +0800
Subject: [PATCH 13/20] Add test for loongarch-relax-tls-le.s and modify
loongarch-relax-emit-relocs.s
---
lld/test/ELF/loongarch-relax-emit-relocs.s | 112 +++++++++++++++++++-
lld/test/ELF/loongarch-relax-tls-le.s | 115 +++++++++++++++++++++
2 files changed, 222 insertions(+), 5 deletions(-)
create mode 100644 lld/test/ELF/loongarch-relax-tls-le.s
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index a02cd272aba5b..5bb445dcaff50 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -1,7 +1,7 @@
# REQUIRES: loongarch
## Test that we can handle --emit-relocs while relaxing.
-# 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 -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.32.o -o %t.32
# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.64.o -o %t.64
@@ -17,19 +17,39 @@
# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
# RELAX: 00010000 <_start>:
-# RELAX-NEXT: pcaddi $a0, 0
+# RELAX-NEXT: pcaddi $a0, 0
# RELAX-NEXT: R_LARCH_RELAX _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
-# RELAX-NEXT: pcaddi $a0, -1
+# RELAX-NEXT: pcaddi $a0, -1
# RELAX-NEXT: R_LARCH_RELAX _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: lu12i.w $a0, 0
+# RELAX-NEXT: R_LARCH_TLS_LE_HI20 a
+# RELAX-NEXT: ori $a0, $a0, 0
+# RELAX-NEXT: R_LARCH_TLS_LE_LO12 a
+# RELAX-NEXT: pcaddi $a0, {{[0-9]+}}
+# RELAX-NEXT: R_LARCH_RELAX a
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: R_LARCH_TLS_GD_PCREL20_S2 a
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: pcaddi $a0, {{[0-9]+}}
+# RELAX-NEXT: R_LARCH_RELAX a
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: R_LARCH_TLS_LD_PCREL20_S2 a
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: addi.{{[dw]}} $a0, $tp, 0
+# RELAX-NEXT: R_LARCH_RELAX a
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: R_LARCH_RELAX a
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: R_LARCH_TLS_LE_LO12_R a
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: nop
# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# RELAX-NEXT: nop
# RELAX-NEXT: ret
# NORELAX: <_start>:
@@ -45,8 +65,36 @@
# NORELAX-NEXT: ld.d $a0, $a0, 0
# NORELAX-NEXT: R_LARCH_GOT_PC_LO12 _start
# NORELAX-NEXT: R_LARCH_RELAX *ABS*
-# NORELAX-NEXT: ret
+# NORELAX-NEXT: lu12i.w $a0, 0
+# NORELAX-NEXT: R_LARCH_TLS_LE_HI20 a
+# NORELAX-NEXT: ori $a0, $a0, 0
+# NORELAX-NEXT: R_LARCH_TLS_LE_LO12 a
+# NORELAX-NEXT: pcalau12i $a0, 16
+# NORELAX-NEXT: R_LARCH_TLS_GD_PC_HI20 a
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: addi.d $a0, $a0, 8
+# NORELAX-NEXT: R_LARCH_GOT_PC_LO12 a
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: pcalau12i $a0, 16
+# NORELAX-NEXT: R_LARCH_TLS_LD_PC_HI20 a
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: addi.d $a0, $a0, 8
+# NORELAX-NEXT: R_LARCH_GOT_PC_LO12 a
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: lu12i.w $a0, 0
+# NORELAX-NEXT: R_LARCH_TLS_LE_HI20_R a
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: add.d $a0, $a0, $tp
+# NORELAX-NEXT: R_LARCH_TLS_LE_ADD_R a
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: addi.d $a0, $a0, 0
+# NORELAX-NEXT: R_LARCH_TLS_LE_LO12_R a
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: nop
# NORELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: nop
+# NORELAX-NEXT: ret
# CHECKR: <_start>:
# CHECKR-NEXT: pcalau12i $a0, 0
@@ -61,15 +109,69 @@
# CHECKR-NEXT: ld.d $a0, $a0, 0
# CHECKR-NEXT: R_LARCH_GOT_PC_LO12 _start
# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: lu12i.w $a0, 0
+# CHECKR-NEXT: R_LARCH_TLS_LE_HI20 a
+# CHECKR-NEXT: ori $a0, $a0, 0
+# CHECKR-NEXT: R_LARCH_TLS_LE_LO12 a
+# CHECKR-NEXT: pcalau12i $a0, 0
+# CHECKR-NEXT: R_LARCH_TLS_GD_PC_HI20 a
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: addi.d $a0, $a0, 0
+# CHECKR-NEXT: R_LARCH_GOT_PC_LO12 a
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: pcalau12i $a0, 0
+# CHECKR-NEXT: R_LARCH_TLS_LD_PC_HI20 a
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: addi.d $a0, $a0, 0
+# CHECKR-NEXT: R_LARCH_GOT_PC_LO12 a
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: lu12i.w $a0, 0
+# CHECKR-NEXT: R_LARCH_TLS_LE_HI20_R a
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: add.d $a0, $a0, $tp
+# CHECKR-NEXT: R_LARCH_TLS_LE_ADD_R a
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: addi.d $a0, $a0, 0
+# CHECKR-NEXT: R_LARCH_TLS_LE_LO12_R a
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
# CHECKR-NEXT: nop
# CHECKR-NEXT: R_LARCH_ALIGN *ABS*+0xc
# CHECKR-NEXT: nop
# CHECKR-NEXT: nop
# CHECKR-NEXT: ret
+.macro add dst, src1, src2, src3
+.ifdef ELF32
+add.w \dst, \src1, \src2, \src3
+.else
+add.d \dst, \src1, \src2, \src3
+.endif
+.endm
+.macro addi dst, src1, src2
+.ifdef ELF32
+addi.w \dst, \src1, \src2
+.else
+addi.d \dst, \src1, \src2
+.endif
+.endm
+
.global _start
_start:
la.pcrel $a0, _start
la.got $a0, _start
+
+ la.tls.le $a0, a # without R_LARCH_RELAX reloaction
+ la.tls.gd $a0, a
+ la.tls.ld $a0, a
+
+ lu12i.w $a0, %le_hi20_r(a)
+ add $a0, $a0, $tp, %le_add_r(a)
+ addi $a0, $a0, %le_lo12_r(a)
+
.p2align 4
ret
+
+.section .tbss,"awT", at nobits
+.globl a
+a:
+.zero 4
diff --git a/lld/test/ELF/loongarch-relax-tls-le.s b/lld/test/ELF/loongarch-relax-tls-le.s
new file mode 100644
index 0000000000000..8f9b6e1092a62
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-tls-le.s
@@ -0,0 +1,115 @@
+# REQUIRES: loongarch
+
+# 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 %t.32.o -o %t.32
+# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX32 %s
+
+# RUN: ld.lld %t.64.o -o %t.64
+# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX64 %s
+
+# RELAX32-LABEL: <_start>:
+## .LANCHOR0 at tprel = 8
+# RELAX32-NEXT: addi.w $a0, $tp, 8
+# RELAX32-NEXT: ld.w $a1, $a0, 0
+# RELAX32-NEXT: ld.w $a2, $tp, 8
+## .a at tprel - 4 = 0x7fc
+# RELAX32-NEXT: addi.w $a1, $zero, 1
+# RELAX32-NEXT: addi.w $a1, $a1, 2
+# RELAX32-NEXT: st.w $a1, $tp, 2044
+## .a at tprel = 0x800
+# RELAX32-NEXT: lu12i.w $a0, 1
+# RELAX32-NEXT: add.w $a0, $a0, $tp
+# RELAX32-NEXT: addi.w $a0, $a0, -2048
+
+# RELAX64-LABEL: <_start>:
+## .LANCHOR0 at tprel = 8
+# RELAX64-NEXT: addi.d $a0, $tp, 8
+# RELAX64-NEXT: ld.d $a1, $a0, 0
+# RELAX64-NEXT: ld.d $a2, $tp, 8
+## .a at tprel - 4 = 0x7fc
+# RELAX64-NEXT: addi.d $a1, $zero, 1
+# RELAX64-NEXT: addi.d $a1, $a1, 2
+# RELAX64-NEXT: st.d $a1, $tp, 2044
+## .a at tprel = 0x800
+# RELAX64-NEXT: lu12i.w $a0, 1
+# RELAX64-NEXT: add.d $a0, $a0, $tp
+# RELAX64-NEXT: addi.d $a0, $a0, -2048
+
+.macro add dst, src1, src2, src3
+.ifdef ELF32
+add.w \dst, \src1, \src2, \src3
+.else
+add.d \dst, \src1, \src2, \src3
+.endif
+.endm
+.macro inst op dst, src1, src2
+.ifdef ELF32
+ .ifc \op, addi
+ addi.w \dst, \src1, \src2
+ .else; .ifc \op, ld
+ ld.w \dst, \src1, \src2
+ .else; .ifc \op, st
+ st.w \dst, \src1, \src2
+ .else; .ifc \op, ldptr
+ ldptr.w \dst, \src1, \src2
+ .else
+ .error "Unknown op in ELF32 mode"
+ .endif; .endif; .endif; .endif
+.else
+ .ifc \op, addi
+ addi.d \dst, \src1, \src2
+ .else; .ifc \op, ld
+ ld.d \dst, \src1, \src2
+ .else; .ifc \op, st
+ st.d \dst, \src1, \src2
+ .else; .ifc \op, ldptr
+ ldptr.d \dst, \src1, \src2
+ .else
+ .error "Unknown op in ELF64 mode"
+ .endif; .endif; .endif; .endif
+.endif
+.endm
+
+.macro addi dst, src1, src2
+inst addi \dst, \src1, \src2
+.endm
+.macro ld dst, src1, src2
+inst ld \dst, \src1, \src2
+.endm
+.macro st dst, src1, src2
+inst st \dst, \src1, \src2
+.endm
+.macro ldptr dst, src1, src2
+inst ldptr \dst, \src1, \src2
+.endm
+
+_start:
+## Test instructions not in pairs.
+lu12i.w $a0, %le_hi20_r(.LANCHOR0)
+add $a0, $a0, $tp, %le_add_r(.LANCHOR0)
+addi $a0, $a0, %le_lo12_r(.LANCHOR0)
+ld $a1, $a0, 0
+ld $a2, $a0, %le_lo12_r(.LANCHOR0)
+
+## hi20(a-4) = hi20(0x7fc) = 0. relaxable
+## Test non-adjacent instructions.
+lu12i.w $a0, %le_hi20_r(a-4)
+addi $a1, $zero, 0x1
+add $a0, $a0, $tp, %le_add_r(a-4)
+addi $a1, $a1, 0x2
+st $a1, $a0, %le_lo12_r(a-4)
+
+## hi20(a) = hi20(0x800) = 1. not relaxable
+lu12i.w $a0, %le_hi20_r(a)
+add $a0, $a0, $tp, %le_add_r(a)
+addi $a0, $a0, %le_lo12_r(a)
+
+.section .tbss,"awT", at nobits
+.space 8
+.LANCHOR0:
+.space 0x800-8
+.globl a
+a:
+.zero 4
>From b57c40e275dc0977e002e68834c2b40fa030d9fc Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Thu, 16 Jan 2025 22:08:02 +0800
Subject: [PATCH 14/20] Modify test. Add --relax option.
---
lld/test/ELF/loongarch-relax-tls-le.s | 4 ++--
lld/test/ELF/loongarch-tls-gd.s | 4 ++--
lld/test/ELF/loongarch-tls-ld.s | 8 ++++----
lld/test/ELF/loongarch-tls-le.s | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/lld/test/ELF/loongarch-relax-tls-le.s b/lld/test/ELF/loongarch-relax-tls-le.s
index 8f9b6e1092a62..b55f284f32cb8 100644
--- a/lld/test/ELF/loongarch-relax-tls-le.s
+++ b/lld/test/ELF/loongarch-relax-tls-le.s
@@ -3,10 +3,10 @@
# 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 %t.32.o -o %t.32
+# RUN: ld.lld --relax %t.32.o -o %t.32
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX32 %s
-# RUN: ld.lld %t.64.o -o %t.64
+# RUN: ld.lld --relax %t.64.o -o %t.64
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX64 %s
# RELAX32-LABEL: <_start>:
diff --git a/lld/test/ELF/loongarch-tls-gd.s b/lld/test/ELF/loongarch-tls-gd.s
index 27d9fdb7ee701..4cfed41d70f38 100644
--- a/lld/test/ELF/loongarch-tls-gd.s
+++ b/lld/test/ELF/loongarch-tls-gd.s
@@ -20,7 +20,7 @@
# RUN: ld.lld -shared %t/a.32.o %t/bc.32.o -o %t/gd.32.so
# RUN: llvm-readobj -r %t/gd.32.so | FileCheck --check-prefix=GD32-REL %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.32.so | FileCheck --check-prefix=GD32 %s
-# RUN: ld.lld -shared %t/a.32.relax.o %t/bc.32.o -o %t/gd.32.relax.so
+# RUN: ld.lld --relax -shared %t/a.32.relax.o %t/bc.32.o -o %t/gd.32.relax.so
# RUN: llvm-readobj -r %t/gd.32.relax.so | FileCheck --check-prefix=GD32-REL-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.32.relax.so | FileCheck --check-prefix=GD32-RELAX %s
@@ -41,7 +41,7 @@
# RUN: ld.lld -shared %t/a.64.o %t/bc.64.o -o %t/gd.64.so
# RUN: llvm-readobj -r %t/gd.64.so | FileCheck --check-prefix=GD64-REL %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.64.so | FileCheck --check-prefix=GD64 %s
-# RUN: ld.lld -shared %t/a.64.relax.o %t/bc.64.o -o %t/gd.64.relax.so
+# RUN: ld.lld --relax -shared %t/a.64.relax.o %t/bc.64.o -o %t/gd.64.relax.so
# RUN: llvm-readobj -r %t/gd.64.relax.so | FileCheck --check-prefix=GD64-REL-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.64.relax.so | FileCheck --check-prefix=GD64-RELAX %s
diff --git a/lld/test/ELF/loongarch-tls-ld.s b/lld/test/ELF/loongarch-tls-ld.s
index 27adb1e17702a..6cf6fa92939d5 100644
--- a/lld/test/ELF/loongarch-tls-ld.s
+++ b/lld/test/ELF/loongarch-tls-ld.s
@@ -17,7 +17,7 @@
# RUN: llvm-readobj -r %t/ld.32.so | FileCheck --check-prefix=LD32-REL %s
# RUN: llvm-readelf -x .got %t/ld.32.so | FileCheck --check-prefix=LD32-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.32.so | FileCheck --check-prefixes=LD32 %s
-# RUN: ld.lld -shared %t/a.32.relax.o -o %t/ld.32.relax.so
+# RUN: ld.lld --relax -shared %t/a.32.relax.o -o %t/ld.32.relax.so
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.32.relax.so | FileCheck --check-prefixes=LD32-RELAX %s
## LA32 LD -> LE
@@ -25,7 +25,7 @@
# RUN: llvm-readelf -r %t/le.32 | FileCheck --check-prefix=NOREL %s
# RUN: llvm-readelf -x .got %t/le.32 | FileCheck --check-prefix=LE32-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.32 | FileCheck --check-prefixes=LE32 %s
-# RUN: ld.lld %t/a.32.relax.o %t/tga.32.o -o %t/le.32.relax
+# RUN: ld.lld --relax %t/a.32.relax.o %t/tga.32.o -o %t/le.32.relax
# RUN: llvm-readelf -x .got %t/le.32.relax | FileCheck --check-prefix=LE32-GOT-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.32.relax | FileCheck --check-prefixes=LE32-RELAX %s
@@ -34,7 +34,7 @@
# RUN: llvm-readobj -r %t/ld.64.so | FileCheck --check-prefix=LD64-REL %s
# RUN: llvm-readelf -x .got %t/ld.64.so | FileCheck --check-prefix=LD64-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.64.so | FileCheck --check-prefixes=LD64 %s
-# RUN: ld.lld -shared %t/a.64.relax.o -o %t/ld.64.relax.so
+# RUN: ld.lld --relax -shared %t/a.64.relax.o -o %t/ld.64.relax.so
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.64.relax.so | FileCheck --check-prefixes=LD64-RELAX %s
## LA64 LD -> LE
@@ -42,7 +42,7 @@
# RUN: llvm-readelf -r %t/le.64 | FileCheck --check-prefix=NOREL %s
# RUN: llvm-readelf -x .got %t/le.64 | FileCheck --check-prefix=LE64-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.64 | FileCheck --check-prefixes=LE64 %s
-# RUN: ld.lld %t/a.64.relax.o %t/tga.64.o -o %t/le.64.relax
+# RUN: ld.lld --relax %t/a.64.relax.o %t/tga.64.o -o %t/le.64.relax
# RUN: llvm-readelf -x .got %t/le.64.relax | FileCheck --check-prefix=LE64-GOT-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.64.relax | FileCheck --check-prefixes=LE64-RELAX %s
diff --git a/lld/test/ELF/loongarch-tls-le.s b/lld/test/ELF/loongarch-tls-le.s
index 981baa6fd726f..bc55e08591d28 100644
--- a/lld/test/ELF/loongarch-tls-le.s
+++ b/lld/test/ELF/loongarch-tls-le.s
@@ -8,12 +8,12 @@
# RUN: ld.lld %t.32.o -o %t.32
# RUN: llvm-nm -p %t.32 | FileCheck --check-prefixes=NM %s
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE,LE32 %s
-# RUN: ld.lld %t.32.relax.o -o %t.32.relax
+# RUN: ld.lld --relax %t.32.relax.o -o %t.32.relax
# RUN: llvm-objdump -d --no-show-raw-insn %t.32.relax | FileCheck --check-prefixes=LE,LE32-RELAX %s
# RUN: ld.lld %t.64.o -o %t.64
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE,LE64 %s
-# RUN: ld.lld %t.64.relax.o -o %t.64.relax
+# RUN: ld.lld --relax %t.64.relax.o -o %t.64.relax
# RUN: llvm-objdump -d --no-show-raw-insn %t.64.relax | FileCheck --check-prefixes=LE,LE64-RELAX %s
# RUN: not ld.lld -shared %t.32.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
>From 924d511235d2a06edd816360b54eebc7599423c3 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 14 Feb 2025 09:31:10 +0800
Subject: [PATCH 15/20] Fixes for reviews.
---
lld/ELF/Arch/LoongArch.cpp | 14 +++++-----
lld/test/ELF/loongarch-relax-align.s | 8 +++---
lld/test/ELF/loongarch-relax-emit-relocs.s | 6 ++--
...loongarch-relax-pc-hi20-lo12-got-symbols.s | 28 +++++++++----------
lld/test/ELF/loongarch-relax-pc-hi20-lo12.s | 12 ++++----
5 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index b999e7fd27ae9..dbf024eadf100 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -790,23 +790,23 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
(ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section)))
return;
- uint64_t symBase = 0;
+ uint64_t dest = 0;
if (rHi20.expr == RE_LOONGARCH_PLT_PAGE_PC)
- symBase = rHi20.sym->getPltVA(ctx);
+ dest = rHi20.sym->getPltVA(ctx);
else if (rHi20.expr == RE_LOONGARCH_PAGE_PC ||
rHi20.expr == RE_LOONGARCH_GOT_PAGE_PC)
- symBase = rHi20.sym->getVA(ctx);
+ dest = rHi20.sym->getVA(ctx);
else {
Err(ctx) << getErrorLoc(ctx, (const uint8_t *)loc) << "unknown expr ("
<< rHi20.expr << ") against symbol " << rHi20.sym
<< "in relaxPCHi20Lo12";
return;
}
- const uint64_t symLocal = symBase + rHi20.addend;
+ dest += rHi20.addend;
- const int64_t distance = symLocal - loc;
- // Check if the distance aligns 4 bytes or exceeds the range of pcaddi.
- if ((distance & 0x3) != 0 || !isInt<22>(distance))
+ const int64_t displace = dest - loc;
+ // Check if the displace aligns 4 bytes or exceeds the range of pcaddi.
+ if ((displace & 0x3) != 0 || !isInt<22>(displace))
return;
// Note: If we can ensure that the .o files generated by LLVM only contain
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s
index 66a8ed3abf71e..79353f2a3be47 100644
--- a/lld/test/ELF/loongarch-relax-align.s
+++ b/lld/test/ELF/loongarch-relax-align.s
@@ -2,8 +2,8 @@
# 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: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --relax %t.32.o -o %t.32
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --relax %t.64.o -o %t.64
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o -o %t.32
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.32.o -o %t.32n
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.64.o -o %t.64n
# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX,NOOLD %s
@@ -13,13 +13,13 @@
## Test the R_LARCH_ALIGN without symbol index.
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.o64.o --defsym=old=1
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --relax %t.o64.o -o %t.o64
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.o64.o -o %t.o64
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.o64.o -o %t.o64n
# RUN: llvm-objdump -td --no-show-raw-insn %t.o64 | FileCheck --check-prefixes=RELAX,OLD %s
# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck --check-prefixes=NORELAX,OLD %s
## -r keeps section contents unchanged.
-# RUN: ld.lld -r --relax %t.64.o -o %t.64.r
+# RUN: ld.lld -r %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr --no-show-raw-insn %t.64.r | FileCheck %s --check-prefix=CHECKR
# NOOLD: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index a02cd272aba5b..7031ffd9f6686 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -3,13 +3,13 @@
# 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: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.32.o -o %t.32
-# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.64.o -o %t.64
+# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.32.o -o %t.32
+# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.64.o -o %t.64
# RUN: llvm-objdump -dr %t.32 | FileCheck %s --check-prefix=RELAX
# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
## -r should keep original relocations.
-# RUN: ld.lld --relax -r %t.64.o -o %t.64.r
+# RUN: ld.lld -r %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
## --no-relax should keep original relocations.
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
index 0a75d2289209c..f37de8e3b7c83 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
@@ -9,45 +9,45 @@
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax abs.s -o abs.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax abs.s -o abs.64.o
-# RUN: ld.lld --shared --relax -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so
-# RUN: ld.lld --shared --relax -Tlinker.t symbols.64.o abs.64.o -o symbols.64.so
+# RUN: ld.lld --shared -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so
+# RUN: ld.lld --shared -Tlinker.t symbols.64.o abs.64.o -o symbols.64.so
# RUN: llvm-objdump -d --no-show-raw-insn symbols.32.so | FileCheck --check-prefixes=LIB %s
# RUN: llvm-objdump -d --no-show-raw-insn symbols.64.so | FileCheck --check-prefixes=LIB %s
-# RUN: ld.lld --relax -Tlinker.t -z undefs symbols.32.o abs.32.o -o symbols.32
-# RUN: ld.lld --relax -Tlinker.t -z undefs symbols.64.o abs.64.o -o symbols.64
+# RUN: ld.lld -Tlinker.t -z undefs symbols.32.o abs.32.o -o symbols.32
+# RUN: ld.lld -Tlinker.t -z undefs symbols.64.o abs.64.o -o symbols.64
# RUN: llvm-objdump -d --no-show-raw-insn symbols.32 | FileCheck --check-prefixes=EXE %s
# RUN: llvm-objdump -d --no-show-raw-insn symbols.64 | FileCheck --check-prefixes=EXE %s
## Symbol 'hidden_sym' is nonpreemptible, the relaxation should be applied.
-LIB: pcaddi $a0, {{[0-9]+}}
+LIB: pcaddi $a0, [[#]]
## Symbol 'global_sym' is preemptible, no relaxations should be applied.
LIB-NEXT: pcalau12i $a1, 4
-LIB-NEXT: ld.{{[wd]}} $a1, $a1, {{[0-9]+}}
+LIB-NEXT: ld.{{[wd]}} $a1, $a1, [[#]]
## Symbol 'undefined_sym' is undefined, no relaxations should be applied.
LIB-NEXT: pcalau12i $a2, 4
-LIB-NEXT: ld.{{[wd]}} $a2, $a2, {{[0-9]+}}
+LIB-NEXT: ld.{{[wd]}} $a2, $a2, [[#]]
## Symbol 'ifunc_sym' is STT_GNU_IFUNC, no relaxations should be applied.
LIB-NEXT: pcalau12i $a3, 4
-LIB-NEXT: ld.{{[wd]}} $a3, $a3, {{[0-9]+}}
+LIB-NEXT: ld.{{[wd]}} $a3, $a3, [[#]]
## Symbol 'abs_sym' is absolute, no relaxations should be applied.
LIB-NEXT: pcalau12i $a4, 4
-LIB-NEXT: ld.{{[wd]}} $a4, $a4, {{[0-9]+}}
+LIB-NEXT: ld.{{[wd]}} $a4, $a4, [[#]]
## Symbol 'hidden_sym' is nonpreemptible, the relaxation should be applied.
-EXE: pcaddi $a0, {{[0-9]+}}
+EXE: pcaddi $a0, [[#]]
## Symbol 'global_sym' is nonpreemptible, the relaxation should be applied.
-EXE-NEXT: pcaddi $a1, {{[0-9]+}}
+EXE-NEXT: pcaddi $a1, [[#]]
## Symbol 'undefined_sym' is undefined, no relaxations should be applied.
EXE-NEXT: pcalau12i $a2, 4
-EXE-NEXT: ld.{{[wd]}} $a2, $a2, {{[0-9]+}}
+EXE-NEXT: ld.{{[wd]}} $a2, $a2, [[#]]
## Symbol 'ifunc_sym' is STT_GNU_IFUNC, no relaxations should be applied.
EXE-NEXT: pcalau12i $a3, 4
-EXE-NEXT: ld.{{[wd]}} $a3, $a3, {{[0-9]+}}
+EXE-NEXT: ld.{{[wd]}} $a3, $a3, [[#]]
## Symbol 'abs_sym' is absolute, relaxations may be applied in -no-pie mode.
-EXE-NEXT: pcaddi $a4, -{{[0-9]+}}
+EXE-NEXT: pcaddi $a4, -[[#]]
## The linker script ensures that .rodata and .text are near (>4M) so that
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
index 760fe77d774e3..a417d89e9fa2e 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -3,18 +3,18 @@
# 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: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 --relax %t.32.o -o %t.32
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 --relax %t.64.o -o %t.64
+# 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 --relax %t.32.o -shared -o %t.32s
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 --relax %t.64.o -shared -o %t.64s
+# 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=0x410000 --relax %t.32.o -o %t.32o
-# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 --relax %t.64.o -o %t.64o
+# 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
>From b9c2ea1ad26ad6c81213ee9d563bd1448ed4a097 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 14 Feb 2025 09:43:07 +0800
Subject: [PATCH 16/20] Revert "Modify test. Add the option --relax."
This reverts commit f2aae15f701863d03edd32657824a97f66696e8d.
---
lld/test/ELF/loongarch-relax-call36-2.s | 6 +++---
lld/test/ELF/loongarch-relax-call36.s | 6 +++---
lld/test/ELF/loongarch-relax-emit-relocs-2.s | 6 +++---
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/lld/test/ELF/loongarch-relax-call36-2.s b/lld/test/ELF/loongarch-relax-call36-2.s
index 71650aefe9432..1c216a9bdc35e 100644
--- a/lld/test/ELF/loongarch-relax-call36-2.s
+++ b/lld/test/ELF/loongarch-relax-call36-2.s
@@ -2,14 +2,14 @@
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.o
-# RUN: ld.lld --relax -T lds a.o -o a
+# RUN: ld.lld -T lds a.o -o a
# RUN: llvm-objdump -d --no-show-raw-insn a | FileCheck %s --check-prefixes=RELAX,RELAX-MID
## Unsure whether this needs a diagnostic. GNU ld allows this.
-# RUN: ld.lld --relax -T lds -pie a.o -o a.pie
+# RUN: ld.lld -T lds -pie a.o -o a.pie
# RUN: llvm-objdump -d --no-show-raw-insn a.pie | FileCheck %s --check-prefixes=RELAX,RELAX-MID
-# RUN: ld.lld --relax -T lds -pie -z notext -z ifunc-noplt a.o -o a.ifunc-noplt
+# RUN: ld.lld -T lds -pie -z notext -z ifunc-noplt a.o -o a.ifunc-noplt
# RUN: llvm-objdump -d --no-show-raw-insn a.ifunc-noplt | FileCheck %s --check-prefixes=RELAX,NORELAX-MID
# RELAX-LABEL: <_start>:
diff --git a/lld/test/ELF/loongarch-relax-call36.s b/lld/test/ELF/loongarch-relax-call36.s
index bda0c4f05da91..57ed214c9eb2e 100644
--- a/lld/test/ELF/loongarch-relax-call36.s
+++ b/lld/test/ELF/loongarch-relax-call36.s
@@ -4,12 +4,12 @@
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.64.o
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax b.s -o b.64.o
-# RUN: ld.lld --relax -shared -soname=b.so b.64.o -o b.64.so
-# RUN: ld.lld --relax -T lds a.64.o b.64.so -o 64
+# RUN: ld.lld -shared -soname=b.so b.64.o -o b.64.so
+# RUN: ld.lld -T lds a.64.o b.64.so -o 64
# RUN: llvm-objdump -td --no-show-raw-insn 64 | FileCheck %s --check-prefix=RELAX
## --no-relax disables relaxation.
-# RUN: ld.lld --no-relax -T lds a.64.o b.64.so -o 64.norelax
+# RUN: ld.lld -T lds a.64.o b.64.so --no-relax -o 64.norelax
# RUN: llvm-objdump -td --no-show-raw-insn 64.norelax | FileCheck %s --check-prefix=NORELAX
# RELAX: {{0*}}00010000 g .text {{0*}}0000001c _start
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs-2.s b/lld/test/ELF/loongarch-relax-emit-relocs-2.s
index eddfc46b1ad08..31cae939eca71 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs-2.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs-2.s
@@ -3,15 +3,15 @@
## Call36 and tail36 need LA64 basic integer, so they donot have 32-bit version.
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
-# RUN: ld.lld --relax -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
## -r should keep original relocations.
-# RUN: ld.lld --relax -r %t.64.o -o %t.64.r
+# RUN: ld.lld -r %t.64.o -o %t.64.r
# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
## --no-relax should keep original relocations.
-# RUN: ld.lld --no-relax -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64.norelax
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
# RELAX: 00010000 <_start>:
>From 11018299e150c7c6f20fc47ff2673d8f963eb199 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 14 Feb 2025 11:23:30 +0800
Subject: [PATCH 17/20] Fixes for reviews.
---
lld/ELF/Arch/LoongArch.cpp | 8 +--
lld/test/ELF/loongarch-relax-call36-2.s | 2 +
lld/test/ELF/loongarch-relax-call36.s | 1 +
lld/test/ELF/loongarch-relax-emit-relocs-2.s | 61 --------------------
lld/test/ELF/loongarch-relax-emit-relocs.s | 43 +++++++++++---
5 files changed, 43 insertions(+), 72 deletions(-)
delete mode 100644 lld/test/ELF/loongarch-relax-emit-relocs-2.s
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 0aa0cf5b657a0..c1e2229c3f9a7 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -840,13 +840,13 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
// b/bl foo
static void relaxCall36(Ctx &ctx, const InputSection &sec, size_t i,
uint64_t loc, Relocation &r, uint32_t &remove) {
- const uint64_t symLocal =
+ const uint64_t dest =
(r.expr == R_PLT_PC ? r.sym->getPltVA(ctx) : r.sym->getVA(ctx)) +
r.addend;
- const int64_t distance = symLocal - loc;
- // Check if the distance aligns 4 bytes or exceeds the range of b[l].
- if ((distance & 0x3) != 0 || !isInt<28>(distance))
+ const int64_t displace = dest - loc;
+ // Check if the displace aligns 4 bytes or exceeds the range of b[l].
+ if ((displace & 0x3) != 0 || !isInt<28>(displace))
return;
const uint32_t nextInsn = read32le(sec.content().data() + r.offset + 4);
diff --git a/lld/test/ELF/loongarch-relax-call36-2.s b/lld/test/ELF/loongarch-relax-call36-2.s
index 1c216a9bdc35e..482eed2ebd111 100644
--- a/lld/test/ELF/loongarch-relax-call36-2.s
+++ b/lld/test/ELF/loongarch-relax-call36-2.s
@@ -1,4 +1,6 @@
# REQUIRES: loongarch
+## Relax R_LARCH_CALL36. This test tests boundary cases and some special symbols.
+
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.o
diff --git a/lld/test/ELF/loongarch-relax-call36.s b/lld/test/ELF/loongarch-relax-call36.s
index 57ed214c9eb2e..0f0ba26b15f30 100644
--- a/lld/test/ELF/loongarch-relax-call36.s
+++ b/lld/test/ELF/loongarch-relax-call36.s
@@ -1,4 +1,5 @@
# REQUIRES: loongarch
+## Relax R_LARCH_CALL36, which involves the macro instructions call36/tail36.
# RUN: rm -rf %t && split-file %s %t && cd %t
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs-2.s b/lld/test/ELF/loongarch-relax-emit-relocs-2.s
deleted file mode 100644
index 31cae939eca71..0000000000000
--- a/lld/test/ELF/loongarch-relax-emit-relocs-2.s
+++ /dev/null
@@ -1,61 +0,0 @@
-# REQUIRES: loongarch
-## Test that we can handle --emit-relocs while relaxing.
-## Call36 and tail36 need LA64 basic integer, so they donot have 32-bit version.
-
-# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
-# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
-# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
-
-## -r should keep original relocations.
-# RUN: ld.lld -r %t.64.o -o %t.64.r
-# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
-
-## --no-relax should keep original relocations.
-# RUN: ld.lld -Ttext=0x10000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
-# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
-
-# RELAX: 00010000 <_start>:
-# RELAX-NEXT: bl 0
-# RELAX-NEXT: R_LARCH_B26 _start
-# RELAX-NEXT: R_LARCH_RELAX *ABS*
-# RELAX-NEXT: b -4
-# RELAX-NEXT: R_LARCH_B26 _start
-# RELAX-NEXT: R_LARCH_RELAX *ABS*
-# RELAX-NEXT: nop
-# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# RELAX-NEXT: nop
-# RELAX-NEXT: ret
-
-# CHECKR: <_start>:
-# CHECKR-NEXT: pcaddu18i $ra, 0
-# CHECKR-NEXT: R_LARCH_CALL36 _start
-# CHECKR-NEXT: R_LARCH_RELAX *ABS*
-# CHECKR-NEXT: jirl $ra, $ra, 0
-# CHECKR-NEXT: pcaddu18i $t0, 0
-# CHECKR-NEXT: R_LARCH_CALL36 _start
-# CHECKR-NEXT: R_LARCH_RELAX *ABS*
-# CHECKR-NEXT: jr $t0
-# CHECKR-NEXT: nop
-# CHECKR-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# CHECKR-NEXT: nop
-# CHECKR-NEXT: nop
-# CHECKR-NEXT: ret
-
-# NORELAX: <_start>:
-# NORELAX-NEXT: pcaddu18i $ra, 0
-# NORELAX-NEXT: R_LARCH_CALL36 _start
-# NORELAX-NEXT: R_LARCH_RELAX *ABS*
-# NORELAX-NEXT: jirl $ra, $ra, 0
-# NORELAX-NEXT: pcaddu18i $t0, 0
-# NORELAX-NEXT: R_LARCH_CALL36 _start
-# NORELAX-NEXT: R_LARCH_RELAX *ABS*
-# NORELAX-NEXT: jirl $zero, $t0, -8
-# NORELAX-NEXT: ret
-# NORELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
-
-.global _start
-_start:
- call36 _start
- tail36 $t0, _start
- .p2align 4
- ret
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index a02cd272aba5b..d7f444470f0f9 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -2,11 +2,11 @@
## Test that we can handle --emit-relocs while relaxing.
# 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=loongarch64 --mattr=+relax --defsym ELF64=1 %s -o %t.64.o
# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.32.o -o %t.32
# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs --relax %t.64.o -o %t.64
-# RUN: llvm-objdump -dr %t.32 | FileCheck %s --check-prefix=RELAX
-# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=RELAX
+# RUN: llvm-objdump -dr %t.32 | FileCheck %s --check-prefixes=RELAX,RELAX32
+# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefixes=RELAX,RELAX64
## -r should keep original relocations.
# RUN: ld.lld --relax -r %t.64.o -o %t.64.r
@@ -27,10 +27,19 @@
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
-# RELAX-NEXT: nop
-# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# RELAX-NEXT: nop
-# RELAX-NEXT: ret
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: ret
+
+# RELAX64-NEXT: bl -8
+# RELAX64-NEXT: R_LARCH_B26 _start
+# RELAX64-NEXT: R_LARCH_RELAX *ABS*
+# RELAX64-NEXT: b -12
+# RELAX64-NEXT: R_LARCH_B26 _start
+# RELAX64-NEXT: R_LARCH_RELAX *ABS*
+# RELAX64-NEXT: ret
+# RELAX64-NEXT: R_LARCH_ALIGN *ABS*+0xc
# NORELAX: <_start>:
# NORELAX-NEXT: pcalau12i $a0, 0
@@ -45,6 +54,14 @@
# NORELAX-NEXT: ld.d $a0, $a0, 0
# NORELAX-NEXT: R_LARCH_GOT_PC_LO12 _start
# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: pcaddu18i $ra, 0
+# NORELAX-NEXT: R_LARCH_CALL36 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: jirl $ra, $ra, -16
+# NORELAX-NEXT: pcaddu18i $a0, 0
+# NORELAX-NEXT: R_LARCH_CALL36 _start
+# NORELAX-NEXT: R_LARCH_RELAX *ABS*
+# NORELAX-NEXT: jirl $zero, $a0, -24
# NORELAX-NEXT: ret
# NORELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
@@ -61,6 +78,14 @@
# CHECKR-NEXT: ld.d $a0, $a0, 0
# CHECKR-NEXT: R_LARCH_GOT_PC_LO12 _start
# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: pcaddu18i $ra, 0
+# CHECKR-NEXT: R_LARCH_CALL36 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: jirl $ra, $ra, 0
+# CHECKR-NEXT: pcaddu18i $a0, 0
+# CHECKR-NEXT: R_LARCH_CALL36 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: jr $a0
# CHECKR-NEXT: nop
# CHECKR-NEXT: R_LARCH_ALIGN *ABS*+0xc
# CHECKR-NEXT: nop
@@ -71,5 +96,9 @@
_start:
la.pcrel $a0, _start
la.got $a0, _start
+.ifdef ELF64
+ call36 _start
+ tail36 $a0, _start
+.endif
.p2align 4
ret
>From 1192441fd76a2c3bd407fa720b1d0d56e6b3f498 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 14 Feb 2025 14:11:17 +0800
Subject: [PATCH 18/20] Revert "Modify test. Add --relax option."
This reverts commit b57c40e275dc0977e002e68834c2b40fa030d9fc.
---
lld/test/ELF/loongarch-relax-tls-le.s | 4 ++--
lld/test/ELF/loongarch-tls-gd.s | 4 ++--
lld/test/ELF/loongarch-tls-ld.s | 8 ++++----
lld/test/ELF/loongarch-tls-le.s | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/lld/test/ELF/loongarch-relax-tls-le.s b/lld/test/ELF/loongarch-relax-tls-le.s
index b55f284f32cb8..8f9b6e1092a62 100644
--- a/lld/test/ELF/loongarch-relax-tls-le.s
+++ b/lld/test/ELF/loongarch-relax-tls-le.s
@@ -3,10 +3,10 @@
# 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 --relax %t.32.o -o %t.32
+# RUN: ld.lld %t.32.o -o %t.32
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX32 %s
-# RUN: ld.lld --relax %t.64.o -o %t.64
+# RUN: ld.lld %t.64.o -o %t.64
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX64 %s
# RELAX32-LABEL: <_start>:
diff --git a/lld/test/ELF/loongarch-tls-gd.s b/lld/test/ELF/loongarch-tls-gd.s
index 4cfed41d70f38..27d9fdb7ee701 100644
--- a/lld/test/ELF/loongarch-tls-gd.s
+++ b/lld/test/ELF/loongarch-tls-gd.s
@@ -20,7 +20,7 @@
# RUN: ld.lld -shared %t/a.32.o %t/bc.32.o -o %t/gd.32.so
# RUN: llvm-readobj -r %t/gd.32.so | FileCheck --check-prefix=GD32-REL %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.32.so | FileCheck --check-prefix=GD32 %s
-# RUN: ld.lld --relax -shared %t/a.32.relax.o %t/bc.32.o -o %t/gd.32.relax.so
+# RUN: ld.lld -shared %t/a.32.relax.o %t/bc.32.o -o %t/gd.32.relax.so
# RUN: llvm-readobj -r %t/gd.32.relax.so | FileCheck --check-prefix=GD32-REL-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.32.relax.so | FileCheck --check-prefix=GD32-RELAX %s
@@ -41,7 +41,7 @@
# RUN: ld.lld -shared %t/a.64.o %t/bc.64.o -o %t/gd.64.so
# RUN: llvm-readobj -r %t/gd.64.so | FileCheck --check-prefix=GD64-REL %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.64.so | FileCheck --check-prefix=GD64 %s
-# RUN: ld.lld --relax -shared %t/a.64.relax.o %t/bc.64.o -o %t/gd.64.relax.so
+# RUN: ld.lld -shared %t/a.64.relax.o %t/bc.64.o -o %t/gd.64.relax.so
# RUN: llvm-readobj -r %t/gd.64.relax.so | FileCheck --check-prefix=GD64-REL-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/gd.64.relax.so | FileCheck --check-prefix=GD64-RELAX %s
diff --git a/lld/test/ELF/loongarch-tls-ld.s b/lld/test/ELF/loongarch-tls-ld.s
index 6cf6fa92939d5..27adb1e17702a 100644
--- a/lld/test/ELF/loongarch-tls-ld.s
+++ b/lld/test/ELF/loongarch-tls-ld.s
@@ -17,7 +17,7 @@
# RUN: llvm-readobj -r %t/ld.32.so | FileCheck --check-prefix=LD32-REL %s
# RUN: llvm-readelf -x .got %t/ld.32.so | FileCheck --check-prefix=LD32-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.32.so | FileCheck --check-prefixes=LD32 %s
-# RUN: ld.lld --relax -shared %t/a.32.relax.o -o %t/ld.32.relax.so
+# RUN: ld.lld -shared %t/a.32.relax.o -o %t/ld.32.relax.so
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.32.relax.so | FileCheck --check-prefixes=LD32-RELAX %s
## LA32 LD -> LE
@@ -25,7 +25,7 @@
# RUN: llvm-readelf -r %t/le.32 | FileCheck --check-prefix=NOREL %s
# RUN: llvm-readelf -x .got %t/le.32 | FileCheck --check-prefix=LE32-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.32 | FileCheck --check-prefixes=LE32 %s
-# RUN: ld.lld --relax %t/a.32.relax.o %t/tga.32.o -o %t/le.32.relax
+# RUN: ld.lld %t/a.32.relax.o %t/tga.32.o -o %t/le.32.relax
# RUN: llvm-readelf -x .got %t/le.32.relax | FileCheck --check-prefix=LE32-GOT-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.32.relax | FileCheck --check-prefixes=LE32-RELAX %s
@@ -34,7 +34,7 @@
# RUN: llvm-readobj -r %t/ld.64.so | FileCheck --check-prefix=LD64-REL %s
# RUN: llvm-readelf -x .got %t/ld.64.so | FileCheck --check-prefix=LD64-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.64.so | FileCheck --check-prefixes=LD64 %s
-# RUN: ld.lld --relax -shared %t/a.64.relax.o -o %t/ld.64.relax.so
+# RUN: ld.lld -shared %t/a.64.relax.o -o %t/ld.64.relax.so
# RUN: llvm-objdump -d --no-show-raw-insn %t/ld.64.relax.so | FileCheck --check-prefixes=LD64-RELAX %s
## LA64 LD -> LE
@@ -42,7 +42,7 @@
# RUN: llvm-readelf -r %t/le.64 | FileCheck --check-prefix=NOREL %s
# RUN: llvm-readelf -x .got %t/le.64 | FileCheck --check-prefix=LE64-GOT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.64 | FileCheck --check-prefixes=LE64 %s
-# RUN: ld.lld --relax %t/a.64.relax.o %t/tga.64.o -o %t/le.64.relax
+# RUN: ld.lld %t/a.64.relax.o %t/tga.64.o -o %t/le.64.relax
# RUN: llvm-readelf -x .got %t/le.64.relax | FileCheck --check-prefix=LE64-GOT-RELAX %s
# RUN: llvm-objdump -d --no-show-raw-insn %t/le.64.relax | FileCheck --check-prefixes=LE64-RELAX %s
diff --git a/lld/test/ELF/loongarch-tls-le.s b/lld/test/ELF/loongarch-tls-le.s
index bc55e08591d28..981baa6fd726f 100644
--- a/lld/test/ELF/loongarch-tls-le.s
+++ b/lld/test/ELF/loongarch-tls-le.s
@@ -8,12 +8,12 @@
# RUN: ld.lld %t.32.o -o %t.32
# RUN: llvm-nm -p %t.32 | FileCheck --check-prefixes=NM %s
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE,LE32 %s
-# RUN: ld.lld --relax %t.32.relax.o -o %t.32.relax
+# RUN: ld.lld %t.32.relax.o -o %t.32.relax
# RUN: llvm-objdump -d --no-show-raw-insn %t.32.relax | FileCheck --check-prefixes=LE,LE32-RELAX %s
# RUN: ld.lld %t.64.o -o %t.64
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE,LE64 %s
-# RUN: ld.lld --relax %t.64.relax.o -o %t.64.relax
+# RUN: ld.lld %t.64.relax.o -o %t.64.relax
# RUN: llvm-objdump -d --no-show-raw-insn %t.64.relax | FileCheck --check-prefixes=LE,LE64-RELAX %s
# RUN: not ld.lld -shared %t.32.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
>From e627784a042eb02a4b26eca40af0b9f2d1bb4f56 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Fri, 14 Feb 2025 14:18:29 +0800
Subject: [PATCH 19/20] Remove unnecessary spaces.
---
lld/test/ELF/loongarch-relax-emit-relocs.s | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index df2c713855a26..0f4ca2ce03657 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -17,12 +17,12 @@
# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
# RELAX: 00010000 <_start>:
-# RELAX-NEXT: pcaddi $a0, 0
+# RELAX-NEXT: pcaddi $a0, 0
# RELAX-NEXT: R_LARCH_RELAX _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
-# RELAX-NEXT: pcaddi $a0, -1
+# RELAX-NEXT: pcaddi $a0, -1
# RELAX-NEXT: R_LARCH_RELAX _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
@@ -191,7 +191,6 @@ addi.w \dst, \src1, \src2
_start:
la.pcrel $a0, _start
la.got $a0, _start
-
.ifdef ELF64
call36 _start
tail36 $a0, _start
>From 26c1e0c29bd09e58d80a6d8ef8552cf1c817c0af Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Mon, 17 Feb 2025 11:28:26 +0800
Subject: [PATCH 20/20] Fixes for reviews.
---
lld/ELF/Arch/LoongArch.cpp | 17 ++++++----
lld/test/ELF/loongarch-relax-tls-le.s | 46 +++++++++++++--------------
2 files changed, 33 insertions(+), 30 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 526d8061fec26..709b31ed4e01a 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -154,6 +154,10 @@ static uint32_t setJ20(uint32_t insn, uint32_t imm) {
return (insn & 0xfe00001f) | (extractBits(imm, 19, 0) << 5);
}
+static uint32_t setJ5(uint32_t insn, uint32_t imm) {
+ return (insn & 0xfffffc1f) | (extractBits(imm, 4, 0) << 5);
+}
+
static uint32_t setK12(uint32_t insn, uint32_t imm) {
return (insn & 0xffc003ff) | (extractBits(imm, 11, 0) << 10);
}
@@ -895,9 +899,7 @@ static void relaxTlsLe(Ctx &ctx, const InputSection &sec, size_t i,
remove = 4;
break;
case R_LARCH_TLS_LE_LO12_R:
- currInsn =
- insn(extractBits(currInsn, 31, 22) << 22, getD5(currInsn), R_TP, 0);
- sec.relaxAux->writes.push_back(currInsn);
+ sec.relaxAux->writes.push_back(setJ5(currInsn, R_TP));
sec.relaxAux->relocTypes[i] = R_LARCH_TLS_LE_LO12_R;
break;
}
@@ -1069,10 +1071,11 @@ void LoongArch::finalizeRelax(int passes) const {
break;
case R_LARCH_TLS_GD_PCREL20_S2:
// Note: R_LARCH_TLS_LD_PCREL20_S2 must also use R_TLSGD_PC instead
- // of R_TLSLD_PC because the processing of relocation
- // R_LARCH_TLS_LD_PC_HI20 is the same as R_LARCH_TLS_GD_PC_HI20. If
- // not, the value obtained from getRelocTargetVA will be unexpected
- // and lead to error.
+ // of R_TLSLD_PC due to historical reasons. In fact, right now TLSLD
+ // behaves exactly like TLSGD on LoongArch.
+ //
+ // This reason has also been mentioned in mold commit:
+ // https://github.com/rui314/mold/commit/5dfa1cf07c03bd57cb3d493b652ef22441bcd71c
case R_LARCH_TLS_LD_PCREL20_S2:
skip = 4;
write32le(p, aux.writes[writesIdx++]);
diff --git a/lld/test/ELF/loongarch-relax-tls-le.s b/lld/test/ELF/loongarch-relax-tls-le.s
index 8f9b6e1092a62..a91374b6e81a3 100644
--- a/lld/test/ELF/loongarch-relax-tls-le.s
+++ b/lld/test/ELF/loongarch-relax-tls-le.s
@@ -39,9 +39,9 @@
.macro add dst, src1, src2, src3
.ifdef ELF32
-add.w \dst, \src1, \src2, \src3
+ add.w \dst, \src1, \src2, \src3
.else
-add.d \dst, \src1, \src2, \src3
+ add.d \dst, \src1, \src2, \src3
.endif
.endm
.macro inst op dst, src1, src2
@@ -73,38 +73,38 @@ add.d \dst, \src1, \src2, \src3
.endm
.macro addi dst, src1, src2
-inst addi \dst, \src1, \src2
+ inst addi \dst, \src1, \src2
.endm
.macro ld dst, src1, src2
-inst ld \dst, \src1, \src2
+ inst ld \dst, \src1, \src2
.endm
.macro st dst, src1, src2
-inst st \dst, \src1, \src2
+ inst st \dst, \src1, \src2
.endm
.macro ldptr dst, src1, src2
-inst ldptr \dst, \src1, \src2
+ inst ldptr \dst, \src1, \src2
.endm
_start:
-## Test instructions not in pairs.
-lu12i.w $a0, %le_hi20_r(.LANCHOR0)
-add $a0, $a0, $tp, %le_add_r(.LANCHOR0)
-addi $a0, $a0, %le_lo12_r(.LANCHOR0)
-ld $a1, $a0, 0
-ld $a2, $a0, %le_lo12_r(.LANCHOR0)
+ ## Test instructions not in pairs.
+ lu12i.w $a0, %le_hi20_r(.LANCHOR0)
+ add $a0, $a0, $tp, %le_add_r(.LANCHOR0)
+ addi $a0, $a0, %le_lo12_r(.LANCHOR0)
+ ld $a1, $a0, 0
+ ld $a2, $a0, %le_lo12_r(.LANCHOR0)
-## hi20(a-4) = hi20(0x7fc) = 0. relaxable
-## Test non-adjacent instructions.
-lu12i.w $a0, %le_hi20_r(a-4)
-addi $a1, $zero, 0x1
-add $a0, $a0, $tp, %le_add_r(a-4)
-addi $a1, $a1, 0x2
-st $a1, $a0, %le_lo12_r(a-4)
+ ## hi20(a-4) = hi20(0x7fc) = 0. relaxable
+ ## Test non-adjacent instructions.
+ lu12i.w $a0, %le_hi20_r(a-4)
+ addi $a1, $zero, 0x1
+ add $a0, $a0, $tp, %le_add_r(a-4)
+ addi $a1, $a1, 0x2
+ st $a1, $a0, %le_lo12_r(a-4)
-## hi20(a) = hi20(0x800) = 1. not relaxable
-lu12i.w $a0, %le_hi20_r(a)
-add $a0, $a0, $tp, %le_add_r(a)
-addi $a0, $a0, %le_lo12_r(a)
+ ## hi20(a) = hi20(0x800) = 1. not relaxable
+ lu12i.w $a0, %le_hi20_r(a)
+ add $a0, $a0, $tp, %le_add_r(a)
+ addi $a0, $a0, %le_lo12_r(a)
.section .tbss,"awT", at nobits
.space 8
More information about the llvm-commits
mailing list