1 //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===// 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 /// \file 10 /// This file implements the targeting of the InstructionSelector class for 11 /// Mips. 12 /// \todo This should be generated by TableGen. 13 //===----------------------------------------------------------------------===// 14 15 #include "MipsRegisterBankInfo.h" 16 #include "MipsTargetMachine.h" 17 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" 18 19 #define DEBUG_TYPE "mips-isel" 20 21 using namespace llvm; 22 23 namespace { 24 25 #define GET_GLOBALISEL_PREDICATE_BITSET 26 #include "MipsGenGlobalISel.inc" 27 #undef GET_GLOBALISEL_PREDICATE_BITSET 28 29 class MipsInstructionSelector : public InstructionSelector { 30 public: 31 MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI, 32 const MipsRegisterBankInfo &RBI); 33 34 bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override; 35 static const char *getName() { return DEBUG_TYPE; } 36 37 private: 38 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; 39 40 const MipsTargetMachine &TM; 41 const MipsSubtarget &STI; 42 const MipsInstrInfo &TII; 43 const MipsRegisterInfo &TRI; 44 const MipsRegisterBankInfo &RBI; 45 46 #define GET_GLOBALISEL_PREDICATES_DECL 47 #include "MipsGenGlobalISel.inc" 48 #undef GET_GLOBALISEL_PREDICATES_DECL 49 50 #define GET_GLOBALISEL_TEMPORARIES_DECL 51 #include "MipsGenGlobalISel.inc" 52 #undef GET_GLOBALISEL_TEMPORARIES_DECL 53 }; 54 55 } // end anonymous namespace 56 57 #define GET_GLOBALISEL_IMPL 58 #include "MipsGenGlobalISel.inc" 59 #undef GET_GLOBALISEL_IMPL 60 61 MipsInstructionSelector::MipsInstructionSelector( 62 const MipsTargetMachine &TM, const MipsSubtarget &STI, 63 const MipsRegisterBankInfo &RBI) 64 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), 65 TRI(*STI.getRegisterInfo()), RBI(RBI), 66 67 #define GET_GLOBALISEL_PREDICATES_INIT 68 #include "MipsGenGlobalISel.inc" 69 #undef GET_GLOBALISEL_PREDICATES_INIT 70 #define GET_GLOBALISEL_TEMPORARIES_INIT 71 #include "MipsGenGlobalISel.inc" 72 #undef GET_GLOBALISEL_TEMPORARIES_INIT 73 { 74 } 75 76 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 77 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 78 const RegisterBankInfo &RBI) { 79 unsigned DstReg = I.getOperand(0).getReg(); 80 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) 81 return true; 82 83 const TargetRegisterClass *RC = &Mips::GPR32RegClass; 84 85 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 86 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 87 << " operand\n"); 88 return false; 89 } 90 return true; 91 } 92 93 bool MipsInstructionSelector::select(MachineInstr &I, 94 CodeGenCoverage &CoverageInfo) const { 95 96 MachineBasicBlock &MBB = *I.getParent(); 97 MachineFunction &MF = *MBB.getParent(); 98 MachineRegisterInfo &MRI = MF.getRegInfo(); 99 100 if (!isPreISelGenericOpcode(I.getOpcode())) { 101 if (I.isCopy()) 102 return selectCopy(I, TII, MRI, TRI, RBI); 103 104 return true; 105 } 106 107 if (selectImpl(I, CoverageInfo)) { 108 return true; 109 } 110 111 MachineInstr *MI = nullptr; 112 using namespace TargetOpcode; 113 114 switch (I.getOpcode()) { 115 case G_GEP: { 116 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) 117 .add(I.getOperand(0)) 118 .add(I.getOperand(1)) 119 .add(I.getOperand(2)); 120 break; 121 } 122 case G_FRAME_INDEX: { 123 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 124 .add(I.getOperand(0)) 125 .add(I.getOperand(1)) 126 .addImm(0); 127 break; 128 } 129 case G_STORE: 130 case G_LOAD: { 131 const unsigned DestReg = I.getOperand(0).getReg(); 132 const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); 133 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); 134 135 if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) 136 return false; 137 138 const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW; 139 140 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) 141 .add(I.getOperand(0)) 142 .add(I.getOperand(1)) 143 .addImm(0) 144 .addMemOperand(*I.memoperands_begin()); 145 break; 146 } 147 case G_CONSTANT: { 148 int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue(); 149 unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 150 MachineInstr *LUi, *ORi; 151 152 LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) 153 .addDef(LUiReg) 154 .addImm(Imm >> 16); 155 156 ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi)) 157 .addDef(I.getOperand(0).getReg()) 158 .addUse(LUiReg) 159 .addImm(Imm & 0xFFFF); 160 161 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 162 return false; 163 if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) 164 return false; 165 166 I.eraseFromParent(); 167 return true; 168 } 169 case G_GLOBAL_VALUE: { 170 if (MF.getTarget().isPositionIndependent()) 171 return false; 172 173 const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal(); 174 unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 175 MachineInstr *LUi, *ADDiu; 176 177 LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) 178 .addDef(LUiReg) 179 .addGlobalAddress(GVal); 180 LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI); 181 182 ADDiu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 183 .addDef(I.getOperand(0).getReg()) 184 .addUse(LUiReg) 185 .addGlobalAddress(GVal); 186 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); 187 188 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 189 return false; 190 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) 191 return false; 192 193 I.eraseFromParent(); 194 return true; 195 } 196 197 default: 198 return false; 199 } 200 201 I.eraseFromParent(); 202 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 203 } 204 205 namespace llvm { 206 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM, 207 MipsSubtarget &Subtarget, 208 MipsRegisterBankInfo &RBI) { 209 return new MipsInstructionSelector(TM, Subtarget, RBI); 210 } 211 } // end namespace llvm 212