[all-commits] [llvm/llvm-project] 3d7535: [ADT] Make canonicalization a compile-time paramet...
Gábor Horváth via All-commits
all-commits at lists.llvm.org
Tue Jul 14 11:13:32 PDT 2026
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: 3d7535a03c1a036204a5347a79e9f66eb96ce4bc
https://github.com/llvm/llvm-project/commit/3d7535a03c1a036204a5347a79e9f66eb96ce4bc
Author: Gábor Horváth <xazax.hun at gmail.com>
Date: 2026-07-14 (Tue, 14 Jul 2026)
Changed paths:
M clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
M clang/include/clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h
M clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
M clang/include/clang/Analysis/Analyses/LifetimeSafety/MovedLoans.h
M clang/include/clang/Analysis/Analyses/LifetimeSafety/Utils.h
M clang/include/clang/Analysis/Analyses/LiveVariables.h
M clang/lib/Analysis/LiveVariables.cpp
M llvm/benchmarks/ImmutableSetBuildBM.cpp
M llvm/benchmarks/ImmutableSetIteratorBM.cpp
M llvm/include/llvm/ADT/ImmutableMap.h
M llvm/include/llvm/ADT/ImmutableSet.h
M llvm/unittests/ADT/ImmutableSetTest.cpp
Log Message:
-----------
[ADT] Make canonicalization a compile-time parameter of ImmutableSet/Map (#209300)
ImmutableSet and ImmutableMap always carried the machinery needed for
tree canonicalization -- a per-node `prev`/`next` cache chain and cached
`digest`, plus the factory-side cache and a runtime `canonicalize` flag
-- even for the many clients that disable it (the Clang dataflow
analyses, e.g. lifetime safety and LiveVariables, for which
canonicalization is a large performance loss). Those clients paid for
state and code paths they never used.
Add a `bool Canonicalize` template parameter (defaulting to true, so
existing users are unaffected) that moves the decision to compile time:
* When disabled, the `prev`/`next` links (empty base) and `digest`
(LLVM_NO_UNIQUE_ADDRESS member) vanish, shrinking a set node from 56 to
40 bytes and a map node from 64 to 40 on 64-bit; `getCanonicalTree`, the
factory cache, and the `destroy()` unlink branch are `if constexpr`-ed
away. Node fields are ordered so the traversal-hot members come first.
* When enabled, the node layout is unchanged, and `operator==`/`!=`
become O(1) pointer comparisons (equal canonical trees share a root, as
with ImmutableList) instead of a structural walk.
The runtime `canonicalize` factory argument is now redundant and
removed; the in-tree non-canonicalizing users are switched to the
template argument.
Node microbenchmark (ImmutableSetBuildBM, non-canonicalizing, -O2):
| Benchmark | Before | After | Speedup |
|--------------------|---------:|---------:|:-------:|
| Build/256 | 20.3 us | 18.3 us | 1.11x |
| Build/4096 | 790 us | 731 us | 1.08x |
| Build/65536 | 18.8 ms | 18.4 ms | 1.02x |
| BuildRemove/256 | 40.7 us | 35.0 us | 1.16x |
| BuildRemove/4096 | 1.46 ms | 1.39 ms | 1.05x |
| BuildRemove/65536 | 34.6 ms | 33.8 ms | 1.02x |
End to end, the smaller node cuts the lifetime-safety analysis peak RSS
by up to ~23% on allocation-dense inputs with neutral-to-positive run
time, and the O(1) equality speeds up a Clang static analyzer run on
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp by ~1.3% (95.1s -> 93.9s).
Assisted by: Claude Opus 4.8
---------
Co-authored-by: Gabor Horvath <gaborh at apple.com>
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list