LLVM 22.0.0git
AArch64FrameLowering.cpp File Reference
#include "AArch64FrameLowering.h"
#include "AArch64InstrInfo.h"
#include "AArch64MachineFunctionInfo.h"
#include "AArch64PrologueEpilogue.h"
#include "AArch64RegisterInfo.h"
#include "AArch64Subtarget.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "Utils/AArch64SMEAttributes.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/CFIInstBuilder.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/WinEHFuncInfo.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <cassert>
#include <cstdint>
#include <iterator>
#include <optional>
#include <vector>

Go to the source code of this file.

Classes

struct  ScopedScavengeOrSpill
 RAII helper class for scavenging or spilling a register. More...
struct  EmergencyStackSlots
 Emergency stack slots for expanding SPILL_PPR_TO_ZPR_SLOT_PSEUDO and FILL_PPR_FROM_ZPR_SLOT_PSEUDO. More...
struct  ScavengeableRegs
 Registers available for scavenging (ZPR, PPR3b, GPR). More...
struct  StackAccess

Macros

#define DEBUG_TYPE   "frame-info"
#define CASE(n)
#define CASE(n)

Functions

static bool produceCompactUnwindFrame (const AArch64FrameLowering &, MachineFunction &MF)
static bool isLikelyToHaveSVEStack (const AArch64FrameLowering &AFL, const MachineFunction &MF)
static unsigned estimateRSStackSizeLimit (MachineFunction &MF)
 Look at each instruction that references stack frames and return the stack size limit beyond which some of these instructions will require a scratch register during their expansion later.
static MCRegister getRegisterOrZero (MCRegister Reg, bool HasSVE)
static void getLiveRegsForEntryMBB (LivePhysRegs &LiveRegs, const MachineBasicBlock &MBB)
static bool isTargetWindows (const MachineFunction &MF)
static unsigned getStackHazardSize (const MachineFunction &MF)
static unsigned getPrologueDeath (MachineFunction &MF, unsigned Reg)
static bool invalidateWindowsRegisterPairing (unsigned Reg1, unsigned Reg2, bool NeedsWinCFI, bool IsFirst, const TargetRegisterInfo *TRI)
static bool invalidateRegisterPairing (unsigned Reg1, unsigned Reg2, bool UsesWinAAPCS, bool NeedsWinCFI, bool NeedsFrameRecord, bool IsFirst, const TargetRegisterInfo *TRI)
 Returns true if Reg1 and Reg2 cannot be paired using a ldp/stp instruction.
unsigned findFreePredicateReg (BitVector &SavedRegs)
bool enableMultiVectorSpillFill (const AArch64Subtarget &Subtarget, MachineFunction &MF)
void computeCalleeSaveRegisterPairs (const AArch64FrameLowering &AFL, MachineFunction &MF, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI, SmallVectorImpl< RegPairInfo > &RegPairs, bool NeedsFrameRecord)
static std::optional< int > getMMOFrameID (MachineMemOperand *MMO, const MachineFrameInfo &MFI)
static std::optional< int > getLdStFrameID (const MachineInstr &MI, const MachineFrameInfo &MFI)
static bool getSVECalleeSaveSlotRange (const MachineFrameInfo &MFI, int &Min, int &Max)
 returns true if there are any SVE callee saves.
static int64_t determineSVEStackObjectOffsets (MachineFrameInfo &MFI, int &MinCSFrameIndex, int &MaxCSFrameIndex, bool AssignOffsets)
static Register tryScavengeRegister (LiveRegUnits const &UsedRegs, BitVector const &ScavengeableRegs, Register PreferredReg)
 Attempts to scavenge a register from ScavengeableRegs given the used registers in UsedRegs.
static void propagateFrameFlags (MachineInstr &SourceMI, ArrayRef< MachineInstr * > MachineInstrs)
 Propagates frame-setup/destroy flags from SourceMI to all instructions in MachineInstrs.
static bool isInPrologueOrEpilogue (const MachineInstr &MI)
static void expandSpillPPRToZPRSlotPseudo (MachineBasicBlock &MBB, MachineInstr &MI, const TargetRegisterInfo &TRI, LiveRegUnits const &UsedRegs, ScavengeableRegs const &SR, EmergencyStackSlots &SpillSlots)
 Expands:
static bool expandFillPPRFromZPRSlotPseudo (MachineBasicBlock &MBB, MachineInstr &MI, const TargetRegisterInfo &TRI, LiveRegUnits const &UsedRegs, ScavengeableRegs const &SR, MachineInstr *&LastPTrue, EmergencyStackSlots &SpillSlots)
 Expands:
