<commit_before>//===- ARMBaseRegisterInfo.cpp - ARM Register Information -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the base ARM implementation of TargetRegisterInfo class.
//
//===----------------------------------------------------------------------===//

#include "ARM.h"
#include "ARMAddressingModes.h"
#include "ARMBaseInstrInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMInstrInfo.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMSubtarget.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/LLVMContext.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"

namespace llvm {
cl::opt<bool>
ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(true),
          cl::desc("Reuse repeated frame index values"));
}

using namespace llvm;

unsigned ARMBaseRegisterInfo::getRegisterNumbering(unsigned RegEnum,
                                                   bool *isSPVFP) {
  if (isSPVFP)
    *isSPVFP = false;

  using namespace ARM;
  switch (RegEnum) {
  default:
    llvm_unreachable("Unknown ARM register!");
  case R0:  case D0:  case Q0:  return 0;
  case R1:  case D1:  case Q1:  return 1;
  case R2:  case D2:  case Q2:  return 2;
  case R3:  case D3:  case Q3:  return 3;
  case R4:  case D4:  case Q4:  return 4;
  case R5:  case D5:  case Q5:  return 5;
  case R6:  case D6:  case Q6:  return 6;
  case R7:  case D7:  case Q7:  return 7;
  case R8:  case D8:  case Q8:  return 8;
  case R9:  case D9:  case Q9:  return 9;
  case R10: case D10: case Q10: return 10;
  case R11: case D11: case Q11: return 11;
  case R12: case D12: case Q12: return 12;
  case SP:  case D13: case Q13: return 13;
  case LR:  case D14: case Q14: return 14;
  case PC:  case D15: case Q15: return 15;

  case D16: return 16;
  case D17: return 17;
  case D18: return 18;
  case D19: return 19;
  case D20: return 20;
  case D21: return 21;
  case D22: return 22;
  case D23: return 23;
  case D24: return 24;
  case D25: return 25;
  case D26: return 26;
  case D27: return 27;
  case D28: return 28;
  case D29: return 29;
  case D30: return 30;
  case D31: return 31;

  case S0: case S1: case S2: case S3:
  case S4: case S5: case S6: case S7:
  case S8: case S9: case S10: case S11:
  case S12: case S13: case S14: case S15:
  case S16: case S17: case S18: case S19:
  case S20: case S21: case S22: case S23:
  case S24: case S25: case S26: case S27:
  case S28: case S29: case S30: case S31: {
    if (isSPVFP)
      *isSPVFP = true;
    switch (RegEnum) {
    default: return 0; // Avoid compile time warning.
    case S0: return 0;
    case S1: return 1;
    case S2: return 2;
    case S3: return 3;
    case S4: return 4;
    case S5: return 5;
    case S6: return 6;
    case S7: return 7;
    case S8: return 8;
    case S9: return 9;
    case S10: return 10;
    case S11: return 11;
    case S12: return 12;
    case S13: return 13;
    case S14: return 14;
    case S15: return 15;
    case S16: return 16;
    case S17: return 17;
    case S18: return 18;
    case S19: return 19;
    case S20: return 20;
    case S21: return 21;
    case S22: return 22;
    case S23: return 23;
    case S24: return 24;
    case S25: return 25;
    case S26: return 26;
    case S27: return 27;
    case S28: return 28;
    case S29: return 29;
    case S30: return 30;
    case S31: return 31;
    }
  }
  }
}

ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii,
                                         const ARMSubtarget &sti)
  : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
    TII(tii), STI(sti),
    FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11) {
}

const unsigned*
ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
  static const unsigned CalleeSavedRegs[] = {
    ARM::LR, ARM::R11, ARM::R10, ARM::R9, ARM::R8,
    ARM::R7, ARM::R6,  ARM::R5,  ARM::R4,

    ARM::D15, ARM::D14, ARM::D13, ARM::D12,
    ARM::D11, ARM::D10, ARM::D9,  ARM::D8,
    0
  };

  static const unsigned DarwinCalleeSavedRegs[] = {
    // Darwin ABI deviates from ARM standard ABI. R9 is not a callee-saved
    // register.
    ARM::LR,  ARM::R7,  ARM::R6, ARM::R5, ARM::R4,
    ARM::R11, ARM::R10, ARM::R8,

    ARM::D15, ARM::D14, ARM::D13, ARM::D12,
    ARM::D11, ARM::D10, ARM::D9,  ARM::D8,
    0
  };
  return STI.isTargetDarwin() ? DarwinCalleeSavedRegs : CalleeSavedRegs;
}

BitVector ARMBaseRegisterInfo::
getReservedRegs(const MachineFunction &MF) const {
  // FIXME: avoid re-calculating this everytime.
  BitVector Reserved(getNumRegs());
  Reserved.set(ARM::SP);
  Reserved.set(ARM::PC);
  Reserved.set(ARM::FPSCR);
  if (STI.isTargetDarwin() || hasFP(MF))
    Reserved.set(FramePtr);
  // Some targets reserve R9.
  if (STI.isR9Reserved())
    Reserved.set(ARM::R9);
  return Reserved;
}

