LLVM 20.0.0git
Classes | Macros | Functions | Variables
AArch64FrameLowering.cpp File Reference
#include "AArch64FrameLowering.h"
#include "AArch64InstrInfo.h"
#include "AArch64MachineFunctionInfo.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/ADT/Statistic.h"
#include "llvm/Analysis/ValueTracking.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  StackAccess
 

Macros

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

Functions

 STATISTIC (NumRedZoneFunctions, "Number of functions using red zone")
 
static int64_t getArgumentStackToRestore (MachineFunction &MF, MachineBasicBlock &MBB)
 Returns how much of the incoming argument stack area (in bytes) we should clean up in an epilogue.
 
static bool produceCompactUnwindFrame (MachineFunction &MF)
 
static bool needsWinCFI (const MachineFunction &MF)
 
static StackOffset getSVEStackSize (const MachineFunction &MF)
 Returns the size of the entire SVE stackframe (calleesaves + spills).
 
static Register findScratchNonCalleeSaveRegister (MachineBasicBlock *MBB)
 
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 unsigned getFixedObjectSize (const MachineFunction &MF, const AArch64FunctionInfo *AFI, bool IsWin64, bool IsFunclet)
 Returns the size of the fixed object area (allocated next to sp on entry) On Win64 this may include a var args area and an UnwindHelp object for EH.
 
static void insertCFISameValue (const MCInstrDesc &Desc, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertPt, unsigned DwarfReg)
 
static void emitCalleeSavedRestores (MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool SVE)
 
static int64_t upperBound (StackOffset Size)
 
static MCRegister getRegisterOrZero (MCRegister Reg, bool HasSVE)
 
static void getLiveRegsForEntryMBB (LivePhysRegs &LiveRegs, const MachineBasicBlock &MBB)
 
static bool windowsRequiresStackProbe (MachineFunction &MF, uint64_t StackSizeInBytes)
 
static MachineBasicBlock::iterator InsertSEH (MachineBasicBlock::iterator MBBI, const TargetInstrInfo &TII, MachineInstr::MIFlag Flag)
 
static void fixupSEHOpcode (MachineBasicBlock::iterator MBBI, unsigned LocalStackSize)
 
bool requiresGetVGCall (MachineFunction &MF)
 
static bool requiresSaveVG (MachineFunction &MF)
 
bool isVGInstruction (MachineBasicBlock::iterator MBBI)
 
static MachineBasicBlock::iterator convertCalleeSaveRestoreToSPPrePostIncDec (MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const TargetInstrInfo *TII, int CSStackSizeInc, bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFI, MachineInstr::MIFlag FrameFlag=MachineInstr::FrameSetup, int CFAOffset=0)
 
static void fixupCalleeSaveRestoreStackOffset (MachineInstr &MI, uint64_t LocalStackSize, bool NeedsWinCFI, bool *HasWinCFI)
 
static bool isTargetWindows (const MachineFunction &MF)
 
static unsigned getStackHazardSize (const MachineFunction &MF)
 
static bool IsSVECalleeSave (MachineBasicBlock::iterator I)
 
static void emitShadowCallStackPrologue (const TargetInstrInfo &TII, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool NeedsWinCFI, bool NeedsUnwindInfo)
 
static void emitShadowCallStackEpilogue (const TargetInstrInfo &TII, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
 
static void emitDefineCFAWithFP (MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned FixedObject)
 
static void getLivePhysRegsUpTo (MachineInstr &MI, const TargetRegisterInfo &TRI, LivePhysRegs &LiveRegs)
 Collect live registers from the end of MI's parent up to (including) MI in LiveRegs.
 
static bool isFuncletReturnInstr (const MachineInstr &MI)
 
static StackOffset getFPOffset (const MachineFunction &MF, int64_t ObjectOffset)
 
static StackOffset getStackOffset (const MachineFunction &MF, int64_t ObjectOffset)
 
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)
 
static void computeCalleeSaveRegisterPairs (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)
 
MachineBasicBlock::iterator emitVGSaveRestore (MachineBasicBlock::iterator II, const AArch64FrameLowering *TFI)
 
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 257 of file AArch64FrameLowering.cpp.

