XCoreRegisterInfo.cpp revision 252723
165832Snyan//===-- XCoreRegisterInfo.cpp - XCore Register Information ----------------===//
265832Snyan//
365832Snyan//                     The LLVM Compiler Infrastructure
465832Snyan//
565832Snyan// This file is distributed under the University of Illinois Open Source
665832Snyan// License. See LICENSE.TXT for details.
765832Snyan//
865832Snyan//===----------------------------------------------------------------------===//
965832Snyan//
1065832Snyan// This file contains the XCore implementation of the MRegisterInfo class.
1165832Snyan//
1265832Snyan//===----------------------------------------------------------------------===//
1365832Snyan
1465832Snyan#include "XCoreRegisterInfo.h"
1565832Snyan#include "XCore.h"
1665832Snyan#include "XCoreMachineFunctionInfo.h"
1765832Snyan#include "llvm/ADT/BitVector.h"
1865832Snyan#include "llvm/ADT/STLExtras.h"
1965832Snyan#include "llvm/CodeGen/MachineFrameInfo.h"
2065832Snyan#include "llvm/CodeGen/MachineFunction.h"
2165832Snyan#include "llvm/CodeGen/MachineInstrBuilder.h"
2265832Snyan#include "llvm/CodeGen/MachineModuleInfo.h"
2365832Snyan#include "llvm/CodeGen/MachineRegisterInfo.h"
2465832Snyan#include "llvm/CodeGen/RegisterScavenging.h"
2565832Snyan#include "llvm/IR/Function.h"
2665832Snyan#include "llvm/IR/Type.h"
2765832Snyan#include "llvm/Support/Debug.h"
2865832Snyan#include "llvm/Support/ErrorHandling.h"
2965832Snyan#include "llvm/Support/raw_ostream.h"
3065832Snyan#include "llvm/Target/TargetFrameLowering.h"
3165832Snyan#include "llvm/Target/TargetInstrInfo.h"
3265832Snyan#include "llvm/Target/TargetMachine.h"
3365832Snyan#include "llvm/Target/TargetOptions.h"
3465832Snyan
3565832Snyan#define GET_REGINFO_TARGET_DESC
3665832Snyan#include "XCoreGenRegisterInfo.inc"
3765832Snyan
3865832Snyanusing namespace llvm;
3965832Snyan
4065832SnyanXCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii)
4165832Snyan  : XCoreGenRegisterInfo(XCore::LR), TII(tii) {
4265832Snyan}
4365832Snyan
4465832Snyan// helper functions
4565832Snyanstatic inline bool isImmUs(unsigned val) {
4665832Snyan  return val <= 11;
4765832Snyan}
4865832Snyan
4965832Snyanstatic inline bool isImmU6(unsigned val) {
5065832Snyan  return val < (1 << 6);
5165832Snyan}
5267442Snyan
5367442Snyanstatic inline bool isImmU16(unsigned val) {
5465832Snyan  return val < (1 << 16);
5565832Snyan}
5665832Snyan
5765832Snyanbool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
5865832Snyan  return MF.getMMI().hasDebugInfo() ||
5965832Snyan    MF.getFunction()->needsUnwindTableEntry();
6065832Snyan}
6165832Snyan
6265832Snyanconst uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
6365832Snyan                                                                         const {
6465832Snyan  static const uint16_t CalleeSavedRegs[] = {
6565832Snyan    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
6665832Snyan    XCore::R8, XCore::R9, XCore::R10, XCore::LR,
6765832Snyan    0
6865832Snyan  };
6965832Snyan  return CalleeSavedRegs;
7065832Snyan}
7165832Snyan
7265832SnyanBitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
7365832Snyan  BitVector Reserved(getNumRegs());
7465832Snyan  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
7565832Snyan
7665832Snyan  Reserved.set(XCore::CP);
7765832Snyan  Reserved.set(XCore::DP);
7865832Snyan  Reserved.set(XCore::SP);
7965832Snyan  Reserved.set(XCore::LR);
8065832Snyan  if (TFI->hasFP(MF)) {
8165832Snyan    Reserved.set(XCore::R10);
8265832Snyan  }
8365832Snyan  return Reserved;
8465832Snyan}
8565832Snyan
8665832Snyanbool
8765832SnyanXCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
8865832Snyan  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
8965832Snyan
9065832Snyan  // TODO can we estimate stack size?
9165832Snyan  return TFI->hasFP(MF);
9265832Snyan}
9365832Snyan
9465832Snyanbool
9565832SnyanXCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
9665832Snyan  return requiresRegisterScavenging(MF);
9765832Snyan}
9865832Snyan
9965832Snyanbool
10065832SnyanXCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
10165832Snyan  return false;
10265832Snyan}
10365832Snyan
10465832Snyanvoid
10565832SnyanXCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
10665832Snyan                                       int SPAdj, unsigned FIOperandNum,
10765832Snyan                                       RegScavenger *RS) const {
10865832Snyan  assert(SPAdj == 0 && "Unexpected");
10965832Snyan  MachineInstr &MI = *II;
11065832Snyan  DebugLoc dl = MI.getDebugLoc();
11165832Snyan  MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
11265832Snyan  int FrameIndex = FrameOp.getIndex();
11365832Snyan
11465832Snyan  MachineFunction &MF = *MI.getParent()->getParent();
11565832Snyan  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
11665832Snyan  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
11765832Snyan  int StackSize = MF.getFrameInfo()->getStackSize();
11865832Snyan
11965832Snyan  #ifndef NDEBUG
12065832Snyan  DEBUG(errs() << "\nFunction         : "
12165832Snyan        << MF.getName() << "\n");
12265832Snyan  DEBUG(errs() << "<--------->\n");
12365832Snyan  DEBUG(MI.print(errs()));
12465832Snyan  DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
12565832Snyan  DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
12665832Snyan  DEBUG(errs() << "StackSize          : " << StackSize << "\n");
12765832Snyan  #endif
12865832Snyan
12965832Snyan  Offset += StackSize;
13065832Snyan
13165832Snyan  unsigned FrameReg = getFrameRegister(MF);
13265832Snyan
13365832Snyan  // Special handling of DBG_VALUE instructions.
13465832Snyan  if (MI.isDebugValue()) {
13565832Snyan    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
13665832Snyan    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
13765832Snyan    return;
13865832Snyan  }
13965832Snyan
14065832Snyan  // fold constant into offset.
14165832Snyan  Offset += MI.getOperand(FIOperandNum + 1).getImm();
14265832Snyan  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
14365832Snyan
14465832Snyan  assert(Offset%4 == 0 && "Misaligned stack offset");
14565832Snyan
14665832Snyan  DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
14765832Snyan
14865832Snyan  Offset/=4;
14965832Snyan
15065832Snyan  bool FP = TFI->hasFP(MF);
15165832Snyan
15265832Snyan  unsigned Reg = MI.getOperand(0).getReg();
15365832Snyan  bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill();
15465832Snyan
15565832Snyan  assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
15665832Snyan
15765832Snyan  MachineBasicBlock &MBB = *MI.getParent();
15865832Snyan
15965832Snyan  if (FP) {
16065832Snyan    bool isUs = isImmUs(Offset);
16165832Snyan
16265832Snyan    if (!isUs) {
16365832Snyan      if (!RS)
16465832Snyan        report_fatal_error("eliminateFrameIndex Frame size too big: " +
16565832Snyan                           Twine(Offset));
16665832Snyan      unsigned ScratchReg = RS->scavengeRegister(&XCore::GRRegsRegClass, II,
16765832Snyan                                                 SPAdj);
16865832Snyan      loadConstant(MBB, II, ScratchReg, Offset, dl);
16965832Snyan      switch (MI.getOpcode()) {
17065832Snyan      case XCore::LDWFI:
17165832Snyan        BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
17265832Snyan              .addReg(FrameReg)
17365832Snyan              .addReg(ScratchReg, RegState::Kill);
17465832Snyan        break;
17565832Snyan      case XCore::STWFI:
17665832Snyan        BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
17765832Snyan              .addReg(Reg, getKillRegState(isKill))
17865832Snyan              .addReg(FrameReg)
17965832Snyan              .addReg(ScratchReg, RegState::Kill);
18065832Snyan        break;
18165832Snyan      case XCore::LDAWFI:
18265832Snyan        BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
18365832Snyan              .addReg(FrameReg)
18465832Snyan              .addReg(ScratchReg, RegState::Kill);
18565832Snyan        break;
18665832Snyan      default:
18765832Snyan        llvm_unreachable("Unexpected Opcode");
18865832Snyan      }
18965832Snyan    } else {
19065832Snyan      switch (MI.getOpcode()) {
19165832Snyan      case XCore::LDWFI:
19265832Snyan        BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
19365832Snyan              .addReg(FrameReg)
19465832Snyan              .addImm(Offset);
19565832Snyan        break;
19665832Snyan      case XCore::STWFI:
19765832Snyan        BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
19865832Snyan              .addReg(Reg, getKillRegState(isKill))
19965832Snyan              .addReg(FrameReg)
20065832Snyan              .addImm(Offset);
20165832Snyan        break;
20265832Snyan      case XCore::LDAWFI:
20365832Snyan        BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
20465832Snyan              .addReg(FrameReg)
20565832Snyan              .addImm(Offset);
20665832Snyan        break;
20765832Snyan      default:
20865832Snyan        llvm_unreachable("Unexpected Opcode");
20965832Snyan      }
21065832Snyan    }
21165832Snyan  } else {
21265832Snyan    bool isU6 = isImmU6(Offset);
21365832Snyan    if (!isU6 && !isImmU16(Offset))
21465832Snyan      report_fatal_error("eliminateFrameIndex Frame size too big: " +
21565832Snyan                         Twine(Offset));
21665832Snyan
21765832Snyan    switch (MI.getOpcode()) {
21865832Snyan    int NewOpcode;
21965832Snyan    case XCore::LDWFI:
22065832Snyan      NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
22165832Snyan      BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
22265832Snyan            .addImm(Offset);
22365832Snyan      break;
22465832Snyan    case XCore::STWFI:
22565832Snyan      NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
22665832Snyan      BuildMI(MBB, II, dl, TII.get(NewOpcode))
22765832Snyan            .addReg(Reg, getKillRegState(isKill))
22865832Snyan            .addImm(Offset);
22965832Snyan      break;
23065832Snyan    case XCore::LDAWFI:
23165832Snyan      NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
23265832Snyan      BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
23365832Snyan            .addImm(Offset);
23465832Snyan      break;
23565832Snyan    default:
23665832Snyan      llvm_unreachable("Unexpected Opcode");
23765832Snyan    }
23865832Snyan  }
23965832Snyan  // Erase old instruction.
24065832Snyan  MBB.erase(II);
24165832Snyan}
24265832Snyan
24365832Snyanvoid XCoreRegisterInfo::
24465832SnyanloadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
24565832Snyan            unsigned DstReg, int64_t Value, DebugLoc dl) const {
24665832Snyan  // TODO use mkmsk if possible.
24765832Snyan  if (!isImmU16(Value)) {
24865832Snyan    // TODO use constant pool.
24965832Snyan    report_fatal_error("loadConstant value too big " + Twine(Value));
25065832Snyan  }
25165832Snyan  int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
25265832Snyan  BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
25365832Snyan}
25465832Snyan
25565832Snyanunsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
25665832Snyan  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
25765832Snyan
25865832Snyan  return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
25965832Snyan}
26065832Snyan