LLVM API Documentation

MipsFastISel.cpp
Go to the documentation of this file.
00001 //===-- MipsastISel.cpp - Mips FastISel implementation
00002 //---------------------===//
00003 
00004 #include "llvm/CodeGen/FunctionLoweringInfo.h"
00005 #include "llvm/CodeGen/FastISel.h"
00006 #include "llvm/CodeGen/MachineInstrBuilder.h"
00007 #include "llvm/IR/GlobalAlias.h"
00008 #include "llvm/IR/GlobalVariable.h"
00009 #include "llvm/Target/TargetInstrInfo.h"
00010 #include "llvm/Target/TargetLibraryInfo.h"
00011 #include "MipsRegisterInfo.h"
00012 #include "MipsISelLowering.h"
00013 #include "MipsMachineFunction.h"
00014 #include "MipsSubtarget.h"
00015 #include "MipsTargetMachine.h"
00016 
00017 using namespace llvm;
00018 
00019 namespace {
00020 
00021 // All possible address modes.
00022 typedef struct Address {
00023   enum { RegBase, FrameIndexBase } BaseType;
00024 
00025   union {
00026     unsigned Reg;
00027     int FI;
00028   } Base;
00029 
00030   int64_t Offset;
00031 
00032   // Innocuous defaults for our address.
00033   Address() : BaseType(RegBase), Offset(0) { Base.Reg = 0; }
00034 } Address;
00035 
00036 class MipsFastISel final : public FastISel {
00037 
00038   /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
00039   /// make the right decision when generating code for different targets.
00040   Module &M;
00041   const TargetMachine &TM;
00042   const TargetInstrInfo &TII;
00043   const TargetLowering &TLI;
00044   const MipsSubtarget *Subtarget;
00045   MipsFunctionInfo *MFI;
00046 
00047   // Convenience variables to avoid some queries.
00048   LLVMContext *Context;
00049 
00050   bool TargetSupported;
00051 
00052 public:
00053   explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
00054                         const TargetLibraryInfo *libInfo)
00055       : FastISel(funcInfo, libInfo),
00056         M(const_cast<Module &>(*funcInfo.Fn->getParent())),
00057         TM(funcInfo.MF->getTarget()),
00058         TII(*TM.getSubtargetImpl()->getInstrInfo()),
00059         TLI(*TM.getSubtargetImpl()->getTargetLowering()),
00060         Subtarget(&TM.getSubtarget<MipsSubtarget>()) {
00061     MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
00062     Context = &funcInfo.Fn->getContext();
00063     TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
00064                        ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) &&
00065                         (Subtarget->isABI_O32())));
00066   }
00067 
00068   bool fastSelectInstruction(const Instruction *I) override;
00069   unsigned fastMaterializeConstant(const Constant *C) override;
00070 
00071   bool ComputeAddress(const Value *Obj, Address &Addr);
00072 
00073 private:
00074   bool EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
00075                 unsigned Alignment = 0);
00076   bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
00077                  unsigned Alignment = 0);
00078   bool SelectLoad(const Instruction *I);
00079   bool SelectRet(const Instruction *I);
00080   bool SelectStore(const Instruction *I);
00081 
00082   bool isTypeLegal(Type *Ty, MVT &VT);
00083   bool isLoadTypeLegal(Type *Ty, MVT &VT);
00084 
00085   unsigned MaterializeFP(const ConstantFP *CFP, MVT VT);
00086   unsigned MaterializeGV(const GlobalValue *GV, MVT VT);
00087   unsigned MaterializeInt(const Constant *C, MVT VT);
00088   unsigned Materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC);
00089 
00090   // for some reason, this default is not generated by tablegen
00091   // so we explicitly generate it here.
00092   //
00093   unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC,
00094                              unsigned Op0, bool Op0IsKill, uint64_t imm1,
00095                              uint64_t imm2, unsigned Op3, bool Op3IsKill) {
00096     return 0;
00097   }
00098 
00099   MachineInstrBuilder EmitInst(unsigned Opc) {
00100     return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
00101   }
00102 
00103   MachineInstrBuilder EmitInst(unsigned Opc, unsigned DstReg) {
00104     return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
00105                    DstReg);
00106   }
00107 
00108   MachineInstrBuilder EmitInstStore(unsigned Opc, unsigned SrcReg,
00109                                     unsigned MemReg, int64_t MemOffset) {
00110     return EmitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
00111   }
00112 
00113   MachineInstrBuilder EmitInstLoad(unsigned Opc, unsigned DstReg,
00114                                    unsigned MemReg, int64_t MemOffset) {
00115     return EmitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
00116   }
00117 
00118 #include "MipsGenFastISel.inc"
00119 };
00120 
00121 bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
00122   EVT evt = TLI.getValueType(Ty, true);
00123   // Only handle simple types.
00124   if (evt == MVT::Other || !evt.isSimple())
00125     return false;
00126   VT = evt.getSimpleVT();
00127 
00128   // Handle all legal types, i.e. a register that will directly hold this
00129   // value.
00130   return TLI.isTypeLegal(VT);
00131 }
00132 
00133 bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
00134   if (isTypeLegal(Ty, VT))
00135     return true;
00136   // We will extend this in a later patch:
00137   //   If this is a type than can be sign or zero-extended to a basic operation
00138   //   go ahead and accept it now.
00139   if (VT == MVT::i8 || VT == MVT::i16)
00140     return true;
00141   return false;
00142 }
00143 
00144 bool MipsFastISel::ComputeAddress(const Value *Obj, Address &Addr) {
00145   // This construct looks a big awkward but it is how other ports handle this
00146   // and as this function is more fully completed, these cases which
00147   // return false will have additional code in them.
00148   //
00149   if (isa<Instruction>(Obj))
00150     return false;
00151   else if (isa<ConstantExpr>(Obj))
00152     return false;
00153   Addr.Base.Reg = getRegForValue(Obj);
00154   return Addr.Base.Reg != 0;
00155 }
00156 
00157 bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
00158                             unsigned Alignment) {
00159   //
00160   // more cases will be handled here in following patches.
00161   //
00162   unsigned Opc;
00163   switch (VT.SimpleTy) {
00164   case MVT::i32: {
00165     ResultReg = createResultReg(&Mips::GPR32RegClass);
00166     Opc = Mips::LW;
00167     break;
00168   }
00169   case MVT::i16: {
00170     ResultReg = createResultReg(&Mips::GPR32RegClass);
00171     Opc = Mips::LHu;
00172     break;
00173   }
00174   case MVT::i8: {
00175     ResultReg = createResultReg(&Mips::GPR32RegClass);
00176     Opc = Mips::LBu;
00177     break;
00178   }
00179   case MVT::f32: {
00180     ResultReg = createResultReg(&Mips::FGR32RegClass);
00181     Opc = Mips::LWC1;
00182     break;
00183   }
00184   case MVT::f64: {
00185     ResultReg = createResultReg(&Mips::AFGR64RegClass);
00186     Opc = Mips::LDC1;
00187     break;
00188   }
00189   default:
00190     return false;
00191   }
00192   EmitInstLoad(Opc, ResultReg, Addr.Base.Reg, Addr.Offset);
00193   return true;
00194 }
00195 
00196 // Materialize a constant into a register, and return the register
00197 // number (or zero if we failed to handle it).
00198 unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
00199   EVT CEVT = TLI.getValueType(C->getType(), true);
00200 
00201   // Only handle simple types.
00202   if (!CEVT.isSimple())
00203     return 0;
00204   MVT VT = CEVT.getSimpleVT();
00205 
00206   if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
00207     return MaterializeFP(CFP, VT);
00208   else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
00209     return MaterializeGV(GV, VT);
00210   else if (isa<ConstantInt>(C))
00211     return MaterializeInt(C, VT);
00212 
00213   return 0;
00214 }
00215 
00216 bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
00217                              unsigned Alignment) {
00218   //
00219   // more cases will be handled here in following patches.
00220   //
00221   unsigned Opc;
00222   switch (VT.SimpleTy) {
00223   case MVT::i8:
00224     Opc = Mips::SB;
00225     break;
00226   case MVT::i16:
00227     Opc = Mips::SH;
00228     break;
00229   case MVT::i32:
00230     Opc = Mips::SW;
00231     break;
00232   case MVT::f32:
00233     Opc = Mips::SWC1;
00234     break;
00235   case MVT::f64:
00236     Opc = Mips::SDC1;
00237     break;
00238   default:
00239     return false;
00240   }
00241   EmitInstStore(Opc, SrcReg, Addr.Base.Reg, Addr.Offset);
00242   return true;
00243 }
00244 
00245 bool MipsFastISel::SelectLoad(const Instruction *I) {
00246   // Atomic loads need special handling.
00247   if (cast<LoadInst>(I)->isAtomic())
00248     return false;
00249 
00250   // Verify we have a legal type before going any further.
00251   MVT VT;
00252   if (!isLoadTypeLegal(I->getType(), VT))
00253     return false;
00254 
00255   // See if we can handle this address.
00256   Address Addr;
00257   if (!ComputeAddress(I->getOperand(0), Addr))
00258     return false;
00259 
00260   unsigned ResultReg;
00261   if (!EmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
00262     return false;
00263   updateValueMap(I, ResultReg);
00264   return true;
00265 }
00266 
00267 bool MipsFastISel::SelectStore(const Instruction *I) {
00268   Value *Op0 = I->getOperand(0);
00269   unsigned SrcReg = 0;
00270 
00271   // Atomic stores need special handling.
00272   if (cast<StoreInst>(I)->isAtomic())
00273     return false;
00274 
00275   // Verify we have a legal type before going any further.
00276   MVT VT;
00277   if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
00278     return false;
00279 
00280   // Get the value to be stored into a register.
00281   SrcReg = getRegForValue(Op0);
00282   if (SrcReg == 0)
00283     return false;
00284 
00285   // See if we can handle this address.
00286   Address Addr;
00287   if (!ComputeAddress(I->getOperand(1), Addr))
00288     return false;
00289 
00290   if (!EmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
00291     return false;
00292   return true;
00293 }
00294 
00295 bool MipsFastISel::SelectRet(const Instruction *I) {
00296   const ReturnInst *Ret = cast<ReturnInst>(I);
00297 
00298   if (!FuncInfo.CanLowerReturn)
00299     return false;
00300   if (Ret->getNumOperands() > 0) {
00301     return false;
00302   }
00303   EmitInst(Mips::RetRA);
00304   return true;
00305 }
00306 
00307 bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
00308   if (!TargetSupported)
00309     return false;
00310   switch (I->getOpcode()) {
00311   default:
00312     break;
00313   case Instruction::Load:
00314     return SelectLoad(I);
00315   case Instruction::Store:
00316     return SelectStore(I);
00317   case Instruction::Ret:
00318     return SelectRet(I);
00319   }
00320   return false;
00321 }
00322 }
00323 
00324 unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) {
00325   int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
00326   if (VT == MVT::f32) {
00327     const TargetRegisterClass *RC = &Mips::FGR32RegClass;
00328     unsigned DestReg = createResultReg(RC);
00329     unsigned TempReg = Materialize32BitInt(Imm, &Mips::GPR32RegClass);
00330     EmitInst(Mips::MTC1, DestReg).addReg(TempReg);
00331     return DestReg;
00332   } else if (VT == MVT::f64) {
00333     const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
00334     unsigned DestReg = createResultReg(RC);
00335     unsigned TempReg1 = Materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
00336     unsigned TempReg2 =
00337         Materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
00338     EmitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
00339     return DestReg;
00340   }
00341   return 0;
00342 }
00343 
00344 unsigned MipsFastISel::MaterializeGV(const GlobalValue *GV, MVT VT) {
00345   // For now 32-bit only.
00346   if (VT != MVT::i32)
00347     return 0;
00348   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
00349   unsigned DestReg = createResultReg(RC);
00350   const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
00351   bool IsThreadLocal = GVar && GVar->isThreadLocal();
00352   // TLS not supported at this time.
00353   if (IsThreadLocal)
00354     return 0;
00355   EmitInst(Mips::LW, DestReg).addReg(MFI->getGlobalBaseReg()).addGlobalAddress(
00356       GV, 0, MipsII::MO_GOT);
00357   if ((GV->hasInternalLinkage() ||
00358        (GV->hasLocalLinkage() && !isa<Function>(GV)))) {
00359     unsigned TempReg = createResultReg(RC);
00360     EmitInst(Mips::ADDiu, TempReg).addReg(DestReg).addGlobalAddress(
00361         GV, 0, MipsII::MO_ABS_LO);
00362     DestReg = TempReg;
00363   }
00364   return DestReg;
00365 }
00366 
00367 unsigned MipsFastISel::MaterializeInt(const Constant *C, MVT VT) {
00368   if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
00369     return 0;
00370   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
00371   const ConstantInt *CI = cast<ConstantInt>(C);
00372   int64_t Imm;
00373   if ((VT != MVT::i1) && CI->isNegative())
00374     Imm = CI->getSExtValue();
00375   else
00376     Imm = CI->getZExtValue();
00377   return Materialize32BitInt(Imm, RC);
00378 }
00379 
00380 unsigned MipsFastISel::Materialize32BitInt(int64_t Imm,
00381                                            const TargetRegisterClass *RC) {
00382   unsigned ResultReg = createResultReg(RC);
00383 
00384   if (isInt<16>(Imm)) {
00385     unsigned Opc = Mips::ADDiu;
00386     EmitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
00387     return ResultReg;
00388   } else if (isUInt<16>(Imm)) {
00389     EmitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
00390     return ResultReg;
00391   }
00392   unsigned Lo = Imm & 0xFFFF;
00393   unsigned Hi = (Imm >> 16) & 0xFFFF;
00394   if (Lo) {
00395     // Both Lo and Hi have nonzero bits.
00396     unsigned TmpReg = createResultReg(RC);
00397     EmitInst(Mips::LUi, TmpReg).addImm(Hi);
00398     EmitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
00399   } else {
00400     EmitInst(Mips::LUi, ResultReg).addImm(Hi);
00401   }
00402   return ResultReg;
00403 }
00404 
00405 namespace llvm {
00406 FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
00407                                const TargetLibraryInfo *libInfo) {
00408   return new MipsFastISel(funcInfo, libInfo);
00409 }
00410 }