[llvm] [CycleInfo] Represent cycles by an opaque handle. NFC (PR #210117)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 10:46:09 PDT 2026
================
@@ -91,37 +91,50 @@ template <typename ContextT> class GenericCycle {
public:
GenericCycle() = default;
+};
- /// Iteration over child cycles: the first child (if any) immediately
- /// follows this cycle in the preorder array, and each next sibling follows
- /// the previous child's subtree.
- //@{
- struct const_child_iterator
- : iterator_facade_base<const_child_iterator, std::forward_iterator_tag,
- GenericCycle *, std::ptrdiff_t, GenericCycle *,
- GenericCycle *> {
- const GenericCycle *C = nullptr;
+/// Opaque handle to a cycle within a GenericCycleInfo. Wraps the cycle's
+/// preorder index; a default-constructed handle is invalid ("no cycle"). All
+/// queries live on GenericCycleInfo, which resolves the handle to storage.
+///
+/// Handles remain valid as long as the cycle forest is not recomputed.
+/// addBlockToCycle() adds a block but never adds, removes, or reorders cycles,
+/// so it leaves every handle valid.
+template <typename ContextT> class GenericCycleRef {
+ static constexpr unsigned InvalidIndex = ~0u;
+ unsigned Index = InvalidIndex;
- const_child_iterator() = default;
- explicit const_child_iterator(const GenericCycle *C) : C(C) {}
+ explicit GenericCycleRef(unsigned Index) : Index(Index) {}
+ friend class GenericCycleInfo<ContextT>;
+ friend struct DenseMapInfo<GenericCycleRef<ContextT>>;
- GenericCycle *operator*() const { return const_cast<GenericCycle *>(C); }
- const_child_iterator &operator++() {
- C += 1 + C->NumDescendants;
- return *this;
- }
- bool operator==(const const_child_iterator &Other) const {
- return C == Other.C;
- }
- };
- //@}
+public:
+ GenericCycleRef() = default;
+ bool isValid() const { return Index != InvalidIndex; }
+ explicit operator bool() const { return isValid(); }
+ bool operator==(GenericCycleRef O) const { return Index == O.Index; }
+ bool operator!=(GenericCycleRef O) const { return Index != O.Index; }
+};
+
+/// The empty/tombstone keys are distinct from the invalid handle, so an invalid
+/// handle stays a legal key -- matching the pointer world where nullptr is a
+/// legal DenseMap/SmallPtrSet key.
+template <typename ContextT> struct DenseMapInfo<GenericCycleRef<ContextT>> {
+ using T = GenericCycleRef<ContextT>;
+ static T getEmptyKey() { return T(~0u - 1); }
+ static T getTombstoneKey() { return T(~0u - 2); }
----------------
MaskRay wrote:
Sorry, AI slop. Deleted
https://github.com/llvm/llvm-project/pull/210117
More information about the llvm-commits
mailing list