diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:04:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:05:05 +0000 |
| commit | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (patch) | |
| tree | 3a4038f3b7bafaeade9fd6146ea8021237616657 /llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp | |
| parent | 6f8fc217eaa12bf657be1c6468ed9938d10168b3 (diff) | |
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp | 82 |
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 |