static bool expandSMEPPRToZPRSpillPseudos (MachineBasicBlock &MBB, const TargetRegisterInfo &TRI, ScavengeableRegs const &SR, EmergencyStackSlots &SpillSlots)
 Expands all FILL_PPR_FROM_ZPR_SLOT_PSEUDO and SPILL_PPR_TO_ZPR_SLOT_PSEUDO operations within the MachineBasicBlock MBB.
static raw_ostreamoperator<< (raw_ostream &OS, const StackAccess &SA)

Variables

static cl::opt< boolEnableRedZone ("aarch64-redzone", cl::desc("enable use of redzone on AArch64"), cl::init(false), cl::Hidden)
static cl::opt< boolStackTaggingMergeSetTag ("stack-tagging-merge-settag", cl::desc("merge settag instruction in function epilog"), cl::init(true), cl::Hidden)
static cl::opt< boolOrderFrameObjects ("aarch64-order-frame-objects", cl::desc("sort stack allocations"), cl::init(true), cl::Hidden)
cl::opt< boolEnableHomogeneousPrologEpilog ("homogeneous-prolog-epilog", cl::Hidden, cl::desc("Emit homogeneous prologue and epilogue for the size " "optimization (default = off)"))
static cl::opt< unsignedStackHazardRemarkSize ("aarch64-stack-hazard-remark-size", cl::init(0), cl::Hidden)
static cl::opt< boolStackHazardInNonStreaming ("aarch64-stack-hazard-in-non-streaming", cl::init(false), cl::Hidden)
static cl::opt< boolDisableMultiVectorSpillFill ("aarch64-disable-multivector-spill-fill", cl::desc("Disable use of LD/ST pairs for SME2 or SVE2p1"), cl::init(false), cl::Hidden)
static const unsigned DefaultSafeSPDisplacement = 255
 This is the biggest offset to the stack pointer we can encode in aarch64 instructions (without using a separate calculation and a temp register).

Macro Definition Documentation

◆ CASE [1/2]

#define CASE ( n)
Value:
case AArch64::W##n: \
case AArch64::X##n: \
return AArch64::X##n

◆ CASE [2/2]

#define CASE ( n)
Value:
case AArch64::B##n: \
case AArch64::H##n: \
case AArch64::S##n: \
case AArch64::D##n: \
case AArch64::Q##n: \
return HasSVE ? AArch64::Z##n : AArch64::Q##n

◆ DEBUG_TYPE

#define DEBUG_TYPE   "frame-info"

Definition at line 262 of file AArch64FrameLowering.cpp.

Function Documentation

◆ computeCalleeSaveRegisterPairs()

void computeCalleeSaveRegisterPairs ( const AArch64FrameLowering & AFL,
MachineFunction & MF,
ArrayRef< CalleeSavedInfo > CSI,
const TargetRegisterInfo * TRI,
SmallVectorImpl< RegPairInfo > & RegPairs,
bool NeedsFrameRecord )

◆ determineSVEStackObjectOffsets()

◆ enableMultiVectorSpillFill()

◆ estimateRSStackSizeLimit()

unsigned estimateRSStackSizeLimit ( MachineFunction & MF)
static

Look at each instruction that references stack frames and return the stack size limit beyond which some of these instructions will require a scratch register during their expansion later.

Definition at line 414 of file AArch64FrameLowering.cpp.

References llvm::AArch64FrameOffsetCannotUpdate, DefaultSafeSPDisplacement, llvm::isAArch64FrameOffsetLegal(), MBB, MI, and llvm::Offset.

Referenced by llvm::AArch64FrameLowering::determineCalleeSaves(), llvm::ARMFrameLowering::determineCalleeSaves(), and llvm::CSKYFrameLowering::determineCalleeSaves().

◆ expandFillPPRFromZPRSlotPseudo()

bool expandFillPPRFromZPRSlotPseudo ( MachineBasicBlock & MBB,
MachineInstr & MI,
const TargetRegisterInfo & TRI,
LiveRegUnits const & UsedRegs,
ScavengeableRegs const & SR,
MachineInstr *& LastPTrue,
EmergencyStackSlots & SpillSlots )
static

Expands:

$p0 = FILL_PPR_FROM_ZPR_SLOT_PSEUDO %stack.0, 0

To:

$z0 = LDR_ZXI %stack.0, 0
$p0 = PTRUE_B 31, implicit $vg
$p0 = CMPNE_PPzZI_B $p0, $z0, 0, implicit-def $nzcv, implicit-def $nzcv

