diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index e9ccc35f34612..0d019bda36130 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -3273,6 +3273,32 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { -MI->getOperand(2).getImm()); return; + case AArch64::SEH_AllocZ: + assert(MI->getOperand(0).getImm() >= 0 && + "AllocZ SEH opcode offset must be non-negative"); + assert(MI->getOperand(0).getImm() <= 255 && + "AllocZ SEH opcode offset must fit into 8 bits"); + TS->emitARM64WinCFIAllocZ(MI->getOperand(0).getImm()); + return; + + case AArch64::SEH_SaveZReg: + assert(MI->getOperand(1).getImm() >= 0 && + "SaveZReg SEH opcode offset must be non-negative"); + assert(MI->getOperand(1).getImm() <= 255 && + "SaveZReg SEH opcode offset must fit into 8 bits"); + TS->emitARM64WinCFISaveZReg(MI->getOperand(0).getImm(), + MI->getOperand(1).getImm()); + return; + + case AArch64::SEH_SavePReg: + assert(MI->getOperand(1).getImm() >= 0 && + "SavePReg SEH opcode offset must be non-negative"); + assert(MI->getOperand(1).getImm() <= 255 && + "SavePReg SEH opcode offset must fit into 8 bits"); + TS->emitARM64WinCFISavePReg(MI->getOperand(0).getImm(), + MI->getOperand(1).getImm()); + return; + case AArch64::BLR: case AArch64::BR: { recordIfImportCall(MI); diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.td b/llvm/lib/Target/AArch64/AArch64CallingConvention.td index 7cca6d9bc6b9c..920cc67273146 100644 --- a/llvm/lib/Target/AArch64/AArch64CallingConvention.td +++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.td @@ -606,6 +606,9 @@ def CSR_Win_AArch64_Arm64EC_Thunk : CalleeSavedRegs<(add (sequence "Q%u", 6, 15) def CSR_AArch64_AAVPCS : CalleeSavedRegs<(add X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, LR, FP, (sequence "Q%u", 8, 23))>; +def CSR_Win_AArch64_AAVPCS : CalleeSavedRegs<(add X19, X20, X21, X22, X23, X24, + X25, X26, X27, X28, FP, LR, + (sequence "Q%u", 8, 23))>; // Functions taking SVE arguments or returning an SVE type // must (additionally) preserve full Z8-Z23 and predicate registers P4-P15 @@ -619,6 +622,11 @@ def CSR_Darwin_AArch64_SVE_AAPCS : CalleeSavedRegs<(add (sequence "Z%u", 8, 23), LR, FP, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28)>; +def CSR_Win_AArch64_SVE_AAPCS : CalleeSavedRegs<(add (sequence "P%u", 4, 15), + (sequence "Z%u", 8, 23), + X19, X20, X21, X22, X23, X24, + X25, X26, X27, X28, FP, LR)>; + // SME ABI support routines such as __arm_tpidr2_save/restore preserve most registers. def CSR_AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0 : CalleeSavedRegs<(add (sequence "Z%u", 0, 31), diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 0f33e77d4eecc..4f048fb90852e 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -44,6 +44,10 @@ // | | // |-----------------------------------| // | | +// | (Win64 only) callee-saved SVE reg | +// | | +// |-----------------------------------| +// | | // | callee-saved gpr registers | <--. // | | | On Darwin platforms these // |- - - - - - - - - - - - - - - - - -| | callee saves are swapped, @@ -1200,7 +1204,25 @@ static MachineBasicBlock::iterator InsertSEH(MachineBasicBlock::iterator MBBI, switch (Opc) { default: - llvm_unreachable("No SEH Opcode for this instruction"); + report_fatal_error("No SEH Opcode for this instruction"); + case AArch64::STR_ZXI: + case AArch64::LDR_ZXI: { + unsigned Reg0 = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg()); + MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveZReg)) + .addImm(Reg0) + .addImm(Imm) + .setMIFlag(Flag); + break; + } + case AArch64::STR_PXI: + case AArch64::LDR_PXI: { + unsigned Reg0 = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg()); + MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SavePReg)) + .addImm(Reg0) + .addImm(Imm) + .setMIFlag(Flag); + break; + } case AArch64::LDPDpost: Imm = -Imm; [[fallthrough]]; @@ -1592,6 +1614,9 @@ static bool IsSVECalleeSave(MachineBasicBlock::iterator I) { case AArch64::CMPNE_PPzZI_B: return I->getFlag(MachineInstr::FrameSetup) || I->getFlag(MachineInstr::FrameDestroy); + case AArch64::SEH_SavePReg: + case AArch64::SEH_SaveZReg: + return true; } } @@ -1874,12 +1899,51 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, bool IsWin64 = Subtarget.isCallingConvWin64(F.getCallingConv(), F.isVarArg()); unsigned FixedObject = getFixedObjectSize(MF, AFI, IsWin64, IsFunclet); + // Windows unwind can't represent the required stack adjustments if we have + // both SVE callee-saves and dynamic stack allocations, and the frame + // pointer is before the SVE spills. The allocation of the frame pointer + // must be the last instruction in the prologue so the unwinder can restore + // the stack pointer correctly. (And there isn't any unwind opcode for + // `addvl sp, x29, -17`.) + // + // Because of this, we do spills in the opposite order on Windows: first SVE, + // then GPRs. The main side-effect of this is that it makes accessing + // parameters passed on the stack more expensive. + // + // We could consider rearranging the spills for simpler cases. + bool FPAfterSVECalleeSaves = + Subtarget.isTargetWindows() && AFI->getSVECalleeSavedStackSize(); + + if (FPAfterSVECalleeSaves && AFI->hasStackHazardSlotIndex()) + reportFatalUsageError("SME hazard padding is not supported on Windows"); + auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject; // All of the remaining stack allocations are for locals. AFI->setLocalStackSize(NumBytes - PrologueSaveSize); bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes); bool HomPrologEpilog = homogeneousPrologEpilog(MF); - if (CombineSPBump) { + if (FPAfterSVECalleeSaves) { + // If we're doing SVE saves first, we need to immediately allocate space + // for fixed objects, then space for the SVE callee saves. + // + // Windows unwind requires that the scalable size is a multiple of 16; + // that's handled when the callee-saved size is computed. + auto SaveSize = + StackOffset::getScalable(AFI->getSVECalleeSavedStackSize()) + + StackOffset::getFixed(FixedObject); + allocateStackSpace(MBB, MBBI, 0, SaveSize, NeedsWinCFI, &HasWinCFI, + /*EmitCFI=*/false, StackOffset{}, + /*FollowupAllocs=*/true); + NumBytes -= FixedObject; + + // Now allocate space for the GPR callee saves. + while (MBBI != End && IsSVECalleeSave(MBBI)) + ++MBBI; + MBBI = convertCalleeSaveRestoreToSPPrePostIncDec( + MBB, MBBI, DL, TII, -AFI->getCalleeSavedStackSize(), NeedsWinCFI, + &HasWinCFI, EmitAsyncCFI); + NumBytes -= AFI->getCalleeSavedStackSize(); + } else if (CombineSPBump) { assert(!SVEStackSize && "Cannot combine SP bump with SVE"); emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, StackOffset::getFixed(-NumBytes), TII, @@ -1982,6 +2046,9 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, : 0; if (windowsRequiresStackProbe(MF, NumBytes + RealignmentPadding)) { + if (AFI->getSVECalleeSavedStackSize()) + report_fatal_error( + "SVE callee saves not yet supported with stack probing"); uint64_t NumWords = (NumBytes + RealignmentPadding) >> 4; if (NeedsWinCFI) { HasWinCFI = true; @@ -2107,31 +2174,35 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, } StackOffset SVECalleeSavesSize = {}, SVELocalsSize = SVEStackSize; - MachineBasicBlock::iterator CalleeSavesBegin = MBBI, CalleeSavesEnd = MBBI; + MachineBasicBlock::iterator CalleeSavesEnd = MBBI; + + StackOffset CFAOffset = + StackOffset::getFixed((int64_t)MFI.getStackSize() - NumBytes); // Process the SVE callee-saves to determine what space needs to be // allocated. if (int64_t CalleeSavedSize = AFI->getSVECalleeSavedStackSize()) { LLVM_DEBUG(dbgs() << "SVECalleeSavedStackSize = " << CalleeSavedSize << "\n"); - // Find callee save instructions in frame. - CalleeSavesBegin = MBBI; - assert(IsSVECalleeSave(CalleeSavesBegin) && "Unexpected instruction"); - while (IsSVECalleeSave(MBBI) && MBBI != MBB.getFirstTerminator()) - ++MBBI; - CalleeSavesEnd = MBBI; - SVECalleeSavesSize = StackOffset::getScalable(CalleeSavedSize); SVELocalsSize = SVEStackSize - SVECalleeSavesSize; - } + // Find callee save instructions in frame. + // Note: With FPAfterSVECalleeSaves the callee saves have already been + // allocated. + if (!FPAfterSVECalleeSaves) { + MachineBasicBlock::iterator CalleeSavesBegin = MBBI; + assert(IsSVECalleeSave(CalleeSavesBegin) && "Unexpected instruction"); + while (IsSVECalleeSave(MBBI) && MBBI != MBB.getFirstTerminator()) + ++MBBI; + CalleeSavesEnd = MBBI; - // Allocate space for the callee saves (if any). - StackOffset CFAOffset = - StackOffset::getFixed((int64_t)MFI.getStackSize() - NumBytes); - StackOffset LocalsSize = SVELocalsSize + StackOffset::getFixed(NumBytes); - allocateStackSpace(MBB, CalleeSavesBegin, 0, SVECalleeSavesSize, false, - nullptr, EmitAsyncCFI && !HasFP, CFAOffset, - MFI.hasVarSizedObjects() || LocalsSize); + StackOffset LocalsSize = SVELocalsSize + StackOffset::getFixed(NumBytes); + // Allocate space for the callee saves (if any). + allocateStackSpace(MBB, CalleeSavesBegin, 0, SVECalleeSavesSize, false, + nullptr, EmitAsyncCFI && !HasFP, CFAOffset, + MFI.hasVarSizedObjects() || LocalsSize); + } + } CFAOffset += SVECalleeSavesSize; if (EmitAsyncCFI) @@ -2303,10 +2374,16 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, assert(AfterCSRPopSize == 0); return; } + + bool FPAfterSVECalleeSaves = + Subtarget.isTargetWindows() && AFI->getSVECalleeSavedStackSize(); + bool CombineSPBump = shouldCombineCSRLocalStackBumpInEpilogue(MBB, NumBytes); // Assume we can't combine the last pop with the sp restore. bool CombineAfterCSRBump = false; - if (!CombineSPBump && PrologueSaveSize != 0) { + if (FPAfterSVECalleeSaves) { + AfterCSRPopSize += FixedObject; + } else if (!CombineSPBump && PrologueSaveSize != 0) { MachineBasicBlock::iterator Pop = std::prev(MBB.getFirstTerminator()); while (Pop->getOpcode() == TargetOpcode::CFI_INSTRUCTION || AArch64InstrInfo::isSEHInstruction(*Pop)) @@ -2339,7 +2416,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, while (LastPopI != Begin) { --LastPopI; if (!LastPopI->getFlag(MachineInstr::FrameDestroy) || - IsSVECalleeSave(LastPopI)) { + (!FPAfterSVECalleeSaves && IsSVECalleeSave(LastPopI))) { ++LastPopI; break; } else if (CombineSPBump) @@ -2415,6 +2492,9 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, StackOffset DeallocateBefore = {}, DeallocateAfter = SVEStackSize; MachineBasicBlock::iterator RestoreBegin = LastPopI, RestoreEnd = LastPopI; if (int64_t CalleeSavedSize = AFI->getSVECalleeSavedStackSize()) { + if (FPAfterSVECalleeSaves) + RestoreEnd = MBB.getFirstTerminator(); + RestoreBegin = std::prev(RestoreEnd); while (RestoreBegin != MBB.begin() && IsSVECalleeSave(std::prev(RestoreBegin))) @@ -2430,7 +2510,31 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, } // Deallocate the SVE area. - if (SVEStackSize) { + if (FPAfterSVECalleeSaves) { + // If the callee-save area is before FP, restoring the FP implicitly + // deallocates non-callee-save SVE allocations. Otherwise, deallocate + // them explicitly. + if (!AFI->isStackRealigned() && !MFI.hasVarSizedObjects()) { + emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::SP, + DeallocateBefore, TII, MachineInstr::FrameDestroy, false, + NeedsWinCFI, &HasWinCFI); + } + + // Deallocate callee-save non-SVE registers. + emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP, + StackOffset::getFixed(AFI->getCalleeSavedStackSize()), TII, + MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI); + + // Deallocate fixed objects. + emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP, + StackOffset::getFixed(FixedObject), TII, + MachineInstr::FrameDestroy, false, NeedsWinCFI, &HasWinCFI); + + // Deallocate callee-save SVE registers. + emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP, + DeallocateAfter, TII, MachineInstr::FrameDestroy, false, + NeedsWinCFI, &HasWinCFI); + } else if (SVEStackSize) { // If we have stack realignment or variable sized objects on the stack, // restore the stack pointer from the frame pointer prior to SVE CSR // restoration. @@ -2450,20 +2554,20 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, emitFrameOffset( MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP, StackOffset::getFixed(NumBytes), TII, MachineInstr::FrameDestroy, - false, false, nullptr, EmitCFI && !hasFP(MF), + false, NeedsWinCFI, &HasWinCFI, EmitCFI && !hasFP(MF), SVEStackSize + StackOffset::getFixed(NumBytes + PrologueSaveSize)); NumBytes = 0; } emitFrameOffset(MBB, RestoreBegin, DL, AArch64::SP, AArch64::SP, DeallocateBefore, TII, MachineInstr::FrameDestroy, false, - false, nullptr, EmitCFI && !hasFP(MF), + NeedsWinCFI, &HasWinCFI, EmitCFI && !hasFP(MF), SVEStackSize + StackOffset::getFixed(NumBytes + PrologueSaveSize)); emitFrameOffset(MBB, RestoreEnd, DL, AArch64::SP, AArch64::SP, DeallocateAfter, TII, MachineInstr::FrameDestroy, false, - false, nullptr, EmitCFI && !hasFP(MF), + NeedsWinCFI, &HasWinCFI, EmitCFI && !hasFP(MF), DeallocateAfter + StackOffset::getFixed(NumBytes + PrologueSaveSize)); } @@ -2587,7 +2691,12 @@ AArch64FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF, return StackOffset::getFixed(ObjectOffset - getOffsetOfLocalArea()); const auto *AFI = MF.getInfo(); + bool FPAfterSVECalleeSaves = + isTargetWindows(MF) && AFI->getSVECalleeSavedStackSize(); if (MFI.getStackID(FI) == TargetStackID::ScalableVector) { + if (FPAfterSVECalleeSaves && + -ObjectOffset <= (int64_t)AFI->getSVECalleeSavedStackSize()) + return StackOffset::getScalable(ObjectOffset); return StackOffset::get(-((int64_t)AFI->getCalleeSavedStackSize()), ObjectOffset); } @@ -2597,8 +2706,12 @@ AArch64FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF, !IsFixed && ObjectOffset >= -((int)AFI->getCalleeSavedStackSize(MFI)); StackOffset ScalableOffset = {}; - if (!IsFixed && !IsCSR) + if (!IsFixed && !IsCSR) { ScalableOffset = -SVEStackSize; + } else if (FPAfterSVECalleeSaves && IsCSR) { + ScalableOffset = + -StackOffset::getScalable(AFI->getSVECalleeSavedStackSize()); + } return StackOffset::getFixed(ObjectOffset) + ScalableOffset; } @@ -2736,13 +2849,21 @@ StackOffset AArch64FrameLowering::resolveFrameOffsetReference( "In the presence of dynamic stack pointer realignment, " "non-argument/CSR objects cannot be accessed through the frame pointer"); + bool FPAfterSVECalleeSaves = + isTargetWindows(MF) && AFI->getSVECalleeSavedStackSize(); + if (isSVE) { + assert(-ObjectOffset > (int64_t)AFI->getSVECalleeSavedStackSize() && + "Math isn't correct for CSRs with FPAfterSVECalleeSaves"); StackOffset FPOffset = StackOffset::get(-AFI->getCalleeSaveBaseToFrameRecordOffset(), ObjectOffset); StackOffset SPOffset = SVEStackSize + StackOffset::get(MFI.getStackSize() - AFI->getCalleeSavedStackSize(), ObjectOffset); + if (FPAfterSVECalleeSaves) { + FPOffset += StackOffset::getScalable(AFI->getSVECalleeSavedStackSize()); + } // Always use the FP for SVE spills if available and beneficial. if (hasFP(MF) && (SPOffset.getFixed() || FPOffset.getScalable() < SPOffset.getScalable() || @@ -2757,10 +2878,28 @@ StackOffset AArch64FrameLowering::resolveFrameOffsetReference( } StackOffset ScalableOffset = {}; - if (UseFP && !(isFixed || isCSR)) - ScalableOffset = -SVEStackSize; - if (!UseFP && (isFixed || isCSR)) - ScalableOffset = SVEStackSize; + if (FPAfterSVECalleeSaves) { + // In this stack layout, the FP is in between the callee saves and other + // SVE allocations. + StackOffset SVECalleeSavedStack = + StackOffset::getScalable(AFI->getSVECalleeSavedStackSize()); + if (UseFP) { + if (isFixed) + ScalableOffset = SVECalleeSavedStack; + else if (!isCSR) + ScalableOffset = SVECalleeSavedStack - SVEStackSize; + } else { + if (isFixed) + ScalableOffset = SVEStackSize; + else if (isCSR) + ScalableOffset = SVEStackSize - SVECalleeSavedStack; + } + } else { + if (UseFP && !(isFixed || isCSR)) + ScalableOffset = -SVEStackSize; + if (!UseFP && (isFixed || isCSR)) + ScalableOffset = SVEStackSize; + } if (UseFP) { FrameReg = RegInfo->getFrameRegister(MF); @@ -2934,7 +3073,9 @@ static void computeCalleeSaveRegisterPairs( RegInc = -1; FirstReg = Count - 1; } - int ScalableByteOffset = AFI->getSVECalleeSavedStackSize(); + bool FPAfterSVECalleeSaves = IsWindows && AFI->getSVECalleeSavedStackSize(); + int ScalableByteOffset = + FPAfterSVECalleeSaves ? 0 : AFI->getSVECalleeSavedStackSize(); bool NeedGapToAlignStack = AFI->hasCalleeSaveStackFreeSpace(); Register LastReg = 0; @@ -3046,6 +3187,12 @@ static void computeCalleeSaveRegisterPairs( RPI.isPaired()) // RPI.FrameIdx must be the lower index of the pair RPI.FrameIdx = CSI[i + RegInc].getFrameIdx(); + // Realign the scalable offset if necesary. This is relevant when + // spilling predicates on Windows. + if (RPI.isScalable() && ScalableByteOffset % Scale != 0) { + ScalableByteOffset = alignTo(ScalableByteOffset, Scale); + } + int OffsetPre = RPI.isScalable() ? ScalableByteOffset : ByteOffset; assert(OffsetPre % Scale == 0); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index d6225bca233b6..128018db26a45 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -1175,6 +1175,9 @@ bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) { case AArch64::SEH_PACSignLR: case AArch64::SEH_SaveAnyRegQP: case AArch64::SEH_SaveAnyRegQPX: + case AArch64::SEH_AllocZ: + case AArch64::SEH_SaveZReg: + case AArch64::SEH_SavePReg: return true; } } @@ -5987,10 +5990,16 @@ static void emitFrameOffsetAdj(MachineBasicBlock &MBB, } if (NeedsWinCFI) { - assert(Sign == 1 && "SEH directives should always have a positive sign"); int Imm = (int)(ThisVal << LocalShiftSize); - if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) || - (SrcReg == AArch64::FP && DestReg == AArch64::SP)) { + if (VScale != 1 && DestReg == AArch64::SP) { + if (HasWinCFI) + *HasWinCFI = true; + BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ)) + .addImm(ThisVal) + .setMIFlag(Flag); + } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) || + (SrcReg == AArch64::FP && DestReg == AArch64::SP)) { + assert(VScale == 1 && "Expected non-scalable operation"); if (HasWinCFI) *HasWinCFI = true; if (Imm == 0) @@ -6002,6 +6011,7 @@ static void emitFrameOffsetAdj(MachineBasicBlock &MBB, assert(Offset == 0 && "Expected remaining offset to be zero to " "emit a single SEH directive"); } else if (DestReg == AArch64::SP) { + assert(VScale == 1 && "Expected non-scalable operation"); if (HasWinCFI) *HasWinCFI = true; assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc"); @@ -6056,14 +6066,14 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB, assert(!(SetNZCV && (NumPredicateVectors || NumDataVectors)) && "SetNZCV not supported with SVE vectors"); - assert(!(NeedsWinCFI && (NumPredicateVectors || NumDataVectors)) && - "WinCFI not supported with SVE vectors"); + assert(!(NeedsWinCFI && NumPredicateVectors) && + "WinCFI can't allocate fractions of an SVE data vector"); if (NumDataVectors) { emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors, - UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, - TII, Flag, NeedsWinCFI, nullptr, EmitCFAOffset, - CFAOffset, FrameReg); + UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII, + Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset, + FrameReg); CFAOffset += StackOffset::getScalable(-NumDataVectors * 16); SrcReg = DestReg; } @@ -6071,9 +6081,9 @@ void llvm::emitFrameOffset(MachineBasicBlock &MBB, if (NumPredicateVectors) { assert(DestReg != AArch64::SP && "Unaligned access to SP"); emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors, - UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, - TII, Flag, NeedsWinCFI, nullptr, EmitCFAOffset, - CFAOffset, FrameReg); + UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII, + Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset, + FrameReg); } } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 72445172059bf..20c17e8f209a8 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -5572,6 +5572,9 @@ let isPseudo = 1 in { def SEH_PACSignLR : Pseudo<(outs), (ins), []>, Sched<[]>; def SEH_SaveAnyRegQP : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>; def SEH_SaveAnyRegQPX : Pseudo<(outs), (ins i32imm:$reg0, i32imm:$reg1, i32imm:$offs), []>, Sched<[]>; + def SEH_AllocZ : Pseudo<(outs), (ins i32imm:$offs), []>, Sched<[]>; + def SEH_SaveZReg : Pseudo<(outs), (ins i32imm:$reg, i32imm:$offs), []>, Sched<[]>; + def SEH_SavePReg : Pseudo<(outs), (ins i32imm:$reg, i32imm:$offs), []>, Sched<[]>; } // Pseudo instructions for Windows EH diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index 8caa49de0af43..c8fd45e4d9cca 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -98,6 +98,13 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { return CSR_Win_AArch64_AAPCS_SwiftError_SaveList; if (MF->getFunction().getCallingConv() == CallingConv::SwiftTail) return CSR_Win_AArch64_AAPCS_SwiftTail_SaveList; + if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall) + return CSR_Win_AArch64_AAVPCS_SaveList; + if (MF->getFunction().getCallingConv() == + CallingConv::AArch64_SVE_VectorCall) + return CSR_Win_AArch64_SVE_AAPCS_SaveList; + if (MF->getInfo()->isSVECC()) + return CSR_Win_AArch64_SVE_AAPCS_SaveList; return CSR_Win_AArch64_AAPCS_SaveList; } if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall) diff --git a/llvm/test/CodeGen/AArch64/framelayout-sve-win.mir b/llvm/test/CodeGen/AArch64/framelayout-sve-win.mir new file mode 100644 index 0000000000000..5933c5daa67ed --- /dev/null +++ b/llvm/test/CodeGen/AArch64/framelayout-sve-win.mir @@ -0,0 +1,894 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --print-fixed-stack --version 5 +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 --print-fixed-stack +# RUN: llc -mattr=+sve -mtriple=aarch64-windows-msvc -run-pass=prologepilog %s -o - | FileCheck %s + +--- | + + define void @test_allocate_sve() uwtable { entry: unreachable } + define void @test_allocate_sve_gpr_callee_saves() uwtable { entry: unreachable } + define void @test_allocate_sve_gpr_realigned() uwtable { entry: unreachable } + define void @test_address_sve() uwtable { entry: unreachable } + define void @test_address_sve_fp() uwtable { entry: unreachable } + define void @test_stack_arg_sve() uwtable { entry: unreachable } + define void @test_address_sve_out_of_range() uwtable { entry: unreachable } + define void @test_address_gpr_vla() uwtable { entry: unreachable } + define aarch64_sve_vector_pcs void @save_restore_pregs_sve() uwtable { entry: unreachable } + define aarch64_sve_vector_pcs void @save_restore_zregs_sve() uwtable { entry: unreachable } + define aarch64_sve_vector_pcs void @save_restore_sve() uwtable { entry: unreachable } + define aarch64_sve_vector_pcs void @save_restore_sve_realign() uwtable { entry: unreachable } + define aarch64_sve_vector_pcs void @frame_layout() uwtable { entry: unreachable } +... +--- +name: test_allocate_sve +stack: + - { id: 0, stack-id: scalable-vector, size: 18, alignment: 2 } + - { id: 1, stack-id: default, size: 16, alignment: 8 } +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_allocate_sve + ; CHECK: fixedStack: + ; CHECK: liveins: $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.2) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: frame-setup SEH_StackAlloc 16 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 2 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 2 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.2) + ; CHECK-NEXT: frame-destroy SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + RET_ReallyLR +... +--- +name: test_allocate_sve_gpr_callee_saves +stack: + - { id: 0, stack-id: scalable-vector, size: 18, alignment: 2 } + - { id: 1, stack-id: default, size: 16, alignment: 8 } +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_allocate_sve_gpr_callee_saves + ; CHECK: fixedStack: + ; CHECK: liveins: $x21, $x20, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STPXpre killed $x20, killed $x21, $sp, -4 :: (store (s64) into %stack.3), (store (s64) into %stack.4) + ; CHECK-NEXT: frame-setup SEH_SaveRegP_X 20, 21, -32 + ; CHECK-NEXT: frame-setup STRXui killed $lr, $sp, 2 :: (store (s64) into %stack.2) + ; CHECK-NEXT: frame-setup SEH_SaveReg 30, 16 + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: frame-setup SEH_StackAlloc 16 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -2, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 2 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $x20 = IMPLICIT_DEF + ; CHECK-NEXT: $x21 = IMPLICIT_DEF + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 2, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 2 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: $lr = frame-destroy LDRXui $sp, 2 :: (load (s64) from %stack.2) + ; CHECK-NEXT: frame-destroy SEH_SaveReg 30, 16 + ; CHECK-NEXT: early-clobber $sp, $x20, $x21 = frame-destroy LDPXpost $sp, 4 :: (load (s64) from %stack.3), (load (s64) from %stack.4) + ; CHECK-NEXT: frame-destroy SEH_SaveRegP_X 20, 21, -32 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + $x20 = IMPLICIT_DEF + $x21 = IMPLICIT_DEF + RET_ReallyLR +... +--- +name: test_allocate_sve_gpr_realigned +stack: + - { id: 0, stack-id: scalable-vector, size: 18, alignment: 2 } + - { id: 1, stack-id: default, size: 16, alignment: 32 } +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_allocate_sve_gpr_realigned + ; CHECK: fixedStack: + ; CHECK: liveins: $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2 :: (store (s64) into %stack.2), (store (s64) into %stack.3) + ; CHECK-NEXT: frame-setup SEH_SaveFPLR_X -16 + ; CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0 + ; CHECK-NEXT: frame-setup SEH_SetFP + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $x9 = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: $x9 = frame-setup ADDVL_XXI $x9, -2, implicit $vg + ; CHECK-NEXT: $sp = frame-setup ANDXri killed $x9, 7930 + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0 + ; CHECK-NEXT: frame-destroy SEH_SetFP + ; CHECK-NEXT: early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2 :: (load (s64) from %stack.2), (load (s64) from %stack.3) + ; CHECK-NEXT: frame-destroy SEH_SaveFPLR_X -16 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + RET_ReallyLR +... +--- +name: test_address_sve +frameInfo: + maxAlignment: 16 +stack: + - { id: 0, stack-id: scalable-vector, size: 16, alignment: 8 } + - { id: 1, stack-id: scalable-vector, size: 16, alignment: 8 } + - { id: 2, stack-id: scalable-vector, size: 2, alignment: 2 } + - { id: 3, stack-id: default, size: 16, alignment: 8 } +body: | + bb.0.entry: + liveins: $z0, $z1, $p0 + + ; CHECK-LABEL: name: test_address_sve + ; CHECK: fixedStack: + ; CHECK: liveins: $z0, $z1, $p0, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.4) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: frame-setup SEH_StackAlloc 16 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 3 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $x8 = ADDXri $sp, 16, 0 + ; CHECK-NEXT: STR_ZXI $z0, killed $x8, 2 + ; CHECK-NEXT: $x8 = ADDXri $sp, 16, 0 + ; CHECK-NEXT: STR_ZXI $z1, killed $x8, 1 + ; CHECK-NEXT: $x8 = ADDXri $sp, 16, 0 + ; CHECK-NEXT: STR_PXI $p0, killed $x8, 7 + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 3 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.4) + ; CHECK-NEXT: frame-destroy SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + STR_ZXI $z0, %stack.0, 0 + STR_ZXI $z1, %stack.1, 0 + STR_PXI $p0, %stack.2, 0 + + RET_ReallyLR +... +--- +name: test_address_sve_fp +frameInfo: + maxAlignment: 16 + isFrameAddressTaken: true +stack: + - { id: 0, stack-id: scalable-vector, size: 16, alignment: 8 } + - { id: 1, stack-id: scalable-vector, size: 16, alignment: 8 } + - { id: 2, stack-id: scalable-vector, size: 2, alignment: 2 } + - { id: 3, stack-id: default, size: 16, alignment: 8 } +body: | + bb.0.entry: + liveins: $z0, $z1, $p0 + + ; CHECK-LABEL: name: test_address_sve_fp + ; CHECK: fixedStack: + ; CHECK: liveins: $z0, $z1, $p0, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2 :: (store (s64) into %stack.4), (store (s64) into %stack.5) + ; CHECK-NEXT: frame-setup SEH_SaveFPLR_X -16 + ; CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0 + ; CHECK-NEXT: frame-setup SEH_SetFP + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3, implicit $vg + ; CHECK-NEXT: STR_ZXI $z0, $fp, -1 + ; CHECK-NEXT: STR_ZXI $z1, $fp, -2 + ; CHECK-NEXT: STR_PXI $p0, $fp, -17 + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 3 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2 :: (load (s64) from %stack.4), (load (s64) from %stack.5) + ; CHECK-NEXT: frame-destroy SEH_SaveFPLR_X -16 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + STR_ZXI $z0, %stack.0, 0 + STR_ZXI $z1, %stack.1, 0 + STR_PXI $p0, %stack.2, 0 + + RET_ReallyLR +... +--- +name: test_stack_arg_sve +fixedStack: + - { id: 0, stack-id: default, size: 16, alignment: 16, offset: 0 } +stack: + - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 } + - { id: 1, stack-id: default, size: 16, alignment: 16 } +body: | + bb.0.entry: + liveins: $x0 + + ; CHECK-LABEL: name: test_stack_arg_sve + ; CHECK: fixedStack: + ; CHECK-NEXT: - { id: 0, type: default, offset: 0, size: 16, alignment: 16, stack-id: default, + ; CHECK-NEXT: isImmutable: false, isAliased: false, callee-saved-register: '', + ; CHECK-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '', + ; CHECK-NEXT: debug-info-location: '' } + ; CHECK: liveins: $x0, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.2) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: frame-setup SEH_StackAlloc 16 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 1 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $x8 = ADDVL_XXI $sp, 1, implicit $vg + ; CHECK-NEXT: $x0 = LDRXui killed $x8, 4 + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 1, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 1 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.2) + ; CHECK-NEXT: frame-destroy SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + $x0 = LDRXui %fixed-stack.0, 0 + RET_ReallyLR +... +--- +name: test_address_sve_out_of_range +frameInfo: + maxAlignment: 16 +stack: + - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 } + - { id: 1, stack-id: scalable-vector, size: 3584, alignment: 16 } + - { id: 2, stack-id: scalable-vector, size: 512, alignment: 16 } + +body: | + bb.0.entry: + liveins: $z0, $p0 + + ; CHECK-LABEL: name: test_address_sve_out_of_range + ; CHECK: fixedStack: + ; CHECK: liveins: $z0, $p0, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.3) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -32, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 1 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $x8 = ADDVL_XXI $sp, 1, implicit $vg + ; CHECK-NEXT: STR_ZXI $z0, killed $x8, 255 + ; CHECK-NEXT: $x8 = ADDPL_XXI $sp, 1, implicit $vg + ; CHECK-NEXT: STR_PXI $p0, killed $x8, 255 + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 31, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 31 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 9, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 9 + ; CHECK-NEXT: early-clobber $sp, $lr = frame-destroy LDRXpost $sp, 16 :: (load (s64) from %stack.3) + ; CHECK-NEXT: frame-destroy SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + STR_ZXI $z0, %stack.0, 0 + STR_PXI $p0, %stack.1, 0 + + RET_ReallyLR +... +--- +name: test_address_gpr_vla +frameInfo: + maxAlignment: 16 +stack: + - { id: 0, stack-id: scalable-vector, size: 16, alignment: 8 } + - { id: 1, stack-id: default, size: 16, alignment: 8 } + - { id: 2, stack-id: default, type: variable-sized } +body: | + bb.0.entry: + liveins: $xzr + + ; CHECK-LABEL: name: test_address_gpr_vla + ; CHECK: fixedStack: + ; CHECK: liveins: $xzr, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $x19, $sp, -32 :: (store (s64) into %stack.5) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 19, -32 + ; CHECK-NEXT: frame-setup STPXi killed $fp, killed $lr, $sp, 1 :: (store (s64) into %stack.3), (store (s64) into %stack.4) + ; CHECK-NEXT: frame-setup SEH_SaveFPLR 8 + ; CHECK-NEXT: $fp = frame-setup ADDXri $sp, 8, 0 + ; CHECK-NEXT: frame-setup SEH_AddFP 8 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1, implicit $vg + ; CHECK-NEXT: $x19 = ADDXri $sp, 0, 0 + ; CHECK-NEXT: STRXui $xzr, $x19, 0 + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy SUBXri $fp, 8, 0 + ; CHECK-NEXT: frame-destroy SEH_AddFP 8 + ; CHECK-NEXT: $fp, $lr = frame-destroy LDPXi $sp, 1 :: (load (s64) from %stack.3), (load (s64) from %stack.4) + ; CHECK-NEXT: frame-destroy SEH_SaveFPLR 8 + ; CHECK-NEXT: early-clobber $sp, $x19 = frame-destroy LDRXpost $sp, 32 :: (load (s64) from %stack.5) + ; CHECK-NEXT: frame-destroy SEH_SaveReg_X 19, -32 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + STRXui $xzr, %stack.1, 0 + + RET_ReallyLR +... +--- +name: save_restore_pregs_sve +stack: + - { id: 0, stack-id: default, size: 32, alignment: 16 } +body: | + bb.0.entry: + + ; CHECK-LABEL: name: save_restore_pregs_sve + ; CHECK: fixedStack: + ; CHECK: liveins: $p4, $p5, $p6, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 1 + ; CHECK-NEXT: frame-setup STR_PXI killed $p4, $sp, 0 :: (store (s16) into %stack.4) + ; CHECK-NEXT: frame-setup SEH_SavePReg 4, 0 + ; CHECK-NEXT: frame-setup STR_PXI killed $p5, $sp, 1 :: (store (s16) into %stack.3) + ; CHECK-NEXT: frame-setup SEH_SavePReg 5, 1 + ; CHECK-NEXT: frame-setup STR_PXI killed $p6, $sp, 2 :: (store (s16) into %stack.2) + ; CHECK-NEXT: frame-setup SEH_SavePReg 6, 2 + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.1) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 32, 0 + ; CHECK-NEXT: frame-setup SEH_StackAlloc 32 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $p4 = IMPLICIT_DEF + ; CHECK-NEXT: $p5 = IMPLICIT_DEF + ; CHECK-NEXT: $p6 = IMPLICIT_DEF + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 32, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 32 + ; CHECK-NEXT: $lr = frame-destroy LDRXui $sp, 0 :: (load (s64) from %stack.1) + ; CHECK-NEXT: frame-destroy SEH_SaveReg 30, 0 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: $p4 = frame-destroy LDR_PXI $sp, 0 :: (load (s16) from %stack.4) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 4, 0 + ; CHECK-NEXT: $p5 = frame-destroy LDR_PXI $sp, 1 :: (load (s16) from %stack.3) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 5, 1 + ; CHECK-NEXT: $p6 = frame-destroy LDR_PXI $sp, 2 :: (load (s16) from %stack.2) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 6, 2 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 1, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 1 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + $p4 = IMPLICIT_DEF + $p5 = IMPLICIT_DEF + $p6 = IMPLICIT_DEF + + RET_ReallyLR +... +--- +name: save_restore_zregs_sve +stack: + - { id: 0, stack-id: default, size: 32, alignment: 16 } +body: | + bb.0.entry: + + ; CHECK-LABEL: name: save_restore_zregs_sve + ; CHECK: fixedStack: + ; CHECK: liveins: $z8, $z9, $z10, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 3 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z8, $sp, 0 :: (store (s128) into %stack.4) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 8, 0 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z9, $sp, 1 :: (store (s128) into %stack.3) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 9, 1 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z10, $sp, 2 :: (store (s128) into %stack.2) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 10, 2 + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.1) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 32, 0 + ; CHECK-NEXT: frame-setup SEH_StackAlloc 32 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $z8 = IMPLICIT_DEF + ; CHECK-NEXT: $z9 = IMPLICIT_DEF + ; CHECK-NEXT: $z10 = IMPLICIT_DEF + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 32, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 32 + ; CHECK-NEXT: $lr = frame-destroy LDRXui $sp, 0 :: (load (s64) from %stack.1) + ; CHECK-NEXT: frame-destroy SEH_SaveReg 30, 0 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: $z8 = frame-destroy LDR_ZXI $sp, 0 :: (load (s128) from %stack.4) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 8, 0 + ; CHECK-NEXT: $z9 = frame-destroy LDR_ZXI $sp, 1 :: (load (s128) from %stack.3) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 9, 1 + ; CHECK-NEXT: $z10 = frame-destroy LDR_ZXI $sp, 2 :: (load (s128) from %stack.2) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 10, 2 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 3 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + $z8 = IMPLICIT_DEF + $z9 = IMPLICIT_DEF + $z10 = IMPLICIT_DEF + + RET_ReallyLR +... +--- +name: save_restore_sve +stack: + - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 } + - { id: 1, stack-id: default, size: 32, alignment: 16 } +body: | + bb.0.entry: + + ; CHECK-LABEL: name: save_restore_sve + ; CHECK: fixedStack: + ; CHECK: liveins: $p4, $p5, $p6, $p7, $p8, $p9, $p10, $p11, $p12, $p13, $p14, $p15, $z8, $z9, $z10, $z11, $z12, $z13, $z14, $z15, $z16, $z17, $z18, $z19, $z20, $z21, $z22, $z23, $x20, $x19, $lr, $x21 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -18, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 18 + ; CHECK-NEXT: frame-setup STR_PXI killed $p4, $sp, 0 :: (store (s16) into %stack.33) + ; CHECK-NEXT: frame-setup SEH_SavePReg 4, 0 + ; CHECK-NEXT: frame-setup STR_PXI killed $p5, $sp, 1 :: (store (s16) into %stack.32) + ; CHECK-NEXT: frame-setup SEH_SavePReg 5, 1 + ; CHECK-NEXT: frame-setup STR_PXI killed $p6, $sp, 2 :: (store (s16) into %stack.31) + ; CHECK-NEXT: frame-setup SEH_SavePReg 6, 2 + ; CHECK-NEXT: frame-setup STR_PXI killed $p7, $sp, 3 :: (store (s16) into %stack.30) + ; CHECK-NEXT: frame-setup SEH_SavePReg 7, 3 + ; CHECK-NEXT: frame-setup STR_PXI killed $p8, $sp, 4 :: (store (s16) into %stack.29) + ; CHECK-NEXT: frame-setup SEH_SavePReg 8, 4 + ; CHECK-NEXT: frame-setup STR_PXI killed $p9, $sp, 5 :: (store (s16) into %stack.28) + ; CHECK-NEXT: frame-setup SEH_SavePReg 9, 5 + ; CHECK-NEXT: frame-setup STR_PXI killed $p10, $sp, 6 :: (store (s16) into %stack.27) + ; CHECK-NEXT: frame-setup SEH_SavePReg 10, 6 + ; CHECK-NEXT: frame-setup STR_PXI killed $p11, $sp, 7 :: (store (s16) into %stack.26) + ; CHECK-NEXT: frame-setup SEH_SavePReg 11, 7 + ; CHECK-NEXT: frame-setup STR_PXI killed $p12, $sp, 8 :: (store (s16) into %stack.25) + ; CHECK-NEXT: frame-setup SEH_SavePReg 12, 8 + ; CHECK-NEXT: frame-setup STR_PXI killed $p13, $sp, 9 :: (store (s16) into %stack.24) + ; CHECK-NEXT: frame-setup SEH_SavePReg 13, 9 + ; CHECK-NEXT: frame-setup STR_PXI killed $p14, $sp, 10 :: (store (s16) into %stack.23) + ; CHECK-NEXT: frame-setup SEH_SavePReg 14, 10 + ; CHECK-NEXT: frame-setup STR_PXI killed $p15, $sp, 11 :: (store (s16) into %stack.22) + ; CHECK-NEXT: frame-setup SEH_SavePReg 15, 11 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z8, $sp, 2 :: (store (s128) into %stack.21) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 8, 2 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z9, $sp, 3 :: (store (s128) into %stack.20) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 9, 3 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z10, $sp, 4 :: (store (s128) into %stack.19) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 10, 4 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z11, $sp, 5 :: (store (s128) into %stack.18) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 11, 5 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z12, $sp, 6 :: (store (s128) into %stack.17) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 12, 6 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z13, $sp, 7 :: (store (s128) into %stack.16) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 13, 7 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z14, $sp, 8 :: (store (s128) into %stack.15) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 14, 8 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z15, $sp, 9 :: (store (s128) into %stack.14) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 15, 9 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z16, $sp, 10 :: (store (s128) into %stack.13) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 16, 10 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z17, $sp, 11 :: (store (s128) into %stack.12) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 17, 11 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z18, $sp, 12 :: (store (s128) into %stack.11) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 18, 12 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z19, $sp, 13 :: (store (s128) into %stack.10) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 19, 13 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z20, $sp, 14 :: (store (s128) into %stack.9) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 20, 14 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z21, $sp, 15 :: (store (s128) into %stack.8) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 21, 15 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z22, $sp, 16 :: (store (s128) into %stack.7) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 22, 16 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z23, $sp, 17 :: (store (s128) into %stack.6) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 23, 17 + ; CHECK-NEXT: early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -4 :: (store (s64) into %stack.4), (store (s64) into %stack.5) + ; CHECK-NEXT: frame-setup SEH_SaveRegP_X 19, 20, -32 + ; CHECK-NEXT: frame-setup STPXi killed $x21, killed $lr, $sp, 2 :: (store (s64) into %stack.2), (store (s64) into %stack.3) + ; CHECK-NEXT: frame-setup SEH_SaveRegP 21, 30, 16 + ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 32, 0 + ; CHECK-NEXT: frame-setup SEH_StackAlloc 32 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -1, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 1 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $z8_z9_z10_z11 = IMPLICIT_DEF + ; CHECK-NEXT: $z12_z13_z14_z15 = IMPLICIT_DEF + ; CHECK-NEXT: $z16_z17_z18_z19 = IMPLICIT_DEF + ; CHECK-NEXT: $z20_z21_z22_z23 = IMPLICIT_DEF + ; CHECK-NEXT: $z24_z25_z26_z27 = IMPLICIT_DEF + ; CHECK-NEXT: $z28_z29_z30_z31 = IMPLICIT_DEF + ; CHECK-NEXT: $p4 = IMPLICIT_DEF + ; CHECK-NEXT: $p5 = IMPLICIT_DEF + ; CHECK-NEXT: $p6 = IMPLICIT_DEF + ; CHECK-NEXT: $p7 = IMPLICIT_DEF + ; CHECK-NEXT: $p8 = IMPLICIT_DEF + ; CHECK-NEXT: $p9 = IMPLICIT_DEF + ; CHECK-NEXT: $p10 = IMPLICIT_DEF + ; CHECK-NEXT: $p11 = IMPLICIT_DEF + ; CHECK-NEXT: $p12 = IMPLICIT_DEF + ; CHECK-NEXT: $p13 = IMPLICIT_DEF + ; CHECK-NEXT: $p14 = IMPLICIT_DEF + ; CHECK-NEXT: $p15 = IMPLICIT_DEF + ; CHECK-NEXT: $x19 = IMPLICIT_DEF + ; CHECK-NEXT: $x20 = IMPLICIT_DEF + ; CHECK-NEXT: $x21 = IMPLICIT_DEF + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 1, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 1 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 32, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 32 + ; CHECK-NEXT: $x21, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64) from %stack.2), (load (s64) from %stack.3) + ; CHECK-NEXT: frame-destroy SEH_SaveRegP 21, 30, 16 + ; CHECK-NEXT: $x19, $x20 = frame-destroy LDPXi $sp, 0 :: (load (s64) from %stack.4), (load (s64) from %stack.5) + ; CHECK-NEXT: frame-destroy SEH_SaveRegP 19, 20, 0 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 32, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 32 + ; CHECK-NEXT: $z8 = frame-destroy LDR_ZXI $sp, 2 :: (load (s128) from %stack.21) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 8, 2 + ; CHECK-NEXT: $z9 = frame-destroy LDR_ZXI $sp, 3 :: (load (s128) from %stack.20) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 9, 3 + ; CHECK-NEXT: $z10 = frame-destroy LDR_ZXI $sp, 4 :: (load (s128) from %stack.19) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 10, 4 + ; CHECK-NEXT: $z11 = frame-destroy LDR_ZXI $sp, 5 :: (load (s128) from %stack.18) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 11, 5 + ; CHECK-NEXT: $z12 = frame-destroy LDR_ZXI $sp, 6 :: (load (s128) from %stack.17) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 12, 6 + ; CHECK-NEXT: $z13 = frame-destroy LDR_ZXI $sp, 7 :: (load (s128) from %stack.16) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 13, 7 + ; CHECK-NEXT: $z14 = frame-destroy LDR_ZXI $sp, 8 :: (load (s128) from %stack.15) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 14, 8 + ; CHECK-NEXT: $z15 = frame-destroy LDR_ZXI $sp, 9 :: (load (s128) from %stack.14) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 15, 9 + ; CHECK-NEXT: $z16 = frame-destroy LDR_ZXI $sp, 10 :: (load (s128) from %stack.13) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 16, 10 + ; CHECK-NEXT: $z17 = frame-destroy LDR_ZXI $sp, 11 :: (load (s128) from %stack.12) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 17, 11 + ; CHECK-NEXT: $z18 = frame-destroy LDR_ZXI $sp, 12 :: (load (s128) from %stack.11) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 18, 12 + ; CHECK-NEXT: $z19 = frame-destroy LDR_ZXI $sp, 13 :: (load (s128) from %stack.10) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 19, 13 + ; CHECK-NEXT: $z20 = frame-destroy LDR_ZXI $sp, 14 :: (load (s128) from %stack.9) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 20, 14 + ; CHECK-NEXT: $z21 = frame-destroy LDR_ZXI $sp, 15 :: (load (s128) from %stack.8) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 21, 15 + ; CHECK-NEXT: $z22 = frame-destroy LDR_ZXI $sp, 16 :: (load (s128) from %stack.7) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 22, 16 + ; CHECK-NEXT: $z23 = frame-destroy LDR_ZXI $sp, 17 :: (load (s128) from %stack.6) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 23, 17 + ; CHECK-NEXT: $p4 = frame-destroy LDR_PXI $sp, 0 :: (load (s16) from %stack.33) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 4, 0 + ; CHECK-NEXT: $p5 = frame-destroy LDR_PXI $sp, 1 :: (load (s16) from %stack.32) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 5, 1 + ; CHECK-NEXT: $p6 = frame-destroy LDR_PXI $sp, 2 :: (load (s16) from %stack.31) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 6, 2 + ; CHECK-NEXT: $p7 = frame-destroy LDR_PXI $sp, 3 :: (load (s16) from %stack.30) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 7, 3 + ; CHECK-NEXT: $p8 = frame-destroy LDR_PXI $sp, 4 :: (load (s16) from %stack.29) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 8, 4 + ; CHECK-NEXT: $p9 = frame-destroy LDR_PXI $sp, 5 :: (load (s16) from %stack.28) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 9, 5 + ; CHECK-NEXT: $p10 = frame-destroy LDR_PXI $sp, 6 :: (load (s16) from %stack.27) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 10, 6 + ; CHECK-NEXT: $p11 = frame-destroy LDR_PXI $sp, 7 :: (load (s16) from %stack.26) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 11, 7 + ; CHECK-NEXT: $p12 = frame-destroy LDR_PXI $sp, 8 :: (load (s16) from %stack.25) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 12, 8 + ; CHECK-NEXT: $p13 = frame-destroy LDR_PXI $sp, 9 :: (load (s16) from %stack.24) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 13, 9 + ; CHECK-NEXT: $p14 = frame-destroy LDR_PXI $sp, 10 :: (load (s16) from %stack.23) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 14, 10 + ; CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 11 :: (load (s16) from %stack.22) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 15, 11 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 18, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 18 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + $z8_z9_z10_z11 = IMPLICIT_DEF + $z12_z13_z14_z15 = IMPLICIT_DEF + $z16_z17_z18_z19 = IMPLICIT_DEF + $z20_z21_z22_z23 = IMPLICIT_DEF + $z24_z25_z26_z27 = IMPLICIT_DEF + $z28_z29_z30_z31 = IMPLICIT_DEF + $p4 = IMPLICIT_DEF + $p5 = IMPLICIT_DEF + $p6 = IMPLICIT_DEF + $p7 = IMPLICIT_DEF + $p8 = IMPLICIT_DEF + $p9 = IMPLICIT_DEF + $p10 = IMPLICIT_DEF + $p11 = IMPLICIT_DEF + $p12 = IMPLICIT_DEF + $p13 = IMPLICIT_DEF + $p14 = IMPLICIT_DEF + $p15 = IMPLICIT_DEF + + $x19 = IMPLICIT_DEF + $x20 = IMPLICIT_DEF + $x21 = IMPLICIT_DEF + + RET_ReallyLR +... +--- +name: save_restore_sve_realign +stack: + - { id: 0, stack-id: scalable-vector, size: 16, alignment: 16 } + - { id: 1, stack-id: default, size: 16, alignment: 32 } +body: | + bb.0.entry: + + ; CHECK-LABEL: name: save_restore_sve_realign + ; CHECK: fixedStack: + ; CHECK: liveins: $p4, $p5, $p6, $p7, $p8, $p9, $p10, $p11, $p12, $p13, $p14, $p15, $z8, $z9, $z10, $z11, $z12, $z13, $z14, $z15, $z16, $z17, $z18, $z19, $z20, $z21, $z22, $z23, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -18, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 18 + ; CHECK-NEXT: frame-setup STR_PXI killed $p4, $sp, 0 :: (store (s16) into %stack.31) + ; CHECK-NEXT: frame-setup SEH_SavePReg 4, 0 + ; CHECK-NEXT: frame-setup STR_PXI killed $p5, $sp, 1 :: (store (s16) into %stack.30) + ; CHECK-NEXT: frame-setup SEH_SavePReg 5, 1 + ; CHECK-NEXT: frame-setup STR_PXI killed $p6, $sp, 2 :: (store (s16) into %stack.29) + ; CHECK-NEXT: frame-setup SEH_SavePReg 6, 2 + ; CHECK-NEXT: frame-setup STR_PXI killed $p7, $sp, 3 :: (store (s16) into %stack.28) + ; CHECK-NEXT: frame-setup SEH_SavePReg 7, 3 + ; CHECK-NEXT: frame-setup STR_PXI killed $p8, $sp, 4 :: (store (s16) into %stack.27) + ; CHECK-NEXT: frame-setup SEH_SavePReg 8, 4 + ; CHECK-NEXT: frame-setup STR_PXI killed $p9, $sp, 5 :: (store (s16) into %stack.26) + ; CHECK-NEXT: frame-setup SEH_SavePReg 9, 5 + ; CHECK-NEXT: frame-setup STR_PXI killed $p10, $sp, 6 :: (store (s16) into %stack.25) + ; CHECK-NEXT: frame-setup SEH_SavePReg 10, 6 + ; CHECK-NEXT: frame-setup STR_PXI killed $p11, $sp, 7 :: (store (s16) into %stack.24) + ; CHECK-NEXT: frame-setup SEH_SavePReg 11, 7 + ; CHECK-NEXT: frame-setup STR_PXI killed $p12, $sp, 8 :: (store (s16) into %stack.23) + ; CHECK-NEXT: frame-setup SEH_SavePReg 12, 8 + ; CHECK-NEXT: frame-setup STR_PXI killed $p13, $sp, 9 :: (store (s16) into %stack.22) + ; CHECK-NEXT: frame-setup SEH_SavePReg 13, 9 + ; CHECK-NEXT: frame-setup STR_PXI killed $p14, $sp, 10 :: (store (s16) into %stack.21) + ; CHECK-NEXT: frame-setup SEH_SavePReg 14, 10 + ; CHECK-NEXT: frame-setup STR_PXI killed $p15, $sp, 11 :: (store (s16) into %stack.20) + ; CHECK-NEXT: frame-setup SEH_SavePReg 15, 11 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z8, $sp, 2 :: (store (s128) into %stack.19) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 8, 2 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z9, $sp, 3 :: (store (s128) into %stack.18) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 9, 3 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z10, $sp, 4 :: (store (s128) into %stack.17) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 10, 4 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z11, $sp, 5 :: (store (s128) into %stack.16) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 11, 5 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z12, $sp, 6 :: (store (s128) into %stack.15) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 12, 6 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z13, $sp, 7 :: (store (s128) into %stack.14) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 13, 7 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z14, $sp, 8 :: (store (s128) into %stack.13) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 14, 8 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z15, $sp, 9 :: (store (s128) into %stack.12) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 15, 9 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z16, $sp, 10 :: (store (s128) into %stack.11) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 16, 10 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z17, $sp, 11 :: (store (s128) into %stack.10) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 17, 11 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z18, $sp, 12 :: (store (s128) into %stack.9) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 18, 12 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z19, $sp, 13 :: (store (s128) into %stack.8) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 19, 13 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z20, $sp, 14 :: (store (s128) into %stack.7) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 20, 14 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z21, $sp, 15 :: (store (s128) into %stack.6) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 21, 15 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z22, $sp, 16 :: (store (s128) into %stack.5) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 22, 16 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z23, $sp, 17 :: (store (s128) into %stack.4) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 23, 17 + ; CHECK-NEXT: early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2 :: (store (s64) into %stack.2), (store (s64) into %stack.3) + ; CHECK-NEXT: frame-setup SEH_SaveFPLR_X -16 + ; CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0 + ; CHECK-NEXT: frame-setup SEH_SetFP + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $x9 = frame-setup SUBXri $sp, 16, 0 + ; CHECK-NEXT: $x9 = frame-setup ADDVL_XXI $x9, -1, implicit $vg + ; CHECK-NEXT: $sp = frame-setup ANDXri killed $x9, 7930 + ; CHECK-NEXT: $z8_z9_z10_z11 = IMPLICIT_DEF + ; CHECK-NEXT: $z12_z13_z14_z15 = IMPLICIT_DEF + ; CHECK-NEXT: $z16_z17_z18_z19 = IMPLICIT_DEF + ; CHECK-NEXT: $z20_z21_z22_z23 = IMPLICIT_DEF + ; CHECK-NEXT: $z24_z25_z26_z27 = IMPLICIT_DEF + ; CHECK-NEXT: $z28_z29_z30_z31 = IMPLICIT_DEF + ; CHECK-NEXT: $p4 = IMPLICIT_DEF + ; CHECK-NEXT: $p5 = IMPLICIT_DEF + ; CHECK-NEXT: $p6 = IMPLICIT_DEF + ; CHECK-NEXT: $p7 = IMPLICIT_DEF + ; CHECK-NEXT: $p8 = IMPLICIT_DEF + ; CHECK-NEXT: $p9 = IMPLICIT_DEF + ; CHECK-NEXT: $p10 = IMPLICIT_DEF + ; CHECK-NEXT: $p11 = IMPLICIT_DEF + ; CHECK-NEXT: $p12 = IMPLICIT_DEF + ; CHECK-NEXT: $p13 = IMPLICIT_DEF + ; CHECK-NEXT: $p14 = IMPLICIT_DEF + ; CHECK-NEXT: $p15 = IMPLICIT_DEF + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDXri $fp, 0, 0 + ; CHECK-NEXT: frame-destroy SEH_SetFP + ; CHECK-NEXT: $fp, $lr = frame-destroy LDPXi $sp, 0 :: (load (s64) from %stack.2), (load (s64) from %stack.3) + ; CHECK-NEXT: frame-destroy SEH_SaveFPLR 0 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: $z8 = frame-destroy LDR_ZXI $sp, 2 :: (load (s128) from %stack.19) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 8, 2 + ; CHECK-NEXT: $z9 = frame-destroy LDR_ZXI $sp, 3 :: (load (s128) from %stack.18) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 9, 3 + ; CHECK-NEXT: $z10 = frame-destroy LDR_ZXI $sp, 4 :: (load (s128) from %stack.17) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 10, 4 + ; CHECK-NEXT: $z11 = frame-destroy LDR_ZXI $sp, 5 :: (load (s128) from %stack.16) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 11, 5 + ; CHECK-NEXT: $z12 = frame-destroy LDR_ZXI $sp, 6 :: (load (s128) from %stack.15) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 12, 6 + ; CHECK-NEXT: $z13 = frame-destroy LDR_ZXI $sp, 7 :: (load (s128) from %stack.14) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 13, 7 + ; CHECK-NEXT: $z14 = frame-destroy LDR_ZXI $sp, 8 :: (load (s128) from %stack.13) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 14, 8 + ; CHECK-NEXT: $z15 = frame-destroy LDR_ZXI $sp, 9 :: (load (s128) from %stack.12) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 15, 9 + ; CHECK-NEXT: $z16 = frame-destroy LDR_ZXI $sp, 10 :: (load (s128) from %stack.11) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 16, 10 + ; CHECK-NEXT: $z17 = frame-destroy LDR_ZXI $sp, 11 :: (load (s128) from %stack.10) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 17, 11 + ; CHECK-NEXT: $z18 = frame-destroy LDR_ZXI $sp, 12 :: (load (s128) from %stack.9) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 18, 12 + ; CHECK-NEXT: $z19 = frame-destroy LDR_ZXI $sp, 13 :: (load (s128) from %stack.8) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 19, 13 + ; CHECK-NEXT: $z20 = frame-destroy LDR_ZXI $sp, 14 :: (load (s128) from %stack.7) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 20, 14 + ; CHECK-NEXT: $z21 = frame-destroy LDR_ZXI $sp, 15 :: (load (s128) from %stack.6) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 21, 15 + ; CHECK-NEXT: $z22 = frame-destroy LDR_ZXI $sp, 16 :: (load (s128) from %stack.5) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 22, 16 + ; CHECK-NEXT: $z23 = frame-destroy LDR_ZXI $sp, 17 :: (load (s128) from %stack.4) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 23, 17 + ; CHECK-NEXT: $p4 = frame-destroy LDR_PXI $sp, 0 :: (load (s16) from %stack.31) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 4, 0 + ; CHECK-NEXT: $p5 = frame-destroy LDR_PXI $sp, 1 :: (load (s16) from %stack.30) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 5, 1 + ; CHECK-NEXT: $p6 = frame-destroy LDR_PXI $sp, 2 :: (load (s16) from %stack.29) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 6, 2 + ; CHECK-NEXT: $p7 = frame-destroy LDR_PXI $sp, 3 :: (load (s16) from %stack.28) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 7, 3 + ; CHECK-NEXT: $p8 = frame-destroy LDR_PXI $sp, 4 :: (load (s16) from %stack.27) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 8, 4 + ; CHECK-NEXT: $p9 = frame-destroy LDR_PXI $sp, 5 :: (load (s16) from %stack.26) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 9, 5 + ; CHECK-NEXT: $p10 = frame-destroy LDR_PXI $sp, 6 :: (load (s16) from %stack.25) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 10, 6 + ; CHECK-NEXT: $p11 = frame-destroy LDR_PXI $sp, 7 :: (load (s16) from %stack.24) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 11, 7 + ; CHECK-NEXT: $p12 = frame-destroy LDR_PXI $sp, 8 :: (load (s16) from %stack.23) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 12, 8 + ; CHECK-NEXT: $p13 = frame-destroy LDR_PXI $sp, 9 :: (load (s16) from %stack.22) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 13, 9 + ; CHECK-NEXT: $p14 = frame-destroy LDR_PXI $sp, 10 :: (load (s16) from %stack.21) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 14, 10 + ; CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 11 :: (load (s16) from %stack.20) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 15, 11 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 18, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 18 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + $z8_z9_z10_z11 = IMPLICIT_DEF + $z12_z13_z14_z15 = IMPLICIT_DEF + $z16_z17_z18_z19 = IMPLICIT_DEF + $z20_z21_z22_z23 = IMPLICIT_DEF + $z24_z25_z26_z27 = IMPLICIT_DEF + $z28_z29_z30_z31 = IMPLICIT_DEF + $p4 = IMPLICIT_DEF + $p5 = IMPLICIT_DEF + $p6 = IMPLICIT_DEF + $p7 = IMPLICIT_DEF + $p8 = IMPLICIT_DEF + $p9 = IMPLICIT_DEF + $p10 = IMPLICIT_DEF + $p11 = IMPLICIT_DEF + $p12 = IMPLICIT_DEF + $p13 = IMPLICIT_DEF + $p14 = IMPLICIT_DEF + $p15 = IMPLICIT_DEF + + RET_ReallyLR +... +--- +name: frame_layout +stack: + - { id: 0, type: default, size: 32, alignment: 16, stack-id: scalable-vector } + - { id: 1, type: default, size: 4, alignment: 2, stack-id: scalable-vector } + - { id: 2, type: default, size: 16, alignment: 16, stack-id: scalable-vector } + - { id: 3, type: default, size: 2, alignment: 2, stack-id: scalable-vector } + - { id: 4, type: spill-slot, size: 16, alignment: 16, stack-id: scalable-vector } + - { id: 5, type: spill-slot, size: 2, alignment: 2, stack-id: scalable-vector } +body: | + bb.0.entry: + + ; Trigger some callee saves + ; CHECK-LABEL: name: frame_layout + ; CHECK: fixedStack: + ; CHECK: liveins: $p4, $p15, $z8, $z23, $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 3 + ; CHECK-NEXT: frame-setup STR_PXI killed $p4, $sp, 0 :: (store (s16) into %stack.10) + ; CHECK-NEXT: frame-setup SEH_SavePReg 4, 0 + ; CHECK-NEXT: frame-setup STR_PXI killed $p15, $sp, 1 :: (store (s16) into %stack.9) + ; CHECK-NEXT: frame-setup SEH_SavePReg 15, 1 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z8, $sp, 1 :: (store (s128) into %stack.8) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 8, 1 + ; CHECK-NEXT: frame-setup STR_ZXI killed $z23, $sp, 2 :: (store (s128) into %stack.7) + ; CHECK-NEXT: frame-setup SEH_SaveZReg 23, 2 + ; CHECK-NEXT: early-clobber $sp = frame-setup STRXpre killed $lr, $sp, -16 :: (store (s64) into %stack.6) + ; CHECK-NEXT: frame-setup SEH_SaveReg_X 30, -16 + ; CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -7, implicit $vg + ; CHECK-NEXT: frame-setup SEH_AllocZ 7 + ; CHECK-NEXT: frame-setup SEH_PrologEnd + ; CHECK-NEXT: $z8 = IMPLICIT_DEF + ; CHECK-NEXT: $z23 = IMPLICIT_DEF + ; CHECK-NEXT: $p4 = IMPLICIT_DEF + ; CHECK-NEXT: $p15 = IMPLICIT_DEF + ; CHECK-NEXT: frame-destroy SEH_EpilogStart + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 7, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 7 + ; CHECK-NEXT: $lr = frame-destroy LDRXui $sp, 0 :: (load (s64) from %stack.6) + ; CHECK-NEXT: frame-destroy SEH_SaveReg 30, 0 + ; CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 16, 0 + ; CHECK-NEXT: frame-destroy SEH_StackAlloc 16 + ; CHECK-NEXT: $z8 = frame-destroy LDR_ZXI $sp, 1 :: (load (s128) from %stack.8) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 8, 1 + ; CHECK-NEXT: $z23 = frame-destroy LDR_ZXI $sp, 2 :: (load (s128) from %stack.7) + ; CHECK-NEXT: frame-destroy SEH_SaveZReg 23, 2 + ; CHECK-NEXT: $p4 = frame-destroy LDR_PXI $sp, 0 :: (load (s16) from %stack.10) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 4, 0 + ; CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 1 :: (load (s16) from %stack.9) + ; CHECK-NEXT: frame-destroy SEH_SavePReg 15, 1 + ; CHECK-NEXT: $sp = frame-destroy ADDVL_XXI $sp, 3, implicit $vg + ; CHECK-NEXT: frame-destroy SEH_AllocZ 3 + ; CHECK-NEXT: frame-destroy SEH_EpilogEnd + ; CHECK-NEXT: RET_ReallyLR + $z8 = IMPLICIT_DEF + $z23 = IMPLICIT_DEF + $p4 = IMPLICIT_DEF + $p15 = IMPLICIT_DEF + + RET_ReallyLR +... diff --git a/llvm/test/CodeGen/AArch64/sve-stack-frame-layout-win.ll b/llvm/test/CodeGen/AArch64/sve-stack-frame-layout-win.ll new file mode 100644 index 0000000000000..8f732bd933124 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-stack-frame-layout-win.ll @@ -0,0 +1,44 @@ +; RUN: llc -mtriple=aarch64-windows-msvc -mattr=+sve -pass-remarks-analysis=stack-frame-layout < %s 2>&1 -o /dev/null | FileCheck %s + +; CHECK: Function: f10 +; CHECK: Offset: [SP+0-16 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-32 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-48 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-64 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-80 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-96 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-112 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-128 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-144 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-160 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-176 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-192 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-208 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-224 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-240 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-256 x vscale], Type: Spill, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP+0-258 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-260 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-262 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-264 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-266 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-268 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-270 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-272 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-274 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-276 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-278 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP+0-280 x vscale], Type: Spill, Align: 2, Size: vscale x 2 +; CHECK: Offset: [SP-16-288 x vscale], Type: Spill, Align: 16, Size: 8 +; CHECK: Offset: [SP-24-288 x vscale], Type: Spill, Align: 8, Size: 8 +; CHECK: Offset: [SP-32-288 x vscale], Type: Spill, Align: 8, Size: 8 +; CHECK: Offset: [SP-32-304 x vscale], Type: Variable, Align: 16, Size: vscale x 16 +; CHECK: Offset: [SP-48-304 x vscale], Type: Variable, Align: 8, Size: 16 + +declare void @g10(ptr,ptr) +define void @f10(i64 %n, %x) "frame-pointer"="all" { + %p1 = alloca [2 x i64] + %p2 = alloca + call void @g10(ptr %p1, ptr %p2) + ret void +} diff --git a/llvm/test/CodeGen/AArch64/win-sve.ll b/llvm/test/CodeGen/AArch64/win-sve.ll new file mode 100644 index 0000000000000..691230af3e67d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/win-sve.ll @@ -0,0 +1,1580 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64-windows-msvc -mattr=+sve < %s | FileCheck %s +; RUN: llc -mtriple=aarch64-windows-msvc -mattr=+sve -filetype=obj < %s -o /dev/null + +declare void @g() +define i32 @f( %x) { +; CHECK-LABEL: f: +; CHECK: .seh_proc f +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: bl g +; CHECK-NEXT: mov w0, #3 // =0x3 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldp x29, x30, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + call void @g() + ret i32 3 +} + +declare void @g2(ptr,ptr) +define void @f2(i64 %n, %x) { +; CHECK-LABEL: f2: +; CHECK: .seh_proc f2 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: str x19, [sp, #-32]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x19, 32 +; CHECK-NEXT: str x28, [sp, #8] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: stp x29, x30, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: add x29, sp, #16 +; CHECK-NEXT: .seh_add_fp 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: sub sp, sp, #32 +; CHECK-NEXT: lsl x8, x0, #3 +; CHECK-NEXT: mov x19, sp +; CHECK-NEXT: add x8, x8, #15 +; CHECK-NEXT: lsr x15, x8, #4 +; CHECK-NEXT: bl __chkstk +; CHECK-NEXT: sub x1, sp, x15, lsl #4 +; CHECK-NEXT: mov sp, x1 +; CHECK-NEXT: add x0, x19, #0 +; CHECK-NEXT: bl g2 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: sub sp, x29, #16 +; CHECK-NEXT: .seh_add_fp 16 +; CHECK-NEXT: ldp x29, x30, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: ldr x28, [sp, #8] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: ldr x19, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x19, 0 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %p1 = alloca [4 x i64] + %p2 = alloca i64, i64 %n + call void @g2(ptr %p1, ptr %p2) + ret void +} + +declare void @g3(ptr,ptr) +define void @f3(i64 %n, %x) { +; CHECK-LABEL: f3: +; CHECK: .seh_proc f3 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: add x0, sp, #8 +; CHECK-NEXT: mov x1, sp +; CHECK-NEXT: bl g3 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldp x29, x30, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %p1 = alloca i64 + %p2 = alloca i64 + call void @g3(ptr %p1, ptr %p2) + ret void +} + +declare void @g4(ptr,ptr) +define void @f4(i64 %n, %x) { +; CHECK-LABEL: f4: +; CHECK: .seh_proc f4 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: add x1, sp, #16 +; CHECK-NEXT: bl g4 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldp x29, x30, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %p1 = alloca [2 x i64] + %p2 = alloca + call void @g4(ptr %p1, ptr %p2) + ret void +} + +declare void @g5(ptr,ptr,ptr) +define void @f5(i64 %n, %x) { +; CHECK-LABEL: f5: +; CHECK: .seh_proc f5 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: str x19, [sp, #-32]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x19, 32 +; CHECK-NEXT: str x28, [sp, #8] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: stp x29, x30, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: add x29, sp, #16 +; CHECK-NEXT: .seh_add_fp 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: sub sp, sp, #64 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: lsl x8, x0, #3 +; CHECK-NEXT: mov x19, sp +; CHECK-NEXT: add x8, x8, #15 +; CHECK-NEXT: lsr x15, x8, #4 +; CHECK-NEXT: bl __chkstk +; CHECK-NEXT: sub x2, sp, x15, lsl #4 +; CHECK-NEXT: mov sp, x2 +; CHECK-NEXT: sub x1, x29, #16 +; CHECK-NEXT: add x0, x19, #0 +; CHECK-NEXT: addvl x1, x1, #-1 +; CHECK-NEXT: bl g5 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: sub sp, x29, #16 +; CHECK-NEXT: .seh_add_fp 16 +; CHECK-NEXT: ldp x29, x30, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: ldr x28, [sp, #8] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: ldr x19, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x19, 0 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %p1 = alloca [8 x i64] + %p2 = alloca + %p3 = alloca i64, i64 %n + call void @g5(ptr %p1, ptr %p2, ptr %p3) + ret void +} + +declare dso_local i32 @__CxxFrameHandler3(...) +declare void @g6(ptr, i64) +declare void @cleanup() +define void @f6( %x, [8 x i64] %pad, i64 %n9) personality ptr @__CxxFrameHandler3 { +; CHECK-LABEL: f6: +; CHECK: .Lfunc_begin0: +; CHECK-NEXT: .seh_proc f6 +; CHECK-NEXT: .seh_handler __CxxFrameHandler3, @unwind, @except +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: str x19, [sp, #-32]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x19, 32 +; CHECK-NEXT: str x28, [sp, #8] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: stp x29, x30, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: add x29, sp, #16 +; CHECK-NEXT: .seh_add_fp 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: sub sp, sp, #64 +; CHECK-NEXT: mov x0, #-2 // =0xfffffffffffffffe +; CHECK-NEXT: addvl x8, x29, #18 +; CHECK-NEXT: mov x19, sp +; CHECK-NEXT: stur x0, [x8, #16] +; CHECK-NEXT: addvl x8, x29, #18 +; CHECK-NEXT: ldr x1, [x8, #32] +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: add x0, x19, #0 +; CHECK-NEXT: bl g6 +; CHECK-NEXT: .Ltmp1: +; CHECK-NEXT: // %bb.1: // %invoke.cont +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: add sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: ldp x29, x30, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: ldr x28, [sp, #8] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: ldr x19, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x19, 0 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_handlerdata +; CHECK-NEXT: .word $cppxdata$f6@IMGREL +; CHECK-NEXT: .text +; CHECK-NEXT: .seh_endproc +; CHECK-NEXT: .def "?dtor$2@?0?f6@4HA"; +; CHECK-NEXT: .scl 3; +; CHECK-NEXT: .type 32; +; CHECK-NEXT: .endef +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: "?dtor$2@?0?f6@4HA": +; CHECK-NEXT: .seh_proc "?dtor$2@?0?f6@4HA" +; CHECK-NEXT: .LBB5_2: // %ehcleanup +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: str x19, [sp, #-32]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x19, 32 +; CHECK-NEXT: str x28, [sp, #8] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: stp x29, x30, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: bl cleanup +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldp x29, x30, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: ldr x28, [sp, #8] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: ldr x19, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x19, 0 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret + %p1 = alloca [8 x i64] + invoke void @g6(ptr %p1, i64 %n9) to label %invoke.cont unwind label %ehcleanup + +invoke.cont: + ret void + +ehcleanup: ; preds = %entry + %c = cleanuppad within none [] + call void @cleanup() [ "funclet"(token %c) ] + cleanupret from %c unwind to caller +} + +declare void @g7(ptr) +define void @f7(i64 %n) { +; CHECK-LABEL: f7: +; CHECK: .seh_proc f7 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: bl g7 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %p = alloca + call void @g7(ptr %p) + ret void +} + +define void @f8( %v) { +; CHECK-LABEL: f8: +; CHECK: .seh_proc f8 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: str z8, [sp] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + call void asm "", "~{d8}"() + ret void +} + +define void @f9( %v, ...) { +; CHECK-LABEL: f9: +; CHECK: .seh_proc f9 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: sub sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: str z8, [sp] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: add x9, sp, #8 +; CHECK-NEXT: str x2, [x8, #32] +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: str x0, [x8, #16] +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: str x1, [x8, #24] +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: str x3, [x8, #40] +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: str x4, [x8, #48] +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: str x5, [x8, #56] +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: str x6, [x8, #64] +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: str x7, [x8, #72] +; CHECK-NEXT: add x8, sp, #16 +; CHECK-NEXT: addvl x8, x8, #1 +; CHECK-NEXT: str x8, [sp, #8] +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: add sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: add sp, sp, #64 +; CHECK-NEXT: .seh_stackalloc 64 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %va_list = alloca ptr + call void @llvm.va_start.p0(ptr %va_list) + call void asm "", "r,~{d8},~{memory}"(ptr %va_list) + ret void +} + +declare void @g10(ptr,ptr) +define void @f10(i64 %n, %x) "frame-pointer"="all" { +; CHECK-LABEL: f10: +; CHECK: .seh_proc f10 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: str p4, [sp] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: str p5, [sp, #1, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: str p6, [sp, #2, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: str p7, [sp, #3, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: str p8, [sp, #4, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: str p9, [sp, #5, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: str p10, [sp, #6, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: str p11, [sp, #7, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: str p12, [sp, #8, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: str p13, [sp, #9, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: str p14, [sp, #10, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: str p15, [sp, #11, mul vl] // 2-byte Folded Spill +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: str z8, [sp, #2, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: str z9, [sp, #3, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: str z10, [sp, #4, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: str z11, [sp, #5, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: str z12, [sp, #6, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: str z13, [sp, #7, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: str z14, [sp, #8, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: str z15, [sp, #9, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: str z16, [sp, #10, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: str z17, [sp, #11, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: str z18, [sp, #12, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: str z19, [sp, #13, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: str z20, [sp, #14, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: str z21, [sp, #15, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: str z22, [sp, #16, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: str z23, [sp, #17, mul vl] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: str x28, [sp, #-32]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x28, 32 +; CHECK-NEXT: stp x29, x30, [sp, #8] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 8 +; CHECK-NEXT: add x29, sp, #8 +; CHECK-NEXT: .seh_add_fp 8 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: sub x1, x29, #8 +; CHECK-NEXT: mov x0, sp +; CHECK-NEXT: addvl x1, x1, #-1 +; CHECK-NEXT: bl g10 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldp x29, x30, [sp, #8] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 8 +; CHECK-NEXT: ldr x28, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 0 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: ldr z8, [sp, #2, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 2 +; CHECK-NEXT: ldr z9, [sp, #3, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z9, 3 +; CHECK-NEXT: ldr z10, [sp, #4, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z10, 4 +; CHECK-NEXT: ldr z11, [sp, #5, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z11, 5 +; CHECK-NEXT: ldr z12, [sp, #6, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z12, 6 +; CHECK-NEXT: ldr z13, [sp, #7, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z13, 7 +; CHECK-NEXT: ldr z14, [sp, #8, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z14, 8 +; CHECK-NEXT: ldr z15, [sp, #9, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z15, 9 +; CHECK-NEXT: ldr z16, [sp, #10, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z16, 10 +; CHECK-NEXT: ldr z17, [sp, #11, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z17, 11 +; CHECK-NEXT: ldr z18, [sp, #12, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z18, 12 +; CHECK-NEXT: ldr z19, [sp, #13, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z19, 13 +; CHECK-NEXT: ldr z20, [sp, #14, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z20, 14 +; CHECK-NEXT: ldr z21, [sp, #15, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z21, 15 +; CHECK-NEXT: ldr z22, [sp, #16, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z22, 16 +; CHECK-NEXT: ldr z23, [sp, #17, mul vl] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z23, 17 +; CHECK-NEXT: ldr p4, [sp] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p4, 0 +; CHECK-NEXT: ldr p5, [sp, #1, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p5, 1 +; CHECK-NEXT: ldr p6, [sp, #2, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p6, 2 +; CHECK-NEXT: ldr p7, [sp, #3, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p7, 3 +; CHECK-NEXT: ldr p8, [sp, #4, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p8, 4 +; CHECK-NEXT: ldr p9, [sp, #5, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p9, 5 +; CHECK-NEXT: ldr p10, [sp, #6, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p10, 6 +; CHECK-NEXT: ldr p11, [sp, #7, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p11, 7 +; CHECK-NEXT: ldr p12, [sp, #8, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p12, 8 +; CHECK-NEXT: ldr p13, [sp, #9, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p13, 9 +; CHECK-NEXT: ldr p14, [sp, #10, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p14, 10 +; CHECK-NEXT: ldr p15, [sp, #11, mul vl] // 2-byte Folded Reload +; CHECK-NEXT: .seh_save_preg p15, 11 +; CHECK-NEXT: addvl sp, sp, #18 +; CHECK-NEXT: .seh_allocz 18 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %p1 = alloca [2 x i64] + %p2 = alloca + call void @g10(ptr %p1, ptr %p2) + ret void +} + +; Check handling of alloca allocated into CSR space, no frame pointer. +define i32 @f11(double %d, %vs) "aarch64_pstate_sm_compatible" { +; CHECK-LABEL: f11: +; CHECK: .seh_proc f11 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: str z8, [sp] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: str d0, [sp, #8] +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldr x30, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %a = alloca double + tail call void asm sideeffect "", "~{d8}"() #1 + store double %d, ptr %a + ret i32 0 +} + +define i32 @f12(double %d, %vs) "aarch64_pstate_sm_compatible" { +; CHECK-LABEL: f12: +; CHECK: .seh_proc f12 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: str z8, [sp] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x30, 16 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: addvl x8, sp, #1 +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: str d0, [x8, #8] +; CHECK-NEXT: str d0, [sp] +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: ldr x30, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %a = alloca double + %b = alloca + tail call void asm sideeffect "", "~{d8}"() #1 + store double %d, ptr %a + store double %d, ptr %b + ret i32 0 +} + +; Check handling of alloca allocated into CSR space, with frame pointer. +define i32 @f13(double %d, %vs) "frame-pointer"="all" { +; CHECK-LABEL: f13: +; CHECK: .seh_proc f13 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: str z8, [sp] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: str x28, [sp, #-32]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x28, 32 +; CHECK-NEXT: stp x29, x30, [sp, #8] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 8 +; CHECK-NEXT: add x29, sp, #8 +; CHECK-NEXT: .seh_add_fp 8 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: str d0, [x29, #16] +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldp x29, x30, [sp, #8] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 8 +; CHECK-NEXT: ldr x28, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 0 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: ldr z8, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %a = alloca double + tail call void asm sideeffect "", "~{d8},~{x28}"() #1 + store double %d, ptr %a + ret i32 0 +} + +define i32 @f14(double %d, %vs) "frame-pointer"="all" { +; CHECK-LABEL: f14: +; CHECK: .seh_proc f14 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: str z8, [sp] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: str x28, [sp, #-32]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x28, 32 +; CHECK-NEXT: stp x29, x30, [sp, #8] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr 8 +; CHECK-NEXT: add x29, sp, #8 +; CHECK-NEXT: .seh_add_fp 8 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: addvl x8, x29, #-1 +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: str d0, [x29, #16] +; CHECK-NEXT: stur d0, [x8, #-8] +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: ldp x29, x30, [sp, #8] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr 8 +; CHECK-NEXT: ldr x28, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 0 +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: .seh_stackalloc 32 +; CHECK-NEXT: ldr z8, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc +entry: + %a = alloca double + %b = alloca + tail call void asm sideeffect "", "~{d8},~{x28}"() #1 + store double %d, ptr %a + store double %d, ptr %b + ret i32 0 +} + +define tailcc void @f15(double %d, %vs, [9 x i64], i32 %i) { +; CHECK-LABEL: f15: +; CHECK: .seh_proc f15 +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: str z8, [sp] // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: str x28, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg_x x28, 16 +; CHECK-NEXT: str x30, [sp, #8] // 8-byte Folded Spill +; CHECK-NEXT: .seh_save_reg x30, 8 +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: addvl sp, sp, #-1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: addvl x8, sp, #2 +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: stp d0, d0, [sp, #8] +; CHECK-NEXT: ldr w8, [x8, #104] +; CHECK-NEXT: str w8, [sp, #8] +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr x30, [sp, #8] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x30, 8 +; CHECK-NEXT: ldr x28, [sp] // 8-byte Folded Reload +; CHECK-NEXT: .seh_save_reg x28, 0 +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: .seh_stackalloc 16 +; CHECK-NEXT: ldr z8, [sp] // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_zreg z8, 0 +; CHECK-NEXT: addvl sp, sp, #1 +; CHECK-NEXT: .seh_allocz 1 +; CHECK-NEXT: add sp, sp, #80 +; CHECK-NEXT: .seh_stackalloc 80 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_endproc + %a = alloca double + %b = alloca + tail call void asm sideeffect "", "~{d8},~{x28}"() #1 + store double %d, ptr %a + store double %d, ptr %b + store i32 %i, ptr %a + ret void +}