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