Function Documentation

◆ computeCalleeSaveRegisterPairs()

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

◆ convertCalleeSaveRestoreToSPPrePostIncDec()

static MachineBasicBlock::iterator convertCalleeSaveRestoreToSPPrePostIncDec ( MachineBasicBlock MBB,
MachineBasicBlock::iterator  MBBI,
const DebugLoc DL,
const TargetInstrInfo TII,
int  CSStackSizeInc,
bool  NeedsWinCFI,
bool HasWinCFI,
bool  EmitCFI,
MachineInstr::MIFlag  FrameFlag = MachineInstr::FrameSetup,
int  CFAOffset = 0 
)
static

◆ determineSVEStackObjectOffsets()

static int64_t determineSVEStackObjectOffsets ( MachineFrameInfo MFI,
int &  MinCSFrameIndex,
int &  MaxCSFrameIndex,
bool  AssignOffsets 
)
static

◆ emitCalleeSavedRestores()

static void emitCalleeSavedRestores ( MachineBasicBlock MBB,
MachineBasicBlock::iterator  MBBI,
bool  SVE 
)
static

◆ emitDefineCFAWithFP()

static void emitDefineCFAWithFP ( MachineFunction MF,
MachineBasicBlock MBB,
MachineBasicBlock::iterator  MBBI,
const DebugLoc DL,
unsigned  FixedObject 
)
static

◆ emitShadowCallStackEpilogue()

static void emitShadowCallStackEpilogue ( const TargetInstrInfo TII,
MachineFunction MF,
MachineBasicBlock MBB,
MachineBasicBlock::iterator  MBBI,
const DebugLoc DL 
)
static

◆ emitShadowCallStackPrologue()

static void emitShadowCallStackPrologue ( const TargetInstrInfo TII,
MachineFunction MF,
MachineBasicBlock MBB,
MachineBasicBlock::iterator  MBBI,
const DebugLoc DL,
bool  NeedsWinCFI,
bool  NeedsUnwindInfo 
)
static

◆ emitVGSaveRestore()

◆ enableMultiVectorSpillFill()

bool enableMultiVectorSpillFill ( const AArch64Subtarget Subtarget,
MachineFunction MF 
)

◆ estimateRSStackSizeLimit()

static 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 396 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().

◆ findFreePredicateReg()

unsigned findFreePredicateReg ( BitVector SavedRegs)

◆ findScratchNonCalleeSaveRegister()

static Register findScratchNonCalleeSaveRegister ( MachineBasicBlock MBB)
static

◆ fixupCalleeSaveRestoreStackOffset()

static void fixupCalleeSaveRestoreStackOffset ( MachineInstr MI,
uint64_t  LocalStackSize,
bool  NeedsWinCFI,
bool HasWinCFI 
)
static

◆ fixupSEHOpcode()

static void fixupSEHOpcode ( MachineBasicBlock::iterator  MBBI,
unsigned  LocalStackSize 
)
static

◆ getArgumentStackToRestore()

static int64_t getArgumentStackToRestore ( MachineFunction MF,
MachineBasicBlock MBB 
)
static

Returns how much of the incoming argument stack area (in bytes) we should clean up in an epilogue.

For the C calling convention this will be 0, for guaranteed tail call conventions it can be positive (a normal return or a tail call to a function that uses less stack space for arguments) or negative (for a tail call to a function that needs more stack space than us for arguments).

Definition at line 299 of file AArch64FrameLowering.cpp.

References llvm::MachineBasicBlock::end(), llvm::AArch64FunctionInfo::getArgumentStackToRestore(), llvm::MachineOperand::getImm(), llvm::MachineFunction::getInfo(), llvm::MachineBasicBlock::getLastNonDebugInstr(), llvm::AArch64InstrInfo::isTailCallReturnInst(), MBB, and MBBI.

Referenced by llvm::AArch64FrameLowering::emitEpilogue(), and llvm::ARMFrameLowering::emitEpilogue().

◆ getFixedObjectSize()

static unsigned getFixedObjectSize ( const MachineFunction MF,
const AArch64FunctionInfo AFI,
bool  IsWin64,
bool  IsFunclet 
)
static

