[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