bool ARMBaseRegisterInfo::isReservedReg(const MachineFunction &MF,
                                        unsigned Reg) const {
  switch (Reg) {
  default: break;
  case ARM::SP:
  case ARM::PC:
    return true;
  case ARM::R7:
  case ARM::R11:
    if (FramePtr == Reg && (STI.isTargetDarwin() || hasFP(MF)))
      return true;
    break;
  case ARM::R9:
    return STI.isR9Reserved();
  }

  return false;
}

const TargetRegisterClass *
ARMBaseRegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
                                              const TargetRegisterClass *B,
                                              unsigned SubIdx) const {
  switch (SubIdx) {
  default: return 0;
  case ARM::ssub_0:
  case ARM::ssub_1:
  case ARM::ssub_2:
  case ARM::ssub_3: {
    // S sub-registers.
    if (A->getSize() == 8) {
      if (B == &ARM::SPR_8RegClass)
        return &ARM::DPR_8RegClass;
      assert(B == &ARM::SPRRegClass && "Expecting SPR register class!");
      if (A == &ARM::DPR_8RegClass)
        return A;
      return &ARM::DPR_VFP2RegClass;
    }

    if (A->getSize() == 16) {
      if (B == &ARM::SPR_8RegClass)
        return &ARM::QPR_8RegClass;
      return &ARM::QPR_VFP2RegClass;
    }

    if (A->getSize() == 32) {
      if (B == &ARM::SPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return &ARM::QQPR_VFP2RegClass;
    }

    assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
    return 0;  // Do not allow coalescing!
  }
  case ARM::dsub_0:
  case ARM::dsub_1:
  case ARM::dsub_2:
  case ARM::dsub_3: {
    // D sub-registers.
    if (A->getSize() == 16) {
      if (B == &ARM::DPR_VFP2RegClass)
        return &ARM::QPR_VFP2RegClass;
      if (B == &ARM::DPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return A;
    }

    if (A->getSize() == 32) {
      if (B == &ARM::DPR_VFP2RegClass)
        return &ARM::QQPR_VFP2RegClass;
      if (B == &ARM::DPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return A;
    }

    assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
    if (B != &ARM::DPRRegClass)
      return 0;  // Do not allow coalescing!
    return A;
  }
  case ARM::dsub_4:
  case ARM::dsub_5:
  case ARM::dsub_6:
  case ARM::dsub_7: {
    // D sub-registers of QQQQ registers.
    if (A->getSize() == 64 && B == &ARM::DPRRegClass)
      return A;
    return 0;  // Do not allow coalescing!
  }

  case ARM::qsub_0:
  case ARM::qsub_1: {
    // Q sub-registers.
    if (A->getSize() == 32) {
      if (B == &ARM::QPR_VFP2RegClass)
        return &ARM::QQPR_VFP2RegClass;
      if (B == &ARM::QPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return A;
    }

    assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
    if (B == &ARM::QPRRegClass)
      return A;
    return 0;  // Do not allow coalescing!
  }
  case ARM::qsub_2:
  case ARM::qsub_3: {
    // Q sub-registers of QQQQ registers.
    if (A->getSize() == 64 && B == &ARM::QPRRegClass)
      return A;
    return 0;  // Do not allow coalescing!
  }
  }
  return 0;
}

bool
ARMBaseRegisterInfo::canCombineSubRegIndices(const TargetRegisterClass *RC,
                                          SmallVectorImpl<unsigned> &SubIndices,
                                          unsigned &NewSubIdx) const {

  unsigned Size = RC->getSize() * 8;
  if (Size < 6)
    return 0;

  NewSubIdx = 0;  // Whole register.
  unsigned NumRegs = SubIndices.size();
  if (NumRegs == 8) {
    // 8 D registers -> 1 QQQQ register.
    return (Size == 512 &&
            SubIndices[0] == ARM::dsub_0 &&
            SubIndices[1] == ARM::dsub_1 &&
            SubIndices[2] == ARM::dsub_2 &&
            SubIndices[3] == ARM::dsub_3 &&
            SubIndices[4] == ARM::dsub_4 &&
            SubIndices[5] == ARM::dsub_5 &&
            SubIndices[6] == ARM::dsub_6 &&
            SubIndices[7] == ARM::dsub_7);
  } else if (NumRegs == 4) {
    if (SubIndices[0] == ARM::qsub_0) {
      // 4 Q registers -> 1 QQQQ register.
      return (Size == 512 &&
              SubIndices[1] == ARM::qsub_1 &&
              SubIndices[2] == ARM::qsub_2 &&
              SubIndices[3] == ARM::qsub_3);
    } else if (SubIndices[0] == ARM::dsub_0) {
      // 4 D registers -> 1 QQ register.
      if (Size >= 256 &&
          SubIndices[1] == ARM::dsub_1 &&
          SubIndices[2] == ARM::dsub_2 &&
          SubIndices[3] == ARM::dsub_3) {
        if (Size == 512)
          NewSubIdx = ARM::qqsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_4) {
      // 4 D registers -> 1 QQ register (2nd).
      if (Size == 512 &&
          SubIndices[1] == ARM::dsub_5 &&
          SubIndices[2] == ARM::dsub_6 &&
          SubIndices[3] == ARM::dsub_7) {
        NewSubIdx = ARM::qqsub_1;
        return true;
      }
    } else if (SubIndices[0] == ARM::ssub_0) {
      // 4 S registers -> 1 Q register.
      if (Size >= 128 &&
          SubIndices[1] == ARM::ssub_1 &&
          SubIndices[2] == ARM::ssub_2 &&
          SubIndices[3] == ARM::ssub_3) {
        if (Size >= 256)
          NewSubIdx = ARM::qsub_0;
        return true;
      }
    }
  } else if (NumRegs == 2) {
    if (SubIndices[0] == ARM::qsub_0) {
      // 2 Q registers -> 1 QQ register.
      if (Size >= 256 && SubIndices[1] == ARM::qsub_1) {
        if (Size == 512)
          NewSubIdx = ARM::qqsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::qsub_2) {
      // 2 Q registers -> 1 QQ register (2nd).
      if (Size == 512 && SubIndices[1] == ARM::qsub_3) {
        NewSubIdx = ARM::qqsub_1;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_0) {
      // 2 D registers -> 1 Q register.
      if (Size >= 128 && SubIndices[1] == ARM::dsub_1) {
        if (Size >= 256)
          NewSubIdx = ARM::qsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_2) {
      // 2 D registers -> 1 Q register (2nd).
      if (Size >= 256 && SubIndices[1] == ARM::dsub_3) {
        NewSubIdx = ARM::qsub_1;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_4) {
      // 2 D registers -> 1 Q register (3rd).
      if (Size == 512 && SubIndices[1] == ARM::dsub_5) {
        NewSubIdx = ARM::qsub_2;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_6) {
      // 2 D registers -> 1 Q register (3rd).
      if (Size == 512 && SubIndices[1] == ARM::dsub_7) {
        NewSubIdx = ARM::qsub_3;
        return true;
      }
    } else if (SubIndices[0] == ARM::ssub_0) {
      // 2 S registers -> 1 D register.
      if (SubIndices[1] == ARM::ssub_1) {
        if (Size >= 128)
          NewSubIdx = ARM::dsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::ssub_2) {
      // 2 S registers -> 1 D register (2nd).
      if (Size >= 128 && SubIndices[1] == ARM::ssub_3) {
        NewSubIdx = ARM::dsub_1;
        return true;
      }
    }
  }
  return false;
}


const TargetRegisterClass *
ARMBaseRegisterInfo::getPointerRegClass(unsigned Kind) const {
  return ARM::GPRRegisterClass;
}

/// getAllocationOrder - Returns the register allocation order for a specified
/// register class in the form of a pair of TargetRegisterClass iterators.
std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
                                        unsigned HintType, unsigned HintReg,
                                        const MachineFunction &MF) const {
  // Alternative register allocation orders when favoring even / odd registers
  // of register pairs.

  // No FP, R9 is available.
  static const unsigned GPREven1[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7,
    ARM::R9, ARM::R11
  };
  static const unsigned GPROdd1[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R9, ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
    ARM::R8, ARM::R10
  };

  // FP is R7, R9 is available.
  static const unsigned GPREven2[] = {
    ARM::R0, ARM::R2, ARM::R4,          ARM::R8, ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6,
    ARM::R9, ARM::R11
  };
  static const unsigned GPROdd2[] = {
    ARM::R1, ARM::R3, ARM::R5,          ARM::R9, ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
    ARM::R8, ARM::R10
  };

  // FP is R11, R9 is available.
  static const unsigned GPREven3[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8,
    ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7,
    ARM::R9
  };
  static const unsigned GPROdd3[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R6, ARM::R9,
    ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R7,
    ARM::R8
  };

  // No FP, R9 is not available.
  static const unsigned GPREven4[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6,          ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8,
    ARM::R11
  };
  static const unsigned GPROdd4[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R7,          ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
    ARM::R10
  };

  // FP is R7, R9 is not available.
  static const unsigned GPREven5[] = {
    ARM::R0, ARM::R2, ARM::R4,                   ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, ARM::R8,
    ARM::R11
  };
  static const unsigned GPROdd5[] = {
    ARM::R1, ARM::R3, ARM::R5,                   ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
    ARM::R10
  };

  // FP is R11, R9 is not available.
  static const unsigned GPREven6[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6,
    ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8
  };
  static const unsigned GPROdd6[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R7,
    ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8
  };


  if (HintType == ARMRI::RegPairEven) {
    if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0)
      // It's no longer possible to fulfill this hint. Return the default
      // allocation order.
      return std::make_pair(RC->allocation_order_begin(MF),
                            RC->allocation_order_end(MF));

    if (!STI.isTargetDarwin() && !hasFP(MF)) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPREven1,
                              GPREven1 + (sizeof(GPREven1)/sizeof(unsigned)));
      else
        return std::make_pair(GPREven4,
                              GPREven4 + (sizeof(GPREven4)/sizeof(unsigned)));
    } else if (FramePtr == ARM::R7) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPREven2,
                              GPREven2 + (sizeof(GPREven2)/sizeof(unsigned)));
      else
        return std::make_pair(GPREven5,
                              GPREven5 + (sizeof(GPREven5)/sizeof(unsigned)));
    } else { // FramePtr == ARM::R11
      if (!STI.isR9Reserved())
        return std::make_pair(GPREven3,
                              GPREven3 + (sizeof(GPREven3)/sizeof(unsigned)));
      else
        return std::make_pair(GPREven6,
                              GPREven6 + (sizeof(GPREven6)/sizeof(unsigned)));
    }
  } else if (HintType == ARMRI::RegPairOdd) {
    if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0)
      // It's no longer possible to fulfill this hint. Return the default
      // allocation order.
      return std::make_pair(RC->allocation_order_begin(MF),
                            RC->allocation_order_end(MF));

    if (!STI.isTargetDarwin() && !hasFP(MF)) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPROdd1,
                              GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned)));
      else
        return std::make_pair(GPROdd4,
                              GPROdd4 + (sizeof(GPROdd4)/sizeof(unsigned)));
    } else if (FramePtr == ARM::R7) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPROdd2,
                              GPROdd2 + (sizeof(GPROdd2)/sizeof(unsigned)));
      else
        return std::make_pair(GPROdd5,
                              GPROdd5 + (sizeof(GPROdd5)/sizeof(unsigned)));
    } else { // FramePtr == ARM::R11
      if (!STI.isR9Reserved())
        return std::make_pair(GPROdd3,
                              GPROdd3 + (sizeof(GPROdd3)/sizeof(unsigned)));
      else
        return std::make_pair(GPROdd6,
                              GPROdd6 + (sizeof(GPROdd6)/sizeof(unsigned)));
    }
  }
  return std::make_pair(RC->allocation_order_begin(MF),
                        RC->allocation_order_end(MF));
}

