[llvm] [Semilattice] Introduce for dataflow analysis with KnownBits (PR #177616)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 23 11:49:33 PST 2026


================
@@ -0,0 +1,184 @@
+//===- Semilattice.h - A semilattice of KnownBits -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Builds a semilattice structure from the integral values in a given function,
+// and holds an associated KnownBits for each value, representing the dataflow
+// of KnownBits. Intended to be used to cache KnownBits for the entire function,
+// with invalidation APIs.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_SEMILATTICE_H
+#define LLVM_ANALYSIS_SEMILATTICE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/KnownBits.h"
+
+namespace llvm {
+class Semilattice;
+
+class SemilatticeNode {
+  friend class Semilattice;
+  PointerIntPair<Value *, 1> ValHasKnownBits;
+  KnownBits Known;
+  SmallVector<SemilatticeNode *, 4> Parents;
+  SmallVector<SemilatticeNode *, 4> Children;
+
+public:
+  using iterator = SmallVectorImpl<SemilatticeNode *>::iterator;
+  LLVM_ABI_FOR_TEST iterator child_begin() { // NOLINT
+    return Children.begin();
+  }
+  LLVM_ABI_FOR_TEST iterator child_end() { return Children.end(); } // NOLINT
+  LLVM_ABI_FOR_TEST iterator_range<iterator> children() {
+    return make_range(child_begin(), child_end());
+  }
+  LLVM_ABI_FOR_TEST bool isLeaf() const { return Children.empty(); }
+  LLVM_ABI_FOR_TEST bool isRoot() const { return Parents.empty(); }
+  LLVM_ABI_FOR_TEST Value *getValue() const {
+    return ValHasKnownBits.getPointer();
+  }
+  LLVM_ABI_FOR_TEST bool hasKnownBits() const {
+    return ValHasKnownBits.getInt();
+  }
+  LLVM_ABI_FOR_TEST void setHasKnownBits() { ValHasKnownBits.setInt(1); }
+  LLVM_ABI_FOR_TEST KnownBits getKnownBits() const { return Known; }
+  LLVM_ABI_FOR_TEST void unionKnownWith(const KnownBits &NewKnown) {
+    Known = Known.unionWith(NewKnown);
+  }
+
+protected:
+  SemilatticeNode() : ValHasKnownBits(nullptr, 0) {}
+  SemilatticeNode(Value *V)
+      : ValHasKnownBits(V, 0),
+        Known(V->getType()->getScalarType()->getIntegerBitWidth()) {
+    assert(V && "Attempting to create a node with an empty Value");
+  }
+  SemilatticeNode(const SemilatticeNode &) = delete;
+  SemilatticeNode &operator=(const SemilatticeNode &) = delete;
+
+  void resetKnownBits() { Known.resetAll(); }
+  SemilatticeNode *addParent(SemilatticeNode *N) {
+    if (!hasParent(N))
+      Parents.push_back(N);
+    return this;
+  }
+  SemilatticeNode *addChild(SemilatticeNode *N) {
+    if (!is_contained(Children, N))
+      Children.push_back(N);
+    return this;
+  }
+  SemilatticeNode *rauw(Value *NewV) {
+    ValHasKnownBits.setPointer(NewV);
+    return this;
+  }
+  bool hasParent(SemilatticeNode *N) const { return is_contained(Parents, N); }
+};
+
+class Semilattice {
+  using NodeT = SemilatticeNode;
+
+  static constexpr size_t SlabSize = 8 * sizeof(NodeT);
+  BumpPtrAllocatorImpl<MallocAllocator, SlabSize, /*SizeThreshold=*/SlabSize,
+                       /*GrowthDelay=*/2>
+      NodeAllocator;
+
+  // The RootNode is a sentinel value to allow for graph traverals to work
+  // smoothly. Typically, to traverse the entire semilattice, a
+  // drop_begin(depth_first(Lat->getRootNode())) is used.
+  NodeT *RootNode;
+  DenseMap<Value *, NodeT *> NodeMap;
+  NodeT *create() { return new (NodeAllocator) NodeT(); }
+  NodeT *create(Value *V) { return new (NodeAllocator) NodeT(V); }
+  NodeT *getOrCreate(Value *V) { return NodeMap.lookup_or(V, create(V)); }
+  NodeT *insert(Value *V, NodeT *Parent = nullptr);
+  SmallVector<NodeT *, 4> insert_range(NodeT *Parent, // NOLINT
+                                       ArrayRef<User *> R);
+  void recurseInsertChildren(ArrayRef<NodeT *>);
+
+  // The roots (excluding the sentinel value) are the arguments of the function,
+  // and PHI nodes in each Basic Block, excluding values whose types are not
----------------
dtcxzyw wrote:

Sure.

https://github.com/llvm/llvm-project/pull/177616


More information about the llvm-commits mailing list