Home | History | Annotate | Download | only in XCore
      1 //===-- XCoreInstrInfo.cpp - XCore Instruction 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 XCore implementation of the TargetInstrInfo class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "XCoreInstrInfo.h"
     15 #include "XCore.h"
     16 #include "XCoreMachineFunctionInfo.h"
     17 #include "llvm/ADT/STLExtras.h"
     18 #include "llvm/CodeGen/MachineFrameInfo.h"
     19 #include "llvm/CodeGen/MachineInstrBuilder.h"
     20 #include "llvm/MC/MCContext.h"
     21 #include "llvm/Support/Debug.h"
     22 #include "llvm/Support/ErrorHandling.h"
     23 #include "llvm/Support/TargetRegistry.h"
     24 
     25 #define GET_INSTRINFO_CTOR
     26 #include "XCoreGenInstrInfo.inc"
     27 
     28 namespace llvm {
     29 namespace XCore {
     30 
     31   // XCore Condition Codes
     32   enum CondCode {
     33     COND_TRUE,
     34     COND_FALSE,
     35     COND_INVALID
     36   };
     37 }
     38 }
     39 
     40 using namespace llvm;
     41 
     42 XCoreInstrInfo::XCoreInstrInfo()
     43   : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
     44     RI(*this) {
     45 }
     46 
     47 static bool isZeroImm(const MachineOperand &op) {
     48   return op.isImm() && op.getImm() == 0;
     49 }
     50 
     51 /// isLoadFromStackSlot - If the specified machine instruction is a direct
     52 /// load from a stack slot, return the virtual or physical register number of
     53 /// the destination along with the FrameIndex of the loaded stack slot.  If
     54 /// not, return 0.  This predicate must return 0 if the instruction has
     55 /// any side effects other than loading from the stack slot.
     56 unsigned
     57 XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const{
     58   int Opcode = MI->getOpcode();
     59   if (Opcode == XCore::LDWFI)
     60   {
     61     if ((MI->getOperand(1).isFI()) && // is a stack slot
     62         (MI->getOperand(2).isImm()) &&  // the imm is zero
     63         (isZeroImm(MI->getOperand(2))))
     64     {
     65       FrameIndex = MI->getOperand(1).getIndex();
     66       return MI->getOperand(0).getReg();
     67     }
     68   }
     69   return 0;
     70 }
     71 
     72   /// isStoreToStackSlot - If the specified machine instruction is a direct
     73   /// store to a stack slot, return the virtual or physical register number of
     74   /// the source reg along with the FrameIndex of the loaded stack slot.  If
     75   /// not, return 0.  This predicate must return 0 if the instruction has
     76   /// any side effects other than storing to the stack slot.
     77 unsigned
     78 XCoreInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
     79                                    int &FrameIndex) const {
     80   int Opcode = MI->getOpcode();
     81   if (Opcode == XCore::STWFI)
     82   {
     83     if ((MI->getOperand(1).isFI()) && // is a stack slot
     84         (MI->getOperand(2).isImm()) &&  // the imm is zero
     85         (isZeroImm(MI->getOperand(2))))
     86     {
     87       FrameIndex = MI->getOperand(1).getIndex();
     88       return MI->getOperand(0).getReg();
     89     }
     90   }
     91   return 0;
     92 }
     93 
     94 //===----------------------------------------------------------------------===//
     95 // Branch Analysis
     96 //===----------------------------------------------------------------------===//
     97 
     98 static inline bool IsBRU(unsigned BrOpc) {
     99   return BrOpc == XCore::BRFU_u6
    100       || BrOpc == XCore::BRFU_lu6
    101       || BrOpc == XCore::BRBU_u6
    102       || BrOpc == XCore::BRBU_lu6;
    103 }
    104 
    105 static inline bool IsBRT(unsigned BrOpc) {
    106   return BrOpc == XCore::BRFT_ru6
    107       || BrOpc == XCore::BRFT_lru6
    108       || BrOpc == XCore::BRBT_ru6
    109       || BrOpc == XCore::BRBT_lru6;
    110 }
    111 
    112 static inline bool IsBRF(unsigned BrOpc) {
    113   return BrOpc == XCore::BRFF_ru6
    114       || BrOpc == XCore::BRFF_lru6
    115       || BrOpc == XCore::BRBF_ru6
    116       || BrOpc == XCore::BRBF_lru6;
    117 }
    118 
    119 static inline bool IsCondBranch(unsigned BrOpc) {
    120   return IsBRF(BrOpc) || IsBRT(BrOpc);
    121 }
    122 
    123 static inline bool IsBR_JT(unsigned BrOpc) {
    124   return BrOpc == XCore::BR_JT
    125       || BrOpc == XCore::BR_JT32;
    126 }
    127 
    128 /// GetCondFromBranchOpc - Return the XCore CC that matches
    129 /// the correspondent Branch instruction opcode.
    130 static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
    131 {
    132   if (IsBRT(BrOpc)) {
    133     return XCore::COND_TRUE;
    134   } else if (IsBRF(BrOpc)) {
    135     return XCore::COND_FALSE;
    136   } else {
    137     return XCore::COND_INVALID;
    138   }
    139 }
    140 
    141 /// GetCondBranchFromCond - Return the Branch instruction
    142 /// opcode that matches the cc.
    143 static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
    144 {
    145   switch (CC) {
    146   default: llvm_unreachable("Illegal condition code!");
    147   case XCore::COND_TRUE   : return XCore::BRFT_lru6;
    148   case XCore::COND_FALSE  : return XCore::BRFF_lru6;
    149   }
    150 }
    151 
    152 /// GetOppositeBranchCondition - Return the inverse of the specified
    153 /// condition, e.g. turning COND_E to COND_NE.
    154 static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
    155 {
    156   switch (CC) {
    157   default: llvm_unreachable("Illegal condition code!");
    158   case XCore::COND_TRUE   : return XCore::COND_FALSE;
    159   case XCore::COND_FALSE  : return XCore::COND_TRUE;
    160   }
    161 }
    162 
    163 /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
    164 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
    165 /// implemented for a target).  Upon success, this returns false and returns
    166 /// with the following information in various cases:
    167 ///
    168 /// 1. If this block ends with no branches (it just falls through to its succ)
    169 ///    just return false, leaving TBB/FBB null.
    170 /// 2. If this block ends with only an unconditional branch, it sets TBB to be
    171 ///    the destination block.
    172 /// 3. If this block ends with an conditional branch and it falls through to
    173 ///    an successor block, it sets TBB to be the branch destination block and a
    174 ///    list of operands that evaluate the condition. These
    175 ///    operands can be passed to other TargetInstrInfo methods to create new
    176 ///    branches.
    177 /// 4. If this block ends with an conditional branch and an unconditional
    178 ///    block, it returns the 'true' destination in TBB, the 'false' destination
    179 ///    in FBB, and a list of operands that evaluate the condition. These
    180 ///    operands can be passed to other TargetInstrInfo methods to create new
    181 ///    branches.
    182 ///
    183 /// Note that RemoveBranch and InsertBranch must be implemented to support
    184 /// cases where this method returns success.
    185 ///
    186 bool
    187 XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
    188                               MachineBasicBlock *&FBB,
    189                               SmallVectorImpl<MachineOperand> &Cond,
    190                               bool AllowModify) const {
    191   // If the block has no terminators, it just falls into the block after it.
    192   MachineBasicBlock::iterator I = MBB.end();
    193   if (I == MBB.begin())
    194     return false;
    195   --I;
    196   while (I->isDebugValue()) {
    197     if (I == MBB.begin())
    198       return false;
    199     --I;
    200   }
    201   if (!isUnpredicatedTerminator(I))
    202     return false;
    203 
    204   // Get the last instruction in the block.
    205   MachineInstr *LastInst = I;
    206 
    207   // If there is only one terminator instruction, process it.
    208   if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
    209     if (IsBRU(LastInst->getOpcode())) {
    210       TBB = LastInst->getOperand(0).getMBB();
    211       return false;
    212     }
    213 
    214     XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
    215     if (BranchCode == XCore::COND_INVALID)
    216       return true;  // Can't handle indirect branch.
    217 
    218     // Conditional branch
    219     // Block ends with fall-through condbranch.
    220 
    221     TBB = LastInst->getOperand(1).getMBB();
    222     Cond.push_back(MachineOperand::CreateImm(BranchCode));
    223     Cond.push_back(LastInst->getOperand(0));
    224     return false;
    225   }
    226 
    227   // Get the instruction before it if it's a terminator.
    228   MachineInstr *SecondLastInst = I;
    229 
    230   // If there are three terminators, we don't know what sort of block this is.
    231   if (SecondLastInst && I != MBB.begin() &&
    232       isUnpredicatedTerminator(--I))
    233     return true;
    234 
    235   unsigned SecondLastOpc    = SecondLastInst->getOpcode();
    236   XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
    237 
    238   // If the block ends with conditional branch followed by unconditional,
    239   // handle it.
    240   if (BranchCode != XCore::COND_INVALID
    241     && IsBRU(LastInst->getOpcode())) {
    242 
    243     TBB = SecondLastInst->getOperand(1).getMBB();
    244     Cond.push_back(MachineOperand::CreateImm(BranchCode));
    245     Cond.push_back(SecondLastInst->getOperand(0));
    246 
    247     FBB = LastInst->getOperand(0).getMBB();
    248     return false;
    249   }
    250 
    251   // If the block ends with two unconditional branches, handle it.  The second
    252   // one is not executed, so remove it.
    253   if (IsBRU(SecondLastInst->getOpcode()) &&
    254       IsBRU(LastInst->getOpcode())) {
    255     TBB = SecondLastInst->getOperand(0).getMBB();
    256     I = LastInst;
    257     if (AllowModify)
    258       I->eraseFromParent();
    259     return false;
    260   }
    261 
    262   // Likewise if it ends with a branch table followed by an unconditional branch.
    263   if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
    264     I = LastInst;
    265     if (AllowModify)
    266       I->eraseFromParent();
    267     return true;
    268   }
    269 
    270   // Otherwise, can't handle this.
    271   return true;
    272 }
    273 
    274 unsigned
    275 XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
    276                              MachineBasicBlock *FBB,
    277                              const SmallVectorImpl<MachineOperand> &Cond,
    278                              DebugLoc DL)const{
    279   // Shouldn't be a fall through.
    280   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
    281   assert((Cond.size() == 2 || Cond.size() == 0) &&
    282          "Unexpected number of components!");
    283 
    284   if (FBB == 0) { // One way branch.
    285     if (Cond.empty()) {
    286       // Unconditional branch
    287       BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
    288     } else {
    289       // Conditional branch.
    290       unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
    291       BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
    292                              .addMBB(TBB);
    293     }
    294     return 1;
    295   }
    296 
    297   // Two-way Conditional branch.
    298   assert(Cond.size() == 2 && "Unexpected number of components!");
    299   unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
    300   BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
    301                          .addMBB(TBB);
    302   BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
    303   return 2;
    304 }
    305 
    306 unsigned
    307 XCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
    308   MachineBasicBlock::iterator I = MBB.end();
    309   if (I == MBB.begin()) return 0;
    310   --I;
    311   while (I->isDebugValue()) {
    312     if (I == MBB.begin())
    313       return 0;
    314     --I;
    315   }
    316   if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
    317     return 0;
    318 
    319   // Remove the branch.
    320   I->eraseFromParent();
    321 
    322   I = MBB.end();
    323 
    324   if (I == MBB.begin()) return 1;
    325   --I;
    326   if (!IsCondBranch(I->getOpcode()))
    327     return 1;
    328 
    329   // Remove the branch.
    330   I->eraseFromParent();
    331   return 2;
    332 }
    333 
    334 void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
    335                                  MachineBasicBlock::iterator I, DebugLoc DL,
    336                                  unsigned DestReg, unsigned SrcReg,
    337                                  bool KillSrc) const {
    338   bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
    339   bool GRSrc  = XCore::GRRegsRegClass.contains(SrcReg);
    340 
    341   if (GRDest && GRSrc) {
    342     BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
    343       .addReg(SrcReg, getKillRegState(KillSrc))
    344       .addImm(0);
    345     return;
    346   }
    347 
    348   if (GRDest && SrcReg == XCore::SP) {
    349     BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
    350     return;
    351   }
    352 
    353   if (DestReg == XCore::SP && GRSrc) {
    354     BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
    355       .addReg(SrcReg, getKillRegState(KillSrc));
    356     return;
    357   }
    358   llvm_unreachable("Impossible reg-to-reg copy");
    359 }
    360 
    361 void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
    362                                          MachineBasicBlock::iterator I,
    363                                          unsigned SrcReg, bool isKill,
    364                                          int FrameIndex,
    365                                          const TargetRegisterClass *RC,
    366                                          const TargetRegisterInfo *TRI) const
    367 {
    368   DebugLoc DL;
    369   if (I != MBB.end()) DL = I->getDebugLoc();
    370   BuildMI(MBB, I, DL, get(XCore::STWFI))
    371     .addReg(SrcReg, getKillRegState(isKill))
    372     .addFrameIndex(FrameIndex)
    373     .addImm(0);
    374 }
    375 
    376 void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
    377                                           MachineBasicBlock::iterator I,
    378                                           unsigned DestReg, int FrameIndex,
    379                                           const TargetRegisterClass *RC,
    380                                           const TargetRegisterInfo *TRI) const
    381 {
    382   DebugLoc DL;
    383   if (I != MBB.end()) DL = I->getDebugLoc();
    384   BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
    385     .addFrameIndex(FrameIndex)
    386     .addImm(0);
    387 }
    388 
    389 MachineInstr*
    390 XCoreInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx,
    391                                          uint64_t Offset, const MDNode *MDPtr,
    392                                          DebugLoc DL) const {
    393   MachineInstrBuilder MIB = BuildMI(MF, DL, get(XCore::DBG_VALUE))
    394     .addFrameIndex(FrameIx).addImm(0).addImm(Offset).addMetadata(MDPtr);
    395   return &*MIB;
    396 }
    397 
    398 /// ReverseBranchCondition - Return the inverse opcode of the
    399 /// specified Branch instruction.
    400 bool XCoreInstrInfo::
    401 ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
    402   assert((Cond.size() == 2) &&
    403           "Invalid XCore branch condition!");
    404   Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
    405   return false;
    406 }
    407