[llvm-branch-commits] [llvm] [PowerPC] Implement paddis (PR #161572)
https://github.com/lei137 updated
https://github.com/llvm/llvm-project/pull/161572
>From ea6d743c7a6c572053b360fc4eee2dedad681b21 Mon Sep 17 00:00:00 2001
From: Lei Huang
Date: Tue, 30 Sep 2025 18:09:31 +
Subject: [PATCH 1/2] [PowerPC] Implement paddis
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 7 +++
.../PowerPC/MCTargetDesc/PPCAsmBackend.cpp| 9
.../PowerPC/MCTargetDesc/PPCFixupKinds.h | 6 +++
.../PowerPC/MCTargetDesc/PPCInstPrinter.cpp | 12 +
.../PowerPC/MCTargetDesc/PPCInstPrinter.h | 2 +
.../PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 1 +
llvm/lib/Target/PowerPC/PPCInstrFuture.td | 44 +++
llvm/lib/Target/PowerPC/PPCRegisterInfo.td| 19
.../PowerPC/ppc-encoding-ISAFuture.txt| 6 +++
.../PowerPC/ppc64le-encoding-ISAFuture.txt| 6 +++
llvm/test/MC/PowerPC/ppc-encoding-ISAFuture.s | 8
11 files changed, 120 insertions(+)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 1fc475dc6cb7e..d09bd9d38d585 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -388,6 +388,13 @@ struct PPCOperand : public MCParsedAsmOperand {
return Kind == Expression ||
(Kind == Immediate && isInt<34>(getImm()) && (getImm() & 15) == 0);
}
+
+ bool isS32Imm() const {
+// Once the PC-Rel ABI is finalized, evaluate whether a 32-bit
+// ContextImmediate is needed.
+return Kind == Expression || (Kind == Immediate && isInt<32>(getImm()));
+ }
+
bool isS34Imm() const {
// Once the PC-Rel ABI is finalized, evaluate whether a 34-bit
// ContextImmediate is needed.
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
index 04b886ae74993..558351b515a2e 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
@@ -47,6 +47,9 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t
Value) {
case PPC::fixup_ppc_half16ds:
case PPC::fixup_ppc_half16dq:
return Value & 0xfffc;
+ case PPC::fixup_ppc_pcrel32:
+ case PPC::fixup_ppc_imm32:
+return Value & 0x;
case PPC::fixup_ppc_pcrel34:
case PPC::fixup_ppc_imm34:
return Value & 0x3;
@@ -71,6 +74,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case PPC::fixup_ppc_br24abs:
case PPC::fixup_ppc_br24_notoc:
return 4;
+ case PPC::fixup_ppc_pcrel32:
+ case PPC::fixup_ppc_imm32:
case PPC::fixup_ppc_pcrel34:
case PPC::fixup_ppc_imm34:
case FK_Data_8:
@@ -154,6 +159,8 @@ MCFixupKindInfo PPCAsmBackend::getFixupKindInfo(MCFixupKind
Kind) const {
{"fixup_ppc_brcond14abs", 16, 14, 0},
{"fixup_ppc_half16", 0, 16, 0},
{"fixup_ppc_half16ds", 0, 14, 0},
+ {"fixup_ppc_pcrel32", 0, 32, 0},
+ {"fixup_ppc_imm32", 0, 32, 0},
{"fixup_ppc_pcrel34", 0, 34, 0},
{"fixup_ppc_imm34", 0, 34, 0},
{"fixup_ppc_nofixup", 0, 0, 0}};
@@ -166,6 +173,8 @@ MCFixupKindInfo PPCAsmBackend::getFixupKindInfo(MCFixupKind
Kind) const {
{"fixup_ppc_brcond14abs", 2, 14, 0},
{"fixup_ppc_half16", 0, 16, 0},
{"fixup_ppc_half16ds", 2, 14, 0},
+ {"fixup_ppc_pcrel32", 0, 32, 0},
+ {"fixup_ppc_imm32", 0, 32, 0},
{"fixup_ppc_pcrel34", 0, 34, 0},
{"fixup_ppc_imm34", 0, 34, 0},
{"fixup_ppc_nofixup", 0, 0, 0}};
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
index df0c666f5b113..4164b697649cd 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
@@ -40,6 +40,12 @@ enum Fixups {
/// instrs like 'std'.
fixup_ppc_half16ds,
+ // A 32-bit fixup corresponding to PC-relative paddis.
+ fixup_ppc_pcrel32,
+
+ // A 32-bit fixup corresponding to Non-PC-relative paddis.
+ fixup_ppc_imm32,
+
// A 34-bit fixup corresponding to PC-relative paddi.
fixup_ppc_pcrel34,
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
index b27bc3bd49315..e2afb9378cbf0 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
@@ -430,6 +430,18 @@ void PPCInstPrinter::printS16ImmOperand(const MCInst *MI,
unsigned OpNo,
printOperand(MI, OpNo, STI, O);
}
+void PPCInstPrinter::printS32ImmOperand(const MCInst *MI, unsigned OpNo,
+const MCSubtargetInfo &STI,
+raw_ostream &O) {
+ if (MI->getOperand(OpNo).isImm()) {
+long long Value = MI->getOperand(OpNo).getImm();
+assert(isInt<32>(Value) && "Invalid s32imm argument!");
+O << (long long)Value;
+ }
+ else
+printOperand(MI
[llvm-branch-commits] [clang] release/21.x: [clang-format] Fix bugs in annotating arrows and square… (PR #161052)
https://github.com/dyung closed https://github.com/llvm/llvm-project/pull/161052 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lldb] release/21.x: [LLDB][ProcessWindows] Set exit status on instance rather than going through all targets (#159308) (PR #161541)
https://github.com/llvmbot milestoned https://github.com/llvm/llvm-project/pull/161541 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lldb] release/21.x: [LLDB][ProcessWindows] Set exit status on instance rather than going through all targets (#159308) (PR #161541)
https://github.com/llvmbot created
https://github.com/llvm/llvm-project/pull/161541
Backport a868f28c6e9beecb2b3fbe8acfbe0d272fabd14d
Requested by: @Nerixyz
>From 90a7797ad1a4f78bd8c120f8355b39525cd17b79 Mon Sep 17 00:00:00 2001
From: nerix
Date: Thu, 18 Sep 2025 11:27:25 +0200
Subject: [PATCH] [LLDB][ProcessWindows] Set exit status on instance rather
than going through all targets (#159308)
When quitting LLDB on Windows while a process was still running, LLDB
would take unusually long to exit. This was due to a temporary deadlock:
The main thread was destroying the processes. In doing so, it iterated
over the target list:
https://github.com/llvm/llvm-project/blob/88c64f76ed2ca226da99b99f60d316b1519fc7d8/lldb/source/Core/Debugger.cpp#L1095-L1098
This locks the list for the whole iteration. Finalizing the process
would eventually lead to `DebuggerThread::StopDebugging`, which
terminates the process and waits for it to exit:
https://github.com/llvm/llvm-project/blob/88c64f76ed2ca226da99b99f60d316b1519fc7d8/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp#L196
The debugger loop (on a separate thread) would see that the process
exited and call
[`ProcessWindows::OnExitProcess`](https://github.com/llvm/llvm-project/blob/88c64f76ed2ca226da99b99f60d316b1519fc7d8/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp#L656-L673).
This calls the static function
[`Process::SetProcessExitStatus`](https://github.com/llvm/llvm-project/blob/0a7a7d56fc882653335beba0d1f8ea9f26089c22/lldb/source/Target/Process.cpp#L1098-L1126).
This tries to find the process by its ID from the debugger's target
list. Doing so requires locking the list, so the debugger thread would
then be stuck on
https://github.com/llvm/llvm-project/blob/0a7a7d56fc882653335beba0d1f8ea9f26089c22/lldb/source/Target/TargetList.cpp#L403
After 5s, the main thread would give up waiting. So every exit where the
process was still running would be delayed by about 5s.
Since `ProcessWindows` would find itself when calling
`SetProcessExitStatus`, we can call `SetExitStatus` directly.
This can also make some tests run faster. For example, the DIA PDB tests
previously took 15s to run on my PC (24 jobs) and now take 5s. For all
shell tests, the difference isn't that big (only about 3s), because most
don't run into this and the tests run in parallel.
(cherry picked from commit a868f28c6e9beecb2b3fbe8acfbe0d272fabd14d)
---
lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 27530f032ce51..0fecefe23b88e 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -666,7 +666,7 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) {
target->ModulesDidUnload(unloaded_modules, true);
}
- SetProcessExitStatus(GetID(), true, 0, exit_code);
+ SetExitStatus(exit_code, /*exit_string=*/"");
SetPrivateState(eStateExited);
ProcessDebugger::OnExitProcess(exit_code);
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lld] d1e2f89 - [LLD] [COFF] Fix symbol names for import thunks (#160694)
Author: Martin Storsjö
Date: 2025-10-01T15:13:48Z
New Revision: d1e2f8916128c8c8f402565b0612f6b6e5566702
URL:
https://github.com/llvm/llvm-project/commit/d1e2f8916128c8c8f402565b0612f6b6e5566702
DIFF:
https://github.com/llvm/llvm-project/commit/d1e2f8916128c8c8f402565b0612f6b6e5566702.diff
LOG: [LLD] [COFF] Fix symbol names for import thunks (#160694)
9cc9efc483339ece1d52923569bb755db42b69f3 changed LLD to use a
StringTableBuilder for optimizing the string table, used for long
section and symbol names.
That commit had a bug, where the symbol table entry for an import thunk
with a long symbol name wouldn't get fetched from the
StringTableBuilder, if the base symbol name (without the "__imp_"
prefix) wasn't over 8 chars.
This should fix issues with Go, which errors out on reading the
executables with a broken symbol table, as noted in
https://github.com/mstorsjo/llvm-mingw/issues/518 and
https://github.com/golang/go/issues/75219.
(cherry picked from commit 0d6af2db6cd9c964ff300e5b5246c070a57d45e2)
Added:
Modified:
lld/COFF/Writer.cpp
lld/test/COFF/strtab.s
Removed:
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 076561807af47..ef9d051bf976e 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1553,7 +1553,7 @@ void Writer::createSymbolAndStringTable() {
dthunk->wrappedSym->writtenToSymtab = true;
if (std::optional sym =
createSymbol(dthunk->wrappedSym)) {
- if (d->getName().size() > COFF::NameSize)
+ if (dthunk->wrappedSym->getName().size() > COFF::NameSize)
longNameSymbols.emplace_back(outputSymtab.size(),
dthunk->wrappedSym->getName());
outputSymtab.push_back(*sym);
diff --git a/lld/test/COFF/strtab.s b/lld/test/COFF/strtab.s
index fbdd8df52d540..9edc13e19e825 100644
--- a/lld/test/COFF/strtab.s
+++ b/lld/test/COFF/strtab.s
@@ -1,17 +1,32 @@
# REQUIRES: x86
# RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.obj
-# RUN: lld-link -out:%t.exe -entry:main %t.obj -debug:dwarf
+# RUN: lld-link -machine:x64 -def:%S/Inputs/library.def -implib:%t.lib
+# RUN: lld-link -out:%t.exe -entry:main %t.obj %t.lib -debug:dwarf
# RUN: llvm-readobj --string-table %t.exe | FileCheck %s
+# RUN: llvm-nm %t.exe | FileCheck %s --check-prefix=SYMBOLS
+
+# Note, for this test to have the intended test coverage, the imported symbol
+# "function" needs to be such that the symbol name itself is <= 8 chars, while
+# "__imp_"+name is >8 chars.
# CHECK: StringTable {
-# CHECK-NEXT: Length: 87
+# CHECK-NEXT: Length: 102
# CHECK-NEXT: [ 4] .debug_abbrev
# CHECK-NEXT: [12] .debug_line
# CHECK-NEXT: [1e] long_name_symbolz
# CHECK-NEXT: [30] .debug_abbrez
-# CHECK-NEXT: [3e] __impl_long_name_symbolA
+# CHECK-NEXT: [3e] __imp_function
+# CHECK-NEXT: [4d] __impl_long_name_symbolA
# CHECK-NEXT: }
+# SYMBOLS: 140001000 N .debug_abbrez
+# SYMBOLS-NEXT: 140002070 R __imp_function
+# SYMBOLS-NEXT: 140001000 t __impl_long_name_symbolA
+# SYMBOLS-NEXT: 140001010 T function
+# SYMBOLS-NEXT: 140001000 t long_name_symbolA
+# SYMBOLS-NEXT: 140001000 t long_name_symbolz
+# SYMBOLS-NEXT: 140001000 T main
+# SYMBOLS-NEXT: 140001000 t name_symbolA
.global main
.text
@@ -21,6 +36,7 @@ long_name_symbolA:
__impl_long_name_symbolA:
name_symbolA:
.debug_abbrez:
+ call function
ret
.section.debug_abbrev,"dr"
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lld] release/21.x: [LLD] [COFF] Fix symbol names for import thunks (#160694) (PR #160770)
github-actions[bot] wrote: @mstorsjo (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. https://github.com/llvm/llvm-project/pull/160770 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/21.x: [Mips] Fix atomic min/max generate mips4 instructions when compiling for mips2 (#159717) (PR #160807)
https://github.com/dyung updated https://github.com/llvm/llvm-project/pull/160807 >From 559d966bcb54e54d03ff29a2086cbc0f15910683 Mon Sep 17 00:00:00 2001 From: yingopq <[email protected]> Date: Fri, 26 Sep 2025 11:29:13 +0800 Subject: [PATCH] [Mips] Fix atomic min/max generate mips4 instructions when compiling for mips2 (#159717) Modify instr movn/movz to mixture of beq, move, and sc. Because atomic-min-max.ll test broken on the expensive builder, I revert https://github.com/llvm/llvm-project/pull/149983 and resubmit this PR. The broken reason: In i16/i8 function expandAtomicBinOpSubword, we use two successor after loop2MBB, one does not specify the second parameter, the other use BranchProbability::getOne() that means 100% probability. This is contradictory. And the second successor is also specified incorrectly. The changess: * llvm/lib/Target/Mips/MipsExpandPseudo.cpp: Change loop2MBB`s second successor to correct one and delete the second parameter BranchProbability::getOne(). * llvm/test/CodeGen/Mips/atomic-min-max.ll: Add -verify-machineinstrs option in RUN command; Modify i16 test and i8 test according to the changes. Fix #145411. (cherry picked from commit 114b3b8b04fe5aae4143e30078637015a9e077ce) --- llvm/lib/Target/Mips/MipsExpandPseudo.cpp | 217 +++-- llvm/test/CodeGen/Mips/atomic-min-max.ll | 521 ++ 2 files changed, 712 insertions(+), 26 deletions(-) diff --git a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp index 34ff41f6e02da..78f2e5db40f9d 100644 --- a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp @@ -432,13 +432,24 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( Register OldVal = I->getOperand(6).getReg(); Register BinOpRes = I->getOperand(7).getReg(); Register StoreVal = I->getOperand(8).getReg(); + bool NoMovnInstr = (IsMin || IsMax) && !STI->hasMips4() && !STI->hasMips32(); const BasicBlock *LLVM_BB = BB.getBasicBlock(); MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop1MBB = nullptr; + MachineBasicBlock *loop2MBB = nullptr; + if (NoMovnInstr) { +loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); +loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); + } MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineFunction::iterator It = ++BB.getIterator(); MF->insert(It, loopMBB); + if (NoMovnInstr) { +MF->insert(It, loop1MBB); +MF->insert(It, loop2MBB); + } MF->insert(It, sinkMBB); MF->insert(It, exitMBB); @@ -446,9 +457,19 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( exitMBB->transferSuccessorsAndUpdatePHIs(&BB); BB.addSuccessor(loopMBB, BranchProbability::getOne()); - loopMBB->addSuccessor(sinkMBB); - loopMBB->addSuccessor(loopMBB); - loopMBB->normalizeSuccProbs(); + if (NoMovnInstr) { +loopMBB->addSuccessor(loop1MBB); +loopMBB->addSuccessor(loop2MBB); + } else { +loopMBB->addSuccessor(sinkMBB); +loopMBB->addSuccessor(loopMBB); +loopMBB->normalizeSuccProbs(); + } + if (NoMovnInstr) { +loop1MBB->addSuccessor(loop2MBB); +loop2MBB->addSuccessor(loopMBB); +loop2MBB->addSuccessor(sinkMBB); + } BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); if (IsNand) { @@ -525,7 +546,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) .addReg(BinOpRes) .addReg(Scratch4); -} else { +} else if (STI->hasMips4() || STI->hasMips32()) { // max: move BinOpRes, StoreVal // movn BinOpRes, Incr, Scratch4, BinOpRes // min: move BinOpRes, StoreVal @@ -537,12 +558,59 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( .addReg(Incr) .addReg(Scratch4) .addReg(BinOpRes); +} else { + // if min: + // loopMBB: move BinOpRes, StoreVal + // beq Scratch4, 0, loop1MBB + // j loop2MBB + // loop1MBB: move BinOpRes, Incr + // loop2MBB: and BinOpRes, BinOpRes, Mask + // and StoreVal, OlddVal, Mask2 + // or StoreVal, StoreVal, BinOpRes + // StoreVal = sc StoreVal, 0(Ptr) + // beq StoreVal, zero, loopMBB + // + // if max: + // loopMBB: move BinOpRes, Incr + // beq Scratch4, 0, loop1MBB + // j loop2MBB + // loop1MBB: move BinOpRes, StoreVal + // loop2MBB: and BinOpRes, BinOpRes, Mask + // and StoreVal, OlddVal, Mask2 + // or StoreVal, StoreVal, BinOpRes + // StoreVal = sc StoreVal, 0(Ptr) + // beq StoreVal, zero, loopMBB + if (IsMin) { +BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) +.addReg(StoreVal) +.addReg(Mips::ZERO);
[llvm-branch-commits] [llvm] release/21.x: [Mips] Fix atomic min/max generate mips4 instructions when compiling for mips2 (#159717) (PR #160807)
https://github.com/dyung closed https://github.com/llvm/llvm-project/pull/160807 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 559d966 - [Mips] Fix atomic min/max generate mips4 instructions when compiling for mips2 (#159717)
Author: yingopq
Date: 2025-10-01T15:15:58Z
New Revision: 559d966bcb54e54d03ff29a2086cbc0f15910683
URL:
https://github.com/llvm/llvm-project/commit/559d966bcb54e54d03ff29a2086cbc0f15910683
DIFF:
https://github.com/llvm/llvm-project/commit/559d966bcb54e54d03ff29a2086cbc0f15910683.diff
LOG: [Mips] Fix atomic min/max generate mips4 instructions when compiling for
mips2 (#159717)
Modify instr movn/movz to mixture of beq, move, and sc.
Because atomic-min-max.ll test broken on the expensive builder, I revert
https://github.com/llvm/llvm-project/pull/149983 and resubmit this PR.
The broken reason:
In i16/i8 function expandAtomicBinOpSubword, we use two successor
after loop2MBB, one does not specify the second parameter, the other
use BranchProbability::getOne() that means 100% probability. This is
contradictory. And the second successor is also specified incorrectly.
The changess:
* llvm/lib/Target/Mips/MipsExpandPseudo.cpp:
Change loop2MBB`s second successor to correct one and delete the
second parameter BranchProbability::getOne().
* llvm/test/CodeGen/Mips/atomic-min-max.ll:
Add -verify-machineinstrs option in RUN command;
Modify i16 test and i8 test according to the changes.
Fix #145411.
(cherry picked from commit 114b3b8b04fe5aae4143e30078637015a9e077ce)
Added:
Modified:
llvm/lib/Target/Mips/MipsExpandPseudo.cpp
llvm/test/CodeGen/Mips/atomic-min-max.ll
Removed:
diff --git a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp
b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp
index 34ff41f6e02da..78f2e5db40f9d 100644
--- a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp
+++ b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp
@@ -432,13 +432,24 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword(
Register OldVal = I->getOperand(6).getReg();
Register BinOpRes = I->getOperand(7).getReg();
Register StoreVal = I->getOperand(8).getReg();
+ bool NoMovnInstr = (IsMin || IsMax) && !STI->hasMips4() && !STI->hasMips32();
const BasicBlock *LLVM_BB = BB.getBasicBlock();
MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *loop1MBB = nullptr;
+ MachineBasicBlock *loop2MBB = nullptr;
+ if (NoMovnInstr) {
+loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB);
+loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ }
MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineFunction::iterator It = ++BB.getIterator();
MF->insert(It, loopMBB);
+ if (NoMovnInstr) {
+MF->insert(It, loop1MBB);
+MF->insert(It, loop2MBB);
+ }
MF->insert(It, sinkMBB);
MF->insert(It, exitMBB);
@@ -446,9 +457,19 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword(
exitMBB->transferSuccessorsAndUpdatePHIs(&BB);
BB.addSuccessor(loopMBB, BranchProbability::getOne());
- loopMBB->addSuccessor(sinkMBB);
- loopMBB->addSuccessor(loopMBB);
- loopMBB->normalizeSuccProbs();
+ if (NoMovnInstr) {
+loopMBB->addSuccessor(loop1MBB);
+loopMBB->addSuccessor(loop2MBB);
+ } else {
+loopMBB->addSuccessor(sinkMBB);
+loopMBB->addSuccessor(loopMBB);
+loopMBB->normalizeSuccProbs();
+ }
+ if (NoMovnInstr) {
+loop1MBB->addSuccessor(loop2MBB);
+loop2MBB->addSuccessor(loopMBB);
+loop2MBB->addSuccessor(sinkMBB);
+ }
BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0);
if (IsNand) {
@@ -525,7 +546,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword(
BuildMI(loopMBB, DL, TII->get(OR), BinOpRes)
.addReg(BinOpRes)
.addReg(Scratch4);
-} else {
+} else if (STI->hasMips4() || STI->hasMips32()) {
// max: move BinOpRes, StoreVal
// movn BinOpRes, Incr, Scratch4, BinOpRes
// min: move BinOpRes, StoreVal
@@ -537,12 +558,59 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword(
.addReg(Incr)
.addReg(Scratch4)
.addReg(BinOpRes);
+} else {
+ // if min:
+ // loopMBB: move BinOpRes, StoreVal
+ // beq Scratch4, 0, loop1MBB
+ // j loop2MBB
+ // loop1MBB: move BinOpRes, Incr
+ // loop2MBB: and BinOpRes, BinOpRes, Mask
+ // and StoreVal, OlddVal, Mask2
+ // or StoreVal, StoreVal, BinOpRes
+ // StoreVal = sc StoreVal, 0(Ptr)
+ // beq StoreVal, zero, loopMBB
+ //
+ // if max:
+ // loopMBB: move BinOpRes, Incr
+ // beq Scratch4, 0, loop1MBB
+ // j loop2MBB
+ // loop1MBB: move BinOpRes, StoreVal
+ // loop2MBB: and BinOpRes, BinOpRes, Mask
+ // and StoreVal, OlddVal, Mask2
+ // or StoreVal, StoreVal, BinOpRes
+ // StoreVal = sc StoreVal, 0(Ptr)
+ // beq StoreVal, zero, loopMBB
+ if (IsMin) {
+BuildMI(loopMBB, DL, TII->get(OR), BinOpRes)
+
[llvm-branch-commits] [llvm] release/21.x: [Mips] Fix atomic min/max generate mips4 instructions when compiling for mips2 (#159717) (PR #160807)
github-actions[bot] wrote: @brad0 (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. https://github.com/llvm/llvm-project/pull/160807 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] release/21.x: [clang-format] Fix bugs in annotating arrows and square… (PR #161052)
https://github.com/dyung updated
https://github.com/llvm/llvm-project/pull/161052
>From 41e817a1d1f441494cff32175bae407a9cadd8ee Mon Sep 17 00:00:00 2001
From: owenca
Date: Sat, 27 Sep 2025 21:29:25 -0700
Subject: [PATCH] release/21.x: [clang-format] Fix bugs in annotating arrows
and square brackets (#160973)
Backport 4edda3d78c26b9d928d115b2059d0c719eec237b
---
clang/lib/Format/TokenAnnotator.cpp | 5
clang/lib/Format/UnwrappedLineParser.cpp | 25 ++-
clang/unittests/Format/TokenAnnotatorTest.cpp | 14 +++
3 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp
b/clang/lib/Format/TokenAnnotator.cpp
index cbeb5ef7e4bf4..580996e870f54 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -829,11 +829,6 @@ class AnnotatingParser {
if (Parent && Parent->is(TT_PointerOrReference))
Parent->overwriteFixedType(TT_BinaryOperator);
}
-// An arrow after an ObjC method expression is not a lambda arrow.
-if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&
-CurrentToken->Next->is(TT_LambdaArrow)) {
- CurrentToken->Next->overwriteFixedType(TT_Unknown);
-}
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
// FirstObjCSelectorName is set when a colon is found. This does
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp
b/clang/lib/Format/UnwrappedLineParser.cpp
index 91b8fdc8a3c38..934605733542f 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2266,7 +2266,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
if (!tryToParseLambdaIntroducer())
return false;
- bool SeenArrow = false;
+ FormatToken *Arrow = nullptr;
bool InTemplateParameterList = false;
while (FormatTok->isNot(tok::l_brace)) {
@@ -2341,17 +2341,13 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::ellipsis:
case tok::kw_true:
case tok::kw_false:
- if (SeenArrow || InTemplateParameterList) {
+ if (Arrow || InTemplateParameterList) {
nextToken();
break;
}
return true;
case tok::arrow:
- // This might or might not actually be a lambda arrow (this could be an
- // ObjC method invocation followed by a dereferencing arrow). We might
- // reset this back to TT_Unknown in TokenAnnotator.
- FormatTok->setFinalizedType(TT_LambdaArrow);
- SeenArrow = true;
+ Arrow = FormatTok;
nextToken();
break;
case tok::kw_requires: {
@@ -2373,6 +2369,9 @@ bool UnwrappedLineParser::tryToParseLambda() {
FormatTok->setFinalizedType(TT_LambdaLBrace);
LSquare.setFinalizedType(TT_LambdaLSquare);
+ if (Arrow)
+Arrow->setFinalizedType(TT_LambdaArrow);
+
NestedLambdas.push_back(Line->SeenDecltypeAuto);
parseChildBlock();
assert(!NestedLambdas.empty());
@@ -2386,11 +2385,6 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
const FormatToken *LeftSquare = FormatTok;
nextToken();
if (Previous) {
-if (Previous->Tok.getIdentifierInfo() &&
-!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
- tok::kw_co_return)) {
- return false;
-}
if (Previous->closesScope()) {
// Not a potential C-style cast.
if (Previous->isNot(tok::r_paren))
@@ -2400,6 +2394,13 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
// and `int (*)()`.
if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren))
return false;
+} else if (Previous->is(tok::star)) {
+ Previous = Previous->getPreviousNonComment();
+}
+if (Previous && Previous->Tok.getIdentifierInfo() &&
+!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
+ tok::kw_co_return)) {
+ return false;
}
}
if (LeftSquare->isCppStructuredBinding(IsCpp))
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 0a3dc946e8c1c..259d7e54133a1 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2229,6 +2229,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 21u) << Tokens;
EXPECT_TOKEN(Tokens[11], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace);
+
+ Tokens = annotate("SomeFunction({[]() -> int *[] { return {}; }});");
+ ASSERT_EQ(Tokens.size(), 22u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::l_square, TT_LambdaLSquare);
+ EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_LambdaDefinitionLParen);
+ EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare);
}
TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) {
@@ -4151,6 +4157,14 @@ TEST_F(TokenAnnota
[llvm-branch-commits] [clang] release/21.x: [clang-format] Fix bugs in annotating arrows and square… (PR #161052)
github-actions[bot] wrote: @owenca (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. https://github.com/llvm/llvm-project/pull/161052 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] release/21.x: [clang][PAC] Don't try to diagnose use of pointer auth on dependent types #159505 (#159859) (PR #161288)
https://github.com/dyung closed https://github.com/llvm/llvm-project/pull/161288 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AArch64][SME] Reshuffle emit[prologue|epilogue]() for splitSVEObjects (NFCI) (PR #161217)
https://github.com/MacDue updated
https://github.com/llvm/llvm-project/pull/161217
>From 9a5c6811af833840fda0d723cc4f154295ef9f50 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell
Date: Mon, 29 Sep 2025 15:17:06 +
Subject: [PATCH 1/2] [AArch64][SME] Reshuffle emit[prologue|epilogue]() for
splitSVEObjects (NFCI)
Requested in
https://github.com/llvm/llvm-project/pull/142392#discussion_r2207880079
Change-Id: I842faddea1bd54c5e30a9985782baf5dce37e5bb
---
.../AArch64/AArch64MachineFunctionInfo.h | 2 +
.../AArch64/AArch64PrologueEpilogue.cpp | 285 +-
2 files changed, 145 insertions(+), 142 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
index 4a79d9ce39c8d..00c104ed2254d 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
@@ -481,6 +481,8 @@ class AArch64FunctionInfo final : public
MachineFunctionInfo {
StackHazardCSRSlotIndex = Index;
}
+ bool hasSplitSVEObjects() const { return false; }
+
SMEAttrs getSMEFnAttrs() const { return SMEFnAttrs; }
unsigned getSRetReturnReg() const { return SRetReturnReg; }
diff --git a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp
b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp
index 3de0d4d5ec230..8d648ed0f2cba 100644
--- a/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp
+++ b/llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp
@@ -708,8 +708,6 @@ void AArch64PrologueEmitter::emitPrologue() {
if (AFL.windowsRequiresStackProbe(MF, NumBytes + RealignmentPadding))
emitWindowsStackProbe(AfterGPRSavesI, DL, NumBytes, RealignmentPadding);
- MachineBasicBlock::iterator CalleeSavesEnd = AfterGPRSavesI;
-
StackOffset PPRCalleeSavesSize =
StackOffset::getScalable(AFI->getPPRCalleeSavedStackSize());
StackOffset ZPRCalleeSavesSize =
@@ -717,76 +715,68 @@ void AArch64PrologueEmitter::emitPrologue() {
StackOffset SVECalleeSavesSize = PPRCalleeSavesSize + ZPRCalleeSavesSize;
StackOffset PPRLocalsSize = AFL.getPPRStackSize(MF) - PPRCalleeSavesSize;
StackOffset ZPRLocalsSize = AFL.getZPRStackSize(MF) - ZPRCalleeSavesSize;
+ std::optional ZPRCalleeSavesBegin,
+ ZPRCalleeSavesEnd, PPRCalleeSavesBegin, PPRCalleeSavesEnd;
StackOffset CFAOffset =
StackOffset::getFixed((int64_t)MFI.getStackSize() - NumBytes);
MachineBasicBlock::iterator AfterSVESavesI = AfterGPRSavesI;
-
if (!FPAfterSVECalleeSaves) {
-MachineBasicBlock::iterator ZPRCalleeSavesBegin = AfterGPRSavesI,
-ZPRCalleeSavesEnd = AfterGPRSavesI;
-MachineBasicBlock::iterator PPRCalleeSavesBegin = AfterGPRSavesI,
-PPRCalleeSavesEnd = AfterGPRSavesI;
-
-// Process the SVE callee-saves to determine what space needs to be
-// allocated.
-
+// Process the SVE callee-saves to find the starts/ends of the ZPR and PPR
+// areas.
+PPRCalleeSavesBegin = AfterGPRSavesI;
if (PPRCalleeSavesSize) {
LLVM_DEBUG(dbgs() << "PPRCalleeSavedStackSize = "
<< PPRCalleeSavesSize.getScalable() << "\n");
- PPRCalleeSavesBegin = AfterSVESavesI;
- assert(isPartOfPPRCalleeSaves(PPRCalleeSavesBegin) &&
+ assert(isPartOfPPRCalleeSaves(*PPRCalleeSavesBegin) &&
"Unexpected instruction");
while (isPartOfPPRCalleeSaves(AfterSVESavesI) &&
AfterSVESavesI != MBB.getFirstTerminator())
++AfterSVESavesI;
- PPRCalleeSavesEnd = AfterSVESavesI;
}
-
+PPRCalleeSavesEnd = ZPRCalleeSavesBegin = AfterSVESavesI;
if (ZPRCalleeSavesSize) {
LLVM_DEBUG(dbgs() << "ZPRCalleeSavedStackSize = "
<< ZPRCalleeSavesSize.getScalable() << "\n");
- ZPRCalleeSavesBegin = AfterSVESavesI;
- assert(isPartOfZPRCalleeSaves(ZPRCalleeSavesBegin) &&
+ assert(isPartOfZPRCalleeSaves(*ZPRCalleeSavesBegin) &&
"Unexpected instruction");
while (isPartOfZPRCalleeSaves(AfterSVESavesI) &&
AfterSVESavesI != MBB.getFirstTerminator())
++AfterSVESavesI;
- ZPRCalleeSavesEnd = AfterSVESavesI;
}
+ZPRCalleeSavesEnd = AfterSVESavesI;
+ }
+
+ if (EmitAsyncCFI)
+emitCalleeSavedSVELocations(AfterSVESavesI);
+ if (AFI->hasSplitSVEObjects()) {
+reportFatalInternalError("not implemented yet");
+ } else {
// Allocate space for the callee saves (if any).
StackOffset LocalsSize =
PPRLocalsSize + ZPRLocalsSize + StackOffset::getFixed(NumBytes);
-MachineBasicBlock::iterator CalleeSavesBegin =
-AFI->getPPRCalleeSavedStackSize() ? PPRCalleeSavesBegin
- : ZPRCalleeSavesBegin;
-allocateStackSpace(CalleeSavesBegin, 0, SVECalleeSavesSize,
- EmitAsyncCFI && !HasFP, CFAOffset,
- MFI.hasVarSizedObjects() || LocalsSize);
-
-C
[llvm-branch-commits] [compiler-rt] release/21.x: [compiler-rt][sanitizer] fix msghdr for musl (PR #159551)
https://github.com/dyung updated https://github.com/llvm/llvm-project/pull/159551 >From 7da3233cd9822fd0d76ffb32d7684a9bea64d2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?De=C3=A1k=20Lajos?= <[email protected]> Date: Tue, 22 Jul 2025 20:31:28 +0200 Subject: [PATCH] [compiler-rt][sanitizer] fix msghdr for musl (#136195) Ran into the issue on Alpine when building with TSAN that `__sanitizer_msghdr` and the `msghdr` provided by musl did not match. This caused lots of tsan reports and an eventual termination of the application by the oom during a `sendmsg`. --- .../sanitizer_platform_limits_posix.h | 24 +++ 1 file changed, 24 insertions(+) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index f118d53f0df80..24966523f3a02 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -478,6 +478,30 @@ struct __sanitizer_cmsghdr { int cmsg_level; int cmsg_type; }; +# elif SANITIZER_MUSL +struct __sanitizer_msghdr { + void *msg_name; + unsigned msg_namelen; + struct __sanitizer_iovec *msg_iov; + int msg_iovlen; +#if SANITIZER_WORDSIZE == 64 + int __pad1; +#endif + void *msg_control; + unsigned msg_controllen; +#if SANITIZER_WORDSIZE == 64 + int __pad2; +#endif + int msg_flags; +}; +struct __sanitizer_cmsghdr { + unsigned cmsg_len; +#if SANITIZER_WORDSIZE == 64 + int __pad1; +#endif + int cmsg_level; + int cmsg_type; +}; # else // In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but // many implementations don't conform to the standard. ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [analyzer] Revert #115918, so empty base class optimization works again (#157480) (PR #160450)
https://github.com/dyung closed https://github.com/llvm/llvm-project/pull/160450 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [IR2Vec] Refactor vocabulary to use section-based storage (PR #158376)
https://github.com/svkeerthy updated
https://github.com/llvm/llvm-project/pull/158376
>From 100c5d4f791440c17041259b30c227fcd57cee43 Mon Sep 17 00:00:00 2001
From: svkeerthy
Date: Fri, 12 Sep 2025 22:06:44 +
Subject: [PATCH] VocabStorage
---
llvm/include/llvm/Analysis/IR2Vec.h | 218 ---
llvm/lib/Analysis/IR2Vec.cpp | 256 +++--
llvm/lib/Analysis/InlineAdvisor.cpp | 2 +-
llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp| 6 +-
.../FunctionPropertiesAnalysisTest.cpp| 13 +-
llvm/unittests/Analysis/IR2VecTest.cpp| 347 --
6 files changed, 648 insertions(+), 194 deletions(-)
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h
b/llvm/include/llvm/Analysis/IR2Vec.h
index f3f9de460218b9..b7c301580a8a4c 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -45,6 +45,7 @@
#include "llvm/Support/JSON.h"
#include
#include
+#include
namespace llvm {
@@ -144,6 +145,73 @@ struct Embedding {
using InstEmbeddingsMap = DenseMap;
using BBEmbeddingsMap = DenseMap;
+/// Generic storage class for section-based vocabularies.
+/// VocabStorage provides a generic foundation for storing and accessing
+/// embeddings organized into sections.
+class VocabStorage {
+private:
+ /// Section-based storage
+ std::vector> Sections;
+
+ const size_t TotalSize;
+ const unsigned Dimension;
+
+public:
+ /// Default constructor creates empty storage (invalid state)
+ VocabStorage() : Sections(), TotalSize(0), Dimension(0) {}
+
+ /// Create a VocabStorage with pre-organized section data
+ VocabStorage(std::vector> &&SectionData);
+
+ VocabStorage(VocabStorage &&) = default;
+ VocabStorage &operator=(VocabStorage &&) = delete;
+
+ VocabStorage(const VocabStorage &) = delete;
+ VocabStorage &operator=(const VocabStorage &) = delete;
+
+ /// Get total number of entries across all sections
+ size_t size() const { return TotalSize; }
+
+ /// Get number of sections
+ unsigned getNumSections() const {
+return static_cast(Sections.size());
+ }
+
+ /// Section-based access: Storage[sectionId][localIndex]
+ const std::vector &operator[](unsigned SectionId) const {
+assert(SectionId < Sections.size() && "Invalid section ID");
+return Sections[SectionId];
+ }
+
+ /// Get vocabulary dimension
+ unsigned getDimension() const { return Dimension; }
+
+ /// Check if vocabulary is valid (has data)
+ bool isValid() const { return TotalSize > 0; }
+
+ /// Iterator support for section-based access
+ class const_iterator {
+const VocabStorage *Storage;
+unsigned SectionId = 0;
+size_t LocalIndex = 0;
+
+ public:
+const_iterator(const VocabStorage *Storage, unsigned SectionId,
+ size_t LocalIndex)
+: Storage(Storage), SectionId(SectionId), LocalIndex(LocalIndex) {}
+
+LLVM_ABI const Embedding &operator*() const;
+LLVM_ABI const_iterator &operator++();
+LLVM_ABI bool operator==(const const_iterator &Other) const;
+LLVM_ABI bool operator!=(const const_iterator &Other) const;
+ };
+
+ const_iterator begin() const { return const_iterator(this, 0, 0); }
+ const_iterator end() const {
+return const_iterator(this, getNumSections(), 0);
+ }
+};
+
/// Class for storing and accessing the IR2Vec vocabulary.
/// The Vocabulary class manages seed embeddings for LLVM IR entities. The
/// seed embeddings are the initial learned representations of the entities
@@ -164,7 +232,7 @@ using BBEmbeddingsMap = DenseMap;
class Vocabulary {
friend class llvm::IR2VecVocabAnalysis;
- // Vocabulary Slot Layout:
+ // Vocabulary Layout:
// ++--+
// | Entity Type| Index Range |
// ++--+
@@ -180,8 +248,16 @@ class Vocabulary {
// and improves learning. Operands include Comparison predicates
// (ICmp/FCmp) along with other operand types. This can be extended to
// include other specializations in future.
- using VocabVector = std::vector;
- VocabVector Vocab;
+ enum class Section : unsigned {
+Opcodes = 0,
+CanonicalTypes = 1,
+Operands = 2,
+Predicates = 3,
+MaxSections
+ };
+
+ // Use section-based storage for better organization and efficiency
+ VocabStorage Storage;
static constexpr unsigned NumICmpPredicates =
static_cast(CmpInst::LAST_ICMP_PREDICATE) -
@@ -233,10 +309,23 @@ class Vocabulary {
NumICmpPredicates + NumFCmpPredicates;
Vocabulary() = default;
- LLVM_ABI Vocabulary(VocabVector &&Vocab) : Vocab(std::move(Vocab)) {}
+ LLVM_ABI Vocabulary(VocabStorage &&Storage) : Storage(std::move(Storage)) {}
+
+ Vocabulary(const Vocabulary &) = delete;
+ Vocabulary &operator=(const Vocabulary &) = delete;
+
+ Vocabulary(Vocabulary &&) = default;
+ Vocabulary &operator
[llvm-branch-commits] [llvm] [IR2Vec] Refactor vocabulary to use section-based storage (PR #158376)
https://github.com/svkeerthy updated
https://github.com/llvm/llvm-project/pull/158376
>From 100c5d4f791440c17041259b30c227fcd57cee43 Mon Sep 17 00:00:00 2001
From: svkeerthy
Date: Fri, 12 Sep 2025 22:06:44 +
Subject: [PATCH] VocabStorage
---
llvm/include/llvm/Analysis/IR2Vec.h | 218 ---
llvm/lib/Analysis/IR2Vec.cpp | 256 +++--
llvm/lib/Analysis/InlineAdvisor.cpp | 2 +-
llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp| 6 +-
.../FunctionPropertiesAnalysisTest.cpp| 13 +-
llvm/unittests/Analysis/IR2VecTest.cpp| 347 --
6 files changed, 648 insertions(+), 194 deletions(-)
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h
b/llvm/include/llvm/Analysis/IR2Vec.h
index f3f9de460218b9..b7c301580a8a4c 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -45,6 +45,7 @@
#include "llvm/Support/JSON.h"
#include
#include
+#include
namespace llvm {
@@ -144,6 +145,73 @@ struct Embedding {
using InstEmbeddingsMap = DenseMap;
using BBEmbeddingsMap = DenseMap;
+/// Generic storage class for section-based vocabularies.
+/// VocabStorage provides a generic foundation for storing and accessing
+/// embeddings organized into sections.
+class VocabStorage {
+private:
+ /// Section-based storage
+ std::vector> Sections;
+
+ const size_t TotalSize;
+ const unsigned Dimension;
+
+public:
+ /// Default constructor creates empty storage (invalid state)
+ VocabStorage() : Sections(), TotalSize(0), Dimension(0) {}
+
+ /// Create a VocabStorage with pre-organized section data
+ VocabStorage(std::vector> &&SectionData);
+
+ VocabStorage(VocabStorage &&) = default;
+ VocabStorage &operator=(VocabStorage &&) = delete;
+
+ VocabStorage(const VocabStorage &) = delete;
+ VocabStorage &operator=(const VocabStorage &) = delete;
+
+ /// Get total number of entries across all sections
+ size_t size() const { return TotalSize; }
+
+ /// Get number of sections
+ unsigned getNumSections() const {
+return static_cast(Sections.size());
+ }
+
+ /// Section-based access: Storage[sectionId][localIndex]
+ const std::vector &operator[](unsigned SectionId) const {
+assert(SectionId < Sections.size() && "Invalid section ID");
+return Sections[SectionId];
+ }
+
+ /// Get vocabulary dimension
+ unsigned getDimension() const { return Dimension; }
+
+ /// Check if vocabulary is valid (has data)
+ bool isValid() const { return TotalSize > 0; }
+
+ /// Iterator support for section-based access
+ class const_iterator {
+const VocabStorage *Storage;
+unsigned SectionId = 0;
+size_t LocalIndex = 0;
+
+ public:
+const_iterator(const VocabStorage *Storage, unsigned SectionId,
+ size_t LocalIndex)
+: Storage(Storage), SectionId(SectionId), LocalIndex(LocalIndex) {}
+
+LLVM_ABI const Embedding &operator*() const;
+LLVM_ABI const_iterator &operator++();
+LLVM_ABI bool operator==(const const_iterator &Other) const;
+LLVM_ABI bool operator!=(const const_iterator &Other) const;
+ };
+
+ const_iterator begin() const { return const_iterator(this, 0, 0); }
+ const_iterator end() const {
+return const_iterator(this, getNumSections(), 0);
+ }
+};
+
/// Class for storing and accessing the IR2Vec vocabulary.
/// The Vocabulary class manages seed embeddings for LLVM IR entities. The
/// seed embeddings are the initial learned representations of the entities
@@ -164,7 +232,7 @@ using BBEmbeddingsMap = DenseMap;
class Vocabulary {
friend class llvm::IR2VecVocabAnalysis;
- // Vocabulary Slot Layout:
+ // Vocabulary Layout:
// ++--+
// | Entity Type| Index Range |
// ++--+
@@ -180,8 +248,16 @@ class Vocabulary {
// and improves learning. Operands include Comparison predicates
// (ICmp/FCmp) along with other operand types. This can be extended to
// include other specializations in future.
- using VocabVector = std::vector;
- VocabVector Vocab;
+ enum class Section : unsigned {
+Opcodes = 0,
+CanonicalTypes = 1,
+Operands = 2,
+Predicates = 3,
+MaxSections
+ };
+
+ // Use section-based storage for better organization and efficiency
+ VocabStorage Storage;
static constexpr unsigned NumICmpPredicates =
static_cast(CmpInst::LAST_ICMP_PREDICATE) -
@@ -233,10 +309,23 @@ class Vocabulary {
NumICmpPredicates + NumFCmpPredicates;
Vocabulary() = default;
- LLVM_ABI Vocabulary(VocabVector &&Vocab) : Vocab(std::move(Vocab)) {}
+ LLVM_ABI Vocabulary(VocabStorage &&Storage) : Storage(std::move(Storage)) {}
+
+ Vocabulary(const Vocabulary &) = delete;
+ Vocabulary &operator=(const Vocabulary &) = delete;
+
+ Vocabulary(Vocabulary &&) = default;
+ Vocabulary &operator
[llvm-branch-commits] [llvm] [AArch64][SME] Support split ZPR and PPR area allocation (PR #142392)
@@ -1,6 +1,7 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 # RUN: llc -mtriple=aarch64-linux-gnu -aarch64-enable-zpr-predicate-spills -run-pass=greedy %s -o - | FileCheck %s # RUN: llc -mtriple=aarch64-linux-gnu -aarch64-enable-zpr-predicate-spills -start-before=greedy -stop-after=aarch64-expand-pseudo -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=EXPAND + sdesmalen-arm wrote: nit: unnecessary whitespace. https://github.com/llvm/llvm-project/pull/142392 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AArch64][SME] Support split ZPR and PPR area allocation (PR #142392)
@@ -4376,8 +4625,7 @@ static bool getSVECalleeSaveSlotRange(const
MachineFrameInfo &MFI,
}
static SVEStackSizes determineSVEStackSizes(MachineFunction &MF,
-AssignObjectOffsets AssignOffsets,
-bool SplitSVEObjects) {
+AssignObjectOffsets AssignOffsets)
{
sdesmalen-arm wrote:
Yeah, that comment was outdated.
https://github.com/llvm/llvm-project/pull/142392
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [IR2Vec] Initial infrastructure for MIR2Vec (PR #161463)
@@ -0,0 +1,325 @@
+//===- MIR2Vec.cpp - Implementation of MIR2Vec ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions. See the LICENSE file for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// \file
+/// This file implements the MIR2Vec algorithm for Machine IR embeddings.
+///
+//===--===//
+
+#include "llvm/CodeGen/MIR2Vec.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Regex.h"
+
+using namespace llvm;
+using namespace mir2vec;
+
+#define DEBUG_TYPE "mir2vec"
+
+STATISTIC(MIRVocabMissCounter,
+ "Number of lookups to MIR entities not present in the vocabulary");
+
+namespace llvm {
+namespace mir2vec {
+cl::OptionCategory MIR2VecCategory("MIR2Vec Options");
+
+// FIXME: Use a default vocab when not specified
+static cl::opt
+VocabFile("mir2vec-vocab-path", cl::Optional,
+ cl::desc("Path to the vocabulary file for MIR2Vec"),
cl::init(""),
+ cl::cat(MIR2VecCategory));
+cl::opt OpcWeight("mir2vec-opc-weight", cl::Optional, cl::init(1.0),
+ cl::desc("Weight for machine opcode embeddings"),
+ cl::cat(MIR2VecCategory));
+} // namespace mir2vec
+} // namespace llvm
+
+//===--===//
+// Vocabulary Implementation
+//===--===//
+
+Vocabulary::Vocabulary(VocabMap &&OpcodeEntries, const TargetInstrInfo *TII) {
+ // Early return for invalid inputs - creates empty/invalid vocabulary
mtrofin wrote:
instead of `isValid` we could have a static `create` returning a
`std::optional`? or this follows the existing pattern in IR2Vec
https://github.com/llvm/llvm-project/pull/161463
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [PowerPC] Implement paddis (PR #161572)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff origin/main HEAD --extensions cpp,h -- llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp `` :warning: The reproduction instructions above might return results for more than one PR in a stack if you are using a stacked PR workflow. You can limit the results by changing `origin/main` to the base branch/commit you want to compare against. :warning: View the diff from clang-format here. ``diff diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp index e2afb9378..acbc39f3e 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp @@ -437,8 +437,7 @@ void PPCInstPrinter::printS32ImmOperand(const MCInst *MI, unsigned OpNo, long long Value = MI->getOperand(OpNo).getImm(); assert(isInt<32>(Value) && "Invalid s32imm argument!"); O << (long long)Value; - } - else + } else printOperand(MI, OpNo, STI, O); } `` https://github.com/llvm/llvm-project/pull/161572 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [IR2Vec] Initial infrastructure for MIR2Vec (PR #161463)
@@ -329,6 +329,43 @@ bool VocabStorage::const_iterator::operator!=(
return !(*this == Other);
}
+Error VocabStorage::parseVocabSection(StringRef Key,
+ const json::Value &ParsedVocabValue,
+ VocabMap &TargetVocab, unsigned &Dim) {
+ json::Path::Root Path("");
svkeerthy wrote:
That's what I am trying to do.. moving it to VocabStorage can help us use this
method in both IR and MIR vocabulary. (Will push it as a separate NFC as you
mentioned in earlier comment)
https://github.com/llvm/llvm-project/pull/161463
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/21.x: [NVPTX] Disable relative lookup tables (#159748) (PR #160064)
https://github.com/dyung updated
https://github.com/llvm/llvm-project/pull/160064
>From 31e4363ba9c2e0582a2b1105fe24dbfff860b7f6 Mon Sep 17 00:00:00 2001
From: Nikita Popov
Date: Mon, 22 Sep 2025 12:18:25 +0200
Subject: [PATCH] [NVPTX] Disable relative lookup tables (#159748)
Relative lookup tables result in "LLVM ERROR: Circular dependency found
in global variable set", so disable them for this target.
(cherry picked from commit 1ed15374638ecf6046169194b4b3ca34b7cf340f)
---
.../Target/NVPTX/NVPTXTargetTransformInfo.h | 5 +++
.../RelLookupTableConverter/nvptx.ll | 32 +++
2 files changed, 37 insertions(+)
create mode 100644 llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
index 9a6e261c811a0..437edfb8ffc75 100644
--- a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
+++ b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
@@ -183,6 +183,11 @@ class NVPTXTTIImpl final : public
BasicTTIImplBase {
void collectKernelLaunchBounds(
const Function &F,
SmallVectorImpl> &LB) const override;
+
+ bool shouldBuildRelLookupTables() const override {
+// Self-referential globals are not supported.
+return false;
+ }
};
} // end namespace llvm
diff --git a/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
b/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
new file mode 100644
index 0..70ebf220c369c
--- /dev/null
+++ b/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
UTC_ARGS: --check-globals all --version 5
+; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -S |
FileCheck %s
+; REQUIRES: nvptx-registered-target
+target triple = "nvptx64-nvidia-cuda"
+
+; Do not produce relative lookup table for nvptx target.
+
+@a1 = internal constant i32 0, align 4
+@b1 = internal constant i32 0, align 4
+@c1 = internal constant i32 0, align 4
+@d1 = internal constant i32 0, align 4
+
[email protected] = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr @b1, ptr
@c1], align 8
+
+;.
+; CHECK: @a1 = internal constant i32 0, align 4
+; CHECK: @b1 = internal constant i32 0, align 4
+; CHECK: @c1 = internal constant i32 0, align 4
+; CHECK: @d1 = internal constant i32 0, align 4
+; CHECK: @switch.table = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr
@b1, ptr @c1], align 8
+;.
+define ptr @internal_linkage(i32 %cond) {
+; CHECK-LABEL: define ptr @internal_linkage(
+; CHECK-SAME: i32 [[COND:%.*]]) {
+; CHECK-NEXT:[[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr
@switch.table, i32 0, i32 [[COND]]
+; CHECK-NEXT:[[RELTABLE_INTRINSIC:%.*]] = load ptr, ptr [[SWITCH_GEP]],
align 8
+; CHECK-NEXT:ret ptr [[RELTABLE_INTRINSIC]]
+;
+ %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table, i32 0,
i32 %cond
+ %switch.load = load ptr, ptr %switch.gep, align 8
+ ret ptr %switch.load
+}
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 31e4363 - [NVPTX] Disable relative lookup tables (#159748)
Author: Nikita Popov
Date: 2025-10-01T14:31:21Z
New Revision: 31e4363ba9c2e0582a2b1105fe24dbfff860b7f6
URL:
https://github.com/llvm/llvm-project/commit/31e4363ba9c2e0582a2b1105fe24dbfff860b7f6
DIFF:
https://github.com/llvm/llvm-project/commit/31e4363ba9c2e0582a2b1105fe24dbfff860b7f6.diff
LOG: [NVPTX] Disable relative lookup tables (#159748)
Relative lookup tables result in "LLVM ERROR: Circular dependency found
in global variable set", so disable them for this target.
(cherry picked from commit 1ed15374638ecf6046169194b4b3ca34b7cf340f)
Added:
llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
Modified:
llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
Removed:
diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
index 9a6e261c811a0..437edfb8ffc75 100644
--- a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
+++ b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h
@@ -183,6 +183,11 @@ class NVPTXTTIImpl final : public
BasicTTIImplBase {
void collectKernelLaunchBounds(
const Function &F,
SmallVectorImpl> &LB) const override;
+
+ bool shouldBuildRelLookupTables() const override {
+// Self-referential globals are not supported.
+return false;
+ }
};
} // end namespace llvm
diff --git a/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
b/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
new file mode 100644
index 0..70ebf220c369c
--- /dev/null
+++ b/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
UTC_ARGS: --check-globals all --version 5
+; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -S |
FileCheck %s
+; REQUIRES: nvptx-registered-target
+target triple = "nvptx64-nvidia-cuda"
+
+; Do not produce relative lookup table for nvptx target.
+
+@a1 = internal constant i32 0, align 4
+@b1 = internal constant i32 0, align 4
+@c1 = internal constant i32 0, align 4
+@d1 = internal constant i32 0, align 4
+
[email protected] = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr @b1, ptr
@c1], align 8
+
+;.
+; CHECK: @a1 = internal constant i32 0, align 4
+; CHECK: @b1 = internal constant i32 0, align 4
+; CHECK: @c1 = internal constant i32 0, align 4
+; CHECK: @d1 = internal constant i32 0, align 4
+; CHECK: @switch.table = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr
@b1, ptr @c1], align 8
+;.
+define ptr @internal_linkage(i32 %cond) {
+; CHECK-LABEL: define ptr @internal_linkage(
+; CHECK-SAME: i32 [[COND:%.*]]) {
+; CHECK-NEXT:[[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr
@switch.table, i32 0, i32 [[COND]]
+; CHECK-NEXT:[[RELTABLE_INTRINSIC:%.*]] = load ptr, ptr [[SWITCH_GEP]],
align 8
+; CHECK-NEXT:ret ptr [[RELTABLE_INTRINSIC]]
+;
+ %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table, i32 0,
i32 %cond
+ %switch.load = load ptr, ptr %switch.gep, align 8
+ ret ptr %switch.load
+}
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] 0060034 - [analyzer] Revert #115918, so empty base class optimization works again (#157480)
Author: Balazs Benics
Date: 2025-10-01T15:10:18Z
New Revision: 0060034c6a0b3735c3f7fd89173884a10fe30206
URL:
https://github.com/llvm/llvm-project/commit/0060034c6a0b3735c3f7fd89173884a10fe30206
DIFF:
https://github.com/llvm/llvm-project/commit/0060034c6a0b3735c3f7fd89173884a10fe30206.diff
LOG: [analyzer] Revert #115918, so empty base class optimization works again
(#157480)
Tldr;
We can't unconditionally trivially copy empty classes because that would
clobber the stored entries in the object that the optimized empty class
overlaps with.
This regression was introduced by #115918, which introduced other
clobbering issues, like the handling of `[[no_unique_address]]` fields
in #137252.
Read issue #157467 for the detailed explanation, but in short, I'd
propose reverting the original patch because these was a lot of problems
with it for arguably not much gain.
In particular, that patch was motivated by unifying the handling of
classes so that copy events would be triggered for a class no matter if
it had data members or not.
So in hindsight, it was not worth it.
I plan to backport this to clang-21 as well, and mention in the release
notes that this should fix the regression from clang-20.
PS: Also an interesting read [D43714](https://reviews.llvm.org/D43714)
in hindsight.
Fixes #157467
CPP-6574
(cherry picked from commit 38b948bd4b9bd0ed532c3bea69e0038b3dffe80a)
Added:
clang/test/Analysis/issue-157467.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
clang/test/Analysis/ctor-trivial-copy.cpp
clang/test/Analysis/taint-generic.cpp
Removed:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f03a3273c4518..43529b0f28c3d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1261,6 +1261,11 @@ New features
Crash and bug fixes
^^^
+- Fixed a regression introduced by clang-20 in #GH115918 that lead to false
+ positive reports when ``[[no_unique_address]]`` or empty base class
+ optimization techniques were used. Most notably, some ``std::unique_ptr``
+ implementations. (#GH157467)
+
- Fixed a crash when C++20 parenthesized initializer lists are used.
This affected a crash of the well-known lambda overloaded pattern.
(#GH136041, #GH135665)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 85353848aa124..dc715c7d46d8b 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -71,21 +71,30 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr,
ExplodedNode *Pred,
Bldr.takeNodes(Pred);
assert(ThisRD);
- SVal V = Call.getArgSVal(0);
- const Expr *VExpr = Call.getArgExpr(0);
- // If the value being copied is not unknown, load from its location to get
- // an aggregate rvalue.
- if (std::optional L = V.getAs())
-V = Pred->getState()->getSVal(*L);
- else
-assert(V.isUnknownOrUndef());
+ if (!ThisRD->isEmpty()) {
+SVal V = Call.getArgSVal(0);
+const Expr *VExpr = Call.getArgExpr(0);
- ExplodedNodeSet Tmp;
- evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V,
- /*isLoad=*/true);
- for (ExplodedNode *N : Tmp)
-evalBind(Dst, CallExpr, N, ThisVal, V, true);
+// If the value being copied is not unknown, load from its location to get
+// an aggregate rvalue.
+if (std::optional L = V.getAs())
+ V = Pred->getState()->getSVal(*L);
+else
+ assert(V.isUnknownOrUndef());
+
+ExplodedNodeSet Tmp;
+evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V,
+ /*isLoad=*/true);
+for (ExplodedNode *N : Tmp)
+ evalBind(Dst, CallExpr, N, ThisVal, V, true);
+ } else {
+// We can't copy empty classes because of empty base class optimization.
+// In that case, copying the empty base class subobject would overwrite the
+// object that it overlaps with - so let's not do that.
+// See issue-157467.cpp for an example.
+Dst.Add(Pred);
+ }
PostStmt PS(CallExpr, LCtx);
for (ExplodedNode *N : Dst) {
diff --git a/clang/test/Analysis/ctor-trivial-copy.cpp
b/clang/test/Analysis/ctor-trivial-copy.cpp
index 45c8ca4c51776..940ff9ba3ed9c 100644
--- a/clang/test/Analysis/ctor-trivial-copy.cpp
+++ b/clang/test/Analysis/ctor-trivial-copy.cpp
@@ -46,15 +46,10 @@ void _01_empty_structs() {
empty Empty = conjure();
empty Empty2 = Empty;
empty Empty3 = Empty2;
- // All of these should refer to the exact same symbol, because all of
- // these trivial copies refer to the original conjured value.
- // There were Unknown before:
- clang_analyzer_denote(Empty, "$Empty");
- clang_analyzer_express(Empty); // expected-warning {{$Empty}}
- clang_analyzer_express(Empty2); // expected-warning {{$Empty}}
- clang_analyzer_express(Empt
[llvm-branch-commits] [clang] release/21.x: [clang][PAC] Don't try to diagnose use of pointer auth on dependent types #159505 (#159859) (PR #161288)
ojhunt wrote: > @ojhunt (or anyone else). If you would like to add a note about this fix in > the release notes (completely optional). Please reply to this comment with a > one or two sentence description of the fix. When you are done, please add the > release:note label to this PR. Fix error when performing bitwise layout queries of uninstantiated template types containing pointer authenticated fields and bases. https://github.com/llvm/llvm-project/pull/161288 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AArch64][SME] Support split ZPR and PPR area allocation (PR #142392)
https://github.com/sdesmalen-arm edited https://github.com/llvm/llvm-project/pull/142392 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [SimplifyCFG][profcheck] Synthesize profile for `br (X == 0 | X == 1), T, F1 -> switch (PR #161549)
https://github.com/mtrofin created
https://github.com/llvm/llvm-project/pull/161549
None
>From 485a8ffed0be28fa5a6852c63ede86615e439342 Mon Sep 17 00:00:00 2001
From: Mircea Trofin
Date: Tue, 30 Sep 2025 16:21:27 -0700
Subject: [PATCH] [SimplifyCFG][profcheck] Synthesize profile for `br (X == 0 |
X == 1), T, F1 -> switch
---
llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 30 ++-
.../Transforms/SimplifyCFG/switch_create.ll | 27 -
2 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 4d1f768e2177a..df436d0f68028 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -5148,14 +5148,18 @@ bool
SimplifyCFGOpt::simplifyBranchOnICmpChain(BranchInst *BI,
if (ExtraCase && Values.size() < 2)
return false;
- // TODO: Preserve branch weight metadata, similarly to how
- // foldValueComparisonIntoPredecessors preserves it.
+ SmallVector BranchWeights;
+ const bool HasProfile = !ProfcheckDisableMetadataFixes &&
+ extractBranchWeights(*BI, BranchWeights);
// Figure out which block is which destination.
BasicBlock *DefaultBB = BI->getSuccessor(1);
BasicBlock *EdgeBB = BI->getSuccessor(0);
- if (!TrueWhenEqual)
+ if (!TrueWhenEqual) {
std::swap(DefaultBB, EdgeBB);
+if (HasProfile)
+ std::swap(BranchWeights[0], BranchWeights[1]);
+ }
BasicBlock *BB = BI->getParent();
@@ -5186,10 +5190,11 @@ bool
SimplifyCFGOpt::simplifyBranchOnICmpChain(BranchInst *BI,
if (!isGuaranteedNotToBeUndefOrPoison(ExtraCase, AC, BI, nullptr))
ExtraCase = Builder.CreateFreeze(ExtraCase);
-if (TrueWhenEqual)
- Builder.CreateCondBr(ExtraCase, EdgeBB, NewBB);
-else
- Builder.CreateCondBr(ExtraCase, NewBB, EdgeBB);
+// We don't have any info about this condition.
+auto *Br = TrueWhenEqual ? Builder.CreateCondBr(ExtraCase, EdgeBB, NewBB)
+ : Builder.CreateCondBr(ExtraCase, NewBB, EdgeBB);
+setExplicitlyUnknownBranchWeightsIfProfiled(*Br, *NewBB->getParent(),
+DEBUG_TYPE);
OldTI->eraseFromParent();
@@ -5216,6 +5221,17 @@ bool
SimplifyCFGOpt::simplifyBranchOnICmpChain(BranchInst *BI,
// Create the new switch instruction now.
SwitchInst *New = Builder.CreateSwitch(CompVal, DefaultBB, Values.size());
+ if (HasProfile) {
+// We know the weight of the default case. We don't know the weight of the
+// other cases, but rather than completely loose profiling info, we split
+// the remaining probability equally over them.
+SmallVector NewWeights(Values.size() + 1);
+NewWeights[0] = BranchWeights[1]; // this is the default, and we swapped if
+ // TrueWhenEqual.
+for (auto &V : drop_begin(NewWeights))
+ V = BranchWeights[0] / Values.size();
+setBranchWeights(*New, NewWeights, /*IsExpected=*/false);
+ }
// Add all of the 'cases' to the switch instruction.
for (ConstantInt *Val : Values)
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index 18c4ade46162c..ef5aee68e268e 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
UTC_ARGS: --check-globals
; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1
-switch-range-to-icmp < %s | FileCheck %s
; RUN: opt -S -data-layout="p:32:32-p1:16:16" -passes=simplifycfg
-simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s |
FileCheck -check-prefix=CHECK -check-prefix=DL %s
@@ -6,12 +6,12 @@ declare void @foo1()
declare void @foo2()
-define void @test1(i32 %V) {
+define void @test1(i32 %V) !prof !0 {
; CHECK-LABEL: @test1(
; CHECK-NEXT:switch i32 [[V:%.*]], label [[F:%.*]] [
; CHECK-NEXT: i32 17, label [[T:%.*]]
; CHECK-NEXT: i32 4, label [[T]]
-; CHECK-NEXT:]
+; CHECK-NEXT:], !prof [[PROF1:![0-9]+]]
; CHECK: common.ret:
; CHECK-NEXT:ret void
; CHECK: T:
@@ -24,7 +24,7 @@ define void @test1(i32 %V) {
%C1 = icmp eq i32 %V, 4 ; [#uses=1]
%C2 = icmp eq i32 %V, 17; [#uses=1]
%CN = or i1 %C1, %C2; [#uses=1]
- br i1 %CN, label %T, label %F
+ br i1 %CN, label %T, label %F, !prof !1
T: ; preds = %0
call void @foo1( )
ret void
@@ -116,12 +116,12 @@ F: ; preds = %0
ret void
}
-define void @test2(i32 %V) {
+define void @test2(i32 %V) !prof !0 {
; CHECK-LABEL: @test2(
; CHECK-NEXT:switch i32 [[V:%.*]], label [[T:%.*]] [
; CHECK-NEXT: i32 17, label [[F:%.*]]
; CHECK-NEXT:
[llvm-branch-commits] [llvm] [SimplifyCFG][profcheck] Synthesize profile for `br (X == 0 | X == 1), T, F1 -> switch (PR #161549)
mtrofin wrote: > [!WARNING] > This pull request is not mergeable via GitHub because a downstack PR is > open. Once all requirements are satisfied, merge this PR as a stack href="https://app.graphite.dev/github/pr/llvm/llvm-project/161549?utm_source=stack-comment-downstack-mergeability-warning"; > >on Graphite. > https://graphite.dev/docs/merge-pull-requests";>Learn more * **#161549** https://app.graphite.dev/github/pr/llvm/llvm-project/161549?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/161549?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#160629** https://app.graphite.dev/github/pr/llvm/llvm-project/160629?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#159645** https://app.graphite.dev/github/pr/llvm/llvm-project/159645?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * **#159644** https://app.graphite.dev/github/pr/llvm/llvm-project/159644?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/161549 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] 41e817a - release/21.x: [clang-format] Fix bugs in annotating arrows and square brackets (#160973)
Author: owenca
Date: 2025-10-01T15:17:16Z
New Revision: 41e817a1d1f441494cff32175bae407a9cadd8ee
URL:
https://github.com/llvm/llvm-project/commit/41e817a1d1f441494cff32175bae407a9cadd8ee
DIFF:
https://github.com/llvm/llvm-project/commit/41e817a1d1f441494cff32175bae407a9cadd8ee.diff
LOG: release/21.x: [clang-format] Fix bugs in annotating arrows and square
brackets (#160973)
Backport 4edda3d78c26b9d928d115b2059d0c719eec237b
Added:
Modified:
clang/lib/Format/TokenAnnotator.cpp
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp
Removed:
diff --git a/clang/lib/Format/TokenAnnotator.cpp
b/clang/lib/Format/TokenAnnotator.cpp
index cbeb5ef7e4bf4..580996e870f54 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -829,11 +829,6 @@ class AnnotatingParser {
if (Parent && Parent->is(TT_PointerOrReference))
Parent->overwriteFixedType(TT_BinaryOperator);
}
-// An arrow after an ObjC method expression is not a lambda arrow.
-if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next &&
-CurrentToken->Next->is(TT_LambdaArrow)) {
- CurrentToken->Next->overwriteFixedType(TT_Unknown);
-}
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
// FirstObjCSelectorName is set when a colon is found. This does
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp
b/clang/lib/Format/UnwrappedLineParser.cpp
index 91b8fdc8a3c38..934605733542f 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -2266,7 +2266,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
if (!tryToParseLambdaIntroducer())
return false;
- bool SeenArrow = false;
+ FormatToken *Arrow = nullptr;
bool InTemplateParameterList = false;
while (FormatTok->isNot(tok::l_brace)) {
@@ -2341,17 +2341,13 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::ellipsis:
case tok::kw_true:
case tok::kw_false:
- if (SeenArrow || InTemplateParameterList) {
+ if (Arrow || InTemplateParameterList) {
nextToken();
break;
}
return true;
case tok::arrow:
- // This might or might not actually be a lambda arrow (this could be an
- // ObjC method invocation followed by a dereferencing arrow). We might
- // reset this back to TT_Unknown in TokenAnnotator.
- FormatTok->setFinalizedType(TT_LambdaArrow);
- SeenArrow = true;
+ Arrow = FormatTok;
nextToken();
break;
case tok::kw_requires: {
@@ -2373,6 +2369,9 @@ bool UnwrappedLineParser::tryToParseLambda() {
FormatTok->setFinalizedType(TT_LambdaLBrace);
LSquare.setFinalizedType(TT_LambdaLSquare);
+ if (Arrow)
+Arrow->setFinalizedType(TT_LambdaArrow);
+
NestedLambdas.push_back(Line->SeenDecltypeAuto);
parseChildBlock();
assert(!NestedLambdas.empty());
@@ -2386,11 +2385,6 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
const FormatToken *LeftSquare = FormatTok;
nextToken();
if (Previous) {
-if (Previous->Tok.getIdentifierInfo() &&
-!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
- tok::kw_co_return)) {
- return false;
-}
if (Previous->closesScope()) {
// Not a potential C-style cast.
if (Previous->isNot(tok::r_paren))
@@ -2400,6 +2394,13 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
// and `int (*)()`.
if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren))
return false;
+} else if (Previous->is(tok::star)) {
+ Previous = Previous->getPreviousNonComment();
+}
+if (Previous && Previous->Tok.getIdentifierInfo() &&
+!Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield,
+ tok::kw_co_return)) {
+ return false;
}
}
if (LeftSquare->isCppStructuredBinding(IsCpp))
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp
b/clang/unittests/Format/TokenAnnotatorTest.cpp
index 0a3dc946e8c1c..259d7e54133a1 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -2229,6 +2229,12 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) {
ASSERT_EQ(Tokens.size(), 21u) << Tokens;
EXPECT_TOKEN(Tokens[11], tok::l_square, TT_LambdaLSquare);
EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace);
+
+ Tokens = annotate("SomeFunction({[]() -> int *[] { return {}; }});");
+ ASSERT_EQ(Tokens.size(), 22u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::l_square, TT_LambdaLSquare);
+ EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_LambdaDefinitionLParen);
+ EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare);
}
TEST_F(TokenAnnotato
[llvm-branch-commits] [clang] port 5b4819e to release (PR #159209)
https://github.com/dyung updated
https://github.com/llvm/llvm-project/pull/159209
>From 4e9d1b69a64c0d4f71b2c7939f043353730d2bbb Mon Sep 17 00:00:00 2001
From: David Blaikie
Date: Tue, 16 Sep 2025 22:42:55 +
Subject: [PATCH] Port 5b4819e to release/21.x
Fix for the port of 665e875 to release/21.x in PR156664
---
clang/test/CodeGenCXX/debug-info-structured-binding.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp
b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp
index 4a4a4d8bdfaad..8032ce85c9e25 100644
--- a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp
+++ b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp
@@ -10,7 +10,7 @@
// CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg
![[Y1_DEBUG_LOC:[0-9]+]]
// CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg
![[Y2_DEBUG_LOC:[0-9]+]]
// CHECK: load ptr, ptr %z2, {{.*}}!dbg ![[Z2_DEBUG_LOC:[0-9]+]]
-// CHECK: getelementptr inbounds [2 x i32], ptr {{.*}}, i64 0, i64 1, !dbg
![[A2_DEBUG_LOC:[0-9]+]]
+// CHECK: getelementptr inbounds [2 x i32], ptr {{.*}}, i{{64|32}} 0,
i{{64|32}} 1, !dbg ![[A2_DEBUG_LOC:[0-9]+]]
// CHECK: getelementptr inbounds nuw { i32, i32 }, ptr {{.*}}, i32 0, i32 1,
!dbg ![[C2_DEBUG_LOC:[0-9]+]]
// CHECK: extractelement <2 x i32> {{.*}}, i32 1, !dbg ![[V2_DEBUG_LOC:[0-9]+]]
// CHECK: ![[VAR_0]] = !DILocalVariable(name: "a"
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [IR2Vec] Refactor vocabulary to use section-based storage (PR #158376)
https://github.com/svkeerthy updated
https://github.com/llvm/llvm-project/pull/158376
>From 51681f2f98ac43b629d7198f1d0d226f84cc500c Mon Sep 17 00:00:00 2001
From: svkeerthy
Date: Fri, 12 Sep 2025 22:06:44 +
Subject: [PATCH] VocabStorage
---
llvm/include/llvm/Analysis/IR2Vec.h | 218 ---
llvm/lib/Analysis/IR2Vec.cpp | 256 +++--
llvm/lib/Analysis/InlineAdvisor.cpp | 2 +-
llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp| 6 +-
.../FunctionPropertiesAnalysisTest.cpp| 13 +-
llvm/unittests/Analysis/IR2VecTest.cpp| 347 --
6 files changed, 648 insertions(+), 194 deletions(-)
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h
b/llvm/include/llvm/Analysis/IR2Vec.h
index f3f9de460218b..b7c301580a8a4 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -45,6 +45,7 @@
#include "llvm/Support/JSON.h"
#include
#include
+#include
namespace llvm {
@@ -144,6 +145,73 @@ struct Embedding {
using InstEmbeddingsMap = DenseMap;
using BBEmbeddingsMap = DenseMap;
+/// Generic storage class for section-based vocabularies.
+/// VocabStorage provides a generic foundation for storing and accessing
+/// embeddings organized into sections.
+class VocabStorage {
+private:
+ /// Section-based storage
+ std::vector> Sections;
+
+ const size_t TotalSize;
+ const unsigned Dimension;
+
+public:
+ /// Default constructor creates empty storage (invalid state)
+ VocabStorage() : Sections(), TotalSize(0), Dimension(0) {}
+
+ /// Create a VocabStorage with pre-organized section data
+ VocabStorage(std::vector> &&SectionData);
+
+ VocabStorage(VocabStorage &&) = default;
+ VocabStorage &operator=(VocabStorage &&) = delete;
+
+ VocabStorage(const VocabStorage &) = delete;
+ VocabStorage &operator=(const VocabStorage &) = delete;
+
+ /// Get total number of entries across all sections
+ size_t size() const { return TotalSize; }
+
+ /// Get number of sections
+ unsigned getNumSections() const {
+return static_cast(Sections.size());
+ }
+
+ /// Section-based access: Storage[sectionId][localIndex]
+ const std::vector &operator[](unsigned SectionId) const {
+assert(SectionId < Sections.size() && "Invalid section ID");
+return Sections[SectionId];
+ }
+
+ /// Get vocabulary dimension
+ unsigned getDimension() const { return Dimension; }
+
+ /// Check if vocabulary is valid (has data)
+ bool isValid() const { return TotalSize > 0; }
+
+ /// Iterator support for section-based access
+ class const_iterator {
+const VocabStorage *Storage;
+unsigned SectionId = 0;
+size_t LocalIndex = 0;
+
+ public:
+const_iterator(const VocabStorage *Storage, unsigned SectionId,
+ size_t LocalIndex)
+: Storage(Storage), SectionId(SectionId), LocalIndex(LocalIndex) {}
+
+LLVM_ABI const Embedding &operator*() const;
+LLVM_ABI const_iterator &operator++();
+LLVM_ABI bool operator==(const const_iterator &Other) const;
+LLVM_ABI bool operator!=(const const_iterator &Other) const;
+ };
+
+ const_iterator begin() const { return const_iterator(this, 0, 0); }
+ const_iterator end() const {
+return const_iterator(this, getNumSections(), 0);
+ }
+};
+
/// Class for storing and accessing the IR2Vec vocabulary.
/// The Vocabulary class manages seed embeddings for LLVM IR entities. The
/// seed embeddings are the initial learned representations of the entities
@@ -164,7 +232,7 @@ using BBEmbeddingsMap = DenseMap;
class Vocabulary {
friend class llvm::IR2VecVocabAnalysis;
- // Vocabulary Slot Layout:
+ // Vocabulary Layout:
// ++--+
// | Entity Type| Index Range |
// ++--+
@@ -180,8 +248,16 @@ class Vocabulary {
// and improves learning. Operands include Comparison predicates
// (ICmp/FCmp) along with other operand types. This can be extended to
// include other specializations in future.
- using VocabVector = std::vector;
- VocabVector Vocab;
+ enum class Section : unsigned {
+Opcodes = 0,
+CanonicalTypes = 1,
+Operands = 2,
+Predicates = 3,
+MaxSections
+ };
+
+ // Use section-based storage for better organization and efficiency
+ VocabStorage Storage;
static constexpr unsigned NumICmpPredicates =
static_cast(CmpInst::LAST_ICMP_PREDICATE) -
@@ -233,10 +309,23 @@ class Vocabulary {
NumICmpPredicates + NumFCmpPredicates;
Vocabulary() = default;
- LLVM_ABI Vocabulary(VocabVector &&Vocab) : Vocab(std::move(Vocab)) {}
+ LLVM_ABI Vocabulary(VocabStorage &&Storage) : Storage(std::move(Storage)) {}
+
+ Vocabulary(const Vocabulary &) = delete;
+ Vocabulary &operator=(const Vocabulary &) = delete;
+
+ Vocabulary(Vocabulary &&) = default;
+ Vocabulary &operator=(
[llvm-branch-commits] [llvm] [IR2Vec] Refactor vocabulary to use section-based storage (PR #158376)
https://github.com/svkeerthy updated
https://github.com/llvm/llvm-project/pull/158376
>From 51681f2f98ac43b629d7198f1d0d226f84cc500c Mon Sep 17 00:00:00 2001
From: svkeerthy
Date: Fri, 12 Sep 2025 22:06:44 +
Subject: [PATCH] VocabStorage
---
llvm/include/llvm/Analysis/IR2Vec.h | 218 ---
llvm/lib/Analysis/IR2Vec.cpp | 256 +++--
llvm/lib/Analysis/InlineAdvisor.cpp | 2 +-
llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp| 6 +-
.../FunctionPropertiesAnalysisTest.cpp| 13 +-
llvm/unittests/Analysis/IR2VecTest.cpp| 347 --
6 files changed, 648 insertions(+), 194 deletions(-)
diff --git a/llvm/include/llvm/Analysis/IR2Vec.h
b/llvm/include/llvm/Analysis/IR2Vec.h
index f3f9de460218b..b7c301580a8a4 100644
--- a/llvm/include/llvm/Analysis/IR2Vec.h
+++ b/llvm/include/llvm/Analysis/IR2Vec.h
@@ -45,6 +45,7 @@
#include "llvm/Support/JSON.h"
#include
#include
+#include
namespace llvm {
@@ -144,6 +145,73 @@ struct Embedding {
using InstEmbeddingsMap = DenseMap;
using BBEmbeddingsMap = DenseMap;
+/// Generic storage class for section-based vocabularies.
+/// VocabStorage provides a generic foundation for storing and accessing
+/// embeddings organized into sections.
+class VocabStorage {
+private:
+ /// Section-based storage
+ std::vector> Sections;
+
+ const size_t TotalSize;
+ const unsigned Dimension;
+
+public:
+ /// Default constructor creates empty storage (invalid state)
+ VocabStorage() : Sections(), TotalSize(0), Dimension(0) {}
+
+ /// Create a VocabStorage with pre-organized section data
+ VocabStorage(std::vector> &&SectionData);
+
+ VocabStorage(VocabStorage &&) = default;
+ VocabStorage &operator=(VocabStorage &&) = delete;
+
+ VocabStorage(const VocabStorage &) = delete;
+ VocabStorage &operator=(const VocabStorage &) = delete;
+
+ /// Get total number of entries across all sections
+ size_t size() const { return TotalSize; }
+
+ /// Get number of sections
+ unsigned getNumSections() const {
+return static_cast(Sections.size());
+ }
+
+ /// Section-based access: Storage[sectionId][localIndex]
+ const std::vector &operator[](unsigned SectionId) const {
+assert(SectionId < Sections.size() && "Invalid section ID");
+return Sections[SectionId];
+ }
+
+ /// Get vocabulary dimension
+ unsigned getDimension() const { return Dimension; }
+
+ /// Check if vocabulary is valid (has data)
+ bool isValid() const { return TotalSize > 0; }
+
+ /// Iterator support for section-based access
+ class const_iterator {
+const VocabStorage *Storage;
+unsigned SectionId = 0;
+size_t LocalIndex = 0;
+
+ public:
+const_iterator(const VocabStorage *Storage, unsigned SectionId,
+ size_t LocalIndex)
+: Storage(Storage), SectionId(SectionId), LocalIndex(LocalIndex) {}
+
+LLVM_ABI const Embedding &operator*() const;
+LLVM_ABI const_iterator &operator++();
+LLVM_ABI bool operator==(const const_iterator &Other) const;
+LLVM_ABI bool operator!=(const const_iterator &Other) const;
+ };
+
+ const_iterator begin() const { return const_iterator(this, 0, 0); }
+ const_iterator end() const {
+return const_iterator(this, getNumSections(), 0);
+ }
+};
+
/// Class for storing and accessing the IR2Vec vocabulary.
/// The Vocabulary class manages seed embeddings for LLVM IR entities. The
/// seed embeddings are the initial learned representations of the entities
@@ -164,7 +232,7 @@ using BBEmbeddingsMap = DenseMap;
class Vocabulary {
friend class llvm::IR2VecVocabAnalysis;
- // Vocabulary Slot Layout:
+ // Vocabulary Layout:
// ++--+
// | Entity Type| Index Range |
// ++--+
@@ -180,8 +248,16 @@ class Vocabulary {
// and improves learning. Operands include Comparison predicates
// (ICmp/FCmp) along with other operand types. This can be extended to
// include other specializations in future.
- using VocabVector = std::vector;
- VocabVector Vocab;
+ enum class Section : unsigned {
+Opcodes = 0,
+CanonicalTypes = 1,
+Operands = 2,
+Predicates = 3,
+MaxSections
+ };
+
+ // Use section-based storage for better organization and efficiency
+ VocabStorage Storage;
static constexpr unsigned NumICmpPredicates =
static_cast(CmpInst::LAST_ICMP_PREDICATE) -
@@ -233,10 +309,23 @@ class Vocabulary {
NumICmpPredicates + NumFCmpPredicates;
Vocabulary() = default;
- LLVM_ABI Vocabulary(VocabVector &&Vocab) : Vocab(std::move(Vocab)) {}
+ LLVM_ABI Vocabulary(VocabStorage &&Storage) : Storage(std::move(Storage)) {}
+
+ Vocabulary(const Vocabulary &) = delete;
+ Vocabulary &operator=(const Vocabulary &) = delete;
+
+ Vocabulary(Vocabulary &&) = default;
+ Vocabulary &operator=(
[llvm-branch-commits] [llvm] [AMDGPU][SIInsertWaitCnts] Remove redundant TII/TRI/MRI arguments (NFC) (PR #161357)
Pierre-vh wrote: ### Merge activity * **Oct 1, 8:51 AM UTC**: A user started a stack merge that includes this pull request via [Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/161357). https://github.com/llvm/llvm-project/pull/161357 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] release/21.x: [clang-format] Fix bugs in annotating arrows and square… (PR #161052)
https://github.com/mydeveloperday approved this pull request. https://github.com/llvm/llvm-project/pull/161052 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [AArch64][SME] Reshuffle emit[prologue|epilogue]() for splitSVEObjects (NFCI) (PR #161217)
https://github.com/sdesmalen-arm edited https://github.com/llvm/llvm-project/pull/161217 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: make use of C++17 features and LLVM helpers (PR #141665)
https://github.com/atrosinenko updated
https://github.com/llvm/llvm-project/pull/141665
>From 3ac1bf12ee9acd480be7125132f4d78e37727c42 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko
Date: Tue, 27 May 2025 21:06:03 +0300
Subject: [PATCH] [BOLT] Gadget scanner: make use of C++17 features and LLVM
helpers
Perform trivial syntactical cleanups:
* make use of structured binding declarations
* use LLVM utility functions when appropriate
* omit braces around single expression inside single-line LLVM_DEBUG()
This patch is NFC aside from minor debug output changes.
---
bolt/lib/Passes/PAuthGadgetScanner.cpp| 60 +--
.../AArch64/gs-pauth-debug-output.s | 14 ++---
2 files changed, 35 insertions(+), 39 deletions(-)
diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp
b/bolt/lib/Passes/PAuthGadgetScanner.cpp
index fa5db960de335..b032561a43274 100644
--- a/bolt/lib/Passes/PAuthGadgetScanner.cpp
+++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp
@@ -88,8 +88,8 @@ class TrackedRegisters {
TrackedRegisters(ArrayRef RegsToTrack)
: Registers(RegsToTrack),
RegToIndexMapping(getMappingSize(RegsToTrack), NoIndex) {
-for (unsigned I = 0; I < RegsToTrack.size(); ++I)
- RegToIndexMapping[RegsToTrack[I]] = I;
+for (auto [MappedIndex, Reg] : llvm::enumerate(RegsToTrack))
+ RegToIndexMapping[Reg] = MappedIndex;
}
ArrayRef getRegisters() const { return Registers; }
@@ -203,9 +203,9 @@ struct SrcState {
SafeToDerefRegs &= StateIn.SafeToDerefRegs;
TrustedRegs &= StateIn.TrustedRegs;
-for (unsigned I = 0; I < LastInstWritingReg.size(); ++I)
- for (const MCInst *J : StateIn.LastInstWritingReg[I])
-LastInstWritingReg[I].insert(J);
+for (auto [ThisSet, OtherSet] :
+ llvm::zip_equal(LastInstWritingReg, StateIn.LastInstWritingReg))
+ ThisSet.insert_range(OtherSet);
return *this;
}
@@ -224,11 +224,9 @@ struct SrcState {
static void printInstsShort(raw_ostream &OS,
ArrayRef Insts) {
OS << "Insts: ";
- for (unsigned I = 0; I < Insts.size(); ++I) {
-auto &Set = Insts[I];
+ for (auto [I, PtrSet] : llvm::enumerate(Insts)) {
OS << "[" << I << "](";
-for (const MCInst *MCInstP : Set)
- OS << MCInstP << " ";
+interleave(PtrSet, OS, " ");
OS << ")";
}
}
@@ -416,8 +414,9 @@ class SrcSafetyAnalysis {
// ... an address can be updated in a safe manner, producing the result
// which is as trusted as the input address.
if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) {
- if (Cur.SafeToDerefRegs[DstAndSrc->second])
-Regs.push_back(DstAndSrc->first);
+ auto [DstReg, SrcReg] = *DstAndSrc;
+ if (Cur.SafeToDerefRegs[SrcReg])
+Regs.push_back(DstReg);
}
// Make sure explicit checker sequence keeps register safe-to-dereference
@@ -469,8 +468,9 @@ class SrcSafetyAnalysis {
// ... an address can be updated in a safe manner, producing the result
// which is as trusted as the input address.
if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) {
- if (Cur.TrustedRegs[DstAndSrc->second])
-Regs.push_back(DstAndSrc->first);
+ auto [DstReg, SrcReg] = *DstAndSrc;
+ if (Cur.TrustedRegs[SrcReg])
+Regs.push_back(DstReg);
}
return Regs;
@@ -865,9 +865,9 @@ struct DstState {
return (*this = StateIn);
CannotEscapeUnchecked &= StateIn.CannotEscapeUnchecked;
-for (unsigned I = 0; I < FirstInstLeakingReg.size(); ++I)
- for (const MCInst *J : StateIn.FirstInstLeakingReg[I])
-FirstInstLeakingReg[I].insert(J);
+for (auto [ThisSet, OtherSet] :
+ llvm::zip_equal(FirstInstLeakingReg, StateIn.FirstInstLeakingReg))
+ ThisSet.insert_range(OtherSet);
return *this;
}
@@ -1033,8 +1033,7 @@ class DstSafetyAnalysis {
// ... an address can be updated in a safe manner, or
if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Inst)) {
- MCPhysReg DstReg, SrcReg;
- std::tie(DstReg, SrcReg) = *DstAndSrc;
+ auto [DstReg, SrcReg] = *DstAndSrc;
// Note that *all* registers containing the derived values must be safe,
// both source and destination ones. No temporaries are supported at now.
if (Cur.CannotEscapeUnchecked[SrcReg] &&
@@ -1074,7 +1073,7 @@ class DstSafetyAnalysis {
// If this instruction terminates the program immediately, no
// authentication oracles are possible past this point.
if (BC.MIB->isTrap(Point)) {
- LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); });
+ LLVM_DEBUG(traceInst(BC, "Trap instruction found", Point));
DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters());
Next.CannotEscapeUnchecked.set();
return Next;
@@ -1249,7 +1248,7 @@ class CFGUnawareDstSafetyAnalysis : public
DstSafetyAnalysis,
// starting to analyze Inst.
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: make use of C++17 features and LLVM helpers (PR #141665)
https://github.com/atrosinenko updated
https://github.com/llvm/llvm-project/pull/141665
>From 3ac1bf12ee9acd480be7125132f4d78e37727c42 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko
Date: Tue, 27 May 2025 21:06:03 +0300
Subject: [PATCH] [BOLT] Gadget scanner: make use of C++17 features and LLVM
helpers
Perform trivial syntactical cleanups:
* make use of structured binding declarations
* use LLVM utility functions when appropriate
* omit braces around single expression inside single-line LLVM_DEBUG()
This patch is NFC aside from minor debug output changes.
---
bolt/lib/Passes/PAuthGadgetScanner.cpp| 60 +--
.../AArch64/gs-pauth-debug-output.s | 14 ++---
2 files changed, 35 insertions(+), 39 deletions(-)
diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp
b/bolt/lib/Passes/PAuthGadgetScanner.cpp
index fa5db960de335..b032561a43274 100644
--- a/bolt/lib/Passes/PAuthGadgetScanner.cpp
+++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp
@@ -88,8 +88,8 @@ class TrackedRegisters {
TrackedRegisters(ArrayRef RegsToTrack)
: Registers(RegsToTrack),
RegToIndexMapping(getMappingSize(RegsToTrack), NoIndex) {
-for (unsigned I = 0; I < RegsToTrack.size(); ++I)
- RegToIndexMapping[RegsToTrack[I]] = I;
+for (auto [MappedIndex, Reg] : llvm::enumerate(RegsToTrack))
+ RegToIndexMapping[Reg] = MappedIndex;
}
ArrayRef getRegisters() const { return Registers; }
@@ -203,9 +203,9 @@ struct SrcState {
SafeToDerefRegs &= StateIn.SafeToDerefRegs;
TrustedRegs &= StateIn.TrustedRegs;
-for (unsigned I = 0; I < LastInstWritingReg.size(); ++I)
- for (const MCInst *J : StateIn.LastInstWritingReg[I])
-LastInstWritingReg[I].insert(J);
+for (auto [ThisSet, OtherSet] :
+ llvm::zip_equal(LastInstWritingReg, StateIn.LastInstWritingReg))
+ ThisSet.insert_range(OtherSet);
return *this;
}
@@ -224,11 +224,9 @@ struct SrcState {
static void printInstsShort(raw_ostream &OS,
ArrayRef Insts) {
OS << "Insts: ";
- for (unsigned I = 0; I < Insts.size(); ++I) {
-auto &Set = Insts[I];
+ for (auto [I, PtrSet] : llvm::enumerate(Insts)) {
OS << "[" << I << "](";
-for (const MCInst *MCInstP : Set)
- OS << MCInstP << " ";
+interleave(PtrSet, OS, " ");
OS << ")";
}
}
@@ -416,8 +414,9 @@ class SrcSafetyAnalysis {
// ... an address can be updated in a safe manner, producing the result
// which is as trusted as the input address.
if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) {
- if (Cur.SafeToDerefRegs[DstAndSrc->second])
-Regs.push_back(DstAndSrc->first);
+ auto [DstReg, SrcReg] = *DstAndSrc;
+ if (Cur.SafeToDerefRegs[SrcReg])
+Regs.push_back(DstReg);
}
// Make sure explicit checker sequence keeps register safe-to-dereference
@@ -469,8 +468,9 @@ class SrcSafetyAnalysis {
// ... an address can be updated in a safe manner, producing the result
// which is as trusted as the input address.
if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) {
- if (Cur.TrustedRegs[DstAndSrc->second])
-Regs.push_back(DstAndSrc->first);
+ auto [DstReg, SrcReg] = *DstAndSrc;
+ if (Cur.TrustedRegs[SrcReg])
+Regs.push_back(DstReg);
}
return Regs;
@@ -865,9 +865,9 @@ struct DstState {
return (*this = StateIn);
CannotEscapeUnchecked &= StateIn.CannotEscapeUnchecked;
-for (unsigned I = 0; I < FirstInstLeakingReg.size(); ++I)
- for (const MCInst *J : StateIn.FirstInstLeakingReg[I])
-FirstInstLeakingReg[I].insert(J);
+for (auto [ThisSet, OtherSet] :
+ llvm::zip_equal(FirstInstLeakingReg, StateIn.FirstInstLeakingReg))
+ ThisSet.insert_range(OtherSet);
return *this;
}
@@ -1033,8 +1033,7 @@ class DstSafetyAnalysis {
// ... an address can be updated in a safe manner, or
if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Inst)) {
- MCPhysReg DstReg, SrcReg;
- std::tie(DstReg, SrcReg) = *DstAndSrc;
+ auto [DstReg, SrcReg] = *DstAndSrc;
// Note that *all* registers containing the derived values must be safe,
// both source and destination ones. No temporaries are supported at now.
if (Cur.CannotEscapeUnchecked[SrcReg] &&
@@ -1074,7 +1073,7 @@ class DstSafetyAnalysis {
// If this instruction terminates the program immediately, no
// authentication oracles are possible past this point.
if (BC.MIB->isTrap(Point)) {
- LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); });
+ LLVM_DEBUG(traceInst(BC, "Trap instruction found", Point));
DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters());
Next.CannotEscapeUnchecked.set();
return Next;
@@ -1249,7 +1248,7 @@ class CFGUnawareDstSafetyAnalysis : public
DstSafetyAnalysis,
// starting to analyze Inst.
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: optionally assume auth traps on failure (PR #139778)
https://github.com/atrosinenko updated
https://github.com/llvm/llvm-project/pull/139778
>From 5f07ab9ee7ea514d20d3b9da5f225d68028208b5 Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko
Date: Tue, 13 May 2025 19:50:41 +0300
Subject: [PATCH 1/2] [BOLT] Gadget scanner: optionally assume auth traps on
failure
On AArch64 it is possible for an auth instruction to either return an
invalid address value on failure (without FEAT_FPAC) or generate an
error (with FEAT_FPAC). It thus may be possible to never emit explicit
pointer checks, if the target CPU is known to support FEAT_FPAC.
This commit implements an --auth-traps-on-failure command line option,
which essentially makes "safe-to-dereference" and "trusted" register
properties identical and disables scanning for authentication oracles
completely.
---
bolt/lib/Passes/PAuthGadgetScanner.cpp| 112 +++
.../binary-analysis/AArch64/cmdline-args.test | 1 +
.../AArch64/gs-pauth-authentication-oracles.s | 6 +-
.../binary-analysis/AArch64/gs-pauth-calls.s | 5 +-
.../AArch64/gs-pauth-debug-output.s | 177 ++---
.../AArch64/gs-pauth-signing-oracles.s| 54 ++---
.../AArch64/gs-pauth-tail-calls.s | 184 +-
7 files changed, 314 insertions(+), 225 deletions(-)
diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp
b/bolt/lib/Passes/PAuthGadgetScanner.cpp
index d3e81dbe91138..c6d3981cbb679 100644
--- a/bolt/lib/Passes/PAuthGadgetScanner.cpp
+++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp
@@ -14,6 +14,7 @@
#include "bolt/Passes/PAuthGadgetScanner.h"
#include "bolt/Core/ParallelUtilities.h"
#include "bolt/Passes/DataflowAnalysis.h"
+#include "bolt/Utils/CommandLineOpts.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/MC/MCInst.h"
@@ -26,6 +27,11 @@ namespace llvm {
namespace bolt {
namespace PAuthGadgetScanner {
+static cl::opt AuthTrapsOnFailure(
+"auth-traps-on-failure",
+cl::desc("Assume authentication instructions always trap on failure"),
+cl::cat(opts::BinaryAnalysisCategory));
+
[[maybe_unused]] static void traceInst(const BinaryContext &BC, StringRef
Label,
const MCInst &MI) {
dbgs() << " " << Label << ": ";
@@ -364,6 +370,34 @@ class SrcSafetyAnalysis {
return Clobbered;
}
+ std::optional getRegMadeTrustedByChecking(const MCInst &Inst,
+ SrcState Cur) const {
+// This functions cannot return multiple registers. This is never the case
+// on AArch64.
+std::optional RegCheckedByInst =
+BC.MIB->getAuthCheckedReg(Inst, /*MayOverwrite=*/false);
+if (RegCheckedByInst && Cur.SafeToDerefRegs[*RegCheckedByInst])
+ return *RegCheckedByInst;
+
+auto It = CheckerSequenceInfo.find(&Inst);
+if (It == CheckerSequenceInfo.end())
+ return std::nullopt;
+
+MCPhysReg RegCheckedBySequence = It->second.first;
+const MCInst *FirstCheckerInst = It->second.second;
+
+// FirstCheckerInst should belong to the same basic block (see the
+// assertion in DataflowSrcSafetyAnalysis::run()), meaning it was
+// deterministically processed a few steps before this instruction.
+const SrcState &StateBeforeChecker = getStateBefore(*FirstCheckerInst);
+
+// The sequence checks the register, but it should be authenticated before.
+if (!StateBeforeChecker.SafeToDerefRegs[RegCheckedBySequence])
+ return std::nullopt;
+
+return RegCheckedBySequence;
+ }
+
// Returns all registers that can be treated as if they are written by an
// authentication instruction.
SmallVector getRegsMadeSafeToDeref(const MCInst &Point,
@@ -386,18 +420,38 @@ class SrcSafetyAnalysis {
Regs.push_back(DstAndSrc->first);
}
+// Make sure explicit checker sequence keeps register safe-to-dereference
+// when the register would be clobbered according to the regular rules:
+//
+//; LR is safe to dereference here
+//mov x16, x30 ; start of the sequence, LR is s-t-d right before
+//xpaclri ; clobbers LR, LR is not safe anymore
+//cmp x30, x16
+//b.eq 1f; end of the sequence: LR is marked as trusted
+//brk 0x1234
+// 1:
+//; at this point LR would be marked as trusted,
+//; but not safe-to-dereference
+//
+// or even just
+//
+//; X1 is safe to dereference here
+//ldr x0, [x1, #8]!
+//; X1 is trusted here, but it was clobbered due to address write-back
+if (auto CheckedReg = getRegMadeTrustedByChecking(Point, Cur))
+ Regs.push_back(*CheckedReg);
+
return Regs;
}
// Returns all registers made trusted by this instruction.
SmallVector getRegsMadeTrusted(const MCInst &Point,
const SrcState &Cur) const {
+assert(!AuthTrapsOnFailure && "Use getRegsMadeSafeToDeref instead");
SmallVe
