[llvm] [RISCV] Order stack objects by access density (PR #217507)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 01:50:42 PDT 2026


================
@@ -2846,6 +2846,82 @@ void RISCVFrameLowering::inlineStackProbe(MachineFunction &MF,
   }
 }
 
+namespace {
+/// Bookkeeping record used while ordering local stack objects by access
+/// density. One record is created for each frame index passed to
+/// orderFrameObjects().
+struct RISCVFrameSortingObject {
+  int ObjectIndex;
+  uint64_t ObjectSize;
+  Align ObjectAlign;
+  uint64_t NumUses = 0;
+};
+} // end anonymous namespace
+
+void RISCVFrameLowering::orderFrameObjects(
+    const MachineFunction &MF, SmallVectorImpl<int> &ObjectsToAllocate) const {
+  // PEI never adds callee-saved, dead, stack-protector, EH, scavenging,
+  // non-default-stack-ID or other special objects to ObjectsToAllocate, so
+  // the objects seen here are safe to reorder.
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  DenseMap<int, unsigned> Index;
+  SmallVector<RISCVFrameSortingObject> Sorting;
+  Sorting.reserve(ObjectsToAllocate.size());
+
+  for (int FI : ObjectsToAllocate) {
+    assert(MFI.getStackID(FI) == TargetStackID::Default &&
+           "Only default stack objects should be reordered");
+    // Variable-sized objects report a size of zero. Give them a non-zero
+    // sentinel so the density comparison below does not degenerate. Their
+    // placement does not matter much in practice: they occupy no space in
+    // the static frame and are addressed by adjusting SP at runtime rather
+    // than through a frame index offset.
+    int64_t Size = MFI.getObjectSize(FI);
+    RISCVFrameSortingObject Obj{FI, Size > 0 ? static_cast<uint64_t>(Size) : 4,
+                                MFI.getObjectAlign(FI)};
+    Index[FI] = Sorting.size();
+    Sorting.push_back(Obj);
+  }
+
+  // Count static references to each frame index. This provides an access
+  // density heuristic without requiring profile data.
+  for (const MachineBasicBlock &MBB : MF) {
+    for (const MachineInstr &MI : MBB) {
+      if (MI.isDebugInstr())
+        continue;
+      for (const MachineOperand &MO : MI.operands()) {
+        if (!MO.isFI())
+          continue;
+        auto It = Index.find(MO.getIndex());
+        if (It != Index.end())
+          ++Sorting[It->second].NumUses;
+      }
+    }
+  }
+
+  // Sort by NumUses / ObjectSize using cross multiplication. High-density
+  // objects are placed at the end of the list, which puts them closest to SP
+  // or BP when PEI allocates objects on the downward-growing stack.
+  llvm::stable_sort(Sorting, [](const RISCVFrameSortingObject &A,
+                                const RISCVFrameSortingObject &B) {
+    uint64_t DensityA = A.NumUses * B.ObjectSize;
+    uint64_t DensityB = B.NumUses * A.ObjectSize;
+    if (DensityA != DensityB)
+      return DensityA < DensityB;
+    return A.ObjectAlign < B.ObjectAlign;
+  });
+
+  for (auto [Idx, Obj] : llvm::enumerate(Sorting))
+    ObjectsToAllocate[Idx] = Obj.ObjectIndex;
+
+  // Ordinary local objects in a non-realigned FP frame are addressed from the
+  // opposite end of the allocation order. Reverse the SP/BP-oriented order so
+  // high-density objects are close to FP instead.
+  if (!STI.getRegisterInfo()->hasStackRealignment(MF) && hasFP(MF))
----------------
arsenm wrote:

I think these overlapping conditions are hard to follow, is there a common helper between hasStackRealignment and hasFP to use 

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


More information about the llvm-commits mailing list