Compare commits
No commits in common. "a9-beta-bootstrap" and "c8-stream-rhel8" have entirely different histories.
a9-beta-bo
...
c8-stream-
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
SOURCES/llvm-project-22.1.8.src.tar.xz
|
SOURCES/llvm-project-21.1.8.src.tar.xz
|
||||||
SOURCES/llvm-project-22.1.8.src.tar.xz.sig
|
SOURCES/llvm-project-21.1.8.src.tar.xz.sig
|
||||||
|
|||||||
@ -1,4 +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
|
a02f43a68bf59be15a61d6ddd0d99bd4973244f4 SOURCES/llvm-project-21.1.8.src.tar.xz
|
||||||
c10b9d8ebce251f8be51eb71378122300fd37de3 SOURCES/llvm-project-21.1.8.src.tar.xz.sig
|
c10b9d8ebce251f8be51eb71378122300fd37de3 SOURCES/llvm-project-21.1.8.src.tar.xz.sig
|
||||||
|
|||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
|
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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
28
SOURCES/20-131099.patch
Normal 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
94
SOURCES/21-146424.patch
Normal 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
|
||||||
|
|
||||||
1579
SPECS/llvm.spec
1579
SPECS/llvm.spec
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user