[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