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