72#define DEBUG_TYPE "aarch64-machine-sme-abi"
124 Register StatusFlags = AArch64::NoRegister;
125 Register X0Save = AArch64::NoRegister;
131 ZAState NeededState{ZAState::ANY};
133 LiveRegs PhysLiveRegs = LiveRegs::None;
140 ZAState FixedEntryState{ZAState::ANY};
141 ZAState DesiredIncomingState{ZAState::ANY};
142 ZAState DesiredOutgoingState{ZAState::ANY};
143 LiveRegs PhysLiveRegsAtEntry = LiveRegs::None;
144 LiveRegs PhysLiveRegsAtExit = LiveRegs::None;
150 std::optional<MachineBasicBlock::iterator> AfterSMEProloguePt;
151 LiveRegs PhysLiveRegsAfterSMEPrologue = LiveRegs::None;
158 EmitContext() =
default;
163 return *TPIDR2BlockFI;
166 return *TPIDR2BlockFI;
171 if (AgnosticZABufferPtr != AArch64::NoRegister)
172 return AgnosticZABufferPtr;
175 AgnosticZABufferPtr =
176 BufferPtr != AArch64::NoRegister
179 return AgnosticZABufferPtr;
192 bool needsSaveBuffer()
const {
193 assert(!(TPIDR2BlockFI && AgnosticZABufferPtr) &&
194 "Cannot have both a TPIDR2 block and agnostic ZA buffer");
195 return TPIDR2BlockFI || AgnosticZABufferPtr != AArch64::NoRegister;
199 std::optional<int> ZT0SaveFI;
200 std::optional<int> TPIDR2BlockFI;
201 Register AgnosticZABufferPtr = AArch64::NoRegister;
204StringRef getZAStateString(ZAState State) {
205#define MAKE_CASE(V) \
227 return AArch64::MPR128RegClass.contains(SR) ||
228 AArch64::ZTRRegClass.contains(SR);
234static std::pair<ZAState, MachineBasicBlock::iterator>
244 if (
MI.getOpcode() == AArch64::InOutZAUsePseudo)
245 return {ZAState::ACTIVE, std::prev(InsertPt)};
248 if (
MI.getOpcode() == AArch64::RequiresZASavePseudo)
249 return {ZAState::LOCAL_SAVED, std::prev(InsertPt)};
258 if (
MI.getOpcode() == AArch64::RequiresZT0SavePseudo) {
259 return {SMEFnAttrs.
hasZAState() ? ZAState::ACTIVE_ZT0_SAVED
260 : ZAState::LOCAL_COMMITTED,
261 std::prev(InsertPt)};
266 return {ZAOffAtReturn ? ZAState::OFF : ZAState::ACTIVE, InsertPt};
269 for (
auto &MO :
MI.operands()) {
270 if (isZAorZTRegOp(
TRI, MO))
271 return {ZAState::ACTIVE, InsertPt};
274 return {ZAState::ANY, InsertPt};
278 inline static char ID = 0;
285 StringRef getPassName()
const override {
return "Machine SME ABI pass"; }
299 FunctionInfo collectNeededZAStates(
SMEAttrs SMEFnAttrs);
304 const FunctionInfo &FnInfo);
308 void insertStateChanges(EmitContext &,
const FunctionInfo &FnInfo,
329 bool ClearTPIDR2,
bool On);
340 LiveRegs PhysLiveRegs,
bool IsSave);
348 std::pair<MachineBasicBlock::iterator, LiveRegs>
358 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
359 return emitFullZASaveRestore(Context,
MBB,
MBBI, PhysLiveRegs,
361 return emitSetupLazySave(Context,
MBB,
MBBI);
365 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
366 return emitFullZASaveRestore(Context,
MBB,
MBBI, PhysLiveRegs,
368 return emitRestoreLazySave(Context,
MBB,
MBBI, PhysLiveRegs);
373 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
374 return emitAllocateFullZASaveBuffer(Context,
MBB,
MBBI, PhysLiveRegs);
375 return emitAllocateLazySaveBuffer(Context,
MBB,
MBBI);
384 unsigned Marker)
const;
391 void emitError(
const Twine &Message) {
419 LiveRegs PhysLiveRegs = LiveRegs::None;
421 PhysLiveRegs |= LiveRegs::NZCV;
425 PhysLiveRegs |= LiveRegs::W0;
426 if (!LiveUnits.
available(AArch64::W0_HI))
427 PhysLiveRegs |= LiveRegs::W0_HI;
432 if (PhysLiveRegs & LiveRegs::NZCV)
433 LiveUnits.
addReg(AArch64::NZCV);
434 if (PhysLiveRegs & LiveRegs::W0)
435 LiveUnits.
addReg(AArch64::W0);
436 if (PhysLiveRegs & LiveRegs::W0_HI)
437 LiveUnits.
addReg(AArch64::W0_HI);
440[[maybe_unused]]
bool isCallStartOpcode(
unsigned Opc) {
442 case AArch64::TLSDESC_CALLSEQ:
443 case AArch64::TLSDESC_AUTH_CALLSEQ:
444 case AArch64::ADJCALLSTACKDOWN:
451FunctionInfo MachineSMEABI::collectNeededZAStates(
SMEAttrs SMEFnAttrs) {
454 "Expected function to have ZA/ZT0 state!");
457 LiveRegs PhysLiveRegsAfterSMEPrologue = LiveRegs::None;
458 std::optional<MachineBasicBlock::iterator> AfterSMEProloguePt;
461 BlockInfo &
Block = Blocks[
MBB.getNumber()];
463 if (
MBB.isEntryBlock()) {
465 Block.FixedEntryState = ZAState::ENTRY;
466 }
else if (
MBB.isEHPad()) {
468 Block.FixedEntryState = ZAState::LOCAL_COMMITTED;
474 Block.PhysLiveRegsAtExit = getPhysLiveRegs(LiveUnits);
475 auto FirstTerminatorInsertPt =
MBB.getFirstTerminator();
476 auto FirstNonPhiInsertPt =
MBB.getFirstNonPHI();
480 LiveRegs PhysLiveRegs = getPhysLiveRegs(LiveUnits);
485 if (
MI.getOpcode() == AArch64::SMEStateAllocPseudo) {
486 AfterSMEProloguePt =
MBBI;
487 PhysLiveRegsAfterSMEPrologue = PhysLiveRegs;
490 auto [NeededState, InsertPt] = getInstNeededZAState(*
TRI,
MI, SMEFnAttrs);
491 assert((InsertPt ==
MBBI || isCallStartOpcode(InsertPt->getOpcode())) &&
492 "Unexpected state change insertion point!");
494 if (
MBBI == FirstTerminatorInsertPt)
495 Block.PhysLiveRegsAtExit = PhysLiveRegs;
496 if (
MBBI == FirstNonPhiInsertPt)
497 Block.PhysLiveRegsAtEntry = PhysLiveRegs;
498 if (NeededState != ZAState::ANY)
499 Block.Insts.push_back({NeededState, InsertPt, PhysLiveRegs});
503 std::reverse(
Block.Insts.begin(),
Block.Insts.end());
507 if (!
Block.Insts.empty()) {
508 Block.DesiredIncomingState =
Block.Insts.front().NeededState;
509 Block.DesiredOutgoingState =
Block.Insts.back().NeededState;
513 return FunctionInfo{std::move(Blocks), AfterSMEProloguePt,
514 PhysLiveRegsAfterSMEPrologue};
520MachineSMEABI::assignBundleZAStates(
const EdgeBundles &Bundles,
521 const FunctionInfo &FnInfo) {
524 std::optional<ZAState> BundleState;
525 for (
unsigned BlockID : Bundles.
getBlocks(
I)) {
526 const BlockInfo &
Block = FnInfo.Blocks[BlockID];
530 if (
Block.FixedEntryState != ZAState::ANY ||
538 BundleState =
Block.DesiredIncomingState;
539 else if (BundleState !=
Block.DesiredIncomingState)
540 BundleState = ZAState::ACTIVE;
543 if (!BundleState || BundleState == ZAState::ANY)
544 BundleState = ZAState::ACTIVE;
546 BundleStates[
I] = *BundleState;
552std::pair<MachineBasicBlock::iterator, LiveRegs>
553MachineSMEABI::findStateChangeInsertionPoint(
558 if (Inst !=
Block.Insts.end()) {
559 InsertPt = Inst->InsertPt;
560 PhysLiveRegs = Inst->PhysLiveRegs;
562 InsertPt =
MBB.getFirstTerminator();
563 PhysLiveRegs =
Block.PhysLiveRegsAtExit;
566 if (PhysLiveRegs == LiveRegs::None)
567 return {InsertPt, PhysLiveRegs};
571 if (Inst ==
Block.Insts.begin()) {
572 PrevStateChangeI =
MBB.begin();
578 PrevStateChangeI = std::prev(Inst)->InsertPt;
583 setPhysLiveRegs(LiveUnits, PhysLiveRegs);
584 auto BestCandidate = std::make_pair(InsertPt, PhysLiveRegs);
587 if (
I->getOpcode() ==
TII->getCallFrameDestroyOpcode() ||
I->isCall())
590 LiveRegs CurrentPhysLiveRegs = getPhysLiveRegs(LiveUnits);
593 if (!(CurrentPhysLiveRegs & LiveRegs::NZCV))
594 BestCandidate = {
I, CurrentPhysLiveRegs};
595 if (CurrentPhysLiveRegs == LiveRegs::None)
598 return BestCandidate;
601void MachineSMEABI::insertStateChanges(EmitContext &Context,
602 const FunctionInfo &FnInfo,
606 const BlockInfo &
Block = FnInfo.Blocks[
MBB.getNumber()];
607 ZAState InState = BundleStates[Bundles.
getBundle(
MBB.getNumber(),
610 ZAState CurrentState =
Block.FixedEntryState;
611 if (CurrentState == ZAState::ANY)
612 CurrentState = InState;
614 for (
auto &Inst :
Block.Insts) {
615 if (CurrentState != Inst.NeededState) {
616 auto [InsertPt, PhysLiveRegs] =
617 findStateChangeInsertionPoint(
MBB,
Block, &Inst);
618 emitStateChange(Context,
MBB, InsertPt, CurrentState, Inst.NeededState,
620 CurrentState = Inst.NeededState;
624 if (
MBB.succ_empty())
629 if (CurrentState != OutState) {
630 auto [InsertPt, PhysLiveRegs] =
631 findStateChangeInsertionPoint(
MBB,
Block,
Block.Insts.end());
632 emitStateChange(Context,
MBB, InsertPt, CurrentState, OutState,
642 return MBBI !=
MBB.end() ?
MBBI->getDebugLoc() :
MBB.back().getDebugLoc();
652 unsigned Marker,
unsigned CallDestroyOpcode) {
653 auto IsMarker = [&](
auto &
MI) {
return MI.getOpcode() == Marker; };
654 auto MarkerInst = std::find_if(
MBBI,
MBB.end(), IsMarker);
655 if (MarkerInst ==
MBB.end())
658 while (++
I !=
MBB.end()) {
659 if (
I->isCall() ||
I->getOpcode() == CallDestroyOpcode)
662 if (
I !=
MBB.end() &&
I->isCall())
668void MachineSMEABI::collectReachableMarkedCalls(
672 assert(Marker == AArch64::InOutZAUsePseudo ||
673 Marker == AArch64::RequiresZASavePseudo ||
674 Marker == AArch64::RequiresZT0SavePseudo);
675 unsigned CallDestroyOpcode =
TII->getCallFrameDestroyOpcode();
676 if (findMarkedCall(StartMBB, StartInst, Calls, Marker, CallDestroyOpcode))
682 while (!Worklist.
empty()) {
688 if (!findMarkedCall(*
MBB,
MBB->begin(), Calls, Marker, CallDestroyOpcode))
712 StringRef StateName = Marker == AArch64::RequiresZT0SavePseudo ?
"ZT0" :
"ZA";
714 return SaveRemark(
DL,
MBB) << SaveName <<
" of " << StateName
715 <<
" emitted in '" << MF->
getName() <<
"'";
720 collectReachableMarkedCalls(
MBB,
MBBI, CallsRequiringSaves, Marker);
725 R <<
" to '" << CalleeName <<
"'";
726 R <<
" requires " << StateName <<
" save";
731void MachineSMEABI::emitSetupLazySave(EmitContext &Context,
736 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZASavePseudo,
737 "SMELazySaveZA",
"lazy save");
740 Register TPIDR2 =
MRI->createVirtualRegister(&AArch64::GPR64spRegClass);
741 Register TPIDR2Ptr =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
750 .
addImm(AArch64SysReg::TPIDR2_EL0)
754PhysRegSave MachineSMEABI::createPhysRegSave(
LiveRegs PhysLiveRegs,
758 PhysRegSave RegSave{PhysLiveRegs};
759 if (PhysLiveRegs & LiveRegs::NZCV) {
760 RegSave.StatusFlags =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
762 .
addImm(AArch64SysReg::NZCV)
767 if (PhysLiveRegs & LiveRegs::W0) {
768 RegSave.X0Save =
MRI->createVirtualRegister(PhysLiveRegs & LiveRegs::W0_HI
769 ? &AArch64::GPR64RegClass
770 : &AArch64::GPR32RegClass);
772 .
addReg(PhysLiveRegs & LiveRegs::W0_HI ? AArch64::X0 : AArch64::W0);
777void MachineSMEABI::restorePhyRegSave(
const PhysRegSave &RegSave,
781 if (RegSave.StatusFlags != AArch64::NoRegister)
783 .
addImm(AArch64SysReg::NZCV)
784 .
addReg(RegSave.StatusFlags)
787 if (RegSave.X0Save != AArch64::NoRegister)
789 RegSave.PhysLiveRegs & LiveRegs::W0_HI ? AArch64::X0 : AArch64::W0)
796 if (LCImpl == RTLIB::Unsupported)
797 emitError(
"cannot lower SME ABI (SME routines unsupported)");
800 if (CC != ExpectedCC)
801 emitError(
"invalid calling convention for SME routine: '" + ImplName +
"'");
807void MachineSMEABI::emitRestoreLazySave(EmitContext &Context,
812 Register TPIDR2EL0 =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
816 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
820 .
addImm(AArch64SVCR::SVCRZA)
824 .
addImm(AArch64SysReg::TPIDR2_EL0);
835 RestoreZA, RTLIB::SMEABI_TPIDR2_RESTORE,
839 .
addImm(AArch64SysReg::TPIDR2_EL0)
842 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
847 bool ClearTPIDR2,
bool On) {
852 .
addImm(AArch64SysReg::TPIDR2_EL0)
857 .
addImm(AArch64SVCR::SVCRZA)
861void MachineSMEABI::emitAllocateLazySaveBuffer(
866 Register SP =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
867 Register SVL =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
874 if (Buffer == AArch64::NoRegister) {
882 "Lazy ZA save is not yet supported on Windows");
883 Buffer =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
904 "TPIDR2 block initialization is not supported on big-endian targets");
926 Register TPIDR2EL0 =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
929 .
addImm(AArch64SysReg::TPIDR2_EL0);
938 CommitZASave, RTLIB::SMEABI_TPIDR2_SAVE,
946 .
addImm(AArch64SVCR::SVCRZA)
958void MachineSMEABI::emitFullZASaveRestore(EmitContext &Context,
961 LiveRegs PhysLiveRegs,
bool IsSave) {
965 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZASavePseudo,
966 "SMEFullZASave",
"full save");
968 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
973 .
addReg(Context.getAgnosticZABufferPtr(*MF));
980 IsSave ? RTLIB::SMEABI_SME_SAVE : RTLIB::SMEABI_SME_RESTORE,
983 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
986void MachineSMEABI::emitZT0SaveRestore(EmitContext &Context,
996 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZT0SavePseudo,
997 "SMEZT0Save",
"spill");
999 Register ZT0Save =
MRI->createVirtualRegister(&AArch64::GPR64spRegClass);
1016void MachineSMEABI::emitAllocateFullZASaveBuffer(
1024 Register BufferPtr = Context.getAgnosticZABufferPtr(*MF);
1025 Register BufferSize =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
1027 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
1034 SMEStateSize, RTLIB::SMEABI_SME_STATE_SIZE,
1054 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
1060 constexpr uint8_t to(ZAState To)
const {
1061 static_assert(NUM_ZA_STATE < 16,
"expected ZAState to fit in 4-bits");
1066constexpr FromState transitionFrom(ZAState From) {
return FromState{From}; }
1068void MachineSMEABI::emitStateChange(EmitContext &Context,
1071 ZAState From, ZAState To,
1074 if (From == ZAState::ANY || To == ZAState::ANY)
1079 if (From == ZAState::ENTRY && To == ZAState::OFF)
1084 if (From == ZAState::ENTRY) {
1086 "ENTRY state only valid in entry block");
1087 emitSMEPrologue(
MBB,
MBB.getFirstNonPHI());
1088 if (To == ZAState::ACTIVE)
1094 From = ZAState::ACTIVE;
1100 bool HasZAState = IsAgnosticZA || SMEFnAttrs.
hasZAState();
1102 switch (transitionFrom(From).to(To)) {
1104 case transitionFrom(ZAState::ACTIVE).to(ZAState::ACTIVE_ZT0_SAVED):
1105 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1107 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::ACTIVE):
1108 emitZT0SaveRestore(Context,
MBB, InsertPt,
false);
1112 case transitionFrom(ZAState::ACTIVE).to(ZAState::LOCAL_SAVED):
1113 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::LOCAL_SAVED):
1114 if (HasZT0State && From == ZAState::ACTIVE)
1115 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1117 emitZASave(Context,
MBB, InsertPt, PhysLiveRegs);
1121 case transitionFrom(ZAState::ACTIVE).to(ZAState::LOCAL_COMMITTED):
1124 assert(HasZT0State && !HasZAState &&
"Expect to only have ZT0 state.");
1125 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1126 emitZAMode(
MBB, InsertPt,
false,
false);
1130 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::OFF):
1131 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::LOCAL_SAVED):
1136 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::ACTIVE):
1137 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::ACTIVE_ZT0_SAVED):
1138 case transitionFrom(ZAState::LOCAL_SAVED).to(ZAState::ACTIVE):
1139 case transitionFrom(ZAState::LOCAL_SAVED).to(ZAState::ACTIVE_ZT0_SAVED):
1141 emitZARestore(Context,
MBB, InsertPt, PhysLiveRegs);
1143 emitZAMode(
MBB, InsertPt,
false,
true);
1144 if (HasZT0State && To == ZAState::ACTIVE)
1145 emitZT0SaveRestore(Context,
MBB, InsertPt,
false);
1149 case transitionFrom(ZAState::ACTIVE).to(ZAState::OFF):
1150 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::OFF):
1151 case transitionFrom(ZAState::LOCAL_SAVED).to(ZAState::OFF):
1153 "Did not expect to turn ZA off in shared/agnostic ZA function");
1154 emitZAMode(
MBB, InsertPt, From == ZAState::LOCAL_SAVED,
1159 dbgs() <<
"Error: Transition from " << getZAStateString(From) <<
" to "
1160 << getZAStateString(To) <<
'\n';
1172 if (!Subtarget->hasSME())
1176 SMEAttrs SMEFnAttrs = AFI->getSMEFnAttrs();
1177 if (!SMEFnAttrs.hasZAState() && !SMEFnAttrs.hasZT0State() &&
1178 !SMEFnAttrs.hasAgnosticZAInterface())
1181 assert(MF.getRegInfo().isSSA() &&
"Expected to be run on SSA form!");
1184 ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
1185 LLI = &getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
1186 *MF.getFunction().getParent(), *Subtarget);
1187 TII = Subtarget->getInstrInfo();
1188 TRI = Subtarget->getRegisterInfo();
1189 MRI = &MF.getRegInfo();
1192 getAnalysis<EdgeBundlesWrapperLegacy>().getEdgeBundles();
1194 FunctionInfo FnInfo = collectNeededZAStates(SMEFnAttrs);
1198 EmitContext Context;
1199 insertStateChanges(Context, FnInfo, Bundles, BundleStates);
1201 if (Context.needsSaveBuffer()) {
1202 if (FnInfo.AfterSMEProloguePt) {
1206 emitAllocateZASaveBuffer(Context, *
MBBI->getParent(),
MBBI,
1207 FnInfo.PhysLiveRegsAfterSMEPrologue);
1210 emitAllocateZASaveBuffer(
1212 FnInfo.Blocks[EntryBlock.
getNumber()].PhysLiveRegsAtEntry);
1220 return new MachineSMEABI(OptLevel);
unsigned const MachineRegisterInfo * MRI
static constexpr unsigned ZERO_ALL_ZA_MASK
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define ENTRY(ASMNAME, ENUM)
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
Register getEarlyAllocSMESaveBuffer() const
SMEAttrs getSMEFnAttrs() const
bool isTargetWindows() const
bool isLittleEndian() const
Represent the analysis usage information of a pass.
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class represents a function call, abstracting a target machine's calling convention.
ArrayRef< unsigned > getBlocks(unsigned Bundle) const
getBlocks - Return an array of blocks that are connected to Bundle.
unsigned getBundle(unsigned N, bool Out) const
getBundle - Return the ingoing (Out = false) or outgoing (Out = true) bundle number for basic block N
unsigned getNumBundles() const
getNumBundles - Return the total number of bundles in the CFG.
FunctionPass class - This class is used to implement most global optimizations.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
Tracks which library functions to use for a particular subtarget.
LLVM_ABI CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const
Get the CallingConv that should be used for the specified libcall.
LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void addReg(MCRegister Reg)
Adds register units covered by physical register Reg.
LLVM_ABI void stepBackward(const MachineInstr &MI)
Updates liveness when stepping backwards over the instruction MI.
LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
MachineInstrBundleIterator< const MachineInstr > const_iterator
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
succ_reverse_iterator succ_rbegin()
MachineInstrBundleIterator< MachineInstr > iterator
succ_reverse_iterator succ_rend()
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
LLVM_ABI int CreateVariableSizedObject(Align Alignment, const AllocaInst *Alloca)
Notify the MachineFrameInfo object that a variable sized object has been created.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasAgnosticZAInterface() const
bool hasPrivateZAInterface() const
bool hasSharedZAInterface() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
typename SuperClass::const_iterator const_iterator
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0
Preserve X0-X13, X19-X29, SP, Z0-Z31, P0-P15.
@ AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1
Preserve X1-X15, X19-X29, SP, Z0-Z31, P0-P15.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ LLVM_MARK_AS_BITMASK_ENUM
FunctionPass * createMachineSMEABIPass(CodeGenOptLevel)
LLVM_ABI char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
LLVM_ABI char & MachineLoopInfoID
MachineLoopInfo - This pass is a loop analysis pass.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
This struct is a compact representation of a valid (non-zero power of two) alignment.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.