Skip to content
ARMRegisterInfo.cpp 56 KiB
Newer Older
//===- ARMRegisterInfo.cpp - ARM Register Information -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the "Instituto Nokia de Tecnologia" and
// is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the ARM implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//

#include "ARM.h"
#include "ARMAddressingModes.h"
#include "ARMInstrInfo.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMRegisterInfo.h"
#include "ARMSubtarget.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.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/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/ADT/STLExtras.h"
#include <algorithm>
using namespace llvm;

static cl::opt<bool> ThumbRegScavenging("enable-thumb-reg-scavenging",
                               cl::Hidden,
                               cl::desc("Enable register scavenging on Thumb"));
unsigned ARMRegisterInfo::getRegisterNumbering(unsigned RegEnum) {
  using namespace ARM;
  switch (RegEnum) {
  case R0:  case S0:  case D0:  return 0;
  case R1:  case S1:  case D1:  return 1;
  case R2:  case S2:  case D2:  return 2;
  case R3:  case S3:  case D3:  return 3;
  case R4:  case S4:  case D4:  return 4;
  case R5:  case S5:  case D5:  return 5;
  case R6:  case S6:  case D6:  return 6;
  case R7:  case S7:  case D7:  return 7;
  case R8:  case S8:  case D8:  return 8;
  case R9:  case S9:  case D9:  return 9;
  case R10: case S10: case D10: return 10;
  case R11: case S11: case D11: return 11;
  case R12: case S12: case D12: return 12;
  case SP:  case S13: case D13: return 13;
  case LR:  case S14: case D14: return 14;
  case PC:  case S15: case D15: 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;
  default:
    assert(0 && "Unknown ARM register!");
    abort();
ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii,
                                 const ARMSubtarget &sti)
  : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
    TII(tii), STI(sti),
Lauro Ramos Venancio's avatar
Lauro Ramos Venancio committed
    FramePtr((STI.useThumbBacktraces() || STI.isThumb()) ? ARM::R7 : ARM::R11) {
bool ARMRegisterInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
                                                MachineBasicBlock::iterator MI,
                                const std::vector<CalleeSavedInfo> &CSI) const {
  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  if (!AFI->isThumbFunction() || CSI.empty())
    return false;

  MachineInstrBuilder MIB = BuildMI(MBB, MI, TII.get(ARM::tPUSH));
  for (unsigned i = CSI.size(); i != 0; --i) {
    unsigned Reg = CSI[i-1].getReg();
    // Add the callee-saved register as live-in. It's killed at the spill.
    MBB.addLiveIn(Reg);
    MIB.addReg(Reg, false/*isDef*/,false/*isImp*/,true/*isKill*/);
  }
  return true;
}

bool ARMRegisterInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
                                                 MachineBasicBlock::iterator MI,
                                const std::vector<CalleeSavedInfo> &CSI) const {
  MachineFunction &MF = *MBB.getParent();
  ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  if (!AFI->isThumbFunction() || CSI.empty())
    return false;

  bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
  MachineInstr *PopMI = new MachineInstr(TII.get(ARM::tPOP));
  MBB.insert(MI, PopMI);
  for (unsigned i = CSI.size(); i != 0; --i) {
    unsigned Reg = CSI[i-1].getReg();
    if (Reg == ARM::LR) {
      // Special epilogue for vararg functions. See emitEpilogue
      if (isVarArg)
        continue;
      Reg = ARM::PC;
      PopMI->setInstrDescriptor(TII.get(ARM::tPOP_RET));
      MBB.erase(MI);
    }
    PopMI->addRegOperand(Reg, true);
  }
  return true;
}

void ARMRegisterInfo::
storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                    unsigned SrcReg, int FI,
                    const TargetRegisterClass *RC) const {
  if (RC == ARM::GPRRegisterClass) {
    MachineFunction &MF = *MBB.getParent();
    ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
    if (AFI->isThumbFunction())
      BuildMI(MBB, I, TII.get(ARM::tSpill)).addReg(SrcReg, false, false, true)
        .addFrameIndex(FI).addImm(0);
    else
      BuildMI(MBB, I, TII.get(ARM::STR)).addReg(SrcReg, false, false, true)
        .addFrameIndex(FI).addReg(0).addImm(0).addImm((int64_t)ARMCC::AL)
        .addReg(0);
  } else if (RC == ARM::DPRRegisterClass) {
    BuildMI(MBB, I, TII.get(ARM::FSTD)).addReg(SrcReg, false, false, true)
      .addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL).addReg(0);
  } else {
    assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
    BuildMI(MBB, I, TII.get(ARM::FSTS)).addReg(SrcReg, false, false, true)
      .addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL).addReg(0);
}

void ARMRegisterInfo::
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                     unsigned DestReg, int FI,
                     const TargetRegisterClass *RC) const {
  if (RC == ARM::GPRRegisterClass) {
    MachineFunction &MF = *MBB.getParent();
    ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
    if (AFI->isThumbFunction())
      BuildMI(MBB, I, TII.get(ARM::tRestore), DestReg)
        .addFrameIndex(FI).addImm(0);
    else
      BuildMI(MBB, I, TII.get(ARM::LDR), DestReg)
        .addFrameIndex(FI).addReg(0).addImm(0).addImm((int64_t)ARMCC::AL)
        .addReg(0);
  } else if (RC == ARM::DPRRegisterClass) {
    BuildMI(MBB, I, TII.get(ARM::FLDD), DestReg)
      .addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL).addReg(0);
  } else {
    assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
    BuildMI(MBB, I, TII.get(ARM::FLDS), DestReg)
      .addFrameIndex(FI).addImm(0).addImm((int64_t)ARMCC::AL).addReg(0);
}

void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
                                   MachineBasicBlock::iterator I,
                                   unsigned DestReg, unsigned SrcReg,
                                   const TargetRegisterClass *RC) const {
  if (RC == ARM::GPRRegisterClass) {
    MachineFunction &MF = *MBB.getParent();
    ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
    if (AFI->isThumbFunction())
      BuildMI(MBB, I, TII.get(ARM::tMOVr), DestReg).addReg(SrcReg);
    else
      BuildMI(MBB, I, TII.get(ARM::MOVr), DestReg).addReg(SrcReg)
        .addImm((int64_t)ARMCC::AL).addReg(0).addReg(0);
  } else if (RC == ARM::SPRRegisterClass)
    BuildMI(MBB, I, TII.get(ARM::FCPYS), DestReg).addReg(SrcReg)
      .addImm((int64_t)ARMCC::AL).addReg(0);
  else if (RC == ARM::DPRRegisterClass)
    BuildMI(MBB, I, TII.get(ARM::FCPYD), DestReg).addReg(SrcReg)
      .addImm((int64_t)ARMCC::AL).addReg(0);
Loading
Loading full blame...