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"; }
316 FunctionInfo collectNeededZAStates(
SMEAttrs SMEFnAttrs);
321 const FunctionInfo &FnInfo);
325 void insertStateChanges(EmitContext &,
const FunctionInfo &FnInfo,
332 void propagateDesiredStates(FunctionInfo &FnInfo,
bool Forwards =
true);
351 bool ClearTPIDR2,
bool On);
362 LiveRegs PhysLiveRegs,
bool IsSave);
370 std::pair<MachineBasicBlock::iterator, LiveRegs>
380 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
381 return emitFullZASaveRestore(Context,
MBB,
MBBI, PhysLiveRegs,
383 return emitSetupLazySave(Context,
MBB,
MBBI);
387 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
388 return emitFullZASaveRestore(Context,
MBB,
MBBI, PhysLiveRegs,
390 return emitRestoreLazySave(Context,
MBB,
MBBI, PhysLiveRegs);
395 if (AFI->getSMEFnAttrs().hasAgnosticZAInterface())
396 return emitAllocateFullZASaveBuffer(Context,
MBB,
MBBI, PhysLiveRegs);
397 return emitAllocateLazySaveBuffer(Context,
MBB,
MBBI);
406 unsigned Marker)
const;
413 void emitError(
const Twine &Message) {
441 LiveRegs PhysLiveRegs = LiveRegs::None;
443 PhysLiveRegs |= LiveRegs::NZCV;
447 PhysLiveRegs |= LiveRegs::W0;
448 if (!LiveUnits.
available(AArch64::W0_HI))
449 PhysLiveRegs |= LiveRegs::W0_HI;
454 if (PhysLiveRegs & LiveRegs::NZCV)
455 LiveUnits.
addReg(AArch64::NZCV);
456 if (PhysLiveRegs & LiveRegs::W0)
457 LiveUnits.
addReg(AArch64::W0);
458 if (PhysLiveRegs & LiveRegs::W0_HI)
459 LiveUnits.
addReg(AArch64::W0_HI);
462[[maybe_unused]]
bool isCallStartOpcode(
unsigned Opc) {
464 case AArch64::TLSDESC_CALLSEQ:
465 case AArch64::TLSDESC_AUTH_CALLSEQ:
466 case AArch64::ADJCALLSTACKDOWN:
473FunctionInfo MachineSMEABI::collectNeededZAStates(
SMEAttrs SMEFnAttrs) {
476 "Expected function to have ZA/ZT0 state!");
479 LiveRegs PhysLiveRegsAfterSMEPrologue = LiveRegs::None;
480 std::optional<MachineBasicBlock::iterator> AfterSMEProloguePt;
483 BlockInfo &
Block = Blocks[
MBB.getNumber()];
485 if (
MBB.isEntryBlock()) {
487 Block.FixedEntryState = ZAState::ENTRY;
488 }
else if (
MBB.isEHPad()) {
490 Block.FixedEntryState = ZAState::LOCAL_COMMITTED;
496 Block.PhysLiveRegsAtExit = getPhysLiveRegs(LiveUnits);
497 auto FirstTerminatorInsertPt =
MBB.getFirstTerminator();
498 auto FirstNonPhiInsertPt =
MBB.getFirstNonPHI();
502 LiveRegs PhysLiveRegs = getPhysLiveRegs(LiveUnits);
507 if (
MI.getOpcode() == AArch64::SMEStateAllocPseudo) {
508 AfterSMEProloguePt =
MBBI;
509 PhysLiveRegsAfterSMEPrologue = PhysLiveRegs;
512 auto [NeededState, InsertPt] = getInstNeededZAState(*
TRI,
MI, SMEFnAttrs);
513 assert((InsertPt ==
MBBI || isCallStartOpcode(InsertPt->getOpcode())) &&
514 "Unexpected state change insertion point!");
516 if (
MBBI == FirstTerminatorInsertPt)
517 Block.PhysLiveRegsAtExit = PhysLiveRegs;
518 if (
MBBI == FirstNonPhiInsertPt)
519 Block.PhysLiveRegsAtEntry = PhysLiveRegs;
520 if (NeededState != ZAState::ANY)
521 Block.Insts.push_back({NeededState, InsertPt, PhysLiveRegs});
525 std::reverse(
Block.Insts.begin(),
Block.Insts.end());
529 if (!
Block.Insts.empty()) {
530 Block.DesiredIncomingState =
Block.Insts.front().NeededState;
531 Block.DesiredOutgoingState =
Block.Insts.back().NeededState;
535 return FunctionInfo{std::move(Blocks), AfterSMEProloguePt,
536 PhysLiveRegsAfterSMEPrologue};
539void MachineSMEABI::propagateDesiredStates(FunctionInfo &FnInfo,
544 auto GetBlockState = [](BlockInfo &
Block,
bool Incoming) -> ZAState & {
549 for (
auto [BlockID, BlockInfo] :
enumerate(FnInfo.Blocks)) {
550 if (!isLegalEdgeBundleZAState(GetBlockState(BlockInfo, Forwards)))
554 while (!Worklist.
empty()) {
556 BlockInfo &
Block = FnInfo.Blocks[
MBB->getNumber()];
560 int StateCounts[ZAState::NUM_ZA_STATE] = {0};
563 BlockInfo &PredOrSuccBlock = FnInfo.Blocks[PredOrSucc->getNumber()];
564 ZAState ZAState = GetBlockState(PredOrSuccBlock, !Forwards);
565 if (isLegalEdgeBundleZAState(ZAState))
566 StateCounts[ZAState]++;
569 ZAState PropagatedState = ZAState(
max_element(StateCounts) - StateCounts);
570 ZAState &CurrentState = GetBlockState(
Block, Forwards);
571 if (PropagatedState != CurrentState) {
572 CurrentState = PropagatedState;
573 ZAState &OtherState = GetBlockState(
Block, !Forwards);
575 if (OtherState == ZAState::ANY)
576 OtherState = PropagatedState;
581 BlockInfo &SuccOrPredBlock = FnInfo.Blocks[SuccOrPred->getNumber()];
582 if (!isLegalEdgeBundleZAState(GetBlockState(SuccOrPredBlock, Forwards)))
592MachineSMEABI::assignBundleZAStates(
const EdgeBundles &Bundles,
593 const FunctionInfo &FnInfo) {
596 LLVM_DEBUG(
dbgs() <<
"Assigning ZA state for edge bundle: " <<
I <<
'\n');
601 int EdgeStateCounts[ZAState::NUM_ZA_STATE] = {0};
602 for (
unsigned BlockID : Bundles.
getBlocks(
I)) {
605 const BlockInfo &
Block = FnInfo.Blocks[BlockID];
606 bool InEdge = Bundles.
getBundle(BlockID,
false) ==
I;
607 bool OutEdge = Bundles.
getBundle(BlockID,
true) ==
I;
610 InEdge && isLegalEdgeBundleZAState(
Block.DesiredIncomingState);
612 OutEdge && isLegalEdgeBundleZAState(
Block.DesiredOutgoingState);
615 << getZAStateString(
Block.DesiredIncomingState));
616 EdgeStateCounts[
Block.DesiredIncomingState]++;
620 << getZAStateString(
Block.DesiredOutgoingState));
621 EdgeStateCounts[
Block.DesiredOutgoingState]++;
623 if (!LegalInEdge && !LegalOutEgde)
628 ZAState BundleState =
629 ZAState(
max_element(EdgeStateCounts) - EdgeStateCounts);
631 if (BundleState == ZAState::ANY)
632 BundleState = ZAState::ACTIVE;
635 dbgs() <<
"Chosen ZA state: " << getZAStateString(BundleState) <<
'\n'
638 dbgs() <<
" " << getZAStateString(ZAState(State)) <<
": " <<
Count;
642 BundleStates[
I] = BundleState;
648std::pair<MachineBasicBlock::iterator, LiveRegs>
649MachineSMEABI::findStateChangeInsertionPoint(
654 if (Inst !=
Block.Insts.end()) {
655 InsertPt = Inst->InsertPt;
656 PhysLiveRegs = Inst->PhysLiveRegs;
658 InsertPt =
MBB.getFirstTerminator();
659 PhysLiveRegs =
Block.PhysLiveRegsAtExit;
662 if (PhysLiveRegs == LiveRegs::None)
663 return {InsertPt, PhysLiveRegs};
667 if (Inst ==
Block.Insts.begin()) {
668 PrevStateChangeI =
MBB.begin();
674 PrevStateChangeI = std::prev(Inst)->InsertPt;
679 setPhysLiveRegs(LiveUnits, PhysLiveRegs);
680 auto BestCandidate = std::make_pair(InsertPt, PhysLiveRegs);
683 if (
I->getOpcode() ==
TII->getCallFrameDestroyOpcode() ||
I->isCall())
686 LiveRegs CurrentPhysLiveRegs = getPhysLiveRegs(LiveUnits);
689 if (!(CurrentPhysLiveRegs & LiveRegs::NZCV))
690 BestCandidate = {
I, CurrentPhysLiveRegs};
691 if (CurrentPhysLiveRegs == LiveRegs::None)
694 return BestCandidate;
697void MachineSMEABI::insertStateChanges(EmitContext &Context,
698 const FunctionInfo &FnInfo,
702 const BlockInfo &
Block = FnInfo.Blocks[
MBB.getNumber()];
703 ZAState InState = BundleStates[Bundles.
getBundle(
MBB.getNumber(),
706 ZAState CurrentState =
Block.FixedEntryState;
707 if (CurrentState == ZAState::ANY)
708 CurrentState = InState;
710 for (
auto &Inst :
Block.Insts) {
711 if (CurrentState != Inst.NeededState) {
712 auto [InsertPt, PhysLiveRegs] =
713 findStateChangeInsertionPoint(
MBB,
Block, &Inst);
714 emitStateChange(Context,
MBB, InsertPt, CurrentState, Inst.NeededState,
716 CurrentState = Inst.NeededState;
720 if (
MBB.succ_empty())
725 if (CurrentState != OutState) {
726 auto [InsertPt, PhysLiveRegs] =
727 findStateChangeInsertionPoint(
MBB,
Block,
Block.Insts.end());
728 emitStateChange(Context,
MBB, InsertPt, CurrentState, OutState,
738 return MBBI !=
MBB.end() ?
MBBI->getDebugLoc() :
MBB.back().getDebugLoc();
748 unsigned Marker,
unsigned CallDestroyOpcode) {
749 auto IsMarker = [&](
auto &
MI) {
return MI.getOpcode() == Marker; };
750 auto MarkerInst = std::find_if(
MBBI,
MBB.end(), IsMarker);
751 if (MarkerInst ==
MBB.end())
754 while (++
I !=
MBB.end()) {
755 if (
I->isCall() ||
I->getOpcode() == CallDestroyOpcode)
758 if (
I !=
MBB.end() &&
I->isCall())
764void MachineSMEABI::collectReachableMarkedCalls(
768 assert(Marker == AArch64::InOutZAUsePseudo ||
769 Marker == AArch64::RequiresZASavePseudo ||
770 Marker == AArch64::RequiresZT0SavePseudo);
771 unsigned CallDestroyOpcode =
TII->getCallFrameDestroyOpcode();
772 if (findMarkedCall(StartMBB, StartInst, Calls, Marker, CallDestroyOpcode))
778 while (!Worklist.
empty()) {
784 if (!findMarkedCall(*
MBB,
MBB->begin(), Calls, Marker, CallDestroyOpcode))
808 StringRef StateName = Marker == AArch64::RequiresZT0SavePseudo ?
"ZT0" :
"ZA";
810 return SaveRemark(
DL,
MBB) << SaveName <<
" of " << StateName
811 <<
" emitted in '" << MF->
getName() <<
"'";
816 collectReachableMarkedCalls(
MBB,
MBBI, CallsRequiringSaves, Marker);
821 R <<
" to '" << CalleeName <<
"'";
822 R <<
" requires " << StateName <<
" save";
827void MachineSMEABI::emitSetupLazySave(EmitContext &Context,
832 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZASavePseudo,
833 "SMELazySaveZA",
"lazy save");
836 Register TPIDR2 =
MRI->createVirtualRegister(&AArch64::GPR64spRegClass);
837 Register TPIDR2Ptr =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
846 .
addImm(AArch64SysReg::TPIDR2_EL0)
850PhysRegSave MachineSMEABI::createPhysRegSave(
LiveRegs PhysLiveRegs,
854 PhysRegSave RegSave{PhysLiveRegs};
855 if (PhysLiveRegs & LiveRegs::NZCV) {
856 RegSave.StatusFlags =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
858 .
addImm(AArch64SysReg::NZCV)
863 if (PhysLiveRegs & LiveRegs::W0) {
864 RegSave.X0Save =
MRI->createVirtualRegister(PhysLiveRegs & LiveRegs::W0_HI
865 ? &AArch64::GPR64RegClass
866 : &AArch64::GPR32RegClass);
868 .
addReg(PhysLiveRegs & LiveRegs::W0_HI ? AArch64::X0 : AArch64::W0);
873void MachineSMEABI::restorePhyRegSave(
const PhysRegSave &RegSave,
877 if (RegSave.StatusFlags != AArch64::NoRegister)
879 .
addImm(AArch64SysReg::NZCV)
880 .
addReg(RegSave.StatusFlags)
883 if (RegSave.X0Save != AArch64::NoRegister)
885 RegSave.PhysLiveRegs & LiveRegs::W0_HI ? AArch64::X0 : AArch64::W0)
892 if (LCImpl == RTLIB::Unsupported)
893 emitError(
"cannot lower SME ABI (SME routines unsupported)");
896 if (CC != ExpectedCC)
897 emitError(
"invalid calling convention for SME routine: '" + ImplName +
"'");
903void MachineSMEABI::emitRestoreLazySave(EmitContext &Context,
908 Register TPIDR2EL0 =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
912 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
916 .
addImm(AArch64SVCR::SVCRZA)
920 .
addImm(AArch64SysReg::TPIDR2_EL0);
931 RestoreZA, RTLIB::SMEABI_TPIDR2_RESTORE,
935 .
addImm(AArch64SysReg::TPIDR2_EL0)
938 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
943 bool ClearTPIDR2,
bool On) {
948 .
addImm(AArch64SysReg::TPIDR2_EL0)
953 .
addImm(AArch64SVCR::SVCRZA)
957void MachineSMEABI::emitAllocateLazySaveBuffer(
962 Register SP =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
963 Register SVL =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
970 if (Buffer == AArch64::NoRegister) {
978 "Lazy ZA save is not yet supported on Windows");
979 Buffer =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
1000 "TPIDR2 block initialization is not supported on big-endian targets");
1022 Register TPIDR2EL0 =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
1025 .
addImm(AArch64SysReg::TPIDR2_EL0);
1034 CommitZASave, RTLIB::SMEABI_TPIDR2_SAVE,
1042 .
addImm(AArch64SVCR::SVCRZA)
1054void MachineSMEABI::emitFullZASaveRestore(EmitContext &Context,
1057 LiveRegs PhysLiveRegs,
bool IsSave) {
1061 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZASavePseudo,
1062 "SMEFullZASave",
"full save");
1064 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
1069 .
addReg(Context.getAgnosticZABufferPtr(*MF));
1076 IsSave ? RTLIB::SMEABI_SME_SAVE : RTLIB::SMEABI_SME_RESTORE,
1079 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
1082void MachineSMEABI::emitZT0SaveRestore(EmitContext &Context,
1092 emitCallSaveRemarks(
MBB,
MBBI,
DL, AArch64::RequiresZT0SavePseudo,
1093 "SMEZT0Save",
"spill");
1095 Register ZT0Save =
MRI->createVirtualRegister(&AArch64::GPR64spRegClass);
1112void MachineSMEABI::emitAllocateFullZASaveBuffer(
1120 Register BufferPtr = Context.getAgnosticZABufferPtr(*MF);
1121 Register BufferSize =
MRI->createVirtualRegister(&AArch64::GPR64RegClass);
1123 PhysRegSave RegSave = createPhysRegSave(PhysLiveRegs,
MBB,
MBBI,
DL);
1130 SMEStateSize, RTLIB::SMEABI_SME_STATE_SIZE,
1150 restorePhyRegSave(RegSave,
MBB,
MBBI,
DL);
1156 constexpr uint8_t to(ZAState To)
const {
1157 static_assert(NUM_ZA_STATE < 16,
"expected ZAState to fit in 4-bits");
1162constexpr FromState transitionFrom(ZAState From) {
return FromState{From}; }
1164void MachineSMEABI::emitStateChange(EmitContext &Context,
1167 ZAState From, ZAState To,
1170 if (From == ZAState::ANY || To == ZAState::ANY)
1175 if (From == ZAState::ENTRY && To == ZAState::OFF)
1180 if (From == ZAState::ENTRY) {
1182 "ENTRY state only valid in entry block");
1183 emitSMEPrologue(
MBB,
MBB.getFirstNonPHI());
1184 if (To == ZAState::ACTIVE)
1190 From = ZAState::ACTIVE;
1196 bool HasZAState = IsAgnosticZA || SMEFnAttrs.
hasZAState();
1198 switch (transitionFrom(From).to(To)) {
1200 case transitionFrom(ZAState::ACTIVE).to(ZAState::ACTIVE_ZT0_SAVED):
1201 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1203 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::ACTIVE):
1204 emitZT0SaveRestore(Context,
MBB, InsertPt,
false);
1208 case transitionFrom(ZAState::ACTIVE).to(ZAState::LOCAL_SAVED):
1209 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::LOCAL_SAVED):
1210 if (HasZT0State && From == ZAState::ACTIVE)
1211 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1213 emitZASave(Context,
MBB, InsertPt, PhysLiveRegs);
1217 case transitionFrom(ZAState::ACTIVE).to(ZAState::LOCAL_COMMITTED):
1220 assert(HasZT0State && !HasZAState &&
"Expect to only have ZT0 state.");
1221 emitZT0SaveRestore(Context,
MBB, InsertPt,
true);
1222 emitZAMode(
MBB, InsertPt,
false,
false);
1226 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::OFF):
1227 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::LOCAL_SAVED):
1232 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::ACTIVE):
1233 case transitionFrom(ZAState::LOCAL_COMMITTED).to(ZAState::ACTIVE_ZT0_SAVED):
1234 case transitionFrom(ZAState::LOCAL_SAVED).to(ZAState::ACTIVE):
1236 emitZARestore(Context,
MBB, InsertPt, PhysLiveRegs);
1238 emitZAMode(
MBB, InsertPt,
false,
true);
1239 if (HasZT0State && To == ZAState::ACTIVE)
1240 emitZT0SaveRestore(Context,
MBB, InsertPt,
false);
1244 case transitionFrom(ZAState::ACTIVE).to(ZAState::OFF):
1245 case transitionFrom(ZAState::ACTIVE_ZT0_SAVED).to(ZAState::OFF):
1246 case transitionFrom(ZAState::LOCAL_SAVED).to(ZAState::OFF):
1248 "Did not expect to turn ZA off in shared/agnostic ZA function");
1249 emitZAMode(
MBB, InsertPt, From == ZAState::LOCAL_SAVED,
1254 dbgs() <<
"Error: Transition from " << getZAStateString(From) <<
" to "
1255 << getZAStateString(To) <<
'\n';
1267 if (!Subtarget->hasSME())
1271 SMEAttrs SMEFnAttrs = AFI->getSMEFnAttrs();
1272 if (!SMEFnAttrs.hasZAState() && !SMEFnAttrs.hasZT0State() &&
1273 !SMEFnAttrs.hasAgnosticZAInterface())
1276 assert(MF.getRegInfo().isSSA() &&
"Expected to be run on SSA form!");
1279 ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
1280 LLI = &getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
1281 *MF.getFunction().getParent(), *Subtarget);
1282 TII = Subtarget->getInstrInfo();
1283 TRI = Subtarget->getRegisterInfo();
1284 MRI = &MF.getRegInfo();
1287 getAnalysis<EdgeBundlesWrapperLegacy>().getEdgeBundles();
1289 FunctionInfo FnInfo = collectNeededZAStates(SMEFnAttrs);
1323 for (
bool Forwards : {
true,
false})
1324 propagateDesiredStates(FnInfo, Forwards);
1329 EmitContext Context;
1330 insertStateChanges(Context, FnInfo, Bundles, BundleStates);
1332 if (Context.needsSaveBuffer()) {
1333 if (FnInfo.AfterSMEProloguePt) {
1337 emitAllocateZASaveBuffer(Context, *
MBBI->getParent(),
MBBI,
1338 FnInfo.PhysLiveRegsAfterSMEPrologue);
1341 emitAllocateZASaveBuffer(
1343 FnInfo.Blocks[EntryBlock.
getNumber()].PhysLiveRegsAtEntry);
1351 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.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
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
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.
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...
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.