Home | History | Annotate | Download | only in Hexagon
      1 //===-- HexagonRegisterInfo.cpp - Hexagon Register Information ------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the Hexagon implementation of the TargetRegisterInfo
     11 // class.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "HexagonRegisterInfo.h"
     16 #include "Hexagon.h"
     17 #include "HexagonSubtarget.h"
     18 #include "HexagonTargetMachine.h"
     19 #include "HexagonMachineFunctionInfo.h"
     20 #include "llvm/Function.h"
     21 #include "llvm/Type.h"
     22 #include "llvm/ADT/BitVector.h"
     23 #include "llvm/ADT/STLExtras.h"
     24 #include "llvm/CodeGen/MachineInstrBuilder.h"
     25 #include "llvm/CodeGen/MachineFunction.h"
     26 #include "llvm/CodeGen/MachineFunctionPass.h"
     27 #include "llvm/CodeGen/MachineFrameInfo.h"
     28 #include "llvm/CodeGen/MachineRegisterInfo.h"
     29 #include "llvm/CodeGen/RegisterScavenging.h"
     30 #include "llvm/MC/MachineLocation.h"
     31 #include "llvm/Target/TargetInstrInfo.h"
     32 #include "llvm/Target/TargetMachine.h"
     33 #include "llvm/Target/TargetOptions.h"
     34 #include "llvm/Support/CommandLine.h"
     35 #include "llvm/Support/ErrorHandling.h"
     36 
     37 using namespace llvm;
     38 
     39 
     40 HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st,
     41                                      const HexagonInstrInfo &tii)
     42   : HexagonGenRegisterInfo(Hexagon::R31),
     43     Subtarget(st),
     44    TII(tii) {
     45 }
     46 
     47 const uint16_t* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction
     48                                                         *MF)
     49   const {
     50   static const uint16_t CalleeSavedRegsV2[] = {
     51     Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
     52   };
     53   static const uint16_t CalleeSavedRegsV3[] = {
     54     Hexagon::R16,   Hexagon::R17,   Hexagon::R18,   Hexagon::R19,
     55     Hexagon::R20,   Hexagon::R21,   Hexagon::R22,   Hexagon::R23,
     56     Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
     57   };
     58 
     59   switch(Subtarget.getHexagonArchVersion()) {
     60   case HexagonSubtarget::V1:
     61     break;
     62   case HexagonSubtarget::V2:
     63     return CalleeSavedRegsV2;
     64   case HexagonSubtarget::V3:
     65   case HexagonSubtarget::V4:
     66     return CalleeSavedRegsV3;
     67   }
     68   llvm_unreachable("Callee saved registers requested for unknown architecture "
     69                    "version");
     70 }
     71 
     72 BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
     73   const {
     74   BitVector Reserved(getNumRegs());
     75   Reserved.set(HEXAGON_RESERVED_REG_1);
     76   Reserved.set(HEXAGON_RESERVED_REG_2);
     77   Reserved.set(Hexagon::R29);
     78   Reserved.set(Hexagon::R30);
     79   Reserved.set(Hexagon::R31);
     80   Reserved.set(Hexagon::D14);
     81   Reserved.set(Hexagon::D15);
     82   Reserved.set(Hexagon::LC0);
     83   Reserved.set(Hexagon::LC1);
     84   Reserved.set(Hexagon::SA0);
     85   Reserved.set(Hexagon::SA1);
     86   return Reserved;
     87 }
     88 
     89 
     90 const TargetRegisterClass* const*
     91 HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
     92   static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = {
     93     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
     94     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
     95     };
     96   static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
     97     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
     98     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
     99     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
    100     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
    101     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
    102     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
    103   };
    104 
    105   switch(Subtarget.getHexagonArchVersion()) {
    106   case HexagonSubtarget::V1:
    107     break;
    108   case HexagonSubtarget::V2:
    109     return CalleeSavedRegClassesV2;
    110   case HexagonSubtarget::V3:
    111   case HexagonSubtarget::V4:
    112     return CalleeSavedRegClassesV3;
    113   }
    114   llvm_unreachable("Callee saved register classes requested for unknown "
    115                    "architecture version");
    116 }
    117 
    118 void HexagonRegisterInfo::
    119 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
    120                               MachineBasicBlock::iterator I) const {
    121   MachineInstr &MI = *I;
    122 
    123   if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) {
    124     // Hexagon_TODO: add code
    125   } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) {
    126     // Hexagon_TODO: add code
    127   } else {
    128     llvm_unreachable("Cannot handle this call frame pseudo instruction");
    129   }
    130   MBB.erase(I);
    131 }
    132 
    133 void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
    134                                             int SPAdj, RegScavenger *RS) const {
    135 
    136   //
    137   // Hexagon_TODO: Do we need to enforce this for Hexagon?
    138   assert(SPAdj == 0 && "Unexpected");
    139 
    140 
    141   unsigned i = 0;
    142   MachineInstr &MI = *II;
    143   while (!MI.getOperand(i).isFI()) {
    144     ++i;
    145     assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
    146   }
    147 
    148   int FrameIndex = MI.getOperand(i).getIndex();
    149 
    150   // Addressable stack objects are accessed using neg. offsets from %fp.
    151   MachineFunction &MF = *MI.getParent()->getParent();
    152   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
    153   MachineFrameInfo &MFI = *MF.getFrameInfo();
    154 
    155   unsigned FrameReg = getFrameRegister(MF);
    156   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
    157   if (!TFI->hasFP(MF)) {
    158     // We will not reserve space on the stack for the lr and fp registers.
    159     Offset -= 2 * Hexagon_WordSize;
    160   }
    161 
    162   const unsigned FrameSize = MFI.getStackSize();
    163 
    164   if (!MFI.hasVarSizedObjects() &&
    165       TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
    166       !TII.isSpillPredRegOp(&MI)) {
    167     // Replace frame index with a stack pointer reference.
    168     MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true);
    169     MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
    170   } else {
    171     // Replace frame index with a frame pointer reference.
    172     if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
    173 
    174       // If the offset overflows, then correct it.
    175       //
    176       // For loads, we do not need a reserved register
    177       // r0 = memw(r30 + #10000) to:
    178       //
    179       // r0 = add(r30, #10000)
    180       // r0 = memw(r0)
    181       if ( (MI.getOpcode() == Hexagon::LDriw)  ||
    182            (MI.getOpcode() == Hexagon::LDrid) ||
    183            (MI.getOpcode() == Hexagon::LDrih) ||
    184            (MI.getOpcode() == Hexagon::LDriuh) ||
    185            (MI.getOpcode() == Hexagon::LDrib) ||
    186            (MI.getOpcode() == Hexagon::LDriub) ) {
    187         unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
    188           *getSubRegisters(MI.getOperand(0).getReg()) :
    189           MI.getOperand(0).getReg();
    190 
    191         // Check if offset can fit in addi.
    192         if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
    193           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    194                   TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
    195           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    196                   TII.get(Hexagon::ADD_rr),
    197                   dstReg).addReg(FrameReg).addReg(dstReg);
    198         } else {
    199           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    200                   TII.get(Hexagon::ADD_ri),
    201                   dstReg).addReg(FrameReg).addImm(Offset);
    202         }
    203 
    204         MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
    205         MI.getOperand(i+1).ChangeToImmediate(0);
    206       } else if ((MI.getOpcode() == Hexagon::STriw) ||
    207                  (MI.getOpcode() == Hexagon::STrid) ||
    208                  (MI.getOpcode() == Hexagon::STrih) ||
    209                  (MI.getOpcode() == Hexagon::STrib)) {
    210         // For stores, we need a reserved register. Change
    211         // memw(r30 + #10000) = r0 to:
    212         //
    213         // rs = add(r30, #10000);
    214         // memw(rs) = r0
    215         unsigned resReg = HEXAGON_RESERVED_REG_1;
    216 
    217         // Check if offset can fit in addi.
    218         if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
    219           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    220                   TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
    221           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    222                   TII.get(Hexagon::ADD_rr),
    223                   resReg).addReg(FrameReg).addReg(resReg);
    224         } else {
    225           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    226                   TII.get(Hexagon::ADD_ri),
    227                   resReg).addReg(FrameReg).addImm(Offset);
    228         }
    229         MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
    230         MI.getOperand(i+1).ChangeToImmediate(0);
    231       } else if (TII.isMemOp(&MI)) {
    232         unsigned resReg = HEXAGON_RESERVED_REG_1;
    233         if (!MFI.hasVarSizedObjects() &&
    234             TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
    235           MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false,
    236                                             true);
    237           MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
    238         } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
    239           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    240                   TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
    241           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    242                   TII.get(Hexagon::ADD_rr),
    243                   resReg).addReg(FrameReg).addReg(resReg);
    244           MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
    245           MI.getOperand(i+1).ChangeToImmediate(0);
    246         } else {
    247           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    248                   TII.get(Hexagon::ADD_ri),
    249                   resReg).addReg(FrameReg).addImm(Offset);
    250           MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
    251           MI.getOperand(i+1).ChangeToImmediate(0);
    252         }
    253       } else {
    254         unsigned dstReg = MI.getOperand(0).getReg();
    255         BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    256                 TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
    257         BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    258                 TII.get(Hexagon::ADD_rr),
    259                 dstReg).addReg(FrameReg).addReg(dstReg);
    260         // Can we delete MI??? r2 = add (r2, #0).
    261         MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
    262         MI.getOperand(i+1).ChangeToImmediate(0);
    263       }
    264     } else {
    265       // If the offset is small enough to fit in the immediate field, directly
    266       // encode it.
    267       MI.getOperand(i).ChangeToRegister(FrameReg, false);
    268       MI.getOperand(i+1).ChangeToImmediate(Offset);
    269     }
    270   }
    271 
    272 }
    273 
    274 unsigned HexagonRegisterInfo::getRARegister() const {
    275   return Hexagon::R31;
    276 }
    277 
    278 unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
    279                                                &MF) const {
    280   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
    281   if (TFI->hasFP(MF)) {
    282     return Hexagon::R30;
    283   }
    284 
    285   return Hexagon::R29;
    286 }
    287 
    288 unsigned HexagonRegisterInfo::getFrameRegister() const {
    289   return Hexagon::R30;
    290 }
    291 
    292 unsigned HexagonRegisterInfo::getStackRegister() const {
    293   return Hexagon::R29;
    294 }
    295 
    296 void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove>
    297                                                &Moves)  const
    298 {
    299   // VirtualFP = (R30 + #0).
    300   unsigned FPReg = getFrameRegister();
    301   MachineLocation Dst(MachineLocation::VirtualFP);
    302   MachineLocation Src(FPReg, 0);
    303   Moves.push_back(MachineMove(0, Dst, Src));
    304 }
    305 
    306 unsigned HexagonRegisterInfo::getEHExceptionRegister() const {
    307   llvm_unreachable("What is the exception register");
    308 }
    309 
    310 unsigned HexagonRegisterInfo::getEHHandlerRegister() const {
    311   llvm_unreachable("What is the exception handler register");
    312 }
    313 
    314 #define GET_REGINFO_TARGET_DESC
    315 #include "HexagonGenRegisterInfo.inc"
    316