◆ getFPOffset()

static StackOffset getFPOffset ( const MachineFunction MF,
int64_t  ObjectOffset 
)
static

◆ getLdStFrameID()

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

Definition at line 3621 of file AArch64FrameLowering.cpp.

References getMMOFrameID(), and MI.

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

◆ getLivePhysRegsUpTo()

static void getLivePhysRegsUpTo ( MachineInstr MI,
const TargetRegisterInfo TRI,
LivePhysRegs LiveRegs 
)
static

Collect live registers from the end of MI's parent up to (including) MI in LiveRegs.

Definition at line 1724 of file AArch64FrameLowering.cpp.

References llvm::LivePhysRegs::addLiveOuts(), llvm::MachineBasicBlock::instr_end(), llvm::make_range(), MBB, MI, llvm::reverse(), and llvm::LivePhysRegs::stepBackward().

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

◆ getLiveRegsForEntryMBB()

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

◆ getMMOFrameID()

static std::optional< int > getMMOFrameID ( MachineMemOperand MMO,
const MachineFrameInfo MFI 
)
static

◆ getPrologueDeath()

static unsigned getPrologueDeath ( MachineFunction MF,
unsigned  Reg 
)
static

◆ getRegisterOrZero()

static MCRegister getRegisterOrZero ( MCRegister  Reg,
bool  HasSVE 
)
static

Definition at line 920 of file AArch64FrameLowering.cpp.

References CASE.

◆ getStackHazardSize()

static unsigned getStackHazardSize ( const MachineFunction MF)
static

◆ getStackOffset()

static StackOffset getStackOffset ( const MachineFunction MF,
int64_t  ObjectOffset 
)
static

◆ getSVECalleeSaveSlotRange()

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

returns true if there are any SVE callee saves.

Definition at line 4072 of file AArch64FrameLowering.cpp.

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

Referenced by determineSVEStackObjectOffsets().

◆ getSVEStackSize()

static StackOffset getSVEStackSize ( const MachineFunction MF)
static

◆ insertCFISameValue()

static void insertCFISameValue ( const MCInstrDesc Desc,
MachineFunction MF,
MachineBasicBlock MBB,
MachineBasicBlock::iterator  InsertPt,
unsigned  DwarfReg 
)
static

◆ InsertSEH()

◆ invalidateRegisterPairing()

static 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 2905 of file AArch64FrameLowering.cpp.

References invalidateWindowsRegisterPairing(), and TRI.

Referenced by computeCalleeSaveRegisterPairs().

◆ invalidateWindowsRegisterPairing()

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

Definition at line 2874 of file AArch64FrameLowering.cpp.

References TRI.

Referenced by computeCalleeSaveRegisterPairs(), and invalidateRegisterPairing().

◆ isFuncletReturnInstr()

static bool isFuncletReturnInstr ( const MachineInstr MI)
static

◆ IsSVECalleeSave()

static bool IsSVECalleeSave ( MachineBasicBlock::iterator  I)
static

◆ isTargetWindows()

static bool isTargetWindows ( const MachineFunction MF)
static

◆ isVGInstruction()

bool isVGInstruction ( MachineBasicBlock::iterator  MBBI)

◆ needsWinCFI()

static bool needsWinCFI ( const MachineFunction MF)
static

◆ operator<<()

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

Definition at line 5184 of file AArch64FrameLowering.cpp.

References OS, and StackAccess::print().

◆ produceCompactUnwindFrame()

static bool produceCompactUnwindFrame ( MachineFunction MF)
static

◆ requiresGetVGCall()

bool requiresGetVGCall ( MachineFunction MF)

◆ requiresSaveVG()

static bool requiresSaveVG ( MachineFunction MF)
static

◆ STATISTIC()

STATISTIC ( NumRedZoneFunctions  ,
"Number of functions using red zone"   
)

◆ upperBound()

static int64_t upperBound ( StackOffset  Size)
static

Definition at line 775 of file AArch64FrameLowering.cpp.

References Size.

◆ windowsRequiresStackProbe()

static bool windowsRequiresStackProbe ( MachineFunction MF,
uint64_t  StackSizeInBytes 
)
static

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 391 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