Home | History | Annotate | Download | only in Mips
      1 //===-- MipsastISel.cpp - Mips FastISel implementation
      2 //---------------------===//
      3 
      4 #include "llvm/CodeGen/FunctionLoweringInfo.h"
      5 #include "llvm/CodeGen/FastISel.h"
      6 #include "llvm/CodeGen/MachineInstrBuilder.h"
      7 #include "llvm/IR/GlobalAlias.h"
      8 #include "llvm/IR/GlobalVariable.h"
      9 #include "llvm/Target/TargetInstrInfo.h"
     10 #include "llvm/Target/TargetLibraryInfo.h"
     11 #include "MipsRegisterInfo.h"
     12 #include "MipsISelLowering.h"
     13 #include "MipsMachineFunction.h"
     14 #include "MipsSubtarget.h"
     15 #include "MipsTargetMachine.h"
     16 
     17 using namespace llvm;
     18 
     19 namespace {
     20 
     21 // All possible address modes.
     22 typedef struct Address {
     23   enum { RegBase, FrameIndexBase } BaseType;
     24 
     25   union {
     26     unsigned Reg;
     27     int FI;
     28   } Base;
     29 
     30   int64_t Offset;
     31 
     32   // Innocuous defaults for our address.
     33   Address() : BaseType(RegBase), Offset(0) { Base.Reg = 0; }
     34 } Address;
     35 
     36 class MipsFastISel final : public FastISel {
     37 
     38   /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
     39   /// make the right decision when generating code for different targets.
     40   Module &M;
     41   const TargetMachine &TM;
     42   const TargetInstrInfo &TII;
     43   const TargetLowering &TLI;
     44   const MipsSubtarget *Subtarget;
     45   MipsFunctionInfo *MFI;
     46 
     47   // Convenience variables to avoid some queries.
     48   LLVMContext *Context;
     49 
     50   bool TargetSupported;
     51 
     52 public:
     53   explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
     54                         const TargetLibraryInfo *libInfo)
     55       : FastISel(funcInfo, libInfo),
     56         M(const_cast<Module &>(*funcInfo.Fn->getParent())),
     57         TM(funcInfo.MF->getTarget()), TII(*TM.getInstrInfo()),
     58         TLI(*TM.getTargetLowering()),
     59         Subtarget(&TM.getSubtarget<MipsSubtarget>()) {
     60     MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
     61     Context = &funcInfo.Fn->getContext();
     62     TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
     63                        (Subtarget->hasMips32r2() && (Subtarget->isABI_O32())));
     64   }
     65 
     66   bool TargetSelectInstruction(const Instruction *I) override;
     67   unsigned TargetMaterializeConstant(const Constant *C) override;
     68 
     69   bool ComputeAddress(const Value *Obj, Address &Addr);
     70 
     71 private:
     72   bool EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
     73                 unsigned Alignment = 0);
     74   bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
     75                  unsigned Alignment = 0);
     76   bool SelectLoad(const Instruction *I);
     77   bool SelectRet(const Instruction *I);
     78   bool SelectStore(const Instruction *I);
     79 
     80   bool isTypeLegal(Type *Ty, MVT &VT);
     81   bool isLoadTypeLegal(Type *Ty, MVT &VT);
     82 
     83   unsigned MaterializeFP(const ConstantFP *CFP, MVT VT);
     84   unsigned MaterializeGV(const GlobalValue *GV, MVT VT);
     85   unsigned MaterializeInt(const Constant *C, MVT VT);
     86   unsigned Materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC);
     87 
     88   // for some reason, this default is not generated by tablegen
     89   // so we explicitly generate it here.
     90   //
     91   unsigned FastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC,
     92                              unsigned Op0, bool Op0IsKill, uint64_t imm1,
     93                              uint64_t imm2, unsigned Op3, bool Op3IsKill) {
     94     return 0;
     95   }
     96 
     97   MachineInstrBuilder EmitInst(unsigned Opc) {
     98     return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
     99   }
    100 
    101   MachineInstrBuilder EmitInst(unsigned Opc, unsigned DstReg) {
    102     return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
    103                    DstReg);
    104   }
    105 
    106   MachineInstrBuilder EmitInstStore(unsigned Opc, unsigned SrcReg,
    107                                     unsigned MemReg, int64_t MemOffset) {
    108     return EmitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
    109   }
    110 
    111   MachineInstrBuilder EmitInstLoad(unsigned Opc, unsigned DstReg,
    112                                       unsigned MemReg, int64_t MemOffset) {
    113     return EmitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
    114   }
    115 
    116 #include "MipsGenFastISel.inc"
    117 };
    118 
    119 bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
    120   EVT evt = TLI.getValueType(Ty, true);
    121   // Only handle simple types.
    122   if (evt == MVT::Other || !evt.isSimple())
    123     return false;
    124   VT = evt.getSimpleVT();
    125 
    126   // Handle all legal types, i.e. a register that will directly hold this
    127   // value.
    128   return TLI.isTypeLegal(VT);
    129 }
    130 
    131 bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
    132   if (isTypeLegal(Ty, VT))
    133     return true;
    134   // We will extend this in a later patch:
    135   //   If this is a type than can be sign or zero-extended to a basic operation
    136   //   go ahead and accept it now.
    137   if (VT == MVT::i8 || VT == MVT::i16)
    138     return true;
    139   return false;
    140 }
    141 
    142 bool MipsFastISel::ComputeAddress(const Value *Obj, Address &Addr) {
    143   // This construct looks a big awkward but it is how other ports handle this
    144   // and as this function is more fully completed, these cases which
    145   // return false will have additional code in them.
    146   //
    147   if (isa<Instruction>(Obj))
    148     return false;
    149   else if (isa<ConstantExpr>(Obj))
    150     return false;
    151   Addr.Base.Reg = getRegForValue(Obj);
    152   return Addr.Base.Reg != 0;
    153 }
    154 
    155 bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
    156                             unsigned Alignment) {
    157   //
    158   // more cases will be handled here in following patches.
    159   //
    160   unsigned Opc;
    161   switch (VT.SimpleTy) {
    162   case MVT::i32: {
    163     ResultReg = createResultReg(&Mips::GPR32RegClass);
    164     Opc = Mips::LW;
    165     break;
    166   }
    167   case MVT::i16: {
    168     ResultReg = createResultReg(&Mips::GPR32RegClass);
    169     Opc = Mips::LHu;
    170     break;
    171   }
    172   case MVT::i8: {
    173     ResultReg = createResultReg(&Mips::GPR32RegClass);
    174     Opc = Mips::LBu;
    175     break;
    176   }
    177   case MVT::f32: {
    178     ResultReg = createResultReg(&Mips::FGR32RegClass);
    179     Opc = Mips::LWC1;
    180     break;
    181   }
    182   case MVT::f64: {
    183     ResultReg = createResultReg(&Mips::AFGR64RegClass);
    184     Opc = Mips::LDC1;
    185     break;
    186   }
    187   default:
    188     return false;
    189   }
    190   EmitInstLoad(Opc, ResultReg, Addr.Base.Reg, Addr.Offset);
    191   return true;
    192 }
    193 
    194 // Materialize a constant into a register, and return the register
    195 // number (or zero if we failed to handle it).
    196 unsigned MipsFastISel::TargetMaterializeConstant(const Constant *C) {
    197   EVT CEVT = TLI.getValueType(C->getType(), true);
    198 
    199   // Only handle simple types.
    200   if (!CEVT.isSimple())
    201     return 0;
    202   MVT VT = CEVT.getSimpleVT();
    203 
    204   if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
    205     return MaterializeFP(CFP, VT);
    206   else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
    207     return MaterializeGV(GV, VT);
    208   else if (isa<ConstantInt>(C))
    209     return MaterializeInt(C, VT);
    210 
    211   return 0;
    212 }
    213 
    214 bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
    215                              unsigned Alignment) {
    216   //
    217   // more cases will be handled here in following patches.
    218   //
    219   unsigned Opc;
    220   switch (VT.SimpleTy) {
    221   case MVT::i8:
    222     Opc = Mips::SB;
    223     break;
    224   case MVT::i16:
    225     Opc = Mips::SH;
    226     break;
    227   case MVT::i32:
    228     Opc = Mips::SW;
    229     break;
    230   case MVT::f32:
    231     Opc = Mips::SWC1;
    232     break;
    233   case MVT::f64:
    234     Opc = Mips::SDC1;
    235     break;
    236   default:
    237     return false;
    238   }
    239   EmitInstStore(Opc, SrcReg, Addr.Base.Reg, Addr.Offset);
    240   return true;
    241 }
    242 
    243 bool MipsFastISel::SelectLoad(const Instruction *I) {
    244   // Atomic loads need special handling.
    245   if (cast<LoadInst>(I)->isAtomic())
    246     return false;
    247 
    248   // Verify we have a legal type before going any further.
    249   MVT VT;
    250   if (!isLoadTypeLegal(I->getType(), VT))
    251     return false;
    252 
    253   // See if we can handle this address.
    254   Address Addr;
    255   if (!ComputeAddress(I->getOperand(0), Addr))
    256     return false;
    257 
    258   unsigned ResultReg;
    259   if (!EmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
    260     return false;
    261   UpdateValueMap(I, ResultReg);
    262   return true;
    263 }
    264 
    265 bool MipsFastISel::SelectStore(const Instruction *I) {
    266   Value *Op0 = I->getOperand(0);
    267   unsigned SrcReg = 0;
    268 
    269   // Atomic stores need special handling.
    270   if (cast<StoreInst>(I)->isAtomic())
    271     return false;
    272 
    273   // Verify we have a legal type before going any further.
    274   MVT VT;
    275   if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
    276     return false;
    277 
    278   // Get the value to be stored into a register.
    279   SrcReg = getRegForValue(Op0);
    280   if (SrcReg == 0)
    281     return false;
    282 
    283   // See if we can handle this address.
    284   Address Addr;
    285   if (!ComputeAddress(I->getOperand(1), Addr))
    286     return false;
    287 
    288   if (!EmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
    289     return false;
    290   return true;
    291 }
    292 
    293 bool MipsFastISel::SelectRet(const Instruction *I) {
    294   const ReturnInst *Ret = cast<ReturnInst>(I);
    295 
    296   if (!FuncInfo.CanLowerReturn)
    297     return false;
    298   if (Ret->getNumOperands() > 0) {
    299     return false;
    300   }
    301   EmitInst(Mips::RetRA);
    302   return true;
    303 }
    304 
    305 bool MipsFastISel::TargetSelectInstruction(const Instruction *I) {
    306   if (!TargetSupported)
    307     return false;
    308   switch (I->getOpcode()) {
    309   default:
    310     break;
    311   case Instruction::Load:
    312     return SelectLoad(I);
    313   case Instruction::Store:
    314     return SelectStore(I);
    315   case Instruction::Ret:
    316     return SelectRet(I);
    317   }
    318   return false;
    319 }
    320 }
    321 
    322 unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) {
    323   int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
    324   if (VT == MVT::f32) {
    325     const TargetRegisterClass *RC = &Mips::FGR32RegClass;
    326     unsigned DestReg = createResultReg(RC);
    327     unsigned TempReg = Materialize32BitInt(Imm, &Mips::GPR32RegClass);
    328     EmitInst(Mips::MTC1, DestReg).addReg(TempReg);
    329     return DestReg;
    330   } else if (VT == MVT::f64) {
    331     const TargetRegisterClass *RC = &Mips::AFGR64RegClass;
    332     unsigned DestReg = createResultReg(RC);
    333     unsigned TempReg1 = Materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass);
    334     unsigned TempReg2 =
    335         Materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass);
    336     EmitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1);
    337     return DestReg;
    338   }
    339   return 0;
    340 }
    341 
    342 unsigned MipsFastISel::MaterializeGV(const GlobalValue *GV, MVT VT) {
    343   // For now 32-bit only.
    344   if (VT != MVT::i32)
    345     return 0;
    346   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
    347   unsigned DestReg = createResultReg(RC);
    348   const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
    349   bool IsThreadLocal = GVar && GVar->isThreadLocal();
    350   // TLS not supported at this time.
    351   if (IsThreadLocal)
    352     return 0;
    353   EmitInst(Mips::LW, DestReg).addReg(MFI->getGlobalBaseReg()).addGlobalAddress(
    354       GV, 0, MipsII::MO_GOT);
    355   return DestReg;
    356 }
    357 unsigned MipsFastISel::MaterializeInt(const Constant *C, MVT VT) {
    358   if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
    359     return 0;
    360   const TargetRegisterClass *RC = &Mips::GPR32RegClass;
    361   const ConstantInt *CI = cast<ConstantInt>(C);
    362   int64_t Imm;
    363   if (CI->isNegative())
    364     Imm = CI->getSExtValue();
    365   else
    366     Imm = CI->getZExtValue();
    367   return Materialize32BitInt(Imm, RC);
    368 }
    369 
    370 unsigned MipsFastISel::Materialize32BitInt(int64_t Imm,
    371                                            const TargetRegisterClass *RC) {
    372   unsigned ResultReg = createResultReg(RC);
    373 
    374   if (isInt<16>(Imm)) {
    375     unsigned Opc = Mips::ADDiu;
    376     EmitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm);
    377     return ResultReg;
    378   } else if (isUInt<16>(Imm)) {
    379     EmitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm);
    380     return ResultReg;
    381   }
    382   unsigned Lo = Imm & 0xFFFF;
    383   unsigned Hi = (Imm >> 16) & 0xFFFF;
    384   if (Lo) {
    385     // Both Lo and Hi have nonzero bits.
    386     unsigned TmpReg = createResultReg(RC);
    387     EmitInst(Mips::LUi, TmpReg).addImm(Hi);
    388     EmitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo);
    389   } else {
    390     EmitInst(Mips::LUi, ResultReg).addImm(Hi);
    391   }
    392   return ResultReg;
    393 }
    394 
    395 namespace llvm {
    396 FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
    397                                const TargetLibraryInfo *libInfo) {
    398   return new MipsFastISel(funcInfo, libInfo);
    399 }
    400 }
    401