//===- ARMFrameLowering.cpp - ARM Frame Information -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the ARM implementation of TargetFrameLowering class.
//
//===----------------------------------------------------------------------===//
//
// This file contains the ARM implementation of TargetFrameLowering class.
//
// On ARM, stack frames are structured as follows:
//
// The stack grows downward.
//
// All of the individual frame areas on the frame below are optional, i.e. it's
// possible to create a function so that the particular area isn't present
// in the frame.
//
// At function entry, the "frame" looks as follows:
//
// |                                   | Higher address
// |-----------------------------------|
// |                                   |
// | arguments passed on the stack     |
// |                                   |
// |-----------------------------------| <- sp
// |                                   | Lower address
//
//
// After the prologue has run, the frame has the following general structure.
// Technically the last frame area (VLAs) doesn't get created until in the
// main function body, after the prologue is run. However, it's depicted here
// for completeness.
//
// |                                   | Higher address
// |-----------------------------------|
// |                                   |
// | arguments passed on the stack     |
// |                                   |
// |-----------------------------------| <- (sp at function entry)
// |                                   |
// | varargs from registers            |
// |                                   |
// |-----------------------------------|
// |                                   |
// | prev_lr                           |
// | prev_fp                           |
// | (a.k.a. "frame record")           |
// |                                   |
// |- - - - - - - - - - - - - - - - - -| <- fp (r7 or r11)
// |                                   |
// | callee-saved gpr registers        |
// |                                   |
// |-----------------------------------|
// |                                   |
// | callee-saved fp/simd regs         |
// |                                   |
// |-----------------------------------|
// |.empty.space.to.make.part.below....|
// |.aligned.in.case.it.needs.more.than| (size of this area is unknown at
// |.the.standard.8-byte.alignment.....|  compile time; if present)
// |-----------------------------------|
// |                                   |
// | local variables of fixed size     |
// | including spill slots             |
// |-----------------------------------| <- base pointer (not defined by ABI,
// |.variable-sized.local.variables....|       LLVM chooses r6)
// |.(VLAs)............................| (size of this area is unknown at
// |...................................|  compile time)
// |-----------------------------------| <- sp
// |                                   | Lower address
//
//
// To access the data in a frame, at-compile time, a constant offset must be
// computable from one of the pointers (fp, bp, sp) to access it. The size
// of the areas with a dotted background cannot be computed at compile-time
// if they are present, making it required to have all three of fp, bp and
// sp to be set up to be able to access all contents in the frame areas,
// assuming all of the frame areas are non-empty.
//
// For most functions, some of the frame areas are empty. For those functions,
// it may not be necessary to set up fp or bp:
// * A base pointer is definitely needed when there are both VLAs and local
//   variables with more-than-default alignment requirements.
// * A frame pointer is definitely needed when there are local variables with
//   more-than-default alignment requirements.
//
// In some cases when a base pointer is not strictly needed, it is generated
// anyway when offsets from the frame pointer to access local variables become
// so large that the offset can't be encoded in the immediate fields of loads
// or stores.
//
// The frame pointer might be chosen to be r7 or r11, depending on the target
// architecture and operating system. See ARMSubtarget::getFramePointerReg for
// details.
//
// Outgoing function arguments must be at the bottom of the stack frame when
// calling another function. If we do not have variable-sized stack objects, we
// can allocate a "reserved call frame" area at the bottom of the local
// variable area, large enough for all outgoing calls. If we do have VLAs, then
// the stack pointer must be decremented and incremented around each call to
// make space for the arguments below the VLAs.
//
//===----------------------------------------------------------------------===//

#include "ARMFrameLowering.h"
#include "ARMBaseInstrInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMConstantPoolValue.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMSubtarget.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "Utils/ARMBaseInfo.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/CFIInstBuilder.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <utility>
#include <vector>

#define DEBUG_TYPE "arm-frame-lowering"

using namespace llvm;

static cl::opt<bool>
SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true),
                     cl::desc("Align ARM NEON spills in prolog and epilog"));

static MachineBasicBlock::iterator
skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI,
                        unsigned NumAlignedDPRCS2Regs);

enum class SpillArea {
  GPRCS1,
  GPRCS2,
  FPStatus,
  DPRCS1,
  DPRCS2,
  GPRCS3,
  FPCXT,
};

/// Get the spill area that Reg should be saved into in the prologue.
SpillArea getSpillArea(Register Reg,
                       ARMSubtarget::PushPopSplitVariation Variation,
                       unsigned NumAlignedDPRCS2Regs,
                       const ARMBaseRegisterInfo *RegInfo) {
  // NoSplit:
  // push {r0-r12, lr}   GPRCS1
  // vpush {r8-d15}      DPRCS1
  //
  // SplitR7:
  // push {r0-r7, lr}    GPRCS1
  // push {r8-r12}       GPRCS2
  // vpush {r8-d15}      DPRCS1
  //
  // SplitR11WindowsSEH:
  // push {r0-r10, r12}  GPRCS1
  // vpush {r8-d15}      DPRCS1
  // push {r11, lr}      GPRCS3
  //
  // SplitR11AAPCSSignRA:
  // push {r0-r10, r12}  GPRSC1
  // push {r11, lr}      GPRCS2
  // vpush {r8-d15}      DPRCS1

  // If FPCXTNS is spilled (for CMSE secure entryfunctions), it is always at
  // the top of the stack frame.
  // The DPRCS2 region is used for ABIs which only guarantee 4-byte alignment
  // of SP. If used, it will be below the other save areas, after the stack has
  // been re-aligned.

  switch (Reg) {
  default:
    dbgs() << "Don't know where to spill " << printReg(Reg, RegInfo) << "\n";
    llvm_unreachable("Don't know where to spill this register");
    break;

  case ARM::FPCXTNS:
    return SpillArea::FPCXT;

  case ARM::FPSCR:
  case ARM::FPEXC:
    return SpillArea::FPStatus;

  case ARM::R0:
  case ARM::R1:
  case ARM::R2:
  case ARM::R3:
  case ARM::R4:
  case ARM::R5:
  case ARM::R6:
  case ARM::R7:
    return SpillArea::GPRCS1;

  case ARM::R8:
  case ARM::R9:
  case ARM::R10:
    if (Variation == ARMSubtarget::SplitR7)
      return SpillArea::GPRCS2;
    else
      return SpillArea::GPRCS1;

  case ARM::R11:
    if (Variation == ARMSubtarget::SplitR7 ||
        Variation == ARMSubtarget::SplitR11AAPCSSignRA)
      return SpillArea::GPRCS2;
    if (Variation == ARMSubtarget::SplitR11WindowsSEH)
      return SpillArea::GPRCS3;

    return SpillArea::GPRCS1;

  case ARM::R12:
    if (Variation == ARMSubtarget::SplitR7)
      return SpillArea::GPRCS2;
    else
      return SpillArea::GPRCS1;

  case ARM::LR:
    if (Variation == ARMSubtarget::SplitR11AAPCSSignRA)
      return SpillArea::GPRCS2;
    if (Variation == ARMSubtarget::SplitR11WindowsSEH)
      return SpillArea::GPRCS3;

    return SpillArea::GPRCS1;

  case ARM::D0:
  case ARM::D1:
  case ARM::D2:
  case ARM::D3:
  case ARM::D4:
  case ARM::D5:
  case ARM::D6:
  case ARM::D7:
    return SpillArea::DPRCS1;

  case ARM::D8:
  case ARM::D9:
  case ARM::D10:
  case ARM::D11:
  case ARM::D12:
  case ARM::D13:
  case ARM::D14:
  case ARM::D15:
    if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
      return SpillArea::DPRCS2;
    else
      return SpillArea::DPRCS1;

  case ARM::D16:
  case ARM::D17:
  case ARM::D18:
  case ARM::D19:
  case ARM::D20:
  case ARM::D21:
  case ARM::D22:
  case ARM::D23:
  case ARM::D24:
  case ARM::D25:
  case ARM::D26:
  case ARM::D27:
  case ARM::D28:
  case ARM::D29:
  case ARM::D30:
  case ARM::D31:
    return SpillArea::DPRCS1;
  }
}

ARMFrameLowering::ARMFrameLowering(const ARMSubtarget &sti)
    : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, Align(4)),
      STI(sti) {}

bool ARMFrameLowering::keepFramePointer(const MachineFunction &MF) const {
  // iOS always has a FP for backtracking, force other targets to keep their FP
  // when doing FastISel. The emitted code is currently superior, and in cases
  // like test-suite's lencod FastISel isn't quite correct when FP is eliminated.
  return MF.getSubtarget<ARMSubtarget>().useFastISel();
}

/// Returns true if the target can safely skip saving callee-saved registers
/// for noreturn nounwind functions.
bool ARMFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {
  assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&
         MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
         !MF.getFunction().hasFnAttribute(Attribute::UWTable));

  // Frame pointer and link register are not treated as normal CSR, thus we
  // can always skip CSR saves for nonreturning functions.
  return true;
}

/// hasFPImpl - Return true if the specified function should have a dedicated
/// frame pointer register.  This is true if the function has variable sized
/// allocas or if frame pointer elimination is disabled.
bool ARMFrameLowering::hasFPImpl(const MachineFunction &MF) const {
  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
  const MachineFrameInfo &MFI = MF.getFrameInfo();

  // Check to see if the target want to forcibly keep frame pointer.
  if (keepFramePointer(MF))
    return true;

  // ABI-required frame pointer.
  if (MF.getTarget().Options.DisableFramePointerElim(MF))
    return true;

  // Frame pointer required for use within this function.
  return (RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
          MFI.isFrameAddressTaken());
}

/// isFPReserved - Return true if the frame pointer register should be
/// considered a reserved register on the scope of the specified function.
bool ARMFrameLowering::isFPReserved(const MachineFunction &MF) const {
  return hasFP(MF) || MF.getTarget().Options.FramePointerIsReserved(MF);
}

/// hasReservedCallFrame - Under normal circumstances, when a frame pointer is
/// not required, we reserve argument space for call sites in the function
/// immediately on entry to the current function.  This eliminates the need for
/// add/sub sp brackets around call sites.  Returns true if the call frame is
/// included as part of the stack frame.
bool ARMFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  unsigned CFSize = MFI.getMaxCallFrameSize();
  // It's not always a good idea to include the call frame as part of the
  // stack frame. ARM (especially Thumb) has small immediate offset to
  // address the stack frame. So a large call frame can cause poor codegen
  // and may even makes it impossible to scavenge a register.
  if (CFSize >= ((1 << 12) - 1) / 2)  // Half of imm12
    return false;

  return !MFI.hasVarSizedObjects();
}

/// canSimplifyCallFramePseudos - If there is a reserved call frame, the
/// call frame pseudos can be simplified.  Unlike most targets, having a FP
/// is not sufficient here since we still may reference some objects via SP
/// even when FP is available in Thumb2 mode.
bool
ARMFrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const {
  return hasReservedCallFrame(MF) || MF.getFrameInfo().hasVarSizedObjects();
}

// Returns how much of the incoming argument stack area we should clean up in an
// epilogue. For the C calling convention this will be 0, for guaranteed tail
// call conventions it can be positive (a normal return or a tail call to a
// function that uses less stack space for arguments) or negative (for a tail
// call to a function that needs more stack space than us for arguments).
static int getArgumentStackToRestore(MachineFunction &MF,
                                     MachineBasicBlock &MBB) {
  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
  bool IsTailCallReturn = false;
  if (MBB.end() != MBBI) {
    unsigned RetOpcode = MBBI->getOpcode();
    IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
                       RetOpcode == ARM::TCRETURNri ||
                       RetOpcode == ARM::TCRETURNrinotr12;
  }
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();

  int ArgumentPopSize = 0;
  if (IsTailCallReturn) {
    MachineOperand &StackAdjust = MBBI->getOperand(1);

    // For a tail-call in a callee-pops-arguments environment, some or all of
    // the stack may actually be in use for the call's arguments, this is
    // calculated during LowerCall and consumed here...
    ArgumentPopSize = StackAdjust.getImm();
  } else {
    // ... otherwise the amount to pop is *all* of the argument space,
    // conveniently stored in the MachineFunctionInfo by
    // LowerFormalArguments. This will, of course, be zero for the C calling
    // convention.
    ArgumentPopSize = AFI->getArgumentStackToRestore();
  }

  return ArgumentPopSize;
}

static bool needsWinCFI(const MachineFunction &MF) {
  const Function &F = MF.getFunction();
  return MF.getTarget().getMCAsmInfo().usesWindowsCFI() &&
         F.needsUnwindTableEntry();
}

// Given a load or a store instruction, generate an appropriate unwinding SEH
// code on Windows.
static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI,
                                             const TargetInstrInfo &TII,
                                             unsigned Flags) {
  unsigned Opc = MBBI->getOpcode();
  MachineBasicBlock *MBB = MBBI->getParent();
  MachineFunction &MF = *MBB->getParent();
  DebugLoc DL = MBBI->getDebugLoc();
  MachineInstrBuilder MIB;
  const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>();
  const ARMBaseRegisterInfo *RegInfo = Subtarget.getRegisterInfo();

  Flags |= MachineInstr::NoMerge;

  switch (Opc) {
  default:
    report_fatal_error("No SEH Opcode for instruction " + TII.getName(Opc));
    break;
  case ARM::t2ADDri:   // add.w r11, sp, #xx
  case ARM::t2ADDri12: // add.w r11, sp, #xx
  case ARM::t2MOVTi16: // movt  r4, #xx
  case ARM::tBL:       // bl __chkstk
    // These are harmless if used for just setting up a frame pointer,
    // but that frame pointer can't be relied upon for unwinding, unless
    // set up with SEH_SaveSP.
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop))
              .addImm(/*Wide=*/1)
              .setMIFlags(Flags);
    break;

  case ARM::t2MOVi16: { // mov(w) r4, #xx
    bool Wide = MBBI->getOperand(1).getImm() >= 256;
    if (!Wide) {
      MachineInstrBuilder NewInstr =
          BuildMI(MF, DL, TII.get(ARM::tMOVi8)).setMIFlags(MBBI->getFlags());
      NewInstr.add(MBBI->getOperand(0));
      NewInstr.add(t1CondCodeOp(/*isDead=*/true));
      for (MachineOperand &MO : llvm::drop_begin(MBBI->operands()))
        NewInstr.add(MO);
      MachineBasicBlock::iterator NewMBBI = MBB->insertAfter(MBBI, NewInstr);
      MBB->erase(MBBI);
      MBBI = NewMBBI;
    }
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop)).addImm(Wide).setMIFlags(Flags);
    break;
  }

  case ARM::tBLXr: // blx r12 (__chkstk)
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop))
              .addImm(/*Wide=*/0)
              .setMIFlags(Flags);
    break;

  case ARM::t2MOVi32imm: // movw+movt
    // This pseudo instruction expands into two mov instructions. If the
    // second operand is a symbol reference, this will stay as two wide
    // instructions, movw+movt. If they're immediates, the first one can
    // end up as a narrow mov though.
    // As two SEH instructions are appended here, they won't get interleaved
    // between the two final movw/movt instructions, but it doesn't make any
    // practical difference.
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop))
              .addImm(/*Wide=*/1)
              .setMIFlags(Flags);
    MBB->insertAfter(MBBI, MIB);
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop))
              .addImm(/*Wide=*/1)
              .setMIFlags(Flags);
    break;

  case ARM::t2STR_PRE:
    if (MBBI->getOperand(0).getReg() == ARM::SP &&
        MBBI->getOperand(2).getReg() == ARM::SP &&
        MBBI->getOperand(3).getImm() == -4) {
      unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
      MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))
                .addImm(1ULL << Reg)
                .addImm(/*Wide=*/1)
                .setMIFlags(Flags);
    } else {
      report_fatal_error("No matching SEH Opcode for t2STR_PRE");
    }
    break;

  case ARM::t2LDR_POST:
    if (MBBI->getOperand(1).getReg() == ARM::SP &&
        MBBI->getOperand(2).getReg() == ARM::SP &&
        MBBI->getOperand(3).getImm() == 4) {
      unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
      MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))
                .addImm(1ULL << Reg)
                .addImm(/*Wide=*/1)
                .setMIFlags(Flags);
    } else {
      report_fatal_error("No matching SEH Opcode for t2LDR_POST");
    }
    break;

  case ARM::t2LDMIA_RET:
  case ARM::t2LDMIA_UPD:
  case ARM::t2STMDB_UPD: {
    unsigned Mask = 0;
    bool Wide = false;
    for (unsigned i = 4, NumOps = MBBI->getNumOperands(); i != NumOps; ++i) {
      const MachineOperand &MO = MBBI->getOperand(i);
      if (!MO.isReg() || MO.isImplicit())
        continue;
      unsigned Reg = RegInfo->getSEHRegNum(MO.getReg());
      if (Reg == 15)
        Reg = 14;
      if (Reg >= 8 && Reg <= 13)
        Wide = true;
      else if (Opc == ARM::t2LDMIA_UPD && Reg == 14)
        Wide = true;
      Mask |= 1 << Reg;
    }
    if (!Wide) {
      unsigned NewOpc;
      switch (Opc) {
      case ARM::t2LDMIA_RET:
        NewOpc = ARM::tPOP_RET;
        break;
      case ARM::t2LDMIA_UPD:
        NewOpc = ARM::tPOP;
        break;
      case ARM::t2STMDB_UPD:
        NewOpc = ARM::tPUSH;
        break;
      default:
        llvm_unreachable("");
      }
      MachineInstrBuilder NewInstr =
          BuildMI(MF, DL, TII.get(NewOpc)).setMIFlags(MBBI->getFlags());
      for (unsigned i = 2, NumOps = MBBI->getNumOperands(); i != NumOps; ++i)
        NewInstr.add(MBBI->getOperand(i));
      MachineBasicBlock::iterator NewMBBI = MBB->insertAfter(MBBI, NewInstr);
      MBB->erase(MBBI);
      MBBI = NewMBBI;
    }
    unsigned SEHOpc =
        (Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
    MIB = BuildMI(MF, DL, TII.get(SEHOpc))
              .addImm(Mask)
              .addImm(Wide ? 1 : 0)
              .setMIFlags(Flags);
    break;
  }
  case ARM::VSTMDDB_UPD:
  case ARM::VLDMDIA_UPD: {
    int First = -1, Last = 0;
    for (const MachineOperand &MO : llvm::drop_begin(MBBI->operands(), 4)) {
      unsigned Reg = RegInfo->getSEHRegNum(MO.getReg());
      if (First == -1)
        First = Reg;
      Last = Reg;
    }
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveFRegs))
              .addImm(First)
              .addImm(Last)
              .setMIFlags(Flags);
    break;
  }
  case ARM::tSUBspi:
  case ARM::tADDspi:
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc))
              .addImm(MBBI->getOperand(2).getImm() * 4)
              .addImm(/*Wide=*/0)
              .setMIFlags(Flags);
    break;
  case ARM::t2SUBspImm:
  case ARM::t2SUBspImm12:
  case ARM::t2ADDspImm:
  case ARM::t2ADDspImm12:
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc))
              .addImm(MBBI->getOperand(2).getImm())
              .addImm(/*Wide=*/1)
              .setMIFlags(Flags);
    break;

  case ARM::tMOVr:
    if (MBBI->getOperand(1).getReg() == ARM::SP &&
        (Flags & MachineInstr::FrameSetup)) {
      unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
      MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP))
                .addImm(Reg)
                .setMIFlags(Flags);
    } else if (MBBI->getOperand(0).getReg() == ARM::SP &&
               (Flags & MachineInstr::FrameDestroy)) {
      unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
      MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP))
                .addImm(Reg)
                .setMIFlags(Flags);
    } else {
      report_fatal_error("No SEH Opcode for MOV");
    }
    break;

  case ARM::tBX_RET:
  case ARM::t2BXAUT_RET:
  case ARM::CLEANUPRET:
  case ARM::CATCHRET:
  case ARM::TCRETURNri:
  case ARM::TCRETURNrinotr12:
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret))
              .addImm(/*Wide=*/0)
              .setMIFlags(Flags);
    break;

  case ARM::TCRETURNdi:
    MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret))
              .addImm(/*Wide=*/1)
              .setMIFlags(Flags);
    break;
  }
  return MBB->insertAfter(MBBI, MIB);
}

