[LifetimeSafety][NFC] Refactor AccessPath and Loan representations
(#180369)
This patch refactors the internal representations of `AccessPath` and
`Loan` to support path elements, preparing for field-sensitive and
interior-sensitive lifetime tracking.
* Introduces `PathElement` representing a field or interior dereference.
* Refactors `AccessPath` to contain a base and a list of `PathElement`s.
* Updates `Loan` and `LoanManager` to use the new `AccessPath`
structure.
---
Old PR description:
Refactor loan representation to use structured access paths, enabling
more precise borrow tracking and detection of use-after-invalidation.
Previously, loans were associated only with top-level storage (e.g., a
variable `x`, temporary `t`). This was insufficient for reasoning about
[32 lines not shown]
[AArch64] Remove unused GPR32arg register class (NFC) (#211778)
GPR32arg was added alongside GPR64arg in fcbec02ea6fb, but has no users
outside the register info generated by TableGen.
Assisted-by: codex
[flang] Add an example plugin exercising the HLFIR pipeline extension points
The HLFIR extension points, the config augmentor registry and fir-opt's symbol
export exist to let an out-of-tree MLIR pass run while the HLFIR intrinsic
operations (hlfir.sum, hlfir.matmul, ...) are still present. None of that was
covered end to end, and there was no worked example of how to use it.
Add flang/examples/HLFIRPipelinePlugin, modelled on PrintFlangFunctionNames. It
contributes a pass that prints the HLFIR operations still present in the
module, tagged with the pipeline position it was inserted at, and exposes it
through both plugin entry points: a static initializer calling
fir::registerPassPipelineConfigCallback for the `flang -fc1 -load` path, and
mlirGetPassPluginInfo so fir-opt can load it with --load-pass-plugin.
Nothing is linked into the shared object: MLIR, FIR and flang symbols resolve
against the host tool, which is what export_executable_symbols_for_plugins on
flang and fir-opt provides. Removing the fir-opt export drops it from ~105k
exported dynamic symbols to one and makes --load-pass-plugin fail to load.
[7 lines not shown]
[flang] Add a pass-pipeline config-augmentor hook for -load'ed plugins
The HLFIR-to-FIR pass pipeline exposes extension points on
MLIRToLLVMPassPipelineConfig, but that config is built inside the frontend, so
a -load'ed plugin has no way to reach it and register passes.
registerDefaultInlinerPass is the only augmentor today, and it is wired in by
hand.
Add a global registry of config augmentors:
* fir::registerPassPipelineConfigCallback(cb) appends a callback, to be
called from a plugin's static initializer at -load time.
* fir::invokePassPipelineConfigCallbacks(config) runs them on the config.
This mirrors what flang already does for -load'ed plugin actions via
FrontendPluginRegistry: a process-global, append-only registry populated from
static initializers, which run before any compilation begins.
Both code generation entry points invoke the callbacks after building their
[11 lines not shown]
[flang] Add HLFIR-to-FIR pass pipeline extension points
The FIR optimizer extension points (FIROptEarly, FIRInliner, FIROptLast) all
run after HLFIR has been lowered to FIR, so the HLFIR intrinsic operations
(hlfir.sum, hlfir.matmul, ...) are gone by the time they run. Transformations
that need to see those operations -- for example automatic differentiation via
Enzyme-MLIR -- have nowhere to attach.
Add two extension points to createHLFIRToFIRPassPipeline:
* HLFIROptEarly, at the start of the pipeline, before any HLFIR
simplification or inlining.
* HLFIROptLast, just before createLowerHLFIRIntrinsics.
Drivers register passes through registerHLFIROptEarlyEPCallbacks and
registerHLFIROptLastEPCallbacks on MLIRToLLVMPassPipelineConfig. The invoke
methods are const so they can be called on the const config the HLFIR pipeline
receives. With no callbacks registered the pipeline is unchanged.
[5 lines not shown]
[llvm][release] Build openmp as runtime in test-release.sh (#212111)
`test_release.sh` tries to build `openmp` as a project, which breaks the
build:
```
CMake Error at CMakeLists.txt:155 (message):
Support for the LLVM_ENABLE_PROJECTS=openmp build mode has been removed.
Please switch to the bootstrapping build
cmake -S <llvm-project>/llvm -B build -DLLVM_ENABLE_PROJECTS=clang -DLLVM_ENABLE_RUNTIMES=openmp
or to the runtimes default build
cmake -S <llvm-project>/runtimes -B build -DLLVM_ENABLE_RUNTIMES=openmp
```
This patch switches it to a runtime to match.
Tested on `x86_64-pc-linux-gnu`.
[SelectionDAG] Stop forming minnum/maxnum in SDAGBuilder (#187738)
The right place to form these is DAGCombine, not SDAGBuilder. This
removes the SPNB_RETURNS_ANY case, the SPNB_RETURNS_OTHER is left to a
followup. We need to propagate FMF flags in a few more places to make
this work.
MSP430: Mark more generic libgcc functions as available (#210962)
The generic soft-float, conversion, comparison and integer helper
routines (__addsf3, __divli's __divsi3, __ashlsi3, ...) exist in the MSP430
libgcc port alongside the preferred __mspabi_* variants. They were previously
removed to force selection of the __mspabi_* names, back when only one
implementation per libcall could be recorded.
Stop hiding them: only __lshrsi3 stays excluded, since the MSP430 libgcc
port provides the 32-bit logical right shift solely under __mspabi_srll and
never defines a generic __lshrsi3.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
[sanitizer_common][tests] Skip MemoryMapping::ParseUnixMemoryProfile … (#212114)
…etc. on NetBSD
The `Sanitizer-x86_64-Test` test doesn't link on NetBSD/amd64 10.1:
```
/usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x25
SANITIZER_TEST_OBJECTS.sanitizer_procmaps_test.cpp.x86_64.o: in function `__sanitizer::MemoryMapping_ParseUnixMemoryProfile_Test::TestBody()':
sanitizer_procmaps_test.cpp:(.text._ZN11__sanitizer41MemoryMapping_ParseUnixMemoryProfile_Test8TestBodyEv+0x52): undefined reference to `__sanitizer::ParseUnixMemoryProfile(void (*)(unsigned long, unsigned long, bool, unsigned long*), unsigned long*, char*, unsigned long)'
/usr/bin/ld: SANITIZER_TEST_OBJECTS.sanitizer_procmaps_test.cpp.x86_64.o: in function `__sanitizer::MemoryMapping_ParseUnixMemoryProfileTruncated_Test::TestBody()':
sanitizer_procmaps_test.cpp:(.text._ZN11__sanitizer50MemoryMapping_ParseUnixMemoryProfileTruncated_Test8TestBodyEv+0x17a): undefined reference to `__sanitizer::ParseUnixMemoryProfile(void (*)(unsigned long, unsigned long, bool, unsigned long*), unsigned long*, char*, unsigned long)'
```
Fixed by skipping the affected subtest.
Tested on `amd64-pc-netbsd10.1` and `x86_64-pc-linux-gnu`.
[LifetimeSafety] Support field-sensitivity in lifetime tracking
This patch enables field-sensitivity when tracking lifetimes of nested objects.
- FactsGenerator now generates `PathElement::getField` for `MemberExpr` accesses, mapping fields to loans.
- LoanPropagation now propagates field paths along flow facts, appending fields to base loans.
- Removes false-positive warnings in `invalidations.cpp` where modifications to one field were incorrectly reported as invalidating iterators/pointers to another field.
- Adds comprehensive unit tests checking nested field access and placeholder fields.
TAG=agy
CONV=2cfd8d00-18d7-4a03-8d78-2aba2f9a8f23
[LifetimeSafety][NFC] Update Checker to use prefix comparison interfaces
This patch switches the Checker's expiry and invalidation checks to use `AccessPath::isPrefixOf` instead of equality (`==`).
Since all generated access paths are currently empty, `isPrefixOf` is behaviorally identical to `==` (NFC). This prepares the checker to handle nested paths (fields and container interiors) in subsequent commits.
TAG=agy
CONV=2cfd8d00-18d7-4a03-8d78-2aba2f9a8f23
[LifetimeSafety] Support container interior paths and invalidations
This patch completes the implementation of path-sensitive lifetime tracking by supporting container interior paths (`.*`) and deep-nested invalidation.
- Enables `PathElement::getInterior` generation in `FactsGenerator` for GSL Owners and Views (e.g. member functions, function parameters, lambda captures).
- Removes bypass checks in `FactsGenerator::handleInvalidatingCall` to track container invalidation on fields.
- Updates `Checker` to use strict prefix comparison (`isStrictPrefixOf`) for container invalidations, ensuring invalidation of container contents (interior) correctly invalidates iterators but not other sibling fields.
- Reorganizes tests in `invalidations.cpp` by resolving duplicates and distributing them logically.
- Updates unit tests and sema tests with correct expectations for interior paths.
TAG=agy
CONV=2cfd8d00-18d7-4a03-8d78-2aba2f9a8f23
[LifetimeSafety][NFC] Refactor AccessPath and Loan representations
This patch refactors the internal representations of `AccessPath` and `Loan` to support path elements, preparing for field-sensitive and interior-sensitive lifetime tracking.
- Introduces `PathElement` representing a field or interior dereference.
- Refactors `AccessPath` to contain a base and a list of `PathElement`s.
- Updates `Loan` and `LoanManager` to use the new `AccessPath` structure.
- Refactors debug dump formatting to output path elements if present.
- Updates Checker and FactsGenerator to compile with the new interfaces, keeping logic behaviorally identical (NFC).
TAG=agy
CONV=2cfd8d00-18d7-4a03-8d78-2aba2f9a8f23
[ELF] Fix -Wc++11-narrowing error in addPltEntry (#212185)
PR #212161 passes the `uint8_t isPreemptible : 1` bit-field straight
into a braced-init-list slot whose parameter type is `bool`.
Older clang (<20 ?) incorrectly rejects it.
```
error: non-constant-expression cannot be narrowed from type 'uint8_t' (aka 'unsigned char') to 'bool' in initializer list [-Wc++11-narrowing]
```
[AArch64] Mark ZT0 register class as non-allocatable (#211750)
ZT0 is not available for register allocation, define it with the other
non-allocatable SME register classes and avoid an unnecessary pressure
set.
Assisted-by: codex
[orc-rt] Session::HandlerTag -> orc_rt_ControllerHandlerTag (#212173)
Replace the `Session::HandlerTag = void*` type alias with
orc_rt_ControllerHandlerTag. The intent is both to make this type
accessible to the C API, and to rename it to clarify its role as a tag
for handlers in the controller that are callable by the executor.
[DomTree] Define the members calling the construction algorithms out of line. NFC (#212145)
DominatorTreeBase defines some functions that call into into
DomTreeBuilder, whose algorithms live in GenericDomTreeConstruction.h.
A translation unit including only GenericDomTree.h inlines the member
and calls the algorithm, which just Dominators.cpp provides, through ten
explicit instantiations. Elsewhere the algorithm survives only where the
inliner leaves a use of it.
A previous revision of #212098 gave LoopInfoBase a member calling
recalculate, so instantiating LoopInfoBase in CFGLoopInfo.cpp referenced
an algorithm that no translation unit defines:
```
ld.lld: error: undefined symbol: void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<mlir::Block, false>>(llvm::DominatorTreeBase<mlir::Block, false>&)
>>> referenced by CFGLoopInfo.cpp
```
Define those members in GenericDomTreeConstruction.h. Such a caller then
[5 lines not shown]
[libc][realpath] Follow symlinks
This commit updates realpath to call readlinkat on symlinks during path resolution. In order to do, it updates `PendingPath` to store a `cpp::string` that is prepended with a symlink target when resolved. This could be more efficient by using a `PATH_MAX` buffer and storing the path at the end of the buffer, but using a `cpp::string` avoids the pointer arithmetic and manual memory management that comes with that approach.
[libc][realpath] Follow symlinks
This commit updates realpath to call readlinkat on symlinks during path resolution. In order to do, it updates `PendingPath` to store a `cpp::string` that is prepended with a symlink target when resolved. This could be more efficient by using a `PATH_MAX` buffer and storing the path at the end of the buffer, but using a `cpp::string` avoids the pointer arithmetic and manual memory management that comes with that approach.
[mlir][arith] Fold trivial shifts (`0<<x`, `x>>x`, `-1>>x`) (#212159)
Add value-preserving folds mirroring LLVM's InstructionSimplify for the
integer shift ops:
```
shli/shrui/shrsi(0, x) -> 0
shrui/shrsi(x, x) -> 0
shrsi(-1, x) -> -1
```
A shift amount greater than or equal to the bit width yields poison, so
refining these cases to a constant is valid. For `shr(x, x)` any
in-range amount `v` satisfies `v >> v == 0 (v < 2^v)`.
Folding an out-of-range shift amount (`c >= bit width`) to poison is
left as a TODO: it would make the arith dialect depend on the ub dialect
to materialize `ub.poison`.
[17 lines not shown]
[RISCV] Declare TLSDESC clobbers for vector registers and CSRs per psABI (#205027)
RISC-V's ABI states that, aside from V extension state, only a0 and t0
are clobbered by TLSDESC resolvers. The original specification was to
also not clobber any V extension state, but due to implementation
concerns an ABI-breaking change has been made[1] to clobber all V
extension state.
This patch adds V-regs/csrs clobbering to the existing PseudoLA_TLSDESC
and PseudoTLSDESCCall in RISCVInstrInfo.td, as well as an additional
test covering the V-register clobber and V-CSRs clobber cases.
[1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/496