Compare commits
No commits in common. "c8-stream-rhel8" and "c9-beta" have entirely different histories.
c8-stream-
...
c9-beta
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
SOURCES/llvm-project-21.1.8.src.tar.xz
|
||||
SOURCES/llvm-project-21.1.8.src.tar.xz.sig
|
||||
SOURCES/llvm-project-22.1.8.src.tar.xz
|
||||
SOURCES/llvm-project-22.1.8.src.tar.xz.sig
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
a02f43a68bf59be15a61d6ddd0d99bd4973244f4 SOURCES/llvm-project-21.1.8.src.tar.xz
|
||||
c10b9d8ebce251f8be51eb71378122300fd37de3 SOURCES/llvm-project-21.1.8.src.tar.xz.sig
|
||||
b8a2cafc2ba8c91cee103f00454a211cdd7144f3 SOURCES/llvm-project-22.1.8.src.tar.xz
|
||||
1210d061f5c4a883cba76d3ae47347338458141d SOURCES/llvm-project-22.1.8.src.tar.xz.sig
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
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
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,143 +0,0 @@
|
||||
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
|
||||
|
||||
47
SOURCES/0001-ELF-Simplify-AArch64-relocateAlloc.-NFC.patch
Normal file
47
SOURCES/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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
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
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
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
|
||||
|
||||
@ -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
|
||||
|
||||
70
SOURCES/0b6a1ef429.patch
Normal file
70
SOURCES/0b6a1ef429.patch
Normal file
@ -0,0 +1,70 @@
|
||||
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
|
||||
@ -1,28 +0,0 @@
|
||||
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
|
||||
@ -1,94 +0,0 @@
|
||||
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
|
||||
|
||||
1577
SPECS/llvm.spec
1577
SPECS/llvm.spec
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user