Backport some upstream patches
From Fedora MR: https://src.fedoraproject.org/rpms/llvm/pull-request/620 Resolves: RHEL-210751 Related: RHEL-211002
This commit is contained in:
parent
f16b24b7a9
commit
d442823b06
47
0001-ELF-Simplify-AArch64-relocateAlloc.-NFC.patch
Normal file
47
0001-ELF-Simplify-AArch64-relocateAlloc.-NFC.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From e710ff28456c1accbeb3a7e503163233bc615b16 Mon Sep 17 00:00:00 2001
|
||||
From: Fangrui Song <i@maskray.me>
|
||||
Date: Wed, 11 Feb 2026 21:23:34 -0800
|
||||
Subject: [PATCH] [ELF] Simplify AArch64::relocateAlloc. NFC
|
||||
|
||||
---
|
||||
lld/ELF/Arch/AArch64.cpp | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
|
||||
index 55434ae2151c..3c0d4ca64555 100644
|
||||
--- a/lld/ELF/Arch/AArch64.cpp
|
||||
+++ b/lld/ELF/Arch/AArch64.cpp
|
||||
@@ -931,9 +931,10 @@ static bool needsGotForMemtag(const Relocation &rel) {
|
||||
|
||||
void AArch64::relocateAlloc(InputSection &sec, uint8_t *buf) const {
|
||||
uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff;
|
||||
- AArch64Relaxer relaxer(ctx, sec.relocs());
|
||||
- for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) {
|
||||
- const Relocation &rel = sec.relocs()[i];
|
||||
+ const ArrayRef<Relocation> relocs = sec.relocs();
|
||||
+ AArch64Relaxer relaxer(ctx, relocs);
|
||||
+ for (size_t i = 0, size = relocs.size(); i != size; ++i) {
|
||||
+ const Relocation &rel = relocs[i];
|
||||
if (rel.expr == R_NONE) // See finalizeAddressDependentContent()
|
||||
continue;
|
||||
uint8_t *loc = buf + rel.offset;
|
||||
@@ -947,14 +948,14 @@ void AArch64::relocateAlloc(InputSection &sec, uint8_t *buf) const {
|
||||
switch (rel.expr) {
|
||||
case RE_AARCH64_GOT_PAGE_PC:
|
||||
if (i + 1 < size &&
|
||||
- relaxer.tryRelaxAdrpLdr(rel, sec.relocs()[i + 1], secAddr, buf)) {
|
||||
+ relaxer.tryRelaxAdrpLdr(rel, relocs[i + 1], secAddr, buf)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case RE_AARCH64_PAGE_PC:
|
||||
if (i + 1 < size &&
|
||||
- relaxer.tryRelaxAdrpAdd(rel, sec.relocs()[i + 1], secAddr, buf)) {
|
||||
+ relaxer.tryRelaxAdrpAdd(rel, relocs[i + 1], secAddr, buf)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
--
|
||||
2.50.1
|
||||
|
||||
416
0001-LLD-AArch64-Make-adrp-ldr-relaxation-per-symbol-all-.patch
Normal file
416
0001-LLD-AArch64-Make-adrp-ldr-relaxation-per-symbol-all-.patch
Normal file
@ -0,0 +1,416 @@
|
||||
From 8d590969badd9f3fed18a99fffbd9afdf3a975c6 Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Popov <npopov@redhat.com>
|
||||
Date: Fri, 10 Jul 2026 09:09:08 +0200
|
||||
Subject: [PATCH] [LLD][AArch64] Make adrp+ldr relaxation per-symbol
|
||||
all-or-nothing (#208396)
|
||||
|
||||
We can't relax only some adrp+ldr pairs for a symbol, because there may
|
||||
be a branch target between the adrp and ldr of this form:
|
||||
|
||||
adrp x1, :got:sym
|
||||
.Lfoo:
|
||||
ldr x1, [x1, :got_lo12:sym]
|
||||
# ...
|
||||
|
||||
adrp x1, :got:sym
|
||||
ldr x2, [x1, :got_lo12:sym]
|
||||
b .Lfoo
|
||||
|
||||
Relaxing the first adrp+ldr here would be invalid. This was clarified in
|
||||
the ARM ABI in:
|
||||
https://github.com/ARM-software/abi-aa/commit/11fb4ef42898060189d6a34ee96966e696ecbd20.
|
||||
|
||||
The implementation already performed a pre-scan to check that the
|
||||
relevant relocations occur in pairs. Change this scan to a) check all
|
||||
the preconditions for the relaxation and b) make the decision per
|
||||
symbol.
|
||||
|
||||
Fixes https://github.com/llvm/llvm-project/issues/138254.
|
||||
---
|
||||
bolt/test/AArch64/got-load-symbolization.s | 11 ++-
|
||||
bolt/test/AArch64/lite-mode.s | 17 +++--
|
||||
lld/ELF/Arch/AArch64.cpp | 83 +++++++++++++--------
|
||||
lld/test/ELF/aarch64-adrp-ldr-got.s | 84 +++++++++++++++++++---
|
||||
4 files changed, 149 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/bolt/test/AArch64/got-load-symbolization.s b/bolt/test/AArch64/got-load-symbolization.s
|
||||
index b4d682688758..399859fd7bfd 100644
|
||||
--- a/bolt/test/AArch64/got-load-symbolization.s
|
||||
+++ b/bolt/test/AArch64/got-load-symbolization.s
|
||||
@@ -38,9 +38,9 @@ _start:
|
||||
# CHECK-NEXT: adrp x2, __BOLT_got_zero
|
||||
# CHECK-NEXT: nop
|
||||
# CHECK-NEXT: ldr x2, [x2, :lo12:__BOLT_got_zero{{.*}}]
|
||||
- adrp x2, :got:near
|
||||
+ adrp x2, :got:near2
|
||||
nop
|
||||
- ldr x2, [x2, :got_lo12:near]
|
||||
+ ldr x2, [x2, :got_lo12:near2]
|
||||
|
||||
## Load data object with local visibility. Relaxable into adrp+add.
|
||||
# CHECK-NEXT: adrp x3, "local_far_data/1"
|
||||
@@ -58,6 +58,7 @@ _start:
|
||||
.size _start, .-_start
|
||||
|
||||
.weak near
|
||||
+.weak near2
|
||||
.weak far
|
||||
.weak far_data
|
||||
|
||||
@@ -77,6 +78,12 @@ near:
|
||||
ret
|
||||
.size near, .-near
|
||||
|
||||
+ .globl near2
|
||||
+ .type near2, @function
|
||||
+near2:
|
||||
+ ret
|
||||
+.size near2, .-near2
|
||||
+
|
||||
#--- far.s
|
||||
|
||||
.text
|
||||
diff --git a/bolt/test/AArch64/lite-mode.s b/bolt/test/AArch64/lite-mode.s
|
||||
index f2d06219f7a2..24c31772b847 100644
|
||||
--- a/bolt/test/AArch64/lite-mode.s
|
||||
+++ b/bolt/test/AArch64/lite-mode.s
|
||||
@@ -24,12 +24,12 @@
|
||||
# CHECK-COMPACT-NOT: <_start.org.0>
|
||||
|
||||
## Verify that the number of FDEs matches the number of functions in the output
|
||||
-## binary. There are three original functions and two optimized.
|
||||
+## binary. There are four original functions and three optimized.
|
||||
## NOTE: at the moment we are emitting extra FDEs for patched functions, thus
|
||||
## there is one more FDE for _start.
|
||||
# RUN: llvm-readelf -u %t.bolt | grep -wc FDE \
|
||||
# RUN: | FileCheck --check-prefix=CHECK-FDE %s
|
||||
-# CHECK-FDE: 6
|
||||
+# CHECK-FDE: 8
|
||||
|
||||
## In lite mode, optimized code will be separated from the original .text by
|
||||
## over 128MB, making it impossible for call/bl instructions in cold functions
|
||||
@@ -106,9 +106,9 @@ cold_function:
|
||||
# CHECK-NEXT: add x4
|
||||
|
||||
## Check that non-relaxable GOT load is left intact.
|
||||
- adrp x5, :got:far_func
|
||||
+ adrp x5, :got:far_func2
|
||||
nop
|
||||
- ldr x5, [x5, #:got_lo12:far_func]
|
||||
+ ldr x5, [x5, #:got_lo12:far_func2]
|
||||
# CHECK-INPUT-NEXT: adrp x5
|
||||
# CHECK-INPUT-NEXT: nop
|
||||
# CHECK-INPUT-NEXT: ldr x5
|
||||
@@ -155,3 +155,12 @@ far_func:
|
||||
ret x30
|
||||
.cfi_endproc
|
||||
.size far_func, .-far_func
|
||||
+
|
||||
+ .globl far_func2
|
||||
+ .type far_func2, %function
|
||||
+far_func2:
|
||||
+# FDATA: 0 [unknown] 0 1 far_func2 0 0 100
|
||||
+ .cfi_startproc
|
||||
+ ret x30
|
||||
+ .cfi_endproc
|
||||
+ .size far_func2, .-far_func2
|
||||
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
|
||||
index ed6d42fd4c05..11c3dca1a358 100644
|
||||
--- a/lld/ELF/Arch/AArch64.cpp
|
||||
+++ b/lld/ELF/Arch/AArch64.cpp
|
||||
@@ -106,13 +106,17 @@ private:
|
||||
|
||||
struct AArch64Relaxer {
|
||||
Ctx &ctx;
|
||||
- bool safeToRelaxAdrpLdr = false;
|
||||
+ SmallPtrSet<Symbol *, 32> unsafeToRelaxAdrpLdr;
|
||||
|
||||
- AArch64Relaxer(Ctx &ctx, ArrayRef<Relocation> relocs);
|
||||
+ AArch64Relaxer(Ctx &ctx, ArrayRef<Relocation> relocs, uint64_t secAddr,
|
||||
+ uint8_t *buf);
|
||||
bool tryRelaxAdrpAdd(const Relocation &adrpRel, const Relocation &addRel,
|
||||
uint64_t secAddr, uint8_t *buf) const;
|
||||
bool tryRelaxAdrpLdr(const Relocation &adrpRel, const Relocation &ldrRel,
|
||||
uint64_t secAddr, uint8_t *buf) const;
|
||||
+ bool isLegalAdrpLdrRelaxationCandidate(const Relocation &adrpRel,
|
||||
+ const Relocation &ldrRel,
|
||||
+ uint64_t secAddr, uint8_t *buf) const;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -896,26 +900,30 @@ void AArch64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
|
||||
llvm_unreachable("invalid relocation for TLS IE to LE relaxation");
|
||||
}
|
||||
|
||||
-AArch64Relaxer::AArch64Relaxer(Ctx &ctx, ArrayRef<Relocation> relocs)
|
||||
+AArch64Relaxer::AArch64Relaxer(Ctx &ctx, ArrayRef<Relocation> relocs,
|
||||
+ uint64_t secAddr, uint8_t *buf)
|
||||
: ctx(ctx) {
|
||||
if (!ctx.arg.relax)
|
||||
return;
|
||||
- // Check if R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC
|
||||
- // always appear in pairs.
|
||||
+ // For a given symbol R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC
|
||||
+ // relaxation is all-or-nothing. We can't relax only some of them, as there
|
||||
+ // may be a jump destination between the two relocations.
|
||||
size_t i = 0;
|
||||
const size_t size = relocs.size();
|
||||
for (; i != size; ++i) {
|
||||
if (relocs[i].type == R_AARCH64_ADR_GOT_PAGE) {
|
||||
- if (i + 1 < size && relocs[i + 1].type == R_AARCH64_LD64_GOT_LO12_NC) {
|
||||
+ if (i + 1 < size && relocs[i + 1].type == R_AARCH64_LD64_GOT_LO12_NC &&
|
||||
+ !unsafeToRelaxAdrpLdr.contains(relocs[i].sym) &&
|
||||
+ isLegalAdrpLdrRelaxationCandidate(relocs[i], relocs[i + 1], secAddr,
|
||||
+ buf)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
- break;
|
||||
+ unsafeToRelaxAdrpLdr.insert(relocs[i].sym);
|
||||
} else if (relocs[i].type == R_AARCH64_LD64_GOT_LO12_NC) {
|
||||
- break;
|
||||
+ unsafeToRelaxAdrpLdr.insert(relocs[i].sym);
|
||||
}
|
||||
}
|
||||
- safeToRelaxAdrpLdr = i == size;
|
||||
}
|
||||
|
||||
bool AArch64Relaxer::tryRelaxAdrpAdd(const Relocation &adrpRel,
|
||||
@@ -966,23 +974,9 @@ bool AArch64Relaxer::tryRelaxAdrpAdd(const Relocation &adrpRel,
|
||||
return true;
|
||||
}
|
||||
|
||||
-bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel,
|
||||
- const Relocation &ldrRel, uint64_t secAddr,
|
||||
- uint8_t *buf) const {
|
||||
- if (!safeToRelaxAdrpLdr)
|
||||
- return false;
|
||||
-
|
||||
- // When the definition of sym is not preemptible then we may
|
||||
- // be able to relax
|
||||
- // ADRP xn, :got: sym
|
||||
- // LDR xn, [ xn :got_lo12: sym]
|
||||
- // to
|
||||
- // ADRP xn, sym
|
||||
- // ADD xn, xn, :lo_12: sym
|
||||
-
|
||||
- if (adrpRel.type != R_AARCH64_ADR_GOT_PAGE ||
|
||||
- ldrRel.type != R_AARCH64_LD64_GOT_LO12_NC)
|
||||
- return false;
|
||||
+bool AArch64Relaxer::isLegalAdrpLdrRelaxationCandidate(
|
||||
+ const Relocation &adrpRel, const Relocation &ldrRel, uint64_t secAddr,
|
||||
+ uint8_t *buf) const {
|
||||
// Check if the relocations apply to consecutive instructions.
|
||||
if (adrpRel.offset + 4 != ldrRel.offset)
|
||||
return false;
|
||||
@@ -1022,10 +1016,37 @@ bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel,
|
||||
if (val != llvm::SignExtend64(val, 33))
|
||||
return false;
|
||||
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel,
|
||||
+ const Relocation &ldrRel, uint64_t secAddr,
|
||||
+ uint8_t *buf) const {
|
||||
+ // When the definition of sym is not preemptible then we may
|
||||
+ // be able to relax
|
||||
+ // ADRP xn, :got: sym
|
||||
+ // LDR xn, [ xn :got_lo12: sym]
|
||||
+ // to
|
||||
+ // ADRP xn, sym
|
||||
+ // ADD xn, xn, :lo_12: sym
|
||||
+
|
||||
+ if (!ctx.arg.relax || adrpRel.type != R_AARCH64_ADR_GOT_PAGE ||
|
||||
+ ldrRel.type != R_AARCH64_LD64_GOT_LO12_NC)
|
||||
+ return false;
|
||||
+
|
||||
+ Symbol *sym = adrpRel.sym;
|
||||
+ if (unsafeToRelaxAdrpLdr.contains(sym))
|
||||
+ return false;
|
||||
+
|
||||
+ assert(isLegalAdrpLdrRelaxationCandidate(adrpRel, ldrRel, secAddr, buf) &&
|
||||
+ "Should have been marked as unsafe");
|
||||
+
|
||||
+ uint32_t adrpInstr = read32le(buf + adrpRel.offset);
|
||||
+ uint32_t adrpDestReg = adrpInstr & 0x1f;
|
||||
Relocation adrpSymRel = {RE_AARCH64_PAGE_PC, R_AARCH64_ADR_PREL_PG_HI21,
|
||||
- adrpRel.offset, /*addend=*/0, &sym};
|
||||
+ adrpRel.offset, /*addend=*/0, sym};
|
||||
Relocation addRel = {R_ABS, R_AARCH64_ADD_ABS_LO12_NC, ldrRel.offset,
|
||||
- /*addend=*/0, &sym};
|
||||
+ /*addend=*/0, sym};
|
||||
|
||||
// adrp x_<dest_reg>
|
||||
write32le(buf + adrpSymRel.offset, 0x90000000 | adrpDestReg);
|
||||
@@ -1034,11 +1055,11 @@ bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel,
|
||||
|
||||
ctx.target->relocate(
|
||||
buf + adrpSymRel.offset, adrpSymRel,
|
||||
- SignExtend64(getAArch64Page(sym.getVA(ctx)) -
|
||||
+ SignExtend64(getAArch64Page(sym->getVA(ctx)) -
|
||||
getAArch64Page(secAddr + adrpSymRel.offset),
|
||||
64));
|
||||
ctx.target->relocate(buf + addRel.offset, addRel,
|
||||
- SignExtend64(sym.getVA(ctx), 64));
|
||||
+ SignExtend64(sym->getVA(ctx), 64));
|
||||
tryRelaxAdrpAdd(adrpSymRel, addRel, secAddr, buf);
|
||||
return true;
|
||||
}
|
||||
@@ -1052,7 +1073,7 @@ static bool needsGotForMemtag(const Relocation &rel) {
|
||||
void AArch64::relocateAlloc(InputSection &sec, uint8_t *buf) const {
|
||||
uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff;
|
||||
const ArrayRef<Relocation> relocs = sec.relocs();
|
||||
- AArch64Relaxer relaxer(ctx, relocs);
|
||||
+ AArch64Relaxer relaxer(ctx, relocs, secAddr, buf);
|
||||
for (size_t i = 0, size = relocs.size(); i != size; ++i) {
|
||||
const Relocation &rel = relocs[i];
|
||||
if (rel.expr == R_NONE) // See finalizeAddressDependentContent()
|
||||
diff --git a/lld/test/ELF/aarch64-adrp-ldr-got.s b/lld/test/ELF/aarch64-adrp-ldr-got.s
|
||||
index 56a90aac3876..a8216da9f20c 100644
|
||||
--- a/lld/test/ELF/aarch64-adrp-ldr-got.s
|
||||
+++ b/lld/test/ELF/aarch64-adrp-ldr-got.s
|
||||
@@ -4,6 +4,7 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/a.s -o %t/a.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/unpaired.s -o %t/unpaired.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/lone-ldr.s -o %t/lone-ldr.o
|
||||
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/all-or-nothing.s -o %t/all-or-nothing.o
|
||||
|
||||
# RUN: ld.lld %t/a.o -T %t/out-of-adr-range.t -o %t/a
|
||||
# RUN: llvm-objdump --no-show-raw-insn -d %t/a | FileCheck %s
|
||||
@@ -49,7 +50,8 @@
|
||||
# RUN: llvm-objdump --no-show-raw-insn -d %t/out-of-range | \
|
||||
# RUN: FileCheck --check-prefix=X1-NO-RELAX %s
|
||||
|
||||
-## Relocations do not appear in pairs, no relaxations should be applied.
|
||||
+## Relocations do not appear in pairs, no relaxations should be applied for
|
||||
+## that symbol. We can still relax other symbols.
|
||||
# RUN: ld.lld %t/unpaired.o -o %t/unpaired
|
||||
# RUN: llvm-objdump --no-show-raw-insn -d %t/unpaired | \
|
||||
# RUN: FileCheck --check-prefix=UNPAIRED %s
|
||||
@@ -58,6 +60,9 @@
|
||||
# UNPAIRED-NEXT: b
|
||||
# UNPAIRED-NEXT: adrp x0
|
||||
# UNPAIRED: ldr x0
|
||||
+## This is a different symbol.
|
||||
+# UNPAIRED: nop
|
||||
+# UNPAIRED: adr x1
|
||||
|
||||
## Relocations do not appear in pairs, no relaxations should be applied.
|
||||
# RUN: ld.lld %t/lone-ldr.o -o %t/lone-ldr
|
||||
@@ -66,6 +71,26 @@
|
||||
|
||||
# LONE-LDR: ldr x0
|
||||
|
||||
+## Make sure that relaxation is not applied if not all adrp+ldr pairs for
|
||||
+## a given symbol can be relaxed. This is not legal, because there may be
|
||||
+## a branch destination between the adrp and ldr instructions. We can still
|
||||
+## perform the relaxation for other symbols, or the same symbol in a different
|
||||
+## section.
|
||||
+# RUN: ld.lld %t/all-or-nothing.o -o %t/all-or-nothing
|
||||
+# RUN: llvm-objdump --no-show-raw-insn -d %t/all-or-nothing | \
|
||||
+# RUN: FileCheck --check-prefix=ALL-OR-NOTHING %s
|
||||
+
|
||||
+# ALL-OR-NOTHING-LABEL: <_start>:
|
||||
+# ALL-OR-NOTHING: adrp x1
|
||||
+# ALL-OR-NOTHING: ldr x1
|
||||
+# ALL-OR-NOTHING: adrp x1
|
||||
+# ALL-OR-NOTHING: ldr x2
|
||||
+# ALL-OR-NOTHING: nop
|
||||
+# ALL-OR-NOTHING: adr x1
|
||||
+# ALL-OR-NOTHING-LABEL: <foo>:
|
||||
+# ALL-OR-NOTHING: nop
|
||||
+# ALL-OR-NOTHING: adr x1
|
||||
+
|
||||
## This linker script ensures that .rodata and .text are sufficiently (>1M)
|
||||
## far apart so that the adrp + ldr pair cannot be relaxed to adr + nop.
|
||||
#--- out-of-adr-range.t
|
||||
@@ -95,25 +120,40 @@ SECTIONS {
|
||||
.hidden x
|
||||
x:
|
||||
.word 10
|
||||
+.hidden y
|
||||
+y:
|
||||
+.word 10
|
||||
+.hidden z
|
||||
+z:
|
||||
+.word 10
|
||||
+.hidden u
|
||||
+u:
|
||||
+.word 10
|
||||
+.hidden v
|
||||
+v:
|
||||
+.word 10
|
||||
.text
|
||||
.global _start
|
||||
_start:
|
||||
adrp x1, :got:x
|
||||
ldr x1, [x1, #:got_lo12:x]
|
||||
- adrp x2, :got:x+1
|
||||
- ldr x2, [x2, #:got_lo12:x]
|
||||
- adrp x3, :got:x
|
||||
- ldr x3, [x3, #:got_lo12:x+8]
|
||||
- adrp x4, :got:x
|
||||
- ldr x5, [x4, #:got_lo12:x]
|
||||
- adrp x6, :got:x
|
||||
- ldr x6, [x0, #:got_lo12:x]
|
||||
+ adrp x2, :got:y+1
|
||||
+ ldr x2, [x2, #:got_lo12:y]
|
||||
+ adrp x3, :got:z
|
||||
+ ldr x3, [x3, #:got_lo12:z+8]
|
||||
+ adrp x4, :got:u
|
||||
+ ldr x5, [x4, #:got_lo12:u]
|
||||
+ adrp x6, :got:v
|
||||
+ ldr x6, [x0, #:got_lo12:v]
|
||||
|
||||
#--- unpaired.s
|
||||
.text
|
||||
.hidden x
|
||||
x:
|
||||
nop
|
||||
+.hidden y
|
||||
+y:
|
||||
+ nop
|
||||
.global _start
|
||||
_start:
|
||||
adrp x0, :got:x
|
||||
@@ -121,6 +161,8 @@ _start:
|
||||
adrp x0, :got:x
|
||||
L:
|
||||
ldr x0, [x0, #:got_lo12:x]
|
||||
+ adrp x1, :got:y
|
||||
+ ldr x1, [x1, #:got_lo12:y]
|
||||
|
||||
#--- lone-ldr.s
|
||||
.text
|
||||
@@ -130,3 +172,27 @@ x:
|
||||
.global _start
|
||||
_start:
|
||||
ldr x0, [x0, #:got_lo12:x]
|
||||
+
|
||||
+#--- all-or-nothing.s
|
||||
+.rodata
|
||||
+.hidden x
|
||||
+x:
|
||||
+.word 10
|
||||
+.hidden y
|
||||
+y:
|
||||
+.word 10
|
||||
+.text
|
||||
+.global _start
|
||||
+_start:
|
||||
+ adrp x1, :got:x
|
||||
+ ldr x1, [x1, #:got_lo12:x]
|
||||
+ adrp x1, :got:x
|
||||
+ ldr x2, [x1, #:got_lo12:x]
|
||||
+ adrp x1, :got:y
|
||||
+ ldr x1, [x1, #:got_lo12:y]
|
||||
+
|
||||
+.section .text.foo
|
||||
+.global foo
|
||||
+foo:
|
||||
+ adrp x1, :got:x
|
||||
+ ldr x1, [x1, #:got_lo12:x]
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
From 7bb9626d5ab901e5c1a8e9acbbb1684c982401b4 Mon Sep 17 00:00:00 2001
|
||||
From: Tulio Magno Quites Machado Filho <tuliom@redhat.com>
|
||||
Date: Fri, 10 Jul 2026 15:45:02 -0300
|
||||
Subject: [PATCH] [LLVM][Verifier] Fix buffer overflow when verifying
|
||||
gc.statepoint (#208278)
|
||||
|
||||
When a negative base index is passed, the verification detects the
|
||||
out-of-bounds value and start printing information that helps to
|
||||
identify what caused the error. In order to print all the information,
|
||||
it tries to dereference the Base pointer at
|
||||
GCRelocateInst::getBasePtr(), causing the buffer overflow. Add a bounds
|
||||
check to getBasePTR() and getDerivedPtr() in order to avoid this.
|
||||
|
||||
Improve the test in order to validate negative values passed as indexes.
|
||||
They're based on the reproducer from issue #199191.
|
||||
|
||||
Fixes #199191
|
||||
---
|
||||
llvm/lib/IR/AsmWriter.cpp | 10 ++++++++--
|
||||
llvm/lib/IR/IntrinsicInst.cpp | 19 ++++++++++++++++---
|
||||
3 files changed, 40 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
|
||||
index e90630a8cae5..6752d6aa344d 100644
|
||||
--- a/llvm/lib/IR/AsmWriter.cpp
|
||||
+++ b/llvm/lib/IR/AsmWriter.cpp
|
||||
@@ -4372,9 +4372,15 @@ void AssemblyWriter::printInstructionLine(const Instruction &I) {
|
||||
/// intrinsic indicating base and derived pointer names.
|
||||
void AssemblyWriter::printGCRelocateComment(const GCRelocateInst &Relocate) {
|
||||
Out << " ; (";
|
||||
- writeOperand(Relocate.getBasePtr(), false);
|
||||
+ if (Value *BasePtr = Relocate.getBasePtr())
|
||||
+ writeOperand(BasePtr, false);
|
||||
+ else
|
||||
+ Out << "invalid";
|
||||
Out << ", ";
|
||||
- writeOperand(Relocate.getDerivedPtr(), false);
|
||||
+ if (Value *DerivedPtr = Relocate.getDerivedPtr())
|
||||
+ writeOperand(DerivedPtr, false);
|
||||
+ else
|
||||
+ Out << "invalid";
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp
|
||||
index 3e9f3257956a..eb964d566f29 100644
|
||||
--- a/llvm/lib/IR/IntrinsicInst.cpp
|
||||
+++ b/llvm/lib/IR/IntrinsicInst.cpp
|
||||
@@ -867,10 +867,16 @@ Value *GCRelocateInst::getBasePtr() const {
|
||||
auto Statepoint = getStatepoint();
|
||||
if (isa<UndefValue>(Statepoint))
|
||||
return UndefValue::get(Statepoint->getType());
|
||||
-
|
||||
+ // Handle too few (bundle) arguments to avoid crashes when printing invalid
|
||||
+ // IR, e.g. in the verifier.
|
||||
auto *GCInst = cast<GCStatepointInst>(Statepoint);
|
||||
- if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
|
||||
+ if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) {
|
||||
+ if (getBasePtrIndex() > Opt->Inputs.size())
|
||||
+ return nullptr;
|
||||
return *(Opt->Inputs.begin() + getBasePtrIndex());
|
||||
+ }
|
||||
+ if (getBasePtrIndex() > GCInst->arg_size())
|
||||
+ return nullptr;
|
||||
return *(GCInst->arg_begin() + getBasePtrIndex());
|
||||
}
|
||||
|
||||
@@ -879,9 +885,16 @@ Value *GCRelocateInst::getDerivedPtr() const {
|
||||
if (isa<UndefValue>(Statepoint))
|
||||
return UndefValue::get(Statepoint->getType());
|
||||
|
||||
+ // Handle too few (bundle) arguments to avoid crashes when printing invalid
|
||||
+ // IR, e.g. in the verifier.
|
||||
auto *GCInst = cast<GCStatepointInst>(Statepoint);
|
||||
- if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live))
|
||||
+ if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) {
|
||||
+ if (getDerivedPtrIndex() > Opt->Inputs.size())
|
||||
+ return nullptr;
|
||||
return *(Opt->Inputs.begin() + getDerivedPtrIndex());
|
||||
+ }
|
||||
+ if (getDerivedPtrIndex() > GCInst->arg_size())
|
||||
+ return nullptr;
|
||||
return *(GCInst->arg_begin() + getDerivedPtrIndex());
|
||||
}
|
||||
|
||||
--
|
||||
2.50.1
|
||||
|
||||
3977
0001-SDAG-Freeze-condition-in-select-of-load-fold-208683.patch
Normal file
3977
0001-SDAG-Freeze-condition-in-select-of-load-fold-208683.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,81 @@
|
||||
From a04c1eced55f2f3ea8dbd3d17db0b6df271c0809 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Weigl-Bosker <stefan@s00.xyz>
|
||||
Date: Mon, 18 May 2026 10:47:14 -0400
|
||||
Subject: [PATCH] [X86] Fix EVEX compression for VPMOV*2M + KMOV with tied mask
|
||||
use (#198220)
|
||||
|
||||
When scanning uses of the mask produced by `VPMOV*2M`, we previously bailed out as soon as we encountered a write. For tied read/write mask instructions such as `KSHIFTR*`, which both read and write the same mask register, the pass could miss the use, fold the earlier `KMOV`, and erase the `VPMOV*2M` def even though the mask was still live.
|
||||
|
||||
Disclaimer: LLM came up with the MIR tests and explained this pass to me.
|
||||
|
||||
Fixes #198197
|
||||
|
||||
(cherry picked from commit f0fc9d0abf7024ceb5cb827b16f02c10e54fe0fd)
|
||||
---
|
||||
llvm/lib/Target/X86/X86CompressEVEX.cpp | 12 ++++++------
|
||||
llvm/test/CodeGen/X86/evex-to-vex-compress.mir | 12 ++++++++++++
|
||||
2 files changed, 18 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/llvm/lib/Target/X86/X86CompressEVEX.cpp b/llvm/lib/Target/X86/X86CompressEVEX.cpp
|
||||
index c1faf7d1aa1e..b8fbcd2582de 100644
|
||||
--- a/llvm/lib/Target/X86/X86CompressEVEX.cpp
|
||||
+++ b/llvm/lib/Target/X86/X86CompressEVEX.cpp
|
||||
@@ -271,12 +271,6 @@ static bool tryCompressVPMOVPattern(MachineInstr &MI, MachineBasicBlock &MBB,
|
||||
|
||||
for (MachineInstr &CurMI : llvm::make_range(
|
||||
std::next(MachineBasicBlock::iterator(MI)), MBB.end())) {
|
||||
- if (CurMI.modifiesRegister(MaskReg, TRI)) {
|
||||
- if (!KMovMI)
|
||||
- return false; // Mask clobbered before use
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
if (CurMI.readsRegister(MaskReg, TRI)) {
|
||||
if (KMovMI)
|
||||
return false; // Fail: Mask has MULTIPLE uses
|
||||
@@ -295,6 +289,12 @@ static bool tryCompressVPMOVPattern(MachineInstr &MI, MachineBasicBlock &MBB,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (CurMI.modifiesRegister(MaskReg, TRI)) {
|
||||
+ if (!KMovMI)
|
||||
+ return false; // Mask clobbered before use
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (!KMovMI && CurMI.modifiesRegister(SrcVecReg, TRI)) {
|
||||
return false; // SrcVecReg modified before it could be used by MOVMSK
|
||||
}
|
||||
diff --git a/llvm/test/CodeGen/X86/evex-to-vex-compress.mir b/llvm/test/CodeGen/X86/evex-to-vex-compress.mir
|
||||
index b33a1d571c81..575f0c7d6a4f 100644
|
||||
--- a/llvm/test/CodeGen/X86/evex-to-vex-compress.mir
|
||||
+++ b/llvm/test/CodeGen/X86/evex-to-vex-compress.mir
|
||||
@@ -914,6 +914,12 @@ body: |
|
||||
$k0 = VPMOVD2MZ256kr $ymm0
|
||||
$eax = KMOVBrk $k0
|
||||
$ebx = KMOVBrk $k0
|
||||
+ ; CHECK: $k0 = VPMOVD2MZ256kr $ymm0
|
||||
+ ; CHECK: $eax = KMOVBrk $k0
|
||||
+ ; CHECK: $k0 = KSHIFTRBki $k0, 2
|
||||
+ $k0 = VPMOVD2MZ256kr $ymm0
|
||||
+ $eax = KMOVBrk $k0
|
||||
+ $k0 = KSHIFTRBki $k0, 2
|
||||
; CHECK: $k0 = VPMOVB2MZ256kr $ymm0
|
||||
; CHECK: $eax = KMOVWrk $k0
|
||||
$k0 = VPMOVB2MZ256kr $ymm0
|
||||
@@ -1803,6 +1809,12 @@ body: |
|
||||
$k0 = VPMOVD2MZ128kr $xmm0
|
||||
$eax = KMOVBrk $k0
|
||||
$ebx = KMOVBrk $k0
|
||||
+ ; CHECK: $k0 = VPMOVD2MZ128kr $xmm0
|
||||
+ ; CHECK: $eax = KMOVBrk $k0
|
||||
+ ; CHECK: $k0 = KSHIFTRBki $k0, 2
|
||||
+ $k0 = VPMOVD2MZ128kr $xmm0
|
||||
+ $eax = KMOVBrk $k0
|
||||
+ $k0 = KSHIFTRBki $k0, 2
|
||||
; CHECK: $k0 = VPMOVB2MZ128kr $xmm0
|
||||
; CHECK: $eax = KMOVBrk $k0
|
||||
$k0 = VPMOVB2MZ128kr $xmm0
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@ -0,0 +1,87 @@
|
||||
From 2119e359b1f968da94ff27a4078d569e18903aef Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Popov <npopov@redhat.com>
|
||||
Date: Mon, 13 Jul 2026 09:08:54 +0200
|
||||
Subject: [PATCH] [lld][ELF] Concatenate .gnu.build.attributes.* sections
|
||||
(#208737)
|
||||
|
||||
ld.bfd/ld.gold have been concatenating the GNU build attribute sections
|
||||
since 2018:
|
||||
|
||||
https://gitlab.com/gnutools/binutils-gdb/-/commit/7d8a31665739412395f6dd370d2279acd322e78e
|
||||
|
||||
Do the same in LLD. These do not have a dedicated section type or flags,
|
||||
so this is handled by the name-based logic. (Peculiarly, there used to
|
||||
be SHF_GNU_BUILD_NOTE, but it was removed again.)
|
||||
|
||||
Not concatenating these results in a huge number of sections, which
|
||||
breaks tools like `file`.
|
||||
---
|
||||
lld/ELF/LinkerScript.cpp | 2 +-
|
||||
lld/test/ELF/gnu-build-attributes.s | 42 +++++++++++++++++++++++++++++
|
||||
2 files changed, 43 insertions(+), 1 deletion(-)
|
||||
create mode 100644 lld/test/ELF/gnu-build-attributes.s
|
||||
|
||||
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
|
||||
index 1c0a49a73962..64fb717e17d9 100644
|
||||
--- a/lld/ELF/LinkerScript.cpp
|
||||
+++ b/lld/ELF/LinkerScript.cpp
|
||||
@@ -119,7 +119,7 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
|
||||
".init_array", ".fini_array", ".tbss",
|
||||
".tdata", ".ARM.exidx", ".ARM.extab",
|
||||
".ctors", ".dtors", ".sbss",
|
||||
- ".sdata", ".srodata"})
|
||||
+ ".sdata", ".srodata", ".gnu.build.attributes"})
|
||||
if (isSectionPrefix(v, s->name))
|
||||
return v;
|
||||
|
||||
diff --git a/lld/test/ELF/gnu-build-attributes.s b/lld/test/ELF/gnu-build-attributes.s
|
||||
new file mode 100644
|
||||
index 000000000000..79ad6c40ae50
|
||||
--- /dev/null
|
||||
+++ b/lld/test/ELF/gnu-build-attributes.s
|
||||
@@ -0,0 +1,42 @@
|
||||
+# REQUIRES: x86
|
||||
+
|
||||
+## Check that .gnu.build.attributes.* sections are concatenated into a single
|
||||
+## .gnu.build.attributes section.
|
||||
+
|
||||
+# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu %s -o %t.o
|
||||
+# RUN: ld.lld %t.o -o %t
|
||||
+# RUN: llvm-readobj -n %t | FileCheck %s
|
||||
+
|
||||
+# CHECK: NoteSections [
|
||||
+# CHECK-NEXT: NoteSection {
|
||||
+# CHECK-NEXT: Name: .gnu.build.attributes
|
||||
+# CHECK-NEXT: Offset: 0x120
|
||||
+# CHECK-NEXT: Size: 0x28
|
||||
+# CHECK-NEXT: Notes [
|
||||
+# CHECK-NEXT: {
|
||||
+# CHECK-NEXT: Owner: GA${{.*}}:a1
|
||||
+# CHECK-NEXT: Data size: 0x0
|
||||
+# CHECK-NEXT: Type: OPEN
|
||||
+# CHECK-NEXT: }
|
||||
+# CHECK-NEXT: {
|
||||
+# CHECK-NEXT: Owner: GA${{.*}}:b1
|
||||
+# CHECK-NEXT: Data size: 0x0
|
||||
+# CHECK-NEXT: Type: OPEN
|
||||
+# CHECK-NEXT: }
|
||||
+# CHECK-NEXT: ]
|
||||
+# CHECK-NEXT: }
|
||||
+# CHECK-NEXT: ]
|
||||
+
|
||||
+.section ".gnu.build.attributes.text.foo", "", @note
|
||||
+.balign 4
|
||||
+.long 8
|
||||
+.long 0
|
||||
+.long 0x100
|
||||
+.asciz "GA$\x03:a1"
|
||||
+
|
||||
+.section ".gnu.build.attributes.text.bar", "", @note
|
||||
+.balign 4
|
||||
+.long 8
|
||||
+.long 0
|
||||
+.long 0x100
|
||||
+.asciz "GA$\x03:b1"
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
* Fri Jul 17 2026 Nikita Popov <npopov@redhat.com> - 22.1.8-2
|
||||
- Backport some patches (RHEL-210751)
|
||||
|
||||
* Thu Jun 25 2026 Nikita Popov <npopov@redhat.com> - 22.1.8-1
|
||||
- Update to LLVM 22.1.8
|
||||
|
||||
|
||||
15
llvm.spec
15
llvm.spec
@ -443,7 +443,7 @@ end
|
||||
Name: %{pkg_name_llvm}
|
||||
Version: %{maj_ver}.%{min_ver}.%{patch_ver}%{?rc_ver:~%{rc_ver}}%{?llvm_snapshot_version_suffix:~%{llvm_snapshot_version_suffix}}
|
||||
%if 0%{?rhel} == 8
|
||||
Release: 1%{?dist}
|
||||
Release: 2%{?dist}
|
||||
%else
|
||||
Release: 1%{?dist}
|
||||
%endif
|
||||
@ -530,9 +530,22 @@ Patch2209: https://github.com/llvm/llvm-project/commit/0b6a1ef429.patch
|
||||
# s390x fix for unaligned memory access performance regressions.
|
||||
Patch2210: 0001-SystemZ-Avoid-unaligned-VL-VST-s-with-memcpy-memmove.patch
|
||||
|
||||
# Fix a heap buffer overflow.
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2496390
|
||||
Patch2211: 0001-LLVM-Verifier-Fix-buffer-overflow-when-verifying-gc..patch
|
||||
|
||||
# Fix miscompilation.
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2499684
|
||||
Patch2212: 0001-SDAG-Freeze-condition-in-select-of-load-fold-208683.patch
|
||||
# Fix a vector miscompilation
|
||||
Patch2213: 0001-X86-Fix-EVEX-compression-for-VPMOV-2M-KMOV-with-tied.patch
|
||||
|
||||
#region LLD patches
|
||||
Patch106: 0001-19-Always-build-shared-libs-for-LLD.patch
|
||||
Patch2103: 0001-lld-Adjust-compressed-debug-level-test-for-s390x-wit.patch
|
||||
Patch2214: 0001-ELF-Simplify-AArch64-relocateAlloc.-NFC.patch
|
||||
Patch2215: 0001-LLD-AArch64-Make-adrp-ldr-relaxation-per-symbol-all-.patch
|
||||
Patch2216: 0001-lld-ELF-Concatenate-.gnu.build.attributes.-sections-.patch
|
||||
#endregion LLD patches
|
||||
|
||||
#region polly patches
|
||||
|
||||
Loading…
Reference in New Issue
Block a user