10b57cec5SDimitry Andric //===-- MachineFrameInfo.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file Implements MachineFrameInfo that manages the stack frame.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
220b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
230b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
240b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
250b57cec5SDimitry Andric #include <cassert>
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric #define DEBUG_TYPE "codegen"
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric
ensureMaxAlignment(Align Alignment)318bcb0991SDimitry Andric void MachineFrameInfo::ensureMaxAlignment(Align Alignment) {
320b57cec5SDimitry Andric if (!StackRealignable)
338bcb0991SDimitry Andric assert(Alignment <= StackAlignment &&
348bcb0991SDimitry Andric "For targets without stack realignment, Alignment is out of limit!");
358bcb0991SDimitry Andric if (MaxAlignment < Alignment)
368bcb0991SDimitry Andric MaxAlignment = Alignment;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric /// Clamp the alignment if requested and emit a warning.
clampStackAlignment(bool ShouldClamp,Align Alignment,Align StackAlignment)408bcb0991SDimitry Andric static inline Align clampStackAlignment(bool ShouldClamp, Align Alignment,
418bcb0991SDimitry Andric Align StackAlignment) {
428bcb0991SDimitry Andric if (!ShouldClamp || Alignment <= StackAlignment)
438bcb0991SDimitry Andric return Alignment;
445ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Warning: requested alignment " << DebugStr(Alignment)
455ffd83dbSDimitry Andric << " exceeds the stack alignment "
465ffd83dbSDimitry Andric << DebugStr(StackAlignment)
470b57cec5SDimitry Andric << " when stack realignment is off" << '\n');
488bcb0991SDimitry Andric return StackAlignment;
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric
CreateStackObject(uint64_t Size,Align Alignment,bool IsSpillSlot,const AllocaInst * Alloca,uint8_t StackID)518bcb0991SDimitry Andric int MachineFrameInfo::CreateStackObject(uint64_t Size, Align Alignment,
520b57cec5SDimitry Andric bool IsSpillSlot,
530b57cec5SDimitry Andric const AllocaInst *Alloca,
540b57cec5SDimitry Andric uint8_t StackID) {
550b57cec5SDimitry Andric assert(Size != 0 && "Cannot allocate zero size stack objects!");
560b57cec5SDimitry Andric Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
570b57cec5SDimitry Andric Objects.push_back(StackObject(Size, Alignment, 0, false, IsSpillSlot, Alloca,
580b57cec5SDimitry Andric !IsSpillSlot, StackID));
590b57cec5SDimitry Andric int Index = (int)Objects.size() - NumFixedObjects - 1;
600b57cec5SDimitry Andric assert(Index >= 0 && "Bad frame index!");
61bdd1243dSDimitry Andric if (contributesToMaxAlignment(StackID))
620b57cec5SDimitry Andric ensureMaxAlignment(Alignment);
630b57cec5SDimitry Andric return Index;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric
CreateSpillStackObject(uint64_t Size,Align Alignment)668bcb0991SDimitry Andric int MachineFrameInfo::CreateSpillStackObject(uint64_t Size, Align Alignment) {
670b57cec5SDimitry Andric Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
680b57cec5SDimitry Andric CreateStackObject(Size, Alignment, true);
690b57cec5SDimitry Andric int Index = (int)Objects.size() - NumFixedObjects - 1;
700b57cec5SDimitry Andric ensureMaxAlignment(Alignment);
710b57cec5SDimitry Andric return Index;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
CreateVariableSizedObject(Align Alignment,const AllocaInst * Alloca)748bcb0991SDimitry Andric int MachineFrameInfo::CreateVariableSizedObject(Align Alignment,
750b57cec5SDimitry Andric const AllocaInst *Alloca) {
760b57cec5SDimitry Andric HasVarSizedObjects = true;
770b57cec5SDimitry Andric Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
780b57cec5SDimitry Andric Objects.push_back(StackObject(0, Alignment, 0, false, false, Alloca, true));
790b57cec5SDimitry Andric ensureMaxAlignment(Alignment);
800b57cec5SDimitry Andric return (int)Objects.size()-NumFixedObjects-1;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric
CreateFixedObject(uint64_t Size,int64_t SPOffset,bool IsImmutable,bool IsAliased)830b57cec5SDimitry Andric int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
840b57cec5SDimitry Andric bool IsImmutable, bool IsAliased) {
850b57cec5SDimitry Andric assert(Size != 0 && "Cannot allocate zero size fixed stack objects!");
860b57cec5SDimitry Andric // The alignment of the frame index can be determined from its offset from
870b57cec5SDimitry Andric // the incoming frame position. If the frame object is at offset 32 and
880b57cec5SDimitry Andric // the stack is guaranteed to be 16-byte aligned, then we know that the
890b57cec5SDimitry Andric // object is 16-byte aligned. Note that unlike the non-fixed case, if the
900b57cec5SDimitry Andric // stack needs realignment, we can't assume that the stack will in fact be
910b57cec5SDimitry Andric // aligned.
928bcb0991SDimitry Andric Align Alignment =
935ffd83dbSDimitry Andric commonAlignment(ForcedRealign ? Align(1) : StackAlignment, SPOffset);
940b57cec5SDimitry Andric Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
950b57cec5SDimitry Andric Objects.insert(Objects.begin(),
960b57cec5SDimitry Andric StackObject(Size, Alignment, SPOffset, IsImmutable,
970b57cec5SDimitry Andric /*IsSpillSlot=*/false, /*Alloca=*/nullptr,
980b57cec5SDimitry Andric IsAliased));
990b57cec5SDimitry Andric return -++NumFixedObjects;
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric
CreateFixedSpillStackObject(uint64_t Size,int64_t SPOffset,bool IsImmutable)1020b57cec5SDimitry Andric int MachineFrameInfo::CreateFixedSpillStackObject(uint64_t Size,
1030b57cec5SDimitry Andric int64_t SPOffset,
1040b57cec5SDimitry Andric bool IsImmutable) {
1058bcb0991SDimitry Andric Align Alignment =
1065ffd83dbSDimitry Andric commonAlignment(ForcedRealign ? Align(1) : StackAlignment, SPOffset);
1070b57cec5SDimitry Andric Alignment = clampStackAlignment(!StackRealignable, Alignment, StackAlignment);
1080b57cec5SDimitry Andric Objects.insert(Objects.begin(),
1090b57cec5SDimitry Andric StackObject(Size, Alignment, SPOffset, IsImmutable,
1100b57cec5SDimitry Andric /*IsSpillSlot=*/true, /*Alloca=*/nullptr,
1110b57cec5SDimitry Andric /*IsAliased=*/false));
1120b57cec5SDimitry Andric return -++NumFixedObjects;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
getPristineRegs(const MachineFunction & MF) const1150b57cec5SDimitry Andric BitVector MachineFrameInfo::getPristineRegs(const MachineFunction &MF) const {
1160b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1170b57cec5SDimitry Andric BitVector BV(TRI->getNumRegs());
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric // Before CSI is calculated, no registers are considered pristine. They can be
1200b57cec5SDimitry Andric // freely used and PEI will make sure they are saved.
1210b57cec5SDimitry Andric if (!isCalleeSavedInfoValid())
1220b57cec5SDimitry Andric return BV;
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
1250b57cec5SDimitry Andric for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR;
1260b57cec5SDimitry Andric ++CSR)
1270b57cec5SDimitry Andric BV.set(*CSR);
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric // Saved CSRs are not pristine.
130fcaf7f86SDimitry Andric for (const auto &I : getCalleeSavedInfo())
13106c3fb27SDimitry Andric for (MCPhysReg S : TRI->subregs_inclusive(I.getReg()))
13206c3fb27SDimitry Andric BV.reset(S);
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric return BV;
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
estimateStackSize(const MachineFunction & MF) const137480093f4SDimitry Andric uint64_t MachineFrameInfo::estimateStackSize(const MachineFunction &MF) const {
1380b57cec5SDimitry Andric const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
1390b57cec5SDimitry Andric const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
1405ffd83dbSDimitry Andric Align MaxAlign = getMaxAlign();
141480093f4SDimitry Andric int64_t Offset = 0;
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric // This code is very, very similar to PEI::calculateFrameObjectOffsets().
1440b57cec5SDimitry Andric // It really should be refactored to share code. Until then, changes
1450b57cec5SDimitry Andric // should keep in mind that there's tight coupling between the two.
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric for (int i = getObjectIndexBegin(); i != 0; ++i) {
1480b57cec5SDimitry Andric // Only estimate stack size of default stack.
1490b57cec5SDimitry Andric if (getStackID(i) != TargetStackID::Default)
1500b57cec5SDimitry Andric continue;
151480093f4SDimitry Andric int64_t FixedOff = -getObjectOffset(i);
1520b57cec5SDimitry Andric if (FixedOff > Offset) Offset = FixedOff;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric for (unsigned i = 0, e = getObjectIndexEnd(); i != e; ++i) {
1550b57cec5SDimitry Andric // Only estimate stack size of live objects on default stack.
1560b57cec5SDimitry Andric if (isDeadObjectIndex(i) || getStackID(i) != TargetStackID::Default)
1570b57cec5SDimitry Andric continue;
1580b57cec5SDimitry Andric Offset += getObjectSize(i);
1595ffd83dbSDimitry Andric Align Alignment = getObjectAlign(i);
1600b57cec5SDimitry Andric // Adjust to alignment boundary
1615ffd83dbSDimitry Andric Offset = alignTo(Offset, Alignment);
1620b57cec5SDimitry Andric
1635ffd83dbSDimitry Andric MaxAlign = std::max(Alignment, MaxAlign);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric if (adjustsStack() && TFI->hasReservedCallFrame(MF))
1670b57cec5SDimitry Andric Offset += getMaxCallFrameSize();
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric // Round up the size to a multiple of the alignment. If the function has
1700b57cec5SDimitry Andric // any calls or alloca's, align to the target's StackAlignment value to
1710b57cec5SDimitry Andric // ensure that the callee's frame or the alloca data is suitably aligned;
1720b57cec5SDimitry Andric // otherwise, for leaf functions, align to the TransientStackAlignment
1730b57cec5SDimitry Andric // value.
1745ffd83dbSDimitry Andric Align StackAlign;
1750b57cec5SDimitry Andric if (adjustsStack() || hasVarSizedObjects() ||
176fe6060f1SDimitry Andric (RegInfo->hasStackRealignment(MF) && getObjectIndexEnd() != 0))
1775ffd83dbSDimitry Andric StackAlign = TFI->getStackAlign();
1780b57cec5SDimitry Andric else
1795ffd83dbSDimitry Andric StackAlign = TFI->getTransientStackAlign();
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andric // If the frame pointer is eliminated, all frame offsets will be relative to
1820b57cec5SDimitry Andric // SP not FP. Align to MaxAlign so this works.
1830b57cec5SDimitry Andric StackAlign = std::max(StackAlign, MaxAlign);
1845ffd83dbSDimitry Andric return alignTo(Offset, StackAlign);
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
computeMaxCallFrameSize(MachineFunction & MF,std::vector<MachineBasicBlock::iterator> * FrameSDOps)1870fca6ea1SDimitry Andric void MachineFrameInfo::computeMaxCallFrameSize(
1880fca6ea1SDimitry Andric MachineFunction &MF, std::vector<MachineBasicBlock::iterator> *FrameSDOps) {
1890b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
1900b57cec5SDimitry Andric unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode();
1910b57cec5SDimitry Andric unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
1920b57cec5SDimitry Andric assert(FrameSetupOpcode != ~0u && FrameDestroyOpcode != ~0u &&
1930b57cec5SDimitry Andric "Can only compute MaxCallFrameSize if Setup/Destroy opcode are known");
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andric MaxCallFrameSize = 0;
1960fca6ea1SDimitry Andric for (MachineBasicBlock &MBB : MF) {
1970fca6ea1SDimitry Andric for (MachineInstr &MI : MBB) {
1980b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode();
1990b57cec5SDimitry Andric if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) {
200*36b606aeSDimitry Andric uint64_t Size = TII.getFrameSize(MI);
2010b57cec5SDimitry Andric MaxCallFrameSize = std::max(MaxCallFrameSize, Size);
2020fca6ea1SDimitry Andric if (FrameSDOps != nullptr)
2030fca6ea1SDimitry Andric FrameSDOps->push_back(&MI);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
print(const MachineFunction & MF,raw_ostream & OS) const2090b57cec5SDimitry Andric void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{
2100b57cec5SDimitry Andric if (Objects.empty()) return;
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric const TargetFrameLowering *FI = MF.getSubtarget().getFrameLowering();
2130b57cec5SDimitry Andric int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0);
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andric OS << "Frame Objects:\n";
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
2180b57cec5SDimitry Andric const StackObject &SO = Objects[i];
2190b57cec5SDimitry Andric OS << " fi#" << (int)(i-NumFixedObjects) << ": ";
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric if (SO.StackID != 0)
2220b57cec5SDimitry Andric OS << "id=" << static_cast<unsigned>(SO.StackID) << ' ';
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric if (SO.Size == ~0ULL) {
2250b57cec5SDimitry Andric OS << "dead\n";
2260b57cec5SDimitry Andric continue;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric if (SO.Size == 0)
2290b57cec5SDimitry Andric OS << "variable sized";
2300b57cec5SDimitry Andric else
2310b57cec5SDimitry Andric OS << "size=" << SO.Size;
2328bcb0991SDimitry Andric OS << ", align=" << SO.Alignment.value();
2330b57cec5SDimitry Andric
2340b57cec5SDimitry Andric if (i < NumFixedObjects)
2350b57cec5SDimitry Andric OS << ", fixed";
2360b57cec5SDimitry Andric if (i < NumFixedObjects || SO.SPOffset != -1) {
2370b57cec5SDimitry Andric int64_t Off = SO.SPOffset - ValOffset;
2380b57cec5SDimitry Andric OS << ", at location [SP";
2390b57cec5SDimitry Andric if (Off > 0)
2400b57cec5SDimitry Andric OS << "+" << Off;
2410b57cec5SDimitry Andric else if (Off < 0)
2420b57cec5SDimitry Andric OS << Off;
2430b57cec5SDimitry Andric OS << "]";
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric OS << "\n";
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump(const MachineFunction & MF) const2500b57cec5SDimitry Andric LLVM_DUMP_METHOD void MachineFrameInfo::dump(const MachineFunction &MF) const {
2510b57cec5SDimitry Andric print(MF, dbgs());
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric #endif
254