[llvm] [DA] batch delinearization (PR #170519)

Ryotaro Kasuga via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 12 06:54:52 PST 2025


================
@@ -164,6 +171,84 @@ bool getIndexExpressionsFromGEP(ScalarEvolution &SE,
                                 SmallVectorImpl<const SCEV *> &Subscripts,
                                 SmallVectorImpl<const SCEV *> &Sizes);
 
+/// BatchDelinearization - A wrapper for batch delinearization that caches
+/// results across multiple queries. Similar to BatchAAResults, this class
+/// should be used when analyzing multiple memory accesses to the same base
+/// pointers, as it computes array dimensions once using terms from all
+/// accesses, leading to better precision.
+///
+/// This class collects all memory accesses in a function, groups them by base
+/// pointer, and computes array dimensions for each base pointer using terms
+/// from all accesses. The results are cached for efficient lookups during
+/// dependence analysis.
+///
+/// Usage:
+///   BatchDelinearization BD(F, SE, LI);
+///   BD.populate();  // Compute and cache delinearization info.
+///   // Then pass BD to DependenceInfo or query it directly.
+class LLVM_ABI BatchDelinearization {
+public:
+  BatchDelinearization(Function &F, ScalarEvolution &SE, LoopInfo &LI)
+      : F(F), SE(SE), LI(LI) {}
+
+  /// Populate the cache with delinearization information for all memory
+  /// accesses in the function.
+  void populate();
+
+  /// Check if the cache has been populated.
+  bool isPopulated() const { return Populated; }
+
+  /// Get the cached array sizes for a base pointer.
+  /// Returns nullptr if not found.
+  const SmallVector<const SCEV *, 4> *
+  getArraySizes(const SCEVUnknown *Base) const {
+    auto It = ArraySizes.find(Base);
+    return It != ArraySizes.end() ? &It->second : nullptr;
+  }
+
+  /// Get the cached subscripts for an instruction.
+  /// Returns nullptr if not found.
+  const SmallVector<const SCEV *, 4> *
+  getSubscripts(const Instruction *I) const {
+    auto It = Subscripts.find(I);
+    return It != Subscripts.end() ? &It->second : nullptr;
+  }
+
+  /// Get the cached element size for a base pointer.
+  /// Returns nullptr if not found.
+  const SCEV *getElementSize(const SCEVUnknown *Base) const {
+    auto It = ElementSizes.find(Base);
+    return It != ElementSizes.end() ? It->second : nullptr;
+  }
+
+  /// Get the ScalarEvolution instance.
+  ScalarEvolution &getSE() { return SE; }
+  const ScalarEvolution &getSE() const { return SE; }
+
+  /// Get the LoopInfo instance.
+  LoopInfo &getLI() { return LI; }
+  const LoopInfo &getLI() const { return LI; }
+
+private:
+  Function &F;
+  ScalarEvolution &SE;
+  LoopInfo &LI;
+
+  /// Map from base pointer to computed array dimension sizes.
+  SmallDenseMap<const SCEVUnknown *, SmallVector<const SCEV *, 4>, 8>
+      ArraySizes;
+
+  /// Map from instruction to pre-computed subscripts.
+  SmallDenseMap<const Instruction *, SmallVector<const SCEV *, 4>, 16>
+      Subscripts;
+
+  /// Element size for the array (used for validation).
+  SmallDenseMap<const SCEVUnknown *, const SCEV *, 8> ElementSizes;
+
+  /// Flag indicating whether the cache has been populated.
+  bool Populated = false;
----------------
kasuga-fj wrote:

Consider using [RAII](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization) rather than holding such a flag.

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


More information about the llvm-commits mailing list