/// ResolveRegAllocHint - Resolves the specified register allocation hint
/// to a physical register. Returns the physical register if it is successful.
unsigned
ARMBaseRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg,
                                         const MachineFunction &MF) const {
  if (Reg == 0 || !isPhysicalRegister(Reg))
    return 0;
  if (Type == 0)
    return Reg;
  else if (Type == (unsigned)ARMRI::RegPairOdd)
    // Odd register.
    return getRegisterPairOdd(Reg, MF);
  else if (Type == (unsigned)ARMRI::RegPairEven)
    // Even register.
    return getRegisterPairEven(Reg, MF);
  return 0;
}

void
ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
                                        MachineFunction &MF) const {
  MachineRegisterInfo *MRI = &MF.getRegInfo();
  std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg);
  if ((Hint.first == (unsigned)ARMRI::RegPairOdd ||
       Hint.first == (unsigned)ARMRI::RegPairEven) &&
      Hint.second && TargetRegisterInfo::isVirtualRegister(Hint.second)) {
    // If 'Reg' is one of the even / odd register pair and it's now changed
    // (e.g. coalesced) into a different register. The other register of the
    // pair allocation hint must be updated to reflect the relationship
    // change.
    unsigned OtherReg = Hint.second;
    Hint = MRI->getRegAllocationHint(OtherReg);
    if (Hint.second == Reg)
      // Make sure the pair has not already divorced.
      MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg);
  }
}

