import CS llvm-22.1.8-1.el9
This commit is contained in:
parent
5b46baa9ef
commit
c2d8923fc1
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
|
||||
|
||||
@ -0,0 +1,137 @@
|
||||
From 98b82f90dfb7865ae4dbfcb5a83a9e817e7894a1 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Per <kevin.per@protonmail.com>
|
||||
Date: Thu, 18 Dec 2025 10:14:01 +0100
|
||||
Subject: [PATCH] [PowerPC]: Add check for cast when shufflevector (#172443)
|
||||
|
||||
The crash happens because the cast for `Mask =
|
||||
cast<ShuffleVectorSDNode>(Res)->getMask();` fails for node `t197: v16i8
|
||||
= vector_shuffle<16,17,18,19,4,5,6,7,8,9,10,11,u,u,u,u> t196, t196`.
|
||||
However, both `LHS` and `RHS` are the same node, so
|
||||
`DAG.getCommutedVectorShuffle` doesn't return a `ShuffleVectorSDNode`
|
||||
and crashes. The fix is to add a check before the cast is performed.
|
||||
|
||||
Closes https://github.com/llvm/llvm-project/issues/172265
|
||||
---
|
||||
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 4 +
|
||||
.../test/CodeGen/PowerPC/vec_shuffle_le_be.ll | 94 +++++++++++++++++++
|
||||
2 files changed, 98 insertions(+)
|
||||
create mode 100644 llvm/test/CodeGen/PowerPC/vec_shuffle_le_be.ll
|
||||
|
||||
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
|
||||
index 5b1d9f814806..21297b812968 100644
|
||||
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
|
||||
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
|
||||
@@ -16886,6 +16886,10 @@ SDValue PPCTargetLowering::combineVectorShuffle(ShuffleVectorSDNode *SVN,
|
||||
RHS.getOpcode() != ISD::VECTOR_SHUFFLE) {
|
||||
std::swap(LHS, RHS);
|
||||
Res = DAG.getCommutedVectorShuffle(*SVN);
|
||||
+
|
||||
+ if (!isa<ShuffleVectorSDNode>(Res))
|
||||
+ return Res;
|
||||
+
|
||||
Mask = cast<ShuffleVectorSDNode>(Res)->getMask();
|
||||
}
|
||||
|
||||
diff --git a/llvm/test/CodeGen/PowerPC/vec_shuffle_le_be.ll b/llvm/test/CodeGen/PowerPC/vec_shuffle_le_be.ll
|
||||
new file mode 100644
|
||||
index 000000000000..24c1e54dd952
|
||||
--- /dev/null
|
||||
+++ b/llvm/test/CodeGen/PowerPC/vec_shuffle_le_be.ll
|
||||
@@ -0,0 +1,94 @@
|
||||
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
+; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu | FileCheck -check-prefix=CHECK-LE %s
|
||||
+; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck -check-prefix=CHECK-BE %s
|
||||
+
|
||||
+define <32 x i32> @issue_172265(<32 x i32> %BS_ARG_1, <3 x i32> %0) {
|
||||
+; CHECK-LABEL: issue_172265:
|
||||
+; CHECK: # %bb.0: # %entry
|
||||
+; CHECK-NEXT: addis 3, 2, .LCPI18_0@toc@ha
|
||||
+; CHECK-NEXT: vspltw 3, 10, 1
|
||||
+; CHECK-NEXT: addi 3, 3, .LCPI18_0@toc@l
|
||||
+; CHECK-NEXT: vmr 7, 3
|
||||
+; CHECK-NEXT: lvx 4, 0, 3
|
||||
+; CHECK-NEXT: addis 3, 2, .LCPI18_1@toc@ha
|
||||
+; CHECK-NEXT: addi 3, 3, .LCPI18_1@toc@l
|
||||
+; CHECK-NEXT: vmr 8, 3
|
||||
+; CHECK-NEXT: vmr 9, 3
|
||||
+; CHECK-NEXT: vperm 4, 3, 3, 4
|
||||
+; CHECK-NEXT: lvx 1, 0, 3
|
||||
+; CHECK-NEXT: addis 3, 2, .LCPI18_2@toc@ha
|
||||
+; CHECK-NEXT: addi 3, 3, .LCPI18_2@toc@l
|
||||
+; CHECK-NEXT: lvx 5, 0, 3
|
||||
+; CHECK-NEXT: addis 3, 2, .LCPI18_3@toc@ha
|
||||
+; CHECK-NEXT: addi 3, 3, .LCPI18_3@toc@l
|
||||
+; CHECK-NEXT: lvx 6, 0, 3
|
||||
+; CHECK-NEXT: addis 3, 2, .LCPI18_4@toc@ha
|
||||
+; CHECK-NEXT: addi 3, 3, .LCPI18_4@toc@l
|
||||
+; CHECK-NEXT: vperm 4, 2, 4, 1
|
||||
+; CHECK-NEXT: lvx 2, 0, 3
|
||||
+; CHECK-NEXT: vperm 0, 3, 3, 5
|
||||
+; CHECK-NEXT: vperm 5, 3, 3, 6
|
||||
+; CHECK-NEXT: vperm 6, 3, 3, 2
|
||||
+; CHECK-NEXT: vmr 2, 0
|
||||
+; CHECK-NEXT: blr
|
||||
+; CHECK-LE-LABEL: issue_172265:
|
||||
+; CHECK-LE: # %bb.0: # %entry
|
||||
+; CHECK-LE-NEXT: addis 3, 2, .LCPI0_0@toc@ha
|
||||
+; CHECK-LE-NEXT: xxspltw 35, 42, 1
|
||||
+; CHECK-LE-NEXT: addi 3, 3, .LCPI0_0@toc@l
|
||||
+; CHECK-LE-NEXT: vmr 7, 3
|
||||
+; CHECK-LE-NEXT: vmr 8, 3
|
||||
+; CHECK-LE-NEXT: vmr 9, 3
|
||||
+; CHECK-LE-NEXT: lxvd2x 0, 0, 3
|
||||
+; CHECK-LE-NEXT: addis 3, 2, .LCPI0_1@toc@ha
|
||||
+; CHECK-LE-NEXT: addi 3, 3, .LCPI0_1@toc@l
|
||||
+; CHECK-LE-NEXT: lxvd2x 1, 0, 3
|
||||
+; CHECK-LE-NEXT: addis 3, 2, .LCPI0_2@toc@ha
|
||||
+; CHECK-LE-NEXT: addi 3, 3, .LCPI0_2@toc@l
|
||||
+; CHECK-LE-NEXT: lxvd2x 2, 0, 3
|
||||
+; CHECK-LE-NEXT: addis 3, 2, .LCPI0_3@toc@ha
|
||||
+; CHECK-LE-NEXT: addi 3, 3, .LCPI0_3@toc@l
|
||||
+; CHECK-LE-NEXT: xxswapd 36, 0
|
||||
+; CHECK-LE-NEXT: lxvd2x 0, 0, 3
|
||||
+; CHECK-LE-NEXT: vperm 4, 2, 3, 4
|
||||
+; CHECK-LE-NEXT: xxswapd 37, 1
|
||||
+; CHECK-LE-NEXT: vperm 2, 3, 3, 5
|
||||
+; CHECK-LE-NEXT: xxswapd 32, 2
|
||||
+; CHECK-LE-NEXT: vperm 5, 3, 3, 0
|
||||
+; CHECK-LE-NEXT: xxswapd 33, 0
|
||||
+; CHECK-LE-NEXT: vperm 6, 3, 3, 1
|
||||
+; CHECK-LE-NEXT: blr
|
||||
+;
|
||||
+; CHECK-BE-LABEL: issue_172265:
|
||||
+; CHECK-BE: # %bb.0: # %entry
|
||||
+; CHECK-BE-NEXT: addis 3, 2, .LCPI0_0@toc@ha
|
||||
+; CHECK-BE-NEXT: vspltw 3, 10, 2
|
||||
+; CHECK-BE-NEXT: addi 3, 3, .LCPI0_0@toc@l
|
||||
+; CHECK-BE-NEXT: vmr 7, 3
|
||||
+; CHECK-BE-NEXT: lvx 4, 0, 3
|
||||
+; CHECK-BE-NEXT: addis 3, 2, .LCPI0_2@toc@ha
|
||||
+; CHECK-BE-NEXT: addi 3, 3, .LCPI0_2@toc@l
|
||||
+; CHECK-BE-NEXT: lvx 5, 0, 3
|
||||
+; CHECK-BE-NEXT: addis 3, 2, .LCPI0_3@toc@ha
|
||||
+; CHECK-BE-NEXT: addi 3, 3, .LCPI0_3@toc@l
|
||||
+; CHECK-BE-NEXT: vperm 0, 3, 3, 5
|
||||
+; CHECK-BE-NEXT: lvx 5, 0, 3
|
||||
+; CHECK-BE-NEXT: addis 3, 2, .LCPI0_1@toc@ha
|
||||
+; CHECK-BE-NEXT: addi 3, 3, .LCPI0_1@toc@l
|
||||
+; CHECK-BE-NEXT: lvx 1, 0, 3
|
||||
+; CHECK-BE-NEXT: addis 3, 2, .LCPI0_4@toc@ha
|
||||
+; CHECK-BE-NEXT: addi 3, 3, .LCPI0_4@toc@l
|
||||
+; CHECK-BE-NEXT: vperm 4, 3, 3, 4
|
||||
+; CHECK-BE-NEXT: vperm 4, 4, 2, 1
|
||||
+; CHECK-BE-NEXT: lvx 2, 0, 3
|
||||
+; CHECK-BE-NEXT: vperm 5, 3, 3, 5
|
||||
+; CHECK-BE-NEXT: vperm 6, 3, 3, 2
|
||||
+; CHECK-BE-NEXT: vmr 2, 0
|
||||
+; CHECK-BE-NEXT: vmr 8, 3
|
||||
+; CHECK-BE-NEXT: vmr 9, 3
|
||||
+; CHECK-BE-NEXT: blr
|
||||
+entry:
|
||||
+ %vecinit37 = shufflevector <3 x i32> %0, <3 x i32> zeroinitializer, <32 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 2, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
|
||||
+ %shuffle56 = shufflevector <32 x i32> %vecinit37, <32 x i32> %BS_ARG_1, <32 x i32> <i32 4, i32 9, i32 3, i32 3, i32 4, i32 1, i32 1, i32 0, i32 16, i32 5, i32 5, i32 34, i32 3, i32 0, i32 8, i32 2, i32 8, i32 1, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i32 7, i32 5, i32 3, i32 6, i32 0, i32 3, i32 4, i32 7>
|
||||
+ ret <32 x i32> %shuffle56
|
||||
+}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -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,191 @@
|
||||
From fc12fc635b96e9fa521a33eb31336c539eed1918 Mon Sep 17 00:00:00 2001
|
||||
From: sujianIBM <98488060+sujianIBM@users.noreply.github.com>
|
||||
Date: Thu, 31 Jul 2025 13:18:23 -0400
|
||||
Subject: [PATCH] [SystemZ] Fix code in widening vector multiplication
|
||||
(#150836)
|
||||
|
||||
Commit cdc7864 has an error which would wrongly fold widening
|
||||
multiplications into an even/odd widening operation.
|
||||
This PR fixes it and adds tests to check scenarios which should not be
|
||||
folded into an even/odd widening operation are actually not.
|
||||
---
|
||||
.../Target/SystemZ/SystemZISelLowering.cpp | 2 +-
|
||||
llvm/test/CodeGen/SystemZ/vec-mul-07.ll | 114 ++++++++++++++++++
|
||||
2 files changed, 115 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
|
||||
index e30d7235b81b..fb0a47dc9dc4 100644
|
||||
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
|
||||
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
|
||||
@@ -9044,7 +9044,7 @@ static unsigned detectEvenOddMultiplyOperand(const SelectionDAG &DAG,
|
||||
if (unsigned(ShuffleMask[Elt]) != 2 * Elt)
|
||||
CanUseEven = false;
|
||||
if (unsigned(ShuffleMask[Elt]) != 2 * Elt + 1)
|
||||
- CanUseEven = true;
|
||||
+ CanUseOdd = false;
|
||||
}
|
||||
Op = Op.getOperand(0);
|
||||
if (CanUseEven)
|
||||
diff --git a/llvm/test/CodeGen/SystemZ/vec-mul-07.ll b/llvm/test/CodeGen/SystemZ/vec-mul-07.ll
|
||||
index 73c7a8dec5df..583561625cfc 100644
|
||||
--- a/llvm/test/CodeGen/SystemZ/vec-mul-07.ll
|
||||
+++ b/llvm/test/CodeGen/SystemZ/vec-mul-07.ll
|
||||
@@ -3,6 +3,23 @@
|
||||
;
|
||||
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
|
||||
|
||||
+; Test a v16i8 -> v8i16 unsigned widening multiplication
|
||||
+; which is not folded into an even/odd widening operation.
|
||||
+define <8 x i16> @f1_not(<16 x i8> %val1, <16 x i8> %val2) {
|
||||
+; CHECK-LABEL: f1_not:
|
||||
+; CHECK: # %bb.0:
|
||||
+; CHECK-NEXT: vuplhb %v0, %v24
|
||||
+; CHECK-NEXT: vuplhb %v1, %v26
|
||||
+; CHECK-NEXT: vmlhw %v24, %v0, %v1
|
||||
+; CHECK-NEXT: br %r14
|
||||
+ %shuf1 = shufflevector <16 x i8> %val1, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
||||
+ %zext1 = zext <8 x i8> %shuf1 to <8 x i16>
|
||||
+ %shuf2 = shufflevector <16 x i8> %val2, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
||||
+ %zext2 = zext <8 x i8> %shuf2 to <8 x i16>
|
||||
+ %ret = mul <8 x i16> %zext1, %zext2
|
||||
+ ret <8 x i16> %ret
|
||||
+}
|
||||
+
|
||||
; Test a v16i8 (even) -> v8i16 unsigned widening multiplication.
|
||||
define <8 x i16> @f1(<16 x i8> %val1, <16 x i8> %val2) {
|
||||
; CHECK-LABEL: f1:
|
||||
@@ -31,6 +48,23 @@ define <8 x i16> @f2(<16 x i8> %val1, <16 x i8> %val2) {
|
||||
ret <8 x i16> %ret
|
||||
}
|
||||
|
||||
+; Test a v16i8 -> v8i16 signed widening multiplication
|
||||
+; which is not folded into an even/odd widening operation.
|
||||
+define <8 x i16> @f3_not(<16 x i8> %val1, <16 x i8> %val2) {
|
||||
+; CHECK-LABEL: f3_not:
|
||||
+; CHECK: # %bb.0:
|
||||
+; CHECK-NEXT: vuphb %v0, %v26
|
||||
+; CHECK-NEXT: vuphb %v1, %v24
|
||||
+; CHECK-NEXT: vmlhw %v24, %v1, %v0
|
||||
+; CHECK-NEXT: br %r14
|
||||
+ %shuf1 = shufflevector <16 x i8> %val1, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
||||
+ %sext1 = sext <8 x i8> %shuf1 to <8 x i16>
|
||||
+ %shuf2 = shufflevector <16 x i8> %val2, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
||||
+ %sext2 = sext <8 x i8> %shuf2 to <8 x i16>
|
||||
+ %ret = mul <8 x i16> %sext1, %sext2
|
||||
+ ret <8 x i16> %ret
|
||||
+}
|
||||
+
|
||||
; Test a v16i8 (even) -> v8i16 signed widening multiplication.
|
||||
define <8 x i16> @f3(<16 x i8> %val1, <16 x i8> %val2) {
|
||||
; CHECK-LABEL: f3:
|
||||
@@ -59,6 +93,23 @@ define <8 x i16> @f4(<16 x i8> %val1, <16 x i8> %val2) {
|
||||
ret <8 x i16> %ret
|
||||
}
|
||||
|
||||
+; Test a v8i16 -> v4i32 unsigned widening multiplication
|
||||
+; which is not folded into an even/odd widening operation.
|
||||
+define <4 x i32> @f5_not(<8 x i16> %val1, <8 x i16> %val2) {
|
||||
+; CHECK-LABEL: f5_not:
|
||||
+; CHECK: # %bb.0:
|
||||
+; CHECK-NEXT: vuplhh %v0, %v24
|
||||
+; CHECK-NEXT: vuplhh %v1, %v26
|
||||
+; CHECK-NEXT: vmlf %v24, %v0, %v1
|
||||
+; CHECK-NEXT: br %r14
|
||||
+ %shuf1 = shufflevector <8 x i16> %val1, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
||||
+ %zext1 = zext <4 x i16> %shuf1 to <4 x i32>
|
||||
+ %shuf2 = shufflevector <8 x i16> %val2, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
||||
+ %zext2 = zext <4 x i16> %shuf2 to <4 x i32>
|
||||
+ %ret = mul <4 x i32> %zext1, %zext2
|
||||
+ ret <4 x i32> %ret
|
||||
+}
|
||||
+
|
||||
; Test a v8i16 (even) -> v4i32 unsigned widening multiplication.
|
||||
define <4 x i32> @f5(<8 x i16> %val1, <8 x i16> %val2) {
|
||||
; CHECK-LABEL: f5:
|
||||
@@ -87,6 +138,23 @@ define <4 x i32> @f6(<8 x i16> %val1, <8 x i16> %val2) {
|
||||
ret <4 x i32> %ret
|
||||
}
|
||||
|
||||
+; Test a v8i16 -> v4i32 signed widening multiplication
|
||||
+; which is not folded into an even/odd widening operation.
|
||||
+define <4 x i32> @f7_not(<8 x i16> %val1, <8 x i16> %val2) {
|
||||
+; CHECK-LABEL: f7_not:
|
||||
+; CHECK: # %bb.0:
|
||||
+; CHECK-NEXT: vuphh %v0, %v26
|
||||
+; CHECK-NEXT: vuphh %v1, %v24
|
||||
+; CHECK-NEXT: vmlf %v24, %v1, %v0
|
||||
+; CHECK-NEXT: br %r14
|
||||
+ %shuf1 = shufflevector <8 x i16> %val1, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
||||
+ %sext1 = sext <4 x i16> %shuf1 to <4 x i32>
|
||||
+ %shuf2 = shufflevector <8 x i16> %val2, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
||||
+ %sext2 = sext <4 x i16> %shuf2 to <4 x i32>
|
||||
+ %ret = mul <4 x i32> %sext1, %sext2
|
||||
+ ret <4 x i32> %ret
|
||||
+}
|
||||
+
|
||||
; Test a v8i16 (even) -> v4i32 signed widening multiplication.
|
||||
define <4 x i32> @f7(<8 x i16> %val1, <8 x i16> %val2) {
|
||||
; CHECK-LABEL: f7:
|
||||
@@ -115,6 +183,29 @@ define <4 x i32> @f8(<8 x i16> %val1, <8 x i16> %val2) {
|
||||
ret <4 x i32> %ret
|
||||
}
|
||||
|
||||
+; Test a v4i32 -> v2i64 unsigned widening multiplication
|
||||
+; which is not folded into an even/odd widening operation.
|
||||
+define <2 x i64> @f9_not(<4 x i32> %val1, <4 x i32> %val2) {
|
||||
+; CHECK-LABEL: f9_not:
|
||||
+; CHECK: # %bb.0:
|
||||
+; CHECK-NEXT: vuplhf %v0, %v24
|
||||
+; CHECK-NEXT: vuplhf %v1, %v26
|
||||
+; CHECK-NEXT: vlgvg %r0, %v1, 1
|
||||
+; CHECK-NEXT: vlgvg %r1, %v0, 1
|
||||
+; CHECK-NEXT: msgr %r1, %r0
|
||||
+; CHECK-NEXT: vlgvg %r0, %v1, 0
|
||||
+; CHECK-NEXT: vlgvg %r2, %v0, 0
|
||||
+; CHECK-NEXT: msgr %r2, %r0
|
||||
+; CHECK-NEXT: vlvgp %v24, %r2, %r1
|
||||
+; CHECK-NEXT: br %r14
|
||||
+ %shuf1 = shufflevector <4 x i32> %val1, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
|
||||
+ %zext1 = zext <2 x i32> %shuf1 to <2 x i64>
|
||||
+ %shuf2 = shufflevector <4 x i32> %val2, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
|
||||
+ %zext2 = zext <2 x i32> %shuf2 to <2 x i64>
|
||||
+ %ret = mul <2 x i64> %zext1, %zext2
|
||||
+ ret <2 x i64> %ret
|
||||
+}
|
||||
+
|
||||
; Test a v4i32 (even) -> v2i64 unsigned widening multiplication.
|
||||
define <2 x i64> @f9(<4 x i32> %val1, <4 x i32> %val2) {
|
||||
; CHECK-LABEL: f9:
|
||||
@@ -143,6 +234,29 @@ define <2 x i64> @f10(<4 x i32> %val1, <4 x i32> %val2) {
|
||||
ret <2 x i64> %ret
|
||||
}
|
||||
|
||||
+; Test a v4i32 -> v2i64 signed widening multiplication
|
||||
+; which is not folded into an even/odd widening operation.
|
||||
+define <2 x i64> @f11_not(<4 x i32> %val1, <4 x i32> %val2) {
|
||||
+; CHECK-LABEL: f11_not:
|
||||
+; CHECK: # %bb.0:
|
||||
+; CHECK-NEXT: vuphf %v0, %v24
|
||||
+; CHECK-NEXT: vuphf %v1, %v26
|
||||
+; CHECK-NEXT: vlgvg %r0, %v1, 1
|
||||
+; CHECK-NEXT: vlgvg %r1, %v0, 1
|
||||
+; CHECK-NEXT: msgr %r1, %r0
|
||||
+; CHECK-NEXT: vlgvg %r0, %v1, 0
|
||||
+; CHECK-NEXT: vlgvg %r2, %v0, 0
|
||||
+; CHECK-NEXT: msgr %r2, %r0
|
||||
+; CHECK-NEXT: vlvgp %v24, %r2, %r1
|
||||
+; CHECK-NEXT: br %r14
|
||||
+ %shuf1 = shufflevector <4 x i32> %val1, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
|
||||
+ %sext1 = sext <2 x i32> %shuf1 to <2 x i64>
|
||||
+ %shuf2 = shufflevector <4 x i32> %val2, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
|
||||
+ %sext2 = sext <2 x i32> %shuf2 to <2 x i64>
|
||||
+ %ret = mul <2 x i64> %sext1, %sext2
|
||||
+ ret <2 x i64> %ret
|
||||
+}
|
||||
+
|
||||
; Test a v4i32 (even) -> v2i64 signed widening multiplication.
|
||||
define <2 x i64> @f11(<4 x i32> %val1, <4 x i32> %val2) {
|
||||
; CHECK-LABEL: f11:
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -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
|
||||
|
||||
276
SOURCES/43cb4631c1f42dbfce78288b8ae30b5840ed59b3.patch
Normal file
276
SOURCES/43cb4631c1f42dbfce78288b8ae30b5840ed59b3.patch
Normal file
@ -0,0 +1,276 @@
|
||||
From 43cb4631c1f42dbfce78288b8ae30b5840ed59b3 Mon Sep 17 00:00:00 2001
|
||||
From: Ebuka Ezike <yerimyah1@gmail.com>
|
||||
Date: Thu, 8 Jan 2026 18:46:03 +0000
|
||||
Subject: [PATCH] [lldb] Fix typed commands not shown on the screen (#174216)
|
||||
|
||||
The cause is that in `python3.14`, `fcntl.ioctl` now throws a buffer
|
||||
overflow error
|
||||
when the buffer is too small or too large (see
|
||||
https://github.com/python/cpython/pull/132919). This caused the Python
|
||||
interpreter to fail terminal detection and not properly echo user
|
||||
commands back to the screen.
|
||||
|
||||
Fix by dropping the custom terminal size check entirely and using the
|
||||
built-in `sys.stdin.isatty()` instead.
|
||||
|
||||
Fixes #173302
|
||||
---
|
||||
.../Python/lldbsuite/test/lldbpexpect.py | 1 +
|
||||
.../Interpreter/embedded_interpreter.py | 59 +++---------------
|
||||
.../python_api/file_handle/TestFileHandle.py | 48 +++++++++++++-
|
||||
.../API/terminal/TestPythonInterpreterEcho.py | 62 +++++++++++++++++++
|
||||
.../Shell/ScriptInterpreter/Python/io.test | 12 ++++
|
||||
5 files changed, 131 insertions(+), 51 deletions(-)
|
||||
create mode 100644 lldb/test/API/terminal/TestPythonInterpreterEcho.py
|
||||
create mode 100644 lldb/test/Shell/ScriptInterpreter/Python/io.test
|
||||
|
||||
diff --git a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
|
||||
index 3279e1fd39f8c..03b2500fbda52 100644
|
||||
--- a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
|
||||
+++ b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
|
||||
@skipIfRemote
|
||||
+@skipIfWindows
|
||||
@add_test_categories(["pexpect"])
|
||||
class PExpectTest(TestBase):
|
||||
NO_DEBUG_INFO_TESTCASE = True
|
||||
diff --git a/lldb/source/Interpreter/embedded_interpreter.py b/lldb/source/Interpreter/embedded_interpreter.py
|
||||
index 42a9ab5fc367a..12c47bd712816 100644
|
||||
--- a/lldb/source/Interpreter/embedded_interpreter.py
|
||||
+++ b/lldb/source/Interpreter/embedded_interpreter.py
|
||||
@@ -32,18 +32,6 @@ def is_libedit():
|
||||
g_run_one_line_str = None
|
||||
|
||||
|
||||
-def get_terminal_size(fd):
|
||||
- try:
|
||||
- import fcntl
|
||||
- import termios
|
||||
- import struct
|
||||
-
|
||||
- hw = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))
|
||||
- except:
|
||||
- hw = (0, 0)
|
||||
- return hw
|
||||
-
|
||||
-
|
||||
class LLDBExit(SystemExit):
|
||||
pass
|
||||
|
||||
@@ -74,50 +62,21 @@ def readfunc_stdio(prompt):
|
||||
def run_python_interpreter(local_dict):
|
||||
# Pass in the dictionary, for continuity from one session to the next.
|
||||
try:
|
||||
- fd = sys.stdin.fileno()
|
||||
- interacted = False
|
||||
- if get_terminal_size(fd)[1] == 0:
|
||||
- try:
|
||||
- import termios
|
||||
-
|
||||
- old = termios.tcgetattr(fd)
|
||||
- if old[3] & termios.ECHO:
|
||||
- # Need to turn off echoing and restore
|
||||
- new = termios.tcgetattr(fd)
|
||||
- new[3] = new[3] & ~termios.ECHO
|
||||
- try:
|
||||
- termios.tcsetattr(fd, termios.TCSADRAIN, new)
|
||||
- interacted = True
|
||||
- code.interact(
|
||||
- banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.",
|
||||
- readfunc=readfunc_stdio,
|
||||
- local=local_dict,
|
||||
- )
|
||||
- finally:
|
||||
- termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
||||
- except:
|
||||
- pass
|
||||
- # Don't need to turn off echoing
|
||||
- if not interacted:
|
||||
- code.interact(
|
||||
- banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
|
||||
- readfunc=readfunc_stdio,
|
||||
- local=local_dict,
|
||||
- )
|
||||
- else:
|
||||
- # We have a real interactive terminal
|
||||
- code.interact(
|
||||
- banner="Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.",
|
||||
- readfunc=readfunc,
|
||||
- local=local_dict,
|
||||
- )
|
||||
+ banner = "Python Interactive Interpreter. To exit, type 'quit()', 'exit()'."
|
||||
+ input_func = readfunc_stdio
|
||||
+
|
||||
+ is_atty = sys.stdin.isatty()
|
||||
+ if is_atty:
|
||||
+ banner = "Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D."
|
||||
+ input_func = readfunc
|
||||
+
|
||||
+ code.interact(banner=banner, readfunc=input_func, local=local_dict)
|
||||
except LLDBExit:
|
||||
pass
|
||||
except SystemExit as e:
|
||||
if e.code:
|
||||
print("Script exited with code %s" % e.code)
|
||||
|
||||
-
|
||||
def run_one_line(local_dict, input_string):
|
||||
global g_run_one_line_str
|
||||
try:
|
||||
diff --git a/lldb/test/API/python_api/file_handle/TestFileHandle.py b/lldb/test/API/python_api/file_handle/TestFileHandle.py
|
||||
index b38585577f6f6..707044a3afb0f 100644
|
||||
--- a/lldb/test/API/python_api/file_handle/TestFileHandle.py
|
||||
+++ b/lldb/test/API/python_api/file_handle/TestFileHandle.py
|
||||
@@ -111,10 +111,11 @@ def setUp(self):
|
||||
super(FileHandleTestCase, self).setUp()
|
||||
self.out_filename = self.getBuildArtifact("output")
|
||||
self.in_filename = self.getBuildArtifact("input")
|
||||
+ self.err_filename = self.getBuildArtifact("error")
|
||||
|
||||
def tearDown(self):
|
||||
super(FileHandleTestCase, self).tearDown()
|
||||
- for name in (self.out_filename, self.in_filename):
|
||||
+ for name in (self.out_filename, self.in_filename, self.err_filename):
|
||||
if os.path.exists(name):
|
||||
os.unlink(name)
|
||||
|
||||
@@ -679,6 +680,51 @@ def test_stdout_file(self):
|
||||
lines = [x for x in f.read().strip().split() if x != "7"]
|
||||
self.assertEqual(lines, ["foobar"])
|
||||
|
||||
+ def test_stdout_file_interactive(self):
|
||||
+ """Ensure when we read stdin from a file, outputs from python goes to the right I/O stream."""
|
||||
+ with open(self.in_filename, "w") as f:
|
||||
+ f.write(
|
||||
+ "script --language python --\nvalue = 250 + 5\nprint(value)\nprint(vel)"
|
||||
+ )
|
||||
+
|
||||
+ with open(self.out_filename, "w") as outf, open(
|
||||
+ self.in_filename, "r"
|
||||
+ ) as inf, open(self.err_filename, "w") as errf:
|
||||
+ status = self.dbg.SetOutputFile(lldb.SBFile(outf))
|
||||
+ self.assertSuccess(status)
|
||||
+ status = self.dbg.SetErrorFile(lldb.SBFile(errf))
|
||||
+ self.assertSuccess(status)
|
||||
+ status = self.dbg.SetInputFile(lldb.SBFile(inf))
|
||||
+ self.assertSuccess(status)
|
||||
+ auto_handle_events = True
|
||||
+ spawn_thread = False
|
||||
+ num_errs = 0
|
||||
+ quit_requested = False
|
||||
+ stopped_for_crash = False
|
||||
+ opts = lldb.SBCommandInterpreterRunOptions()
|
||||
+ self.dbg.RunCommandInterpreter(
|
||||
+ auto_handle_events,
|
||||
+ spawn_thread,
|
||||
+ opts,
|
||||
+ num_errs,
|
||||
+ quit_requested,
|
||||
+ stopped_for_crash,
|
||||
+ )
|
||||
+ self.dbg.GetOutputFile().Flush()
|
||||
+ expected_out_text = "255"
|
||||
+ expected_err_text = "NameError"
|
||||
+ # check stdout
|
||||
+ with open(self.out_filename, "r") as f:
|
||||
+ out_text = f.read()
|
||||
+ self.assertIn(expected_out_text, out_text)
|
||||
+ self.assertNotIn(expected_err_text, out_text)
|
||||
+
|
||||
+ # check stderr
|
||||
+ with open(self.err_filename, "r") as f:
|
||||
+ err_text = f.read()
|
||||
+ self.assertIn(expected_err_text, err_text)
|
||||
+ self.assertNotIn(expected_out_text, err_text)
|
||||
+
|
||||
def test_identity(self):
|
||||
f = io.StringIO()
|
||||
sbf = lldb.SBFile(f)
|
||||
diff --git a/lldb/test/API/terminal/TestPythonInterpreterEcho.py b/lldb/test/API/terminal/TestPythonInterpreterEcho.py
|
||||
new file mode 100644
|
||||
index 0000000000000..758a4f9cede5a
|
||||
--- /dev/null
|
||||
+++ b/lldb/test/API/terminal/TestPythonInterpreterEcho.py
|
||||
@@ -0,0 +1,62 @@
|
||||
+"""
|
||||
+Test that typing python expression in the terminal is echoed back to stdout.
|
||||
+"""
|
||||
+
|
||||
+from lldbsuite.test.decorators import skipIfAsan
|
||||
+from lldbsuite.test.lldbpexpect import PExpectTest
|
||||
+
|
||||
+
|
||||
+@skipIfAsan
|
||||
+class PythonInterpreterEchoTest(PExpectTest):
|
||||
+ PYTHON_PROMPT = ">>> "
|
||||
+
|
||||
+ def verify_command_echo(
|
||||
+ self, command: str, expected_output: str = "", is_regex: bool = False
|
||||
+ ):
|
||||
+ assert self.child != None
|
||||
+ child = self.child
|
||||
+ self.assertIsNotNone(self.child, "expected a running lldb process.")
|
||||
+
|
||||
+ child.sendline(command)
|
||||
+
|
||||
+ # Build pattern list: match whichever comes first (output or prompt).
|
||||
+ # This prevents waiting for a timeout if there's no match.
|
||||
+ pattern = []
|
||||
+ match_expected = expected_output and len(expected_output) > 0
|
||||
+
|
||||
+ if match_expected:
|
||||
+ pattern.append(expected_output)
|
||||
+ pattern.append(self.PYTHON_PROMPT)
|
||||
+
|
||||
+ expect_func = child.expect if is_regex else child.expect_exact
|
||||
+ match_idx = expect_func(pattern)
|
||||
+ if match_expected:
|
||||
+ self.assertEqual(
|
||||
+ match_idx, 0, "Expected output `{expected_output}` in stdout."
|
||||
+ )
|
||||
+
|
||||
+ self.assertIsNotNone(self.child.before, "Expected output before prompt")
|
||||
+ self.assertIsInstance(self.child.before, bytes)
|
||||
+ echoed_text: str = self.child.before.decode("ascii").strip()
|
||||
+ self.assertEqual(
|
||||
+ command, echoed_text, f"Command '{command}' should be echoed to stdout."
|
||||
+ )
|
||||
+
|
||||
+ if match_expected:
|
||||
+ child.expect_exact(self.PYTHON_PROMPT)
|
||||
+
|
||||
+ def test_python_interpreter_echo(self):
|
||||
+ """Test that that the user typed commands is echoed to stdout"""
|
||||
+
|
||||
+ self.launch(use_colors=False, dimensions=(100, 100))
|
||||
+
|
||||
+ # Enter the python interpreter.
|
||||
+ self.verify_command_echo(
|
||||
+ "script --language python --", expected_output="Python.*\\.", is_regex=True
|
||||
+ )
|
||||
+ self.child_in_script_interpreter = True
|
||||
+
|
||||
+ self.verify_command_echo("val = 300")
|
||||
+ self.verify_command_echo(
|
||||
+ "print('result =', 300)", expected_output="result = 300"
|
||||
+ )
|
||||
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/io.test b/lldb/test/Shell/ScriptInterpreter/Python/io.test
|
||||
new file mode 100644
|
||||
index 0000000000000..25e3de41724e0
|
||||
--- /dev/null
|
||||
+++ b/lldb/test/Shell/ScriptInterpreter/Python/io.test
|
||||
@@ -0,0 +1,12 @@
|
||||
+# RUN: rm -rf %t.stdout %t.stderr
|
||||
+# RUN: cat %s | %lldb --script-language python > %t.stdout 2> %t.stderr
|
||||
+# RUN: cat %t.stdout | FileCheck %s --check-prefix STDOUT
|
||||
+# RUN: cat %t.stderr | FileCheck %s --check-prefix STDERR
|
||||
+script
|
||||
+variable = 300
|
||||
+print(variable)
|
||||
+print(not_value)
|
||||
+quit
|
||||
+
|
||||
+# STDOUT: 300
|
||||
+# STDERR: NameError{{.*}}is not defined
|
||||
697
SPECS/llvm.spec
697
SPECS/llvm.spec
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user