[lld] [lld][LoongArch] Relax R_LARCH_PCALA_HI20 and R_LARCH_PCALA_LO12 (PR #112696)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 18 19:08:21 PST 2024
https://github.com/ywgrit updated https://github.com/llvm/llvm-project/pull/112696
>From cf61f100d89e069ba98c2fa7f800658d3aa001d7 Mon Sep 17 00:00:00 2001
From: Xin Wang <wangxin03 at loongson.cn>
Date: Thu, 17 Oct 2024 11:45:06 +0800
Subject: [PATCH 1/7] [lld][LoongArch] Define macros to operate insns and
registers
---
lld/ELF/Arch/LoongArch.cpp | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 5923cda2298b4e..8c3901d641428a 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -22,6 +22,40 @@ using namespace lld;
using namespace lld::elf;
namespace {
+#define LARCH_GET_RD(insn) (insn & 0x1f)
+#define LARCH_GET_RJ(insn) ((insn >> 5) & 0x1f)
+#define LARCH_MK_ADDI_D 0xffc00000
+#define LARCH_OP_ADDI_D 0x02c00000
+#define LARCH_MK_PCADDI 0xfe000000
+#define LARCH_OP_PCADDI 0x18000000
+#define LARCH_MK_PCALAU12I 0xfe000000
+#define LARCH_OP_PCALAU12I 0x1a000000
+#define LARCH_MK_LD_D 0xffc00000
+#define LARCH_OP_LD_D 0x28c00000
+#define LARCH_MK_LD_W 0xffc00000
+#define LARCH_OP_LD_W 0x28800000
+#define LARCH_MK_LU12I_W 0xfe000000
+#define LARCH_OP_LU12I_W 0x14000000
+#define LARCH_MK_ORI 0xffc00000
+#define LARCH_OP_ORI 0x03800000
+#define LARCH_MK_B 0xfc000000
+#define LARCH_OP_B 0x50000000
+#define LARCH_MK_BL 0xfc000000
+#define LARCH_OP_BL 0x54000000
+#define LARCH_MK_JIRL 0xfc000000
+#define LARCH_OP_JIRL 0x4c000000
+#define LARCH_INSN_OPS(insn, op) ((insn & LARCH_MK_##op) == LARCH_OP_##op)
+#define LARCH_INSN_ADDI_D(insn) LARCH_INSN_OPS((insn), ADDI_D)
+#define LARCH_INSN_PCADDI(insn) LARCH_INSN_OPS((insn), PCADDI)
+#define LARCH_INSN_PCALAU12I(insn) LARCH_INSN_OPS((insn), PCALAU12I)
+#define LARCH_INSN_LD_D(insn) LARCH_INSN_OPS((insn), LD_D)
+#define LARCH_INSN_LD_W(insn) LARCH_INSN_OPS((insn), LD_W)
+#define LARCH_INSN_LU12I_W(insn) LARCH_INSN_OPS((insn), LU12I_W)
+#define LARCH_INSN_ORI(insn) LARCH_INSN_OPS((insn), ORI)
+#define LARCH_INSN_B(insn) LARCH_INSN_OPS((insn), B)
+#define LARCH_INSN_BL(insn) LARCH_INSN_OPS((insn), BL)
+#define LARCH_INSN_JIRL(insn) LARCH_INSN_OPS((insn), JIRL)
+
class LoongArch final : public TargetInfo {
public:
LoongArch(Ctx &);
@@ -63,6 +97,7 @@ enum Reg {
R_ZERO = 0,
R_RA = 1,
R_TP = 2,
+ R_A0 = 4,
R_T0 = 12,
R_T1 = 13,
R_T2 = 14,
>From 8f9e9c8e264b72ab161e2963da1bc82059d5a551 Mon Sep 17 00:00:00 2001
From: Xin Wang <wangxin03 at loongson.cn>
Date: Thu, 17 Oct 2024 19:47:07 +0800
Subject: [PATCH 2/7] [lld][loongArch] Relax R_LARCH_PCALA_HI20 and
R_LARCH_PCALA_LO12
A pair of pcalau12i+addi.d relocated by R_LARCH_PCALA_HI20 and
R_LARCH_PCALA_LO12 can be converted to pcaddi.
---
lld/ELF/Arch/LoongArch.cpp | 93 +++++++++-
lld/ELF/InputSection.cpp | 11 ++
lld/test/ELF/loongarch-relax-align.s | 194 ++++++++++++++++-----
lld/test/ELF/loongarch-relax-emit-relocs.s | 85 +++++----
4 files changed, 311 insertions(+), 72 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 8c3901d641428a..e7276c23d0ab88 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -72,11 +72,16 @@ class LoongArch final : public TargetInfo {
bool usesOnlyLowPageBits(RelType type) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
+ void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
bool relaxOnce(int pass) const override;
void finalizeRelax(int passes) const override;
};
} // end anonymous namespace
+// The internal relocation number for local got relaxation which isn't part
+// of the psABI spec.
+#define INTERNAL_R_LARCH_PCALA_LO12 256
+
namespace {
enum Op {
SUB_W = 0x00110000,
@@ -779,6 +784,69 @@ 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;
+}
+
+// Returns true if the two instructions corresponding to the i-th reloc
+// entry and the i+2-th reloc entry can apply relaxation. For scenarios
+// with fewer than four reloc entries, e.g., R_ALRCH_CALL36, this function
+// should not be used to make a judgment.
+static bool isPair(ArrayRef<Relocation> relocs, size_t i) {
+ return relaxable(relocs, i) && relaxable(relocs, i + 2) &&
+ relocs[i].offset + 4 == relocs[i + 2].offset;
+}
+
+void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+ const unsigned bits = ctx.arg.is64 ? 64 : 32;
+ uint64_t secAddr = sec.getOutputSection()->addr;
+ if (auto *s = dyn_cast<InputSection>(&sec))
+ secAddr += s->outSecOff;
+ else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
+ secAddr += ehIn->getParent()->outSecOff;
+ const ArrayRef<Relocation> relocs = sec.relocs();
+ for (size_t i = 0, size = relocs.size(); i != size; ++i) {
+ const Relocation &rel = relocs[i];
+ uint8_t *loc = buf + rel.offset;
+ uint64_t val = SignExtend64(
+ sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), bits);
+
+ switch (rel.expr) {
+ case R_RELAX_HINT:
+ continue;
+ default:
+ break;
+ }
+ relocate(loc, rel, val);
+ }
+}
+
+// Relax pcalau12i,addi.d => pcaddi.
+static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
+ Relocation &r_hi, uint32_t &remove) {
+ const uint64_t symval =
+ (r_hi.expr == R_LOONGARCH_PLT_PAGE_PC ? r_hi.sym->getPltVA(ctx) : r_hi.sym->getVA()) + r_hi.addend;
+ const int64_t dist = symval - loc;
+ uint32_t pca = read32le(sec.content().data() + r_hi.offset);
+ uint32_t add = read32le(sec.content().data() + r_hi.offset + 4);
+ uint32_t rd = LARCH_GET_RD(pca);
+
+ if (!LARCH_INSN_ADDI_D(add)
+ // Is pcalau12i $rd + addi.d $rd, $rd?
+ || LARCH_GET_RD(add) != rd
+ || LARCH_GET_RJ(add) != rd
+ // 4 bytes align
+ || symval & 0x3
+ || !isInt<22>(dist))
+ return;
+
+ // remove the first insn
+ sec.relaxAux->relocTypes[i] = R_LARCH_RELAX;
+ sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
+ sec.relaxAux->writes.push_back(LARCH_OP_PCADDI | rd); // pcaddi
+ remove = 4;
+}
+
static bool relax(Ctx &ctx, InputSection &sec) {
const uint64_t secAddr = sec.getVA();
const MutableArrayRef<Relocation> relocs = sec.relocs();
@@ -817,6 +885,11 @@ static bool relax(Ctx &ctx, InputSection &sec) {
}
break;
}
+ case R_LARCH_PCALA_HI20:
+ if (isPair(relocs, i)
+ && relocs[i + 2].type == R_LARCH_PCALA_LO12)
+ relaxPcalaAddi(sec, i, loc, r, remove);
+ break;
}
// For all anchors whose offsets are <= r.offset, they are preceded by
@@ -887,6 +960,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 = context().bAlloc.Allocate<uint8_t>(newSize);
uint64_t offset = 0;
int64_t delta = 0;
@@ -907,7 +981,24 @@ void LoongArch::finalizeRelax(int passes) const {
uint64_t size = r.offset - offset;
memcpy(p, old.data() + offset, size);
p += size;
- offset = r.offset + remove;
+
+ int64_t skip = 0;
+ if (r.type != R_LARCH_ALIGN) {
+ RelType newType = aux.relocTypes[i];
+ switch (newType) {
+ case R_LARCH_RELAX:
+ break;
+ case R_LARCH_PCREL20_S2:
+ skip = 4;
+ write32le(p, aux.writes[writesIdx++]);
+ break;
+ default:
+ llvm_unreachable("unsupported type");
+ }
+ }
+
+ p += skip;
+ offset = r.offset + remove + skip;
}
memcpy(p, old.data() + offset, old.size() - offset);
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 2e9e8a7007bbf8..b093a8790ef1a7 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -737,6 +737,17 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
int64_t a = r.addend;
switch (r.expr) {
case R_ABS:
+ // pcalau12i,addi.d => pcaddi
+ // With relaxation applied, the relocation type of the third
+ // reloc entry which corresponds to the addi.d insn is converted
+ // from R_LARCH_PCALA_LO12 to R_LARCH_PCREL20_S2.
+ if (r.type == R_LARCH_PCREL20_S2) {
+ if (r.sym->hasFlag(NEEDS_PLT))
+ return r.sym->getPltVA(ctx) + a - p;
+ else
+ return r.sym->getVA(a) - p;
+ }
+ [[fallthrough]];
case R_DTPREL:
case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s
index ab61e15d5caca2..9cbbc69b91c1cb 100644
--- a/lld/test/ELF/loongarch-relax-align.s
+++ b/lld/test/ELF/loongarch-relax-align.s
@@ -6,56 +6,170 @@
# 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 %s --check-prefix=RELAX32
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck %s --check-prefixes=RELAX64,SRELAX64
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32n | FileCheck %s --check-prefix=NORELAX
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64n | FileCheck %s --check-prefix=NORELAX
## 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 %s --check-prefixes=RELAX64,ORELAX64
+# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck %s --check-prefix=ONORELAX
## -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
+# RELAX32-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
+# RELAX32-DAG: {{0*}}10000 l .text {{0*}}44 .Ltext_start
+# RELAX32-DAG: {{0*}}10038 l .text {{0*}}0c .L1
+# RELAX32-DAG: {{0*}}10040 l .text {{0*}}04 .L2
+# RELAX32-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
+
+# RELAX32: <.Ltext_start>:
+# RELAX32-NEXT: break 1
+# RELAX32-NEXT: break 2
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: break 3
+# RELAX32-NEXT: break 4
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: pcalau12i $a0, 0
+# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# RELAX32-NEXT: pcalau12i $a0, 0
+# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 56
+# RELAX32-NEXT: pcalau12i $a0, 0
+# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 64
+# RELAX32-EMPTY:
+# RELAX32-NEXT: <.L1>:
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: nop
+# RELAX32-EMPTY:
+# RELAX32-NEXT: <.L2>:
+# RELAX32-NEXT: break 5
+
+# RELAX32: <.Ltext2_start>:
+# RELAX32-NEXT: pcalau12i $a0, 0
+# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: nop
+# RELAX32-NEXT: break 6
+
+# NORELAX-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
+# 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
+
+
+
+# ORELAX64-DAG: {{0*}}00001 l *ABS* {{0*}}00 old
+# SRELAX64-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
+# RELAX64-DAG: {{0*}}10000 l .text {{0*}}34 .Ltext_start
+# RELAX64-DAG: {{0*}}1002c l .text {{0*}}08 .L1
+# RELAX64-DAG: {{0*}}10030 l .text {{0*}}04 .L2
+# RELAX64-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
+
+# RELAX64: <.Ltext_start>:
+# RELAX64-NEXT: break 1
+# RELAX64-NEXT: break 2
+# RELAX64-NEXT: nop
+# RELAX64-NEXT: nop
+# RELAX64-NEXT: break 3
+# RELAX64-NEXT: break 4
+# RELAX64-NEXT: nop
+# RELAX64-NEXT: nop
+# RELAX64-NEXT: pcaddi $a0, -8
+# RELAX64-NEXT: pcaddi $a0, 2
+# RELAX64-NEXT: pcaddi $a0, 2
+# RELAX64-EMPTY:
+# RELAX64-NEXT: <.L1>:
+# RELAX64-NEXT: nop
+# RELAX64-EMPTY:
+# RELAX64-NEXT: <.L2>:
+# RELAX64-NEXT: break 5
+
+# RELAX64: <.Ltext2_start>:
+# RELAX64-NEXT: pcaddi $a0, 0
+# RELAX64-NEXT: nop
+# RELAX64-NEXT: nop
+# RELAX64-NEXT: nop
+# RELAX64-NEXT: break 6
+
+
+# ONORELAX-DAG: {{0*}}00001 l *ABS* {{0*}}00 old
+# ONORELAX-DAG: {{0*}}10000 l .text {{0*}}44 .Ltext_start
+# ONORELAX-DAG: {{0*}}10038 l .text {{0*}}0c .L1
+# ONORELAX-DAG: {{0*}}10040 l .text {{0*}}04 .L2
+# ONORELAX-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
+
+# ONORELAX: <.Ltext_start>:
+# ONORELAX-NEXT: break 1
+# ONORELAX-NEXT: break 2
+# ONORELAX-NEXT: nop
+# ONORELAX-NEXT: nop
+# ONORELAX-NEXT: break 3
+# ONORELAX-NEXT: break 4
+# ONORELAX-NEXT: nop
+# ONORELAX-NEXT: nop
+# ONORELAX-NEXT: pcalau12i $a0, 0
+# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# ONORELAX-NEXT: pcalau12i $a0, 0
+# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 56
+# ONORELAX-NEXT: pcalau12i $a0, 0
+# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 64
+# ONORELAX-EMPTY:
+# ONORELAX-NEXT: <.L1>:
+# ONORELAX-NEXT: nop
+# ONORELAX-NEXT: nop
+# ONORELAX-EMPTY:
+# ONORELAX-NEXT: <.L2>:
+# ONORELAX-NEXT: break 5
+
+# ONORELAX: <.Ltext2_start>:
+# ONORELAX-NEXT: pcalau12i $a0, 0
+# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# ONORELAX-NEXT: nop
+# ONORELAX-NEXT: nop
+# ONORELAX-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 ba414e8c93f0fb..8784bf57e7ff33 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -5,42 +5,65 @@
# 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=LA32RELOC
+# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=LA64RELOC
## -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
+# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=RELAX
-## --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
-
-# 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
-
-# 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: R_LARCH_PCALA_LO12 _start
-# 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
+# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=NORELAX
+
+# LA32RELOC: 00010000 <_start>:
+# LA32RELOC-NEXT: pcalau12i $a0, 0
+# LA32RELOC-NEXT: R_LARCH_PCALA_HI20 _start
+# LA32RELOC-NEXT: R_LARCH_RELAX *ABS*
+# LA32RELOC-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# LA32RELOC-NEXT: R_LARCH_PCALA_LO12 _start
+# LA32RELOC-NEXT: R_LARCH_RELAX *ABS*
+# LA32RELOC-NEXT: nop
+# LA32RELOC-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# LA32RELOC-NEXT: nop
+# LA32RELOC-NEXT: ret
+
+# LA64RELOC: 00010000 <_start>:
+# LA64RELOC-NEXT: pcaddi $a0, 0
+# LA64RELOC-NEXT: R_LARCH_RELAX _start
+# LA64RELOC-NEXT: R_LARCH_RELAX *ABS*
+# LA64RELOC-NEXT: R_LARCH_PCREL20_S2 _start
+# LA64RELOC-NEXT: R_LARCH_RELAX *ABS*
+# LA64RELOC-NEXT: nop
+# LA64RELOC-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# LA64RELOC-NEXT: nop
+# LA64RELOC-NEXT: nop
+# LA64RELOC-NEXT: ret
+
+
+# RELAX: <_start>:
+# RELAX-NEXT: pcalau12i $a0, 0
+# RELAX-NEXT: R_LARCH_PCALA_HI20 _start
+# RELAX-NEXT: R_LARCH_RELAX *ABS*
+# RELAX-NEXT: addi.d $a0, $a0, 0
+# RELAX-NEXT: R_LARCH_PCALA_LO12 _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
.global _start
_start:
>From daea555d1a4828274424f6e3862f22e4d1ca5747 Mon Sep 17 00:00:00 2001
From: Xin Wang <wangxin03 at loongson.cn>
Date: Fri, 18 Oct 2024 09:27:48 +0800
Subject: [PATCH 3/7] [lld][LoongArch] clang-format code
---
lld/ELF/Arch/LoongArch.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index e7276c23d0ab88..ca3a7fe0108826 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -823,9 +823,11 @@ void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
// Relax pcalau12i,addi.d => pcaddi.
static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
- Relocation &r_hi, uint32_t &remove) {
+ Relocation &r_hi, uint32_t &remove) {
const uint64_t symval =
- (r_hi.expr == R_LOONGARCH_PLT_PAGE_PC ? r_hi.sym->getPltVA(ctx) : r_hi.sym->getVA()) + r_hi.addend;
+ (r_hi.expr == R_LOONGARCH_PLT_PAGE_PC ? r_hi.sym->getPltVA(ctx)
+ : r_hi.sym->getVA()) +
+ r_hi.addend;
const int64_t dist = symval - loc;
uint32_t pca = read32le(sec.content().data() + r_hi.offset);
uint32_t add = read32le(sec.content().data() + r_hi.offset + 4);
@@ -833,11 +835,10 @@ static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
if (!LARCH_INSN_ADDI_D(add)
// Is pcalau12i $rd + addi.d $rd, $rd?
- || LARCH_GET_RD(add) != rd
- || LARCH_GET_RJ(add) != rd
+ || LARCH_GET_RD(add) != rd ||
+ LARCH_GET_RJ(add) != rd
// 4 bytes align
- || symval & 0x3
- || !isInt<22>(dist))
+ || symval & 0x3 || !isInt<22>(dist))
return;
// remove the first insn
@@ -886,8 +887,7 @@ static bool relax(Ctx &ctx, InputSection &sec) {
break;
}
case R_LARCH_PCALA_HI20:
- if (isPair(relocs, i)
- && relocs[i + 2].type == R_LARCH_PCALA_LO12)
+ if (isPair(relocs, i) && relocs[i + 2].type == R_LARCH_PCALA_LO12)
relaxPcalaAddi(sec, i, loc, r, remove);
break;
}
>From 289963686ad9cda99fead49ef489847c58b53d89 Mon Sep 17 00:00:00 2001
From: Xin Wang <wangxin03 at loongson.cn>
Date: Tue, 22 Oct 2024 19:19:01 +0800
Subject: [PATCH 4/7] [lld][LoongArch] remove unused code and determine the
boundaries of relocs correctly
---
lld/ELF/Arch/LoongArch.cpp | 41 ++++----------------------------------
1 file changed, 4 insertions(+), 37 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index ca3a7fe0108826..dbe3f447eb3fe0 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -23,38 +23,14 @@ using namespace lld::elf;
namespace {
#define LARCH_GET_RD(insn) (insn & 0x1f)
-#define LARCH_GET_RJ(insn) ((insn >> 5) & 0x1f)
+#define LARCH_GET_RJ(insn) (insn >> 5 & 0x1f)
#define LARCH_MK_ADDI_D 0xffc00000
#define LARCH_OP_ADDI_D 0x02c00000
#define LARCH_MK_PCADDI 0xfe000000
#define LARCH_OP_PCADDI 0x18000000
-#define LARCH_MK_PCALAU12I 0xfe000000
-#define LARCH_OP_PCALAU12I 0x1a000000
-#define LARCH_MK_LD_D 0xffc00000
-#define LARCH_OP_LD_D 0x28c00000
-#define LARCH_MK_LD_W 0xffc00000
-#define LARCH_OP_LD_W 0x28800000
-#define LARCH_MK_LU12I_W 0xfe000000
-#define LARCH_OP_LU12I_W 0x14000000
-#define LARCH_MK_ORI 0xffc00000
-#define LARCH_OP_ORI 0x03800000
-#define LARCH_MK_B 0xfc000000
-#define LARCH_OP_B 0x50000000
-#define LARCH_MK_BL 0xfc000000
-#define LARCH_OP_BL 0x54000000
-#define LARCH_MK_JIRL 0xfc000000
-#define LARCH_OP_JIRL 0x4c000000
#define LARCH_INSN_OPS(insn, op) ((insn & LARCH_MK_##op) == LARCH_OP_##op)
#define LARCH_INSN_ADDI_D(insn) LARCH_INSN_OPS((insn), ADDI_D)
#define LARCH_INSN_PCADDI(insn) LARCH_INSN_OPS((insn), PCADDI)
-#define LARCH_INSN_PCALAU12I(insn) LARCH_INSN_OPS((insn), PCALAU12I)
-#define LARCH_INSN_LD_D(insn) LARCH_INSN_OPS((insn), LD_D)
-#define LARCH_INSN_LD_W(insn) LARCH_INSN_OPS((insn), LD_W)
-#define LARCH_INSN_LU12I_W(insn) LARCH_INSN_OPS((insn), LU12I_W)
-#define LARCH_INSN_ORI(insn) LARCH_INSN_OPS((insn), ORI)
-#define LARCH_INSN_B(insn) LARCH_INSN_OPS((insn), B)
-#define LARCH_INSN_BL(insn) LARCH_INSN_OPS((insn), BL)
-#define LARCH_INSN_JIRL(insn) LARCH_INSN_OPS((insn), JIRL)
class LoongArch final : public TargetInfo {
public:
@@ -77,11 +53,6 @@ class LoongArch final : public TargetInfo {
void finalizeRelax(int passes) const override;
};
} // end anonymous namespace
-
-// The internal relocation number for local got relaxation which isn't part
-// of the psABI spec.
-#define INTERNAL_R_LARCH_PCALA_LO12 256
-
namespace {
enum Op {
SUB_W = 0x00110000,
@@ -785,7 +756,7 @@ 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;
+ return i + 1 < relocs.size() && relocs[i + 1].type == R_LARCH_RELAX;
}
// Returns true if the two instructions corresponding to the i-th reloc
@@ -833,12 +804,8 @@ static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
uint32_t add = read32le(sec.content().data() + r_hi.offset + 4);
uint32_t rd = LARCH_GET_RD(pca);
- if (!LARCH_INSN_ADDI_D(add)
- // Is pcalau12i $rd + addi.d $rd, $rd?
- || LARCH_GET_RD(add) != rd ||
- LARCH_GET_RJ(add) != rd
- // 4 bytes align
- || symval & 0x3 || !isInt<22>(dist))
+ if (!LARCH_INSN_ADDI_D(add) || LARCH_GET_RJ(add) != rd ||
+ symval & 0x3 /* 4 bytes align */ || !isInt<22>(dist))
return;
// remove the first insn
>From 84b666d5056beb7ea1f64ec6cef73ffb22056316 Mon Sep 17 00:00:00 2001
From: Xin Wang <wangxin03 at loongson.cn>
Date: Mon, 28 Oct 2024 15:13:20 +0800
Subject: [PATCH 5/7] [lld][LoongArch] support relaxation on LoongArch32
---
lld/ELF/Arch/LoongArch.cpp | 10 +-
lld/ELF/InputSection.cpp | 4 +-
lld/test/ELF/loongarch-relax-align.s | 157 ++++++---------------
lld/test/ELF/loongarch-relax-emit-relocs.s | 66 +++------
4 files changed, 70 insertions(+), 167 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index dbe3f447eb3fe0..d854c29f56a0ad 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -24,11 +24,14 @@ using namespace lld::elf;
namespace {
#define LARCH_GET_RD(insn) (insn & 0x1f)
#define LARCH_GET_RJ(insn) (insn >> 5 & 0x1f)
+#define LARCH_MK_ADDI_W 0xffc00000
+#define LARCH_OP_ADDI_W 0x02800000
#define LARCH_MK_ADDI_D 0xffc00000
#define LARCH_OP_ADDI_D 0x02c00000
#define LARCH_MK_PCADDI 0xfe000000
#define LARCH_OP_PCADDI 0x18000000
#define LARCH_INSN_OPS(insn, op) ((insn & LARCH_MK_##op) == LARCH_OP_##op)
+#define LARCH_INSN_ADDI_W(insn) LARCH_INSN_OPS((insn), ADDI_W)
#define LARCH_INSN_ADDI_D(insn) LARCH_INSN_OPS((insn), ADDI_D)
#define LARCH_INSN_PCADDI(insn) LARCH_INSN_OPS((insn), PCADDI)
@@ -792,7 +795,7 @@ void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
}
}
-// Relax pcalau12i,addi.d => pcaddi.
+// Relax pcalau12i,addi.[wd] => pcaddi.
static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
Relocation &r_hi, uint32_t &remove) {
const uint64_t symval =
@@ -804,8 +807,9 @@ static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
uint32_t add = read32le(sec.content().data() + r_hi.offset + 4);
uint32_t rd = LARCH_GET_RD(pca);
- if (!LARCH_INSN_ADDI_D(add) || LARCH_GET_RJ(add) != rd ||
- symval & 0x3 /* 4 bytes align */ || !isInt<22>(dist))
+ if ((!LARCH_INSN_ADDI_W(add) && !LARCH_INSN_ADDI_D(add)) ||
+ LARCH_GET_RJ(add) != rd || symval & 0x3 /* 4 bytes align */ ||
+ !isInt<22>(dist))
return;
// remove the first insn
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index b093a8790ef1a7..1d5f53dfecb8ab 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -737,9 +737,9 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
int64_t a = r.addend;
switch (r.expr) {
case R_ABS:
- // pcalau12i,addi.d => pcaddi
+ // pcalau12i,addi.[wd] => pcaddi
// With relaxation applied, the relocation type of the third
- // reloc entry which corresponds to the addi.d insn is converted
+ // reloc entry which corresponds to the addi.[wd] insn is converted
// from R_LARCH_PCALA_LO12 to R_LARCH_PCREL20_S2.
if (r.type == R_LARCH_PCREL20_S2) {
if (r.sym->hasFlag(NEEDS_PLT))
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s
index 9cbbc69b91c1cb..cbe3e629b81dee 100644
--- a/lld/test/ELF/loongarch-relax-align.s
+++ b/lld/test/ELF/loongarch-relax-align.s
@@ -6,59 +6,24 @@
# 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 --check-prefix=RELAX32
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck %s --check-prefixes=RELAX64,SRELAX64
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32n | FileCheck %s --check-prefix=NORELAX
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64n | FileCheck %s --check-prefix=NORELAX
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck %s --check-prefix=RELAX
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck %s --check-prefixes=RELAX,NOABSRELAX
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32n | FileCheck %s --check-prefixes=NORELAX,NOABSNORELAX
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64n | FileCheck %s --check-prefixes=NORELAX,NOABSNORELAX
## 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 --check-prefixes=RELAX64,ORELAX64
-# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck %s --check-prefix=ONORELAX
+# RUN: llvm-objdump -td --no-show-raw-insn %t.o64 | FileCheck %s --check-prefixes=RELAX,ABSRELAX
+# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck %s --check-prefixes=NORELAX,ABSNORELAX
## -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
-# RELAX32-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
-# RELAX32-DAG: {{0*}}10000 l .text {{0*}}44 .Ltext_start
-# RELAX32-DAG: {{0*}}10038 l .text {{0*}}0c .L1
-# RELAX32-DAG: {{0*}}10040 l .text {{0*}}04 .L2
-# RELAX32-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
-
-# RELAX32: <.Ltext_start>:
-# RELAX32-NEXT: break 1
-# RELAX32-NEXT: break 2
-# RELAX32-NEXT: nop
-# RELAX32-NEXT: nop
-# RELAX32-NEXT: break 3
-# RELAX32-NEXT: break 4
-# RELAX32-NEXT: nop
-# RELAX32-NEXT: nop
-# RELAX32-NEXT: pcalau12i $a0, 0
-# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# RELAX32-NEXT: pcalau12i $a0, 0
-# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 56
-# RELAX32-NEXT: pcalau12i $a0, 0
-# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 64
-# RELAX32-EMPTY:
-# RELAX32-NEXT: <.L1>:
-# RELAX32-NEXT: nop
-# RELAX32-NEXT: nop
-# RELAX32-EMPTY:
-# RELAX32-NEXT: <.L2>:
-# RELAX32-NEXT: break 5
-
-# RELAX32: <.Ltext2_start>:
-# RELAX32-NEXT: pcalau12i $a0, 0
-# RELAX32-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# RELAX32-NEXT: nop
-# RELAX32-NEXT: nop
-# RELAX32-NEXT: break 6
-
-# NORELAX-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
+# NOABSNORELAX-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
+# ABSNORELAX-DAG: {{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
@@ -95,80 +60,38 @@
# NORELAX-NEXT: break 6
-
-# ORELAX64-DAG: {{0*}}00001 l *ABS* {{0*}}00 old
-# SRELAX64-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
-# RELAX64-DAG: {{0*}}10000 l .text {{0*}}34 .Ltext_start
-# RELAX64-DAG: {{0*}}1002c l .text {{0*}}08 .L1
-# RELAX64-DAG: {{0*}}10030 l .text {{0*}}04 .L2
-# RELAX64-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
-
-# RELAX64: <.Ltext_start>:
-# RELAX64-NEXT: break 1
-# RELAX64-NEXT: break 2
-# RELAX64-NEXT: nop
-# RELAX64-NEXT: nop
-# RELAX64-NEXT: break 3
-# RELAX64-NEXT: break 4
-# RELAX64-NEXT: nop
-# RELAX64-NEXT: nop
-# RELAX64-NEXT: pcaddi $a0, -8
-# RELAX64-NEXT: pcaddi $a0, 2
-# RELAX64-NEXT: pcaddi $a0, 2
-# RELAX64-EMPTY:
-# RELAX64-NEXT: <.L1>:
-# RELAX64-NEXT: nop
-# RELAX64-EMPTY:
-# RELAX64-NEXT: <.L2>:
-# RELAX64-NEXT: break 5
-
-# RELAX64: <.Ltext2_start>:
-# RELAX64-NEXT: pcaddi $a0, 0
-# RELAX64-NEXT: nop
-# RELAX64-NEXT: nop
-# RELAX64-NEXT: nop
-# RELAX64-NEXT: break 6
-
-
-# ONORELAX-DAG: {{0*}}00001 l *ABS* {{0*}}00 old
-# ONORELAX-DAG: {{0*}}10000 l .text {{0*}}44 .Ltext_start
-# ONORELAX-DAG: {{0*}}10038 l .text {{0*}}0c .L1
-# ONORELAX-DAG: {{0*}}10040 l .text {{0*}}04 .L2
-# ONORELAX-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
-
-# ONORELAX: <.Ltext_start>:
-# ONORELAX-NEXT: break 1
-# ONORELAX-NEXT: break 2
-# ONORELAX-NEXT: nop
-# ONORELAX-NEXT: nop
-# ONORELAX-NEXT: break 3
-# ONORELAX-NEXT: break 4
-# ONORELAX-NEXT: nop
-# ONORELAX-NEXT: nop
-# ONORELAX-NEXT: pcalau12i $a0, 0
-# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# ONORELAX-NEXT: pcalau12i $a0, 0
-# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 56
-# ONORELAX-NEXT: pcalau12i $a0, 0
-# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 64
-# ONORELAX-EMPTY:
-# ONORELAX-NEXT: <.L1>:
-# ONORELAX-NEXT: nop
-# ONORELAX-NEXT: nop
-# ONORELAX-EMPTY:
-# ONORELAX-NEXT: <.L2>:
-# ONORELAX-NEXT: break 5
-
-# ONORELAX: <.Ltext2_start>:
-# ONORELAX-NEXT: pcalau12i $a0, 0
-# ONORELAX-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# ONORELAX-NEXT: nop
-# ONORELAX-NEXT: nop
-# ONORELAX-NEXT: break 6
-
-
-
-
+# NOABSRELAX-DAG: {{0*}}10000 l .text {{0*}}00 .Lalign_symbol
+# ABSRELAX-DAG: {{0*}}00001 l *ABS* {{0*}}00 old
+# 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>:
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index 8784bf57e7ff33..056262026e8d1d 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -5,47 +5,21 @@
# 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 --check-prefix=LA32RELOC
-# RUN: llvm-objdump -dr %t.64 | FileCheck %s --check-prefix=LA64RELOC
+# 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=RELAX
+# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefixes=CHECKR,CHECKR-RELAX
# 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
+# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s --check-prefix=CHECKR
-# LA32RELOC: 00010000 <_start>:
-# LA32RELOC-NEXT: pcalau12i $a0, 0
-# LA32RELOC-NEXT: R_LARCH_PCALA_HI20 _start
-# LA32RELOC-NEXT: R_LARCH_RELAX *ABS*
-# LA32RELOC-NEXT: addi.{{[dw]}} $a0, $a0, 0
-# LA32RELOC-NEXT: R_LARCH_PCALA_LO12 _start
-# LA32RELOC-NEXT: R_LARCH_RELAX *ABS*
-# LA32RELOC-NEXT: nop
-# LA32RELOC-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# LA32RELOC-NEXT: nop
-# LA32RELOC-NEXT: ret
-
-# LA64RELOC: 00010000 <_start>:
-# LA64RELOC-NEXT: pcaddi $a0, 0
-# LA64RELOC-NEXT: R_LARCH_RELAX _start
-# LA64RELOC-NEXT: R_LARCH_RELAX *ABS*
-# LA64RELOC-NEXT: R_LARCH_PCREL20_S2 _start
-# LA64RELOC-NEXT: R_LARCH_RELAX *ABS*
-# LA64RELOC-NEXT: nop
-# LA64RELOC-NEXT: R_LARCH_ALIGN *ABS*+0xc
-# LA64RELOC-NEXT: nop
-# LA64RELOC-NEXT: nop
-# LA64RELOC-NEXT: ret
-
-
-# RELAX: <_start>:
-# RELAX-NEXT: pcalau12i $a0, 0
-# RELAX-NEXT: R_LARCH_PCALA_HI20 _start
+# RELAX: 00010000 <_start>:
+# RELAX-NEXT: pcaddi $a0, 0
+# RELAX-NEXT: R_LARCH_RELAX _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
-# RELAX-NEXT: addi.d $a0, $a0, 0
-# RELAX-NEXT: R_LARCH_PCALA_LO12 _start
+# RELAX-NEXT: R_LARCH_PCREL20_S2 _start
# RELAX-NEXT: R_LARCH_RELAX *ABS*
# RELAX-NEXT: nop
# RELAX-NEXT: R_LARCH_ALIGN *ABS*+0xc
@@ -53,17 +27,19 @@
# 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
+# CHECKR-NEXT: R_LARCH_PCALA_HI20 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: addi.d $a0, $a0, 0
+# CHECKR-NEXT: R_LARCH_PCALA_LO12 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: R_LARCH_ALIGN *ABS*+0xc
+# CHECKR-NEXT: nop
+# CHECKR-RELAX-NEXT: nop
+# CHECKR-NEXT: ret
.global _start
_start:
>From c40c9310c120893e491e169a19f094aed2085a0f Mon Sep 17 00:00:00 2001
From: Xin Wang <wangxin03 at loongson.cn>
Date: Mon, 18 Nov 2024 10:47:25 +0800
Subject: [PATCH 6/7] [lld][LoongArch] Replace macros which operate insns and
registers with functions
---
lld/ELF/Arch/LoongArch.cpp | 35 ++++++++++++++++-------------------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index d854c29f56a0ad..6d33f90dd8000c 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -22,19 +22,6 @@ using namespace lld;
using namespace lld::elf;
namespace {
-#define LARCH_GET_RD(insn) (insn & 0x1f)
-#define LARCH_GET_RJ(insn) (insn >> 5 & 0x1f)
-#define LARCH_MK_ADDI_W 0xffc00000
-#define LARCH_OP_ADDI_W 0x02800000
-#define LARCH_MK_ADDI_D 0xffc00000
-#define LARCH_OP_ADDI_D 0x02c00000
-#define LARCH_MK_PCADDI 0xfe000000
-#define LARCH_OP_PCADDI 0x18000000
-#define LARCH_INSN_OPS(insn, op) ((insn & LARCH_MK_##op) == LARCH_OP_##op)
-#define LARCH_INSN_ADDI_W(insn) LARCH_INSN_OPS((insn), ADDI_W)
-#define LARCH_INSN_ADDI_D(insn) LARCH_INSN_OPS((insn), ADDI_D)
-#define LARCH_INSN_PCADDI(insn) LARCH_INSN_OPS((insn), PCADDI)
-
class LoongArch final : public TargetInfo {
public:
LoongArch(Ctx &);
@@ -67,6 +54,7 @@ enum Op {
ADDI_D = 0x02c00000,
ANDI = 0x03400000,
PCADDU12I = 0x1c000000,
+ PCADDI = 0x18000000,
LD_W = 0x28800000,
LD_D = 0x28c00000,
JIRL = 0x4c000000,
@@ -76,7 +64,6 @@ enum Reg {
R_ZERO = 0,
R_RA = 1,
R_TP = 2,
- R_A0 = 4,
R_T0 = 12,
R_T1 = 13,
R_T2 = 14,
@@ -173,6 +160,17 @@ static bool isJirl(uint32_t insn) {
return (insn & 0xfc000000) == JIRL;
}
+static bool isAddi_w(uint32_t insn) { return (insn & 0xffc00000) == ADDI_W; }
+
+static bool isAddi_d(uint32_t insn) { return (insn & 0xffc00000) == ADDI_D; }
+
+// LoongArch instructions could be divided into a number of kinds based on
+// the width of imm and the number of registers. get_rd/get_rj only applies
+// to those kinds of instructions that could do relocation.
+static uint8_t get_rd(uint32_t insn) { return insn & 0x1f; }
+
+static uint8_t get_rj(uint32_t insn) { return insn >> 5 & 0x1f; }
+
static void handleUleb128(Ctx &ctx, uint8_t *loc, uint64_t val) {
const uint32_t maxcount = 1 + 64 / 7;
uint32_t count;
@@ -805,17 +803,16 @@ static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
const int64_t dist = symval - loc;
uint32_t pca = read32le(sec.content().data() + r_hi.offset);
uint32_t add = read32le(sec.content().data() + r_hi.offset + 4);
- uint32_t rd = LARCH_GET_RD(pca);
+ uint8_t rd = get_rd(pca);
- if ((!LARCH_INSN_ADDI_W(add) && !LARCH_INSN_ADDI_D(add)) ||
- LARCH_GET_RJ(add) != rd || symval & 0x3 /* 4 bytes align */ ||
- !isInt<22>(dist))
+ if ((!isAddi_w(add) && !isAddi_d(add)) || get_rj(add) != rd ||
+ symval & 0x3 /* not 4 bytes align */ || !isInt<22>(dist))
return;
// remove the first insn
sec.relaxAux->relocTypes[i] = R_LARCH_RELAX;
sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
- sec.relaxAux->writes.push_back(LARCH_OP_PCADDI | rd); // pcaddi
+ sec.relaxAux->writes.push_back(PCADDI | rd); // pcaddi rd, 0
remove = 4;
}
>From 3f7cf3367ae2bbd6711cba1d70cd2dd64c20c315 Mon Sep 17 00:00:00 2001
From: Xin Wang <wangxin03 at loongson.cn>
Date: Tue, 19 Nov 2024 10:22:04 +0800
Subject: [PATCH 7/7] [lld][LoongArch] Adjust RelExpr after relaxation is
applied
---
lld/ELF/Arch/LoongArch.cpp | 4 +++-
lld/ELF/InputSection.cpp | 11 -----------
2 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 6d33f90dd8000c..46a06803fafb34 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -945,7 +945,7 @@ 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;
@@ -959,6 +959,8 @@ void LoongArch::finalizeRelax(int passes) const {
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");
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 1d5f53dfecb8ab..2e9e8a7007bbf8 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -737,17 +737,6 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
int64_t a = r.addend;
switch (r.expr) {
case R_ABS:
- // pcalau12i,addi.[wd] => pcaddi
- // With relaxation applied, the relocation type of the third
- // reloc entry which corresponds to the addi.[wd] insn is converted
- // from R_LARCH_PCALA_LO12 to R_LARCH_PCREL20_S2.
- if (r.type == R_LARCH_PCREL20_S2) {
- if (r.sym->hasFlag(NEEDS_PLT))
- return r.sym->getPltVA(ctx) + a - p;
- else
- return r.sym->getVA(a) - p;
- }
- [[fallthrough]];
case R_DTPREL:
case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
More information about the llvm-commits
mailing list