/// hasFP - 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 ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  return ((DisableFramePointerElim(MF) && MFI->adjustsStack())||
          needsStackRealignment(MF) ||
          MFI->hasVarSizedObjects() ||
          MFI->isFrameAddressTaken());
}

bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  return (RealignStack &&
          !AFI->isThumb1OnlyFunction() &&
          !MFI->hasVarSizedObjects());
}

bool ARMBaseRegisterInfo::
needsStackRealignment(const MachineFunction &MF) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();<commit_msg>ARMBaseRegisterInfo::hasFP() has been broken for a while now. :-( This will always be false before PEI: (DisableFramePointerElim(MF) && MFI->adjustsStack()) Which means it's going to make r11 available as a general purpose register even if -disable-fp-elim is specified. It's working on Darwin only because r7 is always reserved. But it's obviously broken for other targets.<commit_after>//===- ARMBaseRegisterInfo.cpp - ARM Register Information -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the base ARM implementation of TargetRegisterInfo class.
//
//===----------------------------------------------------------------------===//

#include "ARM.h"
#include "ARMAddressingModes.h"
#include "ARMBaseInstrInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMInstrInfo.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMSubtarget.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/LLVMContext.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"

namespace llvm {
cl::opt<bool>
ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(true),
          cl::desc("Reuse repeated frame index values"));
}