static MachineBasicBlock::iterator
initMBBRange(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI) {
  if (MBBI == MBB.begin())
    return MachineBasicBlock::iterator();
  return std::prev(MBBI);
}

static void insertSEHRange(MachineBasicBlock &MBB,
                           MachineBasicBlock::iterator Start,
                           const MachineBasicBlock::iterator &End,
                           const ARMBaseInstrInfo &TII, unsigned MIFlags) {
  if (Start.isValid())
    Start = std::next(Start);
  else
    Start = MBB.begin();

  for (auto MI = Start; MI != End;) {
    auto Next = std::next(MI);
    // Check if this instruction already has got a SEH opcode added. In that
    // case, don't do this generic mapping.
    if (Next != End && isSEHInstruction(*Next)) {
      MI = std::next(Next);
      while (MI != End && isSEHInstruction(*MI))
        ++MI;
      continue;
    }
    insertSEH(MI, TII, MIFlags);
    MI = Next;
  }
}

static void emitRegPlusImmediate(
    bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
    const DebugLoc &dl, const ARMBaseInstrInfo &TII, unsigned DestReg,
    unsigned SrcReg, int NumBytes, unsigned MIFlags = MachineInstr::NoFlags,
    ARMCC::CondCodes Pred = ARMCC::AL, unsigned PredReg = 0) {
  if (isARM)
    emitARMRegPlusImmediate(MBB, MBBI, dl, DestReg, SrcReg, NumBytes,
                            Pred, PredReg, TII, MIFlags);
  else
    emitT2RegPlusImmediate(MBB, MBBI, dl, DestReg, SrcReg, NumBytes,
                           Pred, PredReg, TII, MIFlags);
}

static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB,
                         MachineBasicBlock::iterator &MBBI, const DebugLoc &dl,
                         const ARMBaseInstrInfo &TII, int NumBytes,
                         unsigned MIFlags = MachineInstr::NoFlags,
                         ARMCC::CondCodes Pred = ARMCC::AL,
                         unsigned PredReg = 0) {
  emitRegPlusImmediate(isARM, MBB, MBBI, dl, TII, ARM::SP, ARM::SP, NumBytes,
                       MIFlags, Pred, PredReg);
}

static int sizeOfSPAdjustment(const MachineInstr &MI) {
  int RegSize;
  switch (MI.getOpcode()) {
  case ARM::VSTMDDB_UPD:
    RegSize = 8;
    break;
  case ARM::STMDB_UPD:
  case ARM::t2STMDB_UPD:
    RegSize = 4;
    break;
  case ARM::t2STR_PRE:
  case ARM::STR_PRE_IMM:
    return 4;
  default:
    llvm_unreachable("Unknown push or pop like instruction");
  }

  int count = 0;
  // ARM and Thumb2 push/pop insts have explicit "sp, sp" operands (+
  // pred) so the list starts at 4.
  for (int i = MI.getNumOperands() - 1; i >= 4; --i)
    count += RegSize;
  return count;
}

static bool WindowsRequiresStackProbe(const MachineFunction &MF,
                                      size_t StackSizeInBytes) {
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  const Function &F = MF.getFunction();
  unsigned StackProbeSize = (MFI.getStackProtectorIndex() > 0) ? 4080 : 4096;

  StackProbeSize =
      F.getFnAttributeAsParsedInteger("stack-probe-size", StackProbeSize);
  return (StackSizeInBytes >= StackProbeSize) &&
         !F.hasFnAttribute("no-stack-arg-probe");
}

namespace {

struct StackAdjustingInsts {
  struct InstInfo {
    MachineBasicBlock::iterator I;
    unsigned SPAdjust;
    bool BeforeFPSet;

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    void dump() {
      dbgs() << "  " << (BeforeFPSet ? "before-fp " : "          ")
             << "sp-adjust=" << SPAdjust;
      I->dump();
    }
#endif
  };

  SmallVector<InstInfo, 4> Insts;

  void addInst(MachineBasicBlock::iterator I, unsigned SPAdjust,
               bool BeforeFPSet = false) {
    InstInfo Info = {I, SPAdjust, BeforeFPSet};
    Insts.push_back(Info);
  }

  void addExtraBytes(const MachineBasicBlock::iterator I, unsigned ExtraBytes) {
    auto Info =
        llvm::find_if(Insts, [&](InstInfo &Info) { return Info.I == I; });
    assert(Info != Insts.end() && "invalid sp adjusting instruction");
    Info->SPAdjust += ExtraBytes;
  }

  void emitDefCFAOffsets(MachineBasicBlock &MBB, bool HasFP) {
    CFIInstBuilder CFIBuilder(MBB, MBB.end(), MachineInstr::FrameSetup);
    unsigned CFAOffset = 0;
    for (auto &Info : Insts) {
      if (HasFP && !Info.BeforeFPSet)
        return;

      CFAOffset += Info.SPAdjust;
      CFIBuilder.setInsertPoint(std::next(Info.I));
      CFIBuilder.buildDefCFAOffset(CFAOffset);
    }
  }

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  void dump() {
    dbgs() << "StackAdjustingInsts:\n";
    for (auto &Info : Insts)
      Info.dump();
  }
#endif
};

} // end anonymous namespace

/// Emit an instruction sequence that will align the address in
/// register Reg by zero-ing out the lower bits.  For versions of the
/// architecture that support Neon, this must be done in a single
/// instruction, since skipAlignedDPRCS2Spills assumes it is done in a
/// single instruction. That function only gets called when optimizing
/// spilling of D registers on a core with the Neon instruction set
/// present.
static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI,
                                     const TargetInstrInfo &TII,
                                     MachineBasicBlock &MBB,
                                     MachineBasicBlock::iterator MBBI,
                                     const DebugLoc &DL, const unsigned Reg,
                                     const Align Alignment,
                                     const bool MustBeSingleInstruction) {
  const ARMSubtarget &AST = MF.getSubtarget<ARMSubtarget>();
  const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
  const unsigned AlignMask = Alignment.value() - 1U;
  const unsigned NrBitsToZero = Log2(Alignment);
  assert(!AFI->isThumb1OnlyFunction() && "Thumb1 not supported");
  if (!AFI->isThumbFunction()) {
    // if the BFC instruction is available, use that to zero the lower
    // bits:
    //   bfc Reg, #0, log2(Alignment)
    // otherwise use BIC, if the mask to zero the required number of bits
    // can be encoded in the bic immediate field
    //   bic Reg, Reg, Alignment-1
    // otherwise, emit
    //   lsr Reg, Reg, log2(Alignment)
    //   lsl Reg, Reg, log2(Alignment)
    if (CanUseBFC) {
      BuildMI(MBB, MBBI, DL, TII.get(ARM::BFC), Reg)
          .addReg(Reg, RegState::Kill)
          .addImm(~AlignMask)
          .add(predOps(ARMCC::AL));
    } else if (AlignMask <= 255) {
      BuildMI(MBB, MBBI, DL, TII.get(ARM::BICri), Reg)
          .addReg(Reg, RegState::Kill)
          .addImm(AlignMask)
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
    } else {
      assert(!MustBeSingleInstruction &&
             "Shouldn't call emitAligningInstructions demanding a single "
             "instruction to be emitted for large stack alignment for a target "
             "without BFC.");
      BuildMI(MBB, MBBI, DL, TII.get(ARM::MOVsi), Reg)
          .addReg(Reg, RegState::Kill)
          .addImm(ARM_AM::getSORegOpc(ARM_AM::lsr, NrBitsToZero))
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
      BuildMI(MBB, MBBI, DL, TII.get(ARM::MOVsi), Reg)
          .addReg(Reg, RegState::Kill)
          .addImm(ARM_AM::getSORegOpc(ARM_AM::lsl, NrBitsToZero))
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
    }
  } else {
    // Since this is only reached for Thumb-2 targets, the BFC instruction
    // should always be available.
    assert(CanUseBFC);
    BuildMI(MBB, MBBI, DL, TII.get(ARM::t2BFC), Reg)
        .addReg(Reg, RegState::Kill)
        .addImm(~AlignMask)
        .add(predOps(ARMCC::AL));
  }
}

/// We need the offset of the frame pointer relative to other MachineFrameInfo
/// offsets which are encoded relative to SP at function begin.
/// See also emitPrologue() for how the FP is set up.
/// Unfortunately we cannot determine this value in determineCalleeSaves() yet
/// as assignCalleeSavedSpillSlots() hasn't run at this point. Instead we use
/// this to produce a conservative estimate that we check in an assert() later.
static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI,
                          const MachineFunction &MF) {
  ARMSubtarget::PushPopSplitVariation PushPopSplit =
      STI.getPushPopSplitVariation(MF);
  // For Thumb1, push.w isn't available, so the first push will always push
  // r7 and lr onto the stack first.
  if (AFI.isThumb1OnlyFunction())
    return -AFI.getArgRegsSaveSize() - (2 * 4);
  // This is a conservative estimation: Assume the frame pointer being r7 and
  // pc("r15") up to r8 getting spilled before (= 8 registers).
  int MaxRegBytes = 8 * 4;
  if (PushPopSplit == ARMSubtarget::SplitR11AAPCSSignRA)
    // Here, r11 can be stored below all of r4-r15.
    MaxRegBytes = 11 * 4;
  if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
    // Here, r11 can be stored below all of r4-r15 plus d8-d15.
    MaxRegBytes = 11 * 4 + 8 * 8;
  }
  int FPCXTSaveSize =
      (STI.hasV8_1MMainlineOps() && AFI.isCmseNSEntryFunction()) ? 4 : 0;
  return -FPCXTSaveSize - AFI.getArgRegsSaveSize() - MaxRegBytes;
}

