LLVM API Documentation

XCoreInstrInfo.cpp

Go to the documentation of this file.
00001 //===- XCoreInstrInfo.cpp - XCore Instruction Information -------*- C++ -*-===//
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 TargetInstrInfo class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "XCoreMachineFunctionInfo.h"
00015 #include "XCoreInstrInfo.h"
00016 #include "XCore.h"
00017 #include "llvm/ADT/STLExtras.h"
00018 #include "llvm/CodeGen/MachineInstrBuilder.h"
00019 #include "llvm/CodeGen/MachineFrameInfo.h"
00020 #include "llvm/CodeGen/MachineLocation.h"
00021 #include "llvm/CodeGen/MachineModuleInfo.h"
00022 #include "XCoreGenInstrInfo.inc"
00023 #include "llvm/Support/Debug.h"
00024 
00025 namespace llvm {
00026 namespace XCore {
00027 
00028   // XCore Condition Codes
00029   enum CondCode {
00030     COND_TRUE,
00031     COND_FALSE,
00032     COND_INVALID
00033   };
00034 }
00035 }
00036 
00037 using namespace llvm;
00038 
00039 XCoreInstrInfo::XCoreInstrInfo(void)
00040   : TargetInstrInfoImpl(XCoreInsts, array_lengthof(XCoreInsts)),
00041     RI(*this) {
00042 }
00043 
00044 static bool isZeroImm(const MachineOperand &op) {
00045   return op.isImm() && op.getImm() == 0;
00046 }
00047 
00048 /// Return true if the instruction is a register to register move and
00049 /// leave the source and dest operands in the passed parameters.
00050 ///
00051 bool XCoreInstrInfo::isMoveInstr(const MachineInstr &MI,
00052                                  unsigned &SrcReg, unsigned &DstReg,
00053                                  unsigned &SrcSR, unsigned &DstSR) const {
00054   SrcSR = DstSR = 0; // No sub-registers.
00055 
00056   // We look for 4 kinds of patterns here:
00057   // add dst, src, 0
00058   // sub dst, src, 0
00059   // or dst, src, src
00060   // and dst, src, src
00061   if ((MI.getOpcode() == XCore::ADD_2rus || MI.getOpcode() == XCore::SUB_2rus)
00062       && isZeroImm(MI.getOperand(2))) {
00063     DstReg = MI.getOperand(0).getReg();
00064     SrcReg = MI.getOperand(1).getReg();
00065     return true;
00066   } else if ((MI.getOpcode() == XCore::OR_3r || MI.getOpcode() == XCore::AND_3r)
00067       && MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
00068     DstReg = MI.getOperand(0).getReg();
00069     SrcReg = MI.getOperand(1).getReg();
00070     return true;
00071   }
00072   return false;
00073 }
00074 
00075 /// isLoadFromStackSlot - If the specified machine instruction is a direct
00076 /// load from a stack slot, return the virtual or physical register number of
00077 /// the destination along with the FrameIndex of the loaded stack slot.  If
00078 /// not, return 0.  This predicate must return 0 if the instruction has
00079 /// any side effects other than loading from the stack slot.
00080 unsigned
00081 XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const{
00082   int Opcode = MI->getOpcode();
00083   if (Opcode == XCore::LDWFI) 
00084   {
00085     if ((MI->getOperand(1).isFI()) && // is a stack slot
00086         (MI->getOperand(2).isImm()) &&  // the imm is zero
00087         (isZeroImm(MI->getOperand(2)))) 
00088     {
00089       FrameIndex = MI->getOperand(1).getIndex();
00090       return MI->getOperand(0).getReg();
00091     }
00092   }
00093   return 0;
00094 }
00095   
00096   /// isStoreToStackSlot - If the specified machine instruction is a direct
00097   /// store to a stack slot, return the virtual or physical register number of
00098   /// the source reg along with the FrameIndex of the loaded stack slot.  If
00099   /// not, return 0.  This predicate must return 0 if the instruction has
00100   /// any side effects other than storing to the stack slot.
00101 unsigned
00102 XCoreInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
00103                                    int &FrameIndex) const {
00104   int Opcode = MI->getOpcode();
00105   if (Opcode == XCore::STWFI)
00106   {
00107     if ((MI->getOperand(1).isFI()) && // is a stack slot
00108         (MI->getOperand(2).isImm()) &&  // the imm is zero
00109         (isZeroImm(MI->getOperand(2))))
00110     {
00111       FrameIndex = MI->getOperand(1).getIndex();
00112       return MI->getOperand(0).getReg();
00113     }
00114   }
00115   return 0;
00116 }
00117 
00118 /// isInvariantLoad - Return true if the specified instruction (which is marked
00119 /// mayLoad) is loading from a location whose value is invariant across the
00120 /// function.  For example, loading a value from the constant pool or from
00121 /// from the argument area of a function if it does not change.  This should
00122 /// only return true of *all* loads the instruction does are invariant (if it
00123 /// does multiple loads).
00124 bool
00125 XCoreInstrInfo::isInvariantLoad(const MachineInstr *MI) const {
00126   // Loads from constants pools and loads from invariant argument slots are
00127   // invariant
00128   int Opcode = MI->getOpcode();
00129   if (Opcode == XCore::LDWCP_ru6 || Opcode == XCore::LDWCP_lru6) {
00130     return MI->getOperand(1).isCPI();
00131   }
00132   int FrameIndex;
00133   if (isLoadFromStackSlot(MI, FrameIndex)) {
00134     const MachineFrameInfo &MFI =
00135       *MI->getParent()->getParent()->getFrameInfo();
00136     return MFI.isFixedObjectIndex(FrameIndex) &&
00137            MFI.isImmutableObjectIndex(FrameIndex);
00138   }
00139   return false;
00140 }
00141 
00142 //===----------------------------------------------------------------------===//
00143 // Branch Analysis
00144 //===----------------------------------------------------------------------===//
00145 
00146 static inline bool IsBRU(unsigned BrOpc) {
00147   return BrOpc == XCore::BRFU_u6
00148       || BrOpc == XCore::BRFU_lu6
00149       || BrOpc == XCore::BRBU_u6
00150       || BrOpc == XCore::BRBU_lu6;
00151 }
00152 
00153 static inline bool IsBRT(unsigned BrOpc) {
00154   return BrOpc == XCore::BRFT_ru6
00155       || BrOpc == XCore::BRFT_lru6
00156       || BrOpc == XCore::BRBT_ru6
00157       || BrOpc == XCore::BRBT_lru6;
00158 }
00159 
00160 static inline bool IsBRF(unsigned BrOpc) {
00161   return BrOpc == XCore::BRFF_ru6
00162       || BrOpc == XCore::BRFF_lru6
00163       || BrOpc == XCore::BRBF_ru6
00164       || BrOpc == XCore::BRBF_lru6;
00165 }
00166 
00167 static inline bool IsCondBranch(unsigned BrOpc) {
00168   return IsBRF(BrOpc) || IsBRT(BrOpc);
00169 }
00170 
00171 /// GetCondFromBranchOpc - Return the XCore CC that matches 
00172 /// the correspondent Branch instruction opcode.
00173 static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc) 
00174 {
00175   if (IsBRT(BrOpc)) {
00176     return XCore::COND_TRUE;
00177   } else if (IsBRF(BrOpc)) {
00178     return XCore::COND_FALSE;
00179   } else {
00180     return XCore::COND_INVALID;
00181   }
00182 }
00183 
00184 /// GetCondBranchFromCond - Return the Branch instruction
00185 /// opcode that matches the cc.
00186 static inline unsigned GetCondBranchFromCond(XCore::CondCode CC) 
00187 {
00188   switch (CC) {
00189   default: assert(0 && "Illegal condition code!");
00190   case XCore::COND_TRUE   : return XCore::BRFT_lru6;
00191   case XCore::COND_FALSE  : return XCore::BRFF_lru6;
00192   }
00193 }
00194 
00195 /// GetOppositeBranchCondition - Return the inverse of the specified 
00196 /// condition, e.g. turning COND_E to COND_NE.
00197 static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
00198 {
00199   switch (CC) {
00200   default: assert(0 && "Illegal condition code!");
00201   case XCore::COND_TRUE   : return XCore::COND_FALSE;
00202   case XCore::COND_FALSE  : return XCore::COND_TRUE;
00203   }
00204 }
00205 
00206 /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
00207 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
00208 /// implemented for a target).  Upon success, this returns false and returns
00209 /// with the following information in various cases:
00210 ///
00211 /// 1. If this block ends with no branches (it just falls through to its succ)
00212 ///    just return false, leaving TBB/FBB null.
00213 /// 2. If this block ends with only an unconditional branch, it sets TBB to be
00214 ///    the destination block.
00215 /// 3. If this block ends with an conditional branch and it falls through to
00216 ///    an successor block, it sets TBB to be the branch destination block and a
00217 ///    list of operands that evaluate the condition. These
00218 ///    operands can be passed to other TargetInstrInfo methods to create new
00219 ///    branches.
00220 /// 4. If this block ends with an conditional branch and an unconditional
00221 ///    block, it returns the 'true' destination in TBB, the 'false' destination
00222 ///    in FBB, and a list of operands that evaluate the condition. These
00223 ///    operands can be passed to other TargetInstrInfo methods to create new
00224 ///    branches.
00225 ///
00226 /// Note that RemoveBranch and InsertBranch must be implemented to support
00227 /// cases where this method returns success.
00228 ///
00229 bool
00230 XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
00231                               MachineBasicBlock *&FBB,
00232                               SmallVectorImpl<MachineOperand> &Cond,
00233                               bool AllowModify) const {
00234   // If the block has no terminators, it just falls into the block after it.
00235   MachineBasicBlock::iterator I = MBB.end();
00236   if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
00237     return false;
00238 
00239   // Get the last instruction in the block.
00240   MachineInstr *LastInst = I;
00241   
00242   // If there is only one terminator instruction, process it.
00243   if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
00244     if (IsBRU(LastInst->getOpcode())) {
00245       TBB = LastInst->getOperand(0).getMBB();
00246       return false;
00247     }
00248     
00249     XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
00250     if (BranchCode == XCore::COND_INVALID)
00251       return true;  // Can't handle indirect branch.
00252     
00253     // Conditional branch
00254     // Block ends with fall-through condbranch.
00255 
00256     TBB = LastInst->getOperand(1).getMBB();
00257     Cond.push_back(MachineOperand::CreateImm(BranchCode));
00258     Cond.push_back(LastInst->getOperand(0));
00259     return false;
00260   }
00261   
00262   // Get the instruction before it if it's a terminator.
00263   MachineInstr *SecondLastInst = I;
00264 
00265   // If there are three terminators, we don't know what sort of block this is.
00266   if (SecondLastInst && I != MBB.begin() &&
00267       isUnpredicatedTerminator(--I))
00268     return true;
00269   
00270   unsigned SecondLastOpc    = SecondLastInst->getOpcode();
00271   XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
00272   
00273   // If the block ends with conditional branch followed by unconditional,
00274   // handle it.
00275   if (BranchCode != XCore::COND_INVALID
00276     && IsBRU(LastInst->getOpcode())) {
00277 
00278     TBB = SecondLastInst->getOperand(1).getMBB();
00279     Cond.push_back(MachineOperand::CreateImm(BranchCode));
00280     Cond.push_back(SecondLastInst->getOperand(0));
00281 
00282     FBB = LastInst->getOperand(0).getMBB();
00283     return false;
00284   }
00285   
00286   // If the block ends with two unconditional branches, handle it.  The second
00287   // one is not executed, so remove it.
00288   if (IsBRU(SecondLastInst->getOpcode()) && 
00289       IsBRU(LastInst->getOpcode())) {
00290     TBB = SecondLastInst->getOperand(0).getMBB();
00291     I = LastInst;
00292     if (AllowModify)
00293       I->eraseFromParent();
00294     return false;
00295   }
00296 
00297   // Otherwise, can't handle this.
00298   return true;
00299 }
00300 
00301 unsigned
00302 XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
00303                              MachineBasicBlock *FBB,
00304                              const SmallVectorImpl<MachineOperand> &Cond)const{
00305   // Shouldn't be a fall through.
00306   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
00307   assert((Cond.size() == 2 || Cond.size() == 0) &&
00308          "Unexpected number of components!");
00309   
00310   if (FBB == 0) { // One way branch.
00311     if (Cond.empty()) {
00312       // Unconditional branch
00313       BuildMI(&MBB, get(XCore::BRFU_lu6)).addMBB(TBB);
00314     } else {
00315       // Conditional branch.
00316       unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
00317       BuildMI(&MBB, get(Opc)).addReg(Cond[1].getReg())
00318                              .addMBB(TBB);
00319     }
00320     return 1;
00321   }
00322   
00323   // Two-way Conditional branch.
00324   assert(Cond.size() == 2 && "Unexpected number of components!");
00325   unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
00326   BuildMI(&MBB, get(Opc)).addReg(Cond[1].getReg())
00327                          .addMBB(TBB);
00328   BuildMI(&MBB, get(XCore::BRFU_lu6)).addMBB(FBB);
00329   return 2;
00330 }
00331 
00332 unsigned
00333 XCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
00334   MachineBasicBlock::iterator I = MBB.end();
00335   if (I == MBB.begin()) return 0;
00336   --I;
00337   if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
00338     return 0;
00339   
00340   // Remove the branch.
00341   I->eraseFromParent();
00342   
00343   I = MBB.end();
00344 
00345   if (I == MBB.begin()) return 1;
00346   --I;
00347   if (!IsCondBranch(I->getOpcode()))
00348     return 1;
00349   
00350   // Remove the branch.
00351   I->eraseFromParent();
00352   return 2;
00353 }
00354 
00355 bool XCoreInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
00356                                      MachineBasicBlock::iterator I,
00357                                      unsigned DestReg, unsigned SrcReg,
00358                                      const TargetRegisterClass *DestRC,
00359                                      const TargetRegisterClass *SrcRC) const {
00360   if (DestRC == SrcRC) {
00361     if (DestRC == XCore::GRRegsRegisterClass) {
00362       BuildMI(MBB, I, get(XCore::ADD_2rus), DestReg).addReg(SrcReg).addImm(0);
00363       return true;
00364     } else {
00365       return false;
00366     }
00367   }
00368   
00369   if (SrcRC == XCore::RRegsRegisterClass && SrcReg == XCore::SP &&
00370     DestRC == XCore::GRRegsRegisterClass) {
00371     BuildMI(MBB, I, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
00372     return true;
00373   }
00374   if (DestRC == XCore::RRegsRegisterClass && DestReg == XCore::SP &&
00375     SrcRC == XCore::GRRegsRegisterClass) {
00376     BuildMI(MBB, I, get(XCore::SETSP_1r)).addReg(SrcReg);
00377     return true;
00378   }
00379   return false;
00380 }
00381 
00382 void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
00383                                   MachineBasicBlock::iterator I,
00384                                   unsigned SrcReg, bool isKill, int FrameIndex,
00385                                   const TargetRegisterClass *RC) const
00386 {
00387   BuildMI(MBB, I, get(XCore::STWFI)).addReg(SrcReg, false, false, isKill)
00388                                     .addFrameIndex(FrameIndex).addImm(0);
00389 }
00390 
00391 void XCoreInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
00392                             bool isKill, SmallVectorImpl<MachineOperand> &Addr,
00393                             const TargetRegisterClass *RC,
00394                             SmallVectorImpl<MachineInstr*> &NewMIs) const
00395 {
00396   assert(0 && "unimplemented\n");
00397 }
00398 
00399 void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
00400                                   MachineBasicBlock::iterator I,
00401                                   unsigned DestReg, int FrameIndex,
00402                                   const TargetRegisterClass *RC) const
00403 {
00404   BuildMI(MBB, I, get(XCore::LDWFI), DestReg).addFrameIndex(FrameIndex)
00405                                              .addImm(0);
00406 }
00407 
00408 void XCoreInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
00409                               SmallVectorImpl<MachineOperand> &Addr,
00410                               const TargetRegisterClass *RC,
00411                               SmallVectorImpl<MachineInstr*> &NewMIs) const
00412 {
00413   assert(0 && "unimplemented\n");
00414 }
00415 
00416 bool XCoreInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
00417         MachineBasicBlock::iterator MI,
00418       const std::vector<CalleeSavedInfo> &CSI) const
00419 {
00420   if (CSI.empty()) {
00421     return true;
00422   }
00423   MachineFunction *MF = MBB.getParent();
00424   const MachineFrameInfo *MFI = MF->getFrameInfo();
00425   MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
00426   XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
00427   
00428   bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
00429   
00430   for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
00431                                                     it != CSI.end(); ++it) {
00432     // Add the callee-saved register as live-in. It's killed at the spill.
00433     MBB.addLiveIn(it->getReg());
00434 
00435     storeRegToStackSlot(MBB, MI, it->getReg(), true,
00436                                    it->getFrameIdx(), it->getRegClass());
00437     if (emitFrameMoves) {
00438       unsigned SaveLabelId = MMI->NextLabelID();
00439       BuildMI(MBB, MI, get(XCore::DBG_LABEL)).addImm(SaveLabelId);
00440       XFI->getSpillLabels().push_back(
00441           std::pair<unsigned, CalleeSavedInfo>(SaveLabelId, *it));
00442     }
00443   }
00444   return true;
00445 }
00446 
00447 bool XCoreInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
00448                                          MachineBasicBlock::iterator MI,
00449                                const std::vector<CalleeSavedInfo> &CSI) const
00450 {
00451   bool AtStart = MI == MBB.begin();
00452   MachineBasicBlock::iterator BeforeI = MI;
00453   if (!AtStart)
00454     --BeforeI;
00455   for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
00456                                                     it != CSI.end(); ++it) {
00457     
00458     loadRegFromStackSlot(MBB, MI, it->getReg(),
00459                                   it->getFrameIdx(),
00460                                   it->getRegClass());
00461     assert(MI != MBB.begin() &&
00462            "loadRegFromStackSlot didn't insert any code!");
00463     // Insert in reverse order.  loadRegFromStackSlot can insert multiple
00464     // instructions.
00465     if (AtStart)
00466       MI = MBB.begin();
00467     else {
00468       MI = BeforeI;
00469       ++MI;
00470     }
00471   }
00472   return true;
00473 }
00474 
00475 /// BlockHasNoFallThrough - Analyse if MachineBasicBlock does not
00476 /// fall-through into its successor block.
00477 bool XCoreInstrInfo::
00478 BlockHasNoFallThrough(const MachineBasicBlock &MBB) const 
00479 {
00480   if (MBB.empty()) return false;
00481   
00482   switch (MBB.back().getOpcode()) {
00483   case XCore::RETSP_u6:     // Return.
00484   case XCore::RETSP_lu6:
00485   case XCore::BAU_1r:       // Indirect branch.
00486   case XCore::BRFU_u6:      // Uncond branch.
00487   case XCore::BRFU_lu6:
00488   case XCore::BRBU_u6:
00489   case XCore::BRBU_lu6:
00490     return true;
00491   default: return false;
00492   }
00493 }
00494 
00495 /// ReverseBranchCondition - Return the inverse opcode of the 
00496 /// specified Branch instruction.
00497 bool XCoreInstrInfo::
00498 ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const 
00499 {
00500   assert((Cond.size() == 2) && 
00501           "Invalid XCore branch condition!");
00502   Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
00503   return false;
00504 }