[llvm-branch-commits] [llvm] [SCEV] Add canonical SCEV pointer and use for SCEVUse cmps (NFC) (PR #185040)

Florian Hahn via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Mar 6 08:48:37 PST 2026


https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/185040

Add canonical SCEV pointer, to be used in combination with SCEVUse. For now, SCEVUse with different flags (or their wrapped SCEVs are different due to different flags) are considered equal if they have the same canonical SCEV.

>From a62672ccab0e0614c323c303e133e182ef21c1d1 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 19 Feb 2026 18:02:05 +0000
Subject: [PATCH] [SCEV] Add canonical SCEV pointer and use for SCEVUse cmps
 (NFC)

Add canonical SCEV pointer, to be used in combination with SCEVUse.
For now, SCEVUse with different flags (or their wrapped SCEVs are
different due to different flags) are considered equal if they have the
same canonical SCEV.
---
 llvm/include/llvm/Analysis/ScalarEvolution.h | 39 ++++++++++++++++++--
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index c59a652509e27..77db49d44583a 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -78,10 +78,14 @@ struct SCEVUse : PointerIntPair<const SCEV *, 2> {
 
   void *getRawPointer() const { return getOpaqueValue(); }
 
+  bool isCanonical() const;
+
+  const SCEV *getCanonical() const;
+
   unsigned getFlags() const { return getInt(); }
 
   bool operator==(const SCEVUse &RHS) const {
-    return getRawPointer() == RHS.getRawPointer();
+    return getCanonical() == RHS.getCanonical();
   }
 
   bool operator==(const SCEV *RHS) const { return getRawPointer() == RHS; }
@@ -120,14 +124,24 @@ template <> struct DenseMapInfo<SCEVUse> {
   }
 
   static unsigned getHashValue(SCEVUse U) {
-    return hash_value(U.getRawPointer());
+    return hash_value(U.getCanonical());
   }
 
   static bool isEqual(const SCEVUse LHS, const SCEVUse RHS) {
-    return LHS.getRawPointer() == RHS.getRawPointer();
+    void *L = LHS.getRawPointer();
+    void *R = RHS.getRawPointer();
+    if (L == reinterpret_cast<void *>(-1) ||
+        L == reinterpret_cast<void *>(-2) ||
+        R == reinterpret_cast<void *>(-1) || R == reinterpret_cast<void *>(-2))
+      return L == R;
+    return LHS.getCanonical() == RHS.getCanonical();
   }
 };
 
+inline bool SCEVUse::isCanonical() const {
+  return getCanonical() == getPointer();
+}
+
 template <> struct simplify_type<SCEVUse> {
   using SimpleType = const SCEV *;
 
@@ -157,6 +171,11 @@ class SCEV : public FoldingSetNode {
   /// miscellaneous information.
   unsigned short SubclassData = 0;
 
+private:
+  /// Pointer to the canonical SCEV for this node. SCEVs that differ only in
+  /// no-wrap flags share the same canonical SCEV.
+  const SCEV *CanonicalSCEV;
+
 public:
   /// NoWrapFlags are bitfield indices into SubclassData.
   ///
@@ -204,7 +223,8 @@ class SCEV : public FoldingSetNode {
 
   explicit SCEV(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
                 unsigned short ExpressionSize)
-      : FastID(ID), SCEVType(SCEVTy), ExpressionSize(ExpressionSize) {}
+      : FastID(ID), SCEVType(SCEVTy), ExpressionSize(ExpressionSize),
+        CanonicalSCEV(this) {}
   SCEV(const SCEV &) = delete;
   SCEV &operator=(const SCEV &) = delete;
 
@@ -247,6 +267,8 @@ class SCEV : public FoldingSetNode {
 
   /// This method is used for debugging.
   LLVM_ABI void dump() const;
+
+  const SCEV *getCanonical() const { return CanonicalSCEV; }
 };
 
 // Specialize FoldingSetTrait for SCEV to avoid needing to compute
@@ -269,6 +291,11 @@ inline raw_ostream &operator<<(raw_ostream &OS, const SCEV &S) {
   return OS;
 }
 
+inline raw_ostream &operator<<(raw_ostream &OS, SCEVUse U) {
+  U.print(OS);
+  return OS;
+}
+
 /// An object of this class is returned by queries that could not be answered.
 /// For example, if you ask for the number of iterations of a linked-list
 /// traversal loop, you will get one of these.  None of the standard SCEV
@@ -2636,6 +2663,10 @@ template <> struct DenseMapInfo<ScalarEvolution::FoldID> {
   }
 };
 
+inline const SCEV *SCEVUse::getCanonical() const {
+  return getPointer()->getCanonical();
+}
+
 } // end namespace llvm
 
 #endif // LLVM_ANALYSIS_SCALAREVOLUTION_H



More information about the llvm-branch-commits mailing list