void ARMFrameLowering::emitPrologue(MachineFunction &MF,
                                    MachineBasicBlock &MBB) const {
  MachineBasicBlock::iterator MBBI = MBB.begin();
  MachineFrameInfo  &MFI = MF.getFrameInfo();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  const TargetMachine &TM = MF.getTarget();
  const ARMBaseRegisterInfo *RegInfo = STI.getRegisterInfo();
  const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
  assert(!AFI->isThumb1OnlyFunction() &&
         "This emitPrologue does not support Thumb1!");
  bool isARM = !AFI->isThumbFunction();
  Align Alignment = STI.getFrameLowering()->getStackAlign();
  unsigned ArgRegsSaveSize = AFI->getArgRegsSaveSize();
  unsigned NumBytes = MFI.getStackSize();
  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
  int FPCXTSaveSize = 0;
  bool NeedsWinCFI = needsWinCFI(MF);
  ARMSubtarget::PushPopSplitVariation PushPopSplit =
      STI.getPushPopSplitVariation(MF);

  LLVM_DEBUG(dbgs() << "Emitting prologue for " << MF.getName() << "\n");

  // Debug location must be unknown since the first debug location is used
  // to determine the end of the prologue.
  DebugLoc dl;

  Register FramePtr = RegInfo->getFrameRegister(MF);

  // Determine the sizes of each callee-save spill areas and record which frame
  // belongs to which callee-save spill areas.
  unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,
           DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;
  int FramePtrSpillFI = 0;
  int D8SpillFI = 0;

  // All calls are tail calls in GHC calling conv, and functions have no
  // prologue/epilogue.
  if (MF.getFunction().getCallingConv() == CallingConv::GHC)
    return;

  StackAdjustingInsts DefCFAOffsetCandidates;
  bool HasFP = hasFP(MF);

  if (!AFI->hasStackFrame() &&
      (!STI.isTargetWindows() || !WindowsRequiresStackProbe(MF, NumBytes))) {
    if (NumBytes != 0) {
      emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes,
                   MachineInstr::FrameSetup);
      DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes, true);
    }
    if (!NeedsWinCFI)
      DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, HasFP);
    if (NeedsWinCFI && MBBI != MBB.begin()) {
      insertSEHRange(MBB, {}, MBBI, TII, MachineInstr::FrameSetup);
      BuildMI(MBB, MBBI, dl, TII.get(ARM::SEH_PrologEnd))
          .setMIFlag(MachineInstr::FrameSetup);
      MF.setHasWinCFI(true);
    }
    return;
  }

  // Determine spill area sizes, and some important frame indices.
  SpillArea FramePtrSpillArea = SpillArea::GPRCS1;
  bool BeforeFPPush = true;
  for (const CalleeSavedInfo &I : CSI) {
    MCRegister Reg = I.getReg();
    int FI = I.getFrameIdx();

    SpillArea Area = getSpillArea(Reg, PushPopSplit,
                                  AFI->getNumAlignedDPRCS2Regs(), RegInfo);

    if (Reg == FramePtr.asMCReg()) {
      FramePtrSpillFI = FI;
      FramePtrSpillArea = Area;
    }
    if (Reg == ARM::D8)
      D8SpillFI = FI;

    switch (Area) {
    case SpillArea::FPCXT:
      FPCXTSaveSize += 4;
      break;
    case SpillArea::GPRCS1:
      GPRCS1Size += 4;
      break;
    case SpillArea::GPRCS2:
      GPRCS2Size += 4;
      break;
    case SpillArea::FPStatus:
      FPStatusSize += 4;
      break;
    case SpillArea::DPRCS1:
      DPRCS1Size += 8;
      break;
    case SpillArea::GPRCS3:
      GPRCS3Size += 4;
      break;
    case SpillArea::DPRCS2:
      DPRCS2Size += 8;
      break;
    }
  }

  MachineBasicBlock::iterator LastPush = MBB.end(), GPRCS1Push, GPRCS2Push,
                              DPRCS1Push, GPRCS3Push;

  // Move past the PAC computation.
  if (AFI->shouldSignReturnAddress())
    LastPush = MBBI++;

  // Move past FPCXT area.
  if (FPCXTSaveSize > 0) {
    LastPush = MBBI++;
    DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
  }

  // Allocate the vararg register save area.
  if (ArgRegsSaveSize) {
    emitSPUpdate(isARM, MBB, MBBI, dl, TII, -ArgRegsSaveSize,
                 MachineInstr::FrameSetup);
    LastPush = std::prev(MBBI);
    DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
  }

  // Move past area 1.
  if (GPRCS1Size > 0) {
    GPRCS1Push = LastPush = MBBI++;
    DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
    if (FramePtrSpillArea == SpillArea::GPRCS1)
      BeforeFPPush = false;
  }

  // Determine starting offsets of spill areas. These offsets are all positive
  // offsets from the bottom of the lowest-addressed callee-save area
  // (excluding DPRCS2, which is th the re-aligned stack region) to the bottom
  // of the spill area in question.
  unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
  unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
  unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
  unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;

  Align DPRAlign = DPRCS1Size ? std::min(Align(8), Alignment) : Align(4);
  unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
                         GPRCS2Size + FPStatusSize) %
                        DPRAlign.value();

  unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;

  if (HasFP) {
    // Offset from the CFA to the saved frame pointer, will be negative.
    [[maybe_unused]] int FPOffset = MFI.getObjectOffset(FramePtrSpillFI);
    LLVM_DEBUG(dbgs() << "FramePtrSpillFI: " << FramePtrSpillFI
                      << ", FPOffset: " << FPOffset << "\n");
    assert(getMaxFPOffset(STI, *AFI, MF) <= FPOffset &&
           "Max FP estimation is wrong");
    AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) +
                                NumBytes);
  }
  AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
  AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
  AFI->setDPRCalleeSavedArea1Offset(DPRCS1Offset);

  // Move past area 2.
  if (GPRCS2Size > 0) {
    assert(PushPopSplit != ARMSubtarget::SplitR11WindowsSEH);
    GPRCS2Push = LastPush = MBBI++;
    DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
    if (FramePtrSpillArea == SpillArea::GPRCS2)
      BeforeFPPush = false;
  }

  // Move past FP status save area.
  if (FPStatusSize > 0) {
    while (MBBI != MBB.end()) {
      unsigned Opc = MBBI->getOpcode();
      if (Opc == ARM::VMRS || Opc == ARM::VMRS_FPEXC)
        MBBI++;
      else
        break;
    }
    LastPush = MBBI++;
    DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);
  }

  // Prolog/epilog inserter assumes we correctly align DPRs on the stack, so our
  // .cfi_offset operations will reflect that.
  if (DPRGapSize) {
    assert(DPRGapSize == 4 && "unexpected alignment requirements for DPRs");
    if (LastPush != MBB.end() &&
        tryFoldSPUpdateIntoPushPop(STI, MF, &*LastPush, DPRGapSize))
      DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
    else {
      emitSPUpdate(isARM, MBB, MBBI, dl, TII, -DPRGapSize,
                   MachineInstr::FrameSetup);
      DefCFAOffsetCandidates.addInst(std::prev(MBBI), DPRGapSize, BeforeFPPush);
    }
  }

  // Move past DPRCS1Size.
  if (DPRCS1Size > 0) {
    // Since vpush register list cannot have gaps, there may be multiple vpush
    // instructions in the prologue.
    while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
      DefCFAOffsetCandidates.addInst(MBBI, sizeOfSPAdjustment(*MBBI),
                                     BeforeFPPush);
      DPRCS1Push = LastPush = MBBI++;
    }
  }

  // Move past the aligned DPRCS2 area.
  if (DPRCS2Size > 0) {
    MBBI = skipAlignedDPRCS2Spills(MBBI, AFI->getNumAlignedDPRCS2Regs());
    // The code inserted by emitAlignedDPRCS2Spills realigns the stack, and
    // leaves the stack pointer pointing to the DPRCS2 area.
    //
    // Adjust NumBytes to represent the stack slots below the DPRCS2 area.
    NumBytes += MFI.getObjectOffset(D8SpillFI);
  } else
    NumBytes = DPRCS1Offset;

  // Move GPRCS3, if using using SplitR11WindowsSEH.
  if (GPRCS3Size > 0) {
    assert(PushPopSplit == ARMSubtarget::SplitR11WindowsSEH);
    GPRCS3Push = LastPush = MBBI++;
    DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
    if (FramePtrSpillArea == SpillArea::GPRCS3)
      BeforeFPPush = false;
    NumBytes -= GPRCS3Size;
  }

  bool NeedsWinCFIStackAlloc = NeedsWinCFI;
  if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH && HasFP)
    NeedsWinCFIStackAlloc = false;

  if (STI.isTargetWindows() && WindowsRequiresStackProbe(MF, NumBytes)) {
    uint32_t NumWords = NumBytes >> 2;

    if (NumWords < 65536) {
      BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), ARM::R4)
          .addImm(NumWords)
          .setMIFlags(MachineInstr::FrameSetup)
          .add(predOps(ARMCC::AL));
    } else {
      // Split into two instructions here, instead of using t2MOVi32imm,
      // to allow inserting accurate SEH instructions (including accurate
      // instruction size for each of them).
      BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), ARM::R4)
          .addImm(NumWords & 0xffff)
          .setMIFlags(MachineInstr::FrameSetup)
          .add(predOps(ARMCC::AL));
      BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), ARM::R4)
          .addReg(ARM::R4)
          .addImm(NumWords >> 16)
          .setMIFlags(MachineInstr::FrameSetup)
          .add(predOps(ARMCC::AL));
    }

    const ARMTargetLowering *TLI = STI.getTargetLowering();
    RTLIB::LibcallImpl ChkStkLibcall = TLI->getLibcallImpl(RTLIB::STACK_PROBE);
    if (ChkStkLibcall == RTLIB::Unsupported)
      reportFatalUsageError("no available implementation of __chkstk");
    const char *ChkStk = TLI->getLibcallImplName(ChkStkLibcall).data();

    switch (TM.getCodeModel()) {
    case CodeModel::Tiny:
      llvm_unreachable("Tiny code model not available on ARM.");
    case CodeModel::Small:
    case CodeModel::Medium:
    case CodeModel::Kernel:
      BuildMI(MBB, MBBI, dl, TII.get(ARM::tBL))
          .add(predOps(ARMCC::AL))
          .addExternalSymbol(ChkStk)
          .addReg(ARM::R4, RegState::Implicit)
          .setMIFlags(MachineInstr::FrameSetup);
      break;
    case CodeModel::Large:
      BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), ARM::R12)
          .addExternalSymbol(ChkStk)
          .setMIFlags(MachineInstr::FrameSetup);

      BuildMI(MBB, MBBI, dl, TII.get(ARM::tBLXr))
          .add(predOps(ARMCC::AL))
          .addReg(ARM::R12, RegState::Kill)
          .addReg(ARM::R4, RegState::Implicit)
          .setMIFlags(MachineInstr::FrameSetup);
      break;
    }

    MachineInstrBuilder Instr, SEH;
    Instr = BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), ARM::SP)
                .addReg(ARM::SP, RegState::Kill)
                .addReg(ARM::R4, RegState::Kill)
                .setMIFlags(MachineInstr::FrameSetup)
                .add(predOps(ARMCC::AL))
                .add(condCodeOp());
    if (NeedsWinCFIStackAlloc) {
      SEH = BuildMI(MF, dl, TII.get(ARM::SEH_StackAlloc))
                .addImm(NumBytes)
                .addImm(/*Wide=*/1)
                .setMIFlags(MachineInstr::FrameSetup);
      MBB.insertAfter(Instr, SEH);
    }
    NumBytes = 0;
  }

  if (NumBytes) {
    // Adjust SP after all the callee-save spills.
    if (AFI->getNumAlignedDPRCS2Regs() == 0 &&
        tryFoldSPUpdateIntoPushPop(STI, MF, &*LastPush, NumBytes))
      DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
    else {
      emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes,
                   MachineInstr::FrameSetup);
      DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes);
    }

    if (HasFP && isARM)
      // Restore from fp only in ARM mode: e.g. sub sp, r7, #24
      // Note it's not safe to do this in Thumb2 mode because it would have
      // taken two instructions:
      // mov sp, r7
      // sub sp, #24
      // If an interrupt is taken between the two instructions, then sp is in
      // an inconsistent state (pointing to the middle of callee-saved area).
      // The interrupt handler can end up clobbering the registers.
      AFI->setShouldRestoreSPFromFP(true);
  }

  // Set FP to point to the stack slot that contains the previous FP.
  // For iOS, FP is R7, which has now been stored in spill area 1.
  // Otherwise, if this is not iOS, all the callee-saved registers go
  // into spill area 1, including the FP in R11.  In either case, it
  // is in area one and the adjustment needs to take place just after
  // that push.
  MachineBasicBlock::iterator AfterPush;
  if (HasFP) {
    MachineBasicBlock::iterator FPPushInst;
    // Offset from SP immediately after the push which saved the FP to the FP
    // save slot.
    int64_t FPOffsetAfterPush;
    switch (FramePtrSpillArea) {
    case SpillArea::GPRCS1:
      FPPushInst = GPRCS1Push;
      FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
                          ArgRegsSaveSize + FPCXTSaveSize +
                          sizeOfSPAdjustment(*FPPushInst);
      LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS1, offset "
                        << FPOffsetAfterPush << "  after that push\n");
      break;
    case SpillArea::GPRCS2:
      FPPushInst = GPRCS2Push;
      FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
                          ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
                          sizeOfSPAdjustment(*FPPushInst);
      LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS2, offset "
                        << FPOffsetAfterPush << "  after that push\n");
      break;
    case SpillArea::GPRCS3:
      FPPushInst = GPRCS3Push;
      FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
                          ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
                          FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +
                          sizeOfSPAdjustment(*FPPushInst);
      LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS3, offset "
                        << FPOffsetAfterPush << "  after that push\n");
      break;
    default:
      llvm_unreachable("frame pointer in unknown spill area");
      break;
    }
    AfterPush = std::next(FPPushInst);
    if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
      assert(FPOffsetAfterPush == 0);

    // Emit the MOV or ADD to set up the frame pointer register.
    emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII,
                         FramePtr, ARM::SP, FPOffsetAfterPush,
                         MachineInstr::FrameSetup);

    if (!NeedsWinCFI) {
      // Emit DWARF info to find the CFA using the frame pointer from this
      // point onward.
      CFIInstBuilder CFIBuilder(MBB, AfterPush, MachineInstr::FrameSetup);
      if (FPOffsetAfterPush != 0)
        CFIBuilder.buildDefCFA(FramePtr, -MFI.getObjectOffset(FramePtrSpillFI));
      else
        CFIBuilder.buildDefCFARegister(FramePtr);
    }
  }

  // Emit a SEH opcode indicating the prologue end. The rest of the prologue
  // instructions below don't need to be replayed to unwind the stack.
  if (NeedsWinCFI && MBBI != MBB.begin()) {
    MachineBasicBlock::iterator End = MBBI;
    if (HasFP && PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
      End = AfterPush;
    insertSEHRange(MBB, {}, End, TII, MachineInstr::FrameSetup);
    BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd))
        .setMIFlag(MachineInstr::FrameSetup);
    MF.setHasWinCFI(true);
  }

  // Now that the prologue's actual instructions are finalised, we can insert
  // the necessary DWARF cf instructions to describe the situation. Start by
  // recording where each register ended up:
  if (!NeedsWinCFI) {
    for (const auto &Entry : reverse(CSI)) {
      MCRegister Reg = Entry.getReg();
      int FI = Entry.getFrameIdx();
      MachineBasicBlock::iterator CFIPos;
      switch (getSpillArea(Reg, PushPopSplit, AFI->getNumAlignedDPRCS2Regs(),
                           RegInfo)) {
      case SpillArea::GPRCS1:
        CFIPos = std::next(GPRCS1Push);
        break;
      case SpillArea::GPRCS2:
        CFIPos = std::next(GPRCS2Push);
        break;
      case SpillArea::DPRCS1:
        CFIPos = std::next(DPRCS1Push);
        break;
      case SpillArea::GPRCS3:
        CFIPos = std::next(GPRCS3Push);
        break;
      case SpillArea::FPStatus:
      case SpillArea::FPCXT:
      case SpillArea::DPRCS2:
        // FPCXT and DPRCS2 are not represented in the DWARF info.
        break;
      }

      if (CFIPos.isValid()) {
        CFIInstBuilder(MBB, CFIPos, MachineInstr::FrameSetup)
            .buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
                         MFI.getObjectOffset(FI));
      }
    }
  }

  // Now we can emit descriptions of where the canonical frame address was
  // throughout the process. If we have a frame pointer, it takes over the job
  // half-way through, so only the first few .cfi_def_cfa_offset instructions
  // actually get emitted.
  if (!NeedsWinCFI) {
    LLVM_DEBUG(DefCFAOffsetCandidates.dump());
    DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, HasFP);
  }

  if (STI.isTargetELF() && hasFP(MF))
    MFI.setOffsetAdjustment(MFI.getOffsetAdjustment() -
                            AFI->getFramePtrSpillOffset());

  AFI->setFPCXTSaveAreaSize(FPCXTSaveSize);
  AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
  AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
  AFI->setFPStatusSavesSize(FPStatusSize);
  AFI->setDPRCalleeSavedGapSize(DPRGapSize);
  AFI->setDPRCalleeSavedArea1Size(DPRCS1Size);
  AFI->setGPRCalleeSavedArea3Size(GPRCS3Size);

  // If we need dynamic stack realignment, do it here. Be paranoid and make
  // sure if we also have VLAs, we have a base pointer for frame access.
  // If aligned NEON registers were spilled, the stack has already been
  // realigned.
  if (!AFI->getNumAlignedDPRCS2Regs() && RegInfo->hasStackRealignment(MF)) {
    Align MaxAlign = MFI.getMaxAlign();
    assert(!AFI->isThumb1OnlyFunction());
    if (!AFI->isThumbFunction()) {
      emitAligningInstructions(MF, AFI, TII, MBB, MBBI, dl, ARM::SP, MaxAlign,
                               false);
    } else {
      // We cannot use sp as source/dest register here, thus we're using r4 to
      // perform the calculations. We're emitting the following sequence:
      // mov r4, sp
      // -- use emitAligningInstructions to produce best sequence to zero
      // -- out lower bits in r4
      // mov sp, r4
      // FIXME: It will be better just to find spare register here.
      BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4)
          .addReg(ARM::SP, RegState::Kill)
          .add(predOps(ARMCC::AL));
      emitAligningInstructions(MF, AFI, TII, MBB, MBBI, dl, ARM::R4, MaxAlign,
                               false);
      BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
          .addReg(ARM::R4, RegState::Kill)
          .add(predOps(ARMCC::AL));
    }

    AFI->setShouldRestoreSPFromFP(true);
  }

  // If we need a base pointer, set it up here. It's whatever the value
  // of the stack pointer is at this point. Any variable size objects
  // will be allocated after this, so we can still use the base pointer
  // to reference locals.
  // FIXME: Clarify FrameSetup flags here.
  if (RegInfo->hasBasePointer(MF) && !MBB.isEHFuncletEntry()) {
    if (isARM)
      BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), RegInfo->getBaseRegister())
          .addReg(ARM::SP)
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
    else
      BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), RegInfo->getBaseRegister())
          .addReg(ARM::SP)
          .add(predOps(ARMCC::AL));
  }

  // If the frame has variable sized objects then the epilogue must restore
  // the sp from fp. We can assume there's an FP here since hasFP already
  // checks for hasVarSizedObjects.
  if (MFI.hasVarSizedObjects())
    AFI->setShouldRestoreSPFromFP(true);
}

void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
                                    MachineBasicBlock &MBB) const {
  MachineFrameInfo &MFI = MF.getFrameInfo();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
  const ARMBaseInstrInfo &TII =
      *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());
  assert(!AFI->isThumb1OnlyFunction() &&
         "This emitEpilogue does not support Thumb1!");
  bool isARM = !AFI->isThumbFunction();
  ARMSubtarget::PushPopSplitVariation PushPopSplit =
      STI.getPushPopSplitVariation(MF);

  LLVM_DEBUG(dbgs() << "Emitting epilogue for " << MF.getName() << "\n");

  // Amount of stack space we reserved next to incoming args for either
  // varargs registers or stack arguments in tail calls made by this function.
  unsigned ReservedArgStack = AFI->getArgRegsSaveSize();

  // How much of the stack used by incoming arguments this function is expected
  // to restore in this particular epilogue.
  int IncomingArgStackToRestore = getArgumentStackToRestore(MF, MBB);
  int NumBytes = (int)MFI.getStackSize();
  Register FramePtr = RegInfo->getFrameRegister(MF);

  // All calls are tail calls in GHC calling conv, and functions have no
  // prologue/epilogue.
  if (MF.getFunction().getCallingConv() == CallingConv::GHC)
    return;

  // First put ourselves on the first (from top) terminator instructions.
  MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();

  MachineBasicBlock::iterator RangeStart;
  if (!AFI->hasStackFrame()) {
    if (MF.hasWinCFI()) {
      BuildMI(MBB, MBBI, dl, TII.get(ARM::SEH_EpilogStart))
          .setMIFlag(MachineInstr::FrameDestroy);
      RangeStart = initMBBRange(MBB, MBBI);
    }

    if (NumBytes + IncomingArgStackToRestore != 0)
      emitSPUpdate(isARM, MBB, MBBI, dl, TII,
                   NumBytes + IncomingArgStackToRestore,
                   MachineInstr::FrameDestroy);
  } else {
    // Unwind MBBI to point to first LDR / VLDRD.
    if (MBBI != MBB.begin()) {
      do {
        --MBBI;
      } while (MBBI != MBB.begin() &&
               MBBI->getFlag(MachineInstr::FrameDestroy));
      if (!MBBI->getFlag(MachineInstr::FrameDestroy))
        ++MBBI;
    }

    if (MF.hasWinCFI()) {
      BuildMI(MBB, MBBI, dl, TII.get(ARM::SEH_EpilogStart))
          .setMIFlag(MachineInstr::FrameDestroy);
      RangeStart = initMBBRange(MBB, MBBI);
    }

    // Move SP to start of FP callee save spill area.
    NumBytes -=
        (ReservedArgStack + AFI->getFPCXTSaveAreaSize() +
         AFI->getGPRCalleeSavedArea1Size() + AFI->getGPRCalleeSavedArea2Size() +
         AFI->getFPStatusSavesSize() + AFI->getDPRCalleeSavedGapSize() +
         AFI->getDPRCalleeSavedArea1Size() + AFI->getGPRCalleeSavedArea3Size());

    // Reset SP based on frame pointer only if the stack frame extends beyond
    // frame pointer stack slot or target is ELF and the function has FP.
    if (AFI->shouldRestoreSPFromFP()) {
      NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
      if (NumBytes) {
        if (isARM)
          emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
                                  ARMCC::AL, 0, TII,
                                  MachineInstr::FrameDestroy);
        else {
          // It's not possible to restore SP from FP in a single instruction.
          // For iOS, this looks like:
          // mov sp, r7
          // sub sp, #24
          // This is bad, if an interrupt is taken after the mov, sp is in an
          // inconsistent state.
          // Use the first callee-saved register as a scratch register.
          assert(!MFI.getPristineRegs(MF).test(ARM::R4) &&
                 "No scratch register to restore SP from FP!");
          emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes,
                                 ARMCC::AL, 0, TII, MachineInstr::FrameDestroy);
          BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
              .addReg(ARM::R4)
              .add(predOps(ARMCC::AL))
              .setMIFlag(MachineInstr::FrameDestroy);
        }
      } else {
        // Thumb2 or ARM.
        if (isARM)
          BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
              .addReg(FramePtr)
              .add(predOps(ARMCC::AL))
              .add(condCodeOp())
              .setMIFlag(MachineInstr::FrameDestroy);
        else
          BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
              .addReg(FramePtr)
              .add(predOps(ARMCC::AL))
              .setMIFlag(MachineInstr::FrameDestroy);
      }
    } else if (NumBytes &&
               !tryFoldSPUpdateIntoPushPop(STI, MF, &*MBBI, NumBytes))
      emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes,
                   MachineInstr::FrameDestroy);

    // Increment past our save areas.
    if (AFI->getGPRCalleeSavedArea3Size()) {
      assert(PushPopSplit == ARMSubtarget::SplitR11WindowsSEH);
      (void)PushPopSplit;
      MBBI++;
    }

    if (MBBI != MBB.end() && AFI->getDPRCalleeSavedArea1Size()) {
      MBBI++;
      // Since vpop register list cannot have gaps, there may be multiple vpop
      // instructions in the epilogue.
      while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VLDMDIA_UPD)
        MBBI++;
    }
    if (AFI->getDPRCalleeSavedGapSize()) {
      assert(AFI->getDPRCalleeSavedGapSize() == 4 &&
             "unexpected DPR alignment gap");
      emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedGapSize(),
                   MachineInstr::FrameDestroy);
    }

    if (AFI->getGPRCalleeSavedArea2Size()) {
      assert(PushPopSplit != ARMSubtarget::SplitR11WindowsSEH);
      (void)PushPopSplit;
      MBBI++;
    }
    if (AFI->getGPRCalleeSavedArea1Size()) MBBI++;

    if (ReservedArgStack || IncomingArgStackToRestore) {
      assert((int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
             "attempting to restore negative stack amount");
      emitSPUpdate(isARM, MBB, MBBI, dl, TII,
                   ReservedArgStack + IncomingArgStackToRestore,
                   MachineInstr::FrameDestroy);
    }

    // Validate PAC, It should have been already popped into R12. For CMSE entry
    // function, the validation instruction is emitted during expansion of the
    // tBXNS_RET, since the validation must use the value of SP at function
    // entry, before saving, resp. after restoring, FPCXTNS.
    if (AFI->shouldSignReturnAddress() && !AFI->isCmseNSEntryFunction()) {
      bool CanUseBXAut =
          STI.isThumb() && STI.hasV8_1MMainlineOps() && STI.hasPACBTI();
      auto TMBBI = MBB.getFirstTerminator();
      bool IsBXReturn =
          TMBBI != MBB.end() && TMBBI->getOpcode() == ARM::tBX_RET;
      if (IsBXReturn && CanUseBXAut)
        TMBBI->setDesc(STI.getInstrInfo()->get(ARM::t2BXAUT_RET));
      else
        BuildMI(MBB, MBBI, DebugLoc(), STI.getInstrInfo()->get(ARM::t2AUT));
    }
  }

  if (MF.hasWinCFI()) {
    insertSEHRange(MBB, RangeStart, MBB.end(), TII, MachineInstr::FrameDestroy);
    BuildMI(MBB, MBB.end(), dl, TII.get(ARM::SEH_EpilogEnd))
        .setMIFlag(MachineInstr::FrameDestroy);
  }
}

