10b57cec5SDimitry Andric //===- ARMFrameLowering.cpp - ARM Frame Information -----------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the ARM implementation of TargetFrameLowering class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12fe6060f1SDimitry Andric // 13fe6060f1SDimitry Andric // This file contains the ARM implementation of TargetFrameLowering class. 14fe6060f1SDimitry Andric // 15fe6060f1SDimitry Andric // On ARM, stack frames are structured as follows: 16fe6060f1SDimitry Andric // 17fe6060f1SDimitry Andric // The stack grows downward. 18fe6060f1SDimitry Andric // 19fe6060f1SDimitry Andric // All of the individual frame areas on the frame below are optional, i.e. it's 20fe6060f1SDimitry Andric // possible to create a function so that the particular area isn't present 21fe6060f1SDimitry Andric // in the frame. 22fe6060f1SDimitry Andric // 23fe6060f1SDimitry Andric // At function entry, the "frame" looks as follows: 24fe6060f1SDimitry Andric // 25fe6060f1SDimitry Andric // | | Higher address 26fe6060f1SDimitry Andric // |-----------------------------------| 27fe6060f1SDimitry Andric // | | 28fe6060f1SDimitry Andric // | arguments passed on the stack | 29fe6060f1SDimitry Andric // | | 30fe6060f1SDimitry Andric // |-----------------------------------| <- sp 31fe6060f1SDimitry Andric // | | Lower address 32fe6060f1SDimitry Andric // 33fe6060f1SDimitry Andric // 34fe6060f1SDimitry Andric // After the prologue has run, the frame has the following general structure. 35fe6060f1SDimitry Andric // Technically the last frame area (VLAs) doesn't get created until in the 36fe6060f1SDimitry Andric // main function body, after the prologue is run. However, it's depicted here 37fe6060f1SDimitry Andric // for completeness. 38fe6060f1SDimitry Andric // 39fe6060f1SDimitry Andric // | | Higher address 40fe6060f1SDimitry Andric // |-----------------------------------| 41fe6060f1SDimitry Andric // | | 42fe6060f1SDimitry Andric // | arguments passed on the stack | 43fe6060f1SDimitry Andric // | | 44fe6060f1SDimitry Andric // |-----------------------------------| <- (sp at function entry) 45fe6060f1SDimitry Andric // | | 46fe6060f1SDimitry Andric // | varargs from registers | 47fe6060f1SDimitry Andric // | | 48fe6060f1SDimitry Andric // |-----------------------------------| 49fe6060f1SDimitry Andric // | | 5081ad6265SDimitry Andric // | prev_lr | 5181ad6265SDimitry Andric // | prev_fp | 52fe6060f1SDimitry Andric // | (a.k.a. "frame record") | 53fe6060f1SDimitry Andric // | | 54fe6060f1SDimitry Andric // |- - - - - - - - - - - - - - - - - -| <- fp (r7 or r11) 55fe6060f1SDimitry Andric // | | 56fe6060f1SDimitry Andric // | callee-saved gpr registers | 57fe6060f1SDimitry Andric // | | 58fe6060f1SDimitry Andric // |-----------------------------------| 59fe6060f1SDimitry Andric // | | 60fe6060f1SDimitry Andric // | callee-saved fp/simd regs | 61fe6060f1SDimitry Andric // | | 62fe6060f1SDimitry Andric // |-----------------------------------| 63fe6060f1SDimitry Andric // |.empty.space.to.make.part.below....| 64fe6060f1SDimitry Andric // |.aligned.in.case.it.needs.more.than| (size of this area is unknown at 65fe6060f1SDimitry Andric // |.the.standard.8-byte.alignment.....| compile time; if present) 66fe6060f1SDimitry Andric // |-----------------------------------| 67fe6060f1SDimitry Andric // | | 68fe6060f1SDimitry Andric // | local variables of fixed size | 69fe6060f1SDimitry Andric // | including spill slots | 70fe6060f1SDimitry Andric // |-----------------------------------| <- base pointer (not defined by ABI, 71fe6060f1SDimitry Andric // |.variable-sized.local.variables....| LLVM chooses r6) 72fe6060f1SDimitry Andric // |.(VLAs)............................| (size of this area is unknown at 73fe6060f1SDimitry Andric // |...................................| compile time) 74fe6060f1SDimitry Andric // |-----------------------------------| <- sp 75fe6060f1SDimitry Andric // | | Lower address 76fe6060f1SDimitry Andric // 77fe6060f1SDimitry Andric // 78fe6060f1SDimitry Andric // To access the data in a frame, at-compile time, a constant offset must be 79fe6060f1SDimitry Andric // computable from one of the pointers (fp, bp, sp) to access it. The size 80fe6060f1SDimitry Andric // of the areas with a dotted background cannot be computed at compile-time 81fe6060f1SDimitry Andric // if they are present, making it required to have all three of fp, bp and 82fe6060f1SDimitry Andric // sp to be set up to be able to access all contents in the frame areas, 83fe6060f1SDimitry Andric // assuming all of the frame areas are non-empty. 84fe6060f1SDimitry Andric // 85fe6060f1SDimitry Andric // For most functions, some of the frame areas are empty. For those functions, 86fe6060f1SDimitry Andric // it may not be necessary to set up fp or bp: 87fe6060f1SDimitry Andric // * A base pointer is definitely needed when there are both VLAs and local 88fe6060f1SDimitry Andric // variables with more-than-default alignment requirements. 89fe6060f1SDimitry Andric // * A frame pointer is definitely needed when there are local variables with 90fe6060f1SDimitry Andric // more-than-default alignment requirements. 91fe6060f1SDimitry Andric // 92fe6060f1SDimitry Andric // In some cases when a base pointer is not strictly needed, it is generated 93fe6060f1SDimitry Andric // anyway when offsets from the frame pointer to access local variables become 94fe6060f1SDimitry Andric // so large that the offset can't be encoded in the immediate fields of loads 95fe6060f1SDimitry Andric // or stores. 96fe6060f1SDimitry Andric // 97fe6060f1SDimitry Andric // The frame pointer might be chosen to be r7 or r11, depending on the target 98fe6060f1SDimitry Andric // architecture and operating system. See ARMSubtarget::getFramePointerReg for 99fe6060f1SDimitry Andric // details. 100fe6060f1SDimitry Andric // 101fe6060f1SDimitry Andric // Outgoing function arguments must be at the bottom of the stack frame when 102fe6060f1SDimitry Andric // calling another function. If we do not have variable-sized stack objects, we 103fe6060f1SDimitry Andric // can allocate a "reserved call frame" area at the bottom of the local 104fe6060f1SDimitry Andric // variable area, large enough for all outgoing calls. If we do have VLAs, then 105fe6060f1SDimitry Andric // the stack pointer must be decremented and incremented around each call to 106fe6060f1SDimitry Andric // make space for the arguments below the VLAs. 107fe6060f1SDimitry Andric // 108fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric #include "ARMFrameLowering.h" 1110b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h" 1120b57cec5SDimitry Andric #include "ARMBaseRegisterInfo.h" 1130b57cec5SDimitry Andric #include "ARMConstantPoolValue.h" 1140b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h" 1150b57cec5SDimitry Andric #include "ARMSubtarget.h" 1160b57cec5SDimitry Andric #include "MCTargetDesc/ARMAddressingModes.h" 1170b57cec5SDimitry Andric #include "MCTargetDesc/ARMBaseInfo.h" 1180b57cec5SDimitry Andric #include "Utils/ARMBaseInfo.h" 1190b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 1200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 1210b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 1220b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 1230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 1240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 1250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 1260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 1270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 1280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 1290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 1300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 1310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 1320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 1330b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 1340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 1350b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 1360b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 1370b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 1380b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 1390b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h" 1400b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 1410b57cec5SDimitry Andric #include "llvm/IR/Function.h" 14281ad6265SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 1430b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 1440b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h" 1450b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 1460b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 1470b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 1480b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 1490b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 1500b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 1510b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 1520b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 1530b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 1540b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 1550b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 1560b57cec5SDimitry Andric #include <algorithm> 1570b57cec5SDimitry Andric #include <cassert> 1580b57cec5SDimitry Andric #include <cstddef> 1590b57cec5SDimitry Andric #include <cstdint> 1600b57cec5SDimitry Andric #include <iterator> 1610b57cec5SDimitry Andric #include <utility> 1620b57cec5SDimitry Andric #include <vector> 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric #define DEBUG_TYPE "arm-frame-lowering" 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric using namespace llvm; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric static cl::opt<bool> 1690b57cec5SDimitry Andric SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true), 1700b57cec5SDimitry Andric cl::desc("Align ARM NEON spills in prolog and epilog")); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric static MachineBasicBlock::iterator 1730b57cec5SDimitry Andric skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, 1740b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric ARMFrameLowering::ARMFrameLowering(const ARMSubtarget &sti) 1778bcb0991SDimitry Andric : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, Align(4)), 1780b57cec5SDimitry Andric STI(sti) {} 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric bool ARMFrameLowering::keepFramePointer(const MachineFunction &MF) const { 1810b57cec5SDimitry Andric // iOS always has a FP for backtracking, force other targets to keep their FP 1820b57cec5SDimitry Andric // when doing FastISel. The emitted code is currently superior, and in cases 1830b57cec5SDimitry Andric // like test-suite's lencod FastISel isn't quite correct when FP is eliminated. 1840b57cec5SDimitry Andric return MF.getSubtarget<ARMSubtarget>().useFastISel(); 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric /// Returns true if the target can safely skip saving callee-saved registers 1880b57cec5SDimitry Andric /// for noreturn nounwind functions. 1890b57cec5SDimitry Andric bool ARMFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const { 1900b57cec5SDimitry Andric assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) && 1910b57cec5SDimitry Andric MF.getFunction().hasFnAttribute(Attribute::NoUnwind) && 1920b57cec5SDimitry Andric !MF.getFunction().hasFnAttribute(Attribute::UWTable)); 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric // Frame pointer and link register are not treated as normal CSR, thus we 1950b57cec5SDimitry Andric // can always skip CSR saves for nonreturning functions. 1960b57cec5SDimitry Andric return true; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric /// hasFP - Return true if the specified function should have a dedicated frame 2000b57cec5SDimitry Andric /// pointer register. This is true if the function has variable sized allocas 2010b57cec5SDimitry Andric /// or if frame pointer elimination is disabled. 2020b57cec5SDimitry Andric bool ARMFrameLowering::hasFP(const MachineFunction &MF) const { 2030b57cec5SDimitry Andric const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 2040b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // ABI-required frame pointer. 2070b57cec5SDimitry Andric if (MF.getTarget().Options.DisableFramePointerElim(MF)) 2080b57cec5SDimitry Andric return true; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric // Frame pointer required for use within this function. 211fe6060f1SDimitry Andric return (RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || 2120b57cec5SDimitry Andric MFI.isFrameAddressTaken()); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 21581ad6265SDimitry Andric /// isFPReserved - Return true if the frame pointer register should be 21681ad6265SDimitry Andric /// considered a reserved register on the scope of the specified function. 21781ad6265SDimitry Andric bool ARMFrameLowering::isFPReserved(const MachineFunction &MF) const { 2180fca6ea1SDimitry Andric return hasFP(MF) || MF.getTarget().Options.FramePointerIsReserved(MF); 21981ad6265SDimitry Andric } 22081ad6265SDimitry Andric 2210b57cec5SDimitry Andric /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is 2220b57cec5SDimitry Andric /// not required, we reserve argument space for call sites in the function 2230b57cec5SDimitry Andric /// immediately on entry to the current function. This eliminates the need for 2240b57cec5SDimitry Andric /// add/sub sp brackets around call sites. Returns true if the call frame is 2250b57cec5SDimitry Andric /// included as part of the stack frame. 2260b57cec5SDimitry Andric bool ARMFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 2270b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 2280b57cec5SDimitry Andric unsigned CFSize = MFI.getMaxCallFrameSize(); 2290b57cec5SDimitry Andric // It's not always a good idea to include the call frame as part of the 2300b57cec5SDimitry Andric // stack frame. ARM (especially Thumb) has small immediate offset to 2310b57cec5SDimitry Andric // address the stack frame. So a large call frame can cause poor codegen 2320b57cec5SDimitry Andric // and may even makes it impossible to scavenge a register. 2330b57cec5SDimitry Andric if (CFSize >= ((1 << 12) - 1) / 2) // Half of imm12 2340b57cec5SDimitry Andric return false; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric return !MFI.hasVarSizedObjects(); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric /// canSimplifyCallFramePseudos - If there is a reserved call frame, the 2400b57cec5SDimitry Andric /// call frame pseudos can be simplified. Unlike most targets, having a FP 2410b57cec5SDimitry Andric /// is not sufficient here since we still may reference some objects via SP 2420b57cec5SDimitry Andric /// even when FP is available in Thumb2 mode. 2430b57cec5SDimitry Andric bool 2440b57cec5SDimitry Andric ARMFrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const { 2450b57cec5SDimitry Andric return hasReservedCallFrame(MF) || MF.getFrameInfo().hasVarSizedObjects(); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 248fe6060f1SDimitry Andric // Returns how much of the incoming argument stack area we should clean up in an 249fe6060f1SDimitry Andric // epilogue. For the C calling convention this will be 0, for guaranteed tail 250fe6060f1SDimitry Andric // call conventions it can be positive (a normal return or a tail call to a 251fe6060f1SDimitry Andric // function that uses less stack space for arguments) or negative (for a tail 252fe6060f1SDimitry Andric // call to a function that needs more stack space than us for arguments). 253fe6060f1SDimitry Andric static int getArgumentStackToRestore(MachineFunction &MF, 254fe6060f1SDimitry Andric MachineBasicBlock &MBB) { 255fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 256fe6060f1SDimitry Andric bool IsTailCallReturn = false; 257fe6060f1SDimitry Andric if (MBB.end() != MBBI) { 258fe6060f1SDimitry Andric unsigned RetOpcode = MBBI->getOpcode(); 259fe6060f1SDimitry Andric IsTailCallReturn = RetOpcode == ARM::TCRETURNdi || 2600fca6ea1SDimitry Andric RetOpcode == ARM::TCRETURNri || 2610fca6ea1SDimitry Andric RetOpcode == ARM::TCRETURNrinotr12; 262fe6060f1SDimitry Andric } 263fe6060f1SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 264fe6060f1SDimitry Andric 265fe6060f1SDimitry Andric int ArgumentPopSize = 0; 266fe6060f1SDimitry Andric if (IsTailCallReturn) { 267fe6060f1SDimitry Andric MachineOperand &StackAdjust = MBBI->getOperand(1); 268fe6060f1SDimitry Andric 269fe6060f1SDimitry Andric // For a tail-call in a callee-pops-arguments environment, some or all of 270fe6060f1SDimitry Andric // the stack may actually be in use for the call's arguments, this is 271fe6060f1SDimitry Andric // calculated during LowerCall and consumed here... 272fe6060f1SDimitry Andric ArgumentPopSize = StackAdjust.getImm(); 273fe6060f1SDimitry Andric } else { 274fe6060f1SDimitry Andric // ... otherwise the amount to pop is *all* of the argument space, 275fe6060f1SDimitry Andric // conveniently stored in the MachineFunctionInfo by 276fe6060f1SDimitry Andric // LowerFormalArguments. This will, of course, be zero for the C calling 277fe6060f1SDimitry Andric // convention. 278fe6060f1SDimitry Andric ArgumentPopSize = AFI->getArgumentStackToRestore(); 279fe6060f1SDimitry Andric } 280fe6060f1SDimitry Andric 281fe6060f1SDimitry Andric return ArgumentPopSize; 282fe6060f1SDimitry Andric } 283fe6060f1SDimitry Andric 28481ad6265SDimitry Andric static bool needsWinCFI(const MachineFunction &MF) { 28581ad6265SDimitry Andric const Function &F = MF.getFunction(); 28681ad6265SDimitry Andric return MF.getTarget().getMCAsmInfo()->usesWindowsCFI() && 28781ad6265SDimitry Andric F.needsUnwindTableEntry(); 28881ad6265SDimitry Andric } 28981ad6265SDimitry Andric 29081ad6265SDimitry Andric // Given a load or a store instruction, generate an appropriate unwinding SEH 29181ad6265SDimitry Andric // code on Windows. 29281ad6265SDimitry Andric static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI, 29381ad6265SDimitry Andric const TargetInstrInfo &TII, 29481ad6265SDimitry Andric unsigned Flags) { 29581ad6265SDimitry Andric unsigned Opc = MBBI->getOpcode(); 29681ad6265SDimitry Andric MachineBasicBlock *MBB = MBBI->getParent(); 29781ad6265SDimitry Andric MachineFunction &MF = *MBB->getParent(); 29881ad6265SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 29981ad6265SDimitry Andric MachineInstrBuilder MIB; 30081ad6265SDimitry Andric const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>(); 30181ad6265SDimitry Andric const ARMBaseRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); 30281ad6265SDimitry Andric 30381ad6265SDimitry Andric Flags |= MachineInstr::NoMerge; 30481ad6265SDimitry Andric 30581ad6265SDimitry Andric switch (Opc) { 30681ad6265SDimitry Andric default: 30781ad6265SDimitry Andric report_fatal_error("No SEH Opcode for instruction " + TII.getName(Opc)); 30881ad6265SDimitry Andric break; 30981ad6265SDimitry Andric case ARM::t2ADDri: // add.w r11, sp, #xx 31081ad6265SDimitry Andric case ARM::t2ADDri12: // add.w r11, sp, #xx 31181ad6265SDimitry Andric case ARM::t2MOVTi16: // movt r4, #xx 31281ad6265SDimitry Andric case ARM::tBL: // bl __chkstk 31381ad6265SDimitry Andric // These are harmless if used for just setting up a frame pointer, 31481ad6265SDimitry Andric // but that frame pointer can't be relied upon for unwinding, unless 31581ad6265SDimitry Andric // set up with SEH_SaveSP. 31681ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop)) 31781ad6265SDimitry Andric .addImm(/*Wide=*/1) 31881ad6265SDimitry Andric .setMIFlags(Flags); 31981ad6265SDimitry Andric break; 32081ad6265SDimitry Andric 32181ad6265SDimitry Andric case ARM::t2MOVi16: { // mov(w) r4, #xx 32281ad6265SDimitry Andric bool Wide = MBBI->getOperand(1).getImm() >= 256; 32381ad6265SDimitry Andric if (!Wide) { 32481ad6265SDimitry Andric MachineInstrBuilder NewInstr = 32581ad6265SDimitry Andric BuildMI(MF, DL, TII.get(ARM::tMOVi8)).setMIFlags(MBBI->getFlags()); 32681ad6265SDimitry Andric NewInstr.add(MBBI->getOperand(0)); 32781ad6265SDimitry Andric NewInstr.add(t1CondCodeOp(/*isDead=*/true)); 32806c3fb27SDimitry Andric for (MachineOperand &MO : llvm::drop_begin(MBBI->operands())) 32906c3fb27SDimitry Andric NewInstr.add(MO); 33081ad6265SDimitry Andric MachineBasicBlock::iterator NewMBBI = MBB->insertAfter(MBBI, NewInstr); 33181ad6265SDimitry Andric MBB->erase(MBBI); 33281ad6265SDimitry Andric MBBI = NewMBBI; 33381ad6265SDimitry Andric } 33481ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop)).addImm(Wide).setMIFlags(Flags); 33581ad6265SDimitry Andric break; 33681ad6265SDimitry Andric } 33781ad6265SDimitry Andric 33881ad6265SDimitry Andric case ARM::tBLXr: // blx r12 (__chkstk) 33981ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop)) 34081ad6265SDimitry Andric .addImm(/*Wide=*/0) 34181ad6265SDimitry Andric .setMIFlags(Flags); 34281ad6265SDimitry Andric break; 34381ad6265SDimitry Andric 34481ad6265SDimitry Andric case ARM::t2MOVi32imm: // movw+movt 34581ad6265SDimitry Andric // This pseudo instruction expands into two mov instructions. If the 34681ad6265SDimitry Andric // second operand is a symbol reference, this will stay as two wide 34781ad6265SDimitry Andric // instructions, movw+movt. If they're immediates, the first one can 34881ad6265SDimitry Andric // end up as a narrow mov though. 34981ad6265SDimitry Andric // As two SEH instructions are appended here, they won't get interleaved 35081ad6265SDimitry Andric // between the two final movw/movt instructions, but it doesn't make any 35181ad6265SDimitry Andric // practical difference. 35281ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop)) 35381ad6265SDimitry Andric .addImm(/*Wide=*/1) 35481ad6265SDimitry Andric .setMIFlags(Flags); 35581ad6265SDimitry Andric MBB->insertAfter(MBBI, MIB); 35681ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop)) 35781ad6265SDimitry Andric .addImm(/*Wide=*/1) 35881ad6265SDimitry Andric .setMIFlags(Flags); 35981ad6265SDimitry Andric break; 36081ad6265SDimitry Andric 3611ac55f4cSDimitry Andric case ARM::t2STR_PRE: 3621ac55f4cSDimitry Andric if (MBBI->getOperand(0).getReg() == ARM::SP && 3631ac55f4cSDimitry Andric MBBI->getOperand(2).getReg() == ARM::SP && 3641ac55f4cSDimitry Andric MBBI->getOperand(3).getImm() == -4) { 3651ac55f4cSDimitry Andric unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg()); 3661ac55f4cSDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs)) 3671ac55f4cSDimitry Andric .addImm(1ULL << Reg) 3681ac55f4cSDimitry Andric .addImm(/*Wide=*/1) 3691ac55f4cSDimitry Andric .setMIFlags(Flags); 3701ac55f4cSDimitry Andric } else { 3711ac55f4cSDimitry Andric report_fatal_error("No matching SEH Opcode for t2STR_PRE"); 3721ac55f4cSDimitry Andric } 3731ac55f4cSDimitry Andric break; 3741ac55f4cSDimitry Andric 3751ac55f4cSDimitry Andric case ARM::t2LDR_POST: 3761ac55f4cSDimitry Andric if (MBBI->getOperand(1).getReg() == ARM::SP && 3771ac55f4cSDimitry Andric MBBI->getOperand(2).getReg() == ARM::SP && 3781ac55f4cSDimitry Andric MBBI->getOperand(3).getImm() == 4) { 3791ac55f4cSDimitry Andric unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg()); 3801ac55f4cSDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs)) 3811ac55f4cSDimitry Andric .addImm(1ULL << Reg) 3821ac55f4cSDimitry Andric .addImm(/*Wide=*/1) 3831ac55f4cSDimitry Andric .setMIFlags(Flags); 3841ac55f4cSDimitry Andric } else { 3851ac55f4cSDimitry Andric report_fatal_error("No matching SEH Opcode for t2LDR_POST"); 3861ac55f4cSDimitry Andric } 3871ac55f4cSDimitry Andric break; 3881ac55f4cSDimitry Andric 38981ad6265SDimitry Andric case ARM::t2LDMIA_RET: 39081ad6265SDimitry Andric case ARM::t2LDMIA_UPD: 39181ad6265SDimitry Andric case ARM::t2STMDB_UPD: { 39281ad6265SDimitry Andric unsigned Mask = 0; 39381ad6265SDimitry Andric bool Wide = false; 39481ad6265SDimitry Andric for (unsigned i = 4, NumOps = MBBI->getNumOperands(); i != NumOps; ++i) { 39581ad6265SDimitry Andric const MachineOperand &MO = MBBI->getOperand(i); 39681ad6265SDimitry Andric if (!MO.isReg() || MO.isImplicit()) 39781ad6265SDimitry Andric continue; 39881ad6265SDimitry Andric unsigned Reg = RegInfo->getSEHRegNum(MO.getReg()); 39981ad6265SDimitry Andric if (Reg == 15) 40081ad6265SDimitry Andric Reg = 14; 40181ad6265SDimitry Andric if (Reg >= 8 && Reg <= 13) 40281ad6265SDimitry Andric Wide = true; 40381ad6265SDimitry Andric else if (Opc == ARM::t2LDMIA_UPD && Reg == 14) 40481ad6265SDimitry Andric Wide = true; 40581ad6265SDimitry Andric Mask |= 1 << Reg; 40681ad6265SDimitry Andric } 40781ad6265SDimitry Andric if (!Wide) { 40881ad6265SDimitry Andric unsigned NewOpc; 40981ad6265SDimitry Andric switch (Opc) { 41081ad6265SDimitry Andric case ARM::t2LDMIA_RET: 41181ad6265SDimitry Andric NewOpc = ARM::tPOP_RET; 41281ad6265SDimitry Andric break; 41381ad6265SDimitry Andric case ARM::t2LDMIA_UPD: 41481ad6265SDimitry Andric NewOpc = ARM::tPOP; 41581ad6265SDimitry Andric break; 41681ad6265SDimitry Andric case ARM::t2STMDB_UPD: 41781ad6265SDimitry Andric NewOpc = ARM::tPUSH; 41881ad6265SDimitry Andric break; 41981ad6265SDimitry Andric default: 42081ad6265SDimitry Andric llvm_unreachable(""); 42181ad6265SDimitry Andric } 42281ad6265SDimitry Andric MachineInstrBuilder NewInstr = 42381ad6265SDimitry Andric BuildMI(MF, DL, TII.get(NewOpc)).setMIFlags(MBBI->getFlags()); 42481ad6265SDimitry Andric for (unsigned i = 2, NumOps = MBBI->getNumOperands(); i != NumOps; ++i) 42581ad6265SDimitry Andric NewInstr.add(MBBI->getOperand(i)); 42681ad6265SDimitry Andric MachineBasicBlock::iterator NewMBBI = MBB->insertAfter(MBBI, NewInstr); 42781ad6265SDimitry Andric MBB->erase(MBBI); 42881ad6265SDimitry Andric MBBI = NewMBBI; 42981ad6265SDimitry Andric } 43081ad6265SDimitry Andric unsigned SEHOpc = 43181ad6265SDimitry Andric (Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs; 43281ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(SEHOpc)) 43381ad6265SDimitry Andric .addImm(Mask) 43481ad6265SDimitry Andric .addImm(Wide ? 1 : 0) 43581ad6265SDimitry Andric .setMIFlags(Flags); 43681ad6265SDimitry Andric break; 43781ad6265SDimitry Andric } 43881ad6265SDimitry Andric case ARM::VSTMDDB_UPD: 43981ad6265SDimitry Andric case ARM::VLDMDIA_UPD: { 44081ad6265SDimitry Andric int First = -1, Last = 0; 44106c3fb27SDimitry Andric for (const MachineOperand &MO : llvm::drop_begin(MBBI->operands(), 4)) { 44281ad6265SDimitry Andric unsigned Reg = RegInfo->getSEHRegNum(MO.getReg()); 44381ad6265SDimitry Andric if (First == -1) 44481ad6265SDimitry Andric First = Reg; 44581ad6265SDimitry Andric Last = Reg; 44681ad6265SDimitry Andric } 44781ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveFRegs)) 44881ad6265SDimitry Andric .addImm(First) 44981ad6265SDimitry Andric .addImm(Last) 45081ad6265SDimitry Andric .setMIFlags(Flags); 45181ad6265SDimitry Andric break; 45281ad6265SDimitry Andric } 45381ad6265SDimitry Andric case ARM::tSUBspi: 45481ad6265SDimitry Andric case ARM::tADDspi: 45581ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc)) 45681ad6265SDimitry Andric .addImm(MBBI->getOperand(2).getImm() * 4) 45781ad6265SDimitry Andric .addImm(/*Wide=*/0) 45881ad6265SDimitry Andric .setMIFlags(Flags); 45981ad6265SDimitry Andric break; 46081ad6265SDimitry Andric case ARM::t2SUBspImm: 46181ad6265SDimitry Andric case ARM::t2SUBspImm12: 46281ad6265SDimitry Andric case ARM::t2ADDspImm: 46381ad6265SDimitry Andric case ARM::t2ADDspImm12: 46481ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc)) 46581ad6265SDimitry Andric .addImm(MBBI->getOperand(2).getImm()) 46681ad6265SDimitry Andric .addImm(/*Wide=*/1) 46781ad6265SDimitry Andric .setMIFlags(Flags); 46881ad6265SDimitry Andric break; 46981ad6265SDimitry Andric 47081ad6265SDimitry Andric case ARM::tMOVr: 47181ad6265SDimitry Andric if (MBBI->getOperand(1).getReg() == ARM::SP && 47281ad6265SDimitry Andric (Flags & MachineInstr::FrameSetup)) { 47381ad6265SDimitry Andric unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg()); 47481ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP)) 47581ad6265SDimitry Andric .addImm(Reg) 47681ad6265SDimitry Andric .setMIFlags(Flags); 47781ad6265SDimitry Andric } else if (MBBI->getOperand(0).getReg() == ARM::SP && 47881ad6265SDimitry Andric (Flags & MachineInstr::FrameDestroy)) { 47981ad6265SDimitry Andric unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg()); 48081ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP)) 48181ad6265SDimitry Andric .addImm(Reg) 48281ad6265SDimitry Andric .setMIFlags(Flags); 48381ad6265SDimitry Andric } else { 48481ad6265SDimitry Andric report_fatal_error("No SEH Opcode for MOV"); 48581ad6265SDimitry Andric } 48681ad6265SDimitry Andric break; 48781ad6265SDimitry Andric 48881ad6265SDimitry Andric case ARM::tBX_RET: 48981ad6265SDimitry Andric case ARM::TCRETURNri: 4900fca6ea1SDimitry Andric case ARM::TCRETURNrinotr12: 49181ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret)) 49281ad6265SDimitry Andric .addImm(/*Wide=*/0) 49381ad6265SDimitry Andric .setMIFlags(Flags); 49481ad6265SDimitry Andric break; 49581ad6265SDimitry Andric 49681ad6265SDimitry Andric case ARM::TCRETURNdi: 49781ad6265SDimitry Andric MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret)) 49881ad6265SDimitry Andric .addImm(/*Wide=*/1) 49981ad6265SDimitry Andric .setMIFlags(Flags); 50081ad6265SDimitry Andric break; 50181ad6265SDimitry Andric } 50281ad6265SDimitry Andric return MBB->insertAfter(MBBI, MIB); 50381ad6265SDimitry Andric } 50481ad6265SDimitry Andric 50581ad6265SDimitry Andric static MachineBasicBlock::iterator 50681ad6265SDimitry Andric initMBBRange(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI) { 50781ad6265SDimitry Andric if (MBBI == MBB.begin()) 50881ad6265SDimitry Andric return MachineBasicBlock::iterator(); 50981ad6265SDimitry Andric return std::prev(MBBI); 51081ad6265SDimitry Andric } 51181ad6265SDimitry Andric 51281ad6265SDimitry Andric static void insertSEHRange(MachineBasicBlock &MBB, 51381ad6265SDimitry Andric MachineBasicBlock::iterator Start, 51481ad6265SDimitry Andric const MachineBasicBlock::iterator &End, 51581ad6265SDimitry Andric const ARMBaseInstrInfo &TII, unsigned MIFlags) { 51681ad6265SDimitry Andric if (Start.isValid()) 51781ad6265SDimitry Andric Start = std::next(Start); 51881ad6265SDimitry Andric else 51981ad6265SDimitry Andric Start = MBB.begin(); 52081ad6265SDimitry Andric 52181ad6265SDimitry Andric for (auto MI = Start; MI != End;) { 52281ad6265SDimitry Andric auto Next = std::next(MI); 52381ad6265SDimitry Andric // Check if this instruction already has got a SEH opcode added. In that 52481ad6265SDimitry Andric // case, don't do this generic mapping. 52581ad6265SDimitry Andric if (Next != End && isSEHInstruction(*Next)) { 52681ad6265SDimitry Andric MI = std::next(Next); 52781ad6265SDimitry Andric while (MI != End && isSEHInstruction(*MI)) 52881ad6265SDimitry Andric ++MI; 52981ad6265SDimitry Andric continue; 53081ad6265SDimitry Andric } 53181ad6265SDimitry Andric insertSEH(MI, TII, MIFlags); 53281ad6265SDimitry Andric MI = Next; 53381ad6265SDimitry Andric } 53481ad6265SDimitry Andric } 53581ad6265SDimitry Andric 5360b57cec5SDimitry Andric static void emitRegPlusImmediate( 5370b57cec5SDimitry Andric bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, 5380b57cec5SDimitry Andric const DebugLoc &dl, const ARMBaseInstrInfo &TII, unsigned DestReg, 5390b57cec5SDimitry Andric unsigned SrcReg, int NumBytes, unsigned MIFlags = MachineInstr::NoFlags, 5400b57cec5SDimitry Andric ARMCC::CondCodes Pred = ARMCC::AL, unsigned PredReg = 0) { 5410b57cec5SDimitry Andric if (isARM) 5420b57cec5SDimitry Andric emitARMRegPlusImmediate(MBB, MBBI, dl, DestReg, SrcReg, NumBytes, 5430b57cec5SDimitry Andric Pred, PredReg, TII, MIFlags); 5440b57cec5SDimitry Andric else 5450b57cec5SDimitry Andric emitT2RegPlusImmediate(MBB, MBBI, dl, DestReg, SrcReg, NumBytes, 5460b57cec5SDimitry Andric Pred, PredReg, TII, MIFlags); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, 5500b57cec5SDimitry Andric MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, 5510b57cec5SDimitry Andric const ARMBaseInstrInfo &TII, int NumBytes, 5520b57cec5SDimitry Andric unsigned MIFlags = MachineInstr::NoFlags, 5530b57cec5SDimitry Andric ARMCC::CondCodes Pred = ARMCC::AL, 5540b57cec5SDimitry Andric unsigned PredReg = 0) { 5550b57cec5SDimitry Andric emitRegPlusImmediate(isARM, MBB, MBBI, dl, TII, ARM::SP, ARM::SP, NumBytes, 5560b57cec5SDimitry Andric MIFlags, Pred, PredReg); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric static int sizeOfSPAdjustment(const MachineInstr &MI) { 5600b57cec5SDimitry Andric int RegSize; 5610b57cec5SDimitry Andric switch (MI.getOpcode()) { 5620b57cec5SDimitry Andric case ARM::VSTMDDB_UPD: 5630b57cec5SDimitry Andric RegSize = 8; 5640b57cec5SDimitry Andric break; 5650b57cec5SDimitry Andric case ARM::STMDB_UPD: 5660b57cec5SDimitry Andric case ARM::t2STMDB_UPD: 5670b57cec5SDimitry Andric RegSize = 4; 5680b57cec5SDimitry Andric break; 5690b57cec5SDimitry Andric case ARM::t2STR_PRE: 5700b57cec5SDimitry Andric case ARM::STR_PRE_IMM: 5710b57cec5SDimitry Andric return 4; 5720b57cec5SDimitry Andric default: 5730b57cec5SDimitry Andric llvm_unreachable("Unknown push or pop like instruction"); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric int count = 0; 5770b57cec5SDimitry Andric // ARM and Thumb2 push/pop insts have explicit "sp, sp" operands (+ 5780b57cec5SDimitry Andric // pred) so the list starts at 4. 5790b57cec5SDimitry Andric for (int i = MI.getNumOperands() - 1; i >= 4; --i) 5800b57cec5SDimitry Andric count += RegSize; 5810b57cec5SDimitry Andric return count; 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric static bool WindowsRequiresStackProbe(const MachineFunction &MF, 5850b57cec5SDimitry Andric size_t StackSizeInBytes) { 5860b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 5870b57cec5SDimitry Andric const Function &F = MF.getFunction(); 5880b57cec5SDimitry Andric unsigned StackProbeSize = (MFI.getStackProtectorIndex() > 0) ? 4080 : 4096; 589bdd1243dSDimitry Andric 590bdd1243dSDimitry Andric StackProbeSize = 591bdd1243dSDimitry Andric F.getFnAttributeAsParsedInteger("stack-probe-size", StackProbeSize); 5920b57cec5SDimitry Andric return (StackSizeInBytes >= StackProbeSize) && 5930b57cec5SDimitry Andric !F.hasFnAttribute("no-stack-arg-probe"); 5940b57cec5SDimitry Andric } 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric namespace { 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric struct StackAdjustingInsts { 5990b57cec5SDimitry Andric struct InstInfo { 6000b57cec5SDimitry Andric MachineBasicBlock::iterator I; 6010b57cec5SDimitry Andric unsigned SPAdjust; 6020b57cec5SDimitry Andric bool BeforeFPSet; 6030b57cec5SDimitry Andric }; 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric SmallVector<InstInfo, 4> Insts; 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric void addInst(MachineBasicBlock::iterator I, unsigned SPAdjust, 6080b57cec5SDimitry Andric bool BeforeFPSet = false) { 6090b57cec5SDimitry Andric InstInfo Info = {I, SPAdjust, BeforeFPSet}; 6100b57cec5SDimitry Andric Insts.push_back(Info); 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric void addExtraBytes(const MachineBasicBlock::iterator I, unsigned ExtraBytes) { 6140b57cec5SDimitry Andric auto Info = 6150b57cec5SDimitry Andric llvm::find_if(Insts, [&](InstInfo &Info) { return Info.I == I; }); 6160b57cec5SDimitry Andric assert(Info != Insts.end() && "invalid sp adjusting instruction"); 6170b57cec5SDimitry Andric Info->SPAdjust += ExtraBytes; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric void emitDefCFAOffsets(MachineBasicBlock &MBB, const DebugLoc &dl, 6210b57cec5SDimitry Andric const ARMBaseInstrInfo &TII, bool HasFP) { 6220b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 6230b57cec5SDimitry Andric unsigned CFAOffset = 0; 6240b57cec5SDimitry Andric for (auto &Info : Insts) { 6250b57cec5SDimitry Andric if (HasFP && !Info.BeforeFPSet) 6260b57cec5SDimitry Andric return; 6270b57cec5SDimitry Andric 6285ffd83dbSDimitry Andric CFAOffset += Info.SPAdjust; 6290b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 6305ffd83dbSDimitry Andric MCCFIInstruction::cfiDefCfaOffset(nullptr, CFAOffset)); 6310b57cec5SDimitry Andric BuildMI(MBB, std::next(Info.I), dl, 6320b57cec5SDimitry Andric TII.get(TargetOpcode::CFI_INSTRUCTION)) 6330b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 6340b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric }; 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric } // end anonymous namespace 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric /// Emit an instruction sequence that will align the address in 6420b57cec5SDimitry Andric /// register Reg by zero-ing out the lower bits. For versions of the 6430b57cec5SDimitry Andric /// architecture that support Neon, this must be done in a single 6440b57cec5SDimitry Andric /// instruction, since skipAlignedDPRCS2Spills assumes it is done in a 6450b57cec5SDimitry Andric /// single instruction. That function only gets called when optimizing 6460b57cec5SDimitry Andric /// spilling of D registers on a core with the Neon instruction set 6470b57cec5SDimitry Andric /// present. 6480b57cec5SDimitry Andric static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI, 6490b57cec5SDimitry Andric const TargetInstrInfo &TII, 6500b57cec5SDimitry Andric MachineBasicBlock &MBB, 6510b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 6520b57cec5SDimitry Andric const DebugLoc &DL, const unsigned Reg, 6535ffd83dbSDimitry Andric const Align Alignment, 6540b57cec5SDimitry Andric const bool MustBeSingleInstruction) { 65581ad6265SDimitry Andric const ARMSubtarget &AST = MF.getSubtarget<ARMSubtarget>(); 6560b57cec5SDimitry Andric const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops(); 6575ffd83dbSDimitry Andric const unsigned AlignMask = Alignment.value() - 1U; 6585ffd83dbSDimitry Andric const unsigned NrBitsToZero = Log2(Alignment); 6590b57cec5SDimitry Andric assert(!AFI->isThumb1OnlyFunction() && "Thumb1 not supported"); 6600b57cec5SDimitry Andric if (!AFI->isThumbFunction()) { 6610b57cec5SDimitry Andric // if the BFC instruction is available, use that to zero the lower 6620b57cec5SDimitry Andric // bits: 6630b57cec5SDimitry Andric // bfc Reg, #0, log2(Alignment) 6640b57cec5SDimitry Andric // otherwise use BIC, if the mask to zero the required number of bits 6650b57cec5SDimitry Andric // can be encoded in the bic immediate field 6660b57cec5SDimitry Andric // bic Reg, Reg, Alignment-1 6670b57cec5SDimitry Andric // otherwise, emit 6680b57cec5SDimitry Andric // lsr Reg, Reg, log2(Alignment) 6690b57cec5SDimitry Andric // lsl Reg, Reg, log2(Alignment) 6700b57cec5SDimitry Andric if (CanUseBFC) { 6710b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(ARM::BFC), Reg) 6720b57cec5SDimitry Andric .addReg(Reg, RegState::Kill) 6730b57cec5SDimitry Andric .addImm(~AlignMask) 6740b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 6750b57cec5SDimitry Andric } else if (AlignMask <= 255) { 6760b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(ARM::BICri), Reg) 6770b57cec5SDimitry Andric .addReg(Reg, RegState::Kill) 6780b57cec5SDimitry Andric .addImm(AlignMask) 6790b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 6800b57cec5SDimitry Andric .add(condCodeOp()); 6810b57cec5SDimitry Andric } else { 6820b57cec5SDimitry Andric assert(!MustBeSingleInstruction && 6830b57cec5SDimitry Andric "Shouldn't call emitAligningInstructions demanding a single " 6840b57cec5SDimitry Andric "instruction to be emitted for large stack alignment for a target " 6850b57cec5SDimitry Andric "without BFC."); 6860b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(ARM::MOVsi), Reg) 6870b57cec5SDimitry Andric .addReg(Reg, RegState::Kill) 6880b57cec5SDimitry Andric .addImm(ARM_AM::getSORegOpc(ARM_AM::lsr, NrBitsToZero)) 6890b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 6900b57cec5SDimitry Andric .add(condCodeOp()); 6910b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(ARM::MOVsi), Reg) 6920b57cec5SDimitry Andric .addReg(Reg, RegState::Kill) 6930b57cec5SDimitry Andric .addImm(ARM_AM::getSORegOpc(ARM_AM::lsl, NrBitsToZero)) 6940b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 6950b57cec5SDimitry Andric .add(condCodeOp()); 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric } else { 6980b57cec5SDimitry Andric // Since this is only reached for Thumb-2 targets, the BFC instruction 6990b57cec5SDimitry Andric // should always be available. 7000b57cec5SDimitry Andric assert(CanUseBFC); 7010b57cec5SDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(ARM::t2BFC), Reg) 7020b57cec5SDimitry Andric .addReg(Reg, RegState::Kill) 7030b57cec5SDimitry Andric .addImm(~AlignMask) 7040b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric /// We need the offset of the frame pointer relative to other MachineFrameInfo 7090b57cec5SDimitry Andric /// offsets which are encoded relative to SP at function begin. 7100b57cec5SDimitry Andric /// See also emitPrologue() for how the FP is set up. 7110b57cec5SDimitry Andric /// Unfortunately we cannot determine this value in determineCalleeSaves() yet 7120b57cec5SDimitry Andric /// as assignCalleeSavedSpillSlots() hasn't run at this point. Instead we use 7130b57cec5SDimitry Andric /// this to produce a conservative estimate that we check in an assert() later. 71481ad6265SDimitry Andric static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI, 71581ad6265SDimitry Andric const MachineFunction &MF) { 7160b57cec5SDimitry Andric // For Thumb1, push.w isn't available, so the first push will always push 7170b57cec5SDimitry Andric // r7 and lr onto the stack first. 7180b57cec5SDimitry Andric if (AFI.isThumb1OnlyFunction()) 7190b57cec5SDimitry Andric return -AFI.getArgRegsSaveSize() - (2 * 4); 7200b57cec5SDimitry Andric // This is a conservative estimation: Assume the frame pointer being r7 and 7210b57cec5SDimitry Andric // pc("r15") up to r8 getting spilled before (= 8 registers). 72281ad6265SDimitry Andric int MaxRegBytes = 8 * 4; 72381ad6265SDimitry Andric if (STI.splitFramePointerPush(MF)) { 72481ad6265SDimitry Andric // Here, r11 can be stored below all of r4-r15 (3 registers more than 72581ad6265SDimitry Andric // above), plus d8-d15. 72681ad6265SDimitry Andric MaxRegBytes = 11 * 4 + 8 * 8; 72781ad6265SDimitry Andric } 72881ad6265SDimitry Andric int FPCXTSaveSize = 72981ad6265SDimitry Andric (STI.hasV8_1MMainlineOps() && AFI.isCmseNSEntryFunction()) ? 4 : 0; 73081ad6265SDimitry Andric return -FPCXTSaveSize - AFI.getArgRegsSaveSize() - MaxRegBytes; 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric void ARMFrameLowering::emitPrologue(MachineFunction &MF, 7340b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 7350b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(); 7360b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 7370b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 7380fca6ea1SDimitry Andric MCContext &Context = MF.getContext(); 7390b57cec5SDimitry Andric const TargetMachine &TM = MF.getTarget(); 7400b57cec5SDimitry Andric const MCRegisterInfo *MRI = Context.getRegisterInfo(); 7410b57cec5SDimitry Andric const ARMBaseRegisterInfo *RegInfo = STI.getRegisterInfo(); 7420b57cec5SDimitry Andric const ARMBaseInstrInfo &TII = *STI.getInstrInfo(); 7430b57cec5SDimitry Andric assert(!AFI->isThumb1OnlyFunction() && 7440b57cec5SDimitry Andric "This emitPrologue does not support Thumb1!"); 7450b57cec5SDimitry Andric bool isARM = !AFI->isThumbFunction(); 7465ffd83dbSDimitry Andric Align Alignment = STI.getFrameLowering()->getStackAlign(); 7470b57cec5SDimitry Andric unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize(); 7480b57cec5SDimitry Andric unsigned NumBytes = MFI.getStackSize(); 7490b57cec5SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); 7505ffd83dbSDimitry Andric int FPCXTSaveSize = 0; 75181ad6265SDimitry Andric bool NeedsWinCFI = needsWinCFI(MF); 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric // Debug location must be unknown since the first debug location is used 7540b57cec5SDimitry Andric // to determine the end of the prologue. 7550b57cec5SDimitry Andric DebugLoc dl; 7560b57cec5SDimitry Andric 7578bcb0991SDimitry Andric Register FramePtr = RegInfo->getFrameRegister(MF); 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric // Determine the sizes of each callee-save spill areas and record which frame 7600b57cec5SDimitry Andric // belongs to which callee-save spill areas. 7610b57cec5SDimitry Andric unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; 7620b57cec5SDimitry Andric int FramePtrSpillFI = 0; 7630b57cec5SDimitry Andric int D8SpillFI = 0; 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric // All calls are tail calls in GHC calling conv, and functions have no 7660b57cec5SDimitry Andric // prologue/epilogue. 7670b57cec5SDimitry Andric if (MF.getFunction().getCallingConv() == CallingConv::GHC) 7680b57cec5SDimitry Andric return; 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric StackAdjustingInsts DefCFAOffsetCandidates; 7710b57cec5SDimitry Andric bool HasFP = hasFP(MF); 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric if (!AFI->hasStackFrame() && 7740b57cec5SDimitry Andric (!STI.isTargetWindows() || !WindowsRequiresStackProbe(MF, NumBytes))) { 7750eae32dcSDimitry Andric if (NumBytes != 0) { 7760eae32dcSDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, 7770b57cec5SDimitry Andric MachineInstr::FrameSetup); 7780eae32dcSDimitry Andric DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes, true); 7790b57cec5SDimitry Andric } 78081ad6265SDimitry Andric if (!NeedsWinCFI) 7810b57cec5SDimitry Andric DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, dl, TII, HasFP); 78281ad6265SDimitry Andric if (NeedsWinCFI && MBBI != MBB.begin()) { 78381ad6265SDimitry Andric insertSEHRange(MBB, {}, MBBI, TII, MachineInstr::FrameSetup); 78481ad6265SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::SEH_PrologEnd)) 78581ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameSetup); 78681ad6265SDimitry Andric MF.setHasWinCFI(true); 78781ad6265SDimitry Andric } 7880b57cec5SDimitry Andric return; 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric // Determine spill area sizes. 79281ad6265SDimitry Andric if (STI.splitFramePointerPush(MF)) { 79381ad6265SDimitry Andric for (const CalleeSavedInfo &I : CSI) { 79481ad6265SDimitry Andric Register Reg = I.getReg(); 79581ad6265SDimitry Andric int FI = I.getFrameIdx(); 79681ad6265SDimitry Andric switch (Reg) { 79781ad6265SDimitry Andric case ARM::R11: 79881ad6265SDimitry Andric case ARM::LR: 79981ad6265SDimitry Andric if (Reg == FramePtr) 80081ad6265SDimitry Andric FramePtrSpillFI = FI; 80181ad6265SDimitry Andric GPRCS2Size += 4; 80281ad6265SDimitry Andric break; 80381ad6265SDimitry Andric case ARM::R0: 80481ad6265SDimitry Andric case ARM::R1: 80581ad6265SDimitry Andric case ARM::R2: 80681ad6265SDimitry Andric case ARM::R3: 80781ad6265SDimitry Andric case ARM::R4: 80881ad6265SDimitry Andric case ARM::R5: 80981ad6265SDimitry Andric case ARM::R6: 81081ad6265SDimitry Andric case ARM::R7: 81181ad6265SDimitry Andric case ARM::R8: 81281ad6265SDimitry Andric case ARM::R9: 81381ad6265SDimitry Andric case ARM::R10: 81481ad6265SDimitry Andric case ARM::R12: 81581ad6265SDimitry Andric GPRCS1Size += 4; 81681ad6265SDimitry Andric break; 81781ad6265SDimitry Andric case ARM::FPCXTNS: 81881ad6265SDimitry Andric FPCXTSaveSize = 4; 81981ad6265SDimitry Andric break; 82081ad6265SDimitry Andric default: 82181ad6265SDimitry Andric // This is a DPR. Exclude the aligned DPRCS2 spills. 82281ad6265SDimitry Andric if (Reg == ARM::D8) 82381ad6265SDimitry Andric D8SpillFI = FI; 82481ad6265SDimitry Andric if (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs()) 82581ad6265SDimitry Andric DPRCSSize += 8; 82681ad6265SDimitry Andric } 82781ad6265SDimitry Andric } 82881ad6265SDimitry Andric } else { 8294824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 83004eeddc0SDimitry Andric Register Reg = I.getReg(); 8314824e7fdSDimitry Andric int FI = I.getFrameIdx(); 8320b57cec5SDimitry Andric switch (Reg) { 8330b57cec5SDimitry Andric case ARM::R8: 8340b57cec5SDimitry Andric case ARM::R9: 8350b57cec5SDimitry Andric case ARM::R10: 8360b57cec5SDimitry Andric case ARM::R11: 8370b57cec5SDimitry Andric case ARM::R12: 8380b57cec5SDimitry Andric if (STI.splitFramePushPop(MF)) { 8390b57cec5SDimitry Andric GPRCS2Size += 4; 8400b57cec5SDimitry Andric break; 8410b57cec5SDimitry Andric } 842bdd1243dSDimitry Andric [[fallthrough]]; 8430b57cec5SDimitry Andric case ARM::R0: 8440b57cec5SDimitry Andric case ARM::R1: 8450b57cec5SDimitry Andric case ARM::R2: 8460b57cec5SDimitry Andric case ARM::R3: 8470b57cec5SDimitry Andric case ARM::R4: 8480b57cec5SDimitry Andric case ARM::R5: 8490b57cec5SDimitry Andric case ARM::R6: 8500b57cec5SDimitry Andric case ARM::R7: 8510b57cec5SDimitry Andric case ARM::LR: 8520b57cec5SDimitry Andric if (Reg == FramePtr) 8530b57cec5SDimitry Andric FramePtrSpillFI = FI; 8540b57cec5SDimitry Andric GPRCS1Size += 4; 8550b57cec5SDimitry Andric break; 8565ffd83dbSDimitry Andric case ARM::FPCXTNS: 8575ffd83dbSDimitry Andric FPCXTSaveSize = 4; 8585ffd83dbSDimitry Andric break; 8590b57cec5SDimitry Andric default: 8600b57cec5SDimitry Andric // This is a DPR. Exclude the aligned DPRCS2 spills. 8610b57cec5SDimitry Andric if (Reg == ARM::D8) 8620b57cec5SDimitry Andric D8SpillFI = FI; 8630b57cec5SDimitry Andric if (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs()) 8640b57cec5SDimitry Andric DPRCSSize += 8; 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric } 86781ad6265SDimitry Andric } 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric MachineBasicBlock::iterator LastPush = MBB.end(), GPRCS1Push, GPRCS2Push; 8700eae32dcSDimitry Andric 8710eae32dcSDimitry Andric // Move past the PAC computation. 8720eae32dcSDimitry Andric if (AFI->shouldSignReturnAddress()) 8730eae32dcSDimitry Andric LastPush = MBBI++; 8740eae32dcSDimitry Andric 8750eae32dcSDimitry Andric // Move past FPCXT area. 8765ffd83dbSDimitry Andric if (FPCXTSaveSize > 0) { 8775ffd83dbSDimitry Andric LastPush = MBBI++; 8785ffd83dbSDimitry Andric DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, true); 8795ffd83dbSDimitry Andric } 8805ffd83dbSDimitry Andric 8810eae32dcSDimitry Andric // Allocate the vararg register save area. 8820eae32dcSDimitry Andric if (ArgRegsSaveSize) { 8830eae32dcSDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, -ArgRegsSaveSize, 8840eae32dcSDimitry Andric MachineInstr::FrameSetup); 8850eae32dcSDimitry Andric LastPush = std::prev(MBBI); 8860eae32dcSDimitry Andric DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, true); 8870eae32dcSDimitry Andric } 8880eae32dcSDimitry Andric 8895ffd83dbSDimitry Andric // Move past area 1. 8900b57cec5SDimitry Andric if (GPRCS1Size > 0) { 8910b57cec5SDimitry Andric GPRCS1Push = LastPush = MBBI++; 8920b57cec5SDimitry Andric DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, true); 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric // Determine starting offsets of spill areas. 8965ffd83dbSDimitry Andric unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize; 8975ffd83dbSDimitry Andric unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size; 8980b57cec5SDimitry Andric unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size; 8995ffd83dbSDimitry Andric Align DPRAlign = DPRCSSize ? std::min(Align(8), Alignment) : Align(4); 90081ad6265SDimitry Andric unsigned DPRGapSize = GPRCS1Size + FPCXTSaveSize + ArgRegsSaveSize; 90181ad6265SDimitry Andric if (!STI.splitFramePointerPush(MF)) { 90281ad6265SDimitry Andric DPRGapSize += GPRCS2Size; 90381ad6265SDimitry Andric } 90481ad6265SDimitry Andric DPRGapSize %= DPRAlign.value(); 9055ffd83dbSDimitry Andric 90681ad6265SDimitry Andric unsigned DPRCSOffset; 90781ad6265SDimitry Andric if (STI.splitFramePointerPush(MF)) { 90881ad6265SDimitry Andric DPRCSOffset = GPRCS1Offset - DPRGapSize - DPRCSSize; 90981ad6265SDimitry Andric GPRCS2Offset = DPRCSOffset - GPRCS2Size; 91081ad6265SDimitry Andric } else { 91181ad6265SDimitry Andric DPRCSOffset = GPRCS2Offset - DPRGapSize - DPRCSSize; 91281ad6265SDimitry Andric } 9130b57cec5SDimitry Andric int FramePtrOffsetInPush = 0; 9140b57cec5SDimitry Andric if (HasFP) { 9150b57cec5SDimitry Andric int FPOffset = MFI.getObjectOffset(FramePtrSpillFI); 91681ad6265SDimitry Andric assert(getMaxFPOffset(STI, *AFI, MF) <= FPOffset && 9170b57cec5SDimitry Andric "Max FP estimation is wrong"); 9185ffd83dbSDimitry Andric FramePtrOffsetInPush = FPOffset + ArgRegsSaveSize + FPCXTSaveSize; 9190b57cec5SDimitry Andric AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) + 9200b57cec5SDimitry Andric NumBytes); 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); 9230b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); 9240b57cec5SDimitry Andric AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric // Move past area 2. 92781ad6265SDimitry Andric if (GPRCS2Size > 0 && !STI.splitFramePointerPush(MF)) { 9280b57cec5SDimitry Andric GPRCS2Push = LastPush = MBBI++; 9290b57cec5SDimitry Andric DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size); 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric // Prolog/epilog inserter assumes we correctly align DPRs on the stack, so our 9330b57cec5SDimitry Andric // .cfi_offset operations will reflect that. 9340b57cec5SDimitry Andric if (DPRGapSize) { 9350b57cec5SDimitry Andric assert(DPRGapSize == 4 && "unexpected alignment requirements for DPRs"); 9360b57cec5SDimitry Andric if (LastPush != MBB.end() && 9370b57cec5SDimitry Andric tryFoldSPUpdateIntoPushPop(STI, MF, &*LastPush, DPRGapSize)) 9380b57cec5SDimitry Andric DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize); 9390b57cec5SDimitry Andric else { 9400b57cec5SDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRGapSize, 9410b57cec5SDimitry Andric MachineInstr::FrameSetup); 9420b57cec5SDimitry Andric DefCFAOffsetCandidates.addInst(std::prev(MBBI), DPRGapSize); 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric // Move past area 3. 9470b57cec5SDimitry Andric if (DPRCSSize > 0) { 9480b57cec5SDimitry Andric // Since vpush register list cannot have gaps, there may be multiple vpush 9490b57cec5SDimitry Andric // instructions in the prologue. 9500b57cec5SDimitry Andric while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VSTMDDB_UPD) { 9510b57cec5SDimitry Andric DefCFAOffsetCandidates.addInst(MBBI, sizeOfSPAdjustment(*MBBI)); 9520b57cec5SDimitry Andric LastPush = MBBI++; 9530b57cec5SDimitry Andric } 9540b57cec5SDimitry Andric } 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric // Move past the aligned DPRCS2 area. 9570b57cec5SDimitry Andric if (AFI->getNumAlignedDPRCS2Regs() > 0) { 9580b57cec5SDimitry Andric MBBI = skipAlignedDPRCS2Spills(MBBI, AFI->getNumAlignedDPRCS2Regs()); 9590b57cec5SDimitry Andric // The code inserted by emitAlignedDPRCS2Spills realigns the stack, and 9600b57cec5SDimitry Andric // leaves the stack pointer pointing to the DPRCS2 area. 9610b57cec5SDimitry Andric // 9620b57cec5SDimitry Andric // Adjust NumBytes to represent the stack slots below the DPRCS2 area. 9630b57cec5SDimitry Andric NumBytes += MFI.getObjectOffset(D8SpillFI); 9640b57cec5SDimitry Andric } else 9650b57cec5SDimitry Andric NumBytes = DPRCSOffset; 9660b57cec5SDimitry Andric 96781ad6265SDimitry Andric if (GPRCS2Size > 0 && STI.splitFramePointerPush(MF)) { 96881ad6265SDimitry Andric GPRCS2Push = LastPush = MBBI++; 96981ad6265SDimitry Andric DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size); 97081ad6265SDimitry Andric } 97181ad6265SDimitry Andric 97281ad6265SDimitry Andric bool NeedsWinCFIStackAlloc = NeedsWinCFI; 97381ad6265SDimitry Andric if (STI.splitFramePointerPush(MF) && HasFP) 97481ad6265SDimitry Andric NeedsWinCFIStackAlloc = false; 97581ad6265SDimitry Andric 9760b57cec5SDimitry Andric if (STI.isTargetWindows() && WindowsRequiresStackProbe(MF, NumBytes)) { 9770b57cec5SDimitry Andric uint32_t NumWords = NumBytes >> 2; 9780b57cec5SDimitry Andric 97981ad6265SDimitry Andric if (NumWords < 65536) { 9800b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), ARM::R4) 9810b57cec5SDimitry Andric .addImm(NumWords) 9820b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup) 9830b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 98481ad6265SDimitry Andric } else { 98581ad6265SDimitry Andric // Split into two instructions here, instead of using t2MOVi32imm, 98681ad6265SDimitry Andric // to allow inserting accurate SEH instructions (including accurate 98781ad6265SDimitry Andric // instruction size for each of them). 98881ad6265SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), ARM::R4) 98981ad6265SDimitry Andric .addImm(NumWords & 0xffff) 99081ad6265SDimitry Andric .setMIFlags(MachineInstr::FrameSetup) 99181ad6265SDimitry Andric .add(predOps(ARMCC::AL)); 99281ad6265SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), ARM::R4) 99381ad6265SDimitry Andric .addReg(ARM::R4) 99481ad6265SDimitry Andric .addImm(NumWords >> 16) 99581ad6265SDimitry Andric .setMIFlags(MachineInstr::FrameSetup) 99681ad6265SDimitry Andric .add(predOps(ARMCC::AL)); 99781ad6265SDimitry Andric } 9980b57cec5SDimitry Andric 9990b57cec5SDimitry Andric switch (TM.getCodeModel()) { 10000b57cec5SDimitry Andric case CodeModel::Tiny: 10010b57cec5SDimitry Andric llvm_unreachable("Tiny code model not available on ARM."); 10020b57cec5SDimitry Andric case CodeModel::Small: 10030b57cec5SDimitry Andric case CodeModel::Medium: 10040b57cec5SDimitry Andric case CodeModel::Kernel: 10050b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tBL)) 10060b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 10070b57cec5SDimitry Andric .addExternalSymbol("__chkstk") 10080b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Implicit) 10090b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 10100b57cec5SDimitry Andric break; 10110b57cec5SDimitry Andric case CodeModel::Large: 10120b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ARM::R12) 10130b57cec5SDimitry Andric .addExternalSymbol("__chkstk") 10140b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tBLXr)) 10170b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 10180b57cec5SDimitry Andric .addReg(ARM::R12, RegState::Kill) 10190b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Implicit) 10200b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 10210b57cec5SDimitry Andric break; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 102481ad6265SDimitry Andric MachineInstrBuilder Instr, SEH; 102581ad6265SDimitry Andric Instr = BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), ARM::SP) 10260b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Kill) 10270b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 10280b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup) 10290b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 10300b57cec5SDimitry Andric .add(condCodeOp()); 103181ad6265SDimitry Andric if (NeedsWinCFIStackAlloc) { 103281ad6265SDimitry Andric SEH = BuildMI(MF, dl, TII.get(ARM::SEH_StackAlloc)) 103381ad6265SDimitry Andric .addImm(NumBytes) 103481ad6265SDimitry Andric .addImm(/*Wide=*/1) 103581ad6265SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 103681ad6265SDimitry Andric MBB.insertAfter(Instr, SEH); 103781ad6265SDimitry Andric } 10380b57cec5SDimitry Andric NumBytes = 0; 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric if (NumBytes) { 10420b57cec5SDimitry Andric // Adjust SP after all the callee-save spills. 10430b57cec5SDimitry Andric if (AFI->getNumAlignedDPRCS2Regs() == 0 && 10440b57cec5SDimitry Andric tryFoldSPUpdateIntoPushPop(STI, MF, &*LastPush, NumBytes)) 10450b57cec5SDimitry Andric DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes); 10460b57cec5SDimitry Andric else { 10470b57cec5SDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, 10480b57cec5SDimitry Andric MachineInstr::FrameSetup); 10490b57cec5SDimitry Andric DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes); 10500b57cec5SDimitry Andric } 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric if (HasFP && isARM) 10530b57cec5SDimitry Andric // Restore from fp only in ARM mode: e.g. sub sp, r7, #24 10540b57cec5SDimitry Andric // Note it's not safe to do this in Thumb2 mode because it would have 10550b57cec5SDimitry Andric // taken two instructions: 10560b57cec5SDimitry Andric // mov sp, r7 10570b57cec5SDimitry Andric // sub sp, #24 10580b57cec5SDimitry Andric // If an interrupt is taken between the two instructions, then sp is in 10590b57cec5SDimitry Andric // an inconsistent state (pointing to the middle of callee-saved area). 10600b57cec5SDimitry Andric // The interrupt handler can end up clobbering the registers. 10610b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric // Set FP to point to the stack slot that contains the previous FP. 10650b57cec5SDimitry Andric // For iOS, FP is R7, which has now been stored in spill area 1. 10660b57cec5SDimitry Andric // Otherwise, if this is not iOS, all the callee-saved registers go 10670b57cec5SDimitry Andric // into spill area 1, including the FP in R11. In either case, it 10680b57cec5SDimitry Andric // is in area one and the adjustment needs to take place just after 10690b57cec5SDimitry Andric // that push. 107081ad6265SDimitry Andric // FIXME: The above is not necessary true when PACBTI is enabled. 107181ad6265SDimitry Andric // AAPCS requires use of R11, and PACBTI gets in the way of regular pushes, 107281ad6265SDimitry Andric // so FP ends up on area two. 107381ad6265SDimitry Andric MachineBasicBlock::iterator AfterPush; 10740b57cec5SDimitry Andric if (HasFP) { 107581ad6265SDimitry Andric AfterPush = std::next(GPRCS1Push); 10760b57cec5SDimitry Andric unsigned PushSize = sizeOfSPAdjustment(*GPRCS1Push); 107781ad6265SDimitry Andric int FPOffset = PushSize + FramePtrOffsetInPush; 107881ad6265SDimitry Andric if (STI.splitFramePointerPush(MF)) { 107981ad6265SDimitry Andric AfterPush = std::next(GPRCS2Push); 108081ad6265SDimitry Andric emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII, 108181ad6265SDimitry Andric FramePtr, ARM::SP, 0, MachineInstr::FrameSetup); 108281ad6265SDimitry Andric } else { 108381ad6265SDimitry Andric emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII, 108481ad6265SDimitry Andric FramePtr, ARM::SP, FPOffset, 10850b57cec5SDimitry Andric MachineInstr::FrameSetup); 108681ad6265SDimitry Andric } 108781ad6265SDimitry Andric if (!NeedsWinCFI) { 10880b57cec5SDimitry Andric if (FramePtrOffsetInPush + PushSize != 0) { 10895ffd83dbSDimitry Andric unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa( 10900b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(FramePtr, true), 10915ffd83dbSDimitry Andric FPCXTSaveSize + ArgRegsSaveSize - FramePtrOffsetInPush)); 10920b57cec5SDimitry Andric BuildMI(MBB, AfterPush, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 10930b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 10940b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 10950b57cec5SDimitry Andric } else { 10960b57cec5SDimitry Andric unsigned CFIIndex = 10970b57cec5SDimitry Andric MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( 10980b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(FramePtr, true))); 10990b57cec5SDimitry Andric BuildMI(MBB, AfterPush, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 11000b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 11010b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 11020b57cec5SDimitry Andric } 11030b57cec5SDimitry Andric } 110481ad6265SDimitry Andric } 110581ad6265SDimitry Andric 110681ad6265SDimitry Andric // Emit a SEH opcode indicating the prologue end. The rest of the prologue 110781ad6265SDimitry Andric // instructions below don't need to be replayed to unwind the stack. 110881ad6265SDimitry Andric if (NeedsWinCFI && MBBI != MBB.begin()) { 110981ad6265SDimitry Andric MachineBasicBlock::iterator End = MBBI; 111081ad6265SDimitry Andric if (HasFP && STI.splitFramePointerPush(MF)) 111181ad6265SDimitry Andric End = AfterPush; 111281ad6265SDimitry Andric insertSEHRange(MBB, {}, End, TII, MachineInstr::FrameSetup); 111381ad6265SDimitry Andric BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd)) 111481ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameSetup); 111581ad6265SDimitry Andric MF.setHasWinCFI(true); 111681ad6265SDimitry Andric } 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric // Now that the prologue's actual instructions are finalised, we can insert 11190b57cec5SDimitry Andric // the necessary DWARF cf instructions to describe the situation. Start by 11200b57cec5SDimitry Andric // recording where each register ended up: 112181ad6265SDimitry Andric if (GPRCS1Size > 0 && !NeedsWinCFI) { 11220b57cec5SDimitry Andric MachineBasicBlock::iterator Pos = std::next(GPRCS1Push); 11230b57cec5SDimitry Andric int CFIIndex; 11240b57cec5SDimitry Andric for (const auto &Entry : CSI) { 112504eeddc0SDimitry Andric Register Reg = Entry.getReg(); 11260b57cec5SDimitry Andric int FI = Entry.getFrameIdx(); 11270b57cec5SDimitry Andric switch (Reg) { 11280b57cec5SDimitry Andric case ARM::R8: 11290b57cec5SDimitry Andric case ARM::R9: 11300b57cec5SDimitry Andric case ARM::R10: 11310b57cec5SDimitry Andric case ARM::R11: 11320b57cec5SDimitry Andric case ARM::R12: 11330b57cec5SDimitry Andric if (STI.splitFramePushPop(MF)) 11340b57cec5SDimitry Andric break; 1135bdd1243dSDimitry Andric [[fallthrough]]; 11360b57cec5SDimitry Andric case ARM::R0: 11370b57cec5SDimitry Andric case ARM::R1: 11380b57cec5SDimitry Andric case ARM::R2: 11390b57cec5SDimitry Andric case ARM::R3: 11400b57cec5SDimitry Andric case ARM::R4: 11410b57cec5SDimitry Andric case ARM::R5: 11420b57cec5SDimitry Andric case ARM::R6: 11430b57cec5SDimitry Andric case ARM::R7: 11440b57cec5SDimitry Andric case ARM::LR: 11450b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 11460b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI))); 11470b57cec5SDimitry Andric BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 11480b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 11490b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 11500b57cec5SDimitry Andric break; 11510b57cec5SDimitry Andric } 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric } 11540b57cec5SDimitry Andric 115581ad6265SDimitry Andric if (GPRCS2Size > 0 && !NeedsWinCFI) { 11560b57cec5SDimitry Andric MachineBasicBlock::iterator Pos = std::next(GPRCS2Push); 11570b57cec5SDimitry Andric for (const auto &Entry : CSI) { 115804eeddc0SDimitry Andric Register Reg = Entry.getReg(); 11590b57cec5SDimitry Andric int FI = Entry.getFrameIdx(); 11600b57cec5SDimitry Andric switch (Reg) { 11610b57cec5SDimitry Andric case ARM::R8: 11620b57cec5SDimitry Andric case ARM::R9: 11630b57cec5SDimitry Andric case ARM::R10: 11640b57cec5SDimitry Andric case ARM::R11: 11650b57cec5SDimitry Andric case ARM::R12: 11660b57cec5SDimitry Andric if (STI.splitFramePushPop(MF)) { 11670eae32dcSDimitry Andric unsigned DwarfReg = MRI->getDwarfRegNum( 116804eeddc0SDimitry Andric Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true); 1169*36b606aeSDimitry Andric int64_t Offset = MFI.getObjectOffset(FI); 11700b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 11710b57cec5SDimitry Andric MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); 11720b57cec5SDimitry Andric BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 11730b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 11740b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric break; 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric } 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric 118181ad6265SDimitry Andric if (DPRCSSize > 0 && !NeedsWinCFI) { 11820b57cec5SDimitry Andric // Since vpush register list cannot have gaps, there may be multiple vpush 11830b57cec5SDimitry Andric // instructions in the prologue. 11840b57cec5SDimitry Andric MachineBasicBlock::iterator Pos = std::next(LastPush); 11850b57cec5SDimitry Andric for (const auto &Entry : CSI) { 118604eeddc0SDimitry Andric Register Reg = Entry.getReg(); 11870b57cec5SDimitry Andric int FI = Entry.getFrameIdx(); 11880b57cec5SDimitry Andric if ((Reg >= ARM::D0 && Reg <= ARM::D31) && 11890b57cec5SDimitry Andric (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())) { 11900b57cec5SDimitry Andric unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); 1191*36b606aeSDimitry Andric int64_t Offset = MFI.getObjectOffset(FI); 11920b57cec5SDimitry Andric unsigned CFIIndex = MF.addFrameInst( 11930b57cec5SDimitry Andric MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); 11940b57cec5SDimitry Andric BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) 11950b57cec5SDimitry Andric .addCFIIndex(CFIIndex) 11960b57cec5SDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 11970b57cec5SDimitry Andric } 11980b57cec5SDimitry Andric } 11990b57cec5SDimitry Andric } 12000b57cec5SDimitry Andric 12010b57cec5SDimitry Andric // Now we can emit descriptions of where the canonical frame address was 12020b57cec5SDimitry Andric // throughout the process. If we have a frame pointer, it takes over the job 12030b57cec5SDimitry Andric // half-way through, so only the first few .cfi_def_cfa_offset instructions 12040b57cec5SDimitry Andric // actually get emitted. 120581ad6265SDimitry Andric if (!NeedsWinCFI) 12060b57cec5SDimitry Andric DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, dl, TII, HasFP); 12070b57cec5SDimitry Andric 12080b57cec5SDimitry Andric if (STI.isTargetELF() && hasFP(MF)) 12090b57cec5SDimitry Andric MFI.setOffsetAdjustment(MFI.getOffsetAdjustment() - 12100b57cec5SDimitry Andric AFI->getFramePtrSpillOffset()); 12110b57cec5SDimitry Andric 12125ffd83dbSDimitry Andric AFI->setFPCXTSaveAreaSize(FPCXTSaveSize); 12130b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); 12140b57cec5SDimitry Andric AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); 12150b57cec5SDimitry Andric AFI->setDPRCalleeSavedGapSize(DPRGapSize); 12160b57cec5SDimitry Andric AFI->setDPRCalleeSavedAreaSize(DPRCSSize); 12170b57cec5SDimitry Andric 12180b57cec5SDimitry Andric // If we need dynamic stack realignment, do it here. Be paranoid and make 12190b57cec5SDimitry Andric // sure if we also have VLAs, we have a base pointer for frame access. 12200b57cec5SDimitry Andric // If aligned NEON registers were spilled, the stack has already been 12210b57cec5SDimitry Andric // realigned. 1222fe6060f1SDimitry Andric if (!AFI->getNumAlignedDPRCS2Regs() && RegInfo->hasStackRealignment(MF)) { 12235ffd83dbSDimitry Andric Align MaxAlign = MFI.getMaxAlign(); 12240b57cec5SDimitry Andric assert(!AFI->isThumb1OnlyFunction()); 12250b57cec5SDimitry Andric if (!AFI->isThumbFunction()) { 12260b57cec5SDimitry Andric emitAligningInstructions(MF, AFI, TII, MBB, MBBI, dl, ARM::SP, MaxAlign, 12270b57cec5SDimitry Andric false); 12280b57cec5SDimitry Andric } else { 12290b57cec5SDimitry Andric // We cannot use sp as source/dest register here, thus we're using r4 to 12300b57cec5SDimitry Andric // perform the calculations. We're emitting the following sequence: 12310b57cec5SDimitry Andric // mov r4, sp 12320b57cec5SDimitry Andric // -- use emitAligningInstructions to produce best sequence to zero 12330b57cec5SDimitry Andric // -- out lower bits in r4 12340b57cec5SDimitry Andric // mov sp, r4 12350b57cec5SDimitry Andric // FIXME: It will be better just to find spare register here. 12360b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4) 12370b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Kill) 12380b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 12390b57cec5SDimitry Andric emitAligningInstructions(MF, AFI, TII, MBB, MBBI, dl, ARM::R4, MaxAlign, 12400b57cec5SDimitry Andric false); 12410b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 12420b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 12430b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric 12460b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric 12490b57cec5SDimitry Andric // If we need a base pointer, set it up here. It's whatever the value 12500b57cec5SDimitry Andric // of the stack pointer is at this point. Any variable size objects 12510b57cec5SDimitry Andric // will be allocated after this, so we can still use the base pointer 12520b57cec5SDimitry Andric // to reference locals. 12530b57cec5SDimitry Andric // FIXME: Clarify FrameSetup flags here. 12540b57cec5SDimitry Andric if (RegInfo->hasBasePointer(MF)) { 12550b57cec5SDimitry Andric if (isARM) 12560b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), RegInfo->getBaseRegister()) 12570b57cec5SDimitry Andric .addReg(ARM::SP) 12580b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 12590b57cec5SDimitry Andric .add(condCodeOp()); 12600b57cec5SDimitry Andric else 12610b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), RegInfo->getBaseRegister()) 12620b57cec5SDimitry Andric .addReg(ARM::SP) 12630b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric // If the frame has variable sized objects then the epilogue must restore 12670b57cec5SDimitry Andric // the sp from fp. We can assume there's an FP here since hasFP already 12680b57cec5SDimitry Andric // checks for hasVarSizedObjects. 12690b57cec5SDimitry Andric if (MFI.hasVarSizedObjects()) 12700b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric 12730b57cec5SDimitry Andric void ARMFrameLowering::emitEpilogue(MachineFunction &MF, 12740b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 12750b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 12760b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 12770b57cec5SDimitry Andric const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); 12780b57cec5SDimitry Andric const ARMBaseInstrInfo &TII = 12790b57cec5SDimitry Andric *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo()); 12800b57cec5SDimitry Andric assert(!AFI->isThumb1OnlyFunction() && 12810b57cec5SDimitry Andric "This emitEpilogue does not support Thumb1!"); 12820b57cec5SDimitry Andric bool isARM = !AFI->isThumbFunction(); 12830b57cec5SDimitry Andric 1284fe6060f1SDimitry Andric // Amount of stack space we reserved next to incoming args for either 1285fe6060f1SDimitry Andric // varargs registers or stack arguments in tail calls made by this function. 1286fe6060f1SDimitry Andric unsigned ReservedArgStack = AFI->getArgRegsSaveSize(); 1287fe6060f1SDimitry Andric 1288fe6060f1SDimitry Andric // How much of the stack used by incoming arguments this function is expected 1289fe6060f1SDimitry Andric // to restore in this particular epilogue. 1290fe6060f1SDimitry Andric int IncomingArgStackToRestore = getArgumentStackToRestore(MF, MBB); 12910b57cec5SDimitry Andric int NumBytes = (int)MFI.getStackSize(); 12928bcb0991SDimitry Andric Register FramePtr = RegInfo->getFrameRegister(MF); 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric // All calls are tail calls in GHC calling conv, and functions have no 12950b57cec5SDimitry Andric // prologue/epilogue. 12960b57cec5SDimitry Andric if (MF.getFunction().getCallingConv() == CallingConv::GHC) 12970b57cec5SDimitry Andric return; 12980b57cec5SDimitry Andric 12990b57cec5SDimitry Andric // First put ourselves on the first (from top) terminator instructions. 13000b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); 13010b57cec5SDimitry Andric DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 13020b57cec5SDimitry Andric 130381ad6265SDimitry Andric MachineBasicBlock::iterator RangeStart; 13040b57cec5SDimitry Andric if (!AFI->hasStackFrame()) { 130581ad6265SDimitry Andric if (MF.hasWinCFI()) { 130681ad6265SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::SEH_EpilogStart)) 130781ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 130881ad6265SDimitry Andric RangeStart = initMBBRange(MBB, MBBI); 130981ad6265SDimitry Andric } 131081ad6265SDimitry Andric 13110eae32dcSDimitry Andric if (NumBytes + IncomingArgStackToRestore != 0) 13120eae32dcSDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, 13130eae32dcSDimitry Andric NumBytes + IncomingArgStackToRestore, 13145ffd83dbSDimitry Andric MachineInstr::FrameDestroy); 13150b57cec5SDimitry Andric } else { 13160b57cec5SDimitry Andric // Unwind MBBI to point to first LDR / VLDRD. 13170b57cec5SDimitry Andric if (MBBI != MBB.begin()) { 13180b57cec5SDimitry Andric do { 13190b57cec5SDimitry Andric --MBBI; 13205ffd83dbSDimitry Andric } while (MBBI != MBB.begin() && 13215ffd83dbSDimitry Andric MBBI->getFlag(MachineInstr::FrameDestroy)); 13225ffd83dbSDimitry Andric if (!MBBI->getFlag(MachineInstr::FrameDestroy)) 13230b57cec5SDimitry Andric ++MBBI; 13240b57cec5SDimitry Andric } 13250b57cec5SDimitry Andric 132681ad6265SDimitry Andric if (MF.hasWinCFI()) { 132781ad6265SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::SEH_EpilogStart)) 132881ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 132981ad6265SDimitry Andric RangeStart = initMBBRange(MBB, MBBI); 133081ad6265SDimitry Andric } 133181ad6265SDimitry Andric 13320b57cec5SDimitry Andric // Move SP to start of FP callee save spill area. 1333fe6060f1SDimitry Andric NumBytes -= (ReservedArgStack + 13345ffd83dbSDimitry Andric AFI->getFPCXTSaveAreaSize() + 13350b57cec5SDimitry Andric AFI->getGPRCalleeSavedArea1Size() + 13360b57cec5SDimitry Andric AFI->getGPRCalleeSavedArea2Size() + 13370b57cec5SDimitry Andric AFI->getDPRCalleeSavedGapSize() + 13380b57cec5SDimitry Andric AFI->getDPRCalleeSavedAreaSize()); 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric // Reset SP based on frame pointer only if the stack frame extends beyond 13410b57cec5SDimitry Andric // frame pointer stack slot or target is ELF and the function has FP. 13420b57cec5SDimitry Andric if (AFI->shouldRestoreSPFromFP()) { 13430b57cec5SDimitry Andric NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; 13440b57cec5SDimitry Andric if (NumBytes) { 13450b57cec5SDimitry Andric if (isARM) 13460b57cec5SDimitry Andric emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes, 13475ffd83dbSDimitry Andric ARMCC::AL, 0, TII, 13485ffd83dbSDimitry Andric MachineInstr::FrameDestroy); 13490b57cec5SDimitry Andric else { 13500b57cec5SDimitry Andric // It's not possible to restore SP from FP in a single instruction. 13510b57cec5SDimitry Andric // For iOS, this looks like: 13520b57cec5SDimitry Andric // mov sp, r7 13530b57cec5SDimitry Andric // sub sp, #24 13540b57cec5SDimitry Andric // This is bad, if an interrupt is taken after the mov, sp is in an 13550b57cec5SDimitry Andric // inconsistent state. 13560b57cec5SDimitry Andric // Use the first callee-saved register as a scratch register. 13570b57cec5SDimitry Andric assert(!MFI.getPristineRegs(MF).test(ARM::R4) && 13580b57cec5SDimitry Andric "No scratch register to restore SP from FP!"); 13590b57cec5SDimitry Andric emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, 13605ffd83dbSDimitry Andric ARMCC::AL, 0, TII, MachineInstr::FrameDestroy); 13610b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 13620b57cec5SDimitry Andric .addReg(ARM::R4) 13635ffd83dbSDimitry Andric .add(predOps(ARMCC::AL)) 13645ffd83dbSDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 13650b57cec5SDimitry Andric } 13660b57cec5SDimitry Andric } else { 13670b57cec5SDimitry Andric // Thumb2 or ARM. 13680b57cec5SDimitry Andric if (isARM) 13690b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP) 13700b57cec5SDimitry Andric .addReg(FramePtr) 13710b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 13725ffd83dbSDimitry Andric .add(condCodeOp()) 13735ffd83dbSDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 13740b57cec5SDimitry Andric else 13750b57cec5SDimitry Andric BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) 13760b57cec5SDimitry Andric .addReg(FramePtr) 13775ffd83dbSDimitry Andric .add(predOps(ARMCC::AL)) 13785ffd83dbSDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 13790b57cec5SDimitry Andric } 13800b57cec5SDimitry Andric } else if (NumBytes && 13810b57cec5SDimitry Andric !tryFoldSPUpdateIntoPushPop(STI, MF, &*MBBI, NumBytes)) 13825ffd83dbSDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes, 13835ffd83dbSDimitry Andric MachineInstr::FrameDestroy); 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric // Increment past our save areas. 138681ad6265SDimitry Andric if (AFI->getGPRCalleeSavedArea2Size() && STI.splitFramePointerPush(MF)) 138781ad6265SDimitry Andric MBBI++; 138881ad6265SDimitry Andric 13890b57cec5SDimitry Andric if (MBBI != MBB.end() && AFI->getDPRCalleeSavedAreaSize()) { 13900b57cec5SDimitry Andric MBBI++; 13910b57cec5SDimitry Andric // Since vpop register list cannot have gaps, there may be multiple vpop 13920b57cec5SDimitry Andric // instructions in the epilogue. 13930b57cec5SDimitry Andric while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VLDMDIA_UPD) 13940b57cec5SDimitry Andric MBBI++; 13950b57cec5SDimitry Andric } 13960b57cec5SDimitry Andric if (AFI->getDPRCalleeSavedGapSize()) { 13970b57cec5SDimitry Andric assert(AFI->getDPRCalleeSavedGapSize() == 4 && 13980b57cec5SDimitry Andric "unexpected DPR alignment gap"); 13995ffd83dbSDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedGapSize(), 14005ffd83dbSDimitry Andric MachineInstr::FrameDestroy); 14010b57cec5SDimitry Andric } 14020b57cec5SDimitry Andric 140381ad6265SDimitry Andric if (AFI->getGPRCalleeSavedArea2Size() && !STI.splitFramePointerPush(MF)) 140481ad6265SDimitry Andric MBBI++; 14050b57cec5SDimitry Andric if (AFI->getGPRCalleeSavedArea1Size()) MBBI++; 14060b57cec5SDimitry Andric 1407fe6060f1SDimitry Andric if (ReservedArgStack || IncomingArgStackToRestore) { 1408fe6060f1SDimitry Andric assert((int)ReservedArgStack + IncomingArgStackToRestore >= 0 && 1409fe6060f1SDimitry Andric "attempting to restore negative stack amount"); 1410fe6060f1SDimitry Andric emitSPUpdate(isARM, MBB, MBBI, dl, TII, 1411fe6060f1SDimitry Andric ReservedArgStack + IncomingArgStackToRestore, 14125ffd83dbSDimitry Andric MachineInstr::FrameDestroy); 14130b57cec5SDimitry Andric } 14140eae32dcSDimitry Andric 14150eae32dcSDimitry Andric // Validate PAC, It should have been already popped into R12. For CMSE entry 14160eae32dcSDimitry Andric // function, the validation instruction is emitted during expansion of the 14170eae32dcSDimitry Andric // tBXNS_RET, since the validation must use the value of SP at function 14180eae32dcSDimitry Andric // entry, before saving, resp. after restoring, FPCXTNS. 14190eae32dcSDimitry Andric if (AFI->shouldSignReturnAddress() && !AFI->isCmseNSEntryFunction()) 14200eae32dcSDimitry Andric BuildMI(MBB, MBBI, DebugLoc(), STI.getInstrInfo()->get(ARM::t2AUT)); 14210eae32dcSDimitry Andric } 142281ad6265SDimitry Andric 142381ad6265SDimitry Andric if (MF.hasWinCFI()) { 142481ad6265SDimitry Andric insertSEHRange(MBB, RangeStart, MBB.end(), TII, MachineInstr::FrameDestroy); 142581ad6265SDimitry Andric BuildMI(MBB, MBB.end(), dl, TII.get(ARM::SEH_EpilogEnd)) 142681ad6265SDimitry Andric .setMIFlag(MachineInstr::FrameDestroy); 142781ad6265SDimitry Andric } 1428fe6060f1SDimitry Andric } 14290b57cec5SDimitry Andric 14300b57cec5SDimitry Andric /// getFrameIndexReference - Provide a base+offset reference to an FI slot for 14310b57cec5SDimitry Andric /// debug info. It's the same as what we use for resolving the code-gen 14320b57cec5SDimitry Andric /// references for now. FIXME: This can go wrong when references are 14330b57cec5SDimitry Andric /// SP-relative and simple call frames aren't used. 1434e8d8bef9SDimitry Andric StackOffset ARMFrameLowering::getFrameIndexReference(const MachineFunction &MF, 1435e8d8bef9SDimitry Andric int FI, 14365ffd83dbSDimitry Andric Register &FrameReg) const { 1437e8d8bef9SDimitry Andric return StackOffset::getFixed(ResolveFrameIndexReference(MF, FI, FrameReg, 0)); 14380b57cec5SDimitry Andric } 14390b57cec5SDimitry Andric 14405ffd83dbSDimitry Andric int ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF, 14415ffd83dbSDimitry Andric int FI, Register &FrameReg, 14420b57cec5SDimitry Andric int SPAdj) const { 14430b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 14440b57cec5SDimitry Andric const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( 14450b57cec5SDimitry Andric MF.getSubtarget().getRegisterInfo()); 14460b57cec5SDimitry Andric const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 14470b57cec5SDimitry Andric int Offset = MFI.getObjectOffset(FI) + MFI.getStackSize(); 14480b57cec5SDimitry Andric int FPOffset = Offset - AFI->getFramePtrSpillOffset(); 14490b57cec5SDimitry Andric bool isFixed = MFI.isFixedObjectIndex(FI); 14500b57cec5SDimitry Andric 14510b57cec5SDimitry Andric FrameReg = ARM::SP; 14520b57cec5SDimitry Andric Offset += SPAdj; 14530b57cec5SDimitry Andric 14540b57cec5SDimitry Andric // SP can move around if there are allocas. We may also lose track of SP 14550b57cec5SDimitry Andric // when emergency spilling inside a non-reserved call frame setup. 14560b57cec5SDimitry Andric bool hasMovingSP = !hasReservedCallFrame(MF); 14570b57cec5SDimitry Andric 14580b57cec5SDimitry Andric // When dynamically realigning the stack, use the frame pointer for 14590b57cec5SDimitry Andric // parameters, and the stack/base pointer for locals. 1460fe6060f1SDimitry Andric if (RegInfo->hasStackRealignment(MF)) { 14610b57cec5SDimitry Andric assert(hasFP(MF) && "dynamic stack realignment without a FP!"); 14620b57cec5SDimitry Andric if (isFixed) { 14630b57cec5SDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 14640b57cec5SDimitry Andric Offset = FPOffset; 14650b57cec5SDimitry Andric } else if (hasMovingSP) { 14660b57cec5SDimitry Andric assert(RegInfo->hasBasePointer(MF) && 14670b57cec5SDimitry Andric "VLAs and dynamic stack alignment, but missing base pointer!"); 14680b57cec5SDimitry Andric FrameReg = RegInfo->getBaseRegister(); 14690b57cec5SDimitry Andric Offset -= SPAdj; 14700b57cec5SDimitry Andric } 14710b57cec5SDimitry Andric return Offset; 14720b57cec5SDimitry Andric } 14730b57cec5SDimitry Andric 14740b57cec5SDimitry Andric // If there is a frame pointer, use it when we can. 14750b57cec5SDimitry Andric if (hasFP(MF) && AFI->hasStackFrame()) { 14760b57cec5SDimitry Andric // Use frame pointer to reference fixed objects. Use it for locals if 14770b57cec5SDimitry Andric // there are VLAs (and thus the SP isn't reliable as a base). 14780b57cec5SDimitry Andric if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) { 14790b57cec5SDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 14800b57cec5SDimitry Andric return FPOffset; 14810b57cec5SDimitry Andric } else if (hasMovingSP) { 14820b57cec5SDimitry Andric assert(RegInfo->hasBasePointer(MF) && "missing base pointer!"); 14830b57cec5SDimitry Andric if (AFI->isThumb2Function()) { 14840b57cec5SDimitry Andric // Try to use the frame pointer if we can, else use the base pointer 14850b57cec5SDimitry Andric // since it's available. This is handy for the emergency spill slot, in 14860b57cec5SDimitry Andric // particular. 14870b57cec5SDimitry Andric if (FPOffset >= -255 && FPOffset < 0) { 14880b57cec5SDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 14890b57cec5SDimitry Andric return FPOffset; 14900b57cec5SDimitry Andric } 14910b57cec5SDimitry Andric } 14920b57cec5SDimitry Andric } else if (AFI->isThumbFunction()) { 14930b57cec5SDimitry Andric // Prefer SP to base pointer, if the offset is suitably aligned and in 14940b57cec5SDimitry Andric // range as the effective range of the immediate offset is bigger when 14950b57cec5SDimitry Andric // basing off SP. 14960b57cec5SDimitry Andric // Use add <rd>, sp, #<imm8> 14970b57cec5SDimitry Andric // ldr <rd>, [sp, #<imm8>] 14980b57cec5SDimitry Andric if (Offset >= 0 && (Offset & 3) == 0 && Offset <= 1020) 14990b57cec5SDimitry Andric return Offset; 15000b57cec5SDimitry Andric // In Thumb2 mode, the negative offset is very limited. Try to avoid 15010b57cec5SDimitry Andric // out of range references. ldr <rt>,[<rn>, #-<imm8>] 15020b57cec5SDimitry Andric if (AFI->isThumb2Function() && FPOffset >= -255 && FPOffset < 0) { 15030b57cec5SDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 15040b57cec5SDimitry Andric return FPOffset; 15050b57cec5SDimitry Andric } 15060b57cec5SDimitry Andric } else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) { 15070b57cec5SDimitry Andric // Otherwise, use SP or FP, whichever is closer to the stack slot. 15080b57cec5SDimitry Andric FrameReg = RegInfo->getFrameRegister(MF); 15090b57cec5SDimitry Andric return FPOffset; 15100b57cec5SDimitry Andric } 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric // Use the base pointer if we have one. 15130b57cec5SDimitry Andric // FIXME: Maybe prefer sp on Thumb1 if it's legal and the offset is cheaper? 15140b57cec5SDimitry Andric // That can happen if we forced a base pointer for a large call frame. 15150b57cec5SDimitry Andric if (RegInfo->hasBasePointer(MF)) { 15160b57cec5SDimitry Andric FrameReg = RegInfo->getBaseRegister(); 15170b57cec5SDimitry Andric Offset -= SPAdj; 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric return Offset; 15200b57cec5SDimitry Andric } 15210b57cec5SDimitry Andric 15220b57cec5SDimitry Andric void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, 15230b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 15245ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, 15250b57cec5SDimitry Andric unsigned StmOpc, unsigned StrOpc, 15265ffd83dbSDimitry Andric bool NoGap, bool (*Func)(unsigned, bool), 15270b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs, 15280b57cec5SDimitry Andric unsigned MIFlags) const { 15290b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 15300b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 15310b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric DebugLoc DL; 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric using RegAndKill = std::pair<unsigned, bool>; 15360b57cec5SDimitry Andric 15370b57cec5SDimitry Andric SmallVector<RegAndKill, 4> Regs; 15380b57cec5SDimitry Andric unsigned i = CSI.size(); 15390b57cec5SDimitry Andric while (i != 0) { 15400b57cec5SDimitry Andric unsigned LastReg = 0; 15410b57cec5SDimitry Andric for (; i != 0; --i) { 154204eeddc0SDimitry Andric Register Reg = CSI[i-1].getReg(); 15430b57cec5SDimitry Andric if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue; 15440b57cec5SDimitry Andric 15450b57cec5SDimitry Andric // D-registers in the aligned area DPRCS2 are NOT spilled here. 15460b57cec5SDimitry Andric if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs) 15470b57cec5SDimitry Andric continue; 15480b57cec5SDimitry Andric 15490b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 15500b57cec5SDimitry Andric bool isLiveIn = MRI.isLiveIn(Reg); 15510b57cec5SDimitry Andric if (!isLiveIn && !MRI.isReserved(Reg)) 15520b57cec5SDimitry Andric MBB.addLiveIn(Reg); 15530b57cec5SDimitry Andric // If NoGap is true, push consecutive registers and then leave the rest 15540b57cec5SDimitry Andric // for other instructions. e.g. 15550b57cec5SDimitry Andric // vpush {d8, d10, d11} -> vpush {d8}, vpush {d10, d11} 15560b57cec5SDimitry Andric if (NoGap && LastReg && LastReg != Reg-1) 15570b57cec5SDimitry Andric break; 15580b57cec5SDimitry Andric LastReg = Reg; 15590b57cec5SDimitry Andric // Do not set a kill flag on values that are also marked as live-in. This 15600b57cec5SDimitry Andric // happens with the @llvm-returnaddress intrinsic and with arguments 15610b57cec5SDimitry Andric // passed in callee saved registers. 15620b57cec5SDimitry Andric // Omitting the kill flags is conservatively correct even if the live-in 15630b57cec5SDimitry Andric // is not used after all. 15640b57cec5SDimitry Andric Regs.push_back(std::make_pair(Reg, /*isKill=*/!isLiveIn)); 15650b57cec5SDimitry Andric } 15660b57cec5SDimitry Andric 15670b57cec5SDimitry Andric if (Regs.empty()) 15680b57cec5SDimitry Andric continue; 15690b57cec5SDimitry Andric 15700b57cec5SDimitry Andric llvm::sort(Regs, [&](const RegAndKill &LHS, const RegAndKill &RHS) { 15710b57cec5SDimitry Andric return TRI.getEncodingValue(LHS.first) < TRI.getEncodingValue(RHS.first); 15720b57cec5SDimitry Andric }); 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric if (Regs.size() > 1 || StrOpc== 0) { 15750b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StmOpc), ARM::SP) 15760b57cec5SDimitry Andric .addReg(ARM::SP) 15770b57cec5SDimitry Andric .setMIFlags(MIFlags) 15780b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 15790b57cec5SDimitry Andric for (unsigned i = 0, e = Regs.size(); i < e; ++i) 15800b57cec5SDimitry Andric MIB.addReg(Regs[i].first, getKillRegState(Regs[i].second)); 15810b57cec5SDimitry Andric } else if (Regs.size() == 1) { 15820b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(StrOpc), ARM::SP) 15830b57cec5SDimitry Andric .addReg(Regs[0].first, getKillRegState(Regs[0].second)) 15840b57cec5SDimitry Andric .addReg(ARM::SP) 15850b57cec5SDimitry Andric .setMIFlags(MIFlags) 15860b57cec5SDimitry Andric .addImm(-4) 15870b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 15880b57cec5SDimitry Andric } 15890b57cec5SDimitry Andric Regs.clear(); 15900b57cec5SDimitry Andric 15910b57cec5SDimitry Andric // Put any subsequent vpush instructions before this one: they will refer to 15920b57cec5SDimitry Andric // higher register numbers so need to be pushed first in order to preserve 15930b57cec5SDimitry Andric // monotonicity. 15940b57cec5SDimitry Andric if (MI != MBB.begin()) 15950b57cec5SDimitry Andric --MI; 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, 16000b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 16015ffd83dbSDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, 16020b57cec5SDimitry Andric unsigned LdmOpc, unsigned LdrOpc, 16030b57cec5SDimitry Andric bool isVarArg, bool NoGap, 16040b57cec5SDimitry Andric bool (*Func)(unsigned, bool), 16050b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs) const { 16060b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 16070b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 16080b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 16090b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 16100eae32dcSDimitry Andric bool hasPAC = AFI->shouldSignReturnAddress(); 16110b57cec5SDimitry Andric DebugLoc DL; 16120b57cec5SDimitry Andric bool isTailCall = false; 16130b57cec5SDimitry Andric bool isInterrupt = false; 16140b57cec5SDimitry Andric bool isTrap = false; 16155ffd83dbSDimitry Andric bool isCmseEntry = false; 16160b57cec5SDimitry Andric if (MBB.end() != MI) { 16170b57cec5SDimitry Andric DL = MI->getDebugLoc(); 16180b57cec5SDimitry Andric unsigned RetOpcode = MI->getOpcode(); 16190fca6ea1SDimitry Andric isTailCall = 16200fca6ea1SDimitry Andric (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri || 16210fca6ea1SDimitry Andric RetOpcode == ARM::TCRETURNrinotr12); 16220b57cec5SDimitry Andric isInterrupt = 16230b57cec5SDimitry Andric RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR; 16240b57cec5SDimitry Andric isTrap = 16250b57cec5SDimitry Andric RetOpcode == ARM::TRAP || RetOpcode == ARM::TRAPNaCl || 16260b57cec5SDimitry Andric RetOpcode == ARM::tTRAP; 16275ffd83dbSDimitry Andric isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET); 16280b57cec5SDimitry Andric } 16290b57cec5SDimitry Andric 16300b57cec5SDimitry Andric SmallVector<unsigned, 4> Regs; 16310b57cec5SDimitry Andric unsigned i = CSI.size(); 16320b57cec5SDimitry Andric while (i != 0) { 16330b57cec5SDimitry Andric unsigned LastReg = 0; 16340b57cec5SDimitry Andric bool DeleteRet = false; 16350b57cec5SDimitry Andric for (; i != 0; --i) { 16360b57cec5SDimitry Andric CalleeSavedInfo &Info = CSI[i-1]; 163704eeddc0SDimitry Andric Register Reg = Info.getReg(); 16380b57cec5SDimitry Andric if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue; 16390b57cec5SDimitry Andric 16400b57cec5SDimitry Andric // The aligned reloads from area DPRCS2 are not inserted here. 16410b57cec5SDimitry Andric if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs) 16420b57cec5SDimitry Andric continue; 16430b57cec5SDimitry Andric if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt && 1644fe6060f1SDimitry Andric !isCmseEntry && !isTrap && AFI->getArgumentStackToRestore() == 0 && 164581ad6265SDimitry Andric STI.hasV5TOps() && MBB.succ_empty() && !hasPAC && 164681ad6265SDimitry Andric !STI.splitFramePointerPush(MF)) { 16470b57cec5SDimitry Andric Reg = ARM::PC; 16480b57cec5SDimitry Andric // Fold the return instruction into the LDM. 16490b57cec5SDimitry Andric DeleteRet = true; 16500b57cec5SDimitry Andric LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET; 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric // If NoGap is true, pop consecutive registers and then leave the rest 16540b57cec5SDimitry Andric // for other instructions. e.g. 16550b57cec5SDimitry Andric // vpop {d8, d10, d11} -> vpop {d8}, vpop {d10, d11} 16560b57cec5SDimitry Andric if (NoGap && LastReg && LastReg != Reg-1) 16570b57cec5SDimitry Andric break; 16580b57cec5SDimitry Andric 16590b57cec5SDimitry Andric LastReg = Reg; 16600b57cec5SDimitry Andric Regs.push_back(Reg); 16610b57cec5SDimitry Andric } 16620b57cec5SDimitry Andric 16630b57cec5SDimitry Andric if (Regs.empty()) 16640b57cec5SDimitry Andric continue; 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric llvm::sort(Regs, [&](unsigned LHS, unsigned RHS) { 16670b57cec5SDimitry Andric return TRI.getEncodingValue(LHS) < TRI.getEncodingValue(RHS); 16680b57cec5SDimitry Andric }); 16690b57cec5SDimitry Andric 16700b57cec5SDimitry Andric if (Regs.size() > 1 || LdrOpc == 0) { 16710b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP) 16720b57cec5SDimitry Andric .addReg(ARM::SP) 16735ffd83dbSDimitry Andric .add(predOps(ARMCC::AL)) 16745ffd83dbSDimitry Andric .setMIFlags(MachineInstr::FrameDestroy); 16750fca6ea1SDimitry Andric for (unsigned Reg : Regs) 16760fca6ea1SDimitry Andric MIB.addReg(Reg, getDefRegState(true)); 16770b57cec5SDimitry Andric if (DeleteRet) { 16780b57cec5SDimitry Andric if (MI != MBB.end()) { 16790b57cec5SDimitry Andric MIB.copyImplicitOps(*MI); 16800b57cec5SDimitry Andric MI->eraseFromParent(); 16810b57cec5SDimitry Andric } 16820b57cec5SDimitry Andric } 16830b57cec5SDimitry Andric MI = MIB; 16840b57cec5SDimitry Andric } else if (Regs.size() == 1) { 16850b57cec5SDimitry Andric // If we adjusted the reg to PC from LR above, switch it back here. We 16860b57cec5SDimitry Andric // only do that for LDM. 16870b57cec5SDimitry Andric if (Regs[0] == ARM::PC) 16880b57cec5SDimitry Andric Regs[0] = ARM::LR; 16890b57cec5SDimitry Andric MachineInstrBuilder MIB = 16900b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(LdrOpc), Regs[0]) 16910b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Define) 16925ffd83dbSDimitry Andric .addReg(ARM::SP) 16935ffd83dbSDimitry Andric .setMIFlags(MachineInstr::FrameDestroy); 16940b57cec5SDimitry Andric // ARM mode needs an extra reg0 here due to addrmode2. Will go away once 16950b57cec5SDimitry Andric // that refactoring is complete (eventually). 16960b57cec5SDimitry Andric if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) { 16970b57cec5SDimitry Andric MIB.addReg(0); 16980b57cec5SDimitry Andric MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift)); 16990b57cec5SDimitry Andric } else 17000b57cec5SDimitry Andric MIB.addImm(4); 17010b57cec5SDimitry Andric MIB.add(predOps(ARMCC::AL)); 17020b57cec5SDimitry Andric } 17030b57cec5SDimitry Andric Regs.clear(); 17040b57cec5SDimitry Andric 17050b57cec5SDimitry Andric // Put any subsequent vpop instructions after this one: they will refer to 17060b57cec5SDimitry Andric // higher register numbers so need to be popped afterwards. 17070b57cec5SDimitry Andric if (MI != MBB.end()) 17080b57cec5SDimitry Andric ++MI; 17090b57cec5SDimitry Andric } 17100b57cec5SDimitry Andric } 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric /// Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers 17130b57cec5SDimitry Andric /// starting from d8. Also insert stack realignment code and leave the stack 17140b57cec5SDimitry Andric /// pointer pointing to the d8 spill slot. 17150b57cec5SDimitry Andric static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB, 17160b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 17170b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs, 17185ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, 17190b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 17200b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 17210b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 17220b57cec5SDimitry Andric DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); 17230b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 17240b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 17250b57cec5SDimitry Andric 17260b57cec5SDimitry Andric // Mark the D-register spill slots as properly aligned. Since MFI computes 17270b57cec5SDimitry Andric // stack slot layout backwards, this can actually mean that the d-reg stack 17280b57cec5SDimitry Andric // slot offsets can be wrong. The offset for d8 will always be correct. 17294824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) { 17304824e7fdSDimitry Andric unsigned DNum = I.getReg() - ARM::D8; 17310b57cec5SDimitry Andric if (DNum > NumAlignedDPRCS2Regs - 1) 17320b57cec5SDimitry Andric continue; 17334824e7fdSDimitry Andric int FI = I.getFrameIdx(); 17340b57cec5SDimitry Andric // The even-numbered registers will be 16-byte aligned, the odd-numbered 17350b57cec5SDimitry Andric // registers will be 8-byte aligned. 17365ffd83dbSDimitry Andric MFI.setObjectAlignment(FI, DNum % 2 ? Align(8) : Align(16)); 17370b57cec5SDimitry Andric 17380b57cec5SDimitry Andric // The stack slot for D8 needs to be maximally aligned because this is 17390b57cec5SDimitry Andric // actually the point where we align the stack pointer. MachineFrameInfo 17400b57cec5SDimitry Andric // computes all offsets relative to the incoming stack pointer which is a 17410b57cec5SDimitry Andric // bit weird when realigning the stack. Any extra padding for this 17420b57cec5SDimitry Andric // over-alignment is not realized because the code inserted below adjusts 17430b57cec5SDimitry Andric // the stack pointer by numregs * 8 before aligning the stack pointer. 17440b57cec5SDimitry Andric if (DNum == 0) 17455ffd83dbSDimitry Andric MFI.setObjectAlignment(FI, MFI.getMaxAlign()); 17460b57cec5SDimitry Andric } 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric // Move the stack pointer to the d8 spill slot, and align it at the same 17490b57cec5SDimitry Andric // time. Leave the stack slot address in the scratch register r4. 17500b57cec5SDimitry Andric // 17510b57cec5SDimitry Andric // sub r4, sp, #numregs * 8 17520b57cec5SDimitry Andric // bic r4, r4, #align - 1 17530b57cec5SDimitry Andric // mov sp, r4 17540b57cec5SDimitry Andric // 17550b57cec5SDimitry Andric bool isThumb = AFI->isThumbFunction(); 17560b57cec5SDimitry Andric assert(!AFI->isThumb1OnlyFunction() && "Can't realign stack for thumb1"); 17570b57cec5SDimitry Andric AFI->setShouldRestoreSPFromFP(true); 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric // sub r4, sp, #numregs * 8 17600b57cec5SDimitry Andric // The immediate is <= 64, so it doesn't need any special encoding. 17610b57cec5SDimitry Andric unsigned Opc = isThumb ? ARM::t2SUBri : ARM::SUBri; 17620b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(Opc), ARM::R4) 17630b57cec5SDimitry Andric .addReg(ARM::SP) 17640b57cec5SDimitry Andric .addImm(8 * NumAlignedDPRCS2Regs) 17650b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 17660b57cec5SDimitry Andric .add(condCodeOp()); 17670b57cec5SDimitry Andric 17685ffd83dbSDimitry Andric Align MaxAlign = MF.getFrameInfo().getMaxAlign(); 17690b57cec5SDimitry Andric // We must set parameter MustBeSingleInstruction to true, since 17700b57cec5SDimitry Andric // skipAlignedDPRCS2Spills expects exactly 3 instructions to perform 17710b57cec5SDimitry Andric // stack alignment. Luckily, this can always be done since all ARM 17720b57cec5SDimitry Andric // architecture versions that support Neon also support the BFC 17730b57cec5SDimitry Andric // instruction. 17740b57cec5SDimitry Andric emitAligningInstructions(MF, AFI, TII, MBB, MI, DL, ARM::R4, MaxAlign, true); 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric // mov sp, r4 17770b57cec5SDimitry Andric // The stack pointer must be adjusted before spilling anything, otherwise 17780b57cec5SDimitry Andric // the stack slots could be clobbered by an interrupt handler. 17790b57cec5SDimitry Andric // Leave r4 live, it is used below. 17800b57cec5SDimitry Andric Opc = isThumb ? ARM::tMOVr : ARM::MOVr; 17810b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(Opc), ARM::SP) 17820b57cec5SDimitry Andric .addReg(ARM::R4) 17830b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 17840b57cec5SDimitry Andric if (!isThumb) 17850b57cec5SDimitry Andric MIB.add(condCodeOp()); 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric // Now spill NumAlignedDPRCS2Regs registers starting from d8. 17880b57cec5SDimitry Andric // r4 holds the stack slot address. 17890b57cec5SDimitry Andric unsigned NextReg = ARM::D8; 17900b57cec5SDimitry Andric 17910b57cec5SDimitry Andric // 16-byte aligned vst1.64 with 4 d-regs and address writeback. 17920b57cec5SDimitry Andric // The writeback is only needed when emitting two vst1.64 instructions. 17930b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs >= 6) { 17940b57cec5SDimitry Andric unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, 17950b57cec5SDimitry Andric &ARM::QQPRRegClass); 17960b57cec5SDimitry Andric MBB.addLiveIn(SupReg); 17970b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VST1d64Qwb_fixed), ARM::R4) 17980b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 17990b57cec5SDimitry Andric .addImm(16) 18000b57cec5SDimitry Andric .addReg(NextReg) 18010b57cec5SDimitry Andric .addReg(SupReg, RegState::ImplicitKill) 18020b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 18030b57cec5SDimitry Andric NextReg += 4; 18040b57cec5SDimitry Andric NumAlignedDPRCS2Regs -= 4; 18050b57cec5SDimitry Andric } 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric // We won't modify r4 beyond this point. It currently points to the next 18080b57cec5SDimitry Andric // register to be spilled. 18090b57cec5SDimitry Andric unsigned R4BaseReg = NextReg; 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric // 16-byte aligned vst1.64 with 4 d-regs, no writeback. 18120b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs >= 4) { 18130b57cec5SDimitry Andric unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, 18140b57cec5SDimitry Andric &ARM::QQPRRegClass); 18150b57cec5SDimitry Andric MBB.addLiveIn(SupReg); 18160b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VST1d64Q)) 18170b57cec5SDimitry Andric .addReg(ARM::R4) 18180b57cec5SDimitry Andric .addImm(16) 18190b57cec5SDimitry Andric .addReg(NextReg) 18200b57cec5SDimitry Andric .addReg(SupReg, RegState::ImplicitKill) 18210b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 18220b57cec5SDimitry Andric NextReg += 4; 18230b57cec5SDimitry Andric NumAlignedDPRCS2Regs -= 4; 18240b57cec5SDimitry Andric } 18250b57cec5SDimitry Andric 18260b57cec5SDimitry Andric // 16-byte aligned vst1.64 with 2 d-regs. 18270b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs >= 2) { 18280b57cec5SDimitry Andric unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, 18290b57cec5SDimitry Andric &ARM::QPRRegClass); 18300b57cec5SDimitry Andric MBB.addLiveIn(SupReg); 18310b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VST1q64)) 18320b57cec5SDimitry Andric .addReg(ARM::R4) 18330b57cec5SDimitry Andric .addImm(16) 18340b57cec5SDimitry Andric .addReg(SupReg) 18350b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 18360b57cec5SDimitry Andric NextReg += 2; 18370b57cec5SDimitry Andric NumAlignedDPRCS2Regs -= 2; 18380b57cec5SDimitry Andric } 18390b57cec5SDimitry Andric 18400b57cec5SDimitry Andric // Finally, use a vanilla vstr.64 for the odd last register. 18410b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs) { 18420b57cec5SDimitry Andric MBB.addLiveIn(NextReg); 18430b57cec5SDimitry Andric // vstr.64 uses addrmode5 which has an offset scale of 4. 18440b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VSTRD)) 18450b57cec5SDimitry Andric .addReg(NextReg) 18460b57cec5SDimitry Andric .addReg(ARM::R4) 18470b57cec5SDimitry Andric .addImm((NextReg - R4BaseReg) * 2) 18480b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 18490b57cec5SDimitry Andric } 18500b57cec5SDimitry Andric 18510b57cec5SDimitry Andric // The last spill instruction inserted should kill the scratch register r4. 18520b57cec5SDimitry Andric std::prev(MI)->addRegisterKilled(ARM::R4, TRI); 18530b57cec5SDimitry Andric } 18540b57cec5SDimitry Andric 18550b57cec5SDimitry Andric /// Skip past the code inserted by emitAlignedDPRCS2Spills, and return an 18560b57cec5SDimitry Andric /// iterator to the following instruction. 18570b57cec5SDimitry Andric static MachineBasicBlock::iterator 18580b57cec5SDimitry Andric skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, 18590b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs) { 18600b57cec5SDimitry Andric // sub r4, sp, #numregs * 8 18610b57cec5SDimitry Andric // bic r4, r4, #align - 1 18620b57cec5SDimitry Andric // mov sp, r4 18630b57cec5SDimitry Andric ++MI; ++MI; ++MI; 18640b57cec5SDimitry Andric assert(MI->mayStore() && "Expecting spill instruction"); 18650b57cec5SDimitry Andric 18660b57cec5SDimitry Andric // These switches all fall through. 18670b57cec5SDimitry Andric switch(NumAlignedDPRCS2Regs) { 18680b57cec5SDimitry Andric case 7: 18690b57cec5SDimitry Andric ++MI; 18700b57cec5SDimitry Andric assert(MI->mayStore() && "Expecting spill instruction"); 1871bdd1243dSDimitry Andric [[fallthrough]]; 18720b57cec5SDimitry Andric default: 18730b57cec5SDimitry Andric ++MI; 18740b57cec5SDimitry Andric assert(MI->mayStore() && "Expecting spill instruction"); 1875bdd1243dSDimitry Andric [[fallthrough]]; 18760b57cec5SDimitry Andric case 1: 18770b57cec5SDimitry Andric case 2: 18780b57cec5SDimitry Andric case 4: 18790fca6ea1SDimitry Andric assert(MI->killsRegister(ARM::R4, /*TRI=*/nullptr) && "Missed kill flag"); 18800b57cec5SDimitry Andric ++MI; 18810b57cec5SDimitry Andric } 18820b57cec5SDimitry Andric return MI; 18830b57cec5SDimitry Andric } 18840b57cec5SDimitry Andric 18850b57cec5SDimitry Andric /// Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers 18860b57cec5SDimitry Andric /// starting from d8. These instructions are assumed to execute while the 18870b57cec5SDimitry Andric /// stack is still aligned, unlike the code inserted by emitPopInst. 18880b57cec5SDimitry Andric static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, 18890b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 18900b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs, 18915ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, 18920b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 18930b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 18940b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 18950b57cec5SDimitry Andric DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); 18960b57cec5SDimitry Andric const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 18970b57cec5SDimitry Andric 18980b57cec5SDimitry Andric // Find the frame index assigned to d8. 18990b57cec5SDimitry Andric int D8SpillFI = 0; 19004824e7fdSDimitry Andric for (const CalleeSavedInfo &I : CSI) 19014824e7fdSDimitry Andric if (I.getReg() == ARM::D8) { 19024824e7fdSDimitry Andric D8SpillFI = I.getFrameIdx(); 19030b57cec5SDimitry Andric break; 19040b57cec5SDimitry Andric } 19050b57cec5SDimitry Andric 19060b57cec5SDimitry Andric // Materialize the address of the d8 spill slot into the scratch register r4. 19070b57cec5SDimitry Andric // This can be fairly complicated if the stack frame is large, so just use 19080b57cec5SDimitry Andric // the normal frame index elimination mechanism to do it. This code runs as 19090b57cec5SDimitry Andric // the initial part of the epilog where the stack and base pointers haven't 19100b57cec5SDimitry Andric // been changed yet. 19110b57cec5SDimitry Andric bool isThumb = AFI->isThumbFunction(); 19120b57cec5SDimitry Andric assert(!AFI->isThumb1OnlyFunction() && "Can't realign stack for thumb1"); 19130b57cec5SDimitry Andric 19140b57cec5SDimitry Andric unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri; 19150b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(Opc), ARM::R4) 19160b57cec5SDimitry Andric .addFrameIndex(D8SpillFI) 19170b57cec5SDimitry Andric .addImm(0) 19180b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 19190b57cec5SDimitry Andric .add(condCodeOp()); 19200b57cec5SDimitry Andric 19210b57cec5SDimitry Andric // Now restore NumAlignedDPRCS2Regs registers starting from d8. 19220b57cec5SDimitry Andric unsigned NextReg = ARM::D8; 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric // 16-byte aligned vld1.64 with 4 d-regs and writeback. 19250b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs >= 6) { 19260b57cec5SDimitry Andric unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, 19270b57cec5SDimitry Andric &ARM::QQPRRegClass); 19280b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VLD1d64Qwb_fixed), NextReg) 19290b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Define) 19300b57cec5SDimitry Andric .addReg(ARM::R4, RegState::Kill) 19310b57cec5SDimitry Andric .addImm(16) 19320b57cec5SDimitry Andric .addReg(SupReg, RegState::ImplicitDefine) 19330b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 19340b57cec5SDimitry Andric NextReg += 4; 19350b57cec5SDimitry Andric NumAlignedDPRCS2Regs -= 4; 19360b57cec5SDimitry Andric } 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric // We won't modify r4 beyond this point. It currently points to the next 19390b57cec5SDimitry Andric // register to be spilled. 19400b57cec5SDimitry Andric unsigned R4BaseReg = NextReg; 19410b57cec5SDimitry Andric 19420b57cec5SDimitry Andric // 16-byte aligned vld1.64 with 4 d-regs, no writeback. 19430b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs >= 4) { 19440b57cec5SDimitry Andric unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, 19450b57cec5SDimitry Andric &ARM::QQPRRegClass); 19460b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VLD1d64Q), NextReg) 19470b57cec5SDimitry Andric .addReg(ARM::R4) 19480b57cec5SDimitry Andric .addImm(16) 19490b57cec5SDimitry Andric .addReg(SupReg, RegState::ImplicitDefine) 19500b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 19510b57cec5SDimitry Andric NextReg += 4; 19520b57cec5SDimitry Andric NumAlignedDPRCS2Regs -= 4; 19530b57cec5SDimitry Andric } 19540b57cec5SDimitry Andric 19550b57cec5SDimitry Andric // 16-byte aligned vld1.64 with 2 d-regs. 19560b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs >= 2) { 19570b57cec5SDimitry Andric unsigned SupReg = TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, 19580b57cec5SDimitry Andric &ARM::QPRRegClass); 19590b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VLD1q64), SupReg) 19600b57cec5SDimitry Andric .addReg(ARM::R4) 19610b57cec5SDimitry Andric .addImm(16) 19620b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 19630b57cec5SDimitry Andric NextReg += 2; 19640b57cec5SDimitry Andric NumAlignedDPRCS2Regs -= 2; 19650b57cec5SDimitry Andric } 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric // Finally, use a vanilla vldr.64 for the remaining odd register. 19680b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs) 19690b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII.get(ARM::VLDRD), NextReg) 19700b57cec5SDimitry Andric .addReg(ARM::R4) 19710b57cec5SDimitry Andric .addImm(2 * (NextReg - R4BaseReg)) 19720b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 19730b57cec5SDimitry Andric 19740b57cec5SDimitry Andric // Last store kills r4. 19750b57cec5SDimitry Andric std::prev(MI)->addRegisterKilled(ARM::R4, TRI); 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric 19785ffd83dbSDimitry Andric bool ARMFrameLowering::spillCalleeSavedRegisters( 19795ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 19805ffd83dbSDimitry Andric ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 19810b57cec5SDimitry Andric if (CSI.empty()) 19820b57cec5SDimitry Andric return false; 19830b57cec5SDimitry Andric 19840b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 19850b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 19860b57cec5SDimitry Andric 19870b57cec5SDimitry Andric unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD; 19880b57cec5SDimitry Andric unsigned PushOneOpc = AFI->isThumbFunction() ? 19890b57cec5SDimitry Andric ARM::t2STR_PRE : ARM::STR_PRE_IMM; 19900b57cec5SDimitry Andric unsigned FltOpc = ARM::VSTMDDB_UPD; 19910b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs(); 19920eae32dcSDimitry Andric // Compute PAC in R12. 19930eae32dcSDimitry Andric if (AFI->shouldSignReturnAddress()) { 19940eae32dcSDimitry Andric BuildMI(MBB, MI, DebugLoc(), STI.getInstrInfo()->get(ARM::t2PAC)) 19950eae32dcSDimitry Andric .setMIFlags(MachineInstr::FrameSetup); 19960eae32dcSDimitry Andric } 19975ffd83dbSDimitry Andric // Save the non-secure floating point context. 19985ffd83dbSDimitry Andric if (llvm::any_of(CSI, [](const CalleeSavedInfo &C) { 19995ffd83dbSDimitry Andric return C.getReg() == ARM::FPCXTNS; 20005ffd83dbSDimitry Andric })) { 20015ffd83dbSDimitry Andric BuildMI(MBB, MI, DebugLoc(), STI.getInstrInfo()->get(ARM::VSTR_FPCXTNS_pre), 20025ffd83dbSDimitry Andric ARM::SP) 20035ffd83dbSDimitry Andric .addReg(ARM::SP) 20045ffd83dbSDimitry Andric .addImm(-4) 20055ffd83dbSDimitry Andric .add(predOps(ARMCC::AL)); 20065ffd83dbSDimitry Andric } 200781ad6265SDimitry Andric if (STI.splitFramePointerPush(MF)) { 200881ad6265SDimitry Andric emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, 200981ad6265SDimitry Andric &isSplitFPArea1Register, 0, MachineInstr::FrameSetup); 20100b57cec5SDimitry Andric emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register, 20110b57cec5SDimitry Andric NumAlignedDPRCS2Regs, MachineInstr::FrameSetup); 201281ad6265SDimitry Andric emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, 201381ad6265SDimitry Andric &isSplitFPArea2Register, 0, MachineInstr::FrameSetup); 201481ad6265SDimitry Andric } else { 201581ad6265SDimitry Andric emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, 201681ad6265SDimitry Andric 0, MachineInstr::FrameSetup); 201781ad6265SDimitry Andric emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea2Register, 201881ad6265SDimitry Andric 0, MachineInstr::FrameSetup); 201981ad6265SDimitry Andric emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register, 202081ad6265SDimitry Andric NumAlignedDPRCS2Regs, MachineInstr::FrameSetup); 202181ad6265SDimitry Andric } 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric // The code above does not insert spill code for the aligned DPRCS2 registers. 20240b57cec5SDimitry Andric // The stack realignment code will be inserted between the push instructions 20250b57cec5SDimitry Andric // and these spills. 20260b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs) 20270b57cec5SDimitry Andric emitAlignedDPRCS2Spills(MBB, MI, NumAlignedDPRCS2Regs, CSI, TRI); 20280b57cec5SDimitry Andric 20290b57cec5SDimitry Andric return true; 20300b57cec5SDimitry Andric } 20310b57cec5SDimitry Andric 20325ffd83dbSDimitry Andric bool ARMFrameLowering::restoreCalleeSavedRegisters( 20335ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 20345ffd83dbSDimitry Andric MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 20350b57cec5SDimitry Andric if (CSI.empty()) 20360b57cec5SDimitry Andric return false; 20370b57cec5SDimitry Andric 20380b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 20390b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 20400b57cec5SDimitry Andric bool isVarArg = AFI->getArgRegsSaveSize() > 0; 20410b57cec5SDimitry Andric unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs(); 20420b57cec5SDimitry Andric 20430b57cec5SDimitry Andric // The emitPopInst calls below do not insert reloads for the aligned DPRCS2 20440b57cec5SDimitry Andric // registers. Do that here instead. 20450b57cec5SDimitry Andric if (NumAlignedDPRCS2Regs) 20460b57cec5SDimitry Andric emitAlignedDPRCS2Restores(MBB, MI, NumAlignedDPRCS2Regs, CSI, TRI); 20470b57cec5SDimitry Andric 20480b57cec5SDimitry Andric unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD; 204981ad6265SDimitry Andric unsigned LdrOpc = 205081ad6265SDimitry Andric AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM; 20510b57cec5SDimitry Andric unsigned FltOpc = ARM::VLDMDIA_UPD; 205281ad6265SDimitry Andric if (STI.splitFramePointerPush(MF)) { 205381ad6265SDimitry Andric emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, 205481ad6265SDimitry Andric &isSplitFPArea2Register, 0); 205581ad6265SDimitry Andric emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register, 205681ad6265SDimitry Andric NumAlignedDPRCS2Regs); 205781ad6265SDimitry Andric emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, 205881ad6265SDimitry Andric &isSplitFPArea1Register, 0); 205981ad6265SDimitry Andric } else { 20600b57cec5SDimitry Andric emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register, 20610b57cec5SDimitry Andric NumAlignedDPRCS2Regs); 20620b57cec5SDimitry Andric emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, 20630b57cec5SDimitry Andric &isARMArea2Register, 0); 20640b57cec5SDimitry Andric emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, 20650b57cec5SDimitry Andric &isARMArea1Register, 0); 206681ad6265SDimitry Andric } 20670b57cec5SDimitry Andric 20680b57cec5SDimitry Andric return true; 20690b57cec5SDimitry Andric } 20700b57cec5SDimitry Andric 20710b57cec5SDimitry Andric // FIXME: Make generic? 20720b57cec5SDimitry Andric static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, 20730b57cec5SDimitry Andric const ARMBaseInstrInfo &TII) { 20740b57cec5SDimitry Andric unsigned FnSize = 0; 20750b57cec5SDimitry Andric for (auto &MBB : MF) { 20760b57cec5SDimitry Andric for (auto &MI : MBB) 20770b57cec5SDimitry Andric FnSize += TII.getInstSizeInBytes(MI); 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric if (MF.getJumpTableInfo()) 20800b57cec5SDimitry Andric for (auto &Table: MF.getJumpTableInfo()->getJumpTables()) 20810b57cec5SDimitry Andric FnSize += Table.MBBs.size() * 4; 20820b57cec5SDimitry Andric FnSize += MF.getConstantPool()->getConstants().size() * 4; 20830b57cec5SDimitry Andric return FnSize; 20840b57cec5SDimitry Andric } 20850b57cec5SDimitry Andric 20860b57cec5SDimitry Andric /// estimateRSStackSizeLimit - Look at each instruction that references stack 20870b57cec5SDimitry Andric /// frames and return the stack size limit beyond which some of these 20880b57cec5SDimitry Andric /// instructions will require a scratch register during their expansion later. 20890b57cec5SDimitry Andric // FIXME: Move to TII? 20900b57cec5SDimitry Andric static unsigned estimateRSStackSizeLimit(MachineFunction &MF, 20918bcb0991SDimitry Andric const TargetFrameLowering *TFI, 20928bcb0991SDimitry Andric bool &HasNonSPFrameIndex) { 20930b57cec5SDimitry Andric const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 20948bcb0991SDimitry Andric const ARMBaseInstrInfo &TII = 20958bcb0991SDimitry Andric *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo()); 20968bcb0991SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 20970b57cec5SDimitry Andric unsigned Limit = (1 << 12) - 1; 20980b57cec5SDimitry Andric for (auto &MBB : MF) { 20990b57cec5SDimitry Andric for (auto &MI : MBB) { 21008bcb0991SDimitry Andric if (MI.isDebugInstr()) 21018bcb0991SDimitry Andric continue; 21020b57cec5SDimitry Andric for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { 21030b57cec5SDimitry Andric if (!MI.getOperand(i).isFI()) 21040b57cec5SDimitry Andric continue; 21050b57cec5SDimitry Andric 21060b57cec5SDimitry Andric // When using ADDri to get the address of a stack object, 255 is the 21070b57cec5SDimitry Andric // largest offset guaranteed to fit in the immediate offset. 21080b57cec5SDimitry Andric if (MI.getOpcode() == ARM::ADDri) { 21090b57cec5SDimitry Andric Limit = std::min(Limit, (1U << 8) - 1); 21100b57cec5SDimitry Andric break; 21110b57cec5SDimitry Andric } 21128bcb0991SDimitry Andric // t2ADDri will not require an extra register, it can reuse the 21138bcb0991SDimitry Andric // destination. 21148bcb0991SDimitry Andric if (MI.getOpcode() == ARM::t2ADDri || MI.getOpcode() == ARM::t2ADDri12) 21158bcb0991SDimitry Andric break; 21168bcb0991SDimitry Andric 21178bcb0991SDimitry Andric const MCInstrDesc &MCID = MI.getDesc(); 21188bcb0991SDimitry Andric const TargetRegisterClass *RegClass = TII.getRegClass(MCID, i, TRI, MF); 21198bcb0991SDimitry Andric if (RegClass && !RegClass->contains(ARM::SP)) 21208bcb0991SDimitry Andric HasNonSPFrameIndex = true; 21210b57cec5SDimitry Andric 21220b57cec5SDimitry Andric // Otherwise check the addressing mode. 21230b57cec5SDimitry Andric switch (MI.getDesc().TSFlags & ARMII::AddrModeMask) { 21248bcb0991SDimitry Andric case ARMII::AddrMode_i12: 21258bcb0991SDimitry Andric case ARMII::AddrMode2: 21268bcb0991SDimitry Andric // Default 12 bit limit. 21278bcb0991SDimitry Andric break; 21280b57cec5SDimitry Andric case ARMII::AddrMode3: 21294824e7fdSDimitry Andric case ARMII::AddrModeT2_i8neg: 21300b57cec5SDimitry Andric Limit = std::min(Limit, (1U << 8) - 1); 21310b57cec5SDimitry Andric break; 21328bcb0991SDimitry Andric case ARMII::AddrMode5FP16: 21338bcb0991SDimitry Andric Limit = std::min(Limit, ((1U << 8) - 1) * 2); 21348bcb0991SDimitry Andric break; 21350b57cec5SDimitry Andric case ARMII::AddrMode5: 21360b57cec5SDimitry Andric case ARMII::AddrModeT2_i8s4: 21370b57cec5SDimitry Andric case ARMII::AddrModeT2_ldrex: 21380b57cec5SDimitry Andric Limit = std::min(Limit, ((1U << 8) - 1) * 4); 21390b57cec5SDimitry Andric break; 21400b57cec5SDimitry Andric case ARMII::AddrModeT2_i12: 21410b57cec5SDimitry Andric // i12 supports only positive offset so these will be converted to 21420b57cec5SDimitry Andric // i8 opcodes. See llvm::rewriteT2FrameIndex. 21430b57cec5SDimitry Andric if (TFI->hasFP(MF) && AFI->hasStackFrame()) 21440b57cec5SDimitry Andric Limit = std::min(Limit, (1U << 8) - 1); 21450b57cec5SDimitry Andric break; 21460b57cec5SDimitry Andric case ARMII::AddrMode4: 21470b57cec5SDimitry Andric case ARMII::AddrMode6: 21480b57cec5SDimitry Andric // Addressing modes 4 & 6 (load/store) instructions can't encode an 21490b57cec5SDimitry Andric // immediate offset for stack references. 21500b57cec5SDimitry Andric return 0; 21518bcb0991SDimitry Andric case ARMII::AddrModeT2_i7: 21528bcb0991SDimitry Andric Limit = std::min(Limit, ((1U << 7) - 1) * 1); 21530b57cec5SDimitry Andric break; 21548bcb0991SDimitry Andric case ARMII::AddrModeT2_i7s2: 21558bcb0991SDimitry Andric Limit = std::min(Limit, ((1U << 7) - 1) * 2); 21568bcb0991SDimitry Andric break; 21578bcb0991SDimitry Andric case ARMII::AddrModeT2_i7s4: 21588bcb0991SDimitry Andric Limit = std::min(Limit, ((1U << 7) - 1) * 4); 21598bcb0991SDimitry Andric break; 21608bcb0991SDimitry Andric default: 21618bcb0991SDimitry Andric llvm_unreachable("Unhandled addressing mode in stack size limit calculation"); 21620b57cec5SDimitry Andric } 21630b57cec5SDimitry Andric break; // At most one FI per instruction 21640b57cec5SDimitry Andric } 21650b57cec5SDimitry Andric } 21660b57cec5SDimitry Andric } 21670b57cec5SDimitry Andric 21680b57cec5SDimitry Andric return Limit; 21690b57cec5SDimitry Andric } 21700b57cec5SDimitry Andric 21710b57cec5SDimitry Andric // In functions that realign the stack, it can be an advantage to spill the 21720b57cec5SDimitry Andric // callee-saved vector registers after realigning the stack. The vst1 and vld1 21730b57cec5SDimitry Andric // instructions take alignment hints that can improve performance. 21740b57cec5SDimitry Andric static void 21750b57cec5SDimitry Andric checkNumAlignedDPRCS2Regs(MachineFunction &MF, BitVector &SavedRegs) { 21760b57cec5SDimitry Andric MF.getInfo<ARMFunctionInfo>()->setNumAlignedDPRCS2Regs(0); 21770b57cec5SDimitry Andric if (!SpillAlignedNEONRegs) 21780b57cec5SDimitry Andric return; 21790b57cec5SDimitry Andric 21800b57cec5SDimitry Andric // Naked functions don't spill callee-saved registers. 21810b57cec5SDimitry Andric if (MF.getFunction().hasFnAttribute(Attribute::Naked)) 21820b57cec5SDimitry Andric return; 21830b57cec5SDimitry Andric 21840b57cec5SDimitry Andric // We are planning to use NEON instructions vst1 / vld1. 218581ad6265SDimitry Andric if (!MF.getSubtarget<ARMSubtarget>().hasNEON()) 21860b57cec5SDimitry Andric return; 21870b57cec5SDimitry Andric 21880b57cec5SDimitry Andric // Don't bother if the default stack alignment is sufficiently high. 21895ffd83dbSDimitry Andric if (MF.getSubtarget().getFrameLowering()->getStackAlign() >= Align(8)) 21900b57cec5SDimitry Andric return; 21910b57cec5SDimitry Andric 21920b57cec5SDimitry Andric // Aligned spills require stack realignment. 21930b57cec5SDimitry Andric if (!static_cast<const ARMBaseRegisterInfo *>( 21940b57cec5SDimitry Andric MF.getSubtarget().getRegisterInfo())->canRealignStack(MF)) 21950b57cec5SDimitry Andric return; 21960b57cec5SDimitry Andric 21970b57cec5SDimitry Andric // We always spill contiguous d-registers starting from d8. Count how many 21980b57cec5SDimitry Andric // needs spilling. The register allocator will almost always use the 21990b57cec5SDimitry Andric // callee-saved registers in order, but it can happen that there are holes in 22000b57cec5SDimitry Andric // the range. Registers above the hole will be spilled to the standard DPRCS 22010b57cec5SDimitry Andric // area. 22020b57cec5SDimitry Andric unsigned NumSpills = 0; 22030b57cec5SDimitry Andric for (; NumSpills < 8; ++NumSpills) 22040b57cec5SDimitry Andric if (!SavedRegs.test(ARM::D8 + NumSpills)) 22050b57cec5SDimitry Andric break; 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric // Don't do this for just one d-register. It's not worth it. 22080b57cec5SDimitry Andric if (NumSpills < 2) 22090b57cec5SDimitry Andric return; 22100b57cec5SDimitry Andric 22110b57cec5SDimitry Andric // Spill the first NumSpills D-registers after realigning the stack. 22120b57cec5SDimitry Andric MF.getInfo<ARMFunctionInfo>()->setNumAlignedDPRCS2Regs(NumSpills); 22130b57cec5SDimitry Andric 22140b57cec5SDimitry Andric // A scratch register is required for the vst1 / vld1 instructions. 22150b57cec5SDimitry Andric SavedRegs.set(ARM::R4); 22160b57cec5SDimitry Andric } 22170b57cec5SDimitry Andric 22185ffd83dbSDimitry Andric bool ARMFrameLowering::enableShrinkWrapping(const MachineFunction &MF) const { 22195ffd83dbSDimitry Andric // For CMSE entry functions, we want to save the FPCXT_NS immediately 22205ffd83dbSDimitry Andric // upon function entry (resp. restore it immmediately before return) 22215ffd83dbSDimitry Andric if (STI.hasV8_1MMainlineOps() && 22225ffd83dbSDimitry Andric MF.getInfo<ARMFunctionInfo>()->isCmseNSEntryFunction()) 22235ffd83dbSDimitry Andric return false; 22245ffd83dbSDimitry Andric 22250eae32dcSDimitry Andric // We are disabling shrinkwrapping for now when PAC is enabled, as 22260eae32dcSDimitry Andric // shrinkwrapping can cause clobbering of r12 when the PAC code is 22270eae32dcSDimitry Andric // generated. A follow-up patch will fix this in a more performant manner. 22280eae32dcSDimitry Andric if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress( 222904eeddc0SDimitry Andric true /* SpillsLR */)) 22300eae32dcSDimitry Andric return false; 22310eae32dcSDimitry Andric 22325ffd83dbSDimitry Andric return true; 22335ffd83dbSDimitry Andric } 22345ffd83dbSDimitry Andric 22350fca6ea1SDimitry Andric bool ARMFrameLowering::requiresAAPCSFrameRecord( 22360fca6ea1SDimitry Andric const MachineFunction &MF) const { 223781ad6265SDimitry Andric const auto &Subtarget = MF.getSubtarget<ARMSubtarget>(); 22380fca6ea1SDimitry Andric return Subtarget.createAAPCSFrameChain() && hasFP(MF); 223981ad6265SDimitry Andric } 224081ad6265SDimitry Andric 22415f757f3fSDimitry Andric // Thumb1 may require a spill when storing to a frame index through FP (or any 22425f757f3fSDimitry Andric // access with execute-only), for cases where FP is a high register (R11). This 22435f757f3fSDimitry Andric // scans the function for cases where this may happen. 224481ad6265SDimitry Andric static bool canSpillOnFrameIndexAccess(const MachineFunction &MF, 224581ad6265SDimitry Andric const TargetFrameLowering &TFI) { 224681ad6265SDimitry Andric const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 224781ad6265SDimitry Andric if (!AFI->isThumb1OnlyFunction()) 224881ad6265SDimitry Andric return false; 224981ad6265SDimitry Andric 22505f757f3fSDimitry Andric const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); 225181ad6265SDimitry Andric for (const auto &MBB : MF) 225281ad6265SDimitry Andric for (const auto &MI : MBB) 22535f757f3fSDimitry Andric if (MI.getOpcode() == ARM::tSTRspi || MI.getOpcode() == ARM::tSTRi || 22545f757f3fSDimitry Andric STI.genExecuteOnly()) 225581ad6265SDimitry Andric for (const auto &Op : MI.operands()) 225681ad6265SDimitry Andric if (Op.isFI()) { 225781ad6265SDimitry Andric Register Reg; 225881ad6265SDimitry Andric TFI.getFrameIndexReference(MF, Op.getIndex(), Reg); 225981ad6265SDimitry Andric if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::SP) 226081ad6265SDimitry Andric return true; 226181ad6265SDimitry Andric } 226281ad6265SDimitry Andric return false; 226381ad6265SDimitry Andric } 226481ad6265SDimitry Andric 22650b57cec5SDimitry Andric void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF, 22660b57cec5SDimitry Andric BitVector &SavedRegs, 22670b57cec5SDimitry Andric RegScavenger *RS) const { 22680b57cec5SDimitry Andric TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); 22690b57cec5SDimitry Andric // This tells PEI to spill the FP as if it is any other callee-save register 22700b57cec5SDimitry Andric // to take advantage the eliminateFrameIndex machinery. This also ensures it 22710b57cec5SDimitry Andric // is spilled in the order specified by getCalleeSavedRegs() to make it easier 22720b57cec5SDimitry Andric // to combine multiple loads / stores. 227381ad6265SDimitry Andric bool CanEliminateFrame = !(requiresAAPCSFrameRecord(MF) && hasFP(MF)); 22740b57cec5SDimitry Andric bool CS1Spilled = false; 22750b57cec5SDimitry Andric bool LRSpilled = false; 22760b57cec5SDimitry Andric unsigned NumGPRSpills = 0; 22770b57cec5SDimitry Andric unsigned NumFPRSpills = 0; 22780b57cec5SDimitry Andric SmallVector<unsigned, 4> UnspilledCS1GPRs; 22790b57cec5SDimitry Andric SmallVector<unsigned, 4> UnspilledCS2GPRs; 22800b57cec5SDimitry Andric const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>( 22810b57cec5SDimitry Andric MF.getSubtarget().getRegisterInfo()); 22820b57cec5SDimitry Andric const ARMBaseInstrInfo &TII = 22830b57cec5SDimitry Andric *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo()); 22840b57cec5SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 22850b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 22860b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 22870b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 22880b57cec5SDimitry Andric (void)TRI; // Silence unused warning in non-assert builds. 22898bcb0991SDimitry Andric Register FramePtr = RegInfo->getFrameRegister(MF); 22900b57cec5SDimitry Andric 22910b57cec5SDimitry Andric // Spill R4 if Thumb2 function requires stack realignment - it will be used as 22920b57cec5SDimitry Andric // scratch register. Also spill R4 if Thumb2 function has varsized objects, 22930b57cec5SDimitry Andric // since it's not always possible to restore sp from fp in a single 22940b57cec5SDimitry Andric // instruction. 22950b57cec5SDimitry Andric // FIXME: It will be better just to find spare register here. 22960b57cec5SDimitry Andric if (AFI->isThumb2Function() && 2297fe6060f1SDimitry Andric (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF))) 22980b57cec5SDimitry Andric SavedRegs.set(ARM::R4); 22990b57cec5SDimitry Andric 23000b57cec5SDimitry Andric // If a stack probe will be emitted, spill R4 and LR, since they are 23010b57cec5SDimitry Andric // clobbered by the stack probe call. 23020b57cec5SDimitry Andric // This estimate should be a safe, conservative estimate. The actual 23030b57cec5SDimitry Andric // stack probe is enabled based on the size of the local objects; 23040b57cec5SDimitry Andric // this estimate also includes the varargs store size. 23050b57cec5SDimitry Andric if (STI.isTargetWindows() && 23060b57cec5SDimitry Andric WindowsRequiresStackProbe(MF, MFI.estimateStackSize(MF))) { 23070b57cec5SDimitry Andric SavedRegs.set(ARM::R4); 23080b57cec5SDimitry Andric SavedRegs.set(ARM::LR); 23090b57cec5SDimitry Andric } 23100b57cec5SDimitry Andric 23110b57cec5SDimitry Andric if (AFI->isThumb1OnlyFunction()) { 23120b57cec5SDimitry Andric // Spill LR if Thumb1 function uses variable length argument lists. 23130b57cec5SDimitry Andric if (AFI->getArgRegsSaveSize() > 0) 23140b57cec5SDimitry Andric SavedRegs.set(ARM::LR); 23150b57cec5SDimitry Andric 23160b57cec5SDimitry Andric // Spill R4 if Thumb1 epilogue has to restore SP from FP or the function 23170b57cec5SDimitry Andric // requires stack alignment. We don't know for sure what the stack size 23180b57cec5SDimitry Andric // will be, but for this, an estimate is good enough. If there anything 23190b57cec5SDimitry Andric // changes it, it'll be a spill, which implies we've used all the registers 23200b57cec5SDimitry Andric // and so R4 is already used, so not marking it here will be OK. 23210b57cec5SDimitry Andric // FIXME: It will be better just to find spare register here. 2322fe6060f1SDimitry Andric if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) || 23230b57cec5SDimitry Andric MFI.estimateStackSize(MF) > 508) 23240b57cec5SDimitry Andric SavedRegs.set(ARM::R4); 23250b57cec5SDimitry Andric } 23260b57cec5SDimitry Andric 23270b57cec5SDimitry Andric // See if we can spill vector registers to aligned stack. 23280b57cec5SDimitry Andric checkNumAlignedDPRCS2Regs(MF, SavedRegs); 23290b57cec5SDimitry Andric 23300b57cec5SDimitry Andric // Spill the BasePtr if it's used. 23310b57cec5SDimitry Andric if (RegInfo->hasBasePointer(MF)) 23320b57cec5SDimitry Andric SavedRegs.set(RegInfo->getBaseRegister()); 23330b57cec5SDimitry Andric 23345ffd83dbSDimitry Andric // On v8.1-M.Main CMSE entry functions save/restore FPCXT. 23355ffd83dbSDimitry Andric if (STI.hasV8_1MMainlineOps() && AFI->isCmseNSEntryFunction()) 23365ffd83dbSDimitry Andric CanEliminateFrame = false; 23375ffd83dbSDimitry Andric 23385f757f3fSDimitry Andric // When return address signing is enabled R12 is treated as callee-saved. 23395f757f3fSDimitry Andric if (AFI->shouldSignReturnAddress()) 23405f757f3fSDimitry Andric CanEliminateFrame = false; 23415f757f3fSDimitry Andric 23420b57cec5SDimitry Andric // Don't spill FP if the frame can be eliminated. This is determined 23430b57cec5SDimitry Andric // by scanning the callee-save registers to see if any is modified. 23440b57cec5SDimitry Andric const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF); 23450b57cec5SDimitry Andric for (unsigned i = 0; CSRegs[i]; ++i) { 23460b57cec5SDimitry Andric unsigned Reg = CSRegs[i]; 23470b57cec5SDimitry Andric bool Spilled = false; 23480b57cec5SDimitry Andric if (SavedRegs.test(Reg)) { 23490b57cec5SDimitry Andric Spilled = true; 23500b57cec5SDimitry Andric CanEliminateFrame = false; 23510b57cec5SDimitry Andric } 23520b57cec5SDimitry Andric 23530b57cec5SDimitry Andric if (!ARM::GPRRegClass.contains(Reg)) { 23540b57cec5SDimitry Andric if (Spilled) { 23550b57cec5SDimitry Andric if (ARM::SPRRegClass.contains(Reg)) 23560b57cec5SDimitry Andric NumFPRSpills++; 23570b57cec5SDimitry Andric else if (ARM::DPRRegClass.contains(Reg)) 23580b57cec5SDimitry Andric NumFPRSpills += 2; 23590b57cec5SDimitry Andric else if (ARM::QPRRegClass.contains(Reg)) 23600b57cec5SDimitry Andric NumFPRSpills += 4; 23610b57cec5SDimitry Andric } 23620b57cec5SDimitry Andric continue; 23630b57cec5SDimitry Andric } 23640b57cec5SDimitry Andric 23650b57cec5SDimitry Andric if (Spilled) { 23660b57cec5SDimitry Andric NumGPRSpills++; 23670b57cec5SDimitry Andric 23680b57cec5SDimitry Andric if (!STI.splitFramePushPop(MF)) { 23690b57cec5SDimitry Andric if (Reg == ARM::LR) 23700b57cec5SDimitry Andric LRSpilled = true; 23710b57cec5SDimitry Andric CS1Spilled = true; 23720b57cec5SDimitry Andric continue; 23730b57cec5SDimitry Andric } 23740b57cec5SDimitry Andric 23750b57cec5SDimitry Andric // Keep track if LR and any of R4, R5, R6, and R7 is spilled. 23760b57cec5SDimitry Andric switch (Reg) { 23770b57cec5SDimitry Andric case ARM::LR: 23780b57cec5SDimitry Andric LRSpilled = true; 2379bdd1243dSDimitry Andric [[fallthrough]]; 23800b57cec5SDimitry Andric case ARM::R0: case ARM::R1: 23810b57cec5SDimitry Andric case ARM::R2: case ARM::R3: 23820b57cec5SDimitry Andric case ARM::R4: case ARM::R5: 23830b57cec5SDimitry Andric case ARM::R6: case ARM::R7: 23840b57cec5SDimitry Andric CS1Spilled = true; 23850b57cec5SDimitry Andric break; 23860b57cec5SDimitry Andric default: 23870b57cec5SDimitry Andric break; 23880b57cec5SDimitry Andric } 23890b57cec5SDimitry Andric } else { 23900b57cec5SDimitry Andric if (!STI.splitFramePushPop(MF)) { 23910b57cec5SDimitry Andric UnspilledCS1GPRs.push_back(Reg); 23920b57cec5SDimitry Andric continue; 23930b57cec5SDimitry Andric } 23940b57cec5SDimitry Andric 23950b57cec5SDimitry Andric switch (Reg) { 23960b57cec5SDimitry Andric case ARM::R0: case ARM::R1: 23970b57cec5SDimitry Andric case ARM::R2: case ARM::R3: 23980b57cec5SDimitry Andric case ARM::R4: case ARM::R5: 23990b57cec5SDimitry Andric case ARM::R6: case ARM::R7: 24000b57cec5SDimitry Andric case ARM::LR: 24010b57cec5SDimitry Andric UnspilledCS1GPRs.push_back(Reg); 24020b57cec5SDimitry Andric break; 24030b57cec5SDimitry Andric default: 24040b57cec5SDimitry Andric UnspilledCS2GPRs.push_back(Reg); 24050b57cec5SDimitry Andric break; 24060b57cec5SDimitry Andric } 24070b57cec5SDimitry Andric } 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric 24100b57cec5SDimitry Andric bool ForceLRSpill = false; 24110b57cec5SDimitry Andric if (!LRSpilled && AFI->isThumb1OnlyFunction()) { 24120b57cec5SDimitry Andric unsigned FnSize = EstimateFunctionSizeInBytes(MF, TII); 24130b57cec5SDimitry Andric // Force LR to be spilled if the Thumb function size is > 2048. This enables 24145ffd83dbSDimitry Andric // use of BL to implement far jump. 24150b57cec5SDimitry Andric if (FnSize >= (1 << 11)) { 24160b57cec5SDimitry Andric CanEliminateFrame = false; 24170b57cec5SDimitry Andric ForceLRSpill = true; 24180b57cec5SDimitry Andric } 24190b57cec5SDimitry Andric } 24200b57cec5SDimitry Andric 24210b57cec5SDimitry Andric // If any of the stack slot references may be out of range of an immediate 24220b57cec5SDimitry Andric // offset, make sure a register (or a spill slot) is available for the 24230b57cec5SDimitry Andric // register scavenger. Note that if we're indexing off the frame pointer, the 24240b57cec5SDimitry Andric // effective stack size is 4 bytes larger since the FP points to the stack 24250b57cec5SDimitry Andric // slot of the previous FP. Also, if we have variable sized objects in the 24260b57cec5SDimitry Andric // function, stack slot references will often be negative, and some of 24270b57cec5SDimitry Andric // our instructions are positive-offset only, so conservatively consider 24280b57cec5SDimitry Andric // that case to want a spill slot (or register) as well. Similarly, if 24290b57cec5SDimitry Andric // the function adjusts the stack pointer during execution and the 24300b57cec5SDimitry Andric // adjustments aren't already part of our stack size estimate, our offset 24310b57cec5SDimitry Andric // calculations may be off, so be conservative. 24320b57cec5SDimitry Andric // FIXME: We could add logic to be more precise about negative offsets 24330b57cec5SDimitry Andric // and which instructions will need a scratch register for them. Is it 24340b57cec5SDimitry Andric // worth the effort and added fragility? 24350b57cec5SDimitry Andric unsigned EstimatedStackSize = 24360b57cec5SDimitry Andric MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills); 24370b57cec5SDimitry Andric 24380b57cec5SDimitry Andric // Determine biggest (positive) SP offset in MachineFrameInfo. 24390b57cec5SDimitry Andric int MaxFixedOffset = 0; 24400b57cec5SDimitry Andric for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) { 24410b57cec5SDimitry Andric int MaxObjectOffset = MFI.getObjectOffset(I) + MFI.getObjectSize(I); 24420b57cec5SDimitry Andric MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset); 24430b57cec5SDimitry Andric } 24440b57cec5SDimitry Andric 24450b57cec5SDimitry Andric bool HasFP = hasFP(MF); 24460b57cec5SDimitry Andric if (HasFP) { 24470b57cec5SDimitry Andric if (AFI->hasStackFrame()) 24480b57cec5SDimitry Andric EstimatedStackSize += 4; 24490b57cec5SDimitry Andric } else { 24500b57cec5SDimitry Andric // If FP is not used, SP will be used to access arguments, so count the 24510b57cec5SDimitry Andric // size of arguments into the estimation. 24520b57cec5SDimitry Andric EstimatedStackSize += MaxFixedOffset; 24530b57cec5SDimitry Andric } 24540b57cec5SDimitry Andric EstimatedStackSize += 16; // For possible paddings. 24550b57cec5SDimitry Andric 24560b57cec5SDimitry Andric unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit; 24578bcb0991SDimitry Andric bool HasNonSPFrameIndex = false; 24580b57cec5SDimitry Andric if (AFI->isThumb1OnlyFunction()) { 24590b57cec5SDimitry Andric // For Thumb1, don't bother to iterate over the function. The only 24600b57cec5SDimitry Andric // instruction that requires an emergency spill slot is a store to a 24610b57cec5SDimitry Andric // frame index. 24620b57cec5SDimitry Andric // 24630b57cec5SDimitry Andric // tSTRspi, which is used for sp-relative accesses, has an 8-bit unsigned 24640b57cec5SDimitry Andric // immediate. tSTRi, which is used for bp- and fp-relative accesses, has 24650b57cec5SDimitry Andric // a 5-bit unsigned immediate. 24660b57cec5SDimitry Andric // 24670b57cec5SDimitry Andric // We could try to check if the function actually contains a tSTRspi 24680b57cec5SDimitry Andric // that might need the spill slot, but it's not really important. 24690b57cec5SDimitry Andric // Functions with VLAs or extremely large call frames are rare, and 24700b57cec5SDimitry Andric // if a function is allocating more than 1KB of stack, an extra 4-byte 24710b57cec5SDimitry Andric // slot probably isn't relevant. 247281ad6265SDimitry Andric // 247381ad6265SDimitry Andric // A special case is the scenario where r11 is used as FP, where accesses 247481ad6265SDimitry Andric // to a frame index will require its value to be moved into a low reg. 247581ad6265SDimitry Andric // This is handled later on, once we are able to determine if we have any 247681ad6265SDimitry Andric // fp-relative accesses. 24770b57cec5SDimitry Andric if (RegInfo->hasBasePointer(MF)) 24780b57cec5SDimitry Andric EstimatedRSStackSizeLimit = (1U << 5) * 4; 24790b57cec5SDimitry Andric else 24800b57cec5SDimitry Andric EstimatedRSStackSizeLimit = (1U << 8) * 4; 24810b57cec5SDimitry Andric EstimatedRSFixedSizeLimit = (1U << 5) * 4; 24820b57cec5SDimitry Andric } else { 24838bcb0991SDimitry Andric EstimatedRSStackSizeLimit = 24848bcb0991SDimitry Andric estimateRSStackSizeLimit(MF, this, HasNonSPFrameIndex); 24850b57cec5SDimitry Andric EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit; 24860b57cec5SDimitry Andric } 24870b57cec5SDimitry Andric // Final estimate of whether sp or bp-relative accesses might require 24880b57cec5SDimitry Andric // scavenging. 24890b57cec5SDimitry Andric bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit; 24900b57cec5SDimitry Andric 24910b57cec5SDimitry Andric // If the stack pointer moves and we don't have a base pointer, the 24920b57cec5SDimitry Andric // estimate logic doesn't work. The actual offsets might be larger when 24930b57cec5SDimitry Andric // we're constructing a call frame, or we might need to use negative 24940b57cec5SDimitry Andric // offsets from fp. 24950b57cec5SDimitry Andric bool HasMovingSP = MFI.hasVarSizedObjects() || 24960b57cec5SDimitry Andric (MFI.adjustsStack() && !canSimplifyCallFramePseudos(MF)); 24970b57cec5SDimitry Andric bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP; 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric // If we have a frame pointer, we assume arguments will be accessed 25000b57cec5SDimitry Andric // relative to the frame pointer. Check whether fp-relative accesses to 25010b57cec5SDimitry Andric // arguments require scavenging. 25020b57cec5SDimitry Andric // 25030b57cec5SDimitry Andric // We could do slightly better on Thumb1; in some cases, an sp-relative 25040b57cec5SDimitry Andric // offset would be legal even though an fp-relative offset is not. 250581ad6265SDimitry Andric int MaxFPOffset = getMaxFPOffset(STI, *AFI, MF); 25060b57cec5SDimitry Andric bool HasLargeArgumentList = 25070b57cec5SDimitry Andric HasFP && (MaxFixedOffset - MaxFPOffset) > (int)EstimatedRSFixedSizeLimit; 25080b57cec5SDimitry Andric 25090b57cec5SDimitry Andric bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP || 25108bcb0991SDimitry Andric HasLargeArgumentList || HasNonSPFrameIndex; 25110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "EstimatedLimit: " << EstimatedRSStackSizeLimit 25128bcb0991SDimitry Andric << "; EstimatedStack: " << EstimatedStackSize 25138bcb0991SDimitry Andric << "; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset 25148bcb0991SDimitry Andric << "; BigFrameOffsets: " << BigFrameOffsets << "\n"); 25150b57cec5SDimitry Andric if (BigFrameOffsets || 25160b57cec5SDimitry Andric !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) { 25170b57cec5SDimitry Andric AFI->setHasStackFrame(true); 25180b57cec5SDimitry Andric 25190b57cec5SDimitry Andric if (HasFP) { 25200b57cec5SDimitry Andric SavedRegs.set(FramePtr); 25210b57cec5SDimitry Andric // If the frame pointer is required by the ABI, also spill LR so that we 25220b57cec5SDimitry Andric // emit a complete frame record. 252381ad6265SDimitry Andric if ((requiresAAPCSFrameRecord(MF) || 252481ad6265SDimitry Andric MF.getTarget().Options.DisableFramePointerElim(MF)) && 252581ad6265SDimitry Andric !LRSpilled) { 25260b57cec5SDimitry Andric SavedRegs.set(ARM::LR); 25270b57cec5SDimitry Andric LRSpilled = true; 25280b57cec5SDimitry Andric NumGPRSpills++; 25290b57cec5SDimitry Andric auto LRPos = llvm::find(UnspilledCS1GPRs, ARM::LR); 25300b57cec5SDimitry Andric if (LRPos != UnspilledCS1GPRs.end()) 25310b57cec5SDimitry Andric UnspilledCS1GPRs.erase(LRPos); 25320b57cec5SDimitry Andric } 25330b57cec5SDimitry Andric auto FPPos = llvm::find(UnspilledCS1GPRs, FramePtr); 25340b57cec5SDimitry Andric if (FPPos != UnspilledCS1GPRs.end()) 25350b57cec5SDimitry Andric UnspilledCS1GPRs.erase(FPPos); 25360b57cec5SDimitry Andric NumGPRSpills++; 25370b57cec5SDimitry Andric if (FramePtr == ARM::R7) 25380b57cec5SDimitry Andric CS1Spilled = true; 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric 25415f757f3fSDimitry Andric // This is the number of extra spills inserted for callee-save GPRs which 25425f757f3fSDimitry Andric // would not otherwise be used by the function. When greater than zero it 25435f757f3fSDimitry Andric // guaranteees that it is possible to scavenge a register to hold the 25445f757f3fSDimitry Andric // address of a stack slot. On Thumb1, the register must be a valid operand 25455f757f3fSDimitry Andric // to tSTRi, i.e. r4-r7. For other subtargets, this is any GPR, i.e. r4-r11 25465f757f3fSDimitry Andric // or lr. 25470b57cec5SDimitry Andric // 25480b57cec5SDimitry Andric // If we don't insert a spill, we instead allocate an emergency spill 25490b57cec5SDimitry Andric // slot, which can be used by scavenging to spill an arbitrary register. 25500b57cec5SDimitry Andric // 25510b57cec5SDimitry Andric // We currently don't try to figure out whether any specific instruction 25520b57cec5SDimitry Andric // requires scavening an additional register. 25535f757f3fSDimitry Andric unsigned NumExtraCSSpill = 0; 25540b57cec5SDimitry Andric 25550b57cec5SDimitry Andric if (AFI->isThumb1OnlyFunction()) { 25560b57cec5SDimitry Andric // For Thumb1-only targets, we need some low registers when we save and 25570b57cec5SDimitry Andric // restore the high registers (which aren't allocatable, but could be 25580b57cec5SDimitry Andric // used by inline assembly) because the push/pop instructions can not 25590b57cec5SDimitry Andric // access high registers. If necessary, we might need to push more low 25600b57cec5SDimitry Andric // registers to ensure that there is at least one free that can be used 25610b57cec5SDimitry Andric // for the saving & restoring, and preferably we should ensure that as 25620b57cec5SDimitry Andric // many as are needed are available so that fewer push/pop instructions 25630b57cec5SDimitry Andric // are required. 25640b57cec5SDimitry Andric 25650b57cec5SDimitry Andric // Low registers which are not currently pushed, but could be (r4-r7). 25660b57cec5SDimitry Andric SmallVector<unsigned, 4> AvailableRegs; 25670b57cec5SDimitry Andric 25680b57cec5SDimitry Andric // Unused argument registers (r0-r3) can be clobbered in the prologue for 25690b57cec5SDimitry Andric // free. 25700b57cec5SDimitry Andric int EntryRegDeficit = 0; 25710b57cec5SDimitry Andric for (unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) { 25720b57cec5SDimitry Andric if (!MF.getRegInfo().isLiveIn(Reg)) { 25730b57cec5SDimitry Andric --EntryRegDeficit; 25740b57cec5SDimitry Andric LLVM_DEBUG(dbgs() 25750b57cec5SDimitry Andric << printReg(Reg, TRI) 25760b57cec5SDimitry Andric << " is unused argument register, EntryRegDeficit = " 25770b57cec5SDimitry Andric << EntryRegDeficit << "\n"); 25780b57cec5SDimitry Andric } 25790b57cec5SDimitry Andric } 25800b57cec5SDimitry Andric 25810b57cec5SDimitry Andric // Unused return registers can be clobbered in the epilogue for free. 25820b57cec5SDimitry Andric int ExitRegDeficit = AFI->getReturnRegsCount() - 4; 25830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << AFI->getReturnRegsCount() 25840b57cec5SDimitry Andric << " return regs used, ExitRegDeficit = " 25850b57cec5SDimitry Andric << ExitRegDeficit << "\n"); 25860b57cec5SDimitry Andric 25870b57cec5SDimitry Andric int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit); 25880b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RegDeficit = " << RegDeficit << "\n"); 25890b57cec5SDimitry Andric 25900b57cec5SDimitry Andric // r4-r6 can be used in the prologue if they are pushed by the first push 25910b57cec5SDimitry Andric // instruction. 25920b57cec5SDimitry Andric for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) { 25930b57cec5SDimitry Andric if (SavedRegs.test(Reg)) { 25940b57cec5SDimitry Andric --RegDeficit; 25950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(Reg, TRI) 25960b57cec5SDimitry Andric << " is saved low register, RegDeficit = " 25970b57cec5SDimitry Andric << RegDeficit << "\n"); 25980b57cec5SDimitry Andric } else { 25990b57cec5SDimitry Andric AvailableRegs.push_back(Reg); 26000b57cec5SDimitry Andric LLVM_DEBUG( 26010b57cec5SDimitry Andric dbgs() 26020b57cec5SDimitry Andric << printReg(Reg, TRI) 26030b57cec5SDimitry Andric << " is non-saved low register, adding to AvailableRegs\n"); 26040b57cec5SDimitry Andric } 26050b57cec5SDimitry Andric } 26060b57cec5SDimitry Andric 26070b57cec5SDimitry Andric // r7 can be used if it is not being used as the frame pointer. 260881ad6265SDimitry Andric if (!HasFP || FramePtr != ARM::R7) { 26090b57cec5SDimitry Andric if (SavedRegs.test(ARM::R7)) { 26100b57cec5SDimitry Andric --RegDeficit; 26110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "%r7 is saved low register, RegDeficit = " 26120b57cec5SDimitry Andric << RegDeficit << "\n"); 26130b57cec5SDimitry Andric } else { 26140b57cec5SDimitry Andric AvailableRegs.push_back(ARM::R7); 26150b57cec5SDimitry Andric LLVM_DEBUG( 26160b57cec5SDimitry Andric dbgs() 26170b57cec5SDimitry Andric << "%r7 is non-saved low register, adding to AvailableRegs\n"); 26180b57cec5SDimitry Andric } 26190b57cec5SDimitry Andric } 26200b57cec5SDimitry Andric 26210b57cec5SDimitry Andric // Each of r8-r11 needs to be copied to a low register, then pushed. 26220b57cec5SDimitry Andric for (unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) { 26230b57cec5SDimitry Andric if (SavedRegs.test(Reg)) { 26240b57cec5SDimitry Andric ++RegDeficit; 26250b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printReg(Reg, TRI) 26260b57cec5SDimitry Andric << " is saved high register, RegDeficit = " 26270b57cec5SDimitry Andric << RegDeficit << "\n"); 26280b57cec5SDimitry Andric } 26290b57cec5SDimitry Andric } 26300b57cec5SDimitry Andric 26310b57cec5SDimitry Andric // LR can only be used by PUSH, not POP, and can't be used at all if the 26320b57cec5SDimitry Andric // llvm.returnaddress intrinsic is used. This is only worth doing if we 26330b57cec5SDimitry Andric // are more limited at function entry than exit. 26340b57cec5SDimitry Andric if ((EntryRegDeficit > ExitRegDeficit) && 26350b57cec5SDimitry Andric !(MF.getRegInfo().isLiveIn(ARM::LR) && 26360b57cec5SDimitry Andric MF.getFrameInfo().isReturnAddressTaken())) { 26370b57cec5SDimitry Andric if (SavedRegs.test(ARM::LR)) { 26380b57cec5SDimitry Andric --RegDeficit; 26390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "%lr is saved register, RegDeficit = " 26400b57cec5SDimitry Andric << RegDeficit << "\n"); 26410b57cec5SDimitry Andric } else { 26420b57cec5SDimitry Andric AvailableRegs.push_back(ARM::LR); 26430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "%lr is not saved, adding to AvailableRegs\n"); 26440b57cec5SDimitry Andric } 26450b57cec5SDimitry Andric } 26460b57cec5SDimitry Andric 26470b57cec5SDimitry Andric // If there are more high registers that need pushing than low registers 26480b57cec5SDimitry Andric // available, push some more low registers so that we can use fewer push 26490b57cec5SDimitry Andric // instructions. This might not reduce RegDeficit all the way to zero, 26500b57cec5SDimitry Andric // because we can only guarantee that r4-r6 are available, but r8-r11 may 26510b57cec5SDimitry Andric // need saving. 26520b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Final RegDeficit = " << RegDeficit << "\n"); 26530b57cec5SDimitry Andric for (; RegDeficit > 0 && !AvailableRegs.empty(); --RegDeficit) { 26540b57cec5SDimitry Andric unsigned Reg = AvailableRegs.pop_back_val(); 26550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, TRI) 26560b57cec5SDimitry Andric << " to make up reg deficit\n"); 26570b57cec5SDimitry Andric SavedRegs.set(Reg); 26580b57cec5SDimitry Andric NumGPRSpills++; 26590b57cec5SDimitry Andric CS1Spilled = true; 26600b57cec5SDimitry Andric assert(!MRI.isReserved(Reg) && "Should not be reserved"); 26610b57cec5SDimitry Andric if (Reg != ARM::LR && !MRI.isPhysRegUsed(Reg)) 26625f757f3fSDimitry Andric NumExtraCSSpill++; 26630b57cec5SDimitry Andric UnspilledCS1GPRs.erase(llvm::find(UnspilledCS1GPRs, Reg)); 26640b57cec5SDimitry Andric if (Reg == ARM::LR) 26650b57cec5SDimitry Andric LRSpilled = true; 26660b57cec5SDimitry Andric } 26670b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "After adding spills, RegDeficit = " << RegDeficit 26680b57cec5SDimitry Andric << "\n"); 26690b57cec5SDimitry Andric } 26700b57cec5SDimitry Andric 26710b57cec5SDimitry Andric // Avoid spilling LR in Thumb1 if there's a tail call: it's expensive to 26720b57cec5SDimitry Andric // restore LR in that case. 26730b57cec5SDimitry Andric bool ExpensiveLRRestore = AFI->isThumb1OnlyFunction() && MFI.hasTailCall(); 26740b57cec5SDimitry Andric 26750b57cec5SDimitry Andric // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled. 26760b57cec5SDimitry Andric // Spill LR as well so we can fold BX_RET to the registers restore (LDM). 26770b57cec5SDimitry Andric if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) { 26780b57cec5SDimitry Andric SavedRegs.set(ARM::LR); 26790b57cec5SDimitry Andric NumGPRSpills++; 26800b57cec5SDimitry Andric SmallVectorImpl<unsigned>::iterator LRPos; 26810b57cec5SDimitry Andric LRPos = llvm::find(UnspilledCS1GPRs, (unsigned)ARM::LR); 26820b57cec5SDimitry Andric if (LRPos != UnspilledCS1GPRs.end()) 26830b57cec5SDimitry Andric UnspilledCS1GPRs.erase(LRPos); 26840b57cec5SDimitry Andric 26850b57cec5SDimitry Andric ForceLRSpill = false; 26860b57cec5SDimitry Andric if (!MRI.isReserved(ARM::LR) && !MRI.isPhysRegUsed(ARM::LR) && 26870b57cec5SDimitry Andric !AFI->isThumb1OnlyFunction()) 26885f757f3fSDimitry Andric NumExtraCSSpill++; 26890b57cec5SDimitry Andric } 26900b57cec5SDimitry Andric 26910b57cec5SDimitry Andric // If stack and double are 8-byte aligned and we are spilling an odd number 26920b57cec5SDimitry Andric // of GPRs, spill one extra callee save GPR so we won't have to pad between 26930b57cec5SDimitry Andric // the integer and double callee save areas. 26940b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "NumGPRSpills = " << NumGPRSpills << "\n"); 26955ffd83dbSDimitry Andric const Align TargetAlign = getStackAlign(); 26965ffd83dbSDimitry Andric if (TargetAlign >= Align(8) && (NumGPRSpills & 1)) { 26970b57cec5SDimitry Andric if (CS1Spilled && !UnspilledCS1GPRs.empty()) { 2698cb14a3feSDimitry Andric for (unsigned Reg : UnspilledCS1GPRs) { 26990b57cec5SDimitry Andric // Don't spill high register if the function is thumb. In the case of 27000b57cec5SDimitry Andric // Windows on ARM, accept R11 (frame pointer) 27010b57cec5SDimitry Andric if (!AFI->isThumbFunction() || 27020b57cec5SDimitry Andric (STI.isTargetWindows() && Reg == ARM::R11) || 27030b57cec5SDimitry Andric isARMLowRegister(Reg) || 27040b57cec5SDimitry Andric (Reg == ARM::LR && !ExpensiveLRRestore)) { 27050b57cec5SDimitry Andric SavedRegs.set(Reg); 27060b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, TRI) 27070b57cec5SDimitry Andric << " to make up alignment\n"); 27080b57cec5SDimitry Andric if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg) && 27090b57cec5SDimitry Andric !(Reg == ARM::LR && AFI->isThumb1OnlyFunction())) 27105f757f3fSDimitry Andric NumExtraCSSpill++; 27110b57cec5SDimitry Andric break; 27120b57cec5SDimitry Andric } 27130b57cec5SDimitry Andric } 27140b57cec5SDimitry Andric } else if (!UnspilledCS2GPRs.empty() && !AFI->isThumb1OnlyFunction()) { 27150b57cec5SDimitry Andric unsigned Reg = UnspilledCS2GPRs.front(); 27160b57cec5SDimitry Andric SavedRegs.set(Reg); 27170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, TRI) 27180b57cec5SDimitry Andric << " to make up alignment\n"); 27190b57cec5SDimitry Andric if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg)) 27205f757f3fSDimitry Andric NumExtraCSSpill++; 27210b57cec5SDimitry Andric } 27220b57cec5SDimitry Andric } 27230b57cec5SDimitry Andric 27245f757f3fSDimitry Andric // Estimate if we might need to scavenge registers at some point in order 27250b57cec5SDimitry Andric // to materialize a stack offset. If so, either spill one additional 27260b57cec5SDimitry Andric // callee-saved register or reserve a special spill slot to facilitate 27270b57cec5SDimitry Andric // register scavenging. Thumb1 needs a spill slot for stack pointer 272881ad6265SDimitry Andric // adjustments and for frame index accesses when FP is high register, 272981ad6265SDimitry Andric // even when the frame itself is small. 27305f757f3fSDimitry Andric unsigned RegsNeeded = 0; 27315f757f3fSDimitry Andric if (BigFrameOffsets || canSpillOnFrameIndexAccess(MF, *this)) { 27325f757f3fSDimitry Andric RegsNeeded++; 27335f757f3fSDimitry Andric // With thumb1 execute-only we may need an additional register for saving 27345f757f3fSDimitry Andric // and restoring the CPSR. 27355f757f3fSDimitry Andric if (AFI->isThumb1OnlyFunction() && STI.genExecuteOnly() && !STI.useMovt()) 27365f757f3fSDimitry Andric RegsNeeded++; 27375f757f3fSDimitry Andric } 27385f757f3fSDimitry Andric 27395f757f3fSDimitry Andric if (RegsNeeded > NumExtraCSSpill) { 27400b57cec5SDimitry Andric // If any non-reserved CS register isn't spilled, just spill one or two 27410b57cec5SDimitry Andric // extra. That should take care of it! 27425ffd83dbSDimitry Andric unsigned NumExtras = TargetAlign.value() / 4; 27430b57cec5SDimitry Andric SmallVector<unsigned, 2> Extras; 27440b57cec5SDimitry Andric while (NumExtras && !UnspilledCS1GPRs.empty()) { 2745e8d8bef9SDimitry Andric unsigned Reg = UnspilledCS1GPRs.pop_back_val(); 27460b57cec5SDimitry Andric if (!MRI.isReserved(Reg) && 27470b57cec5SDimitry Andric (!AFI->isThumb1OnlyFunction() || isARMLowRegister(Reg))) { 27480b57cec5SDimitry Andric Extras.push_back(Reg); 27490b57cec5SDimitry Andric NumExtras--; 27500b57cec5SDimitry Andric } 27510b57cec5SDimitry Andric } 27520b57cec5SDimitry Andric // For non-Thumb1 functions, also check for hi-reg CS registers 27530b57cec5SDimitry Andric if (!AFI->isThumb1OnlyFunction()) { 27540b57cec5SDimitry Andric while (NumExtras && !UnspilledCS2GPRs.empty()) { 2755e8d8bef9SDimitry Andric unsigned Reg = UnspilledCS2GPRs.pop_back_val(); 27560b57cec5SDimitry Andric if (!MRI.isReserved(Reg)) { 27570b57cec5SDimitry Andric Extras.push_back(Reg); 27580b57cec5SDimitry Andric NumExtras--; 27590b57cec5SDimitry Andric } 27600b57cec5SDimitry Andric } 27610b57cec5SDimitry Andric } 27620b57cec5SDimitry Andric if (NumExtras == 0) { 27630b57cec5SDimitry Andric for (unsigned Reg : Extras) { 27640b57cec5SDimitry Andric SavedRegs.set(Reg); 27650b57cec5SDimitry Andric if (!MRI.isPhysRegUsed(Reg)) 27665f757f3fSDimitry Andric NumExtraCSSpill++; 27670b57cec5SDimitry Andric } 27680b57cec5SDimitry Andric } 27695f757f3fSDimitry Andric while ((RegsNeeded > NumExtraCSSpill) && RS) { 27700b57cec5SDimitry Andric // Reserve a slot closest to SP or frame pointer. 27710b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Reserving emergency spill slot\n"); 27720b57cec5SDimitry Andric const TargetRegisterClass &RC = ARM::GPRRegClass; 27730b57cec5SDimitry Andric unsigned Size = TRI->getSpillSize(RC); 27745ffd83dbSDimitry Andric Align Alignment = TRI->getSpillAlign(RC); 27755ffd83dbSDimitry Andric RS->addScavengingFrameIndex( 27765ffd83dbSDimitry Andric MFI.CreateStackObject(Size, Alignment, false)); 27775f757f3fSDimitry Andric --RegsNeeded; 27780b57cec5SDimitry Andric } 27790b57cec5SDimitry Andric } 27800b57cec5SDimitry Andric } 27810b57cec5SDimitry Andric 27825ffd83dbSDimitry Andric if (ForceLRSpill) 27830b57cec5SDimitry Andric SavedRegs.set(ARM::LR); 27840b57cec5SDimitry Andric AFI->setLRIsSpilled(SavedRegs.test(ARM::LR)); 2785480093f4SDimitry Andric } 2786480093f4SDimitry Andric 2787439352acSDimitry Andric void ARMFrameLowering::updateLRRestored(MachineFunction &MF) { 2788cb14a3feSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 2789cb14a3feSDimitry Andric if (!MFI.isCalleeSavedInfoValid()) 2790cb14a3feSDimitry Andric return; 2791cb14a3feSDimitry Andric 2792cb14a3feSDimitry Andric // Check if all terminators do not implicitly use LR. Then we can 'restore' LR 2793cb14a3feSDimitry Andric // into PC so it is not live out of the return block: Clear the Restored bit 2794cb14a3feSDimitry Andric // in that case. 2795cb14a3feSDimitry Andric for (CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) { 2796cb14a3feSDimitry Andric if (Info.getReg() != ARM::LR) 2797cb14a3feSDimitry Andric continue; 2798cb14a3feSDimitry Andric if (all_of(MF, [](const MachineBasicBlock &MBB) { 2799cb14a3feSDimitry Andric return all_of(MBB.terminators(), [](const MachineInstr &Term) { 2800cb14a3feSDimitry Andric return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET || 2801cb14a3feSDimitry Andric Term.getOpcode() == ARM::t2LDMIA_RET || 2802cb14a3feSDimitry Andric Term.getOpcode() == ARM::tPOP_RET; 2803cb14a3feSDimitry Andric }); 2804cb14a3feSDimitry Andric })) { 2805cb14a3feSDimitry Andric Info.setRestored(false); 2806cb14a3feSDimitry Andric break; 2807cb14a3feSDimitry Andric } 2808cb14a3feSDimitry Andric } 2809cb14a3feSDimitry Andric } 2810cb14a3feSDimitry Andric 2811439352acSDimitry Andric void ARMFrameLowering::processFunctionBeforeFrameFinalized( 2812439352acSDimitry Andric MachineFunction &MF, RegScavenger *RS) const { 2813439352acSDimitry Andric TargetFrameLowering::processFunctionBeforeFrameFinalized(MF, RS); 2814439352acSDimitry Andric updateLRRestored(MF); 2815439352acSDimitry Andric } 2816439352acSDimitry Andric 2817480093f4SDimitry Andric void ARMFrameLowering::getCalleeSaves(const MachineFunction &MF, 2818480093f4SDimitry Andric BitVector &SavedRegs) const { 2819480093f4SDimitry Andric TargetFrameLowering::getCalleeSaves(MF, SavedRegs); 28208bcb0991SDimitry Andric 28218bcb0991SDimitry Andric // If we have the "returned" parameter attribute which guarantees that we 28228bcb0991SDimitry Andric // return the value which was passed in r0 unmodified (e.g. C++ 'structors), 28238bcb0991SDimitry Andric // record that fact for IPRA. 2824480093f4SDimitry Andric const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 28258bcb0991SDimitry Andric if (AFI->getPreservesR0()) 28268bcb0991SDimitry Andric SavedRegs.set(ARM::R0); 28270b57cec5SDimitry Andric } 28280b57cec5SDimitry Andric 28295ffd83dbSDimitry Andric bool ARMFrameLowering::assignCalleeSavedSpillSlots( 28305ffd83dbSDimitry Andric MachineFunction &MF, const TargetRegisterInfo *TRI, 28315ffd83dbSDimitry Andric std::vector<CalleeSavedInfo> &CSI) const { 28325ffd83dbSDimitry Andric // For CMSE entry functions, handle floating-point context as if it was a 28335ffd83dbSDimitry Andric // callee-saved register. 28345ffd83dbSDimitry Andric if (STI.hasV8_1MMainlineOps() && 28355ffd83dbSDimitry Andric MF.getInfo<ARMFunctionInfo>()->isCmseNSEntryFunction()) { 28365ffd83dbSDimitry Andric CSI.emplace_back(ARM::FPCXTNS); 28375ffd83dbSDimitry Andric CSI.back().setRestored(false); 28385ffd83dbSDimitry Andric } 28395ffd83dbSDimitry Andric 28400eae32dcSDimitry Andric // For functions, which sign their return address, upon function entry, the 28410eae32dcSDimitry Andric // return address PAC is computed in R12. Treat R12 as a callee-saved register 28420eae32dcSDimitry Andric // in this case. 28430eae32dcSDimitry Andric const auto &AFI = *MF.getInfo<ARMFunctionInfo>(); 28440eae32dcSDimitry Andric if (AFI.shouldSignReturnAddress()) { 28450eae32dcSDimitry Andric // The order of register must match the order we push them, because the 28460eae32dcSDimitry Andric // PEI assigns frame indices in that order. When compiling for return 28470eae32dcSDimitry Andric // address sign and authenication, we use split push, therefore the orders 28480eae32dcSDimitry Andric // we want are: 28490eae32dcSDimitry Andric // LR, R7, R6, R5, R4, <R12>, R11, R10, R9, R8, D15-D8 28500eae32dcSDimitry Andric CSI.insert(find_if(CSI, 28510eae32dcSDimitry Andric [=](const auto &CS) { 285204eeddc0SDimitry Andric Register Reg = CS.getReg(); 28530eae32dcSDimitry Andric return Reg == ARM::R10 || Reg == ARM::R11 || 28540eae32dcSDimitry Andric Reg == ARM::R8 || Reg == ARM::R9 || 28550eae32dcSDimitry Andric ARM::DPRRegClass.contains(Reg); 28560eae32dcSDimitry Andric }), 28570eae32dcSDimitry Andric CalleeSavedInfo(ARM::R12)); 28580eae32dcSDimitry Andric } 28590eae32dcSDimitry Andric 28605ffd83dbSDimitry Andric return false; 28615ffd83dbSDimitry Andric } 28625ffd83dbSDimitry Andric 28635ffd83dbSDimitry Andric const TargetFrameLowering::SpillSlot * 28645ffd83dbSDimitry Andric ARMFrameLowering::getCalleeSavedSpillSlots(unsigned &NumEntries) const { 28655ffd83dbSDimitry Andric static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}}; 2866bdd1243dSDimitry Andric NumEntries = std::size(FixedSpillOffsets); 28675ffd83dbSDimitry Andric return FixedSpillOffsets; 28685ffd83dbSDimitry Andric } 28695ffd83dbSDimitry Andric 28700b57cec5SDimitry Andric MachineBasicBlock::iterator ARMFrameLowering::eliminateCallFramePseudoInstr( 28710b57cec5SDimitry Andric MachineFunction &MF, MachineBasicBlock &MBB, 28720b57cec5SDimitry Andric MachineBasicBlock::iterator I) const { 28730b57cec5SDimitry Andric const ARMBaseInstrInfo &TII = 28740b57cec5SDimitry Andric *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo()); 2875fe6060f1SDimitry Andric ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); 2876fe6060f1SDimitry Andric bool isARM = !AFI->isThumbFunction(); 2877fe6060f1SDimitry Andric DebugLoc dl = I->getDebugLoc(); 2878fe6060f1SDimitry Andric unsigned Opc = I->getOpcode(); 2879fe6060f1SDimitry Andric bool IsDestroy = Opc == TII.getCallFrameDestroyOpcode(); 2880fe6060f1SDimitry Andric unsigned CalleePopAmount = IsDestroy ? I->getOperand(1).getImm() : 0; 2881fe6060f1SDimitry Andric 2882fe6060f1SDimitry Andric assert(!AFI->isThumb1OnlyFunction() && 2883fe6060f1SDimitry Andric "This eliminateCallFramePseudoInstr does not support Thumb1!"); 2884fe6060f1SDimitry Andric 2885fe6060f1SDimitry Andric int PIdx = I->findFirstPredOperandIdx(); 2886fe6060f1SDimitry Andric ARMCC::CondCodes Pred = (PIdx == -1) 2887fe6060f1SDimitry Andric ? ARMCC::AL 2888fe6060f1SDimitry Andric : (ARMCC::CondCodes)I->getOperand(PIdx).getImm(); 2889fe6060f1SDimitry Andric unsigned PredReg = TII.getFramePred(*I); 2890fe6060f1SDimitry Andric 28910b57cec5SDimitry Andric if (!hasReservedCallFrame(MF)) { 2892fe6060f1SDimitry Andric // Bail early if the callee is expected to do the adjustment. 2893fe6060f1SDimitry Andric if (IsDestroy && CalleePopAmount != -1U) 2894fe6060f1SDimitry Andric return MBB.erase(I); 2895fe6060f1SDimitry Andric 28960b57cec5SDimitry Andric // If we have alloca, convert as follows: 28970b57cec5SDimitry Andric // ADJCALLSTACKDOWN -> sub, sp, sp, amount 28980b57cec5SDimitry Andric // ADJCALLSTACKUP -> add, sp, sp, amount 2899fe6060f1SDimitry Andric unsigned Amount = TII.getFrameSize(*I); 29000b57cec5SDimitry Andric if (Amount != 0) { 29010b57cec5SDimitry Andric // We need to keep the stack aligned properly. To do this, we round the 29020b57cec5SDimitry Andric // amount of space needed for the outgoing arguments up to the next 29030b57cec5SDimitry Andric // alignment boundary. 29040b57cec5SDimitry Andric Amount = alignSPAdjust(Amount); 29050b57cec5SDimitry Andric 29060b57cec5SDimitry Andric if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { 29070b57cec5SDimitry Andric emitSPUpdate(isARM, MBB, I, dl, TII, -Amount, MachineInstr::NoFlags, 29080b57cec5SDimitry Andric Pred, PredReg); 29090b57cec5SDimitry Andric } else { 29100b57cec5SDimitry Andric assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); 29110b57cec5SDimitry Andric emitSPUpdate(isARM, MBB, I, dl, TII, Amount, MachineInstr::NoFlags, 29120b57cec5SDimitry Andric Pred, PredReg); 29130b57cec5SDimitry Andric } 29140b57cec5SDimitry Andric } 2915fe6060f1SDimitry Andric } else if (CalleePopAmount != -1U) { 2916fe6060f1SDimitry Andric // If the calling convention demands that the callee pops arguments from the 2917fe6060f1SDimitry Andric // stack, we want to add it back if we have a reserved call frame. 2918fe6060f1SDimitry Andric emitSPUpdate(isARM, MBB, I, dl, TII, -CalleePopAmount, 2919fe6060f1SDimitry Andric MachineInstr::NoFlags, Pred, PredReg); 29200b57cec5SDimitry Andric } 29210b57cec5SDimitry Andric return MBB.erase(I); 29220b57cec5SDimitry Andric } 29230b57cec5SDimitry Andric 29240b57cec5SDimitry Andric /// Get the minimum constant for ARM that is greater than or equal to the 29250b57cec5SDimitry Andric /// argument. In ARM, constants can have any value that can be produced by 29260b57cec5SDimitry Andric /// rotating an 8-bit value to the right by an even number of bits within a 29270b57cec5SDimitry Andric /// 32-bit word. 29280b57cec5SDimitry Andric static uint32_t alignToARMConstant(uint32_t Value) { 29290b57cec5SDimitry Andric unsigned Shifted = 0; 29300b57cec5SDimitry Andric 29310b57cec5SDimitry Andric if (Value == 0) 29320b57cec5SDimitry Andric return 0; 29330b57cec5SDimitry Andric 29340b57cec5SDimitry Andric while (!(Value & 0xC0000000)) { 29350b57cec5SDimitry Andric Value = Value << 2; 29360b57cec5SDimitry Andric Shifted += 2; 29370b57cec5SDimitry Andric } 29380b57cec5SDimitry Andric 29390b57cec5SDimitry Andric bool Carry = (Value & 0x00FFFFFF); 29400b57cec5SDimitry Andric Value = ((Value & 0xFF000000) >> 24) + Carry; 29410b57cec5SDimitry Andric 29420b57cec5SDimitry Andric if (Value & 0x0000100) 29430b57cec5SDimitry Andric Value = Value & 0x000001FC; 29440b57cec5SDimitry Andric 29450b57cec5SDimitry Andric if (Shifted > 24) 29460b57cec5SDimitry Andric Value = Value >> (Shifted - 24); 29470b57cec5SDimitry Andric else 29480b57cec5SDimitry Andric Value = Value << (24 - Shifted); 29490b57cec5SDimitry Andric 29500b57cec5SDimitry Andric return Value; 29510b57cec5SDimitry Andric } 29520b57cec5SDimitry Andric 29530b57cec5SDimitry Andric // The stack limit in the TCB is set to this many bytes above the actual 29540b57cec5SDimitry Andric // stack limit. 29550b57cec5SDimitry Andric static const uint64_t kSplitStackAvailable = 256; 29560b57cec5SDimitry Andric 29570b57cec5SDimitry Andric // Adjust the function prologue to enable split stacks. This currently only 29580b57cec5SDimitry Andric // supports android and linux. 29590b57cec5SDimitry Andric // 29600b57cec5SDimitry Andric // The ABI of the segmented stack prologue is a little arbitrarily chosen, but 29610b57cec5SDimitry Andric // must be well defined in order to allow for consistent implementations of the 29620b57cec5SDimitry Andric // __morestack helper function. The ABI is also not a normal ABI in that it 29630b57cec5SDimitry Andric // doesn't follow the normal calling conventions because this allows the 29640b57cec5SDimitry Andric // prologue of each function to be optimized further. 29650b57cec5SDimitry Andric // 29660b57cec5SDimitry Andric // Currently, the ABI looks like (when calling __morestack) 29670b57cec5SDimitry Andric // 29680b57cec5SDimitry Andric // * r4 holds the minimum stack size requested for this function call 29690b57cec5SDimitry Andric // * r5 holds the stack size of the arguments to the function 29700b57cec5SDimitry Andric // * the beginning of the function is 3 instructions after the call to 29710b57cec5SDimitry Andric // __morestack 29720b57cec5SDimitry Andric // 29730b57cec5SDimitry Andric // Implementations of __morestack should use r4 to allocate a new stack, r5 to 29740b57cec5SDimitry Andric // place the arguments on to the new stack, and the 3-instruction knowledge to 29750b57cec5SDimitry Andric // jump directly to the body of the function when working on the new stack. 29760b57cec5SDimitry Andric // 29770b57cec5SDimitry Andric // An old (and possibly no longer compatible) implementation of __morestack for 29780b57cec5SDimitry Andric // ARM can be found at [1]. 29790b57cec5SDimitry Andric // 29800b57cec5SDimitry Andric // [1] - https://github.com/mozilla/rust/blob/86efd9/src/rt/arch/arm/morestack.S 29810b57cec5SDimitry Andric void ARMFrameLowering::adjustForSegmentedStacks( 29820b57cec5SDimitry Andric MachineFunction &MF, MachineBasicBlock &PrologueMBB) const { 29830b57cec5SDimitry Andric unsigned Opcode; 29840b57cec5SDimitry Andric unsigned CFIIndex; 29850b57cec5SDimitry Andric const ARMSubtarget *ST = &MF.getSubtarget<ARMSubtarget>(); 29860b57cec5SDimitry Andric bool Thumb = ST->isThumb(); 298781ad6265SDimitry Andric bool Thumb2 = ST->isThumb2(); 29880b57cec5SDimitry Andric 29890b57cec5SDimitry Andric // Sadly, this currently doesn't support varargs, platforms other than 29900b57cec5SDimitry Andric // android/linux. Note that thumb1/thumb2 are support for android/linux. 29910b57cec5SDimitry Andric if (MF.getFunction().isVarArg()) 29920b57cec5SDimitry Andric report_fatal_error("Segmented stacks do not support vararg functions."); 29930b57cec5SDimitry Andric if (!ST->isTargetAndroid() && !ST->isTargetLinux()) 29940b57cec5SDimitry Andric report_fatal_error("Segmented stacks not supported on this platform."); 29950b57cec5SDimitry Andric 29960b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 29970fca6ea1SDimitry Andric MCContext &Context = MF.getContext(); 29980b57cec5SDimitry Andric const MCRegisterInfo *MRI = Context.getRegisterInfo(); 29990b57cec5SDimitry Andric const ARMBaseInstrInfo &TII = 30000b57cec5SDimitry Andric *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo()); 30010b57cec5SDimitry Andric ARMFunctionInfo *ARMFI = MF.getInfo<ARMFunctionInfo>(); 30020b57cec5SDimitry Andric DebugLoc DL; 30030b57cec5SDimitry Andric 300481ad6265SDimitry Andric if (!MFI.needsSplitStackProlog()) 30050b57cec5SDimitry Andric return; 300681ad6265SDimitry Andric 300781ad6265SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 30080b57cec5SDimitry Andric 30090b57cec5SDimitry Andric // Use R4 and R5 as scratch registers. 30100b57cec5SDimitry Andric // We save R4 and R5 before use and restore them before leaving the function. 30110b57cec5SDimitry Andric unsigned ScratchReg0 = ARM::R4; 30120b57cec5SDimitry Andric unsigned ScratchReg1 = ARM::R5; 30135f757f3fSDimitry Andric unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm; 30140b57cec5SDimitry Andric uint64_t AlignedStackSize; 30150b57cec5SDimitry Andric 30160b57cec5SDimitry Andric MachineBasicBlock *PrevStackMBB = MF.CreateMachineBasicBlock(); 30170b57cec5SDimitry Andric MachineBasicBlock *PostStackMBB = MF.CreateMachineBasicBlock(); 30180b57cec5SDimitry Andric MachineBasicBlock *AllocMBB = MF.CreateMachineBasicBlock(); 30190b57cec5SDimitry Andric MachineBasicBlock *GetMBB = MF.CreateMachineBasicBlock(); 30200b57cec5SDimitry Andric MachineBasicBlock *McrMBB = MF.CreateMachineBasicBlock(); 30210b57cec5SDimitry Andric 30220b57cec5SDimitry Andric // Grab everything that reaches PrologueMBB to update there liveness as well. 30230b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> BeforePrologueRegion; 30240b57cec5SDimitry Andric SmallVector<MachineBasicBlock *, 2> WalkList; 30250b57cec5SDimitry Andric WalkList.push_back(&PrologueMBB); 30260b57cec5SDimitry Andric 30270b57cec5SDimitry Andric do { 30280b57cec5SDimitry Andric MachineBasicBlock *CurMBB = WalkList.pop_back_val(); 30290b57cec5SDimitry Andric for (MachineBasicBlock *PredBB : CurMBB->predecessors()) { 30300b57cec5SDimitry Andric if (BeforePrologueRegion.insert(PredBB).second) 30310b57cec5SDimitry Andric WalkList.push_back(PredBB); 30320b57cec5SDimitry Andric } 30330b57cec5SDimitry Andric } while (!WalkList.empty()); 30340b57cec5SDimitry Andric 30350b57cec5SDimitry Andric // The order in that list is important. 30360b57cec5SDimitry Andric // The blocks will all be inserted before PrologueMBB using that order. 30370b57cec5SDimitry Andric // Therefore the block that should appear first in the CFG should appear 30380b57cec5SDimitry Andric // first in the list. 30390b57cec5SDimitry Andric MachineBasicBlock *AddedBlocks[] = {PrevStackMBB, McrMBB, GetMBB, AllocMBB, 30400b57cec5SDimitry Andric PostStackMBB}; 30410b57cec5SDimitry Andric 30420b57cec5SDimitry Andric for (MachineBasicBlock *B : AddedBlocks) 30430b57cec5SDimitry Andric BeforePrologueRegion.insert(B); 30440b57cec5SDimitry Andric 30450b57cec5SDimitry Andric for (const auto &LI : PrologueMBB.liveins()) { 30460b57cec5SDimitry Andric for (MachineBasicBlock *PredBB : BeforePrologueRegion) 30470b57cec5SDimitry Andric PredBB->addLiveIn(LI); 30480b57cec5SDimitry Andric } 30490b57cec5SDimitry Andric 30500b57cec5SDimitry Andric // Remove the newly added blocks from the list, since we know 30510b57cec5SDimitry Andric // we do not have to do the following updates for them. 30520b57cec5SDimitry Andric for (MachineBasicBlock *B : AddedBlocks) { 30530b57cec5SDimitry Andric BeforePrologueRegion.erase(B); 30540b57cec5SDimitry Andric MF.insert(PrologueMBB.getIterator(), B); 30550b57cec5SDimitry Andric } 30560b57cec5SDimitry Andric 30570b57cec5SDimitry Andric for (MachineBasicBlock *MBB : BeforePrologueRegion) { 30580b57cec5SDimitry Andric // Make sure the LiveIns are still sorted and unique. 30590b57cec5SDimitry Andric MBB->sortUniqueLiveIns(); 30600b57cec5SDimitry Andric // Replace the edges to PrologueMBB by edges to the sequences 306181ad6265SDimitry Andric // we are about to add, but only update for immediate predecessors. 306281ad6265SDimitry Andric if (MBB->isSuccessor(&PrologueMBB)) 30630b57cec5SDimitry Andric MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]); 30640b57cec5SDimitry Andric } 30650b57cec5SDimitry Andric 30660b57cec5SDimitry Andric // The required stack size that is aligned to ARM constant criterion. 30670b57cec5SDimitry Andric AlignedStackSize = alignToARMConstant(StackSize); 30680b57cec5SDimitry Andric 30690b57cec5SDimitry Andric // When the frame size is less than 256 we just compare the stack 30700b57cec5SDimitry Andric // boundary directly to the value of the stack pointer, per gcc. 30710b57cec5SDimitry Andric bool CompareStackPointer = AlignedStackSize < kSplitStackAvailable; 30720b57cec5SDimitry Andric 30730b57cec5SDimitry Andric // We will use two of the callee save registers as scratch registers so we 30740b57cec5SDimitry Andric // need to save those registers onto the stack. 30750b57cec5SDimitry Andric // We will use SR0 to hold stack limit and SR1 to hold the stack size 30760b57cec5SDimitry Andric // requested and arguments for __morestack(). 30770b57cec5SDimitry Andric // SR0: Scratch Register #0 30780b57cec5SDimitry Andric // SR1: Scratch Register #1 30790b57cec5SDimitry Andric // push {SR0, SR1} 30800b57cec5SDimitry Andric if (Thumb) { 30810b57cec5SDimitry Andric BuildMI(PrevStackMBB, DL, TII.get(ARM::tPUSH)) 30820b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 30830b57cec5SDimitry Andric .addReg(ScratchReg0) 30840b57cec5SDimitry Andric .addReg(ScratchReg1); 30850b57cec5SDimitry Andric } else { 30860b57cec5SDimitry Andric BuildMI(PrevStackMBB, DL, TII.get(ARM::STMDB_UPD)) 30870b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Define) 30880b57cec5SDimitry Andric .addReg(ARM::SP) 30890b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 30900b57cec5SDimitry Andric .addReg(ScratchReg0) 30910b57cec5SDimitry Andric .addReg(ScratchReg1); 30920b57cec5SDimitry Andric } 30930b57cec5SDimitry Andric 30940b57cec5SDimitry Andric // Emit the relevant DWARF information about the change in stack pointer as 30950b57cec5SDimitry Andric // well as where to find both r4 and r5 (the callee-save registers) 309681ad6265SDimitry Andric if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI()) { 30975ffd83dbSDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 8)); 30980b57cec5SDimitry Andric BuildMI(PrevStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 30990b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 31000b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 31010b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(ScratchReg1, true), -4)); 31020b57cec5SDimitry Andric BuildMI(PrevStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 31030b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 31040b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 31050b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(ScratchReg0, true), -8)); 31060b57cec5SDimitry Andric BuildMI(PrevStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 31070b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 310881ad6265SDimitry Andric } 31090b57cec5SDimitry Andric 31100b57cec5SDimitry Andric // mov SR1, sp 31110b57cec5SDimitry Andric if (Thumb) { 31120b57cec5SDimitry Andric BuildMI(McrMBB, DL, TII.get(ARM::tMOVr), ScratchReg1) 31130b57cec5SDimitry Andric .addReg(ARM::SP) 31140b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 31150b57cec5SDimitry Andric } else if (CompareStackPointer) { 31160b57cec5SDimitry Andric BuildMI(McrMBB, DL, TII.get(ARM::MOVr), ScratchReg1) 31170b57cec5SDimitry Andric .addReg(ARM::SP) 31180b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 31190b57cec5SDimitry Andric .add(condCodeOp()); 31200b57cec5SDimitry Andric } 31210b57cec5SDimitry Andric 31220b57cec5SDimitry Andric // sub SR1, sp, #StackSize 31230b57cec5SDimitry Andric if (!CompareStackPointer && Thumb) { 312481ad6265SDimitry Andric if (AlignedStackSize < 256) { 31250b57cec5SDimitry Andric BuildMI(McrMBB, DL, TII.get(ARM::tSUBi8), ScratchReg1) 31260b57cec5SDimitry Andric .add(condCodeOp()) 31270b57cec5SDimitry Andric .addReg(ScratchReg1) 31280b57cec5SDimitry Andric .addImm(AlignedStackSize) 31290b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 313081ad6265SDimitry Andric } else { 31315f757f3fSDimitry Andric if (Thumb2 || ST->genExecuteOnly()) { 31325f757f3fSDimitry Andric BuildMI(McrMBB, DL, TII.get(MovOp), ScratchReg0) 313381ad6265SDimitry Andric .addImm(AlignedStackSize); 313481ad6265SDimitry Andric } else { 313581ad6265SDimitry Andric auto MBBI = McrMBB->end(); 313681ad6265SDimitry Andric auto RegInfo = STI.getRegisterInfo(); 313781ad6265SDimitry Andric RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0, 313881ad6265SDimitry Andric AlignedStackSize); 313981ad6265SDimitry Andric } 314081ad6265SDimitry Andric BuildMI(McrMBB, DL, TII.get(ARM::tSUBrr), ScratchReg1) 314181ad6265SDimitry Andric .add(condCodeOp()) 314281ad6265SDimitry Andric .addReg(ScratchReg1) 314381ad6265SDimitry Andric .addReg(ScratchReg0) 314481ad6265SDimitry Andric .add(predOps(ARMCC::AL)); 314581ad6265SDimitry Andric } 31460b57cec5SDimitry Andric } else if (!CompareStackPointer) { 314781ad6265SDimitry Andric if (AlignedStackSize < 256) { 31480b57cec5SDimitry Andric BuildMI(McrMBB, DL, TII.get(ARM::SUBri), ScratchReg1) 31490b57cec5SDimitry Andric .addReg(ARM::SP) 31500b57cec5SDimitry Andric .addImm(AlignedStackSize) 31510b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 31520b57cec5SDimitry Andric .add(condCodeOp()); 315381ad6265SDimitry Andric } else { 315481ad6265SDimitry Andric auto MBBI = McrMBB->end(); 315581ad6265SDimitry Andric auto RegInfo = STI.getRegisterInfo(); 315681ad6265SDimitry Andric RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0, 315781ad6265SDimitry Andric AlignedStackSize); 315881ad6265SDimitry Andric BuildMI(McrMBB, DL, TII.get(ARM::SUBrr), ScratchReg1) 315981ad6265SDimitry Andric .addReg(ARM::SP) 316081ad6265SDimitry Andric .addReg(ScratchReg0) 316181ad6265SDimitry Andric .add(predOps(ARMCC::AL)) 316281ad6265SDimitry Andric .add(condCodeOp()); 316381ad6265SDimitry Andric } 31640b57cec5SDimitry Andric } 31650b57cec5SDimitry Andric 31660b57cec5SDimitry Andric if (Thumb && ST->isThumb1Only()) { 31675f757f3fSDimitry Andric if (ST->genExecuteOnly()) { 31685f757f3fSDimitry Andric BuildMI(GetMBB, DL, TII.get(MovOp), ScratchReg0) 31695f757f3fSDimitry Andric .addExternalSymbol("__STACK_LIMIT"); 31705f757f3fSDimitry Andric } else { 31710b57cec5SDimitry Andric unsigned PCLabelId = ARMFI->createPICLabelUId(); 31720b57cec5SDimitry Andric ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol::Create( 31730b57cec5SDimitry Andric MF.getFunction().getContext(), "__STACK_LIMIT", PCLabelId, 0); 31740b57cec5SDimitry Andric MachineConstantPool *MCP = MF.getConstantPool(); 31755ffd83dbSDimitry Andric unsigned CPI = MCP->getConstantPoolIndex(NewCPV, Align(4)); 31760b57cec5SDimitry Andric 31770b57cec5SDimitry Andric // ldr SR0, [pc, offset(STACK_LIMIT)] 31780b57cec5SDimitry Andric BuildMI(GetMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0) 31790b57cec5SDimitry Andric .addConstantPoolIndex(CPI) 31800b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 31815f757f3fSDimitry Andric } 31820b57cec5SDimitry Andric 31830b57cec5SDimitry Andric // ldr SR0, [SR0] 31840b57cec5SDimitry Andric BuildMI(GetMBB, DL, TII.get(ARM::tLDRi), ScratchReg0) 31850b57cec5SDimitry Andric .addReg(ScratchReg0) 31860b57cec5SDimitry Andric .addImm(0) 31870b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 31880b57cec5SDimitry Andric } else { 31890b57cec5SDimitry Andric // Get TLS base address from the coprocessor 31900b57cec5SDimitry Andric // mrc p15, #0, SR0, c13, c0, #3 3191480093f4SDimitry Andric BuildMI(McrMBB, DL, TII.get(Thumb ? ARM::t2MRC : ARM::MRC), 3192480093f4SDimitry Andric ScratchReg0) 31930b57cec5SDimitry Andric .addImm(15) 31940b57cec5SDimitry Andric .addImm(0) 31950b57cec5SDimitry Andric .addImm(13) 31960b57cec5SDimitry Andric .addImm(0) 31970b57cec5SDimitry Andric .addImm(3) 31980b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 31990b57cec5SDimitry Andric 32000b57cec5SDimitry Andric // Use the last tls slot on android and a private field of the TCP on linux. 32010b57cec5SDimitry Andric assert(ST->isTargetAndroid() || ST->isTargetLinux()); 32020b57cec5SDimitry Andric unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1; 32030b57cec5SDimitry Andric 32040b57cec5SDimitry Andric // Get the stack limit from the right offset 32050b57cec5SDimitry Andric // ldr SR0, [sr0, #4 * TlsOffset] 3206480093f4SDimitry Andric BuildMI(GetMBB, DL, TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12), 3207480093f4SDimitry Andric ScratchReg0) 32080b57cec5SDimitry Andric .addReg(ScratchReg0) 32090b57cec5SDimitry Andric .addImm(4 * TlsOffset) 32100b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 32110b57cec5SDimitry Andric } 32120b57cec5SDimitry Andric 32130b57cec5SDimitry Andric // Compare stack limit with stack size requested. 32140b57cec5SDimitry Andric // cmp SR0, SR1 32150b57cec5SDimitry Andric Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr; 32160b57cec5SDimitry Andric BuildMI(GetMBB, DL, TII.get(Opcode)) 32170b57cec5SDimitry Andric .addReg(ScratchReg0) 32180b57cec5SDimitry Andric .addReg(ScratchReg1) 32190b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 32200b57cec5SDimitry Andric 322106c3fb27SDimitry Andric // This jump is taken if StackLimit <= SP - stack required. 32220b57cec5SDimitry Andric Opcode = Thumb ? ARM::tBcc : ARM::Bcc; 322306c3fb27SDimitry Andric BuildMI(GetMBB, DL, TII.get(Opcode)) 322406c3fb27SDimitry Andric .addMBB(PostStackMBB) 322506c3fb27SDimitry Andric .addImm(ARMCC::LS) 32260b57cec5SDimitry Andric .addReg(ARM::CPSR); 32270b57cec5SDimitry Andric 32280b57cec5SDimitry Andric // Calling __morestack(StackSize, Size of stack arguments). 32290b57cec5SDimitry Andric // __morestack knows that the stack size requested is in SR0(r4) 32300b57cec5SDimitry Andric // and amount size of stack arguments is in SR1(r5). 32310b57cec5SDimitry Andric 32320b57cec5SDimitry Andric // Pass first argument for the __morestack by Scratch Register #0. 32330b57cec5SDimitry Andric // The amount size of stack required 32340b57cec5SDimitry Andric if (Thumb) { 323581ad6265SDimitry Andric if (AlignedStackSize < 256) { 32360b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg0) 32370b57cec5SDimitry Andric .add(condCodeOp()) 32380b57cec5SDimitry Andric .addImm(AlignedStackSize) 32390b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 32400b57cec5SDimitry Andric } else { 32415f757f3fSDimitry Andric if (Thumb2 || ST->genExecuteOnly()) { 32425f757f3fSDimitry Andric BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg0) 324381ad6265SDimitry Andric .addImm(AlignedStackSize); 324481ad6265SDimitry Andric } else { 324581ad6265SDimitry Andric auto MBBI = AllocMBB->end(); 324681ad6265SDimitry Andric auto RegInfo = STI.getRegisterInfo(); 324781ad6265SDimitry Andric RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0, 324881ad6265SDimitry Andric AlignedStackSize); 324981ad6265SDimitry Andric } 325081ad6265SDimitry Andric } 325181ad6265SDimitry Andric } else { 325281ad6265SDimitry Andric if (AlignedStackSize < 256) { 32530b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg0) 32540b57cec5SDimitry Andric .addImm(AlignedStackSize) 32550b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 32560b57cec5SDimitry Andric .add(condCodeOp()); 325781ad6265SDimitry Andric } else { 325881ad6265SDimitry Andric auto MBBI = AllocMBB->end(); 325981ad6265SDimitry Andric auto RegInfo = STI.getRegisterInfo(); 326081ad6265SDimitry Andric RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0, 326181ad6265SDimitry Andric AlignedStackSize); 32620b57cec5SDimitry Andric } 326381ad6265SDimitry Andric } 326481ad6265SDimitry Andric 32650b57cec5SDimitry Andric // Pass second argument for the __morestack by Scratch Register #1. 32660b57cec5SDimitry Andric // The amount size of stack consumed to save function arguments. 32670b57cec5SDimitry Andric if (Thumb) { 326881ad6265SDimitry Andric if (ARMFI->getArgumentStackSize() < 256) { 32690b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg1) 32700b57cec5SDimitry Andric .add(condCodeOp()) 32710b57cec5SDimitry Andric .addImm(alignToARMConstant(ARMFI->getArgumentStackSize())) 32720b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 32730b57cec5SDimitry Andric } else { 32745f757f3fSDimitry Andric if (Thumb2 || ST->genExecuteOnly()) { 32755f757f3fSDimitry Andric BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg1) 327681ad6265SDimitry Andric .addImm(alignToARMConstant(ARMFI->getArgumentStackSize())); 327781ad6265SDimitry Andric } else { 327881ad6265SDimitry Andric auto MBBI = AllocMBB->end(); 327981ad6265SDimitry Andric auto RegInfo = STI.getRegisterInfo(); 328081ad6265SDimitry Andric RegInfo->emitLoadConstPool( 328181ad6265SDimitry Andric *AllocMBB, MBBI, DL, ScratchReg1, 0, 328281ad6265SDimitry Andric alignToARMConstant(ARMFI->getArgumentStackSize())); 328381ad6265SDimitry Andric } 328481ad6265SDimitry Andric } 328581ad6265SDimitry Andric } else { 328681ad6265SDimitry Andric if (alignToARMConstant(ARMFI->getArgumentStackSize()) < 256) { 32870b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg1) 32880b57cec5SDimitry Andric .addImm(alignToARMConstant(ARMFI->getArgumentStackSize())) 32890b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 32900b57cec5SDimitry Andric .add(condCodeOp()); 329181ad6265SDimitry Andric } else { 329281ad6265SDimitry Andric auto MBBI = AllocMBB->end(); 329381ad6265SDimitry Andric auto RegInfo = STI.getRegisterInfo(); 329481ad6265SDimitry Andric RegInfo->emitLoadConstPool( 329581ad6265SDimitry Andric *AllocMBB, MBBI, DL, ScratchReg1, 0, 329681ad6265SDimitry Andric alignToARMConstant(ARMFI->getArgumentStackSize())); 329781ad6265SDimitry Andric } 32980b57cec5SDimitry Andric } 32990b57cec5SDimitry Andric 33000b57cec5SDimitry Andric // push {lr} - Save return address of this function. 33010b57cec5SDimitry Andric if (Thumb) { 33020b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::tPUSH)) 33030b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33040b57cec5SDimitry Andric .addReg(ARM::LR); 33050b57cec5SDimitry Andric } else { 33060b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::STMDB_UPD)) 33070b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Define) 33080b57cec5SDimitry Andric .addReg(ARM::SP) 33090b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33100b57cec5SDimitry Andric .addReg(ARM::LR); 33110b57cec5SDimitry Andric } 33120b57cec5SDimitry Andric 33130b57cec5SDimitry Andric // Emit the DWARF info about the change in stack as well as where to find the 33140b57cec5SDimitry Andric // previous link register 331581ad6265SDimitry Andric if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI()) { 33165ffd83dbSDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 12)); 33170b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 33180b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 33190b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( 33200b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(ARM::LR, true), -12)); 33210b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 33220b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 332381ad6265SDimitry Andric } 33240b57cec5SDimitry Andric 33250b57cec5SDimitry Andric // Call __morestack(). 33260b57cec5SDimitry Andric if (Thumb) { 33270b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::tBL)) 33280b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33290b57cec5SDimitry Andric .addExternalSymbol("__morestack"); 33300b57cec5SDimitry Andric } else { 33310b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::BL)) 33320b57cec5SDimitry Andric .addExternalSymbol("__morestack"); 33330b57cec5SDimitry Andric } 33340b57cec5SDimitry Andric 33350b57cec5SDimitry Andric // pop {lr} - Restore return address of this original function. 33360b57cec5SDimitry Andric if (Thumb) { 33370b57cec5SDimitry Andric if (ST->isThumb1Only()) { 33380b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::tPOP)) 33390b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33400b57cec5SDimitry Andric .addReg(ScratchReg0); 33410b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::tMOVr), ARM::LR) 33420b57cec5SDimitry Andric .addReg(ScratchReg0) 33430b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 33440b57cec5SDimitry Andric } else { 33450b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::t2LDR_POST)) 33460b57cec5SDimitry Andric .addReg(ARM::LR, RegState::Define) 33470b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Define) 33480b57cec5SDimitry Andric .addReg(ARM::SP) 33490b57cec5SDimitry Andric .addImm(4) 33500b57cec5SDimitry Andric .add(predOps(ARMCC::AL)); 33510b57cec5SDimitry Andric } 33520b57cec5SDimitry Andric } else { 33530b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD)) 33540b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Define) 33550b57cec5SDimitry Andric .addReg(ARM::SP) 33560b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33570b57cec5SDimitry Andric .addReg(ARM::LR); 33580b57cec5SDimitry Andric } 33590b57cec5SDimitry Andric 33600b57cec5SDimitry Andric // Restore SR0 and SR1 in case of __morestack() was called. 33610b57cec5SDimitry Andric // __morestack() will skip PostStackMBB block so we need to restore 33620b57cec5SDimitry Andric // scratch registers from here. 33630b57cec5SDimitry Andric // pop {SR0, SR1} 33640b57cec5SDimitry Andric if (Thumb) { 33650b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::tPOP)) 33660b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33670b57cec5SDimitry Andric .addReg(ScratchReg0) 33680b57cec5SDimitry Andric .addReg(ScratchReg1); 33690b57cec5SDimitry Andric } else { 33700b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD)) 33710b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Define) 33720b57cec5SDimitry Andric .addReg(ARM::SP) 33730b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33740b57cec5SDimitry Andric .addReg(ScratchReg0) 33750b57cec5SDimitry Andric .addReg(ScratchReg1); 33760b57cec5SDimitry Andric } 33770b57cec5SDimitry Andric 33780b57cec5SDimitry Andric // Update the CFA offset now that we've popped 337981ad6265SDimitry Andric if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI()) { 33805ffd83dbSDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 0)); 33810b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 33820b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 338381ad6265SDimitry Andric } 33840b57cec5SDimitry Andric 33850b57cec5SDimitry Andric // Return from this function. 33860b57cec5SDimitry Andric BuildMI(AllocMBB, DL, TII.get(ST->getReturnOpcode())).add(predOps(ARMCC::AL)); 33870b57cec5SDimitry Andric 33880b57cec5SDimitry Andric // Restore SR0 and SR1 in case of __morestack() was not called. 33890b57cec5SDimitry Andric // pop {SR0, SR1} 33900b57cec5SDimitry Andric if (Thumb) { 33910b57cec5SDimitry Andric BuildMI(PostStackMBB, DL, TII.get(ARM::tPOP)) 33920b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 33930b57cec5SDimitry Andric .addReg(ScratchReg0) 33940b57cec5SDimitry Andric .addReg(ScratchReg1); 33950b57cec5SDimitry Andric } else { 33960b57cec5SDimitry Andric BuildMI(PostStackMBB, DL, TII.get(ARM::LDMIA_UPD)) 33970b57cec5SDimitry Andric .addReg(ARM::SP, RegState::Define) 33980b57cec5SDimitry Andric .addReg(ARM::SP) 33990b57cec5SDimitry Andric .add(predOps(ARMCC::AL)) 34000b57cec5SDimitry Andric .addReg(ScratchReg0) 34010b57cec5SDimitry Andric .addReg(ScratchReg1); 34020b57cec5SDimitry Andric } 34030b57cec5SDimitry Andric 34040b57cec5SDimitry Andric // Update the CFA offset now that we've popped 340581ad6265SDimitry Andric if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI()) { 34065ffd83dbSDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 0)); 34070b57cec5SDimitry Andric BuildMI(PostStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 34080b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 34090b57cec5SDimitry Andric 34100b57cec5SDimitry Andric // Tell debuggers that r4 and r5 are now the same as they were in the 34110b57cec5SDimitry Andric // previous function, that they're the "Same Value". 34120b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createSameValue( 34130b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(ScratchReg0, true))); 34140b57cec5SDimitry Andric BuildMI(PostStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 34150b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 34160b57cec5SDimitry Andric CFIIndex = MF.addFrameInst(MCCFIInstruction::createSameValue( 34170b57cec5SDimitry Andric nullptr, MRI->getDwarfRegNum(ScratchReg1, true))); 34180b57cec5SDimitry Andric BuildMI(PostStackMBB, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) 34190b57cec5SDimitry Andric .addCFIIndex(CFIIndex); 342081ad6265SDimitry Andric } 34210b57cec5SDimitry Andric 34220b57cec5SDimitry Andric // Organizing MBB lists 34230b57cec5SDimitry Andric PostStackMBB->addSuccessor(&PrologueMBB); 34240b57cec5SDimitry Andric 34250b57cec5SDimitry Andric AllocMBB->addSuccessor(PostStackMBB); 34260b57cec5SDimitry Andric 34270b57cec5SDimitry Andric GetMBB->addSuccessor(PostStackMBB); 34280b57cec5SDimitry Andric GetMBB->addSuccessor(AllocMBB); 34290b57cec5SDimitry Andric 34300b57cec5SDimitry Andric McrMBB->addSuccessor(GetMBB); 34310b57cec5SDimitry Andric 34320b57cec5SDimitry Andric PrevStackMBB->addSuccessor(McrMBB); 34330b57cec5SDimitry Andric 34340b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 34350b57cec5SDimitry Andric MF.verify(); 34360b57cec5SDimitry Andric #endif 34370b57cec5SDimitry Andric } 3438