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 21 #define DEBUG_TYPE "mips-isel" 22 23 using namespace llvm; 24 25 namespace { 26 27 #define GET_GLOBALISEL_PREDICATE_BITSET 28 #include "MipsGenGlobalISel.inc" 29 #undef GET_GLOBALISEL_PREDICATE_BITSET 30 31 class MipsInstructionSelector : public InstructionSelector { 32 public: 33 MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI, 34 const MipsRegisterBankInfo &RBI); 35 36 bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override; 37 static const char *getName() { return DEBUG_TYPE; } 38 39 private: 40 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; 41 bool materialize32BitImm(unsigned DestReg, APInt Imm, 42 MachineIRBuilder &B) const; 43 bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const; 44 45 const MipsTargetMachine &TM; 46 const MipsSubtarget &STI; 47 const MipsInstrInfo &TII; 48 const MipsRegisterInfo &TRI; 49 const MipsRegisterBankInfo &RBI; 50 51 #define GET_GLOBALISEL_PREDICATES_DECL 52 #include "MipsGenGlobalISel.inc" 53 #undef GET_GLOBALISEL_PREDICATES_DECL 54 55 #define GET_GLOBALISEL_TEMPORARIES_DECL 56 #include "MipsGenGlobalISel.inc" 57 #undef GET_GLOBALISEL_TEMPORARIES_DECL 58 }; 59 60 } // end anonymous namespace 61 62 #define GET_GLOBALISEL_IMPL 63 #include "MipsGenGlobalISel.inc" 64 #undef GET_GLOBALISEL_IMPL 65 66 MipsInstructionSelector::MipsInstructionSelector( 67 const MipsTargetMachine &TM, const MipsSubtarget &STI, 68 const MipsRegisterBankInfo &RBI) 69 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), 70 TRI(*STI.getRegisterInfo()), RBI(RBI), 71 72 #define GET_GLOBALISEL_PREDICATES_INIT 73 #include "MipsGenGlobalISel.inc" 74 #undef GET_GLOBALISEL_PREDICATES_INIT 75 #define GET_GLOBALISEL_TEMPORARIES_INIT 76 #include "MipsGenGlobalISel.inc" 77 #undef GET_GLOBALISEL_TEMPORARIES_INIT 78 { 79 } 80 81 bool MipsInstructionSelector::selectCopy(MachineInstr &I, 82 MachineRegisterInfo &MRI) const { 83 unsigned DstReg = I.getOperand(0).getReg(); 84 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) 85 return true; 86 87 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI); 88 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); 89 90 const TargetRegisterClass *RC = &Mips::GPR32RegClass; 91 if (RegBank->getID() == Mips::FPRBRegBankID) { 92 if (DstSize == 32) 93 RC = &Mips::FGR32RegClass; 94 else if (DstSize == 64) 95 RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; 96 else 97 llvm_unreachable("Unsupported destination size"); 98 } 99 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 100 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 101 << " operand\n"); 102 return false; 103 } 104 return true; 105 } 106 107 bool MipsInstructionSelector::materialize32BitImm(unsigned DestReg, APInt Imm, 108 MachineIRBuilder &B) const { 109 assert(Imm.getBitWidth() == 32 && "Unsupported immediate size."); 110 // Ori zero extends immediate. Used for values with zeros in high 16 bits. 111 if (Imm.getHiBits(16).isNullValue()) { 112 MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Mips::ZERO}) 113 .addImm(Imm.getLoBits(16).getLimitedValue()); 114 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); 115 } 116 // Lui places immediate in high 16 bits and sets low 16 bits to zero. 117 if (Imm.getLoBits(16).isNullValue()) { 118 MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {}) 119 .addImm(Imm.getHiBits(16).getLimitedValue()); 120 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); 121 } 122 // ADDiu sign extends immediate. Used for values with 1s in high 17 bits. 123 if (Imm.isSignedIntN(16)) { 124 MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Mips::ZERO}) 125 .addImm(Imm.getLoBits(16).getLimitedValue()); 126 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); 127 } 128 // Values that cannot be materialized with single immediate instruction. 129 unsigned LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass); 130 MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {}) 131 .addImm(Imm.getHiBits(16).getLimitedValue()); 132 MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg}) 133 .addImm(Imm.getLoBits(16).getLimitedValue()); 134 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 135 return false; 136 if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) 137 return false; 138 return true; 139 } 140 141 /// Returning Opc indicates that we failed to select MIPS instruction opcode. 142 static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes) { 143 if (Opc == TargetOpcode::G_STORE) 144 switch (MemSizeInBytes) { 145 case 4: 146 return Mips::SW; 147 case 2: 148 return Mips::SH; 149 case 1: 150 return Mips::SB; 151 default: 152 return Opc; 153 } 154 else 155 // Unspecified extending load is selected into zeroExtending load. 156 switch (MemSizeInBytes) { 157 case 4: 158 return Mips::LW; 159 case 2: 160 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu; 161 case 1: 162 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu; 163 default: 164 return Opc; 165 } 166 } 167 168 bool MipsInstructionSelector::select(MachineInstr &I, 169 CodeGenCoverage &CoverageInfo) const { 170 171 MachineBasicBlock &MBB = *I.getParent(); 172 MachineFunction &MF = *MBB.getParent(); 173 MachineRegisterInfo &MRI = MF.getRegInfo(); 174 175 if (!isPreISelGenericOpcode(I.getOpcode())) { 176 if (I.isCopy()) 177 return selectCopy(I, MRI); 178 179 return true; 180 } 181 182 if (I.getOpcode() == Mips::G_MUL) { 183 MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL)) 184 .add(I.getOperand(0)) 185 .add(I.getOperand(1)) 186 .add(I.getOperand(2)); 187 if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI)) 188 return false; 189 Mul->getOperand(3).setIsDead(true); 190 Mul->getOperand(4).setIsDead(true); 191 192 I.eraseFromParent(); 193 return true; 194 } 195 196 if (selectImpl(I, CoverageInfo)) 197 return true; 198 199 MachineInstr *MI = nullptr; 200 using namespace TargetOpcode; 201 202 switch (I.getOpcode()) { 203 case G_UMULH: { 204 unsigned PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); 205 MachineInstr *PseudoMULTu, *PseudoMove; 206 207 PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu)) 208 .addDef(PseudoMULTuReg) 209 .add(I.getOperand(1)) 210 .add(I.getOperand(2)); 211 if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI)) 212 return false; 213 214 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI)) 215 .addDef(I.getOperand(0).getReg()) 216 .addUse(PseudoMULTuReg); 217 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) 218 return false; 219 220 I.eraseFromParent(); 221 return true; 222 } 223 case G_GEP: { 224 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) 225 .add(I.getOperand(0)) 226 .add(I.getOperand(1)) 227 .add(I.getOperand(2)); 228 break; 229 } 230 case G_FRAME_INDEX: { 231 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 232 .add(I.getOperand(0)) 233 .add(I.getOperand(1)) 234 .addImm(0); 235 break; 236 } 237 case G_BRCOND: { 238 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE)) 239 .add(I.getOperand(0)) 240 .addUse(Mips::ZERO) 241 .add(I.getOperand(1)); 242 break; 243 } 244 case G_PHI: { 245 const unsigned DestReg = I.getOperand(0).getReg(); 246 const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); 247 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); 248 249 if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) 250 return false; 251 252 const TargetRegisterClass *DefRC = &Mips::GPR32RegClass; 253 I.setDesc(TII.get(TargetOpcode::PHI)); 254 return RBI.constrainGenericRegister(DestReg, *DefRC, MRI); 255 } 256 case G_STORE: 257 case G_LOAD: 258 case G_ZEXTLOAD: 259 case G_SEXTLOAD: { 260 const unsigned DestReg = I.getOperand(0).getReg(); 261 const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); 262 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); 263 const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize(); 264 265 if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) 266 return false; 267 268 const unsigned NewOpc = 269 selectLoadStoreOpCode(I.getOpcode(), OpMemSizeInBytes); 270 if (NewOpc == I.getOpcode()) 271 return false; 272 273 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) 274 .add(I.getOperand(0)) 275 .add(I.getOperand(1)) 276 .addImm(0) 277 .addMemOperand(*I.memoperands_begin()); 278 break; 279 } 280 case G_UDIV: 281 case G_UREM: 282 case G_SDIV: 283 case G_SREM: { 284 unsigned HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); 285 bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV; 286 bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV; 287 288 MachineInstr *PseudoDIV, *PseudoMove; 289 PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(), 290 TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV)) 291 .addDef(HILOReg) 292 .add(I.getOperand(1)) 293 .add(I.getOperand(2)); 294 if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI)) 295 return false; 296 297 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), 298 TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI)) 299 .addDef(I.getOperand(0).getReg()) 300 .addUse(HILOReg); 301 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) 302 return false; 303 304 I.eraseFromParent(); 305 return true; 306 } 307 case G_SELECT: { 308 // Handle operands with pointer type. 309 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I)) 310 .add(I.getOperand(0)) 311 .add(I.getOperand(2)) 312 .add(I.getOperand(1)) 313 .add(I.getOperand(3)); 314 break; 315 } 316 case G_CONSTANT: { 317 MachineIRBuilder B(I); 318 if (!materialize32BitImm(I.getOperand(0).getReg(), 319 I.getOperand(1).getCImm()->getValue(), B)) 320 return false; 321 322 I.eraseFromParent(); 323 return true; 324 } 325 case G_FCONSTANT: { 326 const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF(); 327 APInt APImm = FPimm.bitcastToAPInt(); 328 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); 329 330 if (Size == 32) { 331 unsigned GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 332 MachineIRBuilder B(I); 333 if (!materialize32BitImm(GPRReg, APImm, B)) 334 return false; 335 336 MachineInstrBuilder MTC1 = 337 B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg}); 338 if (!MTC1.constrainAllUses(TII, TRI, RBI)) 339 return false; 340 } 341 if (Size == 64) { 342 unsigned GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass); 343 unsigned GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass); 344 MachineIRBuilder B(I); 345 if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B)) 346 return false; 347 if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B)) 348 return false; 349 350 MachineInstrBuilder PairF64 = B.buildInstr( 351 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, 352 {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh}); 353 if (!PairF64.constrainAllUses(TII, TRI, RBI)) 354 return false; 355 } 356 357 I.eraseFromParent(); 358 return true; 359 } 360 case G_FABS: { 361 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); 362 unsigned FABSOpcode = 363 Size == 32 ? Mips::FABS_S 364 : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32; 365 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode)) 366 .add(I.getOperand(0)) 367 .add(I.getOperand(1)); 368 break; 369 } 370 case G_GLOBAL_VALUE: { 371 const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal(); 372 if (MF.getTarget().isPositionIndependent()) { 373 MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW)) 374 .addDef(I.getOperand(0).getReg()) 375 .addReg(MF.getInfo<MipsFunctionInfo>() 376 ->getGlobalBaseRegForGlobalISel()) 377 .addGlobalAddress(GVal); 378 // Global Values that don't have local linkage are handled differently 379 // when they are part of call sequence. MipsCallLowering::lowerCall 380 // creates G_GLOBAL_VALUE instruction as part of call sequence and adds 381 // MO_GOT_CALL flag when Callee doesn't have local linkage. 382 if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL) 383 LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL); 384 else 385 LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT); 386 LWGOT->addMemOperand( 387 MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF), 388 MachineMemOperand::MOLoad, 4, 4)); 389 if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI)) 390 return false; 391 392 if (GVal->hasLocalLinkage()) { 393 unsigned LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass); 394 LWGOT->getOperand(0).setReg(LWGOTDef); 395 396 MachineInstr *ADDiu = 397 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 398 .addDef(I.getOperand(0).getReg()) 399 .addReg(LWGOTDef) 400 .addGlobalAddress(GVal); 401 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); 402 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) 403 return false; 404 } 405 } else { 406 unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 407 408 MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) 409 .addDef(LUiReg) 410 .addGlobalAddress(GVal); 411 LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI); 412 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) 413 return false; 414 415 MachineInstr *ADDiu = 416 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 417 .addDef(I.getOperand(0).getReg()) 418 .addUse(LUiReg) 419 .addGlobalAddress(GVal); 420 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); 421 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) 422 return false; 423 } 424 I.eraseFromParent(); 425 return true; 426 } 427 case G_ICMP: { 428 struct Instr { 429 unsigned Opcode, Def, LHS, RHS; 430 Instr(unsigned Opcode, unsigned Def, unsigned LHS, unsigned RHS) 431 : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){}; 432 433 bool hasImm() const { 434 if (Opcode == Mips::SLTiu || Opcode == Mips::XORi) 435 return true; 436 return false; 437 } 438 }; 439 440 SmallVector<struct Instr, 2> Instructions; 441 unsigned ICMPReg = I.getOperand(0).getReg(); 442 unsigned Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass); 443 unsigned LHS = I.getOperand(2).getReg(); 444 unsigned RHS = I.getOperand(3).getReg(); 445 CmpInst::Predicate Cond = 446 static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate()); 447 448 switch (Cond) { 449 case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1 450 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); 451 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1); 452 break; 453 case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS) 454 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); 455 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp); 456 break; 457 case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS 458 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS); 459 break; 460 case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS) 461 Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS); 462 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 463 break; 464 case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS 465 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS); 466 break; 467 case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS) 468 Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS); 469 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 470 break; 471 case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS 472 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS); 473 break; 474 case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS) 475 Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS); 476 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 477 break; 478 case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS 479 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS); 480 break; 481 case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS) 482 Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS); 483 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); 484 break; 485 default: 486 return false; 487 } 488 489 MachineIRBuilder B(I); 490 for (const struct Instr &Instruction : Instructions) { 491 MachineInstrBuilder MIB = B.buildInstr( 492 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS}); 493 494 if (Instruction.hasImm()) 495 MIB.addImm(Instruction.RHS); 496 else 497 MIB.addUse(Instruction.RHS); 498 499 if (!MIB.constrainAllUses(TII, TRI, RBI)) 500 return false; 501 } 502 503 I.eraseFromParent(); 504 return true; 505 } 506 case G_FCMP: { 507 unsigned MipsFCMPCondCode; 508 bool isLogicallyNegated; 509 switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>( 510 I.getOperand(1).getPredicate())) { 511 case CmpInst::FCMP_UNO: // Unordered 512 case CmpInst::FCMP_ORD: // Ordered (OR) 513 MipsFCMPCondCode = Mips::FCOND_UN; 514 isLogicallyNegated = Cond != CmpInst::FCMP_UNO; 515 break; 516 case CmpInst::FCMP_OEQ: // Equal 517 case CmpInst::FCMP_UNE: // Not Equal (NEQ) 518 MipsFCMPCondCode = Mips::FCOND_OEQ; 519 isLogicallyNegated = Cond != CmpInst::FCMP_OEQ; 520 break; 521 case CmpInst::FCMP_UEQ: // Unordered or Equal 522 case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL) 523 MipsFCMPCondCode = Mips::FCOND_UEQ; 524 isLogicallyNegated = Cond != CmpInst::FCMP_UEQ; 525 break; 526 case CmpInst::FCMP_OLT: // Ordered or Less Than 527 case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE) 528 MipsFCMPCondCode = Mips::FCOND_OLT; 529 isLogicallyNegated = Cond != CmpInst::FCMP_OLT; 530 break; 531 case CmpInst::FCMP_ULT: // Unordered or Less Than 532 case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE) 533 MipsFCMPCondCode = Mips::FCOND_ULT; 534 isLogicallyNegated = Cond != CmpInst::FCMP_ULT; 535 break; 536 case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal 537 case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT) 538 MipsFCMPCondCode = Mips::FCOND_OLE; 539 isLogicallyNegated = Cond != CmpInst::FCMP_OLE; 540 break; 541 case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal 542 case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT) 543 MipsFCMPCondCode = Mips::FCOND_ULE; 544 isLogicallyNegated = Cond != CmpInst::FCMP_ULE; 545 break; 546 default: 547 return false; 548 } 549 550 // Default compare result in gpr register will be `true`. 551 // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false 552 // using MOVF_I. When orignal predicate (Cond) is logically negated 553 // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used. 554 unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I; 555 556 unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); 557 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) 558 .addDef(TrueInReg) 559 .addUse(Mips::ZERO) 560 .addImm(1); 561 562 unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits(); 563 unsigned FCMPOpcode = 564 Size == 32 ? Mips::FCMP_S32 565 : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32; 566 MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode)) 567 .addUse(I.getOperand(2).getReg()) 568 .addUse(I.getOperand(3).getReg()) 569 .addImm(MipsFCMPCondCode); 570 if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI)) 571 return false; 572 573 MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode)) 574 .addDef(I.getOperand(0).getReg()) 575 .addUse(Mips::ZERO) 576 .addUse(Mips::FCC0) 577 .addUse(TrueInReg); 578 if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) 579 return false; 580 581 I.eraseFromParent(); 582 return true; 583 } 584 default: 585 return false; 586 } 587 588 I.eraseFromParent(); 589 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 590 } 591 592 namespace llvm { 593 InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM, 594 MipsSubtarget &Subtarget, 595 MipsRegisterBankInfo &RBI) { 596 return new MipsInstructionSelector(TM, Subtarget, RBI); 597 } 598 } // end namespace llvm 599