LLVM API Documentation

XCoreRegisterInfo.cpp
Go to the documentation of this file.
00001 //===-- XCoreRegisterInfo.cpp - XCore Register Information ----------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains the XCore implementation of the MRegisterInfo class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "XCoreRegisterInfo.h"
00015 #include "XCore.h"
00016 #include "XCoreMachineFunctionInfo.h"
00017 #include "llvm/ADT/BitVector.h"
00018 #include "llvm/ADT/STLExtras.h"
00019 #include "llvm/CodeGen/MachineFrameInfo.h"
00020 #include "llvm/CodeGen/MachineFunction.h"
00021 #include "llvm/CodeGen/MachineInstrBuilder.h"
00022 #include "llvm/CodeGen/MachineModuleInfo.h"
00023 #include "llvm/CodeGen/MachineRegisterInfo.h"
00024 #include "llvm/CodeGen/RegisterScavenging.h"
00025 #include "llvm/IR/Function.h"
00026 #include "llvm/IR/Type.h"
00027 #include "llvm/Support/Debug.h"
00028 #include "llvm/Support/ErrorHandling.h"
00029 #include "llvm/Support/raw_ostream.h"
00030 #include "llvm/Target/TargetFrameLowering.h"
00031 #include "llvm/Target/TargetInstrInfo.h"
00032 #include "llvm/Target/TargetMachine.h"
00033 #include "llvm/Target/TargetOptions.h"
00034 
00035 #define GET_REGINFO_TARGET_DESC
00036 #include "XCoreGenRegisterInfo.inc"
00037 
00038 using namespace llvm;
00039 
00040 XCoreRegisterInfo::XCoreRegisterInfo(const TargetInstrInfo &tii)
00041   : XCoreGenRegisterInfo(XCore::LR), TII(tii) {
00042 }
00043 
00044 // helper functions
00045 static inline bool isImmUs(unsigned val) {
00046   return val <= 11;
00047 }
00048 
00049 static inline bool isImmU6(unsigned val) {
00050   return val < (1 << 6);
00051 }
00052 
00053 static inline bool isImmU16(unsigned val) {
00054   return val < (1 << 16);
00055 }
00056 
00057 bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
00058   return MF.getMMI().hasDebugInfo() ||
00059     MF.getFunction()->needsUnwindTableEntry();
00060 }
00061 
00062 const uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
00063                                                                          const {
00064   static const uint16_t CalleeSavedRegs[] = {
00065     XCore::R4, XCore::R5, XCore::R6, XCore::R7,
00066     XCore::R8, XCore::R9, XCore::R10, XCore::LR,
00067     0
00068   };
00069   return CalleeSavedRegs;
00070 }
00071 
00072 BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
00073   BitVector Reserved(getNumRegs());
00074   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
00075 
00076   Reserved.set(XCore::CP);
00077   Reserved.set(XCore::DP);
00078   Reserved.set(XCore::SP);
00079   Reserved.set(XCore::LR);
00080   if (TFI->hasFP(MF)) {
00081     Reserved.set(XCore::R10);
00082   }
00083   return Reserved;
00084 }
00085 
00086 bool
00087 XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
00088   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
00089 
00090   // TODO can we estimate stack size?
00091   return TFI->hasFP(MF);
00092 }
00093 
00094 bool
00095 XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
00096   return requiresRegisterScavenging(MF);
00097 }
00098 
00099 bool
00100 XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
00101   return false;
00102 }
00103 
00104 void
00105 XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
00106                                        int SPAdj, unsigned FIOperandNum,
00107                                        RegScavenger *RS) const {
00108   assert(SPAdj == 0 && "Unexpected");
00109   MachineInstr &MI = *II;
00110   DebugLoc dl = MI.getDebugLoc();
00111   MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
00112   int FrameIndex = FrameOp.getIndex();
00113 
00114   MachineFunction &MF = *MI.getParent()->getParent();
00115   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
00116   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
00117   int StackSize = MF.getFrameInfo()->getStackSize();
00118 
00119   #ifndef NDEBUG
00120   DEBUG(errs() << "\nFunction         : " 
00121         << MF.getName() << "\n");
00122   DEBUG(errs() << "<--------->\n");
00123   DEBUG(MI.print(errs()));
00124   DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
00125   DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
00126   DEBUG(errs() << "StackSize          : " << StackSize << "\n");
00127   #endif
00128 
00129   Offset += StackSize;
00130 
00131   unsigned FrameReg = getFrameRegister(MF);
00132 
00133   // Special handling of DBG_VALUE instructions.
00134   if (MI.isDebugValue()) {
00135     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
00136     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
00137     return;
00138   }
00139 
00140   // fold constant into offset.
00141   Offset += MI.getOperand(FIOperandNum + 1).getImm();
00142   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
00143   
00144   assert(Offset%4 == 0 && "Misaligned stack offset");
00145 
00146   DEBUG(errs() << "Offset             : " << Offset << "\n" << "<--------->\n");
00147   
00148   Offset/=4;
00149   
00150   bool FP = TFI->hasFP(MF);
00151 
00152   unsigned Reg = MI.getOperand(0).getReg();
00153   bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill();
00154 
00155   assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
00156   
00157   MachineBasicBlock &MBB = *MI.getParent();
00158   
00159   if (FP) {
00160     bool isUs = isImmUs(Offset);
00161     
00162     if (!isUs) {
00163       if (!RS)
00164         report_fatal_error("eliminateFrameIndex Frame size too big: " +
00165                            Twine(Offset));
00166       unsigned ScratchReg = RS->scavengeRegister(&XCore::GRRegsRegClass, II,
00167                                                  SPAdj);
00168       loadConstant(MBB, II, ScratchReg, Offset, dl);
00169       switch (MI.getOpcode()) {
00170       case XCore::LDWFI:
00171         BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
00172               .addReg(FrameReg)
00173               .addReg(ScratchReg, RegState::Kill);
00174         break;
00175       case XCore::STWFI:
00176         BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
00177               .addReg(Reg, getKillRegState(isKill))
00178               .addReg(FrameReg)
00179               .addReg(ScratchReg, RegState::Kill);
00180         break;
00181       case XCore::LDAWFI:
00182         BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
00183               .addReg(FrameReg)
00184               .addReg(ScratchReg, RegState::Kill);
00185         break;
00186       default:
00187         llvm_unreachable("Unexpected Opcode");
00188       }
00189     } else {
00190       switch (MI.getOpcode()) {
00191       case XCore::LDWFI:
00192         BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
00193               .addReg(FrameReg)
00194               .addImm(Offset);
00195         break;
00196       case XCore::STWFI:
00197         BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
00198               .addReg(Reg, getKillRegState(isKill))
00199               .addReg(FrameReg)
00200               .addImm(Offset);
00201         break;
00202       case XCore::LDAWFI:
00203         BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
00204               .addReg(FrameReg)
00205               .addImm(Offset);
00206         break;
00207       default:
00208         llvm_unreachable("Unexpected Opcode");
00209       }
00210     }
00211   } else {
00212     bool isU6 = isImmU6(Offset);
00213     if (!isU6 && !isImmU16(Offset))
00214       report_fatal_error("eliminateFrameIndex Frame size too big: " +
00215                          Twine(Offset));
00216 
00217     switch (MI.getOpcode()) {
00218     int NewOpcode;
00219     case XCore::LDWFI:
00220       NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
00221       BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
00222             .addImm(Offset);
00223       break;
00224     case XCore::STWFI:
00225       NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
00226       BuildMI(MBB, II, dl, TII.get(NewOpcode))
00227             .addReg(Reg, getKillRegState(isKill))
00228             .addImm(Offset);
00229       break;
00230     case XCore::LDAWFI:
00231       NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
00232       BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
00233             .addImm(Offset);
00234       break;
00235     default:
00236       llvm_unreachable("Unexpected Opcode");
00237     }
00238   }
00239   // Erase old instruction.
00240   MBB.erase(II);
00241 }
00242 
00243 void XCoreRegisterInfo::
00244 loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
00245             unsigned DstReg, int64_t Value, DebugLoc dl) const {
00246   // TODO use mkmsk if possible.
00247   if (!isImmU16(Value)) {
00248     // TODO use constant pool.
00249     report_fatal_error("loadConstant value too big " + Twine(Value));
00250   }
00251   int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
00252   BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
00253 }
00254 
00255 unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
00256   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
00257 
00258   return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
00259 }