/// getFrameIndexReference - Provide a base+offset reference to an FI slot for
/// debug info.  It's the same as what we use for resolving the code-gen
/// references for now.  FIXME: This can go wrong when references are
/// SP-relative and simple call frames aren't used.
StackOffset ARMFrameLowering::getFrameIndexReference(const MachineFunction &MF,
                                                     int FI,
                                                     Register &FrameReg) const {
  return StackOffset::getFixed(ResolveFrameIndexReference(MF, FI, FrameReg, 0));
}

StackOffset
ARMFrameLowering::getNonLocalFrameIndexReference(const MachineFunction &MF,
                                                 int FI) const {
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  int Offset = MFI.getObjectOffset(FI) + MFI.getStackSize();
  return StackOffset::getFixed(Offset);
}

int ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF,
                                                 int FI, Register &FrameReg,
                                                 int SPAdj) const {
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>(
      MF.getSubtarget().getRegisterInfo());
  const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  int Offset = MFI.getObjectOffset(FI) + MFI.getStackSize();
  int FPOffset = Offset - AFI->getFramePtrSpillOffset();
  bool isFixed = MFI.isFixedObjectIndex(FI);

  FrameReg = ARM::SP;
  Offset += SPAdj;

  // SP can move around if there are allocas.  We may also lose track of SP
  // when emergency spilling inside a non-reserved call frame setup.
  bool hasMovingSP = !hasReservedCallFrame(MF);

  // When dynamically realigning the stack, use the frame pointer for
  // parameters, and the stack/base pointer for locals.
  if (RegInfo->hasStackRealignment(MF)) {
    assert(hasFP(MF) && "dynamic stack realignment without a FP!");
    if (isFixed) {
      FrameReg = RegInfo->getFrameRegister(MF);
      Offset = FPOffset;
    } else if (hasMovingSP) {
      assert(RegInfo->hasBasePointer(MF) &&
             "VLAs and dynamic stack alignment, but missing base pointer!");
      FrameReg = RegInfo->getBaseRegister();
      Offset -= SPAdj;
    }
    return Offset;
  }

  // If there is a frame pointer, use it when we can.
  if (hasFP(MF) && AFI->hasStackFrame()) {
    // Use frame pointer to reference fixed objects. Use it for locals if
    // there are VLAs (and thus the SP isn't reliable as a base).
    if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
      FrameReg = RegInfo->getFrameRegister(MF);
      return FPOffset;
    } else if (hasMovingSP) {
      assert(RegInfo->hasBasePointer(MF) && "missing base pointer!");
      if (AFI->isThumb2Function()) {
        // Try to use the frame pointer if we can, else use the base pointer
        // since it's available. This is handy for the emergency spill slot, in
        // particular.
        if (FPOffset >= -255 && FPOffset < 0) {
          FrameReg = RegInfo->getFrameRegister(MF);
          return FPOffset;
        }
      }
    } else if (AFI->isThumbFunction()) {
      // Prefer SP to base pointer, if the offset is suitably aligned and in
      // range as the effective range of the immediate offset is bigger when
      // basing off SP.
      // Use  add <rd>, sp, #<imm8>
      //      ldr <rd>, [sp, #<imm8>]
      if (Offset >= 0 && (Offset & 3) == 0 && Offset <= 1020)
        return Offset;
      // In Thumb2 mode, the negative offset is very limited. Try to avoid
      // out of range references. ldr <rt>,[<rn>, #-<imm8>]
      if (AFI->isThumb2Function() && FPOffset >= -255 && FPOffset < 0) {
        FrameReg = RegInfo->getFrameRegister(MF);
        return FPOffset;
      }
    } else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
      // Otherwise, use SP or FP, whichever is closer to the stack slot.
      FrameReg = RegInfo->getFrameRegister(MF);
      return FPOffset;
    }
  }
  // Use the base pointer if we have one.
  // FIXME: Maybe prefer sp on Thumb1 if it's legal and the offset is cheaper?
  // That can happen if we forced a base pointer for a large call frame.
  if (RegInfo->hasBasePointer(MF)) {
    FrameReg = RegInfo->getBaseRegister();
    Offset -= SPAdj;
  }
  return Offset;
}

void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
                                    MachineBasicBlock::iterator MI,
                                    ArrayRef<CalleeSavedInfo> CSI,
                                    unsigned StmOpc, unsigned StrOpc,
                                    bool NoGap,
                                    function_ref<bool(unsigned)> Func) const {
  MachineFunction &MF = *MBB.getParent();
  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();

  DebugLoc DL;

  using RegAndKill = std::pair<unsigned, bool>;

  SmallVector<RegAndKill, 4> Regs;
  unsigned i = CSI.size();
  while (i != 0) {
    unsigned LastReg = 0;
    for (; i != 0; --i) {
      MCRegister Reg = CSI[i-1].getReg();
      if (!Func(Reg))
        continue;

      const MachineRegisterInfo &MRI = MF.getRegInfo();
      bool isLiveIn = MRI.isLiveIn(Reg);
      if (!isLiveIn && !MRI.isReserved(Reg))
        MBB.addLiveIn(Reg);
      // If NoGap is true, push consecutive registers and then leave the rest
      // for other instructions. e.g.
      // vpush {d8, d10, d11} -> vpush {d8}, vpush {d10, d11}
      if (NoGap && LastReg && LastReg != Reg-1)
        break;
      LastReg = Reg;
      // Do not set a kill flag on values that are also marked as live-in. This
      // happens with the @llvm-returnaddress intrinsic and with arguments
      // passed in callee saved registers.
      // Omitting the kill flags is conservatively correct even if the live-in
      // is not used after all.
      Regs.push_back(std::make_pair(Reg, /*isKill=*/!isLiveIn));
    }

    if (Regs.empty())
      continue;

    llvm::sort(Regs, [&](const RegAndKill &LHS, const RegAndKill &RHS) {
      return TRI.getEncodingValue(LHS.first) < TRI.getEncodingValue(RHS.first);
    });

    if (Regs.size() > 1 || StrOpc== 0) {
      MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StmOpc), ARM::SP)
                                    .addReg(ARM::SP)
                                    .setMIFlags(MachineInstr::FrameSetup)
                                    .add(predOps(ARMCC::AL));
      for (const auto &[Reg, Kill] : Regs)
        MIB.addReg(Reg, getKillRegState(Kill));
    } else if (Regs.size() == 1) {
      BuildMI(MBB, MI, DL, TII.get(StrOpc), ARM::SP)
          .addReg(Regs[0].first, getKillRegState(Regs[0].second))
          .addReg(ARM::SP)
          .setMIFlags(MachineInstr::FrameSetup)
          .addImm(-4)
          .add(predOps(ARMCC::AL));
    }
    Regs.clear();

    // Put any subsequent vpush instructions before this one: they will refer to
    // higher register numbers so need to be pushed first in order to preserve
    // monotonicity.
    if (MI != MBB.begin())
      --MI;
  }
}

void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
                                   MachineBasicBlock::iterator MI,
                                   MutableArrayRef<CalleeSavedInfo> CSI,
                                   unsigned LdmOpc, unsigned LdrOpc,
                                   bool isVarArg, bool NoGap,
                                   function_ref<bool(unsigned)> Func) const {
  MachineFunction &MF = *MBB.getParent();
  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  bool hasPAC = AFI->shouldSignReturnAddress();
  DebugLoc DL;
  bool isTailCall = false;
  bool isInterrupt = false;
  bool isTrap = false;
  bool isCmseEntry = false;
  ARMSubtarget::PushPopSplitVariation PushPopSplit =
      STI.getPushPopSplitVariation(MF);
  if (MBB.end() != MI) {
    DL = MI->getDebugLoc();
    unsigned RetOpcode = MI->getOpcode();
    isTailCall =
        (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
         RetOpcode == ARM::TCRETURNrinotr12);
    isInterrupt =
        RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
    isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;
    isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
  }

  SmallVector<unsigned, 4> Regs;
  unsigned i = CSI.size();
  while (i != 0) {
    unsigned LastReg = 0;
    bool DeleteRet = false;
    for (; i != 0; --i) {
      CalleeSavedInfo &Info = CSI[i-1];
      MCRegister Reg = Info.getReg();
      if (!Func(Reg))
        continue;

      if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
          !isCmseEntry && !isTrap && AFI->getArgumentStackToRestore() == 0 &&
          STI.hasV5TOps() && MBB.succ_empty() && !hasPAC &&
          (PushPopSplit != ARMSubtarget::SplitR11WindowsSEH &&
           PushPopSplit != ARMSubtarget::SplitR11AAPCSSignRA)) {
        Reg = ARM::PC;
        // Fold the return instruction into the LDM.
        DeleteRet = true;
        LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
      }

      // If NoGap is true, pop consecutive registers and then leave the rest
      // for other instructions. e.g.
      // vpop {d8, d10, d11} -> vpop {d8}, vpop {d10, d11}
      if (NoGap && LastReg && LastReg != Reg-1)
        break;

      LastReg = Reg;
      Regs.push_back(Reg);
    }

    if (Regs.empty())
      continue;

    llvm::sort(Regs, [&](unsigned LHS, unsigned RHS) {
      return TRI.getEncodingValue(LHS) < TRI.getEncodingValue(RHS);
    });

    if (Regs.size() > 1 || LdrOpc == 0) {
      MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP)
                                    .addReg(ARM::SP)
                                    .add(predOps(ARMCC::AL))
                                    .setMIFlags(MachineInstr::FrameDestroy);
      for (unsigned Reg : Regs)
        MIB.addReg(Reg, getDefRegState(true));
      if (DeleteRet) {
        if (MI != MBB.end()) {
          MIB.copyImplicitOps(*MI);
          MI->eraseFromParent();
        }
      }
      MI = MIB;
    } else if (Regs.size() == 1) {
      // If we adjusted the reg to PC from LR above, switch it back here. We
      // only do that for LDM.
      if (Regs[0] == ARM::PC)
        Regs[0] = ARM::LR;
      MachineInstrBuilder MIB =
        BuildMI(MBB, MI, DL, TII.get(LdrOpc), Regs[0])
          .addReg(ARM::SP, RegState::Define)
          .addReg(ARM::SP)
          .setMIFlags(MachineInstr::FrameDestroy);
      // ARM mode needs an extra reg0 here due to addrmode2. Will go away once
      // that refactoring is complete (eventually).
      if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
        MIB.addReg(0);
        MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift));
      } else
        MIB.addImm(4);
      MIB.add(predOps(ARMCC::AL));
    }
    Regs.clear();

    // Put any subsequent vpop instructions after this one: they will refer to
    // higher register numbers so need to be popped afterwards.
    if (MI != MBB.end())
      ++MI;
  }
}

void ARMFrameLowering::emitFPStatusSaves(MachineBasicBlock &MBB,
                                         MachineBasicBlock::iterator MI,
                                         ArrayRef<CalleeSavedInfo> CSI,
                                         unsigned PushOpc) const {
  MachineFunction &MF = *MBB.getParent();
  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();

  SmallVector<MCRegister> Regs;
  auto RegPresent = [&CSI](MCRegister Reg) {
    return llvm::any_of(CSI, [Reg](const CalleeSavedInfo &C) {
      return C.getReg() == Reg;
    });
  };

  // If we need to save FPSCR, then we must move FPSCR into R4 with the VMRS
  // instruction.
  if (RegPresent(ARM::FPSCR)) {
    BuildMI(MBB, MI, DebugLoc(), TII.get(ARM::VMRS), ARM::R4)
        .add(predOps(ARMCC::AL))
        .setMIFlags(MachineInstr::FrameSetup);

    Regs.push_back(ARM::R4);
  }

  // If we need to save FPEXC, then we must move FPEXC into R5 with the
  // VMRS_FPEXC instruction.
  if (RegPresent(ARM::FPEXC)) {
    BuildMI(MBB, MI, DebugLoc(), TII.get(ARM::VMRS_FPEXC), ARM::R5)
        .add(predOps(ARMCC::AL))
        .setMIFlags(MachineInstr::FrameSetup);

    Regs.push_back(ARM::R5);
  }

  // If neither FPSCR and FPEXC are present, then do nothing.
  if (Regs.size() == 0)
    return;

  // Push both R4 and R5 onto the stack, if present.
  MachineInstrBuilder MIB =
      BuildMI(MBB, MI, DebugLoc(), TII.get(PushOpc), ARM::SP)
          .addReg(ARM::SP)
          .add(predOps(ARMCC::AL))
          .setMIFlags(MachineInstr::FrameSetup);

  for (Register Reg : Regs) {
    MIB.addReg(Reg);
  }
}

void ARMFrameLowering::emitFPStatusRestores(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
    MutableArrayRef<CalleeSavedInfo> CSI, unsigned LdmOpc) const {
  MachineFunction &MF = *MBB.getParent();
  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();

  auto RegPresent = [&CSI](MCRegister Reg) {
    return llvm::any_of(CSI, [Reg](const CalleeSavedInfo &C) {
      return C.getReg() == Reg;
    });
  };

  // Do nothing if we don't need to restore any FP status registers.
  if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))
    return;

  // Pop registers off of the stack.
  MachineInstrBuilder MIB =
      BuildMI(MBB, MI, DebugLoc(), TII.get(LdmOpc), ARM::SP)
          .addReg(ARM::SP)
          .add(predOps(ARMCC::AL))
          .setMIFlags(MachineInstr::FrameDestroy);

  // If FPSCR was saved, it will be popped into R4.
  if (RegPresent(ARM::FPSCR)) {
    MIB.addReg(ARM::R4, RegState::Define);
  }

  // If FPEXC was saved, it will be popped into R5.
  if (RegPresent(ARM::FPEXC)) {
    MIB.addReg(ARM::R5, RegState::Define);
  }

  // Move the FPSCR value back into the register with the VMSR instruction.
  if (RegPresent(ARM::FPSCR)) {
    BuildMI(MBB, MI, DebugLoc(), STI.getInstrInfo()->get(ARM::VMSR))
        .addReg(ARM::R4)
        .add(predOps(ARMCC::AL))
        .setMIFlags(MachineInstr::FrameDestroy);
  }

  // Move the FPEXC value back into the register with the VMSR_FPEXC
  // instruction.
  if (RegPresent(ARM::FPEXC)) {
    BuildMI(MBB, MI, DebugLoc(), STI.getInstrInfo()->get(ARM::VMSR_FPEXC))
        .addReg(ARM::R5)
        .add(predOps(ARMCC::AL))
        .setMIFlags(MachineInstr::FrameDestroy);
  }
}

/// Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers
/// starting from d8.  Also insert stack realignment code and leave the stack
/// pointer pointing to the d8 spill slot.
static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB,
                                    MachineBasicBlock::iterator MI,
                                    unsigned NumAlignedDPRCS2Regs,
                                    ArrayRef<CalleeSavedInfo> CSI,
                                    const TargetRegisterInfo *TRI) {
  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
  MachineFrameInfo &MFI = MF.getFrameInfo();

  // Mark the D-register spill slots as properly aligned.  Since MFI computes
  // stack slot layout backwards, this can actually mean that the d-reg stack
  // slot offsets can be wrong. The offset for d8 will always be correct.
  for (const CalleeSavedInfo &I : CSI) {
    unsigned DNum = I.getReg() - ARM::D8;
    if (DNum > NumAlignedDPRCS2Regs - 1)
      continue;
    int FI = I.getFrameIdx();
    // The even-numbered registers will be 16-byte aligned, the odd-numbered
    // registers will be 8-byte aligned.
    MFI.setObjectAlignment(FI, DNum % 2 ? Align(8) : Align(16));

    // The stack slot for D8 needs to be maximally aligned because this is
    // actually the point where we align the stack pointer.  MachineFrameInfo
    // computes all offsets relative to the incoming stack pointer which is a
    // bit weird when realigning the stack.  Any extra padding for this
    // over-alignment is not realized because the code inserted below adjusts
    // the stack pointer by numregs * 8 before aligning the stack pointer.
    if (DNum == 0)
      MFI.setObjectAlignment(FI, MFI.getMaxAlign());
  }

  // Move the stack pointer to the d8 spill slot, and align it at the same
  // time. Leave the stack slot address in the scratch register r4.
  //
  //   sub r4, sp, #numregs * 8
  //   bic r4, r4, #align - 1
  //   mov sp, r4
  //
  bool isThumb = AFI->isThumbFunction();
  assert(!AFI->isThumb1OnlyFunction() && "Can't realign stack for thumb1");
  AFI->setShouldRestoreSPFromFP(true);

  // sub r4, sp, #numregs * 8
  // The immediate is <= 64, so it doesn't need any special encoding.
  unsigned Opc = isThumb ? ARM::t2SUBri : ARM::SUBri;
  BuildMI(MBB, MI, DL, TII.get(Opc), ARM::R4)
      .addReg(ARM::SP)
      .addImm(8 * NumAlignedDPRCS2Regs)
      .add(predOps(ARMCC::AL))
      .add(condCodeOp());

  Align MaxAlign = MF.getFrameInfo().getMaxAlign();
  // We must set parameter MustBeSingleInstruction to true, since
  // skipAlignedDPRCS2Spills expects exactly 3 instructions to perform
  // stack alignment.  Luckily, this can always be done since all ARM
  // architecture versions that support Neon also support the BFC
  // instruction.
  emitAligningInstructions(MF, AFI, TII, MBB, MI, DL, ARM::R4, MaxAlign, true);

  // mov sp, r4
  // The stack pointer must be adjusted before spilling anything, otherwise
  // the stack slots could be clobbered by an interrupt handler.
  // Leave r4 live, it is used below.
  Opc = isThumb ? ARM::tMOVr : ARM::MOVr;
  MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(Opc), ARM::SP)
                                .addReg(ARM::R4)
                                .add(predOps(ARMCC::AL));
  if (!isThumb)
    MIB.add(condCodeOp());

  // Now spill NumAlignedDPRCS2Regs registers starting from d8.
  // r4 holds the stack slot address.
  unsigned NextReg = ARM::D8;

  // 16-byte aligned vst1.64 with 4 d-regs and address writeback.
  // The writeback is only needed when emitting two vst1.64 instructions.
  if (NumAlignedDPRCS2Regs >= 6) {
    MCRegister SupReg =
        TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
    MBB.addLiveIn(SupReg);
    BuildMI(MBB, MI, DL, TII.get(ARM::VST1d64Qwb_fixed), ARM::R4)
        .addReg(ARM::R4, RegState::Kill)
        .addImm(16)
        .addReg(NextReg)
        .addReg(SupReg, RegState::ImplicitKill)
        .add(predOps(ARMCC::AL));
    NextReg += 4;
    NumAlignedDPRCS2Regs -= 4;
  }

  // We won't modify r4 beyond this point.  It currently points to the next
  // register to be spilled.
  unsigned R4BaseReg = NextReg;

  // 16-byte aligned vst1.64 with 4 d-regs, no writeback.
  if (NumAlignedDPRCS2Regs >= 4) {
    MCRegister SupReg =
        TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
    MBB.addLiveIn(SupReg);
    BuildMI(MBB, MI, DL, TII.get(ARM::VST1d64Q))
        .addReg(ARM::R4)
        .addImm(16)
        .addReg(NextReg)
        .addReg(SupReg, RegState::ImplicitKill)
        .add(predOps(ARMCC::AL));
    NextReg += 4;
    NumAlignedDPRCS2Regs -= 4;
  }

  // 16-byte aligned vst1.64 with 2 d-regs.
  if (NumAlignedDPRCS2Regs >= 2) {
    MCRegister SupReg =
        TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
    MBB.addLiveIn(SupReg);
    BuildMI(MBB, MI, DL, TII.get(ARM::VST1q64))
        .addReg(ARM::R4)
        .addImm(16)
        .addReg(SupReg)
        .add(predOps(ARMCC::AL));
    NextReg += 2;
    NumAlignedDPRCS2Regs -= 2;
  }

  // Finally, use a vanilla vstr.64 for the odd last register.
  if (NumAlignedDPRCS2Regs) {
    MBB.addLiveIn(NextReg);
    // vstr.64 uses addrmode5 which has an offset scale of 4.
    BuildMI(MBB, MI, DL, TII.get(ARM::VSTRD))
        .addReg(NextReg)
        .addReg(ARM::R4)
        .addImm((NextReg - R4BaseReg) * 2)
        .add(predOps(ARMCC::AL));
  }

  // The last spill instruction inserted should kill the scratch register r4.
  std::prev(MI)->addRegisterKilled(ARM::R4, TRI);
}

/// Skip past the code inserted by emitAlignedDPRCS2Spills, and return an
/// iterator to the following instruction.
static MachineBasicBlock::iterator
skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI,
                        unsigned NumAlignedDPRCS2Regs) {
  //   sub r4, sp, #numregs * 8
  //   bic r4, r4, #align - 1
  //   mov sp, r4
  ++MI; ++MI; ++MI;
  assert(MI->mayStore() && "Expecting spill instruction");

  // These switches all fall through.
  switch(NumAlignedDPRCS2Regs) {
  case 7:
    ++MI;
    assert(MI->mayStore() && "Expecting spill instruction");
    [[fallthrough]];
  default:
    ++MI;
    assert(MI->mayStore() && "Expecting spill instruction");
    [[fallthrough]];
  case 1:
  case 2:
  case 4:
    assert(MI->killsRegister(ARM::R4, /*TRI=*/nullptr) && "Missed kill flag");
    ++MI;
  }
  return MI;
}

/// Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers
/// starting from d8.  These instructions are assumed to execute while the
/// stack is still aligned, unlike the code inserted by emitPopInst.
static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB,
                                      MachineBasicBlock::iterator MI,
                                      unsigned NumAlignedDPRCS2Regs,
                                      ArrayRef<CalleeSavedInfo> CSI,
                                      const TargetRegisterInfo *TRI) {
  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();

  // Find the frame index assigned to d8.
  int D8SpillFI = 0;
  for (const CalleeSavedInfo &I : CSI)
    if (I.getReg() == ARM::D8) {
      D8SpillFI = I.getFrameIdx();
      break;
    }

  // Materialize the address of the d8 spill slot into the scratch register r4.
  // This can be fairly complicated if the stack frame is large, so just use
  // the normal frame index elimination mechanism to do it.  This code runs as
  // the initial part of the epilog where the stack and base pointers haven't
  // been changed yet.
  bool isThumb = AFI->isThumbFunction();
  assert(!AFI->isThumb1OnlyFunction() && "Can't realign stack for thumb1");

  unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri;
  BuildMI(MBB, MI, DL, TII.get(Opc), ARM::R4)
      .addFrameIndex(D8SpillFI)
      .addImm(0)
      .add(predOps(ARMCC::AL))
      .add(condCodeOp());

  // Now restore NumAlignedDPRCS2Regs registers starting from d8.
  unsigned NextReg = ARM::D8;

  // 16-byte aligned vld1.64 with 4 d-regs and writeback.
  if (NumAlignedDPRCS2Regs >= 6) {
    MCRegister SupReg =
        TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
    BuildMI(MBB, MI, DL, TII.get(ARM::VLD1d64Qwb_fixed), NextReg)
        .addReg(ARM::R4, RegState::Define)
        .addReg(ARM::R4, RegState::Kill)
        .addImm(16)
        .addReg(SupReg, RegState::ImplicitDefine)
        .add(predOps(ARMCC::AL));
    NextReg += 4;
    NumAlignedDPRCS2Regs -= 4;
  }

  // We won't modify r4 beyond this point.  It currently points to the next
  // register to be spilled.
  unsigned R4BaseReg = NextReg;

  // 16-byte aligned vld1.64 with 4 d-regs, no writeback.
  if (NumAlignedDPRCS2Regs >= 4) {
    MCRegister SupReg =
        TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
    BuildMI(MBB, MI, DL, TII.get(ARM::VLD1d64Q), NextReg)
        .addReg(ARM::R4)
        .addImm(16)
        .addReg(SupReg, RegState::ImplicitDefine)
        .add(predOps(ARMCC::AL));
    NextReg += 4;
    NumAlignedDPRCS2Regs -= 4;
  }

  // 16-byte aligned vld1.64 with 2 d-regs.
  if (NumAlignedDPRCS2Regs >= 2) {
    MCRegister SupReg =
        TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
    BuildMI(MBB, MI, DL, TII.get(ARM::VLD1q64), SupReg)
        .addReg(ARM::R4)
        .addImm(16)
        .add(predOps(ARMCC::AL));
    NextReg += 2;
    NumAlignedDPRCS2Regs -= 2;
  }

  // Finally, use a vanilla vldr.64 for the remaining odd register.
  if (NumAlignedDPRCS2Regs)
    BuildMI(MBB, MI, DL, TII.get(ARM::VLDRD), NextReg)
        .addReg(ARM::R4)
        .addImm(2 * (NextReg - R4BaseReg))
        .add(predOps(ARMCC::AL));

  // Last store kills r4.
  std::prev(MI)->addRegisterKilled(ARM::R4, TRI);
}

bool ARMFrameLowering::spillCalleeSavedRegisters(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
    ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
  if (CSI.empty())
    return false;

  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  ARMSubtarget::PushPopSplitVariation PushPopSplit =
      STI.getPushPopSplitVariation(MF);
  const ARMBaseRegisterInfo *RegInfo = STI.getRegisterInfo();

  unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
  unsigned PushOneOpc = AFI->isThumbFunction() ?
    ARM::t2STR_PRE : ARM::STR_PRE_IMM;
  unsigned FltOpc = ARM::VSTMDDB_UPD;
  unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs();
  // Compute PAC in R12.
  if (AFI->shouldSignReturnAddress()) {
    BuildMI(MBB, MI, DebugLoc(), STI.getInstrInfo()->get(ARM::t2PAC))
        .setMIFlags(MachineInstr::FrameSetup);
  }
  // Save the non-secure floating point context.
  if (llvm::any_of(CSI, [](const CalleeSavedInfo &C) {
        return C.getReg() == ARM::FPCXTNS;
      })) {
    BuildMI(MBB, MI, DebugLoc(), STI.getInstrInfo()->get(ARM::VSTR_FPCXTNS_pre),
            ARM::SP)
        .addReg(ARM::SP)
        .addImm(-4)
        .add(predOps(ARMCC::AL));
  }

  auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
                       RegInfo](unsigned Reg, SpillArea TestArea) {
    return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
           TestArea;
  };
  auto IsGPRCS1 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::GPRCS1);
  };
  auto IsGPRCS2 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::GPRCS2);
  };
  auto IsDPRCS1 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::DPRCS1);
  };
  auto IsGPRCS3 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::GPRCS3);
  };

  emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS1);
  emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS2);
  emitFPStatusSaves(MBB, MI, CSI, PushOpc);
  emitPushInst(MBB, MI, CSI, FltOpc, 0, true, IsDPRCS1);
  emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS3);

  // The code above does not insert spill code for the aligned DPRCS2 registers.
  // The stack realignment code will be inserted between the push instructions
  // and these spills.
  if (NumAlignedDPRCS2Regs)
    emitAlignedDPRCS2Spills(MBB, MI, NumAlignedDPRCS2Regs, CSI, TRI);

  return true;
}

bool ARMFrameLowering::restoreCalleeSavedRegisters(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
  if (CSI.empty())
    return false;

  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  const ARMBaseRegisterInfo *RegInfo = STI.getRegisterInfo();

  bool isVarArg = AFI->getArgRegsSaveSize() > 0;
  unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs();
  ARMSubtarget::PushPopSplitVariation PushPopSplit =
      STI.getPushPopSplitVariation(MF);

  // The emitPopInst calls below do not insert reloads for the aligned DPRCS2
  // registers. Do that here instead.
  if (NumAlignedDPRCS2Regs)
    emitAlignedDPRCS2Restores(MBB, MI, NumAlignedDPRCS2Regs, CSI, TRI);

  unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
  unsigned LdrOpc =
      AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
  unsigned FltOpc = ARM::VLDMDIA_UPD;

  auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
                       RegInfo](unsigned Reg, SpillArea TestArea) {
    return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
           TestArea;
  };
  auto IsGPRCS1 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::GPRCS1);
  };
  auto IsGPRCS2 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::GPRCS2);
  };
  auto IsDPRCS1 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::DPRCS1);
  };
  auto IsGPRCS3 = [&CheckRegArea](unsigned Reg) {
    return CheckRegArea(Reg, SpillArea::GPRCS3);
  };

  emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS3);
  emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, IsDPRCS1);
  emitFPStatusRestores(MBB, MI, CSI, PopOpc);
  emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS2);
  emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS1);

  return true;
}

// FIXME: Make generic?
static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF,
                                            const ARMBaseInstrInfo &TII,
                                            const ARMSubtarget &STI,
                                            const ARMBaseRegisterInfo *RegInfo,
                                            BitVector &SavedRegs,
                                            bool BigFrameOffsets) {
  unsigned FnSize = 0;

  bool KCFI = MF.getFunction().getParent()->getModuleFlag("kcfi");

  if (MF.shouldSplitStack()) {
    // Split stack prologue saves r4,r5; makes a copy of sp and loads
    // a literal; compares the two, and if sp < literal, pushes
    // further registers and calls __morestack.
    FnSize += 0x24;
  }

  // Count the number of saved high registers, which take more effort
  // to push and pop in the prologue and epilogue.
  unsigned SavedHighRegs = 0;
  for (auto Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11, ARM::R12})
    if (SavedRegs.test(Reg))
      ++SavedHighRegs;

  // Size of a particularly large Thumb1 stack setup prologue:
  // update sp for variadic functions (2 bytes)
  // + push registers (2 bytes for PUSH {low regs} + 4 bytes per high register
  //   that needs to be copied into a low reg and then pushed)
  // + frame pointer (might use r11, requiring pushing it first, 6 bytes)
  // + stack update (up to 12 bytes if a constant load is needed and a branch
  //   required later to skip the constant)
  // + stack realignment (8, if needed)
  // + make base pointer (2).
  unsigned PrologueSize = 2 + 4 * SavedHighRegs + 6 + 12 + 2;
  if (RegInfo->hasStackRealignment(MF))
    PrologueSize += 8;
  FnSize += PrologueSize;

  // Size of a large epilogue:
  // restore sp from frame pointer (6 bytes if it's in r11)
  // + pop registers (2 bytes + 4 per high register, as above)
  // + pop r11 if it was saved to make frame pointer (4 bytes)
  // + pop return address into a low reg (2 bytes)
  // + update sp to undo variadic function setup (2 bytes)
  // + BX to where you popped the return address (2 bytes)
  unsigned EpilogueSize = 6 + 2 + 4 * SavedHighRegs + 4 + 2 + 2;

  bool FirstBlock = true;
  for (auto &MBB : MF) {
    if (!FirstBlock) {
      // We might have to insert padding to align the start of this basic
      // block.
      unsigned Alignment = MBB.getMaxBytesForAlignment();
      FnSize += Alignment;
    }

    unsigned SizeBeforeThisBB = FnSize;

    bool seenBranch = false, seenConstantLoad = false;
    for (auto &MI : MBB) {
      unsigned InstSize;
      switch (MI.getOpcode()) {
      case ARM::tADDframe:
        if (BigFrameOffsets)
          // We might need two ADD instructions, or even a constant
          // load. In the latter case we must count the constant as
          // well as the load instruction and the addition, for 8
          // bytes total.
          InstSize = 8;
        else
          InstSize = 2;
        break;
      case ARM::tLDRspi:
      case ARM::tSTRspi:
        if (BigFrameOffsets)
          // In a really nasty case, accessing a stack slot might
          // require saving and restoring a scratch register (4 bytes)
          // to make space to load (2 bytes) a constant (4 bytes) to
          // add to SP or FP (2 bytes) and then do the load/store to
          // the resulting register (2 bytes).
          InstSize = 14;
        else
          InstSize = 2;
        break;
      case TargetOpcode::COPY:
        // In some situations, COPY has to go via a high register, to
        // avoid corrupting the PSR flags: Thumb moves between low and
        // high registers don't write the PSR, whereas low/low moves
        // do.
        InstSize = 4; // may have to go via a high reg
        break;
      case ARM::MEMCPY:
        InstSize = 4; // becomes one LDMIA_UPD + STMIA_UPD pair
        break;

      case ARM::Int_eh_sjlj_dispatchsetup:
        // Worst case is 6 bytes, loading a constant from a literal pool.
        InstSize = 6;
        break;

      case ARM::tLDRpci_pic:
        InstSize = 4; // ordinary LDRpci + add to pc
        break;

      case ARM::ADJCALLSTACKDOWN:
      case ARM::ADJCALLSTACKUP:
        InstSize = 2;
        break;

      case ARM::tBLXNS_CALL:
        // A call across a CMSE trust boundary involves a lot of work. We must
        // clear all the registers that might contain our own secrets, which
        // means pushing them first. So first push low registers, then move
        // four high regs into them and push those too.
        InstSize = 2 + 2 * 4 + 2;
        // Then we must clear the low bit of the target register, because
        // instead of indicating Arm/Thumb it indicates the CMSE security
        // status. That takes two instructions.
        InstSize += 4;
        // Now actually clear all the registers, via a MOV for each one. This
        // includes argument registers as well as saved regs, so it can be
        // r1-r12 inclusive.
        InstSize += 2 * 12;
        // Clear the PSR flags (a wide instruction even in Armv8-M Baseline).
        InstSize += 4;
        // Perform the BLXNS call itself.
        InstSize += 2;
        // Now pop all the saved registers, which takes the same amount of
        // effort as pushing them did.
        InstSize += 2 + 2 * 4 + 2;
        break;

      case ARM::tBXNS_RET:
        // When returning across a CMSE boundary, we must potentially clear all
        // the registers that we haven't restored to the caller's value: r0-r3
        // and r12. We also clear the PSR flags, and finally return via BXNS.
        InstSize = 5 * 2 + 4 + 2;
        break;

      case TargetOpcode::LOAD_STACK_GUARD:
        if (STI.genExecuteOnly())
          // In execute-only code generation, it costs seven 2-byte
          // instructions (MOV + 3 ADD + 3 LSL) to load an arbitrary
          // 32-bit constant, plus two 4-byte MSRs to save/restore the
          // flags those instructions clobber. Then we load from the
          // resulting address with one more 2-byte instruction.
          InstSize = 7 * 2 + 2 * 4 + 8;
        else
          // If we're not generating execute-only code, the constant
          // just costs an LDR and a literal, and then another LDR is
          // needed to load from that address.
          InstSize = 2 * 2 + 4;
        break;

      default:
        InstSize = TII.getInstSizeInBytes(MI);
        break;
      }

      FnSize += InstSize;

      // If the instruction loads a constant, score the size of the
      // constant, in case it can't be shared with other basic blocks.
      for (MachineMemOperand *MO : MI.memoperands()) {
        const PseudoSourceValue *PSV =
            dyn_cast_if_present<const PseudoSourceValue *>(
                MO->getPointerInfo().V);
        if (PSV && PSV->kind() == PseudoSourceValue::ConstantPool) {
          unsigned ConstSize = MO->getType().getSizeInBytes();
          FnSize += ConstSize;
          seenConstantLoad = true;
        }
      }

      // If the instruction is a return or a tailcall, count the size
      // of an epilogue. (We do this for each return, in case the
      // epilogue must be duplicated.)
      if (MI.isReturn() || TII.isTailCall(MI)) {
        FnSize += EpilogueSize;
      }

      // If the instruction is a call, and KCFI is enabled, then count the
      // cost of a KCFI_CHECK_Thumb1 pseudo.
      if (KCFI && MI.isCall() && MI.getCFIType()) {
        const MCInstrDesc &MCID = TII.get(ARM::KCFI_CHECK_Thumb1);
        FnSize += MCID.getSize();
      }

      if (MI.isUnconditionalBranch())
        seenBranch = true;
    }

    // If there's no branch instruction in the block and we saw a constant,
    // count a branch + realignment to 4 bytes, in case we have to branch round
    // it.
    if (seenConstantLoad && !seenBranch) {
      FnSize += 4;
    }

    // Also, if the block is really, really big, then count an extra 4 bytes
    // (again branch + realignment) for potentially splitting it in order to
    // put constants in the middle, avoiding the problem of an LDR not being
    // able to reach all the way to the end. The LDR offset limit is 1024
    // bytes; the splitting itself adds some cost, but since any function this
    // large is likely to have already gone over the "must stack LR" limit, we
    // can keep things simple by assuming we split at half that rate.
    unsigned BBSize = FnSize - SizeBeforeThisBB;
    FnSize += 4 * BBSize / 512;
  }
  if (MF.getJumpTableInfo()) {
    for (auto &Table : MF.getJumpTableInfo()->getJumpTables()) {
      unsigned TableLen = Table.MBBs.size();
      unsigned TableSizeBytes = TableLen * 4;
      FnSize += TableSizeBytes;
    }
  }
  LLVM_DEBUG(dbgs() << "Estimated function size for " << MF.getName() << " = "
                    << FnSize << " bytes\n");
  return FnSize;
}