using namespace llvm;

unsigned ARMBaseRegisterInfo::getRegisterNumbering(unsigned RegEnum,
                                                   bool *isSPVFP) {
  if (isSPVFP)
    *isSPVFP = false;

  using namespace ARM;
  switch (RegEnum) {
  default:
    llvm_unreachable("Unknown ARM register!");
  case R0:  case D0:  case Q0:  return 0;
  case R1:  case D1:  case Q1:  return 1;
  case R2:  case D2:  case Q2:  return 2;
  case R3:  case D3:  case Q3:  return 3;
  case R4:  case D4:  case Q4:  return 4;
  case R5:  case D5:  case Q5:  return 5;
  case R6:  case D6:  case Q6:  return 6;
  case R7:  case D7:  case Q7:  return 7;
  case R8:  case D8:  case Q8:  return 8;
  case R9:  case D9:  case Q9:  return 9;
  case R10: case D10: case Q10: return 10;
  case R11: case D11: case Q11: return 11;
  case R12: case D12: case Q12: return 12;
  case SP:  case D13: case Q13: return 13;
  case LR:  case D14: case Q14: return 14;
  case PC:  case D15: case Q15: return 15;

  case D16: return 16;
  case D17: return 17;
  case D18: return 18;
  case D19: return 19;
  case D20: return 20;
  case D21: return 21;
  case D22: return 22;
  case D23: return 23;
  case D24: return 24;
  case D25: return 25;
  case D26: return 26;
  case D27: return 27;
  case D28: return 28;
  case D29: return 29;
  case D30: return 30;
  case D31: return 31;

  case S0: case S1: case S2: case S3:
  case S4: case S5: case S6: case S7:
  case S8: case S9: case S10: case S11:
  case S12: case S13: case S14: case S15:
  case S16: case S17: case S18: case S19:
  case S20: case S21: case S22: case S23:
  case S24: case S25: case S26: case S27:
  case S28: case S29: case S30: case S31: {
    if (isSPVFP)
      *isSPVFP = true;
    switch (RegEnum) {
    default: return 0; // Avoid compile time warning.
    case S0: return 0;
    case S1: return 1;
    case S2: return 2;
    case S3: return 3;
    case S4: return 4;
    case S5: return 5;
    case S6: return 6;
    case S7: return 7;
    case S8: return 8;
    case S9: return 9;
    case S10: return 10;
    case S11: return 11;
    case S12: return 12;
    case S13: return 13;
    case S14: return 14;
    case S15: return 15;
    case S16: return 16;
    case S17: return 17;
    case S18: return 18;
    case S19: return 19;
    case S20: return 20;
    case S21: return 21;
    case S22: return 22;
    case S23: return 23;
    case S24: return 24;
    case S25: return 25;
    case S26: return 26;
    case S27: return 27;
    case S28: return 28;
    case S29: return 29;
    case S30: return 30;
    case S31: return 31;
    }
  }
  }
}

ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii,
                                         const ARMSubtarget &sti)
  : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
    TII(tii), STI(sti),
    FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11) {
}

const unsigned*
ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
  static const unsigned CalleeSavedRegs[] = {
    ARM::LR, ARM::R11, ARM::R10, ARM::R9, ARM::R8,
    ARM::R7, ARM::R6,  ARM::R5,  ARM::R4,

    ARM::D15, ARM::D14, ARM::D13, ARM::D12,
    ARM::D11, ARM::D10, ARM::D9,  ARM::D8,
    0
  };

  static const unsigned DarwinCalleeSavedRegs[] = {
    // Darwin ABI deviates from ARM standard ABI. R9 is not a callee-saved
    // register.
    ARM::LR,  ARM::R7,  ARM::R6, ARM::R5, ARM::R4,
    ARM::R11, ARM::R10, ARM::R8,

    ARM::D15, ARM::D14, ARM::D13, ARM::D12,
    ARM::D11, ARM::D10, ARM::D9,  ARM::D8,
    0
  };
  return STI.isTargetDarwin() ? DarwinCalleeSavedRegs : CalleeSavedRegs;
}

BitVector ARMBaseRegisterInfo::
getReservedRegs(const MachineFunction &MF) const {
  // FIXME: avoid re-calculating this everytime.
  BitVector Reserved(getNumRegs());
  Reserved.set(ARM::SP);
  Reserved.set(ARM::PC);
  Reserved.set(ARM::FPSCR);
  if (STI.isTargetDarwin() || hasFP(MF))
    Reserved.set(FramePtr);
  // Some targets reserve R9.
  if (STI.isR9Reserved())
    Reserved.set(ARM::R9);
  return Reserved;
}

