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 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 19 20 #define DEBUG_TYPE "mips-isel" 21 22 using namespace llvm; 23 24 namespace { 25 26 #define GET_GLOBALISEL_PREDICATE_BITSET 27 #include "MipsGenGlobalISel.inc" 28 #undef GET_GLOBALISEL_PREDICATE_BITSET 29 30 class MipsInstructionSelector : public InstructionSelector { 31 public: 32 MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI, 33 const MipsRegisterBankInfo &RBI); 34 35 bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override; 36 static const char *getName() { return DEBUG_TYPE; } 37 38 private: 39 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; 40 41 const MipsTargetMachine &TM; 42 const MipsSubtarget &STI; 43 const MipsInstrInfo &TII; 44 const MipsRegisterInfo &TRI; 45 const MipsRegisterBankInfo &RBI; 46 47 #define GET_GLOBALISEL_PREDICATES_DECL 48 #include "MipsGenGlobalISel.inc" 49 #undef GET_GLOBALISEL_PREDICATES_DECL 50 51 #define GET_GLOBALISEL_TEMPORARIES_DECL 52 #include "MipsGenGlobalISel.inc" 53 #undef GET_GLOBALISEL_TEMPORARIES_DECL 54 }; 55 56 } // end anonymous namespace 57 58 #define GET_GLOBALISEL_IMPL 59 #include "MipsGenGlobalISel.inc" 60 #undef GET_GLOBALISEL_IMPL 61 62 MipsInstructionSelector::MipsInstructionSelector( 63 const MipsTargetMachine &TM, const MipsSubtarget &STI, 64 const MipsRegisterBankInfo &RBI) 65 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), 66 TRI(*STI.getRegisterInfo()), RBI(RBI), 67 68 #define GET_GLOBALISEL_PREDICATES_INIT 69 #include "MipsGenGlobalISel.inc" 70 #undef GET_GLOBALISEL_PREDICATES_INIT 71 #define GET_GLOBALISEL_TEMPORARIES_INIT 72 #include "MipsGenGlobalISel.inc" 73 #undef GET_GLOBALISEL_TEMPORARIES_INIT 74 { 75 } 76 77 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 78 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 79 const RegisterBankInfo &RBI) { 80 unsigned DstReg = I.getOperand(0).getReg(); 81 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) 82 return true; 83 84 const TargetRegisterClass *RC = &Mips::GPR32RegClass; 85 86 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 87 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 88 << " operand\n"); 89 return false; 90 } 91 return true; 92 } 93 94 bool MipsInstructionSelector::select(MachineInstr &I, 95 CodeGenCoverage &CoverageInfo) const { 96 97 MachineBasicBlock &MBB = *I.getParent(); 98 MachineFunction &MF = *MBB.getParent(); 99 MachineRegisterInfo &MRI = MF.getRegInfo(); 100 101 if (!isPreISelGenericOpcode(I.getOpcode())) { 102 if (I.isCopy()) 103 return selectCopy(I, TII, MRI, TRI, RBI); 104 105 return true; 106 } 107 108 if (selectImpl(I, CoverageInfo)) { 109 return true; 110 } 111 112 MachineInstr *MI = nullptr; 113 using namespace TargetOpcode; 114 115 switch (I.getOpcode()) { 116 case G_GEP: { 117 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) 118 .add(I.getOperand(0)) 119 .add(I.getOperand(1)) 120 .add(I.getOperand(2)); 121 break; 122 } 123 case G_FRAME_INDEX: { 124 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 125 .add(I.getOperand(0)) 126 .add(I.getOperand(1)) 127 .addImm(0); 128 break; 129 } 130 case G_STORE: 131 case G_LOAD: { 132 const unsigned DestReg = I.getOperand(0).getReg(); 133 const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); 134 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); 135 136 if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) 137 return false; 138 139 const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW; 140 141 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) 142 .add(I.getOperand(0)) 143 .add(I.getOperand(1)) 144 .addImm(0) 145 .addMemOperand(*I.memoperands_begin()); 146 break; 147 } 148 case G_CONSTANT: { 149 int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue(); 150 unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 151 MachineInstr *LUi, *ORi; 152 153 LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) 154 .addDef(LUiReg) 155 .addImm(Imm >> 16); 156 157 ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi)) 158 .addDef(I.getOperand(0).getReg()) 159 .addUse(LUiReg) 160 .addImm(Imm & 0xFFFF); 161 162 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 163 return false; 164 if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) 165 return false; 166 167 I.eraseFromParent(); 168 return true; 169 } 170 case G_GLOBAL_VALUE: { 171 if (MF.getTarget().isPositionIndependent()) 172 return false; 173 174 const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal(); 175 unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 176 MachineInstr *LUi, *ADDiu; 177 178 LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) 179 .addDef(LUiReg) 180 .addGlobalAddress(GVal); 181 LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI); 182 183 ADDiu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 184 .addDef(I.getOperand(0).getReg()) 185 .addUse(LUiReg) 186 .addGlobalAddress(GVal); 187 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); 188 189 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 190 return false; 191 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) 192 return false; 193 194 I.eraseFromParent(); 195 return true; 196 } 197 case G_ICMP: { 198 struct Instr { 199 unsigned Opcode, Def, LHS, RHS; 200 Instr(unsigned Opcode, unsigned Def, unsigned LHS, unsigned RHS) 201 : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){}; 202 203 bool hasImm() const { 204 if (Opcode == Mips::SLTiu || Opcode == Mips::XORi) 205 return true; 206 return false; 207 } 208 }; 209 210 SmallVector<struct Instr, 2> Instructions; 211 unsigned ICMPReg = I.getOperand(0).getReg(); 212 unsigned Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass); 213 unsigned LHS = I.getOperand(2).getReg(); 214 unsigned RHS = I.getOperand(3).getReg(); 215 CmpInst::Predicate Cond = 216 static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate()); 217 218 switch (Cond) { 219 case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1 220 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); 221 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1); 222 break; 223 case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS) 224 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); 225 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp); 226 break; 227 case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS 228 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS); 229 break; 230 case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS) 231 Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS); 232 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 233 break; 234 case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS 235 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS); 236 break; 237 case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS) 238 Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS); 239 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 240 break; 241 case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS 242 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS); 243 break; 244 case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS) 245 Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS); 246 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 247 break; 248 case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS 249 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS); 250 break; 251 case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS) 252 Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS); 253 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 254 break; 255 default: 256 return false; 257 } 258 259 MachineIRBuilder B(I); 260 for (const struct Instr &Instruction : Instructions) { 261 MachineInstrBuilder MIB = B.buildInstr( 262 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS}); 263 264 if (Instruction.hasImm()) 265 MIB.addImm(Instruction.RHS); 266 else 267 MIB.addUse(Instruction.RHS); 268 269 if (!MIB.constrainAllUses(TII, TRI, RBI)) 270 return false; 271 } 272 273 I.eraseFromParent(); 274 return true; 275 } 276 default: 277 return false; 278 } 279 280 I.eraseFromParent(); 281 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 282 } 283 284 namespace llvm { 285 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM, 286 MipsSubtarget &Subtarget, 287 MipsRegisterBankInfo &RBI) { 288 return new MipsInstructionSelector(TM, Subtarget, RBI); 289 } 290 } // end namespace llvm 291