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;
209static bool isLegalEdgeBundleZAState(ZAState State) {
211 case ZAState::ACTIVE:
212 case ZAState::ACTIVE_ZT0_SAVED:
213 case ZAState::LOCAL_SAVED:
214 case ZAState::LOCAL_COMMITTED:
221StringRef getZAStateString(ZAState State) {
222#define MAKE_CASE(V) \
244 return AArch64::MPR128RegClass.contains(SR) ||
245 AArch64::ZTRRegClass.contains(SR);
251static std::pair<ZAState, MachineBasicBlock::iterator>
261 if (
MI.getOpcode() == AArch64::InOutZAUsePseudo)
262 return {ZAState::ACTIVE, std::prev(InsertPt)};
265 if (
MI.getOpcode() == AArch64::RequiresZASavePseudo)
266 return {ZAState::LOCAL_SAVED, std::prev(InsertPt)};
275 if (
MI.getOpcode() == AArch64::RequiresZT0SavePseudo) {
276 return {SMEFnAttrs.
hasZAState() ? ZAState::ACTIVE_ZT0_SAVED
277 : ZAState::LOCAL_COMMITTED,
278 std::prev(InsertPt)};
283 return {ZAOffAtReturn ? ZAState::OFF : ZAState::ACTIVE, InsertPt};
286 for (
auto &MO :
MI.operands()) {
287 if (isZAorZTRegOp(
TRI, MO))
288 return {ZAState::ACTIVE, InsertPt};
291 return {ZAState::ANY, InsertPt};
295 inline static char ID = 0;
302 StringRef getPassName()
const override {
return "Machine SME ABI pass"; }
315 FunctionInfo collectNeededZAStates(
SMEAttrs SMEFnAttrs);
320 const FunctionInfo &FnInfo);
324 void insertStateChanges(EmitContext &,
const FunctionInfo &FnInfo,
331 void propagateDesiredStates(FunctionInfo &FnInfo,
bool Forwards =
true);
347 bool ClearTPIDR2,
bool On);
358 LiveRegs PhysLiveRegs,
bool IsSave);
366 std::pair<MachineBasicBlock::iterator, LiveRegs>
376 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
377 return emitFullZASaveRestore(Context,
MBB,
MBBI, PhysLiveRegs,
379 return emitSetupLazySave(Context,
MBB,
MBBI);
383 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
384 return emitFullZASaveRestore(Context,
MBB,
MBBI, PhysLiveRegs,
386 return emitRestoreLazySave(Context,
MBB,
MBBI, PhysLiveRegs);
391 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
392 return emitAllocateFullZASaveBuffer(Context,
MBB,
MBBI, PhysLiveRegs);
393 return emitAllocateLazySaveBuffer(Context,
MBB,
MBBI);
402 unsigned Marker)
const;
431 LiveRegs PhysLiveRegs = LiveRegs::None;
433 PhysLiveRegs |= LiveRegs::NZCV;
437 PhysLiveRegs |= LiveRegs::W0;
438 if (!LiveUnits.
available(AArch64::W0_HI))
439 PhysLiveRegs |= LiveRegs::W0_HI;
444 if (PhysLiveRegs & LiveRegs::NZCV)
445 LiveUnits.
addReg(AArch64::NZCV);
446 if (PhysLiveRegs & LiveRegs::W0)
447 LiveUnits.
addReg(AArch64::W0);
448 if (PhysLiveRegs & LiveRegs::W0_HI)
449 LiveUnits.
addReg(AArch64::W0_HI);
452[[maybe_unused]]
bool isCallStartOpcode(
unsigned Opc) {
454 case AArch64::TLSDESC_CALLSEQ:
455 case AArch64::TLSDESC_AUTH_CALLSEQ:
456 case AArch64::ADJCALLSTACKDOWN:
463FunctionInfo MachineSMEABI::collectNeededZAStates(
SMEAttrs SMEFnAttrs) {
466 "Expected function to have ZA/ZT0 state!");
469 LiveRegs PhysLiveRegsAfterSMEPrologue = LiveRegs::None;
470 std::optional<MachineBasicBlock::iterator> AfterSMEProloguePt;
473 BlockInfo &
Block = Blocks[
MBB.getNumber()];
475 if (
MBB.isEntryBlock()) {
477 Block.FixedEntryState = ZAState::ENTRY;
478 }
else if (
MBB.isEHPad()) {
480 Block.FixedEntryState = ZAState::LOCAL_COMMITTED;
486 Block.PhysLiveRegsAtExit = getPhysLiveRegs(LiveUnits);
487 auto FirstTerminatorInsertPt =
MBB.getFirstTerminator();
488 auto FirstNonPhiInsertPt =
MBB.getFirstNonPHI();
492 LiveRegs PhysLiveRegs = getPhysLiveRegs(LiveUnits);
497 if (
MI.getOpcode() == AArch64::SMEStateAllocPseudo) {
498 AfterSMEProloguePt =
MBBI;
499 PhysLiveRegsAfterSMEPrologue = PhysLiveRegs;
502 auto [NeededState, InsertPt] = getInstNeededZAState(*
TRI,
MI, SMEFnAttrs);
503 assert((InsertPt ==
MBBI || isCallStartOpcode(InsertPt->getOpcode())) &&
504 "Unexpected state change insertion point!");
506 if (
MBBI == FirstTerminatorInsertPt)
507 Block.PhysLiveRegsAtExit = PhysLiveRegs;
508 if (
MBBI == FirstNonPhiInsertPt)
509 Block.PhysLiveRegsAtEntry = PhysLiveRegs;
510 if (NeededState != ZAState::ANY)
511 Block.Insts.push_back({NeededState, InsertPt, PhysLiveRegs});
515 std::reverse(
Block.Insts.begin(),
Block.Insts.end());
519 if (!
Block.Insts.empty()) {
520 Block.DesiredIncomingState =
Block.Insts.front().NeededState;
521 Block.DesiredOutgoingState =
Block.Insts.back().NeededState;
525 return FunctionInfo{std::move(Blocks), AfterSMEProloguePt,
526 PhysLiveRegsAfterSMEPrologue};
529void MachineSMEABI::propagateDesiredStates(FunctionInfo &FnInfo,
534 auto GetBlockState = [](BlockInfo &
Block,
bool Incoming) -> ZAState & {
539 for (
auto [BlockID, BlockInfo] :
enumerate(FnInfo.Blocks)) {
540 if (!isLegalEdgeBundleZAState(GetBlockState(BlockInfo, Forwards)))
544 while (!Worklist.
empty()) {
546 BlockInfo &
Block = FnInfo.Blocks[
MBB->getNumber()];
550 int StateCounts[ZAState::NUM_ZA_STATE] = {0};
553 BlockInfo &PredOrSuccBlock = FnInfo.Blocks[PredOrSucc->getNumber()];
554 ZAState ZAState = GetBlockState(PredOrSuccBlock, !Forwards);
555 if (isLegalEdgeBundleZAState(ZAState))
556 StateCounts[ZAState]++;
559 ZAState PropagatedState = ZAState(
max_element(StateCounts) - StateCounts);
560 ZAState &CurrentState = GetBlockState(
Block, Forwards);
561 if (PropagatedState != CurrentState) {
562 CurrentState = PropagatedState;
563 ZAState &OtherState = GetBlockState(
Block, !Forwards);
565 if (OtherState == ZAState::ANY)
566 OtherState = PropagatedState;
571 BlockInfo &SuccOrPredBlock = FnInfo.Blocks[SuccOrPred->getNumber()];
572 if (!isLegalEdgeBundleZAState(GetBlockState(SuccOrPredBlock, Forwards)))
582MachineSMEABI::assignBundleZAStates(
const EdgeBundles &Bundles,
583 const FunctionInfo &FnInfo) {
586 LLVM_DEBUG(
dbgs() <<
"Assigning ZA state for edge bundle: " <<
I <<
'\n');
591 int EdgeStateCounts[ZAState::NUM_ZA_STATE] = {0};
592 for (
unsigned BlockID : Bundles.
getBlocks(
I)) {
595 const BlockInfo &
Block = FnInfo.Blocks[BlockID];
596 bool InEdge = Bundles.
getBundle(BlockID,
false) ==
I;
597 bool OutEdge = Bundles.
getBundle(BlockID,
true) ==
I;
600 InEdge && isLegalEdgeBundleZAState(
Block.DesiredIncomingState);
602 OutEdge && isLegalEdgeBundleZAState(
Block.DesiredOutgoingState);
605 << getZAStateString(
Block.DesiredIncomingState));
606 EdgeStateCounts[
Block.DesiredIncomingState]++;
610 << getZAStateString(
Block.DesiredOutgoingState));
611 EdgeStateCounts[
Block.DesiredOutgoingState]++;
613 if (!LegalInEdge && !LegalOutEgde)
618 ZAState BundleState =
619 ZAState(
max_element(EdgeStateCounts) - EdgeStateCounts);
621 if (BundleState == ZAState::ANY)
622 BundleState = ZAState::ACTIVE;
625 dbgs() <<
"Chosen ZA state: " << getZAStateString(BundleState) <<
'\n'
628 dbgs() <<
" " << getZAStateString(ZAState(State)) <<
": " <<
Count;
632 BundleStates[
I] = BundleState;
638std::pair<MachineBasicBlock::iterator, LiveRegs>
639MachineSMEABI::findStateChangeInsertionPoint(
644 if (Inst !=
Block.Insts.end()) {
645 InsertPt = Inst->InsertPt;
646 PhysLiveRegs = Inst->PhysLiveRegs;
648 InsertPt =
MBB.getFirstTerminator();
649 PhysLiveRegs =
Block.PhysLiveRegsAtExit;
652 if (PhysLiveRegs == LiveRegs::None)
653 return {InsertPt, PhysLiveRegs};
657 if (Inst ==
Block.Insts.begin()) {
658 PrevStateChangeI =
MBB.begin();
664 PrevStateChangeI = std::prev(Inst)->InsertPt;
669 setPhysLiveRegs(LiveUnits, PhysLiveRegs);
670 auto BestCandidate = std::make_pair(InsertPt, PhysLiveRegs);
673 if (
I->getOpcode() ==
TII->getCallFrameDestroyOpcode() ||
I->isCall())
676 LiveRegs CurrentPhysLiveRegs = getPhysLiveRegs(LiveUnits);
679 if (!(CurrentPhysLiveRegs & LiveRegs::NZCV))
680 BestCandidate = {
I, CurrentPhysLiveRegs};
681 if (CurrentPhysLiveRegs == LiveRegs::None)
684 return BestCandidate;
687void MachineSMEABI::insertStateChanges(EmitContext &Context,
688 const FunctionInfo &FnInfo,
692 const BlockInfo &
Block = FnInfo.Blocks[
MBB.getNumber()];
693 ZAState InState = BundleStates[Bundles.
getBundle(
MBB.getNumber(),
696 ZAState CurrentState =
Block.FixedEntryState;
697 if (CurrentState == ZAState::ANY)
698 CurrentState = InState;
700 for (
auto &Inst :
Block.Insts) {
701 if (CurrentState != Inst.NeededState) {
702 auto [InsertPt, PhysLiveRegs] =
703 findStateChangeInsertionPoint(
MBB,
Block, &Inst);
704 emitStateChange(Context,
MBB, InsertPt, CurrentState, Inst.NeededState,
706 CurrentState = Inst.NeededState;
710 if (
MBB.succ_empty())
715 if (CurrentState != OutState) {
716 auto [InsertPt, PhysLiveRegs] =
717 findStateChangeInsertionPoint(
MBB,
Block,
Block.Insts.end());
718 emitStateChange(Context,
MBB, InsertPt, CurrentState, OutState,
728 return MBBI !=
MBB.end() ?
MBBI->getDebugLoc() :
MBB.back().getDebugLoc();
738 unsigned Marker,
unsigned CallDestroyOpcode) {
739 auto IsMarker = [&](
auto &
MI) {
return MI.getOpcode() == Marker; };
740 auto MarkerInst = std::find_if(
MBBI,
MBB.end(), IsMarker);
741 if (MarkerInst ==
MBB.end())
744 while (++
I !=
MBB.end()) {
745 if (
I->isCall() ||
I->getOpcode() == CallDestroyOpcode)
748 if (
I !=
MBB.end() &&
I->isCall())
754void MachineSMEABI::collectReachableMarkedCalls(
758 assert(Marker == AArch64::InOutZAUsePseudo ||
759 Marker == AArch64::RequiresZASavePseudo ||
760 Marker == AArch64::RequiresZT0SavePseudo);
761 unsigned CallDestroyOpcode =
TII->getCallFrameDestroyOpcode();
762 if (findMarkedCall(StartMBB, StartInst, Calls, Marker, CallDestroyOpcode))
768 while (!Worklist.
empty()) {
774 if (!findMarkedCall(*
MBB,
MBB->begin(), Calls, Marker, CallDestroyOpcode))
798 StringRef StateName = Marker == AArch64::RequiresZT0SavePseudo ?
"ZT0" :
"ZA";
800 return SaveRemark(
DL,
MBB) << SaveName <<
" of " << StateName
801 <<
" emitted in '" << MF->
getName() <<
"'";
806 collectReachableMarkedCalls(
MBB,
MBBI, CallsRequiringSaves, Marker);
811 R <<
" to '" << CalleeName <<
"'";
812 R <<
" requires " << StateName <<
" save";
817void MachineSMEABI::emitSetupLazySave(EmitContext &Context,
822 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZASavePseudo,
823 "SMELazySaveZA",
"lazy save");
826 Register TPIDR2 =
MRI->createVirtualRegister(&AArch64::GPR64spRegClass);
827 Register TPIDR2Ptr =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
836 .
addImm(AArch64SysReg::TPIDR2_EL0)
840PhysRegSave MachineSMEABI::createPhysRegSave(
LiveRegs PhysLiveRegs,
844 PhysRegSave RegSave{PhysLiveRegs};
845 if (PhysLiveRegs & LiveRegs::NZCV) {
846 RegSave.StatusFlags =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
848 .
addImm(AArch64SysReg::NZCV)
853 if (PhysLiveRegs & LiveRegs::W0) {
854 RegSave.X0Save =
MRI->createVirtualRegister(PhysLiveRegs & LiveRegs::W0_HI
855 ? &AArch64::GPR64RegClass
856 : &AArch64::GPR32RegClass);
858 .
addReg(PhysLiveRegs & LiveRegs::W0_HI ? AArch64::X0 : AArch64::W0);
863void MachineSMEABI::restorePhyRegSave(
const PhysRegSave &RegSave,
867 if (RegSave.StatusFlags != AArch64::NoRegister)
869 .
addImm(AArch64SysReg::NZCV)
870 .
addReg(RegSave.StatusFlags)
873 if (RegSave.X0Save != AArch64::NoRegister)
875 RegSave.PhysLiveRegs & LiveRegs::W0_HI ? AArch64::X0 : AArch64::W0)
879void MachineSMEABI::emitRestoreLazySave(EmitContext &Context,
885 Register TPIDR2EL0 =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
889 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
893 .
addImm(AArch64SVCR::SVCRZA)
897 .
addImm(AArch64SysReg::TPIDR2_EL0);
908 .
addRegMask(
TRI->SMEABISupportRoutinesCallPreservedMaskFromX0());
911 .
addImm(AArch64SysReg::TPIDR2_EL0)
914 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
919 bool ClearTPIDR2,
bool On) {
924 .
addImm(AArch64SysReg::TPIDR2_EL0)
929 .
addImm(AArch64SVCR::SVCRZA)
933void MachineSMEABI::emitAllocateLazySaveBuffer(
938 Register SP =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
939 Register SVL =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
946 if (Buffer == AArch64::NoRegister) {
954 "Lazy ZA save is not yet supported on Windows");
955 Buffer =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
976 "TPIDR2 block initialization is not supported on big-endian targets");
999 Register TPIDR2EL0 =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
1002 .
addImm(AArch64SysReg::TPIDR2_EL0);
1011 .
addRegMask(
TRI->SMEABISupportRoutinesCallPreservedMaskFromX0());
1018 .
addImm(AArch64SVCR::SVCRZA)
1030void MachineSMEABI::emitFullZASaveRestore(EmitContext &Context,
1033 LiveRegs PhysLiveRegs,
bool IsSave) {
1039 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZASavePseudo,
1040 "SMEFullZASave",
"full save");
1042 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
1047 .
addReg(Context.getAgnosticZABufferPtr(*MF));
1053 IsSave ? RTLIB::SMEABI_SME_SAVE : RTLIB::SMEABI_SME_RESTORE))
1058 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
1061void MachineSMEABI::emitZT0SaveRestore(EmitContext &Context,
1071 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZT0SavePseudo,
1072 "SMEZT0Save",
"spill");
1074 Register ZT0Save =
MRI->createVirtualRegister(&AArch64::GPR64spRegClass);
1091void MachineSMEABI::emitAllocateFullZASaveBuffer(
1099 Register BufferPtr = Context.getAgnosticZABufferPtr(*MF);
1100 Register BufferSize =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
1102 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
1132 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
1138 constexpr uint8_t to(ZAState To)
const {
1139 static_assert(NUM_ZA_STATE < 16,
"expected ZAState to fit in 4-bits");
1144constexpr FromState transitionFrom(ZAState From) {
return FromState{From}; }
1146void MachineSMEABI::emitStateChange(EmitContext &Context,
1149 ZAState From, ZAState To,
1152 if (From == ZAState::ANY || To == ZAState::ANY)
1157 if (From == ZAState::ENTRY && To == ZAState::OFF)
1162 if (From == ZAState::ENTRY) {
1164 "ENTRY state only valid in entry block");
1165 emitSMEPrologue(
MBB,
MBB.getFirstNonPHI());
1166 if (To == ZAState::ACTIVE)
1172 From = ZAState::ACTIVE;
1178 bool HasZAState = IsAgnosticZA || SMEFnAttrs.
hasZAState();
1180 switch (transitionFrom(From).to(To)) {
1182 case transitionFrom(ZAState::ACTIVE).to(ZAState::ACTIVE_ZT0_SAVED):
1183 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1185 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::ACTIVE):
1186 emitZT0SaveRestore(Context,
MBB, InsertPt,
false);
1190 case transitionFrom(ZAState::ACTIVE).to(ZAState::LOCAL_SAVED):
1191 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::LOCAL_SAVED):
1192 if (HasZT0State && From == ZAState::ACTIVE)
1193 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1195 emitZASave(Context,
MBB, InsertPt, PhysLiveRegs);
1199 case transitionFrom(ZAState::ACTIVE).to(ZAState::LOCAL_COMMITTED):
1202 assert(HasZT0State && !HasZAState &&
"Expect to only have ZT0 state.");
1203 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1204 emitZAMode(
MBB, InsertPt,
false,
false);
1208 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::OFF):
1209 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::LOCAL_SAVED):
1214 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::ACTIVE):
1215 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::ACTIVE_ZT0_SAVED):
1216 case transitionFrom(ZAState::LOCAL_SAVED).to(ZAState::ACTIVE):
1218 emitZARestore(Context,
MBB, InsertPt, PhysLiveRegs);
1220 emitZAMode(
MBB, InsertPt,
false,
true);
1221 if (HasZT0State && To == ZAState::ACTIVE)
1222 emitZT0SaveRestore(Context,
MBB, InsertPt,
false);
1226 case transitionFrom(ZAState::ACTIVE).to(ZAState::OFF):
1227 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::OFF):
1228 case transitionFrom(ZAState::LOCAL_SAVED).to(ZAState::OFF):
1230 "Did not expect to turn ZA off in shared/agnostic ZA function");
1231 emitZAMode(
MBB, InsertPt, From == ZAState::LOCAL_SAVED,
1236 dbgs() <<
"Error: Transition from " << getZAStateString(From) <<
" to "
1237 << getZAStateString(To) <<
'\n';
1252 SMEAttrs SMEFnAttrs = AFI->getSMEFnAttrs();
1253 if (!SMEFnAttrs.hasZAState() && !SMEFnAttrs.hasZT0State() &&
1254 !SMEFnAttrs.hasAgnosticZAInterface())
1257 assert(MF.getRegInfo().isSSA() &&
"Expected to be run on SSA form!");
1261 ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
1262 TII = Subtarget->getInstrInfo();
1263 TRI = Subtarget->getRegisterInfo();
1264 MRI = &MF.getRegInfo();
1267 getAnalysis<EdgeBundlesWrapperLegacy>().getEdgeBundles();
1269 FunctionInfo FnInfo = collectNeededZAStates(SMEFnAttrs);
1303 for (
bool Forwards : {
true,
false})
1304 propagateDesiredStates(FnInfo, Forwards);
1309 EmitContext Context;
1310 insertStateChanges(Context, FnInfo, Bundles, BundleStates);
1312 if (Context.needsSaveBuffer()) {
1313 if (FnInfo.AfterSMEProloguePt) {
1317 emitAllocateZASaveBuffer(Context, *
MBBI->getParent(),
MBBI,
1318 FnInfo.PhysLiveRegsAfterSMEPrologue);
1321 emitAllocateZASaveBuffer(
1323 FnInfo.Blocks[EntryBlock.
getNumber()].PhysLiveRegsAtEntry);
1331 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
const AArch64RegisterInfo * getRegisterInfo() const override
const AArch64TargetLowering * getTargetLowering() const override
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.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
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.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
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 & 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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, 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.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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...
CallingConv Namespace - This namespace contains an enum with a value for the well-known calling conve...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1
Preserve X1-X15, X19-X29, SP, Z0-Z31, P0-P15.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
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.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
auto successors(const MachineBasicBlock *BB)
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.
FunctionAddr VTableAddr Count
CodeGenOptLevel
Code generation optimization level.
@ LLVM_MARK_AS_BITMASK_ENUM
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
auto predecessors(const MachineBasicBlock *BB)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...