While ensuring a ZPR ($z0 in this example) is free for the predicate ( spilling if necessary). If the status flags are in use at the point of expansion they are preserved (by moving them to/from a GPR). This may cause an additional spill if no GPR is free at the expansion point.

Definition at line 2925 of file AArch64FrameLowering.cpp.

References llvm::MachineInstrBuilder::add(), llvm::MachineInstrBuilder::addImm(), llvm::MachineInstrBuilder::addReg(), assert(), llvm::LiveRegUnits::available(), llvm::BuildMI(), llvm::RegState::Define, DL, llvm::MachineInstrBuilder::getInstr(), llvm::MachineInstr::getOperand(), llvm::MachineOperand::getReg(), llvm::MachineFunction::getSubtarget(), ScavengeableRegs::GPRRegs, EmergencyStackSlots::GPRSpillFI, ScopedScavengeOrSpill::hasSpilled(), llvm::RegState::Implicit, llvm::RegState::ImplicitDefine, isInPrologueOrEpilogue(), MBB, MI, llvm::MachineInstr::moveBefore(), ScavengeableRegs::PPR3bRegs, EmergencyStackSlots::PPRSpillFI, propagateFrameFlags(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::MachineInstrBuilder::setMemRefs(), TII, TRI, ScavengeableRegs::ZPRRegs, and EmergencyStackSlots::ZPRSpillFI.

Referenced by expandSMEPPRToZPRSpillPseudos().

◆ expandSMEPPRToZPRSpillPseudos()

◆ expandSpillPPRToZPRSlotPseudo()

void expandSpillPPRToZPRSlotPseudo ( MachineBasicBlock & MBB,
MachineInstr & MI,
const TargetRegisterInfo & TRI,
LiveRegUnits const & UsedRegs,
ScavengeableRegs const & SR,
EmergencyStackSlots & SpillSlots )
static

◆ findFreePredicateReg()

unsigned findFreePredicateReg ( BitVector & SavedRegs)

◆ getLdStFrameID()

std::optional< int > getLdStFrameID ( const MachineInstr & MI,
const MachineFrameInfo & MFI )
static

Definition at line 2194 of file AArch64FrameLowering.cpp.

References getMMOFrameID(), and MI.

Referenced by llvm::AArch64FrameLowering::orderFrameObjects().

◆ getLiveRegsForEntryMBB()

void getLiveRegsForEntryMBB ( LivePhysRegs & LiveRegs,
const MachineBasicBlock & MBB )
static

◆ getMMOFrameID()

◆ getPrologueDeath()

◆ getRegisterOrZero()

MCRegister getRegisterOrZero ( MCRegister Reg,
bool HasSVE )
static

Definition at line 709 of file AArch64FrameLowering.cpp.

References CASE, and Reg.

◆ getStackHazardSize()

◆ getSVECalleeSaveSlotRange()

bool getSVECalleeSaveSlotRange ( const MachineFrameInfo & MFI,
int & Min,
int & Max )
static

returns true if there are any SVE callee saves.

Definition at line 2646 of file AArch64FrameLowering.cpp.

References assert(), contains(), llvm::MachineFrameInfo::getCalleeSavedInfo(), and llvm::MachineFrameInfo::isCalleeSavedInfoValid().

Referenced by determineSVEStackObjectOffsets().

◆ invalidateRegisterPairing()

bool invalidateRegisterPairing ( unsigned Reg1,
unsigned Reg2,
bool UsesWinAAPCS,
bool NeedsWinCFI,
bool NeedsFrameRecord,
bool IsFirst,
const TargetRegisterInfo * TRI )
static

Returns true if Reg1 and Reg2 cannot be paired using a ldp/stp instruction.

WindowsCFI requires that only consecutive registers can be paired. LR and FP need to be allocated together when the frame needs to save the frame-record. This means any other register pairing with LR is invalid.

Definition at line 1516 of file AArch64FrameLowering.cpp.

References invalidateWindowsRegisterPairing(), and TRI.

Referenced by computeCalleeSaveRegisterPairs().

◆ invalidateWindowsRegisterPairing()

bool invalidateWindowsRegisterPairing ( unsigned Reg1,
unsigned Reg2,
bool NeedsWinCFI,
bool IsFirst,
const TargetRegisterInfo * TRI )
static

Definition at line 1485 of file AArch64FrameLowering.cpp.

References TRI.

Referenced by computeCalleeSaveRegisterPairs(), and invalidateRegisterPairing().

◆ isInPrologueOrEpilogue()

◆ isLikelyToHaveSVEStack()

◆ isTargetWindows()

◆ operator<<()

raw_ostream & operator<< ( raw_ostream & OS,
const StackAccess & SA )
inlinestatic

Definition at line 4035 of file AArch64FrameLowering.cpp.

References StackAccess::print().

◆ produceCompactUnwindFrame()

◆ propagateFrameFlags()

void propagateFrameFlags ( MachineInstr & SourceMI,
ArrayRef< MachineInstr * > MachineInstrs )
static

Propagates frame-setup/destroy flags from SourceMI to all instructions in MachineInstrs.

Definition at line 2778 of file AArch64FrameLowering.cpp.

References llvm::MachineInstr::FrameDestroy, llvm::MachineInstr::FrameSetup, llvm::MachineInstr::getFlag(), and MI.

Referenced by expandFillPPRFromZPRSlotPseudo(), and expandSpillPPRToZPRSlotPseudo().

◆ tryScavengeRegister()

Register tryScavengeRegister ( LiveRegUnits const & UsedRegs,
BitVector const & ScavengeableRegs,
Register PreferredReg )
static

Attempts to scavenge a register from ScavengeableRegs given the used registers in UsedRegs.

Definition at line 2764 of file AArch64FrameLowering.cpp.

References llvm::LiveRegUnits::available(), and Reg.

Referenced by ScopedScavengeOrSpill::ScopedScavengeOrSpill().

Variable Documentation

◆ DefaultSafeSPDisplacement

const unsigned DefaultSafeSPDisplacement = 255
static

This is the biggest offset to the stack pointer we can encode in aarch64 instructions (without using a separate calculation and a temp register).

Note that the exception here are vector stores/loads which cannot encode any displacements (see estimateRSStackSizeLimit(), isAArch64FrameOffsetLegal()).

Definition at line 409 of file AArch64FrameLowering.cpp.

Referenced by estimateRSStackSizeLimit(), and llvm::AArch64FrameLowering::hasFPImpl().

◆ DisableMultiVectorSpillFill

cl::opt< bool > DisableMultiVectorSpillFill("aarch64-disable-multivector-spill-fill", cl::desc("Disable use of LD/ST pairs for SME2 or SVE2p1"), cl::init(false), cl::Hidden) ( "aarch64-disable-multivector-spill-fill" ,
cl::desc("Disable use of LD/ST pairs for SME2 or SVE2p1") ,
cl::init(false) ,
cl::Hidden  )
static

◆ EnableHomogeneousPrologEpilog

cl::opt< bool > EnableHomogeneousPrologEpilog("homogeneous-prolog-epilog", cl::Hidden, cl::desc("Emit homogeneous prologue and epilogue for the size " "optimization (default = off)")) ( "homogeneous-prolog-epilog" ,
cl::Hidden ,
cl::desc("Emit homogeneous prologue and epilogue for the size " "optimization (default = off)")  )

◆ EnableRedZone

cl::opt< bool > EnableRedZone("aarch64-redzone", cl::desc("enable use of redzone on AArch64"), cl::init(false), cl::Hidden) ( "aarch64-redzone" ,
cl::desc("enable use of redzone on AArch64") ,
cl::init(false) ,
cl::Hidden  )
static

◆ OrderFrameObjects

cl::opt< bool > OrderFrameObjects("aarch64-order-frame-objects", cl::desc("sort stack allocations"), cl::init(true), cl::Hidden) ( "aarch64-order-frame-objects" ,
cl::desc("sort stack allocations") ,
cl::init(true) ,
cl::Hidden  )
static

◆ StackHazardInNonStreaming

cl::opt< bool > StackHazardInNonStreaming("aarch64-stack-hazard-in-non-streaming", cl::init(false), cl::Hidden) ( "aarch64-stack-hazard-in-non-streaming" ,
cl::init(false) ,
cl::Hidden  )
static

◆ StackHazardRemarkSize

cl::opt< unsigned > StackHazardRemarkSize("aarch64-stack-hazard-remark-size", cl::init(0), cl::Hidden) ( "aarch64-stack-hazard-remark-size" ,
cl::init(0) ,
cl::Hidden  )
static

◆ StackTaggingMergeSetTag

cl::opt< bool > StackTaggingMergeSetTag("stack-tagging-merge-settag", cl::desc("merge settag instruction in function epilog"), cl::init(true), cl::Hidden) ( "stack-tagging-merge-settag" ,
cl::desc("merge settag instruction in function epilog") ,
cl::init(true) ,
cl::Hidden  )
static