bool ARMBaseRegisterInfo::isReservedReg(const MachineFunction &MF,
                                        unsigned Reg) const {
  switch (Reg) {
  default: break;
  case ARM::SP:
  case ARM::PC:
    return true;
  case ARM::R7:
  case ARM::R11:
    if (FramePtr == Reg && (STI.isTargetDarwin() || hasFP(MF)))
      return true;
    break;
  case ARM::R9:
    return STI.isR9Reserved();
  }

  return false;
}

const TargetRegisterClass *
ARMBaseRegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
                                              const TargetRegisterClass *B,
                                              unsigned SubIdx) const {
  switch (SubIdx) {
  default: return 0;
  case ARM::ssub_0:
  case ARM::ssub_1:
  case ARM::ssub_2:
  case ARM::ssub_3: {
    // S sub-registers.
    if (A->getSize() == 8) {
      if (B == &ARM::SPR_8RegClass)
        return &ARM::DPR_8RegClass;
      assert(B == &ARM::SPRRegClass && "Expecting SPR register class!");
      if (A == &ARM::DPR_8RegClass)
        return A;
      return &ARM::DPR_VFP2RegClass;
    }

    if (A->getSize() == 16) {
      if (B == &ARM::SPR_8RegClass)
        return &ARM::QPR_8RegClass;
      return &ARM::QPR_VFP2RegClass;
    }

    if (A->getSize() == 32) {
      if (B == &ARM::SPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return &ARM::QQPR_VFP2RegClass;
    }

    assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
    return 0;  // Do not allow coalescing!
  }
  case ARM::dsub_0:
  case ARM::dsub_1:
  case ARM::dsub_2:
  case ARM::dsub_3: {
    // D sub-registers.
    if (A->getSize() == 16) {
      if (B == &ARM::DPR_VFP2RegClass)
        return &ARM::QPR_VFP2RegClass;
      if (B == &ARM::DPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return A;
    }

    if (A->getSize() == 32) {
      if (B == &ARM::DPR_VFP2RegClass)
        return &ARM::QQPR_VFP2RegClass;
      if (B == &ARM::DPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return A;
    }

    assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
    if (B != &ARM::DPRRegClass)
      return 0;  // Do not allow coalescing!
    return A;
  }
  case ARM::dsub_4:
  case ARM::dsub_5:
  case ARM::dsub_6:
  case ARM::dsub_7: {
    // D sub-registers of QQQQ registers.
    if (A->getSize() == 64 && B == &ARM::DPRRegClass)
      return A;
    return 0;  // Do not allow coalescing!
  }

  case ARM::qsub_0:
  case ARM::qsub_1: {
    // Q sub-registers.
    if (A->getSize() == 32) {
      if (B == &ARM::QPR_VFP2RegClass)
        return &ARM::QQPR_VFP2RegClass;
      if (B == &ARM::QPR_8RegClass)
        return 0;  // Do not allow coalescing!
      return A;
    }

    assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
    if (B == &ARM::QPRRegClass)
      return A;
    return 0;  // Do not allow coalescing!
  }
  case ARM::qsub_2:
  case ARM::qsub_3: {
    // Q sub-registers of QQQQ registers.
    if (A->getSize() == 64 && B == &ARM::QPRRegClass)
      return A;
    return 0;  // Do not allow coalescing!
  }
  }
  return 0;
}

bool
ARMBaseRegisterInfo::canCombineSubRegIndices(const TargetRegisterClass *RC,
                                          SmallVectorImpl<unsigned> &SubIndices,
                                          unsigned &NewSubIdx) const {

  unsigned Size = RC->getSize() * 8;
  if (Size < 6)
    return 0;

  NewSubIdx = 0;  // Whole register.
  unsigned NumRegs = SubIndices.size();
  if (NumRegs == 8) {
    // 8 D registers -> 1 QQQQ register.
    return (Size == 512 &&
            SubIndices[0] == ARM::dsub_0 &&
            SubIndices[1] == ARM::dsub_1 &&
            SubIndices[2] == ARM::dsub_2 &&
            SubIndices[3] == ARM::dsub_3 &&
            SubIndices[4] == ARM::dsub_4 &&
            SubIndices[5] == ARM::dsub_5 &&
            SubIndices[6] == ARM::dsub_6 &&
            SubIndices[7] == ARM::dsub_7);
  } else if (NumRegs == 4) {
    if (SubIndices[0] == ARM::qsub_0) {
      // 4 Q registers -> 1 QQQQ register.
      return (Size == 512 &&
              SubIndices[1] == ARM::qsub_1 &&
              SubIndices[2] == ARM::qsub_2 &&
              SubIndices[3] == ARM::qsub_3);
    } else if (SubIndices[0] == ARM::dsub_0) {
      // 4 D registers -> 1 QQ register.
      if (Size >= 256 &&
          SubIndices[1] == ARM::dsub_1 &&
          SubIndices[2] == ARM::dsub_2 &&
          SubIndices[3] == ARM::dsub_3) {
        if (Size == 512)
          NewSubIdx = ARM::qqsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_4) {
      // 4 D registers -> 1 QQ register (2nd).
      if (Size == 512 &&
          SubIndices[1] == ARM::dsub_5 &&
          SubIndices[2] == ARM::dsub_6 &&
          SubIndices[3] == ARM::dsub_7) {
        NewSubIdx = ARM::qqsub_1;
        return true;
      }
    } else if (SubIndices[0] == ARM::ssub_0) {
      // 4 S registers -> 1 Q register.
      if (Size >= 128 &&
          SubIndices[1] == ARM::ssub_1 &&
          SubIndices[2] == ARM::ssub_2 &&
          SubIndices[3] == ARM::ssub_3) {
        if (Size >= 256)
          NewSubIdx = ARM::qsub_0;
        return true;
      }
    }
  } else if (NumRegs == 2) {
    if (SubIndices[0] == ARM::qsub_0) {
      // 2 Q registers -> 1 QQ register.
      if (Size >= 256 && SubIndices[1] == ARM::qsub_1) {
        if (Size == 512)
          NewSubIdx = ARM::qqsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::qsub_2) {
      // 2 Q registers -> 1 QQ register (2nd).
      if (Size == 512 && SubIndices[1] == ARM::qsub_3) {
        NewSubIdx = ARM::qqsub_1;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_0) {
      // 2 D registers -> 1 Q register.
      if (Size >= 128 && SubIndices[1] == ARM::dsub_1) {
        if (Size >= 256)
          NewSubIdx = ARM::qsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_2) {
      // 2 D registers -> 1 Q register (2nd).
      if (Size >= 256 && SubIndices[1] == ARM::dsub_3) {
        NewSubIdx = ARM::qsub_1;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_4) {
      // 2 D registers -> 1 Q register (3rd).
      if (Size == 512 && SubIndices[1] == ARM::dsub_5) {
        NewSubIdx = ARM::qsub_2;
        return true;
      }
    } else if (SubIndices[0] == ARM::dsub_6) {
      // 2 D registers -> 1 Q register (3rd).
      if (Size == 512 && SubIndices[1] == ARM::dsub_7) {
        NewSubIdx = ARM::qsub_3;
        return true;
      }
    } else if (SubIndices[0] == ARM::ssub_0) {
      // 2 S registers -> 1 D register.
      if (SubIndices[1] == ARM::ssub_1) {
        if (Size >= 128)
          NewSubIdx = ARM::dsub_0;
        return true;
      }
    } else if (SubIndices[0] == ARM::ssub_2) {
      // 2 S registers -> 1 D register (2nd).
      if (Size >= 128 && SubIndices[1] == ARM::ssub_3) {
        NewSubIdx = ARM::dsub_1;
        return true;
      }
    }
  }
  return false;
}


const TargetRegisterClass *
ARMBaseRegisterInfo::getPointerRegClass(unsigned Kind) const {
  return ARM::GPRRegisterClass;
}

/// getAllocationOrder - Returns the register allocation order for a specified
/// register class in the form of a pair of TargetRegisterClass iterators.
std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
                                        unsigned HintType, unsigned HintReg,
                                        const MachineFunction &MF) const {
  // Alternative register allocation orders when favoring even / odd registers
  // of register pairs.

  // No FP, R9 is available.
  static const unsigned GPREven1[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7,
    ARM::R9, ARM::R11
  };
  static const unsigned GPROdd1[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R9, ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
    ARM::R8, ARM::R10
  };

  // FP is R7, R9 is available.
  static const unsigned GPREven2[] = {
    ARM::R0, ARM::R2, ARM::R4,          ARM::R8, ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6,
    ARM::R9, ARM::R11
  };
  static const unsigned GPROdd2[] = {
    ARM::R1, ARM::R3, ARM::R5,          ARM::R9, ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
    ARM::R8, ARM::R10
  };

  // FP is R11, R9 is available.
  static const unsigned GPREven3[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8,
    ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7,
    ARM::R9
  };
  static const unsigned GPROdd3[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R6, ARM::R9,
    ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R7,
    ARM::R8
  };

  // No FP, R9 is not available.
  static const unsigned GPREven4[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6,          ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8,
    ARM::R11
  };
  static const unsigned GPROdd4[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R7,          ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
    ARM::R10
  };

  // FP is R7, R9 is not available.
  static const unsigned GPREven5[] = {
    ARM::R0, ARM::R2, ARM::R4,                   ARM::R10,
    ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, ARM::R8,
    ARM::R11
  };
  static const unsigned GPROdd5[] = {
    ARM::R1, ARM::R3, ARM::R5,                   ARM::R11,
    ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
    ARM::R10
  };

  // FP is R11, R9 is not available.
  static const unsigned GPREven6[] = {
    ARM::R0, ARM::R2, ARM::R4, ARM::R6,
    ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8
  };
  static const unsigned GPROdd6[] = {
    ARM::R1, ARM::R3, ARM::R5, ARM::R7,
    ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8
  };


  if (HintType == ARMRI::RegPairEven) {
    if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0)
      // It's no longer possible to fulfill this hint. Return the default
      // allocation order.
      return std::make_pair(RC->allocation_order_begin(MF),
                            RC->allocation_order_end(MF));

    if (!STI.isTargetDarwin() && !hasFP(MF)) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPREven1,
                              GPREven1 + (sizeof(GPREven1)/sizeof(unsigned)));
      else
        return std::make_pair(GPREven4,
                              GPREven4 + (sizeof(GPREven4)/sizeof(unsigned)));
    } else if (FramePtr == ARM::R7) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPREven2,
                              GPREven2 + (sizeof(GPREven2)/sizeof(unsigned)));
      else
        return std::make_pair(GPREven5,
                              GPREven5 + (sizeof(GPREven5)/sizeof(unsigned)));
    } else { // FramePtr == ARM::R11
      if (!STI.isR9Reserved())
        return std::make_pair(GPREven3,
                              GPREven3 + (sizeof(GPREven3)/sizeof(unsigned)));
      else
        return std::make_pair(GPREven6,
                              GPREven6 + (sizeof(GPREven6)/sizeof(unsigned)));
    }
  } else if (HintType == ARMRI::RegPairOdd) {
    if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0)
      // It's no longer possible to fulfill this hint. Return the default
      // allocation order.
      return std::make_pair(RC->allocation_order_begin(MF),
                            RC->allocation_order_end(MF));

    if (!STI.isTargetDarwin() && !hasFP(MF)) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPROdd1,
                              GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned)));
      else
        return std::make_pair(GPROdd4,
                              GPROdd4 + (sizeof(GPROdd4)/sizeof(unsigned)));
    } else if (FramePtr == ARM::R7) {
      if (!STI.isR9Reserved())
        return std::make_pair(GPROdd2,
                              GPROdd2 + (sizeof(GPROdd2)/sizeof(unsigned)));
      else
        return std::make_pair(GPROdd5,
                              GPROdd5 + (sizeof(GPROdd5)/sizeof(unsigned)));
    } else { // FramePtr == ARM::R11
      if (!STI.isR9Reserved())
        return std::make_pair(GPROdd3,
                              GPROdd3 + (sizeof(GPROdd3)/sizeof(unsigned)));
      else
        return std::make_pair(GPROdd6,
                              GPROdd6 + (sizeof(GPROdd6)/sizeof(unsigned)));
    }
  }
  return std::make_pair(RC->allocation_order_begin(MF),
                        RC->allocation_order_end(MF));
}

