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