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 "HexagonMachineFunctionInfo.h"
     18 #include "HexagonSubtarget.h"
     19 #include "HexagonTargetMachine.h"
     20 #include "llvm/ADT/BitVector.h"
     21 #include "llvm/ADT/STLExtras.h"
     22 #include "llvm/CodeGen/MachineFrameInfo.h"
     23 #include "llvm/CodeGen/MachineFunction.h"
     24 #include "llvm/CodeGen/MachineFunctionPass.h"
     25 #include "llvm/CodeGen/MachineInstrBuilder.h"
     26 #include "llvm/CodeGen/MachineRegisterInfo.h"
     27 #include "llvm/CodeGen/PseudoSourceValue.h"
     28 #include "llvm/CodeGen/RegisterScavenging.h"
     29 #include "llvm/IR/Function.h"
     30 #include "llvm/IR/Type.h"
     31 #include "llvm/MC/MachineLocation.h"
     32 #include "llvm/Support/CommandLine.h"
     33 #include "llvm/Support/ErrorHandling.h"
     34 #include "llvm/Target/TargetInstrInfo.h"
     35 #include "llvm/Target/TargetMachine.h"
     36 #include "llvm/Target/TargetOptions.h"
     37 
     38 using namespace llvm;
     39 
     40 
     41 HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st)
     42   : HexagonGenRegisterInfo(Hexagon::R31),
     43     Subtarget(st) {
     44 }
     45 
     46 const MCPhysReg *
     47 HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
     48   static const MCPhysReg CalleeSavedRegsV2[] = {
     49     Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
     50   };
     51   static const MCPhysReg CalleeSavedRegsV3[] = {
     52     Hexagon::R16,   Hexagon::R17,   Hexagon::R18,   Hexagon::R19,
     53     Hexagon::R20,   Hexagon::R21,   Hexagon::R22,   Hexagon::R23,
     54     Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
     55   };
     56 
     57   switch(Subtarget.getHexagonArchVersion()) {
     58   case HexagonSubtarget::V1:
     59     break;
     60   case HexagonSubtarget::V2:
     61     return CalleeSavedRegsV2;
     62   case HexagonSubtarget::V3:
     63   case HexagonSubtarget::V4:
     64   case HexagonSubtarget::V5:
     65     return CalleeSavedRegsV3;
     66   }
     67   llvm_unreachable("Callee saved registers requested for unknown architecture "
     68                    "version");
     69 }
     70 
     71 BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
     72   const {
     73   BitVector Reserved(getNumRegs());
     74   Reserved.set(HEXAGON_RESERVED_REG_1);
     75   Reserved.set(HEXAGON_RESERVED_REG_2);
     76   Reserved.set(Hexagon::R29);
     77   Reserved.set(Hexagon::R30);
     78   Reserved.set(Hexagon::R31);
     79   Reserved.set(Hexagon::D14);
     80   Reserved.set(Hexagon::D15);
     81   Reserved.set(Hexagon::LC0);
     82   Reserved.set(Hexagon::LC1);
     83   Reserved.set(Hexagon::SA0);
     84   Reserved.set(Hexagon::SA1);
     85   return Reserved;
     86 }
     87 
     88 
     89 const TargetRegisterClass* const*
     90 HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
     91   static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = {
     92     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
     93     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
     94     };
     95   static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
     96     &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
     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   };
    103 
    104   switch(Subtarget.getHexagonArchVersion()) {
    105   case HexagonSubtarget::V1:
    106     break;
    107   case HexagonSubtarget::V2:
    108     return CalleeSavedRegClassesV2;
    109   case HexagonSubtarget::V3:
    110   case HexagonSubtarget::V4:
    111   case HexagonSubtarget::V5:
    112     return CalleeSavedRegClassesV3;
    113   }
    114   llvm_unreachable("Callee saved register classes requested for unknown "
    115                    "architecture version");
    116 }
    117 
    118 void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
    119                                               int SPAdj, unsigned FIOperandNum,
    120                                               RegScavenger *RS) const {
    121   //
    122   // Hexagon_TODO: Do we need to enforce this for Hexagon?
    123   assert(SPAdj == 0 && "Unexpected");
    124 
    125   MachineInstr &MI = *II;
    126   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
    127 
    128   // Addressable stack objects are accessed using neg. offsets from %fp.
    129   MachineFunction &MF = *MI.getParent()->getParent();
    130   const HexagonInstrInfo &TII =
    131     *static_cast<const HexagonInstrInfo*>(MF.getTarget().getInstrInfo());
    132   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
    133   MachineFrameInfo &MFI = *MF.getFrameInfo();
    134 
    135   unsigned FrameReg = getFrameRegister(MF);
    136   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
    137   if (!TFI->hasFP(MF)) {
    138     // We will not reserve space on the stack for the lr and fp registers.
    139     Offset -= 2 * Hexagon_WordSize;
    140   }
    141 
    142   const unsigned FrameSize = MFI.getStackSize();
    143 
    144   if (!MFI.hasVarSizedObjects() &&
    145       TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
    146       !TII.isSpillPredRegOp(&MI)) {
    147     // Replace frame index with a stack pointer reference.
    148     MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), false,
    149                                                  false, true);
    150     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(FrameSize+Offset);
    151   } else {
    152     // Replace frame index with a frame pointer reference.
    153     if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
    154 
    155       // If the offset overflows, then correct it.
    156       //
    157       // For loads, we do not need a reserved register
    158       // r0 = memw(r30 + #10000) to:
    159       //
    160       // r0 = add(r30, #10000)
    161       // r0 = memw(r0)
    162       if ( (MI.getOpcode() == Hexagon::LDriw)  ||
    163            (MI.getOpcode() == Hexagon::LDrid)   ||
    164            (MI.getOpcode() == Hexagon::LDrih)   ||
    165            (MI.getOpcode() == Hexagon::LDriuh)  ||
    166            (MI.getOpcode() == Hexagon::LDrib)   ||
    167            (MI.getOpcode() == Hexagon::LDriub)  ||
    168            (MI.getOpcode() == Hexagon::LDriw_f) ||
    169            (MI.getOpcode() == Hexagon::LDrid_f)) {
    170         unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
    171           getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) :
    172           MI.getOperand(0).getReg();
    173 
    174         // Check if offset can fit in addi.
    175         if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
    176           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    177                   TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
    178           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    179                   TII.get(Hexagon::ADD_rr),
    180                   dstReg).addReg(FrameReg).addReg(dstReg);
    181         } else {
    182           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    183                   TII.get(Hexagon::ADD_ri),
    184                   dstReg).addReg(FrameReg).addImm(Offset);
    185         }
    186 
    187         MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
    188         MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
    189       } else if ((MI.getOpcode() == Hexagon::STriw_indexed) ||
    190                  (MI.getOpcode() == Hexagon::STriw) ||
    191                  (MI.getOpcode() == Hexagon::STrid) ||
    192                  (MI.getOpcode() == Hexagon::STrih) ||
    193                  (MI.getOpcode() == Hexagon::STrib) ||
    194                  (MI.getOpcode() == Hexagon::STrid_f) ||
    195                  (MI.getOpcode() == Hexagon::STriw_f)) {
    196         // For stores, we need a reserved register. Change
    197         // memw(r30 + #10000) = r0 to:
    198         //
    199         // rs = add(r30, #10000);
    200         // memw(rs) = r0
    201         unsigned resReg = HEXAGON_RESERVED_REG_1;
    202 
    203         // Check if offset can fit in addi.
    204         if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
    205           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    206                   TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
    207           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    208                   TII.get(Hexagon::ADD_rr),
    209                   resReg).addReg(FrameReg).addReg(resReg);
    210         } else {
    211           BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    212                   TII.get(Hexagon::ADD_ri),
    213                   resReg).addReg(FrameReg).addImm(Offset);
    214         }
    215         MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,true);
    216         MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
    217       } else if (TII.isMemOp(&MI)) {
    218         // use the constant extender if the instruction provides it
    219         // and we are V4TOps.
    220         if (Subtarget.hasV4TOps()) {
    221           if (TII.isConstExtended(&MI)) {
    222             MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
    223             MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
    224             TII.immediateExtend(&MI);
    225           } else {
    226             llvm_unreachable("Need to implement for memops");
    227           }
    228         } else {
    229           // Only V3 and older instructions here.
    230           unsigned ResReg = HEXAGON_RESERVED_REG_1;
    231           if (!MFI.hasVarSizedObjects() &&
    232               TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
    233             MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(),
    234                                                          false, false, false);
    235             MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset);
    236           } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
    237             BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    238                     TII.get(Hexagon::CONST32_Int_Real), ResReg).addImm(Offset);
    239             BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    240                     TII.get(Hexagon::ADD_rr), ResReg).addReg(FrameReg).
    241               addReg(ResReg);
    242             MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
    243                                                          true);
    244             MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
    245           } else {
    246             BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    247                     TII.get(Hexagon::ADD_ri), ResReg).addReg(FrameReg).
    248               addImm(Offset);
    249             MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
    250                                                          true);
    251             MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
    252           }
    253         }
    254       } else {
    255         unsigned dstReg = MI.getOperand(0).getReg();
    256         BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    257                 TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
    258         BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
    259                 TII.get(Hexagon::ADD_rr),
    260                 dstReg).addReg(FrameReg).addReg(dstReg);
    261         // Can we delete MI??? r2 = add (r2, #0).
    262         MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
    263         MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
    264       }
    265     } else {
    266       // If the offset is small enough to fit in the immediate field, directly
    267       // encode it.
    268       MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
    269       MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
    270     }
    271   }
    272 
    273 }
    274 
    275 unsigned HexagonRegisterInfo::getRARegister() const {
    276   return Hexagon::R31;
    277 }
    278 
    279 unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
    280                                                &MF) const {
    281   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
    282   if (TFI->hasFP(MF)) {
    283     return Hexagon::R30;
    284   }
    285 
    286   return Hexagon::R29;
    287 }
    288 
    289 unsigned HexagonRegisterInfo::getFrameRegister() const {
    290   return Hexagon::R30;
    291 }
    292 
    293 unsigned HexagonRegisterInfo::getStackRegister() const {
    294   return Hexagon::R29;
    295 }
    296 
    297 #define GET_REGINFO_TARGET_DESC
    298 #include "HexagonGenRegisterInfo.inc"
    299