/// ResolveRegAllocHint - Resolves the specified register allocation hint
/// to a physical register. Returns the physical register if it is successful.
unsigned
ARMBaseRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg,
                                         const MachineFunction &MF) const {
  if (Reg == 0 || !isPhysicalRegister(Reg))
    return 0;
  if (Type == 0)
    return Reg;
  else if (Type == (unsigned)ARMRI::RegPairOdd)
    // Odd register.
    return getRegisterPairOdd(Reg, MF);
  else if (Type == (unsigned)ARMRI::RegPairEven)
    // Even register.
    return getRegisterPairEven(Reg, MF);
  return 0;
}

void
ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
                                        MachineFunction &MF) const {
  MachineRegisterInfo *MRI = &MF.getRegInfo();
  std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg);
  if ((Hint.first == (unsigned)ARMRI::RegPairOdd ||
       Hint.first == (unsigned)ARMRI::RegPairEven) &&
      Hint.second && TargetRegisterInfo::isVirtualRegister(Hint.second)) {
    // If 'Reg' is one of the even / odd register pair and it's now changed
    // (e.g. coalesced) into a different register. The other register of the
    // pair allocation hint must be updated to reflect the relationship
    // change.
    unsigned OtherReg = Hint.second;
    Hint = MRI->getRegAllocationHint(OtherReg);
    if (Hint.second == Reg)
      // Make sure the pair has not already divorced.
      MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg);
  }
}

/// hasFP - 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 ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  // Always eliminate non-leaf frame pointers.
  return ((DisableFramePointerElim(MF) && MFI->hasCalls()) ||
          needsStackRealignment(MF) ||
          MFI->hasVarSizedObjects() ||
          MFI->isFrameAddressTaken());
}

bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  return (RealignStack &&
          !AFI->isThumb1OnlyFunction() &&
          !MFI->hasVarSizedObjects());
}

bool ARMBaseRegisterInfo::
needsStackRealignment(const MachineFunction &MF) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
{'fraction_non_alphanumeric': 0.14986627535442948, 'fraction_numerical': 0.04125346145653357, 'mean_word_length': 2.4638465322183967, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 110, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7234091', 'n_tokens_mistral': 15672, 'n_tokens_neox': 14796, 'n_words': 3749}