summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-02-05 18:04:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-02-05 18:05:05 +0000
commitecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (patch)
tree3a4038f3b7bafaeade9fd6146ea8021237616657 /llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
parent6f8fc217eaa12bf657be1c6468ed9938d10168b3 (diff)
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp')
-rw-r--r--llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
index ccc7d0737f53..610627e7e3f0 100644
--- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
@@ -80,6 +80,88 @@ MachineBasicBlock::iterator SystemZFrameLowering::eliminateCallFramePseudoInstr(
}
}
+namespace {
+struct SZFrameSortingObj {
+ bool IsValid = false; // True if we care about this Object.
+ uint32_t ObjectIndex = 0; // Index of Object into MFI list.
+ uint64_t ObjectSize = 0; // Size of Object in bytes.
+ uint32_t D12Count = 0; // 12-bit displacement only.
+ uint32_t DPairCount = 0; // 12 or 20 bit displacement.
+};
+typedef std::vector<SZFrameSortingObj> SZFrameObjVec;
+} // namespace
+
+// TODO: Move to base class.
+void SystemZELFFrameLowering::orderFrameObjects(
+ const MachineFunction &MF, SmallVectorImpl<int> &ObjectsToAllocate) const {
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const SystemZInstrInfo *TII =
+ static_cast<const SystemZInstrInfo *>(MF.getSubtarget().getInstrInfo());
+
+ // Make a vector of sorting objects to track all MFI objects and mark those
+ // to be sorted as valid.
+ if (ObjectsToAllocate.size() <= 1)
+ return;
+ SZFrameObjVec SortingObjects(MFI.getObjectIndexEnd());
+ for (auto &Obj : ObjectsToAllocate) {
+ SortingObjects[Obj].IsValid = true;
+ SortingObjects[Obj].ObjectIndex = Obj;
+ SortingObjects[Obj].ObjectSize = MFI.getObjectSize(Obj);
+ }
+
+ // Examine uses for each object and record short (12-bit) and "pair"
+ // displacement types.
+ for (auto &MBB : MF)
+ for (auto &MI : MBB) {
+ if (MI.isDebugInstr())
+ continue;
+ for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
+ const MachineOperand &MO = MI.getOperand(I);
+ if (!MO.isFI())
+ continue;
+ int Index = MO.getIndex();
+ if (Index >= 0 && Index < MFI.getObjectIndexEnd() &&
+ SortingObjects[Index].IsValid) {
+ if (TII->hasDisplacementPairInsn(MI.getOpcode()))
+ SortingObjects[Index].DPairCount++;
+ else if (!(MI.getDesc().TSFlags & SystemZII::Has20BitOffset))
+ SortingObjects[Index].D12Count++;
+ }
+ }
+ }
+
+ // Sort all objects for short/paired displacements, which should be
+ // sufficient as it seems like all frame objects typically are within the
+ // long displacement range. Sorting works by computing the "density" as
+ // Count / ObjectSize. The comparisons of two such fractions are refactored
+ // by multiplying both sides with A.ObjectSize * B.ObjectSize, in order to
+ // eliminate the (fp) divisions. A higher density object needs to go after
+ // in the list in order for it to end up lower on the stack.
+ auto CmpD12 = [](const SZFrameSortingObj &A, const SZFrameSortingObj &B) {
+ // Put all invalid and variable sized objects at the end.
+ if (!A.IsValid || !B.IsValid)
+ return A.IsValid;
+ if (!A.ObjectSize || !B.ObjectSize)
+ return A.ObjectSize > 0;
+ uint64_t ADensityCmp = A.D12Count * B.ObjectSize;
+ uint64_t BDensityCmp = B.D12Count * A.ObjectSize;
+ if (ADensityCmp != BDensityCmp)
+ return ADensityCmp < BDensityCmp;
+ return A.DPairCount * B.ObjectSize < B.DPairCount * A.ObjectSize;
+ };
+ std::stable_sort(SortingObjects.begin(), SortingObjects.end(), CmpD12);
+
+ // Now modify the original list to represent the final order that
+ // we want.
+ unsigned Idx = 0;
+ for (auto &Obj : SortingObjects) {
+ // All invalid items are sorted at the end, so it's safe to stop.
+ if (!Obj.IsValid)
+ break;
+ ObjectsToAllocate[Idx++] = Obj.ObjectIndex;
+ }
+}
+
bool SystemZFrameLowering::hasReservedCallFrame(
const MachineFunction &MF) const {
// The ELF ABI requires us to allocate 160 bytes of stack space for the