xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARM/ARMFrameLowering.cpp (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
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