[libc][tsearch] add weak AVL tree for tsearch implementation (#172411)

Related to #114695.

This PR adds a Weak AVL Tree for tsearch APIs. The symbol
implementations are coming in a
following up PR to avoid creating a huge patch. The work is based on
@MaskRay's recent post (see below).

A general self-balancing binary search tree where the node pointer can
be used as stable handles to the stored values.

The self-balancing strategy is the Weak AVL (WAVL) tree, based on the
following foundational references:
1. https://maskray.me/blog/2025-12-14-weak-avl-tree
2. https://reviews.freebsd.org/D25480
3. https://ics.uci.edu/~goodrich/teach/cs165/notes/WeakAVLTrees.pdf
4. https://dl.acm.org/doi/10.1145/2689412 (Rank-Balanced Trees)

WAVL trees belong to the rank-balanced binary search tree framework
(reference 4), alongside AVL and Red-Black trees.

Key Properties of WAVL Trees:
1. Relationship to Red-Black Trees: A WAVL tree can always be colored as
a
   Red-Black tree.
2. Relationship to AVL Trees: An AVL tree meets all the requirements of
a
WAVL tree. Insertion-only WAVL trees maintain the same structure as AVL
   trees.

Rank-Based Balancing:
In rank-balanced trees, each node is assigned a rank (conceptually
similar
to height). In AVL/WAVL, the rank difference between a parent and its
child is
strictly enforced to be either **1** or **2**.

- **AVL Trees:** Rank is equivalent to height. The strict condition is
that
there are no 2-2 nodes (a parent with rank difference 2 to both
children).
- **WAVL Trees:** The no 2-2 node rule is relaxed for internal nodes
during
the deletion fixup process, making WAVL trees less strictly balanced
than
  AVL trees but easier to maintain than Red-Black trees.

Balancing Mechanics (Promotion/Demotion):
- **Null nodes** are considered to have rank -1.
- **External/leaf nodes** have rank 0.
- **Insertion:** Inserting a node may create a situation where a parent
and
child
have the same rank (difference 0). This is fixed by **promoting** the
rank
of the parent and propagating the fix upwards using at most two
rotations
  (trinode fixup).
- **Deletion:** Deleting a node may result in a parent being 3 ranks
higher
than a child (difference 3). This is fixed by **demoting** the parent's
  rank and propagating the fix upwards.

Implementation Detail:
The rank is **implicitly** maintained. We never store the full rank.
Instead,
a 2-bit tag is used on each node to record the rank difference to each
child:
- Bit cleared (0) -> Rank difference is **1**.
- Bit set (1)     -> Rank difference is **2**.

---------

Co-authored-by: Michael Jones <michaelrj@google.com>
6 files changed
tree: c1a1c8572aad8fb90b904f9cd5f343e167b3b1ad
  1. .ci/
  2. .github/
  3. bolt/
  4. clang/
  5. clang-tools-extra/
  6. cmake/
  7. compiler-rt/
  8. cross-project-tests/
  9. flang/
  10. flang-rt/
  11. libc/
  12. libclc/
  13. libcxx/
  14. libcxxabi/
  15. libsycl/
  16. libunwind/
  17. lld/
  18. lldb/
  19. llvm/
  20. llvm-libgcc/
  21. mlir/
  22. offload/
  23. openmp/
  24. orc-rt/
  25. polly/
  26. runtimes/
  27. third-party/
  28. utils/
  29. .clang-format
  30. .clang-format-ignore
  31. .clang-tidy
  32. .git-blame-ignore-revs
  33. .gitattributes
  34. .gitignore
  35. .mailmap
  36. CODE_OF_CONDUCT.md
  37. CONTRIBUTING.md
  38. LICENSE.TXT
  39. pyproject.toml
  40. README.md
  41. SECURITY.md
README.md

The LLVM Compiler Infrastructure

OpenSSF Scorecard OpenSSF Best Practices libc++

Welcome to the LLVM project!

This repository contains the source code for LLVM, a toolkit for the construction of highly optimized compilers, optimizers, and run-time environments.

The LLVM project has multiple components. The core of the project is itself called “LLVM”. This contains all of the tools, libraries, and header files needed to process intermediate representations and convert them into object files. Tools include an assembler, disassembler, bitcode analyzer, and bitcode optimizer.

C-like languages use the Clang frontend. This component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode -- and from there into object files, using LLVM.

Other components include: the libc++ C++ standard library, the LLD linker, and more.

Getting the Source Code and Building LLVM

Consult the Getting Started with LLVM page for information on building and running LLVM.

For information on how to contribute to the LLVM project, please take a look at the Contributing to LLVM guide.

Getting in touch

Join the LLVM Discourse forums, Discord chat, LLVM Office Hours or Regular sync-ups.

The LLVM project has adopted a code of conduct for participants to all modes of communication within the project.