/// estimateRSStackSizeLimit - Look at each instruction that references stack
/// frames and return the stack size limit beyond which some of these
/// instructions will require a scratch register during their expansion later.
// FIXME: Move to TII?
static unsigned estimateRSStackSizeLimit(MachineFunction &MF,
                                         const TargetFrameLowering *TFI,
                                         bool &HasNonSPFrameIndex) {
  const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  const ARMBaseInstrInfo &TII =
      *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());
  unsigned Limit = (1 << 12) - 1;
  for (auto &MBB : MF) {
    for (auto &MI : MBB) {
      if (MI.isDebugInstr())
        continue;
      if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
        continue;
      for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
        if (!MI.getOperand(i).isFI())
          continue;

        // When using ADDri to get the address of a stack object, 255 is the
        // largest offset guaranteed to fit in the immediate offset.
        if (MI.getOpcode() == ARM::ADDri) {
          Limit = std::min(Limit, (1U << 8) - 1);
          break;
        }
        // t2ADDri will not require an extra register, it can reuse the
        // destination.
        if (MI.getOpcode() == ARM::t2ADDri || MI.getOpcode() == ARM::t2ADDri12)
          break;

        const MCInstrDesc &MCID = MI.getDesc();
        const TargetRegisterClass *RegClass = TII.getRegClass(MCID, i);
        if (RegClass && !RegClass->contains(ARM::SP))
          HasNonSPFrameIndex = true;

        // Otherwise check the addressing mode.
        switch (MI.getDesc().TSFlags & ARMII::AddrModeMask) {
        case ARMII::AddrMode_i12:
        case ARMII::AddrMode2:
          // Default 12 bit limit.
          break;
        case ARMII::AddrMode3:
        case ARMII::AddrModeT2_i8neg:
          Limit = std::min(Limit, (1U << 8) - 1);
          break;
        case ARMII::AddrMode5FP16:
          Limit = std::min(Limit, ((1U << 8) - 1) * 2);
          break;
        case ARMII::AddrMode5:
        case ARMII::AddrModeT2_i8s4:
        case ARMII::AddrModeT2_ldrex:
          Limit = std::min(Limit, ((1U << 8) - 1) * 4);
          break;
        case ARMII::AddrModeT2_i12:
          // i12 supports only positive offset so these will be converted to
          // i8 opcodes. See llvm::rewriteT2FrameIndex.
          if (TFI->hasFP(MF) && AFI->hasStackFrame())
            Limit = std::min(Limit, (1U << 8) - 1);
          break;
        case ARMII::AddrMode4:
        case ARMII::AddrMode6:
          // Addressing modes 4 & 6 (load/store) instructions can't encode an
          // immediate offset for stack references.
          return 0;
        case ARMII::AddrModeT2_i7:
          Limit = std::min(Limit, ((1U << 7) - 1) * 1);
          break;
        case ARMII::AddrModeT2_i7s2:
          Limit = std::min(Limit, ((1U << 7) - 1) * 2);
          break;
        case ARMII::AddrModeT2_i7s4:
          Limit = std::min(Limit, ((1U << 7) - 1) * 4);
          break;
        default:
          llvm_unreachable("Unhandled addressing mode in stack size limit calculation");
        }
        break; // At most one FI per instruction
      }
    }
  }

  return Limit;
}

// In functions that realign the stack, it can be an advantage to spill the
// callee-saved vector registers after realigning the stack. The vst1 and vld1
// instructions take alignment hints that can improve performance.
static void
checkNumAlignedDPRCS2Regs(MachineFunction &MF, BitVector &SavedRegs) {
  MF.getInfo<ARMFunctionInfo>()->setNumAlignedDPRCS2Regs(0);
  if (!SpillAlignedNEONRegs)
    return;

  // Naked functions don't spill callee-saved registers.
  if (MF.getFunction().hasFnAttribute(Attribute::Naked))
    return;

  // We are planning to use NEON instructions vst1 / vld1.
  if (!MF.getSubtarget<ARMSubtarget>().hasNEON())
    return;

  // Don't bother if the default stack alignment is sufficiently high.
  if (MF.getSubtarget().getFrameLowering()->getStackAlign() >= Align(8))
    return;

  // Aligned spills require stack realignment.
  if (!static_cast<const ARMBaseRegisterInfo *>(
           MF.getSubtarget().getRegisterInfo())->canRealignStack(MF))
    return;

  // We always spill contiguous d-registers starting from d8. Count how many
  // needs spilling.  The register allocator will almost always use the
  // callee-saved registers in order, but it can happen that there are holes in
  // the range.  Registers above the hole will be spilled to the standard DPRCS
  // area.
  unsigned NumSpills = 0;
  for (; NumSpills < 8; ++NumSpills)
    if (!SavedRegs.test(ARM::D8 + NumSpills))
      break;

  // Don't do this for just one d-register. It's not worth it.
  if (NumSpills < 2)
    return;

  // Spill the first NumSpills D-registers after realigning the stack.
  MF.getInfo<ARMFunctionInfo>()->setNumAlignedDPRCS2Regs(NumSpills);

  // A scratch register is required for the vst1 / vld1 instructions.
  SavedRegs.set(ARM::R4);
}

bool ARMFrameLowering::enableShrinkWrapping(const MachineFunction &MF) const {
  // For CMSE entry functions, we want to save the FPCXT_NS immediately
  // upon function entry (resp. restore it immediately before return)
  if (STI.hasV8_1MMainlineOps() &&
      MF.getInfo<ARMFunctionInfo>()->isCmseNSEntryFunction())
    return false;

  // We are disabling shrinkwrapping for now when PAC is enabled, as
  // shrinkwrapping can cause clobbering of r12 when the PAC code is
  // generated. A follow-up patch will fix this in a more performant manner.
  if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
          true /* SpillsLR */))
    return false;

  return true;
}

bool ARMFrameLowering::requiresAAPCSFrameRecord(
    const MachineFunction &MF) const {
  const auto &Subtarget = MF.getSubtarget<ARMSubtarget>();
  return Subtarget.createAAPCSFrameChain() && hasFP(MF);
}

// Thumb1 may require a spill when storing to a frame index through FP (or any
// access with execute-only), for cases where FP is a high register (R11). This
// scans the function for cases where this may happen.
static bool canSpillOnFrameIndexAccess(const MachineFunction &MF,
                                       const TargetFrameLowering &TFI) {
  const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  if (!AFI->isThumb1OnlyFunction())
    return false;

  const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
  for (const auto &MBB : MF)
    for (const auto &MI : MBB)
      if (MI.getOpcode() == ARM::tSTRspi || MI.getOpcode() == ARM::tSTRi ||
          STI.genExecuteOnly())
        for (const auto &Op : MI.operands())
          if (Op.isFI()) {
            Register Reg;
            TFI.getFrameIndexReference(MF, Op.getIndex(), Reg);
            if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::SP)
              return true;
          }
  return false;
}

