diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 9adf758b46c48..4971281ec2388 100644 --- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -62,14 +62,16 @@ ARMBaseRegisterInfo::ARMBaseRegisterInfo() const MCPhysReg* ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { const ARMSubtarget &STI = MF->getSubtarget(); - bool UseSplitPush = STI.splitFramePushPop(*MF); + bool UseSplitPush = (STI.getPushPopSplitVariation(*MF) == + ARMSubtarget::PushPopSplitVariation::R7Split); const Function &F = MF->getFunction(); if (F.getCallingConv() == CallingConv::GHC) { // GHC set of callee saved regs is empty as all those regs are // used for passing STG regs around return CSR_NoRegs_SaveList; - } else if (STI.splitFramePointerPush(*MF)) { + } else if (STI.getPushPopSplitVariation(*MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { return CSR_Win_SplitFP_SaveList; } else if (F.getCallingConv() == CallingConv::CFGuard_Check) { return CSR_Win_AAPCS_CFGuard_Check_SaveList; diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 9b54dd4e4e618..d251ad5543baf 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -718,9 +718,14 @@ static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI, // This is a conservative estimation: Assume the frame pointer being r7 and // pc("r15") up to r8 getting spilled before (= 8 registers). int MaxRegBytes = 8 * 4; - if (STI.splitFramePointerPush(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning) // Here, r11 can be stored below all of r4-r15 (3 registers more than - // above), plus d8-d15. + // above). + MaxRegBytes = 11 * 4; + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { + // Here, r11 can be stored below all of r4-r15 plus d8-d15. MaxRegBytes = 11 * 4 + 8 * 8; } int FPCXTSaveSize = @@ -788,7 +793,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, } // Determine spill area sizes. - if (STI.splitFramePointerPush(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning || + STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { for (const CalleeSavedInfo &I : CSI) { Register Reg = I.getReg(); int FI = I.getFrameIdx(); @@ -834,7 +842,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, case ARM::R10: case ARM::R11: case ARM::R12: - if (STI.splitFramePushPop(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R7Split) { GPRCS2Size += 4; break; } @@ -897,13 +906,15 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size; Align DPRAlign = DPRCSSize ? std::min(Align(8), Alignment) : Align(4); unsigned DPRGapSize = GPRCS1Size + FPCXTSaveSize + ArgRegsSaveSize; - if (!STI.splitFramePointerPush(MF)) { + if (STI.getPushPopSplitVariation(MF) != + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { DPRGapSize += GPRCS2Size; } DPRGapSize %= DPRAlign.value(); unsigned DPRCSOffset; - if (STI.splitFramePointerPush(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { DPRCSOffset = GPRCS1Offset - DPRGapSize - DPRCSSize; GPRCS2Offset = DPRCSOffset - GPRCS2Size; } else { @@ -922,8 +933,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); - // Move past area 2. - if (GPRCS2Size > 0 && !STI.splitFramePointerPush(MF)) { + // Move past area 2, unless following the CSR_Win_SplitFP calling convention. + if (GPRCS2Size > 0 && + STI.getPushPopSplitVariation(MF) != + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { GPRCS2Push = LastPush = MBBI++; DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size); } @@ -963,13 +976,18 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, } else NumBytes = DPRCSOffset; - if (GPRCS2Size > 0 && STI.splitFramePointerPush(MF)) { + // Move past area 2 if following the CSR_Win_SplitFP calling convention. + if (GPRCS2Size > 0 && + STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { GPRCS2Push = LastPush = MBBI++; DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size); } bool NeedsWinCFIStackAlloc = NeedsWinCFI; - if (STI.splitFramePointerPush(MF) && HasFP) + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind && + HasFP) NeedsWinCFIStackAlloc = false; if (STI.isTargetWindows() && WindowsRequiresStackProbe(MF, NumBytes)) { @@ -1074,7 +1092,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, AfterPush = std::next(GPRCS1Push); unsigned PushSize = sizeOfSPAdjustment(*GPRCS1Push); int FPOffset = PushSize + FramePtrOffsetInPush; - if (STI.splitFramePointerPush(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning || + STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { AfterPush = std::next(GPRCS2Push); emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII, FramePtr, ARM::SP, 0, MachineInstr::FrameSetup); @@ -1106,7 +1127,9 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, // instructions below don't need to be replayed to unwind the stack. if (NeedsWinCFI && MBBI != MBB.begin()) { MachineBasicBlock::iterator End = MBBI; - if (HasFP && STI.splitFramePointerPush(MF)) + if (HasFP && + STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) End = AfterPush; insertSEHRange(MBB, {}, End, TII, MachineInstr::FrameSetup); BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd)) @@ -1118,51 +1141,103 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, // the necessary DWARF cf instructions to describe the situation. Start by // recording where each register ended up: if (GPRCS1Size > 0 && !NeedsWinCFI) { - MachineBasicBlock::iterator Pos = std::next(GPRCS1Push); - int CFIIndex; - for (const auto &Entry : CSI) { - Register Reg = Entry.getReg(); - int FI = Entry.getFrameIdx(); - switch (Reg) { - case ARM::R8: - case ARM::R9: - case ARM::R10: - case ARM::R11: - case ARM::R12: - if (STI.splitFramePushPop(MF)) + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning) { + MachineBasicBlock::iterator Pos = std::next(GPRCS1Push); + int CFIIndex; + for (const auto &Entry : CSI) { + Register Reg = Entry.getReg(); + int FI = Entry.getFrameIdx(); + switch (Reg) { + case ARM::R0: + case ARM::R1: + case ARM::R2: + case ARM::R3: + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R12: + CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( + nullptr, MRI->getDwarfRegNum(Reg, true), + MFI.getObjectOffset(FI))); + BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); break; - [[fallthrough]]; - case ARM::R0: - case ARM::R1: - case ARM::R2: - case ARM::R3: - case ARM::R4: - case ARM::R5: - case ARM::R6: - case ARM::R7: - case ARM::LR: - CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( - nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); - BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlags(MachineInstr::FrameSetup); - break; + } + } + } else { + MachineBasicBlock::iterator Pos = std::next(GPRCS1Push); + int CFIIndex; + for (const auto &Entry : CSI) { + Register Reg = Entry.getReg(); + int FI = Entry.getFrameIdx(); + switch (Reg) { + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + case ARM::R12: + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R7Split) + break; + [[fallthrough]]; + case ARM::R0: + case ARM::R1: + case ARM::R2: + case ARM::R3: + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + case ARM::LR: + CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( + nullptr, MRI->getDwarfRegNum(Reg, true), + MFI.getObjectOffset(FI))); + BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); + break; + } } } } if (GPRCS2Size > 0 && !NeedsWinCFI) { MachineBasicBlock::iterator Pos = std::next(GPRCS2Push); - for (const auto &Entry : CSI) { - Register Reg = Entry.getReg(); - int FI = Entry.getFrameIdx(); - switch (Reg) { - case ARM::R8: - case ARM::R9: - case ARM::R10: - case ARM::R11: - case ARM::R12: - if (STI.splitFramePushPop(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning) { + for (const auto &Entry : CSI) { + Register Reg = Entry.getReg(); + int FI = Entry.getFrameIdx(); + switch (Reg) { + case ARM::R11: + case ARM::LR: + unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); + unsigned Offset = MFI.getObjectOffset(FI); + unsigned CFIIndex = MF.addFrameInst( + MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); + BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); + break; + } + } + } else { + MachineBasicBlock::iterator Pos = std::next(GPRCS2Push); + for (const auto &Entry : CSI) { + Register Reg = Entry.getReg(); + int FI = Entry.getFrameIdx(); + switch (Reg) { + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + case ARM::R12: unsigned DwarfReg = MRI->getDwarfRegNum( Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true); unsigned Offset = MFI.getObjectOffset(FI); @@ -1171,8 +1246,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF, BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); + break; } - break; } } } @@ -1382,7 +1457,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, MachineInstr::FrameDestroy); // Increment past our save areas. - if (AFI->getGPRCalleeSavedArea2Size() && STI.splitFramePointerPush(MF)) + if (AFI->getGPRCalleeSavedArea2Size() && + STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) MBBI++; if (MBBI != MBB.end() && AFI->getDPRCalleeSavedAreaSize()) { @@ -1399,7 +1476,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, MachineInstr::FrameDestroy); } - if (AFI->getGPRCalleeSavedArea2Size() && !STI.splitFramePointerPush(MF)) + if (AFI->getGPRCalleeSavedArea2Size() && + STI.getPushPopSplitVariation(MF) != + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) MBBI++; if (AFI->getGPRCalleeSavedArea1Size()) MBBI++; @@ -1539,7 +1618,9 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, unsigned LastReg = 0; for (; i != 0; --i) { Register Reg = CSI[i-1].getReg(); - if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue; + if (!(Func)(Reg, STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R7Split)) + continue; // D-registers in the aligned area DPRCS2 are NOT spilled here. if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs) @@ -1632,7 +1713,9 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, for (; i != 0; --i) { CalleeSavedInfo &Info = CSI[i-1]; Register Reg = Info.getReg(); - if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue; + if (!(Func)(Reg, STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R7Split)) + continue; // The aligned reloads from area DPRCS2 are not inserted here. if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs) @@ -1640,7 +1723,11 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt && !isCmseEntry && !isTrap && AFI->getArgumentStackToRestore() == 0 && STI.hasV5TOps() && MBB.succ_empty() && !hasPAC && - !STI.splitFramePointerPush(MF)) { + (STI.getPushPopSplitVariation(MF) != + ARMSubtarget::PushPopSplitVariation:: + R11SplitAAPCSBranchSigning && + STI.getPushPopSplitVariation(MF) != + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind)) { Reg = ARM::PC; // Fold the return instruction into the LDM. DeleteRet = true; @@ -2001,7 +2088,10 @@ bool ARMFrameLowering::spillCalleeSavedRegisters( .addImm(-4) .add(predOps(ARMCC::AL)); } - if (STI.splitFramePointerPush(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning || + STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isSplitFPArea1Register, 0, MachineInstr::FrameSetup); emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register, @@ -2046,7 +2136,10 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters( unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM; unsigned FltOpc = ARM::VLDMDIA_UPD; - if (STI.splitFramePointerPush(MF)) { + if (STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitAAPCSBranchSigning || + STI.getPushPopSplitVariation(MF) == + ARMSubtarget::PushPopSplitVariation::R11SplitWindowsSEHUnwind) { emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, &isSplitFPArea2Register, 0); emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register, @@ -2362,7 +2455,8 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF, if (Spilled) { NumGPRSpills++; - if (!STI.splitFramePushPop(MF)) { + if (STI.getPushPopSplitVariation(MF) != + ARMSubtarget::PushPopSplitVariation::R7Split) { if (Reg == ARM::LR) LRSpilled = true; CS1Spilled = true; @@ -2384,7 +2478,8 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF, break; } } else { - if (!STI.splitFramePushPop(MF)) { + if (STI.getPushPopSplitVariation(MF) != + ARMSubtarget::PushPopSplitVariation::R7Split) { UnspilledCS1GPRs.push_back(Reg); continue; } diff --git a/llvm/lib/Target/ARM/ARMSubtarget.cpp b/llvm/lib/Target/ARM/ARMSubtarget.cpp index 691715dc29637..b9e63ab3afc53 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.cpp +++ b/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -493,11 +493,38 @@ bool ARMSubtarget::ignoreCSRForAllocationOrder(const MachineFunction &MF, ARM::GPRRegClass.contains(PhysReg); } -bool ARMSubtarget::splitFramePointerPush(const MachineFunction &MF) const { +ARMSubtarget::PushPopSplitVariation +ARMSubtarget::getPushPopSplitVariation(const MachineFunction &MF) const { const Function &F = MF.getFunction(); - if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI() || - !F.needsUnwindTableEntry()) - return false; const MachineFrameInfo &MFI = MF.getFrameInfo(); - return MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF); + const std::vector CSI = + MF.getFrameInfo().getCalleeSavedInfo(); + // Returns R7Split if the frame setup must be split into two separate pushes + // of r0-r7,lr and another containing r8-r11 (+r12 if necessary). This is + // always required on Thumb1-only targets, as the push and pop instructions + // can't access the high registers. This is also required when R7 is the frame + // pointer and frame pointer elimiination is disabled, or branch signing is + // enabled and AAPCS is disabled. + if ((MF.getInfo()->shouldSignReturnAddress() && + !createAAPCSFrameChain()) || + (getFramePointerReg() == ARM::R7 && + MF.getTarget().Options.DisableFramePointerElim(MF)) || + isThumb1Only()) + return R7Split; + // Returns R11SplitWindowsSEHUnwind when the stack pointer needs to be + // restored from the frame pointer r11 + an offset and Windows CFI is enabled. + // This stack unwinding cannot be expressed with SEH unwind opcodes when done + // with a single push, making it necessary to split the push into r4-r10, and + // another containing r11+lr. + if (MF.getTarget().getMCAsmInfo()->usesWindowsCFI() && + F.needsUnwindTableEntry() && + (MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF))) + return R11SplitWindowsSEHUnwind; + // Returns R11SplitAAPCSBranchSigning if R11 and lr are not adjacent to each + // other in the list of callee saved registers in a frame, and branch + // signing is enabled. + if (MF.getInfo()->shouldSignReturnAddress() && + getFramePointerReg() == ARM::R11) + return R11SplitAAPCSBranchSigning; + return NoSplit; } diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h index 044b1c4c54e0c..435a2d2c5f1eb 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -150,6 +150,26 @@ class ARMSubtarget : public ARMGenSubtargetInfo { SingleIssuePlusExtras, }; + /// How the pushing and popping of callee saved registers to and from the + /// stack should be split. + enum PushPopSplitVariation { + /// r4-r11+lr (+r12 if necessary) can be pushed in a single instruction. + NoSplit, + /// The registers need to be split into a push of r4-r7+lr and another + /// containing r8-r11 (+r12 if necessary). Due to Thumb1FrameLowering + /// having separate handling of AAPCS being enabled, and therefore r11+lr + /// needing to be in a separate push, this value is also used as the push + /// variation in that case. + R7Split, + /// The registers need to be split into a push containing r4-r10+r12 and + /// another containing r11 + lr. + R11SplitAAPCSBranchSigning, + /// The registers need to be split into a push containing r4-r10 and another + /// containing r11 + lr. In this case, the floating point registers are + /// pushed between these two pushes. + R11SplitWindowsSEHUnwind + }; + protected: // Bool members corresponding to the SubtargetFeatures defined in tablegen #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ @@ -447,19 +467,8 @@ class ARMSubtarget : public ARMGenSubtargetInfo { return ARM::R11; } - /// Returns true if the frame setup is split into two separate pushes (first - /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent - /// to lr. This is always required on Thumb1-only targets, as the push and - /// pop instructions can't access the high registers. - bool splitFramePushPop(const MachineFunction &MF) const { - if (MF.getInfo()->shouldSignReturnAddress()) - return true; - return (getFramePointerReg() == ARM::R7 && - MF.getTarget().Options.DisableFramePointerElim(MF)) || - isThumb1Only(); - } - - bool splitFramePointerPush(const MachineFunction &MF) const; + enum PushPopSplitVariation + getPushPopSplitVariation(const MachineFunction &MF) const; bool useStride4VFPs() const; diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp index 0f4ece64bff53..f1558e64ed3ee 100644 --- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -222,11 +222,8 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, case ARM::R8: case ARM::R9: case ARM::R10: - if (STI.splitFramePushPop(MF)) { - GPRCS2Size += 4; - break; - } - [[fallthrough]]; + GPRCS2Size += 4; + break; case ARM::LR: if (HasFrameRecordArea) { FRSize += 4; @@ -361,14 +358,6 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF, Register Reg = I.getReg(); int FI = I.getFrameIdx(); switch (Reg) { - case ARM::R8: - case ARM::R9: - case ARM::R10: - case ARM::R11: - case ARM::R12: - if (STI.splitFramePushPop(MF)) - break; - [[fallthrough]]; case ARM::R0: case ARM::R1: case ARM::R2: diff --git a/llvm/test/CodeGen/Thumb2/pacbti-m-frame-chain.ll b/llvm/test/CodeGen/Thumb2/pacbti-m-frame-chain.ll new file mode 100644 index 0000000000000..77759355e576a --- /dev/null +++ b/llvm/test/CodeGen/Thumb2/pacbti-m-frame-chain.ll @@ -0,0 +1,82 @@ +; RUN: llc -filetype asm -o - %s --frame-pointer=all -mattr=+aapcs-frame-chain -mattr=+aapcs-frame-chain-leaf -force-dwarf-frame-section | FileCheck %s +target triple = "thumbv8m.main-none-none-eabi" + +; int f() { +; return 0; +; } +; +; int x(int, char *); +; int y(int n) { +; char a[n]; +; return 1 + x(n, a); +; } + +define hidden i32 @f() local_unnamed_addr { +entry: + ret i32 0; +} + +define hidden i32 @x(i32 noundef %n) local_unnamed_addr { +entry: + %vla = alloca i8, i32 %n, align 1 + %call = call i32 @y(i32 noundef %n, ptr noundef nonnull %vla) + %add = add nsw i32 %call, 1 + ret i32 %add +} + +declare dso_local i32 @y(i32 noundef, ptr noundef) local_unnamed_addr + +; CHECK-LABEL: f: +; CHECK: pac r12, lr, sp +; CHECK-NEXT: .save {ra_auth_code} +; CHECK-NEXT: str r12, [sp, #-4]! +; CHECK-NEXT: .cfi_def_cfa_offset 4 +; CHECK-NEXT: .cfi_offset r12, -8 +; CHECK-NEXT: .save {r11, lr} +; CHECK-NEXT: push.w {r11, lr} +; CHECK-NEXT: .cfi_offset lr, -4 +; CHECK-NEXT: .cfi_offset r11, -12 +; CHECK-NEXT: .setfp r11, sp +; CHECK-NEXT: mov r11, sp +; CHECK-NEXT: .cfi_def_cfa r11, 12 +; CHECK-NEXT: movs r0, #0 +; CHECK-NEXT: pop.w {r11, lr} +; CHECK-NEXT: ldr r12, [sp], #4 +; CHECK-NEXT: aut r12, lr, sp +; CHECK-NEXT: bx lr + +; CHECK-LABEL: x: +; CHECK: pac r12, lr, sp +; CHECK-NEXT: .save {r4, r7, ra_auth_code} +; CHECK-NEXT: push.w {r4, r7, r12} +; CHECK-NEXT: .cfi_def_cfa_offset 12 +; CHECK-NEXT: .cfi_offset r12, -8 +; CHECK-NEXT: .cfi_offset r7, -16 +; CHECK-NEXT: .cfi_offset r4, -20 +; CHECK-NEXT: .save {r11, lr} +; CHECK-NEXT: push.w {r11, lr} +; CHECK-NEXT: .cfi_offset lr, -4 +; CHECK-NEXT: .cfi_offset r11, -12 +; CHECK-NEXT: .setfp r11, sp +; CHECK-NEXT: mov r11, sp +; CHECK-NEXT: .cfi_def_cfa_register r11 +; CHECK-NEXT: .pad #4 +; CHECK-NEXT: sub sp, #4 +; CHECK-NEXT: adds r1, r0, #7 +; CHECK-NEXT: bic r1, r1, #7 +; CHECK-NEXT: sub.w r1, sp, r1 +; CHECK-NEXT: mov sp, r1 +; CHECK-NEXT: bl y +; CHECK-NEXT: sub.w r4, r11, #8 +; CHECK-NEXT: adds r0, #1 +; CHECK-NEXT: mov sp, r4 +; CHECK-NEXT: pop.w {r11, lr} +; CHECK-NEXT: pop.w {r4, r7, r12} +; CHECK-NEXT: aut r12, lr, sp +; CHECK-NEXT: bx lr + +!llvm.module.flags = !{!0, !1, !2} + +!0 = !{i32 8, !"sign-return-address", i32 1} +!1 = !{i32 8, !"sign-return-address-all", i32 0} +!2 = !{i32 8, !"branch-target-enforcement", i32 0}