[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