void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                            BitVector &SavedRegs,
                                            RegScavenger *RS) const {
  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
  // This tells PEI to spill the FP as if it is any other callee-save register
  // to take advantage the eliminateFrameIndex machinery. This also ensures it
  // is spilled in the order specified by getCalleeSavedRegs() to make it easier
  // to combine multiple loads / stores.
  bool CanEliminateFrame = !(requiresAAPCSFrameRecord(MF) && hasFP(MF)) &&
                           !MF.getTarget().Options.DisableFramePointerElim(MF);
  bool CS1Spilled = false;
  bool LRSpilled = false;
  unsigned NumGPRSpills = 0;
  unsigned NumFPRSpills = 0;
  SmallVector<unsigned, 4> UnspilledCS1GPRs;
  SmallVector<unsigned, 4> UnspilledCS2GPRs;
  const Function &F = MF.getFunction();
  const ARMBaseRegisterInfo *RegInfo = static_cast<const ARMBaseRegisterInfo *>(
      MF.getSubtarget().getRegisterInfo());
  const ARMBaseInstrInfo &TII =
      *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  MachineRegisterInfo &MRI = MF.getRegInfo();
  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
  (void)TRI;  // Silence unused warning in non-assert builds.
  Register FramePtr = STI.getFramePointerReg();
  ARMSubtarget::PushPopSplitVariation PushPopSplit =
      STI.getPushPopSplitVariation(MF);

  // For a floating point interrupt, save these registers always, since LLVM
  // currently doesn't model reads/writes to these registers.
  if (F.hasFnAttribute("interrupt") && F.hasFnAttribute("save-fp")) {
    SavedRegs.set(ARM::FPSCR);
    SavedRegs.set(ARM::R4);

    // This register will only be present on non-MClass registers.
    if (STI.isMClass()) {
      SavedRegs.reset(ARM::FPEXC);
    } else {
      SavedRegs.set(ARM::FPEXC);
      SavedRegs.set(ARM::R5);
    }
  }

  // Spill R4 if Thumb2 function requires stack realignment - it will be used as
  // scratch register. Also spill R4 if Thumb2 function has varsized objects,
  // since it's not always possible to restore sp from fp in a single
  // instruction.
  // FIXME: It will be better just to find spare register here.
  if (AFI->isThumb2Function() &&
      (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
    SavedRegs.set(ARM::R4);

  // If a stack probe will be emitted, spill R4 and LR, since they are
  // clobbered by the stack probe call.
  // This estimate should be a safe, conservative estimate. The actual
  // stack probe is enabled based on the size of the local objects;
  // this estimate also includes the varargs store size.
  if (STI.isTargetWindows() &&
      WindowsRequiresStackProbe(MF, MFI.estimateStackSize(MF))) {
    SavedRegs.set(ARM::R4);
    SavedRegs.set(ARM::LR);
  }

  if (AFI->isThumb1OnlyFunction()) {
    // Spill LR if Thumb1 function uses variable length argument lists.
    if (AFI->getArgRegsSaveSize() > 0)
      SavedRegs.set(ARM::LR);

    // Spill R4 if Thumb1 epilogue has to restore SP from FP or the function
    // requires stack alignment.  We don't know for sure what the stack size
    // will be, but for this, an estimate is good enough. If there anything
    // changes it, it'll be a spill, which implies we've used all the registers
    // and so R4 is already used, so not marking it here will be OK.
    // FIXME: It will be better just to find spare register here.
    if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
        MFI.estimateStackSize(MF) > 508)
      SavedRegs.set(ARM::R4);
  }

  // See if we can spill vector registers to aligned stack.
  checkNumAlignedDPRCS2Regs(MF, SavedRegs);

  // Spill the BasePtr if it's used.
  if (RegInfo->hasBasePointer(MF))
    SavedRegs.set(RegInfo->getBaseRegister());

  // On v8.1-M.Main CMSE entry functions save/restore FPCXT.
  if (STI.hasV8_1MMainlineOps() && AFI->isCmseNSEntryFunction())
    CanEliminateFrame = false;

  // When return address signing is enabled R12 is treated as callee-saved.
  if (AFI->shouldSignReturnAddress())
    CanEliminateFrame = false;

  // Don't spill FP if the frame can be eliminated. This is determined
  // by scanning the callee-save registers to see if any is modified.
  const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    bool Spilled = false;
    if (SavedRegs.test(Reg)) {
      Spilled = true;
      CanEliminateFrame = false;
    }

    if (!ARM::GPRRegClass.contains(Reg)) {
      if (Spilled) {
        if (ARM::SPRRegClass.contains(Reg))
          NumFPRSpills++;
        else if (ARM::DPRRegClass.contains(Reg))
          NumFPRSpills += 2;
        else if (ARM::QPRRegClass.contains(Reg))
          NumFPRSpills += 4;
      }
      continue;
    }

    if (Spilled) {
      NumGPRSpills++;

      if (PushPopSplit != ARMSubtarget::SplitR7) {
        if (Reg == ARM::LR)
          LRSpilled = true;
        CS1Spilled = true;
        continue;
      }

      // Keep track if LR and any of R4, R5, R6, and R7 is spilled.
      switch (Reg) {
      case ARM::LR:
        LRSpilled = true;
        [[fallthrough]];
      case ARM::R0: case ARM::R1:
      case ARM::R2: case ARM::R3:
      case ARM::R4: case ARM::R5:
      case ARM::R6: case ARM::R7:
        CS1Spilled = true;
        break;
      default:
        break;
      }
    } else {
      if (PushPopSplit != ARMSubtarget::SplitR7) {
        UnspilledCS1GPRs.push_back(Reg);
        continue;
      }

      switch (Reg) {
      case ARM::R0: case ARM::R1:
      case ARM::R2: case ARM::R3:
      case ARM::R4: case ARM::R5:
      case ARM::R6: case ARM::R7:
      case ARM::LR:
        UnspilledCS1GPRs.push_back(Reg);
        break;
      default:
        UnspilledCS2GPRs.push_back(Reg);
        break;
      }
    }
  }

  bool ForceLRSpill = false;

  // If any of the stack slot references may be out of range of an immediate
  // offset, make sure a register (or a spill slot) is available for the
  // register scavenger. Note that if we're indexing off the frame pointer, the
  // effective stack size is 4 bytes larger since the FP points to the stack
  // slot of the previous FP. Also, if we have variable sized objects in the
  // function, stack slot references will often be negative, and some of
  // our instructions are positive-offset only, so conservatively consider
  // that case to want a spill slot (or register) as well. Similarly, if
  // the function adjusts the stack pointer during execution and the
  // adjustments aren't already part of our stack size estimate, our offset
  // calculations may be off, so be conservative.
  // FIXME: We could add logic to be more precise about negative offsets
  //        and which instructions will need a scratch register for them. Is it
  //        worth the effort and added fragility?
  unsigned EstimatedStackSize =
      MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);

  // Determine biggest (positive) SP offset in MachineFrameInfo.
  int MaxFixedOffset = 0;
  for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {
    int MaxObjectOffset = MFI.getObjectOffset(I) + MFI.getObjectSize(I);
    MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
  }

  bool HasFP = hasFP(MF);
  if (HasFP) {
    if (AFI->hasStackFrame())
      EstimatedStackSize += 4;
  } else {
    // If FP is not used, SP will be used to access arguments, so count the
    // size of arguments into the estimation.
    EstimatedStackSize += MaxFixedOffset;
  }
  EstimatedStackSize += 16; // For possible paddings.

  unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
  bool HasNonSPFrameIndex = false;
  if (AFI->isThumb1OnlyFunction()) {
    // For Thumb1, don't bother to iterate over the function. The only
    // instruction that requires an emergency spill slot is a store to a
    // frame index.
    //
    // tSTRspi, which is used for sp-relative accesses, has an 8-bit unsigned
    // immediate. tSTRi, which is used for bp- and fp-relative accesses, has
    // a 5-bit unsigned immediate.
    //
    // We could try to check if the function actually contains a tSTRspi
    // that might need the spill slot, but it's not really important.
    // Functions with VLAs or extremely large call frames are rare, and
    // if a function is allocating more than 1KB of stack, an extra 4-byte
    // slot probably isn't relevant.
    //
    // A special case is the scenario where r11 is used as FP, where accesses
    // to a frame index will require its value to be moved into a low reg.
    // This is handled later on, once we are able to determine if we have any
    // fp-relative accesses.
    if (RegInfo->hasBasePointer(MF))
      EstimatedRSStackSizeLimit = (1U << 5) * 4;
    else
      EstimatedRSStackSizeLimit = (1U << 8) * 4;
    EstimatedRSFixedSizeLimit = (1U << 5) * 4;
  } else {
    EstimatedRSStackSizeLimit =
        estimateRSStackSizeLimit(MF, this, HasNonSPFrameIndex);
    EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
  }
  // Final estimate of whether sp or bp-relative accesses might require
  // scavenging.
  bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;

  // If the stack pointer moves and we don't have a base pointer, the
  // estimate logic doesn't work. The actual offsets might be larger when
  // we're constructing a call frame, or we might need to use negative
  // offsets from fp.
  bool HasMovingSP = MFI.hasVarSizedObjects() ||
    (MFI.adjustsStack() && !canSimplifyCallFramePseudos(MF));
  bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;

  // If we have a frame pointer, we assume arguments will be accessed
  // relative to the frame pointer. Check whether fp-relative accesses to
  // arguments require scavenging.
  //
  // We could do slightly better on Thumb1; in some cases, an sp-relative
  // offset would be legal even though an fp-relative offset is not.
  int MaxFPOffset = getMaxFPOffset(STI, *AFI, MF);
  bool HasLargeArgumentList =
      HasFP && (MaxFixedOffset - MaxFPOffset) > (int)EstimatedRSFixedSizeLimit;

  bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
                         HasLargeArgumentList || HasNonSPFrameIndex;
  LLVM_DEBUG(dbgs() << "EstimatedLimit: " << EstimatedRSStackSizeLimit
                    << "; EstimatedStack: " << EstimatedStackSize
                    << "; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
                    << "; BigFrameOffsets: " << BigFrameOffsets << "\n");

  if (!LRSpilled && AFI->isThumb1OnlyFunction()) {
    unsigned FnSize = EstimateFunctionSizeInBytes(MF, TII, STI, RegInfo,
                                                  SavedRegs, BigFrameOffsets);

    if (FnSize >= (1 << 11)) {
      // Force LR to be spilled if the Thumb function size is > 2048. This
      // enables use of BL to implement far jump.
      CanEliminateFrame = false;
      ForceLRSpill = true;
    }
  }

  if (BigFrameOffsets ||
      !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
    AFI->setHasStackFrame(true);

    // Save the FP if:
    // 1. We currently need it (HasFP), OR
    // 2. We might need it later due to stack realignment from aligned DPRCS2
    //    saves (which will make hasFP() become true in emitPrologue).
    if (HasFP || (isFPReserved(MF) && AFI->getNumAlignedDPRCS2Regs() > 0)) {
      SavedRegs.set(FramePtr);
      // If the frame pointer is required by the ABI, also spill LR so that we
      // emit a complete frame record.
      if ((requiresAAPCSFrameRecord(MF) ||
           MF.getTarget().Options.DisableFramePointerElim(MF)) &&
          !LRSpilled) {
        SavedRegs.set(ARM::LR);
        LRSpilled = true;
        NumGPRSpills++;
        auto LRPos = llvm::find(UnspilledCS1GPRs, ARM::LR);
        if (LRPos != UnspilledCS1GPRs.end())
          UnspilledCS1GPRs.erase(LRPos);
      }
      auto FPPos = llvm::find(UnspilledCS1GPRs, FramePtr);
      if (FPPos != UnspilledCS1GPRs.end())
        UnspilledCS1GPRs.erase(FPPos);
      NumGPRSpills++;
      if (FramePtr == ARM::R7)
        CS1Spilled = true;
    }

    // This is the number of extra spills inserted for callee-save GPRs which
    // would not otherwise be used by the function. When greater than zero it
    // guaranteees that it is possible to scavenge a register to hold the
    // address of a stack slot. On Thumb1, the register must be a valid operand
    // to tSTRi, i.e. r4-r7. For other subtargets, this is any GPR, i.e. r4-r11
    // or lr.
    //
    // If we don't insert a spill, we instead allocate an emergency spill
    // slot, which can be used by scavenging to spill an arbitrary register.
    //
    // We currently don't try to figure out whether any specific instruction
    // requires scavening an additional register.
    unsigned NumExtraCSSpill = 0;

    if (AFI->isThumb1OnlyFunction()) {
      // For Thumb1-only targets, we need some low registers when we save and
      // restore the high registers (which aren't allocatable, but could be
      // used by inline assembly) because the push/pop instructions can not
      // access high registers. If necessary, we might need to push more low
      // registers to ensure that there is at least one free that can be used
      // for the saving & restoring, and preferably we should ensure that as
      // many as are needed are available so that fewer push/pop instructions
      // are required.

      // Low registers which are not currently pushed, but could be (r4-r7).
      SmallVector<unsigned, 4> AvailableRegs;

      // Unused argument registers (r0-r3) can be clobbered in the prologue for
      // free.
      int EntryRegDeficit = 0;
      for (unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
        if (!MF.getRegInfo().isLiveIn(Reg)) {
          --EntryRegDeficit;
          LLVM_DEBUG(dbgs()
                     << printReg(Reg, TRI)
                     << " is unused argument register, EntryRegDeficit = "
                     << EntryRegDeficit << "\n");
        }
      }

      // Unused return registers can be clobbered in the epilogue for free.
      int ExitRegDeficit = AFI->getReturnRegsCount() - 4;
      LLVM_DEBUG(dbgs() << AFI->getReturnRegsCount()
                        << " return regs used, ExitRegDeficit = "
                        << ExitRegDeficit << "\n");

      int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
      LLVM_DEBUG(dbgs() << "RegDeficit = " << RegDeficit << "\n");

      // r4-r6 can be used in the prologue if they are pushed by the first push
      // instruction.
      for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
        if (SavedRegs.test(Reg)) {
          --RegDeficit;
          LLVM_DEBUG(dbgs() << printReg(Reg, TRI)
                            << " is saved low register, RegDeficit = "
                            << RegDeficit << "\n");
        } else {
          AvailableRegs.push_back(Reg);
          LLVM_DEBUG(
              dbgs()
              << printReg(Reg, TRI)
              << " is non-saved low register, adding to AvailableRegs\n");
        }
      }

      // r7 can be used if it is not being used as the frame pointer.
      if (!HasFP || FramePtr != ARM::R7) {
        if (SavedRegs.test(ARM::R7)) {
          --RegDeficit;
          LLVM_DEBUG(dbgs() << "%r7 is saved low register, RegDeficit = "
                            << RegDeficit << "\n");
        } else {
          AvailableRegs.push_back(ARM::R7);
          LLVM_DEBUG(
              dbgs()
              << "%r7 is non-saved low register, adding to AvailableRegs\n");
        }
      }

      // Each of r8-r11 needs to be copied to a low register, then pushed.
      for (unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
        if (SavedRegs.test(Reg)) {
          ++RegDeficit;
          LLVM_DEBUG(dbgs() << printReg(Reg, TRI)
                            << " is saved high register, RegDeficit = "
                            << RegDeficit << "\n");
        }
      }

      // LR can only be used by PUSH, not POP, and can't be used at all if the
      // llvm.returnaddress intrinsic is used. This is only worth doing if we
      // are more limited at function entry than exit.
      if ((EntryRegDeficit > ExitRegDeficit) &&
          !(MF.getRegInfo().isLiveIn(ARM::LR) &&
            MF.getFrameInfo().isReturnAddressTaken())) {
        if (SavedRegs.test(ARM::LR)) {
          --RegDeficit;
          LLVM_DEBUG(dbgs() << "%lr is saved register, RegDeficit = "
                            << RegDeficit << "\n");
        } else {
          AvailableRegs.push_back(ARM::LR);
          LLVM_DEBUG(dbgs() << "%lr is not saved, adding to AvailableRegs\n");
        }
      }

      // If there are more high registers that need pushing than low registers
      // available, push some more low registers so that we can use fewer push
      // instructions. This might not reduce RegDeficit all the way to zero,
      // because we can only guarantee that r4-r6 are available, but r8-r11 may
      // need saving.
      LLVM_DEBUG(dbgs() << "Final RegDeficit = " << RegDeficit << "\n");
      for (; RegDeficit > 0 && !AvailableRegs.empty(); --RegDeficit) {
        unsigned Reg = AvailableRegs.pop_back_val();
        LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, TRI)
                          << " to make up reg deficit\n");
        SavedRegs.set(Reg);
        NumGPRSpills++;
        CS1Spilled = true;
        assert(!MRI.isReserved(Reg) && "Should not be reserved");
        if (Reg != ARM::LR && !MRI.isPhysRegUsed(Reg))
          NumExtraCSSpill++;
        UnspilledCS1GPRs.erase(llvm::find(UnspilledCS1GPRs, Reg));
        if (Reg == ARM::LR)
          LRSpilled = true;
      }
      LLVM_DEBUG(dbgs() << "After adding spills, RegDeficit = " << RegDeficit
                        << "\n");
    }

    // Avoid spilling LR in Thumb1 if there's a tail call: it's expensive to
    // restore LR in that case.
    bool ExpensiveLRRestore = AFI->isThumb1OnlyFunction() && MFI.hasTailCall();

    // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled.
    // Spill LR as well so we can fold BX_RET to the registers restore (LDM).
    if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
      SavedRegs.set(ARM::LR);
      NumGPRSpills++;
      SmallVectorImpl<unsigned>::iterator LRPos;
      LRPos = llvm::find(UnspilledCS1GPRs, (unsigned)ARM::LR);
      if (LRPos != UnspilledCS1GPRs.end())
        UnspilledCS1GPRs.erase(LRPos);

      ForceLRSpill = false;
      if (!MRI.isReserved(ARM::LR) && !MRI.isPhysRegUsed(ARM::LR) &&
          !AFI->isThumb1OnlyFunction())
        NumExtraCSSpill++;
    }

    // If stack and double are 8-byte aligned and we are spilling an odd number
    // of GPRs, spill one extra callee save GPR so we won't have to pad between
    // the integer and double callee save areas.
    LLVM_DEBUG(dbgs() << "NumGPRSpills = " << NumGPRSpills << "\n");
    const Align TargetAlign = getStackAlign();
    if (TargetAlign >= Align(8) && (NumGPRSpills & 1)) {
      if (CS1Spilled && !UnspilledCS1GPRs.empty()) {
        for (unsigned Reg : UnspilledCS1GPRs) {
          // Don't spill high register if the function is thumb.  In the case of
          // Windows on ARM, accept R11 (frame pointer)
          if (!AFI->isThumbFunction() ||
              (STI.isTargetWindows() && Reg == ARM::R11) ||
              isARMLowRegister(Reg) ||
              (Reg == ARM::LR && !ExpensiveLRRestore)) {
            SavedRegs.set(Reg);
            LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, TRI)
                              << " to make up alignment\n");
            if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg) &&
                !(Reg == ARM::LR && AFI->isThumb1OnlyFunction()))
              NumExtraCSSpill++;
            break;
          }
        }
      } else if (!UnspilledCS2GPRs.empty() && !AFI->isThumb1OnlyFunction()) {
        unsigned Reg = UnspilledCS2GPRs.front();
        SavedRegs.set(Reg);
        LLVM_DEBUG(dbgs() << "Spilling " << printReg(Reg, TRI)
                          << " to make up alignment\n");
        if (!MRI.isReserved(Reg) && !MRI.isPhysRegUsed(Reg))
          NumExtraCSSpill++;
      }
    }

    // Estimate if we might need to scavenge registers at some point in order
    // to materialize a stack offset. If so, either spill one additional
    // callee-saved register or reserve a special spill slot to facilitate
    // register scavenging. Thumb1 needs a spill slot for stack pointer
    // adjustments and for frame index accesses when FP is high register,
    // even when the frame itself is small.
    unsigned RegsNeeded = 0;
    if (BigFrameOffsets || canSpillOnFrameIndexAccess(MF, *this)) {
      RegsNeeded++;
      // With thumb1 execute-only we may need an additional register for saving
      // and restoring the CPSR.
      if (AFI->isThumb1OnlyFunction() && STI.genExecuteOnly() && !STI.useMovt())
        RegsNeeded++;
    }

    if (RegsNeeded > NumExtraCSSpill) {
      // If any non-reserved CS register isn't spilled, just spill one or two
      // extra. That should take care of it!
      unsigned NumExtras = TargetAlign.value() / 4;
      SmallVector<unsigned, 2> Extras;
      while (NumExtras && !UnspilledCS1GPRs.empty()) {
        unsigned Reg = UnspilledCS1GPRs.pop_back_val();
        if (!MRI.isReserved(Reg) &&
            (!AFI->isThumb1OnlyFunction() || isARMLowRegister(Reg))) {
          Extras.push_back(Reg);
          NumExtras--;
        }
      }
      // For non-Thumb1 functions, also check for hi-reg CS registers
      if (!AFI->isThumb1OnlyFunction()) {
        while (NumExtras && !UnspilledCS2GPRs.empty()) {
          unsigned Reg = UnspilledCS2GPRs.pop_back_val();
          if (!MRI.isReserved(Reg)) {
            Extras.push_back(Reg);
            NumExtras--;
          }
        }
      }
      if (NumExtras == 0) {
        for (unsigned Reg : Extras) {
          SavedRegs.set(Reg);
          if (!MRI.isPhysRegUsed(Reg))
            NumExtraCSSpill++;
        }
      }
      while ((RegsNeeded > NumExtraCSSpill) && RS) {
        // Reserve a slot closest to SP or frame pointer.
        LLVM_DEBUG(dbgs() << "Reserving emergency spill slot\n");
        const TargetRegisterClass &RC = ARM::GPRRegClass;
        unsigned Size = TRI->getSpillSize(RC);
        Align Alignment = TRI->getSpillAlign(RC);
        RS->addScavengingFrameIndex(
            MFI.CreateSpillStackObject(Size, Alignment));
        --RegsNeeded;
      }
    }
  }

  if (ForceLRSpill)
    SavedRegs.set(ARM::LR);
  AFI->setLRIsSpilled(SavedRegs.test(ARM::LR));
}

void ARMFrameLowering::updateLRRestored(MachineFunction &MF) {
  MachineFrameInfo &MFI = MF.getFrameInfo();
  if (!MFI.isCalleeSavedInfoValid())
    return;

  // Check if all terminators do not implicitly use LR. Then we can 'restore' LR
  // into PC so it is not live out of the return block: Clear the Restored bit
  // in that case.
  for (CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
    if (Info.getReg() != ARM::LR)
      continue;
    if (all_of(MF, [](const MachineBasicBlock &MBB) {
          return all_of(MBB.terminators(), [](const MachineInstr &Term) {
            return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
                   Term.getOpcode() == ARM::t2LDMIA_RET ||
                   Term.getOpcode() == ARM::tPOP_RET;
          });
        })) {
      Info.setRestored(false);
      break;
    }
  }
}

void ARMFrameLowering::processFunctionBeforeFrameFinalized(
    MachineFunction &MF, RegScavenger *RS) const {
  TargetFrameLowering::processFunctionBeforeFrameFinalized(MF, RS);
  updateLRRestored(MF);
}

void ARMFrameLowering::getCalleeSaves(const MachineFunction &MF,
                                      BitVector &SavedRegs) const {
  TargetFrameLowering::getCalleeSaves(MF, SavedRegs);

  // If we have the "returned" parameter attribute which guarantees that we
  // return the value which was passed in r0 unmodified (e.g. C++ 'structors),
  // record that fact for IPRA.
  const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  if (AFI->getPreservesR0())
    SavedRegs.set(ARM::R0);
}

bool ARMFrameLowering::assignCalleeSavedSpillSlots(
    MachineFunction &MF, const TargetRegisterInfo *TRI,
    std::vector<CalleeSavedInfo> &CSI) const {
  // For CMSE entry functions, handle floating-point context as if it was a
  // callee-saved register.
  if (STI.hasV8_1MMainlineOps() &&
      MF.getInfo<ARMFunctionInfo>()->isCmseNSEntryFunction()) {
    CSI.emplace_back(ARM::FPCXTNS);
    CSI.back().setRestored(false);
  }

  // For functions, which sign their return address, upon function entry, the
  // return address PAC is computed in R12. Treat R12 as a callee-saved register
  // in this case.
  const auto &AFI = *MF.getInfo<ARMFunctionInfo>();
  if (AFI.shouldSignReturnAddress()) {
    // The order of register must match the order we push them, because the
    // PEI assigns frame indices in that order. That order depends on the
    // PushPopSplitVariation, there are only two cases which we use with return
    // address signing:
    switch (STI.getPushPopSplitVariation(MF)) {
    case ARMSubtarget::SplitR7:
      // LR, R7, R6, R5, R4, <R12>, R11, R10,  R9,  R8, D15-D8
      CSI.insert(find_if(CSI,
                         [=](const auto &CS) {
                           MCRegister Reg = CS.getReg();
                           return Reg == ARM::R10 || Reg == ARM::R11 ||
                                  Reg == ARM::R8 || Reg == ARM::R9 ||
                                  ARM::DPRRegClass.contains(Reg);
                         }),
                 CalleeSavedInfo(ARM::R12));
      break;
    case ARMSubtarget::SplitR11AAPCSSignRA:
      // With SplitR11AAPCSSignRA, R12 will always be the highest-addressed CSR
      // on the stack.
      CSI.insert(CSI.begin(), CalleeSavedInfo(ARM::R12));
      break;
    case ARMSubtarget::NoSplit:
      assert(!MF.getTarget().Options.DisableFramePointerElim(MF) &&
             "ABI-required frame pointers need a CSR split when signing return "
             "address.");
      CSI.insert(find_if(CSI,
                         [=](const auto &CS) {
                           MCRegister Reg = CS.getReg();
                           return Reg != ARM::LR;
                         }),
                 CalleeSavedInfo(ARM::R12));
      break;
    default:
      llvm_unreachable("Unexpected CSR split with return address signing");
    }
  }

  return false;
}

const TargetFrameLowering::SpillSlot *
ARMFrameLowering::getCalleeSavedSpillSlots(unsigned &NumEntries) const {
  static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
  NumEntries = std::size(FixedSpillOffsets);
  return FixedSpillOffsets;
}

MachineBasicBlock::iterator ARMFrameLowering::eliminateCallFramePseudoInstr(
    MachineFunction &MF, MachineBasicBlock &MBB,
    MachineBasicBlock::iterator I) const {
  const ARMBaseInstrInfo &TII =
      *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  bool isARM = !AFI->isThumbFunction();
  DebugLoc dl = I->getDebugLoc();
  unsigned Opc = I->getOpcode();
  bool IsDestroy = Opc == TII.getCallFrameDestroyOpcode();
  unsigned CalleePopAmount = IsDestroy ? I->getOperand(1).getImm() : 0;

  assert(!AFI->isThumb1OnlyFunction() &&
         "This eliminateCallFramePseudoInstr does not support Thumb1!");

  int PIdx = I->findFirstPredOperandIdx();
  ARMCC::CondCodes Pred = (PIdx == -1)
                              ? ARMCC::AL
                              : (ARMCC::CondCodes)I->getOperand(PIdx).getImm();
  unsigned PredReg = TII.getFramePred(*I);

  if (!hasReservedCallFrame(MF)) {
    // Bail early if the callee is expected to do the adjustment.
    if (IsDestroy && CalleePopAmount != -1U)
      return MBB.erase(I);

    // If we have alloca, convert as follows:
    // ADJCALLSTACKDOWN -> sub, sp, sp, amount
    // ADJCALLSTACKUP   -> add, sp, sp, amount
    unsigned Amount = TII.getFrameSize(*I);
    if (Amount != 0) {
      // We need to keep the stack aligned properly.  To do this, we round the
      // amount of space needed for the outgoing arguments up to the next
      // alignment boundary.
      Amount = alignSPAdjust(Amount);

      if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
        emitSPUpdate(isARM, MBB, I, dl, TII, -Amount, MachineInstr::NoFlags,
                     Pred, PredReg);
      } else {
        assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
        emitSPUpdate(isARM, MBB, I, dl, TII, Amount, MachineInstr::NoFlags,
                     Pred, PredReg);
      }
    }
  } else if (CalleePopAmount != -1U) {
    // If the calling convention demands that the callee pops arguments from the
    // stack, we want to add it back if we have a reserved call frame.
    emitSPUpdate(isARM, MBB, I, dl, TII, -CalleePopAmount,
                 MachineInstr::NoFlags, Pred, PredReg);
  }
  return MBB.erase(I);
}

