[llvm] [Attributor] Change allocation size and load/store offsets using AAPointerInfo for Alloca instructions and keep track of instructions causing an Access (PR #72029)

Shilei Tian via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 7 21:50:43 PST 2025


================
@@ -13451,41 +13701,124 @@ struct AAAllocationInfoImpl : public AAAllocationInfo {
     if (!AllocationSize)
       return indicatePessimisticFixpoint();
 
-    // For zero sized allocations, we give up.
-    // Since we can't reduce further
+    // For zero sized allocations, we give up
+    // because we cannot reduce them any further.
     if (*AllocationSize == 0)
       return indicatePessimisticFixpoint();
 
-    int64_t BinSize = PI->numOffsetBins();
-
-    // TODO: implement for multiple bins
-    if (BinSize > 1)
-      return indicatePessimisticFixpoint();
-
-    if (BinSize == 0) {
-      auto NewAllocationSize = std::make_optional<TypeSize>(0, false);
+    int64_t NumBins = PI->numOffsetBins();
+    if (NumBins == 0) {
+      std::optional<TypeSize> NewAllocationSize =
+          std::optional<TypeSize>(TypeSize(0, false));
       if (!changeAllocationSize(NewAllocationSize))
         return ChangeStatus::UNCHANGED;
       return ChangeStatus::CHANGED;
     }
 
-    // TODO: refactor this to be part of multiple bin case
-    const auto &It = PI->begin();
+    // Algorithm:
+    // For all the accessed ranges in AAPointerInfo, we need to find the minimum
+    // longest range that contains all the accessed offsets.
+    // In case, disjoint ranges exist, we want to merge them since we want to
+    // make a packed Alloca. For this we need to calculate the minimum size of
+    // the new allocation. Then adjust all the old offsets and map them to their
+    // new offsets.
+
+    // A tuple to store a cluster, a cluster is a maximal unique range.
+    // Different Clusters are meant to be disjoint, but we eventually merge them
+    // together. A bigger cluster can subsume a smaller cluster inside it.
+    using ClusterTy = std::tuple<int64_t, int64_t>;
+    using ClustersTy = SmallVector<ClusterTy, 4>;
+
+    // BinInterval is an interval to keep track of the Start and
+    // End of a RangeTy. Since RangeTy stores the Offset and the
+    // Corresponding size but not the end of the range.
+    //(StartOffset, EndOffset, RangeTy struct)
+    using AccessedInterval = std::tuple<int64_t, int64_t, AA::RangeTy>;
+    using AccessedIntervals = SmallVector<AccessedInterval, 4>;
+
+    // Obtain all the offset bins that exists in AAPointerInfo.
+    SmallVector<AA::RangeTy, 4> OldBins;
+    for (AAPointerInfo::OffsetBinsTy::const_iterator It = PI->begin();
+         It != PI->end(); It++) {
+      const AA::RangeTy &Bin = It->getFirst();
+      // In case unknown or unassigned bins exists,
+      // We don't want to change the allocation size and return a
+      // pessimistic fixpoint.
+      if (Bin.offsetOrSizeAreUnknown() || Bin.isUnassigned())
+        return indicatePessimisticFixpoint();
+      OldBins.push_back(Bin);
+    }
 
-    // TODO: handle if Offset is not zero
-    if (It->first.Offset != 0)
-      return indicatePessimisticFixpoint();
+    AccessedIntervals Intervals;
+    // Obtain the intervals from the ranges.
+    for (AA::RangeTy &OldBin : OldBins) {
+      AccessedInterval Interval =
+          std::make_tuple(OldBin.Offset, OldBin.Offset + OldBin.Size, OldBin);
+      Intervals.push_back(Interval);
+    }
 
-    uint64_t SizeOfBin = It->first.Offset + It->first.Size;
+    // sort the intervals to push the largest interval to the beginning.
+    llvm::sort(Intervals,
+               [](const AccessedInterval &A, const AccessedInterval &B) {
+                 return get<0>(A) < get<0>(B);
+               });
 
-    if (SizeOfBin >= *AllocationSize)
-      return indicatePessimisticFixpoint();
+    ClustersTy Clusters;
+    int64_t CurrentClusterStart = get<0>(Intervals[0]);
+    int64_t CurrentClusterEnd = get<1>(Intervals[0]);
 
-    auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8, false);
+    for (size_t I = 1; I < Intervals.size(); I++) {
+      if (get<0>(Intervals[I]) <= CurrentClusterEnd) {
+        CurrentClusterEnd = std::max(CurrentClusterEnd, get<1>(Intervals[I]));
+      } else {
+        Clusters.push_back({CurrentClusterStart, CurrentClusterEnd});
+        CurrentClusterStart = get<0>(Intervals[I]);
+        CurrentClusterEnd = get<1>(Intervals[I]);
+      }
+    }
+    Clusters.push_back({CurrentClusterStart, CurrentClusterEnd});
+
+    int64_t PackedRangeSize = 0;
+    // Sum up each cluster to get the total size of the packed Alloca.
+    for (ClusterTy &Cluster : Clusters)
+      PackedRangeSize += (get<1>(Cluster) - get<0>(Cluster));
+
+    // For each access bin we compute its new start offset
+    // and store the results in a new map (NewOffsetBins).
+    // NewOffsetsBins is a Map from AA::RangeTy OldRange to AA::RangeTy
+    // NewRange
+    int64_t PackedCursorStart = 0;
+    bool ChangedOffsets = false;
+    for (ClusterTy &Cluster : Clusters) {
+      const long &ClusterStart = get<0>(Cluster);
+      const long &ClusterEnd = get<1>(Cluster);
+      for (AccessedInterval &Interval : Intervals) {
+        const long &InterValStart = get<0>(Interval);
+        const long &InterValEnd = get<1>(Interval);
+        if (InterValStart >= ClusterStart && InterValEnd <= ClusterEnd) {
+          int64_t NewRangeStart =
+              PackedCursorStart + (InterValStart - ClusterStart);
+          int64_t NewRangeSize = InterValEnd - InterValStart;
+          const AA::RangeTy &OldRange = get<2>(Interval);
+
+          ChangedOffsets |= setNewOffsets(OldRange, OldRange.Offset,
+                                          NewRangeStart, NewRangeSize);
+        }
+      }
+      PackedCursorStart += ClusterEnd - ClusterStart;
+    }
+
+    // Set the new size of the allocation. The new size of the Allocation should
+    // be the size of PrevBinEndOffset * 8 in bits.
+    std::optional<TypeSize> NewAllocationSize =
----------------
shiltian wrote:

Same here

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


More information about the llvm-commits mailing list