Compare commits

..

No commits in common. "c9-beta" and "c8-stream-rhel8" have entirely different histories.

19 changed files with 718 additions and 10346 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/llvm-project-22.1.8.src.tar.xz
SOURCES/llvm-project-22.1.8.src.tar.xz.sig
SOURCES/llvm-project-21.1.8.src.tar.xz
SOURCES/llvm-project-21.1.8.src.tar.xz.sig

View File

@ -1,2 +1,2 @@
b8a2cafc2ba8c91cee103f00454a211cdd7144f3 SOURCES/llvm-project-22.1.8.src.tar.xz
1210d061f5c4a883cba76d3ae47347338458141d SOURCES/llvm-project-22.1.8.src.tar.xz.sig
a02f43a68bf59be15a61d6ddd0d99bd4973244f4 SOURCES/llvm-project-21.1.8.src.tar.xz
c10b9d8ebce251f8be51eb71378122300fd37de3 SOURCES/llvm-project-21.1.8.src.tar.xz.sig

View File

@ -1,27 +0,0 @@
From 49f827b09db549de62dcaf8b90b3fcb3e08c0ee5 Mon Sep 17 00:00:00 2001
From: Serge Guelton <sguelton@redhat.com>
Date: Mon, 6 Mar 2023 12:37:48 +0100
Subject: [PATCH] Make -funwind-tables the default on all archs
---
clang/lib/Driver/ToolChains/Gnu.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 24fbdcffc07b..8fed46b49515 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -3082,6 +3082,10 @@ Generic_GCC::getDefaultUnwindTableLevel(const ArgList &Args) const {
case llvm::Triple::riscv64be:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
+ // Enable -funwind-tables on all architectures supported by Fedora:
+ // rhbz#1655546
+ case llvm::Triple::systemz:
+ case llvm::Triple::arm:
return UnwindTableLevel::Asynchronous;
default:
return UnwindTableLevel::None;
--
2.39.1

View File

@ -0,0 +1,26 @@
From ffc7d5ae2d79f98967943fabb2abfbc1b1e047fd Mon Sep 17 00:00:00 2001
From: Douglas Yung <douglas.yung@sony.com>
Date: Tue, 24 Jun 2025 04:08:34 +0000
Subject: [PATCH] Add `REQUIRES: asserts` to test added in #145149 because it
uses the `-debug-only=` flag.
This should fix the test failure when building without asserts.
---
llvm/test/CodeGen/PowerPC/pr141642.ll | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/test/CodeGen/PowerPC/pr141642.ll b/llvm/test/CodeGen/PowerPC/pr141642.ll
index 38a706574786..61bda4dfaf53 100644
--- a/llvm/test/CodeGen/PowerPC/pr141642.ll
+++ b/llvm/test/CodeGen/PowerPC/pr141642.ll
@@ -2,6 +2,7 @@
; RUN: FileCheck %s
; CHECK-NOT: lxvdsx
; CHECK-NOT: LD_SPLAT
+; REQUIRES: asserts
define weak_odr dso_local void @unpack(ptr noalias noundef %packed_in) local_unnamed_addr {
entry:
--
2.49.0

View File

@ -0,0 +1,131 @@
From dde30a47313bf52fef02bbcb1de931a8d725659f Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo@fhahn.com>
Date: Fri, 6 Jun 2025 12:38:30 +0100
Subject: [PATCH] [CGP] Bail out if (Base|Scaled)Reg does not dominate insert
point. (#142949)
(Base|Scaled)Reg may not dominate the chosen insert point, if there are
multiple uses of the address. Bail out if that's the case, otherwise we
will generate invalid IR.
In some cases, we could probably adjust the insert point or hoist the
(Base|Scaled)Reg.
Fixes https://github.com/llvm/llvm-project/issues/142830.
PR: https://github.com/llvm/llvm-project/pull/142949
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 13 +++-
.../X86/sink-addrmode-reg-does-not-geps.ll | 76 +++++++++++++++++++
2 files changed, 87 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-reg-does-not-geps.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 822ed6283117..32348a899683 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -5945,8 +5945,17 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
// The current BB may be optimized multiple times, we can't guarantee the
// reuse of Addr happens later, call findInsertPos to find an appropriate
// insert position.
- IRBuilder<> Builder(MemoryInst->getParent(),
- findInsertPos(Addr, MemoryInst, SunkAddr));
+ auto InsertPos = findInsertPos(Addr, MemoryInst, SunkAddr);
+
+ // TODO: Adjust insert point considering (Base|Scaled)Reg if possible.
+ if (!SunkAddr) {
+ auto &DT = getDT(*MemoryInst->getFunction());
+ if ((AddrMode.BaseReg && !DT.dominates(AddrMode.BaseReg, &*InsertPos)) ||
+ (AddrMode.ScaledReg && !DT.dominates(AddrMode.ScaledReg, &*InsertPos)))
+ return Modified;
+ }
+
+ IRBuilder<> Builder(MemoryInst->getParent(), InsertPos);
if (SunkAddr) {
LLVM_DEBUG(dbgs() << "CGP: Reusing nonlocal addrmode: " << AddrMode
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-reg-does-not-geps.ll b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-reg-does-not-geps.ll
new file mode 100644
index 000000000000..1640bafbd0bf
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode-reg-does-not-geps.ll
@@ -0,0 +1,76 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux"
+
+declare i1 @cond(float)
+
+define void @scaled_reg_does_not_dominate_insert_point(ptr %src) {
+; CHECK-LABEL: define void @scaled_reg_does_not_dominate_insert_point(
+; CHECK-SAME: ptr [[SRC:%.*]]) {
+; CHECK-NEXT: [[BB:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[SUNKADDR2:%.*]] = mul i64 [[IV_NEXT]], 2
+; CHECK-NEXT: [[SUNKADDR3:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[SUNKADDR2]]
+; CHECK-NEXT: [[SUNKADDR4:%.*]] = getelementptr i8, ptr [[SUNKADDR3]], i64 6
+; CHECK-NEXT: [[L_0:%.*]] = load float, ptr [[SUNKADDR4]], align 4
+; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV]], 2
+; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[SUNKADDR]]
+; CHECK-NEXT: [[L_1:%.*]] = load float, ptr [[SUNKADDR1]], align 4
+; CHECK-NEXT: [[TMP0:%.*]] = call i1 @cond(float [[L_0]])
+; CHECK-NEXT: [[C:%.*]] = call i1 @cond(float [[L_1]])
+; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+bb:
+ %gep.base = getelementptr i8, ptr %src, i64 8
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %bb ], [ %iv.next, %loop ]
+ %iv.shl = shl i64 %iv, 1
+ %gep.shl = getelementptr i8, ptr %gep.base, i64 %iv.shl
+ %gep.sub = getelementptr i8, ptr %gep.shl, i64 -8
+ %iv.next = add i64 %iv, 1
+ %l.0 = load float, ptr %gep.shl, align 4
+ %l.1 = load float, ptr %gep.sub, align 4
+ call i1 @cond(float %l.0)
+ %c = call i1 @cond(float %l.1)
+ br i1 %c, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+define void @check_dt_after_modifying_cfg(ptr %dst, i64 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: define void @check_dt_after_modifying_cfg(
+; CHECK-SAME: ptr [[DST:%.*]], i64 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[OFFSET:%.*]] = lshr i64 [[X]], 2
+; CHECK-NEXT: [[SEL_FROZEN:%.*]] = freeze i8 [[Z]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[SEL_FROZEN]], 0
+; CHECK-NEXT: br i1 [[CMP]], label %[[SELECT_END:.*]], label %[[SELECT_FALSE_SINK:.*]]
+; CHECK: [[SELECT_FALSE_SINK]]:
+; CHECK-NEXT: [[SMIN:%.*]] = tail call i8 @llvm.smin.i8(i8 [[Y]], i8 0)
+; CHECK-NEXT: br label %[[SELECT_END]]
+; CHECK: [[SELECT_END]]:
+; CHECK-NEXT: [[SEL:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[SMIN]], %[[SELECT_FALSE_SINK]] ]
+; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr i8, ptr [[DST]], i64 [[OFFSET]]
+; CHECK-NEXT: store i8 [[SEL]], ptr [[SUNKADDR]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ %offset = lshr i64 %x, 2
+ %gep.dst = getelementptr i8, ptr %dst, i64 %offset
+ %smin = tail call i8 @llvm.smin.i8(i8 %y, i8 0)
+ %cmp = icmp slt i8 %z, 0
+ %sel = select i1 %cmp, i8 0, i8 %smin
+ store i8 %sel, ptr %gep.dst, align 1
+ ret void
+}
+
+declare i8 @llvm.smin.i8(i8, i8) #0
--
2.50.1

View File

@ -0,0 +1,143 @@
From c76137f1cfd5758f6889236d49a65f059e6432ff Mon Sep 17 00:00:00 2001
From: weiguozhi <57237827+weiguozhi@users.noreply.github.com>
Date: Thu, 15 May 2025 09:27:25 -0700
Subject: [PATCH] [CodeGenPrepare] Make sure instruction get from SunkAddrs is
before MemoryInst (#139303)
Function optimizeBlock may do optimizations on a block for multiple
times. In the first iteration of the loop, MemoryInst1 may generate a
sunk instruction and store it into SunkAddrs. In the second iteration of
the loop, MemoryInst2 may use the same address and then it can reuse the
sunk instruction stored in SunkAddrs, but MemoryInst2 may be before
MemoryInst1 and the corresponding sunk instruction. In order to avoid
use before def error, we need to find appropriate insert position for the
sunk instruction.
Fixes #138208.
(cherry picked from commit 59c6d70ed8120b8864e5f796e2bf3de5518a0ef0)
---
llvm/lib/CodeGen/CodeGenPrepare.cpp | 41 ++++++++++++++---
.../CodeGenPrepare/X86/sink-addr-reuse.ll | 44 +++++++++++++++++++
2 files changed, 80 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/Transforms/CodeGenPrepare/X86/sink-addr-reuse.ll
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 088062afab17..f779f4b782ae 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -5728,6 +5728,35 @@ static bool IsNonLocalValue(Value *V, BasicBlock *BB) {
return false;
}
+// Find an insert position of Addr for MemoryInst. We can't guarantee MemoryInst
+// is the first instruction that will use Addr. So we need to find the first
+// user of Addr in current BB.
+static BasicBlock::iterator findInsertPos(Value *Addr, Instruction *MemoryInst,
+ Value *SunkAddr) {
+ if (Addr->hasOneUse())
+ return MemoryInst->getIterator();
+
+ // We already have a SunkAddr in current BB, but we may need to insert cast
+ // instruction after it.
+ if (SunkAddr) {
+ if (Instruction *AddrInst = dyn_cast<Instruction>(SunkAddr))
+ return std::next(AddrInst->getIterator());
+ }
+
+ // Find the first user of Addr in current BB.
+ Instruction *Earliest = MemoryInst;
+ for (User *U : Addr->users()) {
+ Instruction *UserInst = dyn_cast<Instruction>(U);
+ if (UserInst && UserInst->getParent() == MemoryInst->getParent()) {
+ if (isa<PHINode>(UserInst) || UserInst->isDebugOrPseudoInst())
+ continue;
+ if (UserInst->comesBefore(Earliest))
+ Earliest = UserInst;
+ }
+ }
+ return Earliest->getIterator();
+}
+
/// Sink addressing mode computation immediate before MemoryInst if doing so
/// can be done without increasing register pressure. The need for the
/// register pressure constraint means this can end up being an all or nothing
@@ -5852,11 +5881,6 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
return Modified;
}
- // Insert this computation right after this user. Since our caller is
- // scanning from the top of the BB to the bottom, reuse of the expr are
- // guaranteed to happen later.
- IRBuilder<> Builder(MemoryInst);
-
// Now that we determined the addressing expression we want to use and know
// that we have to sink it into this block. Check to see if we have already
// done this for some other load/store instr in this block. If so, reuse
@@ -5867,6 +5891,13 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr;
Type *IntPtrTy = DL->getIntPtrType(Addr->getType());
+
+ // The current BB may be optimized multiple times, we can't guarantee the
+ // reuse of Addr happens later, call findInsertPos to find an appropriate
+ // insert position.
+ IRBuilder<> Builder(MemoryInst->getParent(),
+ findInsertPos(Addr, MemoryInst, SunkAddr));
+
if (SunkAddr) {
LLVM_DEBUG(dbgs() << "CGP: Reusing nonlocal addrmode: " << AddrMode
<< " for " << *MemoryInst << "\n");
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addr-reuse.ll b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addr-reuse.ll
new file mode 100644
index 000000000000..019f31140655
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addr-reuse.ll
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -p 'require<profile-summary>,codegenprepare' -cgpp-huge-func=0 < %s | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+declare void @g(ptr)
+
+; %load and %load5 use the same address, %load5 is optimized first, %load is
+; optimized later and reuse the same address computation instruction. We must
+; make sure not to generate use before def error.
+
+define void @f(ptr %arg) {
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: ptr [[ARG:%.*]]) {
+; CHECK-NEXT: [[BB:.*:]]
+; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i8, ptr [[ARG]], i64 -64
+; CHECK-NEXT: call void @g(ptr [[GETELEMENTPTR]])
+; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[ARG]], i64 -64
+; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[SUNKADDR1]], align 8
+; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr i8, ptr [[ARG]], i64 -56
+; CHECK-NEXT: [[LOAD4:%.*]] = load i32, ptr [[SUNKADDR]], align 8
+; CHECK-NEXT: [[LOAD5:%.*]] = load ptr, ptr [[SUNKADDR1]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 1, i32 0)
+; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0
+; CHECK-NEXT: ret void
+;
+bb:
+ %getelementptr = getelementptr i8, ptr %arg, i64 -64
+ %getelementptr1 = getelementptr i8, ptr %arg, i64 -56
+ call void @g(ptr %getelementptr)
+ br label %bb3
+
+bb3:
+ %load = load ptr, ptr %getelementptr, align 8
+ %load4 = load i32, ptr %getelementptr1, align 8
+ %load5 = load ptr, ptr %getelementptr, align 8
+ %add = add i32 1, 0
+ %icmp = icmp eq i32 %add, 0
+ br i1 %icmp, label %bb7, label %bb7
+
+bb7:
+ ret void
+}
--
2.49.0

View File

@ -1,47 +0,0 @@
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

View File

@ -1,416 +0,0 @@
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

View File

@ -1,88 +0,0 @@
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

View File

@ -0,0 +1,67 @@
From 735d721de451067c3a618b309703d0b8beb9cacc Mon Sep 17 00:00:00 2001
From: Wael Yehia <wmyehia2001@yahoo.com>
Date: Mon, 23 Jun 2025 13:22:33 -0400
Subject: [PATCH] [PowerPC] Fix handling of undefs in the
PPC::isSplatShuffleMask query (#145149)
Currently, the query assumes that a single undef byte implies the rest of
the `EltSize - 1` bytes are undefs, but that's not always true.
e.g. isSplatShuffleMask(
<0,1,2,3,4,5,6,7,undef,undef,undef,undef,0,1,2,3>, 8) should return
false.
---------
Co-authored-by: Wael Yehia <wyehia@ca.ibm.com>
---
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 13 +++++++++----
llvm/test/CodeGen/PowerPC/pr141642.ll | 13 +++++++++++++
2 files changed, 22 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/PowerPC/pr141642.ll
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 421a808de667..88c6fe632d26 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -2242,10 +2242,15 @@ bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) {
return false;
for (unsigned i = EltSize, e = 16; i != e; i += EltSize) {
- if (N->getMaskElt(i) < 0) continue;
- for (unsigned j = 0; j != EltSize; ++j)
- if (N->getMaskElt(i+j) != N->getMaskElt(j))
- return false;
+ // An UNDEF element is a sequence of UNDEF bytes.
+ if (N->getMaskElt(i) < 0) {
+ for (unsigned j = 1; j != EltSize; ++j)
+ if (N->getMaskElt(i + j) >= 0)
+ return false;
+ } else
+ for (unsigned j = 0; j != EltSize; ++j)
+ if (N->getMaskElt(i + j) != N->getMaskElt(j))
+ return false;
}
return true;
}
diff --git a/llvm/test/CodeGen/PowerPC/pr141642.ll b/llvm/test/CodeGen/PowerPC/pr141642.ll
new file mode 100644
index 000000000000..38a706574786
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/pr141642.ll
@@ -0,0 +1,13 @@
+; RUN: llc -mcpu=pwr8 -mtriple=powerpc64le-unknown-linux-gnu -O0 -debug-only=selectiondag -o - < %s 2>&1 | \
+; RUN: FileCheck %s
+; CHECK-NOT: lxvdsx
+; CHECK-NOT: LD_SPLAT
+
+define weak_odr dso_local void @unpack(ptr noalias noundef %packed_in) local_unnamed_addr {
+entry:
+ %ld = load <2 x i32>, ptr %packed_in, align 2
+ %shuf = shufflevector <2 x i32> %ld, <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 0>
+ %ie = insertelement <4 x i32> %shuf, i32 7, i32 2
+ store <4 x i32> %shuf, ptr %packed_in, align 2
+ ret void
+}
--
2.49.0

View File

@ -1,81 +0,0 @@
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

View File

@ -0,0 +1,39 @@
From 06774eb8a7dc0bc36b59e53310c7f5b5d89f6c29 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov@redhat.com>
Date: Tue, 28 Jan 2025 12:31:49 +0100
Subject: [PATCH] [cmake] Resolve symlink when finding install prefix
When determining the install prefix in LLVMConfig.cmake etc resolve
symlinks in CMAKE_CURRENT_LIST_FILE first. The motivation for this
is to support symlinks like `/usr/lib64/cmake/llvm` to
`/usr/lib64/llvm19/lib/cmake/llvm`. This only works correctly if
the paths are relative to the resolved symlink.
It's worth noting that this *mostly* already works out of the box,
because cmake automatically does the symlink resolution when the
library is found via CMAKE_PREFIX_PATH. It just doesn't happen
when it's found via the default prefix path.
---
cmake/Modules/FindPrefixFromConfig.cmake | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cmake/Modules/FindPrefixFromConfig.cmake b/cmake/Modules/FindPrefixFromConfig.cmake
index 22211e4b72f2..3daff607ff84 100644
--- a/cmake/Modules/FindPrefixFromConfig.cmake
+++ b/cmake/Modules/FindPrefixFromConfig.cmake
@@ -39,10 +39,10 @@ function(find_prefix_from_config out_var prefix_var path_to_leave)
# install prefix, and avoid hard-coding any absolute paths.
set(config_code
"# Compute the installation prefix from this LLVMConfig.cmake file location."
- "get_filename_component(${prefix_var} \"\${CMAKE_CURRENT_LIST_FILE}\" PATH)")
+ "get_filename_component(${prefix_var} \"\${CMAKE_CURRENT_LIST_FILE}\" REALPATH)")
# Construct the proper number of get_filename_component(... PATH)
# calls to compute the installation prefix.
- string(REGEX REPLACE "/" ";" _count "${path_to_leave}")
+ string(REGEX REPLACE "/" ";" _count "${path_to_leave}/plus_one")
foreach(p ${_count})
list(APPEND config_code
"get_filename_component(${prefix_var} \"\${${prefix_var}}\" PATH)")
--
2.48.1

View File

@ -1,87 +0,0 @@
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

View File

@ -1,70 +0,0 @@
From 0b6a1ef4297bb839fe26041602d32411358e0032 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
Date: Tue, 26 May 2026 01:41:01 +0200
Subject: [PATCH] [lit] Normalize RLIM_INFINITY to "infinity" in
print_limits.py for Python 3.15+ (#190953)
Python 3.15 changed resource.getrlimit() to return the platform's
maximum value (e.g., 18446744073709551615 on 64-bit systems) instead of
-1 for RLIM_INFINITY. This breaks lit tests that expect -1 for unlimited
resource limits.
This patch normalizes the return value to "infinity" when it equals
RLIM_INFINITY to maintain compatibility with existing tests across all
Python versions.
Fixes test failure: shtest-ulimit-nondarwin.py
Expected: RLIMIT_FSIZE=-1
Got: RLIMIT_FSIZE=18446744073709551615
Reference:
https://github.com/python/cpython/commit/0324c726dea702282a0300225e989b19ae23b759
Reference: https://bugzilla.redhat.com/show_bug.cgi?id=2448969
Analysis and testing assisted by AI.
Assisted-by: Claude Sonnet 4.5
---------
Co-authored-by: Alexander Richardson <mail@alexrichardson.me>
Co-authored-by: Tulio Magno Quites Machado Filho <tuliom@quites.com.br>
---
.../tests/Inputs/shtest-ulimit/print_limits.py | 17 +++++++++++++----
llvm/utils/lit/tests/shtest-ulimit-nondarwin.py | 2 +-
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/llvm/utils/lit/tests/Inputs/shtest-ulimit/print_limits.py b/llvm/utils/lit/tests/Inputs/shtest-ulimit/print_limits.py
index c732c0429e661..6c03721baf36d 100644
--- a/llvm/utils/lit/tests/Inputs/shtest-ulimit/print_limits.py
+++ b/llvm/utils/lit/tests/Inputs/shtest-ulimit/print_limits.py
@@ -1,6 +1,15 @@
import resource
-print("RLIMIT_AS=" + str(resource.getrlimit(resource.RLIMIT_AS)[0]))
-print("RLIMIT_NOFILE=" + str(resource.getrlimit(resource.RLIMIT_NOFILE)[0]))
-print("RLIMIT_STACK=" + str(resource.getrlimit(resource.RLIMIT_STACK)[0]))
-print("RLIMIT_FSIZE=" + str(resource.getrlimit(resource.RLIMIT_FSIZE)[0]))
+
+def normalize_limit(limit_value):
+ """Normalize RLIM_INFINITY to "infinity" for consistency across Python versions.
+
+ Python 3.15+ returns the platform's max value (e.g., 2^64-1) instead of -1.
+ """
+ return "infinity" if limit_value == resource.RLIM_INFINITY else str(limit_value)
+
+
+print("RLIMIT_AS=" + normalize_limit(resource.getrlimit(resource.RLIMIT_AS)[0]))
+print("RLIMIT_NOFILE=" + normalize_limit(resource.getrlimit(resource.RLIMIT_NOFILE)[0]))
+print("RLIMIT_STACK=" + normalize_limit(resource.getrlimit(resource.RLIMIT_STACK)[0]))
+print("RLIMIT_FSIZE=" + normalize_limit(resource.getrlimit(resource.RLIMIT_FSIZE)[0]))
diff --git a/llvm/utils/lit/tests/shtest-ulimit-nondarwin.py b/llvm/utils/lit/tests/shtest-ulimit-nondarwin.py
index 43811db750f80..80844d1d79460 100644
--- a/llvm/utils/lit/tests/shtest-ulimit-nondarwin.py
+++ b/llvm/utils/lit/tests/shtest-ulimit-nondarwin.py
@@ -18,4 +18,4 @@
# CHECK: ulimit -f 5
# CHECK: RLIMIT_FSIZE=5
# CHECK: ulimit -f unlimited
-# CHECK: RLIMIT_FSIZE=-1
+# CHECK: RLIMIT_FSIZE=infinity

28
SOURCES/20-131099.patch Normal file
View File

@ -0,0 +1,28 @@
From e43271ec7438ecb78f99db134aeca274a47f6c28 Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkleine@redhat.com>
Date: Thu, 13 Mar 2025 09:12:24 +0100
Subject: [PATCH] Filter out configuration file from compile commands
The commands to run the compilation when printed with `-###` contain
various irrelevant lines for the perf-training. Most of them are
filtered out already but when configured with
`CLANG_CONFIG_FILE_SYSTEM_DIR` a new line like the following is
added and needs to be filtered out:
`Configuration file: /etc/clang/x86_64-redhat-linux-gnu-clang.cfg`
---
clang/utils/perf-training/perf-helper.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/utils/perf-training/perf-helper.py b/clang/utils/perf-training/perf-helper.py
index 80c6356d0497c..29904aded5ab0 100644
--- a/clang/utils/perf-training/perf-helper.py
+++ b/clang/utils/perf-training/perf-helper.py
@@ -237,6 +237,7 @@ def get_cc1_command_for_args(cmd, env):
or ln.startswith("InstalledDir:")
or ln.startswith("LLVM Profile Note")
or ln.startswith(" (in-process)")
+ or ln.startswith("Configuration file:")
or " version " in ln
):
continue

94
SOURCES/21-146424.patch Normal file
View File

@ -0,0 +1,94 @@
From eba58195932f37fb461ae17c69fc517181b99c9a Mon Sep 17 00:00:00 2001
From: Paul Murphy <paumurph@redhat.com>
Date: Mon, 30 Jun 2025 10:13:37 -0500
Subject: [PATCH] [PowerPC] fix lowering of SPILL_CRBIT on pwr9 and pwr10
If a copy exists between creation of a crbit and a spill, machine-cp
may delete the copy since it seems unaware of the relation between a cr
and crbit. A fix was previously made for the generic ppc64 lowering. It
should be applied to the pwr9 and pwr10 variants too.
Likewise, relax and extend the pwr8 test to verify pwr9 and pwr10
codegen too.
This fixes #143989.
---
llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 17 +++++++++++------
.../PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir | 8 +++++++-
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 76dca4794e05..78d254a55fd9 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -1102,13 +1102,20 @@ void PPCRegisterInfo::lowerCRBitSpilling(MachineBasicBlock::iterator II,
SpillsKnownBit = true;
break;
default:
+ // When spilling a CR bit, The super register may not be explicitly defined
+ // (i.e. it can be defined by a CR-logical that only defines the subreg) so
+ // we state that the CR field is undef. Also, in order to preserve the kill
+ // flag on the CR bit, we add it as an implicit use.
+
// On Power10, we can use SETNBC to spill all CR bits. SETNBC will set all
// bits (specifically, it produces a -1 if the CR bit is set). Ultimately,
// the bit that is of importance to us is bit 32 (bit 0 of a 32-bit
// register), and SETNBC will set this.
if (Subtarget.isISA3_1()) {
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::SETNBC8 : PPC::SETNBC), Reg)
- .addReg(SrcReg, RegState::Undef);
+ .addReg(SrcReg, RegState::Undef)
+ .addReg(SrcReg, RegState::Implicit |
+ getKillRegState(MI.getOperand(0).isKill()));
break;
}
@@ -1122,16 +1129,14 @@ void PPCRegisterInfo::lowerCRBitSpilling(MachineBasicBlock::iterator II,
SrcReg == PPC::CR4LT || SrcReg == PPC::CR5LT ||
SrcReg == PPC::CR6LT || SrcReg == PPC::CR7LT) {
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::SETB8 : PPC::SETB), Reg)
- .addReg(getCRFromCRBit(SrcReg), RegState::Undef);
+ .addReg(getCRFromCRBit(SrcReg), RegState::Undef)
+ .addReg(SrcReg, RegState::Implicit |
+ getKillRegState(MI.getOperand(0).isKill()));
break;
}
}
// We need to move the CR field that contains the CR bit we are spilling.
- // The super register may not be explicitly defined (i.e. it can be defined
- // by a CR-logical that only defines the subreg) so we state that the CR
- // field is undef. Also, in order to preserve the kill flag on the CR bit,
- // we add it as an implicit use.
BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::MFOCRF8 : PPC::MFOCRF), Reg)
.addReg(getCRFromCRBit(SrcReg), RegState::Undef)
.addReg(SrcReg,
diff --git a/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir b/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir
index 41e21248a3f0..2796cdb3ae87 100644
--- a/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir
+++ b/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir
@@ -1,6 +1,12 @@
# RUN: llc -mcpu=pwr8 -mtriple=powerpc64le-unknown-linux-gnu -start-after \
# RUN: virtregrewriter -ppc-asm-full-reg-names -verify-machineinstrs %s \
# RUN: -o - | FileCheck %s
+# RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-linux-gnu -start-after \
+# RUN: virtregrewriter -ppc-asm-full-reg-names -verify-machineinstrs %s \
+# RUN: -o - | FileCheck %s
+# RUN: llc -mcpu=pwr10 -mtriple=powerpc64le-unknown-linux-gnu -start-after \
+# RUN: virtregrewriter -ppc-asm-full-reg-names -verify-machineinstrs %s \
+# RUN: -o - | FileCheck %s
--- |
; ModuleID = 'a.ll'
@@ -30,7 +36,7 @@
; Function Attrs: nounwind
declare void @llvm.stackprotector(ptr, ptr) #1
- attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "frame-pointer"="none" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector" "unsafe-fp-math"="false" "use-soft-float"="false" }
+ attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "frame-pointer"="none" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }
!llvm.ident = !{!0}
--
2.49.0

File diff suppressed because it is too large Load Diff