/// Get the minimum constant for ARM that is greater than or equal to the
/// argument. In ARM, constants can have any value that can be produced by
/// rotating an 8-bit value to the right by an even number of bits within a
/// 32-bit word.
static uint32_t alignToARMConstant(uint32_t Value) {
  unsigned Shifted = 0;

  if (Value == 0)
      return 0;

  while (!(Value & 0xC0000000)) {
      Value = Value << 2;
      Shifted += 2;
  }

  bool Carry = (Value & 0x00FFFFFF);
  Value = ((Value & 0xFF000000) >> 24) + Carry;

  if (Value & 0x0000100)
      Value = Value & 0x000001FC;

  if (Shifted > 24)
      Value = Value >> (Shifted - 24);
  else
      Value = Value << (24 - Shifted);

  return Value;
}

// The stack limit in the TCB is set to this many bytes above the actual
// stack limit.
static const uint64_t kSplitStackAvailable = 256;

// Adjust the function prologue to enable split stacks. This currently only
// supports android and linux.
//
// The ABI of the segmented stack prologue is a little arbitrarily chosen, but
// must be well defined in order to allow for consistent implementations of the
// __morestack helper function. The ABI is also not a normal ABI in that it
// doesn't follow the normal calling conventions because this allows the
// prologue of each function to be optimized further.
//
// Currently, the ABI looks like (when calling __morestack)
//
//  * r4 holds the minimum stack size requested for this function call
//  * r5 holds the stack size of the arguments to the function
//  * the beginning of the function is 3 instructions after the call to
//    __morestack
//
// Implementations of __morestack should use r4 to allocate a new stack, r5 to
// place the arguments on to the new stack, and the 3-instruction knowledge to
// jump directly to the body of the function when working on the new stack.
//
// An old (and possibly no longer compatible) implementation of __morestack for
// ARM can be found at [1].
//
// [1] - https://github.com/mozilla/rust/blob/86efd9/src/rt/arch/arm/morestack.S
void ARMFrameLowering::adjustForSegmentedStacks(
    MachineFunction &MF, MachineBasicBlock &PrologueMBB) const {
  unsigned Opcode;
  const ARMSubtarget *ST = &MF.getSubtarget<ARMSubtarget>();
  bool Thumb = ST->isThumb();
  bool Thumb2 = ST->isThumb2();

  // Sadly, this currently doesn't support varargs, platforms other than
  // android/linux. Note that thumb1/thumb2 are support for android/linux.
  if (MF.getFunction().isVarArg())
    report_fatal_error("Segmented stacks do not support vararg functions.");
  if (!ST->isTargetAndroid() && !ST->isTargetLinux())
    report_fatal_error("Segmented stacks not supported on this platform.");

  MachineFrameInfo &MFI = MF.getFrameInfo();
  const ARMBaseInstrInfo &TII =
      *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo());
  ARMFunctionInfo *ARMFI = MF.getInfo<ARMFunctionInfo>();
  DebugLoc DL;

  if (!MFI.needsSplitStackProlog())
    return;

  uint64_t StackSize = MFI.getStackSize();

  // Use R4 and R5 as scratch registers.
  // We save R4 and R5 before use and restore them before leaving the function.
  unsigned ScratchReg0 = ARM::R4;
  unsigned ScratchReg1 = ARM::R5;
  unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
  uint64_t AlignedStackSize;

  MachineBasicBlock *PrevStackMBB = MF.CreateMachineBasicBlock();
  MachineBasicBlock *PostStackMBB = MF.CreateMachineBasicBlock();
  MachineBasicBlock *AllocMBB = MF.CreateMachineBasicBlock();
  MachineBasicBlock *GetMBB = MF.CreateMachineBasicBlock();
  MachineBasicBlock *McrMBB = MF.CreateMachineBasicBlock();

  // Grab everything that reaches PrologueMBB to update there liveness as well.
  SmallPtrSet<MachineBasicBlock *, 8> BeforePrologueRegion;
  SmallVector<MachineBasicBlock *, 2> WalkList;
  WalkList.push_back(&PrologueMBB);

  do {
    MachineBasicBlock *CurMBB = WalkList.pop_back_val();
    for (MachineBasicBlock *PredBB : CurMBB->predecessors()) {
      if (BeforePrologueRegion.insert(PredBB).second)
        WalkList.push_back(PredBB);
    }
  } while (!WalkList.empty());

  // The order in that list is important.
  // The blocks will all be inserted before PrologueMBB using that order.
  // Therefore the block that should appear first in the CFG should appear
  // first in the list.
  MachineBasicBlock *AddedBlocks[] = {PrevStackMBB, McrMBB, GetMBB, AllocMBB,
                                      PostStackMBB};

  BeforePrologueRegion.insert_range(AddedBlocks);

  for (const auto &LI : PrologueMBB.liveins()) {
    for (MachineBasicBlock *PredBB : BeforePrologueRegion)
      PredBB->addLiveIn(LI);
  }

  // Remove the newly added blocks from the list, since we know
  // we do not have to do the following updates for them.
  for (MachineBasicBlock *B : AddedBlocks) {
    BeforePrologueRegion.erase(B);
    MF.insert(PrologueMBB.getIterator(), B);
  }

  for (MachineBasicBlock *MBB : BeforePrologueRegion) {
    // Make sure the LiveIns are still sorted and unique.
    MBB->sortUniqueLiveIns();
    // Replace the edges to PrologueMBB by edges to the sequences
    // we are about to add, but only update for immediate predecessors.
    if (MBB->isSuccessor(&PrologueMBB))
      MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
  }

  // The required stack size that is aligned to ARM constant criterion.
  AlignedStackSize = alignToARMConstant(StackSize);

  // When the frame size is less than 256 we just compare the stack
  // boundary directly to the value of the stack pointer, per gcc.
  bool CompareStackPointer = AlignedStackSize < kSplitStackAvailable;

  // We will use two of the callee save registers as scratch registers so we
  // need to save those registers onto the stack.
  // We will use SR0 to hold stack limit and SR1 to hold the stack size
  // requested and arguments for __morestack().
  // SR0: Scratch Register #0
  // SR1: Scratch Register #1
  // push {SR0, SR1}
  if (Thumb) {
    BuildMI(PrevStackMBB, DL, TII.get(ARM::tPUSH))
        .add(predOps(ARMCC::AL))
        .addReg(ScratchReg0)
        .addReg(ScratchReg1);
  } else {
    BuildMI(PrevStackMBB, DL, TII.get(ARM::STMDB_UPD))
        .addReg(ARM::SP, RegState::Define)
        .addReg(ARM::SP)
        .add(predOps(ARMCC::AL))
        .addReg(ScratchReg0)
        .addReg(ScratchReg1);
  }

  // Emit the relevant DWARF information about the change in stack pointer as
  // well as where to find both r4 and r5 (the callee-save registers)
  if (!MF.getTarget().getMCAsmInfo().usesWindowsCFI()) {
    CFIInstBuilder CFIBuilder(PrevStackMBB, MachineInstr::NoFlags);
    CFIBuilder.buildDefCFAOffset(8);
    CFIBuilder.buildOffset(ScratchReg1, -4);
    CFIBuilder.buildOffset(ScratchReg0, -8);
  }

  // mov SR1, sp
  if (Thumb) {
    BuildMI(McrMBB, DL, TII.get(ARM::tMOVr), ScratchReg1)
        .addReg(ARM::SP)
        .add(predOps(ARMCC::AL));
  } else if (CompareStackPointer) {
    BuildMI(McrMBB, DL, TII.get(ARM::MOVr), ScratchReg1)
        .addReg(ARM::SP)
        .add(predOps(ARMCC::AL))
        .add(condCodeOp());
  }

  // sub SR1, sp, #StackSize
  if (!CompareStackPointer && Thumb) {
    if (AlignedStackSize < 256) {
      BuildMI(McrMBB, DL, TII.get(ARM::tSUBi8), ScratchReg1)
          .add(condCodeOp())
          .addReg(ScratchReg1)
          .addImm(AlignedStackSize)
          .add(predOps(ARMCC::AL));
    } else {
      if (Thumb2 || ST->genExecuteOnly()) {
        BuildMI(McrMBB, DL, TII.get(MovOp), ScratchReg0)
            .addImm(AlignedStackSize);
      } else {
        auto MBBI = McrMBB->end();
        auto RegInfo = STI.getRegisterInfo();
        RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0,
                                   AlignedStackSize);
      }
      BuildMI(McrMBB, DL, TII.get(ARM::tSUBrr), ScratchReg1)
          .add(condCodeOp())
          .addReg(ScratchReg1)
          .addReg(ScratchReg0)
          .add(predOps(ARMCC::AL));
    }
  } else if (!CompareStackPointer) {
    if (AlignedStackSize < 256) {
      BuildMI(McrMBB, DL, TII.get(ARM::SUBri), ScratchReg1)
          .addReg(ARM::SP)
          .addImm(AlignedStackSize)
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
    } else {
      auto MBBI = McrMBB->end();
      auto RegInfo = STI.getRegisterInfo();
      RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0,
                                 AlignedStackSize);
      BuildMI(McrMBB, DL, TII.get(ARM::SUBrr), ScratchReg1)
          .addReg(ARM::SP)
          .addReg(ScratchReg0)
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
    }
  }

  if (Thumb && ST->isThumb1Only()) {
    if (ST->genExecuteOnly()) {
      BuildMI(GetMBB, DL, TII.get(MovOp), ScratchReg0)
          .addExternalSymbol("__STACK_LIMIT");
    } else {
      unsigned PCLabelId = ARMFI->createPICLabelUId();
      ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol::Create(
          MF.getFunction().getContext(), "__STACK_LIMIT", PCLabelId, 0);
      MachineConstantPool *MCP = MF.getConstantPool();
      unsigned CPI = MCP->getConstantPoolIndex(NewCPV, Align(4));

      // ldr SR0, [pc, offset(STACK_LIMIT)]
      BuildMI(GetMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0)
          .addConstantPoolIndex(CPI)
          .add(predOps(ARMCC::AL));
    }

    // ldr SR0, [SR0]
    BuildMI(GetMBB, DL, TII.get(ARM::tLDRi), ScratchReg0)
        .addReg(ScratchReg0)
        .addImm(0)
        .add(predOps(ARMCC::AL));
  } else {
    // Get TLS base address from the coprocessor
    // mrc p15, #0, SR0, c13, c0, #3
    BuildMI(McrMBB, DL, TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
            ScratchReg0)
        .addImm(15)
        .addImm(0)
        .addImm(13)
        .addImm(0)
        .addImm(3)
        .add(predOps(ARMCC::AL));

    // Use the last tls slot on android and a private field of the TCP on linux.
    assert(ST->isTargetAndroid() || ST->isTargetLinux());
    unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;

    // Get the stack limit from the right offset
    // ldr SR0, [sr0, #4 * TlsOffset]
    BuildMI(GetMBB, DL, TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
            ScratchReg0)
        .addReg(ScratchReg0)
        .addImm(4 * TlsOffset)
        .add(predOps(ARMCC::AL));
  }

  // Compare stack limit with stack size requested.
  // cmp SR0, SR1
  Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
  BuildMI(GetMBB, DL, TII.get(Opcode))
      .addReg(ScratchReg0)
      .addReg(ScratchReg1)
      .add(predOps(ARMCC::AL));

  // This jump is taken if StackLimit <= SP - stack required.
  Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
  BuildMI(GetMBB, DL, TII.get(Opcode))
      .addMBB(PostStackMBB)
      .addImm(ARMCC::LS)
      .addReg(ARM::CPSR);

  // Calling __morestack(StackSize, Size of stack arguments).
  // __morestack knows that the stack size requested is in SR0(r4)
  // and amount size of stack arguments is in SR1(r5).

  // Pass first argument for the __morestack by Scratch Register #0.
  //   The amount size of stack required
  if (Thumb) {
    if (AlignedStackSize < 256) {
      BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg0)
          .add(condCodeOp())
          .addImm(AlignedStackSize)
          .add(predOps(ARMCC::AL));
    } else {
      if (Thumb2 || ST->genExecuteOnly()) {
        BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg0)
            .addImm(AlignedStackSize);
      } else {
        auto MBBI = AllocMBB->end();
        auto RegInfo = STI.getRegisterInfo();
        RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0,
                                   AlignedStackSize);
      }
    }
  } else {
    if (AlignedStackSize < 256) {
      BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg0)
          .addImm(AlignedStackSize)
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
    } else {
      auto MBBI = AllocMBB->end();
      auto RegInfo = STI.getRegisterInfo();
      RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0,
                                 AlignedStackSize);
    }
  }

  // Pass second argument for the __morestack by Scratch Register #1.
  //   The amount size of stack consumed to save function arguments.
  if (Thumb) {
    if (ARMFI->getArgumentStackSize() < 256) {
      BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg1)
          .add(condCodeOp())
          .addImm(alignToARMConstant(ARMFI->getArgumentStackSize()))
          .add(predOps(ARMCC::AL));
    } else {
      if (Thumb2 || ST->genExecuteOnly()) {
        BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg1)
            .addImm(alignToARMConstant(ARMFI->getArgumentStackSize()));
      } else {
        auto MBBI = AllocMBB->end();
        auto RegInfo = STI.getRegisterInfo();
        RegInfo->emitLoadConstPool(
            *AllocMBB, MBBI, DL, ScratchReg1, 0,
            alignToARMConstant(ARMFI->getArgumentStackSize()));
      }
    }
  } else {
    if (alignToARMConstant(ARMFI->getArgumentStackSize()) < 256) {
      BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg1)
          .addImm(alignToARMConstant(ARMFI->getArgumentStackSize()))
          .add(predOps(ARMCC::AL))
          .add(condCodeOp());
    } else {
      auto MBBI = AllocMBB->end();
      auto RegInfo = STI.getRegisterInfo();
      RegInfo->emitLoadConstPool(
          *AllocMBB, MBBI, DL, ScratchReg1, 0,
          alignToARMConstant(ARMFI->getArgumentStackSize()));
    }
  }

  // push {lr} - Save return address of this function.
  if (Thumb) {
    BuildMI(AllocMBB, DL, TII.get(ARM::tPUSH))
        .add(predOps(ARMCC::AL))
        .addReg(ARM::LR);
  } else {
    BuildMI(AllocMBB, DL, TII.get(ARM::STMDB_UPD))
        .addReg(ARM::SP, RegState::Define)
        .addReg(ARM::SP)
        .add(predOps(ARMCC::AL))
        .addReg(ARM::LR);
  }

  // Emit the DWARF info about the change in stack as well as where to find the
  // previous link register
  if (!MF.getTarget().getMCAsmInfo().usesWindowsCFI()) {
    CFIInstBuilder CFIBuilder(AllocMBB, MachineInstr::NoFlags);
    CFIBuilder.buildDefCFAOffset(12);
    CFIBuilder.buildOffset(ARM::LR, -12);
  }

  // Call __morestack().
  if (Thumb) {
    BuildMI(AllocMBB, DL, TII.get(ARM::tBL))
        .add(predOps(ARMCC::AL))
        .addExternalSymbol("__morestack");
  } else {
    BuildMI(AllocMBB, DL, TII.get(ARM::BL))
        .addExternalSymbol("__morestack");
  }

  // pop {lr} - Restore return address of this original function.
  if (Thumb) {
    if (ST->isThumb1Only()) {
      BuildMI(AllocMBB, DL, TII.get(ARM::tPOP))
          .add(predOps(ARMCC::AL))
          .addReg(ScratchReg0);
      BuildMI(AllocMBB, DL, TII.get(ARM::tMOVr), ARM::LR)
          .addReg(ScratchReg0)
          .add(predOps(ARMCC::AL));
    } else {
      BuildMI(AllocMBB, DL, TII.get(ARM::t2LDR_POST))
          .addReg(ARM::LR, RegState::Define)
          .addReg(ARM::SP, RegState::Define)
          .addReg(ARM::SP)
          .addImm(4)
          .add(predOps(ARMCC::AL));
    }
  } else {
    BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD))
        .addReg(ARM::SP, RegState::Define)
        .addReg(ARM::SP)
        .add(predOps(ARMCC::AL))
        .addReg(ARM::LR);
  }

  // Restore SR0 and SR1 in case of __morestack() was called.
  // __morestack() will skip PostStackMBB block so we need to restore
  // scratch registers from here.
  // pop {SR0, SR1}
  if (Thumb) {
    BuildMI(AllocMBB, DL, TII.get(ARM::tPOP))
        .add(predOps(ARMCC::AL))
        .addReg(ScratchReg0)
        .addReg(ScratchReg1);
  } else {
    BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD))
        .addReg(ARM::SP, RegState::Define)
        .addReg(ARM::SP)
        .add(predOps(ARMCC::AL))
        .addReg(ScratchReg0)
        .addReg(ScratchReg1);
  }

  // Update the CFA offset now that we've popped
  if (!MF.getTarget().getMCAsmInfo().usesWindowsCFI())
    CFIInstBuilder(AllocMBB, MachineInstr::NoFlags).buildDefCFAOffset(0);

  // Return from this function.
  BuildMI(AllocMBB, DL, TII.get(ST->getReturnOpcode())).add(predOps(ARMCC::AL));

  // Restore SR0 and SR1 in case of __morestack() was not called.
  // pop {SR0, SR1}
  if (Thumb) {
    BuildMI(PostStackMBB, DL, TII.get(ARM::tPOP))
        .add(predOps(ARMCC::AL))
        .addReg(ScratchReg0)
        .addReg(ScratchReg1);
  } else {
    BuildMI(PostStackMBB, DL, TII.get(ARM::LDMIA_UPD))
        .addReg(ARM::SP, RegState::Define)
        .addReg(ARM::SP)
        .add(predOps(ARMCC::AL))
        .addReg(ScratchReg0)
        .addReg(ScratchReg1);
  }

  // Update the CFA offset now that we've popped
  if (!MF.getTarget().getMCAsmInfo().usesWindowsCFI()) {
    CFIInstBuilder CFIBuilder(PostStackMBB, MachineInstr::NoFlags);
    CFIBuilder.buildDefCFAOffset(0);

    // Tell debuggers that r4 and r5 are now the same as they were in the
    // previous function, that they're the "Same Value".
    CFIBuilder.buildSameValue(ScratchReg0);
    CFIBuilder.buildSameValue(ScratchReg1);
  }

  // Organizing MBB lists
  PostStackMBB->addSuccessor(&PrologueMBB);

  AllocMBB->addSuccessor(PostStackMBB);

  GetMBB->addSuccessor(PostStackMBB);
  GetMBB->addSuccessor(AllocMBB);

  McrMBB->addSuccessor(GetMBB);

  PrevStackMBB->addSuccessor(McrMBB);

#ifdef EXPENSIVE_CHECKS
  MF.verify();
#endif
}
