1 //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file implements the targeting of the InstructionSelector class for 10 /// Mips. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "MCTargetDesc/MipsInstPrinter.h" 15 #include "MipsMachineFunction.h" 16 #include "MipsRegisterBankInfo.h" 17 #include "MipsTargetMachine.h" 18 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" 19 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 20 #include "llvm/CodeGen/MachineJumpTableInfo.h" 21 22 #define DEBUG_TYPE "mips-isel" 23 24 using namespace llvm; 25 26 namespace { 27 28 #define GET_GLOBALISEL_PREDICATE_BITSET 29 #include "MipsGenGlobalISel.inc" 30 #undef GET_GLOBALISEL_PREDICATE_BITSET 31 32 class MipsInstructionSelector : public InstructionSelector { 33 public: 34 MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI, 35 const MipsRegisterBankInfo &RBI); 36 37 bool select(MachineInstr &I) override; 38 static const char *getName() { return DEBUG_TYPE; } 39 40 private: 41 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; 42 bool materialize32BitImm(Register DestReg, APInt Imm, 43 MachineIRBuilder &B) const; 44 bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const; 45 const TargetRegisterClass * 46 getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB, 47 const RegisterBankInfo &RBI) const; 48 unsigned selectLoadStoreOpCode(MachineInstr &I, 49 MachineRegisterInfo &MRI) const; 50 51 const MipsTargetMachine &TM; 52 const MipsSubtarget &STI; 53 const MipsInstrInfo &TII; 54 const MipsRegisterInfo &TRI; 55 const MipsRegisterBankInfo &RBI; 56 57 #define GET_GLOBALISEL_PREDICATES_DECL 58 #include "MipsGenGlobalISel.inc" 59 #undef GET_GLOBALISEL_PREDICATES_DECL 60 61 #define GET_GLOBALISEL_TEMPORARIES_DECL 62 #include "MipsGenGlobalISel.inc" 63 #undef GET_GLOBALISEL_TEMPORARIES_DECL 64 }; 65 66 } // end anonymous namespace 67 68 #define GET_GLOBALISEL_IMPL 69 #include "MipsGenGlobalISel.inc" 70 #undef GET_GLOBALISEL_IMPL 71 72 MipsInstructionSelector::MipsInstructionSelector( 73 const MipsTargetMachine &TM, const MipsSubtarget &STI, 74 const MipsRegisterBankInfo &RBI) 75 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), 76 TRI(*STI.getRegisterInfo()), RBI(RBI), 77 78 #define GET_GLOBALISEL_PREDICATES_INIT 79 #include "MipsGenGlobalISel.inc" 80 #undef GET_GLOBALISEL_PREDICATES_INIT 81 #define GET_GLOBALISEL_TEMPORARIES_INIT 82 #include "MipsGenGlobalISel.inc" 83 #undef GET_GLOBALISEL_TEMPORARIES_INIT 84 { 85 } 86 87 bool MipsInstructionSelector::selectCopy(MachineInstr &I, 88 MachineRegisterInfo &MRI) const { 89 Register DstReg = I.getOperand(0).getReg(); 90 if (Register::isPhysicalRegister(DstReg)) 91 return true; 92 93 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI); 94 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); 95 96 const TargetRegisterClass *RC = &Mips::GPR32RegClass; 97 if (RegBank->getID() == Mips::FPRBRegBankID) { 98 if (DstSize == 32) 99 RC = &Mips::FGR32RegClass; 100 else if (DstSize == 64) 101 RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; 102 else 103 llvm_unreachable("Unsupported destination size"); 104 } 105 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 106 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 107 << " operand\n"); 108 return false; 109 } 110 return true; 111 } 112 113 const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank( 114 unsigned OpSize, const RegisterBank &RB, 115 const RegisterBankInfo &RBI) const { 116 if (RB.getID() == Mips::GPRBRegBankID) 117 return &Mips::GPR32RegClass; 118 119 if (RB.getID() == Mips::FPRBRegBankID) 120 return OpSize == 32 121 ? &Mips::FGR32RegClass 122 : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass 123 : &Mips::AFGR64RegClass; 124 125 llvm_unreachable("getRegClassForTypeOnBank can't find register class."); 126 return nullptr; 127 } 128 129 bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm, 130 MachineIRBuilder &B) const { 131 assert(Imm.getBitWidth() == 32 && "Unsupported immediate size."); 132 // Ori zero extends immediate. Used for values with zeros in high 16 bits. 133 if (Imm.getHiBits(16).isNullValue()) { 134 MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)}) 135 .addImm(Imm.getLoBits(16).getLimitedValue()); 136 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); 137 } 138 // Lui places immediate in high 16 bits and sets low 16 bits to zero. 139 if (Imm.getLoBits(16).isNullValue()) { 140 MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {}) 141 .addImm(Imm.getHiBits(16).getLimitedValue()); 142 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); 143 } 144 // ADDiu sign extends immediate. Used for values with 1s in high 17 bits. 145 if (Imm.isSignedIntN(16)) { 146 MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)}) 147 .addImm(Imm.getLoBits(16).getLimitedValue()); 148 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); 149 } 150 // Values that cannot be materialized with single immediate instruction. 151 Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass); 152 MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {}) 153 .addImm(Imm.getHiBits(16).getLimitedValue()); 154 MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg}) 155 .addImm(Imm.getLoBits(16).getLimitedValue()); 156 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 157 return false; 158 if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) 159 return false; 160 return true; 161 } 162 163 /// Returning Opc indicates that we failed to select MIPS instruction opcode. 164 unsigned 165 MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I, 166 MachineRegisterInfo &MRI) const { 167 STI.getRegisterInfo(); 168 const Register DestReg = I.getOperand(0).getReg(); 169 const unsigned RegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); 170 const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize(); 171 unsigned Opc = I.getOpcode(); 172 const bool isStore = Opc == TargetOpcode::G_STORE; 173 if (RegBank == Mips::GPRBRegBankID) { 174 if (isStore) 175 switch (MemSizeInBytes) { 176 case 4: 177 return Mips::SW; 178 case 2: 179 return Mips::SH; 180 case 1: 181 return Mips::SB; 182 default: 183 return Opc; 184 } 185 else 186 // Unspecified extending load is selected into zeroExtending load. 187 switch (MemSizeInBytes) { 188 case 4: 189 return Mips::LW; 190 case 2: 191 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu; 192 case 1: 193 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu; 194 default: 195 return Opc; 196 } 197 } 198 199 if (RegBank == Mips::FPRBRegBankID) { 200 switch (MemSizeInBytes) { 201 case 4: 202 return isStore ? Mips::SWC1 : Mips::LWC1; 203 case 8: 204 if (STI.isFP64bit()) 205 return isStore ? Mips::SDC164 : Mips::LDC164; 206 else 207 return isStore ? Mips::SDC1 : Mips::LDC1; 208 case 16: { 209 assert(STI.hasMSA() && "Vector instructions require target with MSA."); 210 const unsigned VectorElementSizeInBytes = 211 MRI.getType(DestReg).getElementType().getSizeInBytes(); 212 if (VectorElementSizeInBytes == 1) 213 return isStore ? Mips::ST_B : Mips::LD_B; 214 if (VectorElementSizeInBytes == 2) 215 return isStore ? Mips::ST_H : Mips::LD_H; 216 if (VectorElementSizeInBytes == 4) 217 return isStore ? Mips::ST_W : Mips::LD_W; 218 if (VectorElementSizeInBytes == 8) 219 return isStore ? Mips::ST_D : Mips::LD_D; 220 return Opc; 221 } 222 default: 223 return Opc; 224 } 225 } 226 return Opc; 227 } 228 229 bool MipsInstructionSelector::select(MachineInstr &I) { 230 231 MachineBasicBlock &MBB = *I.getParent(); 232 MachineFunction &MF = *MBB.getParent(); 233 MachineRegisterInfo &MRI = MF.getRegInfo(); 234 235 if (!isPreISelGenericOpcode(I.getOpcode())) { 236 if (I.isCopy()) 237 return selectCopy(I, MRI); 238 239 return true; 240 } 241 242 if (I.getOpcode() == Mips::G_MUL && 243 (RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI)->getID() == 244 Mips::GPRBRegBankID)) { 245 MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL)) 246 .add(I.getOperand(0)) 247 .add(I.getOperand(1)) 248 .add(I.getOperand(2)); 249 if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI)) 250 return false; 251 Mul->getOperand(3).setIsDead(true); 252 Mul->getOperand(4).setIsDead(true); 253 254 I.eraseFromParent(); 255 return true; 256 } 257 258 if (selectImpl(I, *CoverageInfo)) 259 return true; 260 261 MachineInstr *MI = nullptr; 262 using namespace TargetOpcode; 263 264 switch (I.getOpcode()) { 265 case G_UMULH: { 266 Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); 267 MachineInstr *PseudoMULTu, *PseudoMove; 268 269 PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu)) 270 .addDef(PseudoMULTuReg) 271 .add(I.getOperand(1)) 272 .add(I.getOperand(2)); 273 if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI)) 274 return false; 275 276 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI)) 277 .addDef(I.getOperand(0).getReg()) 278 .addUse(PseudoMULTuReg); 279 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) 280 return false; 281 282 I.eraseFromParent(); 283 return true; 284 } 285 case G_GEP: { 286 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) 287 .add(I.getOperand(0)) 288 .add(I.getOperand(1)) 289 .add(I.getOperand(2)); 290 break; 291 } 292 case G_INTTOPTR: 293 case G_PTRTOINT: { 294 I.setDesc(TII.get(COPY)); 295 return selectCopy(I, MRI); 296 } 297 case G_FRAME_INDEX: { 298 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 299 .add(I.getOperand(0)) 300 .add(I.getOperand(1)) 301 .addImm(0); 302 break; 303 } 304 case G_BRCOND: { 305 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE)) 306 .add(I.getOperand(0)) 307 .addUse(Mips::ZERO) 308 .add(I.getOperand(1)); 309 break; 310 } 311 case G_BRJT: { 312 unsigned EntrySize = 313 MF.getJumpTableInfo()->getEntrySize(MF.getDataLayout()); 314 assert(isPowerOf2_32(EntrySize) && 315 "Non-power-of-two jump-table entry size not supported."); 316 317 Register JTIndex = MRI.createVirtualRegister(&Mips::GPR32RegClass); 318 MachineInstr *SLL = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SLL)) 319 .addDef(JTIndex) 320 .addUse(I.getOperand(2).getReg()) 321 .addImm(Log2_32(EntrySize)); 322 if (!constrainSelectedInstRegOperands(*SLL, TII, TRI, RBI)) 323 return false; 324 325 Register DestAddress = MRI.createVirtualRegister(&Mips::GPR32RegClass); 326 MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) 327 .addDef(DestAddress) 328 .addUse(I.getOperand(0).getReg()) 329 .addUse(JTIndex); 330 if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI)) 331 return false; 332 333 Register Dest = MRI.createVirtualRegister(&Mips::GPR32RegClass); 334 MachineInstr *LW = 335 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW)) 336 .addDef(Dest) 337 .addUse(DestAddress) 338 .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_LO) 339 .addMemOperand(MF.getMachineMemOperand( 340 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, 4)); 341 if (!constrainSelectedInstRegOperands(*LW, TII, TRI, RBI)) 342 return false; 343 344 if (MF.getTarget().isPositionIndependent()) { 345 Register DestTmp = MRI.createVirtualRegister(&Mips::GPR32RegClass); 346 LW->getOperand(0).setReg(DestTmp); 347 MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) 348 .addDef(Dest) 349 .addUse(DestTmp) 350 .addUse(MF.getInfo<MipsFunctionInfo>() 351 ->getGlobalBaseRegForGlobalISel()); 352 if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI)) 353 return false; 354 } 355 356 MachineInstr *Branch = 357 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch)) 358 .addUse(Dest); 359 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI)) 360 return false; 361 362 I.eraseFromParent(); 363 return true; 364 } 365 case G_BRINDIRECT: { 366 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch)) 367 .add(I.getOperand(0)); 368 break; 369 } 370 case G_PHI: { 371 const Register DestReg = I.getOperand(0).getReg(); 372 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); 373 374 const TargetRegisterClass *DefRC = nullptr; 375 if (Register::isPhysicalRegister(DestReg)) 376 DefRC = TRI.getRegClass(DestReg); 377 else 378 DefRC = getRegClassForTypeOnBank(OpSize, 379 *RBI.getRegBank(DestReg, MRI, TRI), RBI); 380 381 I.setDesc(TII.get(TargetOpcode::PHI)); 382 return RBI.constrainGenericRegister(DestReg, *DefRC, MRI); 383 } 384 case G_STORE: 385 case G_LOAD: 386 case G_ZEXTLOAD: 387 case G_SEXTLOAD: { 388 const unsigned NewOpc = selectLoadStoreOpCode(I, MRI); 389 if (NewOpc == I.getOpcode()) 390 return false; 391 392 MachineOperand BaseAddr = I.getOperand(1); 393 int64_t SignedOffset = 0; 394 // Try to fold load/store + G_GEP + G_CONSTANT 395 // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate 396 // %Addr:(p0) = G_GEP %BaseAddr, %SignedOffset 397 // %LoadResult/%StoreSrc = load/store %Addr(p0) 398 // into: 399 // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate 400 401 MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg()); 402 if (Addr->getOpcode() == G_GEP) { 403 MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg()); 404 if (Offset->getOpcode() == G_CONSTANT) { 405 APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue(); 406 if (OffsetValue.isSignedIntN(16)) { 407 BaseAddr = Addr->getOperand(1); 408 SignedOffset = OffsetValue.getSExtValue(); 409 } 410 } 411 } 412 413 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) 414 .add(I.getOperand(0)) 415 .add(BaseAddr) 416 .addImm(SignedOffset) 417 .addMemOperand(*I.memoperands_begin()); 418 break; 419 } 420 case G_UDIV: 421 case G_UREM: 422 case G_SDIV: 423 case G_SREM: { 424 Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); 425 bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV; 426 bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV; 427 428 MachineInstr *PseudoDIV, *PseudoMove; 429 PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(), 430 TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV)) 431 .addDef(HILOReg) 432 .add(I.getOperand(1)) 433 .add(I.getOperand(2)); 434 if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI)) 435 return false; 436 437 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), 438 TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI)) 439 .addDef(I.getOperand(0).getReg()) 440 .addUse(HILOReg); 441 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) 442 return false; 443 444 I.eraseFromParent(); 445 return true; 446 } 447 case G_SELECT: { 448 // Handle operands with pointer type. 449 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I)) 450 .add(I.getOperand(0)) 451 .add(I.getOperand(2)) 452 .add(I.getOperand(1)) 453 .add(I.getOperand(3)); 454 break; 455 } 456 case G_IMPLICIT_DEF: { 457 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF)) 458 .add(I.getOperand(0)); 459 460 // Set class based on register bank, there can be fpr and gpr implicit def. 461 MRI.setRegClass(MI->getOperand(0).getReg(), 462 getRegClassForTypeOnBank( 463 MRI.getType(I.getOperand(0).getReg()).getSizeInBits(), 464 *RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI), 465 RBI)); 466 break; 467 } 468 case G_CONSTANT: { 469 MachineIRBuilder B(I); 470 if (!materialize32BitImm(I.getOperand(0).getReg(), 471 I.getOperand(1).getCImm()->getValue(), B)) 472 return false; 473 474 I.eraseFromParent(); 475 return true; 476 } 477 case G_FCONSTANT: { 478 const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF(); 479 APInt APImm = FPimm.bitcastToAPInt(); 480 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); 481 482 if (Size == 32) { 483 Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 484 MachineIRBuilder B(I); 485 if (!materialize32BitImm(GPRReg, APImm, B)) 486 return false; 487 488 MachineInstrBuilder MTC1 = 489 B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg}); 490 if (!MTC1.constrainAllUses(TII, TRI, RBI)) 491 return false; 492 } 493 if (Size == 64) { 494 Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass); 495 Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass); 496 MachineIRBuilder B(I); 497 if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B)) 498 return false; 499 if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B)) 500 return false; 501 502 MachineInstrBuilder PairF64 = B.buildInstr( 503 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, 504 {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh}); 505 if (!PairF64.constrainAllUses(TII, TRI, RBI)) 506 return false; 507 } 508 509 I.eraseFromParent(); 510 return true; 511 } 512 case G_FABS: { 513 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); 514 unsigned FABSOpcode = 515 Size == 32 ? Mips::FABS_S 516 : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32; 517 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode)) 518 .add(I.getOperand(0)) 519 .add(I.getOperand(1)); 520 break; 521 } 522 case G_FPTOSI: { 523 unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits(); 524 unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); 525 (void)ToSize; 526 assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI"); 527 assert((FromSize == 32 || FromSize == 64) && 528 "Unsupported floating point size for G_FPTOSI"); 529 530 unsigned Opcode; 531 if (FromSize == 32) 532 Opcode = Mips::TRUNC_W_S; 533 else 534 Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32; 535 Register ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass); 536 MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode)) 537 .addDef(ResultInFPR) 538 .addUse(I.getOperand(1).getReg()); 539 if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI)) 540 return false; 541 542 MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1)) 543 .addDef(I.getOperand(0).getReg()) 544 .addUse(ResultInFPR); 545 if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) 546 return false; 547 548 I.eraseFromParent(); 549 return true; 550 } 551 case G_GLOBAL_VALUE: { 552 const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal(); 553 if (MF.getTarget().isPositionIndependent()) { 554 MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW)) 555 .addDef(I.getOperand(0).getReg()) 556 .addReg(MF.getInfo<MipsFunctionInfo>() 557 ->getGlobalBaseRegForGlobalISel()) 558 .addGlobalAddress(GVal); 559 // Global Values that don't have local linkage are handled differently 560 // when they are part of call sequence. MipsCallLowering::lowerCall 561 // creates G_GLOBAL_VALUE instruction as part of call sequence and adds 562 // MO_GOT_CALL flag when Callee doesn't have local linkage. 563 if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL) 564 LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL); 565 else 566 LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT); 567 LWGOT->addMemOperand( 568 MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF), 569 MachineMemOperand::MOLoad, 4, 4)); 570 if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI)) 571 return false; 572 573 if (GVal->hasLocalLinkage()) { 574 Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass); 575 LWGOT->getOperand(0).setReg(LWGOTDef); 576 577 MachineInstr *ADDiu = 578 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 579 .addDef(I.getOperand(0).getReg()) 580 .addReg(LWGOTDef) 581 .addGlobalAddress(GVal); 582 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); 583 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) 584 return false; 585 } 586 } else { 587 Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 588 589 MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) 590 .addDef(LUiReg) 591 .addGlobalAddress(GVal); 592 LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI); 593 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 594 return false; 595 596 MachineInstr *ADDiu = 597 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 598 .addDef(I.getOperand(0).getReg()) 599 .addUse(LUiReg) 600 .addGlobalAddress(GVal); 601 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); 602 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) 603 return false; 604 } 605 I.eraseFromParent(); 606 return true; 607 } 608 case G_JUMP_TABLE: { 609 if (MF.getTarget().isPositionIndependent()) { 610 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW)) 611 .addDef(I.getOperand(0).getReg()) 612 .addReg(MF.getInfo<MipsFunctionInfo>() 613 ->getGlobalBaseRegForGlobalISel()) 614 .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_GOT) 615 .addMemOperand( 616 MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF), 617 MachineMemOperand::MOLoad, 4, 4)); 618 } else { 619 MI = 620 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) 621 .addDef(I.getOperand(0).getReg()) 622 .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_HI); 623 } 624 break; 625 } 626 case G_ICMP: { 627 struct Instr { 628 unsigned Opcode; 629 Register Def, LHS, RHS; 630 Instr(unsigned Opcode, Register Def, Register LHS, Register RHS) 631 : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){}; 632 633 bool hasImm() const { 634 if (Opcode == Mips::SLTiu || Opcode == Mips::XORi) 635 return true; 636 return false; 637 } 638 }; 639 640 SmallVector<struct Instr, 2> Instructions; 641 Register ICMPReg = I.getOperand(0).getReg(); 642 Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass); 643 Register LHS = I.getOperand(2).getReg(); 644 Register RHS = I.getOperand(3).getReg(); 645 CmpInst::Predicate Cond = 646 static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate()); 647 648 switch (Cond) { 649 case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1 650 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); 651 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1); 652 break; 653 case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS) 654 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); 655 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp); 656 break; 657 case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS 658 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS); 659 break; 660 case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS) 661 Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS); 662 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 663 break; 664 case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS 665 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS); 666 break; 667 case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS) 668 Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS); 669 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 670 break; 671 case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS 672 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS); 673 break; 674 case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS) 675 Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS); 676 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 677 break; 678 case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS 679 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS); 680 break; 681 case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS) 682 Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS); 683 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 684 break; 685 default: 686 return false; 687 } 688 689 MachineIRBuilder B(I); 690 for (const struct Instr &Instruction : Instructions) { 691 MachineInstrBuilder MIB = B.buildInstr( 692 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS}); 693 694 if (Instruction.hasImm()) 695 MIB.addImm(Instruction.RHS); 696 else 697 MIB.addUse(Instruction.RHS); 698 699 if (!MIB.constrainAllUses(TII, TRI, RBI)) 700 return false; 701 } 702 703 I.eraseFromParent(); 704 return true; 705 } 706 case G_FCMP: { 707 unsigned MipsFCMPCondCode; 708 bool isLogicallyNegated; 709 switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>( 710 I.getOperand(1).getPredicate())) { 711 case CmpInst::FCMP_UNO: // Unordered 712 case CmpInst::FCMP_ORD: // Ordered (OR) 713 MipsFCMPCondCode = Mips::FCOND_UN; 714 isLogicallyNegated = Cond != CmpInst::FCMP_UNO; 715 break; 716 case CmpInst::FCMP_OEQ: // Equal 717 case CmpInst::FCMP_UNE: // Not Equal (NEQ) 718 MipsFCMPCondCode = Mips::FCOND_OEQ; 719 isLogicallyNegated = Cond != CmpInst::FCMP_OEQ; 720 break; 721 case CmpInst::FCMP_UEQ: // Unordered or Equal 722 case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL) 723 MipsFCMPCondCode = Mips::FCOND_UEQ; 724 isLogicallyNegated = Cond != CmpInst::FCMP_UEQ; 725 break; 726 case CmpInst::FCMP_OLT: // Ordered or Less Than 727 case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE) 728 MipsFCMPCondCode = Mips::FCOND_OLT; 729 isLogicallyNegated = Cond != CmpInst::FCMP_OLT; 730 break; 731 case CmpInst::FCMP_ULT: // Unordered or Less Than 732 case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE) 733 MipsFCMPCondCode = Mips::FCOND_ULT; 734 isLogicallyNegated = Cond != CmpInst::FCMP_ULT; 735 break; 736 case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal 737 case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT) 738 MipsFCMPCondCode = Mips::FCOND_OLE; 739 isLogicallyNegated = Cond != CmpInst::FCMP_OLE; 740 break; 741 case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal 742 case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT) 743 MipsFCMPCondCode = Mips::FCOND_ULE; 744 isLogicallyNegated = Cond != CmpInst::FCMP_ULE; 745 break; 746 default: 747 return false; 748 } 749 750 // Default compare result in gpr register will be `true`. 751 // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false 752 // using MOVF_I. When orignal predicate (Cond) is logically negated 753 // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used. 754 unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I; 755 756 Register TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 757 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 758 .addDef(TrueInReg) 759 .addUse(Mips::ZERO) 760 .addImm(1); 761 762 unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits(); 763 unsigned FCMPOpcode = 764 Size == 32 ? Mips::FCMP_S32 765 : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32; 766 MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode)) 767 .addUse(I.getOperand(2).getReg()) 768 .addUse(I.getOperand(3).getReg()) 769 .addImm(MipsFCMPCondCode); 770 if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI)) 771 return false; 772 773 MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode)) 774 .addDef(I.getOperand(0).getReg()) 775 .addUse(Mips::ZERO) 776 .addUse(Mips::FCC0) 777 .addUse(TrueInReg); 778 if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) 779 return false; 780 781 I.eraseFromParent(); 782 return true; 783 } 784 case G_FENCE: { 785 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0); 786 break; 787 } 788 case G_VASTART: { 789 MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); 790 int FI = FuncInfo->getVarArgsFrameIndex(); 791 792 Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 793 MachineInstr *LEA_ADDiu = 794 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu)) 795 .addDef(LeaReg) 796 .addFrameIndex(FI) 797 .addImm(0); 798 if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI)) 799 return false; 800 801 MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW)) 802 .addUse(LeaReg) 803 .addUse(I.getOperand(0).getReg()) 804 .addImm(0); 805 if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI)) 806 return false; 807 808 I.eraseFromParent(); 809 return true; 810 } 811 default: 812 return false; 813 } 814 815 I.eraseFromParent(); 816 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 817 } 818 819 namespace llvm { 820 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM, 821 MipsSubtarget &Subtarget, 822 MipsRegisterBankInfo &RBI) { 823 return new MipsInstructionSelector(TM, Subtarget, RBI); 824 } 825 } // end namespace llvm 826