blob: 9952b5c4588269702590dc5b177a46f96d5efce0 [file] [log] [blame]
Petar Jovanovicfac93e22018-02-23 11:06:40 +00001//===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Petar Jovanovicfac93e22018-02-23 11:06:40 +00006//
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
Petar Avramovic22e99c42019-06-05 14:03:13 +000014#include "MCTargetDesc/MipsInstPrinter.h"
Petar Avramovicefcd3c02019-05-31 08:27:06 +000015#include "MipsMachineFunction.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000016#include "MipsRegisterBankInfo.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000017#include "MipsTargetMachine.h"
Petar Jovanovic366857a2018-04-11 15:12:32 +000018#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +000019#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
Petar Avramoviccaef9302019-08-08 10:21:12 +000020#include "llvm/CodeGen/MachineJumpTableInfo.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000021
Petar Jovanovic366857a2018-04-11 15:12:32 +000022#define DEBUG_TYPE "mips-isel"
23
Petar Jovanovicfac93e22018-02-23 11:06:40 +000024using namespace llvm;
25
26namespace {
27
Petar Jovanovic366857a2018-04-11 15:12:32 +000028#define GET_GLOBALISEL_PREDICATE_BITSET
29#include "MipsGenGlobalISel.inc"
30#undef GET_GLOBALISEL_PREDICATE_BITSET
31
Petar Jovanovicfac93e22018-02-23 11:06:40 +000032class MipsInstructionSelector : public InstructionSelector {
33public:
34 MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
35 const MipsRegisterBankInfo &RBI);
36
Amara Emersone14c91b2019-08-13 06:26:59 +000037 bool select(MachineInstr &I) override;
Petar Jovanovic366857a2018-04-11 15:12:32 +000038 static const char *getName() { return DEBUG_TYPE; }
Petar Jovanovicfac93e22018-02-23 11:06:40 +000039
40private:
Petar Jovanovic366857a2018-04-11 15:12:32 +000041 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +000042 bool materialize32BitImm(Register DestReg, APInt Imm,
Petar Avramovic3e0da142019-03-15 07:07:50 +000043 MachineIRBuilder &B) const;
Petar Avramovica034a642019-03-25 11:38:06 +000044 bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
Petar Avramovic7d0778e2019-07-10 13:18:13 +000045 const TargetRegisterClass *
46 getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB,
47 const RegisterBankInfo &RBI) const;
Petar Avramovic599591f2019-10-15 09:30:08 +000048 unsigned selectLoadStoreOpCode(MachineInstr &I,
49 MachineRegisterInfo &MRI) const;
Petar Jovanovic366857a2018-04-11 15:12:32 +000050
51 const MipsTargetMachine &TM;
52 const MipsSubtarget &STI;
Petar Jovanovicfac93e22018-02-23 11:06:40 +000053 const MipsInstrInfo &TII;
54 const MipsRegisterInfo &TRI;
Petar Jovanovic366857a2018-04-11 15:12:32 +000055 const MipsRegisterBankInfo &RBI;
56
57#define GET_GLOBALISEL_PREDICATES_DECL
58#include "MipsGenGlobalISel.inc"
59#undef GET_GLOBALISEL_PREDICATES_DECL
60
61#define GET_GLOBALISEL_TEMPORARIES_DECL
62#include "MipsGenGlobalISel.inc"
63#undef GET_GLOBALISEL_TEMPORARIES_DECL
Petar Jovanovicfac93e22018-02-23 11:06:40 +000064};
65
66} // end anonymous namespace
67
Petar Jovanovic366857a2018-04-11 15:12:32 +000068#define GET_GLOBALISEL_IMPL
69#include "MipsGenGlobalISel.inc"
70#undef GET_GLOBALISEL_IMPL
71
Petar Jovanovicfac93e22018-02-23 11:06:40 +000072MipsInstructionSelector::MipsInstructionSelector(
73 const MipsTargetMachine &TM, const MipsSubtarget &STI,
74 const MipsRegisterBankInfo &RBI)
Petar Jovanovic366857a2018-04-11 15:12:32 +000075 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
76 TRI(*STI.getRegisterInfo()), RBI(RBI),
77
78#define GET_GLOBALISEL_PREDICATES_INIT
79#include "MipsGenGlobalISel.inc"
80#undef GET_GLOBALISEL_PREDICATES_INIT
81#define GET_GLOBALISEL_TEMPORARIES_INIT
82#include "MipsGenGlobalISel.inc"
83#undef GET_GLOBALISEL_TEMPORARIES_INIT
84{
85}
86
Petar Avramovica034a642019-03-25 11:38:06 +000087bool MipsInstructionSelector::selectCopy(MachineInstr &I,
88 MachineRegisterInfo &MRI) const {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +000089 Register DstReg = I.getOperand(0).getReg();
Daniel Sanders2bea69b2019-08-01 23:27:28 +000090 if (Register::isPhysicalRegister(DstReg))
Petar Jovanovic366857a2018-04-11 15:12:32 +000091 return true;
92
Petar Avramovica034a642019-03-25 11:38:06 +000093 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
94 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Petar Jovanovic366857a2018-04-11 15:12:32 +000095
Petar Avramovica034a642019-03-25 11:38:06 +000096 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
97 if (RegBank->getID() == Mips::FPRBRegBankID) {
98 if (DstSize == 32)
99 RC = &Mips::FGR32RegClass;
100 else if (DstSize == 64)
101 RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
102 else
103 llvm_unreachable("Unsupported destination size");
104 }
Petar Jovanovic366857a2018-04-11 15:12:32 +0000105 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000106 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
107 << " operand\n");
Petar Jovanovic366857a2018-04-11 15:12:32 +0000108 return false;
109 }
110 return true;
111}
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000112
Petar Avramovic7d0778e2019-07-10 13:18:13 +0000113const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
114 unsigned OpSize, const RegisterBank &RB,
115 const RegisterBankInfo &RBI) const {
116 if (RB.getID() == Mips::GPRBRegBankID)
117 return &Mips::GPR32RegClass;
118
119 if (RB.getID() == Mips::FPRBRegBankID)
120 return OpSize == 32
121 ? &Mips::FGR32RegClass
122 : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass
123 : &Mips::AFGR64RegClass;
124
125 llvm_unreachable("getRegClassForTypeOnBank can't find register class.");
126 return nullptr;
127}
128
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000129bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
Petar Avramovic3e0da142019-03-15 07:07:50 +0000130 MachineIRBuilder &B) const {
131 assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
132 // Ori zero extends immediate. Used for values with zeros in high 16 bits.
133 if (Imm.getHiBits(16).isNullValue()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000134 MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
Petar Avramovic3e0da142019-03-15 07:07:50 +0000135 .addImm(Imm.getLoBits(16).getLimitedValue());
136 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
137 }
138 // Lui places immediate in high 16 bits and sets low 16 bits to zero.
139 if (Imm.getLoBits(16).isNullValue()) {
140 MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
141 .addImm(Imm.getHiBits(16).getLimitedValue());
142 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
143 }
144 // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
145 if (Imm.isSignedIntN(16)) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000146 MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
Petar Avramovic3e0da142019-03-15 07:07:50 +0000147 .addImm(Imm.getLoBits(16).getLimitedValue());
148 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
149 }
150 // Values that cannot be materialized with single immediate instruction.
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000151 Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
Petar Avramovic3e0da142019-03-15 07:07:50 +0000152 MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
153 .addImm(Imm.getHiBits(16).getLimitedValue());
154 MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
155 .addImm(Imm.getLoBits(16).getLimitedValue());
156 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
157 return false;
158 if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
159 return false;
160 return true;
161}
162
Petar Avramovic79df8592019-01-24 10:27:21 +0000163/// Returning Opc indicates that we failed to select MIPS instruction opcode.
Petar Avramovic599591f2019-10-15 09:30:08 +0000164unsigned
165MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I,
166 MachineRegisterInfo &MRI) const {
167 STI.getRegisterInfo();
168 const Register DestReg = I.getOperand(0).getReg();
169 const unsigned RegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
170 const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize();
171 unsigned Opc = I.getOpcode();
172 const bool isStore = Opc == TargetOpcode::G_STORE;
Petar Avramovic7b314912019-07-10 12:55:21 +0000173 if (RegBank == Mips::GPRBRegBankID) {
174 if (isStore)
175 switch (MemSizeInBytes) {
176 case 4:
177 return Mips::SW;
178 case 2:
179 return Mips::SH;
180 case 1:
181 return Mips::SB;
182 default:
183 return Opc;
184 }
185 else
186 // Unspecified extending load is selected into zeroExtending load.
187 switch (MemSizeInBytes) {
188 case 4:
189 return Mips::LW;
190 case 2:
191 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
192 case 1:
193 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
194 default:
195 return Opc;
196 }
197 }
198
199 if (RegBank == Mips::FPRBRegBankID) {
Petar Avramovic79df8592019-01-24 10:27:21 +0000200 switch (MemSizeInBytes) {
201 case 4:
Petar Avramovic7b314912019-07-10 12:55:21 +0000202 return isStore ? Mips::SWC1 : Mips::LWC1;
203 case 8:
Petar Avramovic599591f2019-10-15 09:30:08 +0000204 if (STI.isFP64bit())
Petar Avramovic7b314912019-07-10 12:55:21 +0000205 return isStore ? Mips::SDC164 : Mips::LDC164;
206 else
207 return isStore ? Mips::SDC1 : Mips::LDC1;
Petar Avramovic599591f2019-10-15 09:30:08 +0000208 case 16: {
209 assert(STI.hasMSA() && "Vector instructions require target with MSA.");
210 const unsigned VectorElementSizeInBytes =
211 MRI.getType(DestReg).getElementType().getSizeInBytes();
212 if (VectorElementSizeInBytes == 1)
213 return isStore ? Mips::ST_B : Mips::LD_B;
214 if (VectorElementSizeInBytes == 2)
215 return isStore ? Mips::ST_H : Mips::LD_H;
216 if (VectorElementSizeInBytes == 4)
217 return isStore ? Mips::ST_W : Mips::LD_W;
218 if (VectorElementSizeInBytes == 8)
219 return isStore ? Mips::ST_D : Mips::LD_D;
220 return Opc;
221 }
Petar Avramovic79df8592019-01-24 10:27:21 +0000222 default:
223 return Opc;
224 }
Petar Avramovic7b314912019-07-10 12:55:21 +0000225 }
226 return Opc;
Petar Avramovic79df8592019-01-24 10:27:21 +0000227}
228
Amara Emersone14c91b2019-08-13 06:26:59 +0000229bool MipsInstructionSelector::select(MachineInstr &I) {
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000230
Petar Jovanovic366857a2018-04-11 15:12:32 +0000231 MachineBasicBlock &MBB = *I.getParent();
232 MachineFunction &MF = *MBB.getParent();
233 MachineRegisterInfo &MRI = MF.getRegInfo();
234
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000235 if (!isPreISelGenericOpcode(I.getOpcode())) {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000236 if (I.isCopy())
Petar Avramovica034a642019-03-25 11:38:06 +0000237 return selectCopy(I, MRI);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000238
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000239 return true;
240 }
241
Petar Avramovicd1815da2019-10-23 11:22:07 +0200242 if (I.getOpcode() == Mips::G_MUL &&
243 (RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI)->getID() ==
244 Mips::GPRBRegBankID)) {
Petar Avramovic3d3120d2019-03-07 13:28:29 +0000245 MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
246 .add(I.getOperand(0))
247 .add(I.getOperand(1))
248 .add(I.getOperand(2));
249 if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
250 return false;
251 Mul->getOperand(3).setIsDead(true);
252 Mul->getOperand(4).setIsDead(true);
253
254 I.eraseFromParent();
Petar Jovanovic366857a2018-04-11 15:12:32 +0000255 return true;
256 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000257
Amara Emersone14c91b2019-08-13 06:26:59 +0000258 if (selectImpl(I, *CoverageInfo))
Petar Avramovic3d3120d2019-03-07 13:28:29 +0000259 return true;
260
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000261 MachineInstr *MI = nullptr;
262 using namespace TargetOpcode;
263
264 switch (I.getOpcode()) {
Petar Avramovica48285a2019-03-01 07:25:44 +0000265 case G_UMULH: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000266 Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
Petar Avramovica48285a2019-03-01 07:25:44 +0000267 MachineInstr *PseudoMULTu, *PseudoMove;
268
269 PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
270 .addDef(PseudoMULTuReg)
271 .add(I.getOperand(1))
272 .add(I.getOperand(2));
273 if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
274 return false;
275
276 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
277 .addDef(I.getOperand(0).getReg())
278 .addUse(PseudoMULTuReg);
279 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
280 return false;
281
282 I.eraseFromParent();
283 return true;
284 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000285 case G_GEP: {
286 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
287 .add(I.getOperand(0))
288 .add(I.getOperand(1))
289 .add(I.getOperand(2));
290 break;
291 }
Petar Avramovicb1fc6f62019-07-26 13:08:06 +0000292 case G_INTTOPTR:
293 case G_PTRTOINT: {
294 I.setDesc(TII.get(COPY));
295 return selectCopy(I, MRI);
296 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000297 case G_FRAME_INDEX: {
298 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
299 .add(I.getOperand(0))
300 .add(I.getOperand(1))
301 .addImm(0);
302 break;
303 }
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +0000304 case G_BRCOND: {
305 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
306 .add(I.getOperand(0))
307 .addUse(Mips::ZERO)
308 .add(I.getOperand(1));
309 break;
310 }
Petar Avramoviccaef9302019-08-08 10:21:12 +0000311 case G_BRJT: {
312 unsigned EntrySize =
313 MF.getJumpTableInfo()->getEntrySize(MF.getDataLayout());
314 assert(isPowerOf2_32(EntrySize) &&
315 "Non-power-of-two jump-table entry size not supported.");
316
317 Register JTIndex = MRI.createVirtualRegister(&Mips::GPR32RegClass);
318 MachineInstr *SLL = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SLL))
319 .addDef(JTIndex)
320 .addUse(I.getOperand(2).getReg())
321 .addImm(Log2_32(EntrySize));
322 if (!constrainSelectedInstRegOperands(*SLL, TII, TRI, RBI))
323 return false;
324
325 Register DestAddress = MRI.createVirtualRegister(&Mips::GPR32RegClass);
326 MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
327 .addDef(DestAddress)
328 .addUse(I.getOperand(0).getReg())
329 .addUse(JTIndex);
330 if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
331 return false;
332
333 Register Dest = MRI.createVirtualRegister(&Mips::GPR32RegClass);
334 MachineInstr *LW =
335 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
336 .addDef(Dest)
337 .addUse(DestAddress)
338 .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_LO)
339 .addMemOperand(MF.getMachineMemOperand(
340 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, 4));
341 if (!constrainSelectedInstRegOperands(*LW, TII, TRI, RBI))
342 return false;
343
344 if (MF.getTarget().isPositionIndependent()) {
345 Register DestTmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
346 LW->getOperand(0).setReg(DestTmp);
347 MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
348 .addDef(Dest)
349 .addUse(DestTmp)
350 .addUse(MF.getInfo<MipsFunctionInfo>()
351 ->getGlobalBaseRegForGlobalISel());
352 if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
353 return false;
354 }
355
356 MachineInstr *Branch =
357 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
358 .addUse(Dest);
359 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
360 return false;
361
362 I.eraseFromParent();
363 return true;
364 }
Petar Avramovicff6ac1e2019-09-12 11:44:36 +0000365 case G_BRINDIRECT: {
366 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
367 .add(I.getOperand(0));
368 break;
369 }
Petar Avramovic14c7ecf2019-02-14 12:36:19 +0000370 case G_PHI: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000371 const Register DestReg = I.getOperand(0).getReg();
Petar Avramovic14c7ecf2019-02-14 12:36:19 +0000372 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
373
Petar Avramovic7d0778e2019-07-10 13:18:13 +0000374 const TargetRegisterClass *DefRC = nullptr;
Daniel Sanders2bea69b2019-08-01 23:27:28 +0000375 if (Register::isPhysicalRegister(DestReg))
Petar Avramovic7d0778e2019-07-10 13:18:13 +0000376 DefRC = TRI.getRegClass(DestReg);
377 else
378 DefRC = getRegClassForTypeOnBank(OpSize,
379 *RBI.getRegBank(DestReg, MRI, TRI), RBI);
Petar Avramovic14c7ecf2019-02-14 12:36:19 +0000380
Petar Avramovic14c7ecf2019-02-14 12:36:19 +0000381 I.setDesc(TII.get(TargetOpcode::PHI));
382 return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
383 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000384 case G_STORE:
Petar Avramovic79df8592019-01-24 10:27:21 +0000385 case G_LOAD:
386 case G_ZEXTLOAD:
387 case G_SEXTLOAD: {
Petar Avramovic599591f2019-10-15 09:30:08 +0000388 const unsigned NewOpc = selectLoadStoreOpCode(I, MRI);
Petar Avramovic79df8592019-01-24 10:27:21 +0000389 if (NewOpc == I.getOpcode())
390 return false;
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000391
Petar Avramovic8a40ced2019-08-01 09:40:13 +0000392 MachineOperand BaseAddr = I.getOperand(1);
393 int64_t SignedOffset = 0;
394 // Try to fold load/store + G_GEP + G_CONSTANT
395 // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate
396 // %Addr:(p0) = G_GEP %BaseAddr, %SignedOffset
397 // %LoadResult/%StoreSrc = load/store %Addr(p0)
398 // into:
399 // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate
400
401 MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg());
402 if (Addr->getOpcode() == G_GEP) {
403 MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg());
404 if (Offset->getOpcode() == G_CONSTANT) {
405 APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue();
406 if (OffsetValue.isSignedIntN(16)) {
407 BaseAddr = Addr->getOperand(1);
408 SignedOffset = OffsetValue.getSExtValue();
409 }
410 }
411 }
412
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000413 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
414 .add(I.getOperand(0))
Petar Avramovic8a40ced2019-08-01 09:40:13 +0000415 .add(BaseAddr)
416 .addImm(SignedOffset)
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000417 .addMemOperand(*I.memoperands_begin());
418 break;
419 }
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000420 case G_UDIV:
421 case G_UREM:
422 case G_SDIV:
423 case G_SREM: {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000424 Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000425 bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
426 bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
427
428 MachineInstr *PseudoDIV, *PseudoMove;
429 PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
430 TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
431 .addDef(HILOReg)
432 .add(I.getOperand(1))
433 .add(I.getOperand(2));
434 if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
435 return false;
436
437 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
438 TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
439 .addDef(I.getOperand(0).getReg())
440 .addUse(HILOReg);
441 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
442 return false;
443
444 I.eraseFromParent();
445 return true;
446 }
Petar Avramovic09dff332018-12-25 14:42:30 +0000447 case G_SELECT: {
448 // Handle operands with pointer type.
449 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
450 .add(I.getOperand(0))
451 .add(I.getOperand(2))
452 .add(I.getOperand(1))
453 .add(I.getOperand(3));
454 break;
455 }
Petar Avramovic75e43a62019-09-12 11:32:38 +0000456 case G_IMPLICIT_DEF: {
457 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
458 .add(I.getOperand(0));
459
460 // Set class based on register bank, there can be fpr and gpr implicit def.
461 MRI.setRegClass(MI->getOperand(0).getReg(),
462 getRegClassForTypeOnBank(
463 MRI.getType(I.getOperand(0).getReg()).getSizeInBits(),
464 *RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI),
465 RBI));
466 break;
467 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000468 case G_CONSTANT: {
Petar Avramovic3e0da142019-03-15 07:07:50 +0000469 MachineIRBuilder B(I);
470 if (!materialize32BitImm(I.getOperand(0).getReg(),
471 I.getOperand(1).getCImm()->getValue(), B))
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000472 return false;
473
474 I.eraseFromParent();
475 return true;
476 }
Petar Avramovic1af05df2019-03-28 16:58:12 +0000477 case G_FCONSTANT: {
478 const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
479 APInt APImm = FPimm.bitcastToAPInt();
480 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
481
482 if (Size == 32) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000483 Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
Petar Avramovic1af05df2019-03-28 16:58:12 +0000484 MachineIRBuilder B(I);
485 if (!materialize32BitImm(GPRReg, APImm, B))
486 return false;
487
488 MachineInstrBuilder MTC1 =
489 B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
490 if (!MTC1.constrainAllUses(TII, TRI, RBI))
491 return false;
492 }
493 if (Size == 64) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000494 Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
495 Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
Petar Avramovic1af05df2019-03-28 16:58:12 +0000496 MachineIRBuilder B(I);
497 if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
498 return false;
499 if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
500 return false;
501
502 MachineInstrBuilder PairF64 = B.buildInstr(
503 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
504 {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
505 if (!PairF64.constrainAllUses(TII, TRI, RBI))
506 return false;
507 }
508
509 I.eraseFromParent();
510 return true;
511 }
Petar Avramovic0a1fd352019-06-06 09:22:37 +0000512 case G_FABS: {
513 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
514 unsigned FABSOpcode =
515 Size == 32 ? Mips::FABS_S
516 : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
517 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
518 .add(I.getOperand(0))
519 .add(I.getOperand(1));
520 break;
521 }
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000522 case G_FPTOSI: {
523 unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
524 unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
Fangrui Songddd056c2019-06-21 01:51:50 +0000525 (void)ToSize;
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000526 assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
527 assert((FromSize == 32 || FromSize == 64) &&
528 "Unsupported floating point size for G_FPTOSI");
529
530 unsigned Opcode;
531 if (FromSize == 32)
532 Opcode = Mips::TRUNC_W_S;
533 else
534 Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
Daniel Sanders0c476112019-08-15 19:22:08 +0000535 Register ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
Petar Avramovic4b4dae12019-06-20 08:52:53 +0000536 MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
537 .addDef(ResultInFPR)
538 .addUse(I.getOperand(1).getReg());
539 if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
540 return false;
541
542 MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
543 .addDef(I.getOperand(0).getReg())
544 .addUse(ResultInFPR);
545 if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
546 return false;
547
548 I.eraseFromParent();
549 return true;
550 }
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000551 case G_GLOBAL_VALUE: {
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000552 const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000553 if (MF.getTarget().isPositionIndependent()) {
554 MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
555 .addDef(I.getOperand(0).getReg())
556 .addReg(MF.getInfo<MipsFunctionInfo>()
557 ->getGlobalBaseRegForGlobalISel())
558 .addGlobalAddress(GVal);
559 // Global Values that don't have local linkage are handled differently
560 // when they are part of call sequence. MipsCallLowering::lowerCall
561 // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
562 // MO_GOT_CALL flag when Callee doesn't have local linkage.
563 if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL)
564 LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL);
565 else
566 LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT);
567 LWGOT->addMemOperand(
568 MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
569 MachineMemOperand::MOLoad, 4, 4));
570 if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
571 return false;
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000572
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000573 if (GVal->hasLocalLinkage()) {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000574 Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000575 LWGOT->getOperand(0).setReg(LWGOTDef);
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000576
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000577 MachineInstr *ADDiu =
578 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000579 .addDef(I.getOperand(0).getReg())
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000580 .addReg(LWGOTDef)
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000581 .addGlobalAddress(GVal);
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000582 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
583 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
584 return false;
585 }
586 } else {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000587 Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000588
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000589 MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
590 .addDef(LUiReg)
591 .addGlobalAddress(GVal);
592 LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
593 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
594 return false;
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000595
Petar Avramovicefcd3c02019-05-31 08:27:06 +0000596 MachineInstr *ADDiu =
597 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
598 .addDef(I.getOperand(0).getReg())
599 .addUse(LUiReg)
600 .addGlobalAddress(GVal);
601 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
602 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
603 return false;
604 }
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000605 I.eraseFromParent();
606 return true;
607 }
Petar Avramoviccaef9302019-08-08 10:21:12 +0000608 case G_JUMP_TABLE: {
609 if (MF.getTarget().isPositionIndependent()) {
610 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
611 .addDef(I.getOperand(0).getReg())
612 .addReg(MF.getInfo<MipsFunctionInfo>()
613 ->getGlobalBaseRegForGlobalISel())
614 .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_GOT)
615 .addMemOperand(
616 MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
617 MachineMemOperand::MOLoad, 4, 4));
618 } else {
619 MI =
620 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
621 .addDef(I.getOperand(0).getReg())
622 .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_HI);
623 }
624 break;
625 }
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000626 case G_ICMP: {
627 struct Instr {
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000628 unsigned Opcode;
629 Register Def, LHS, RHS;
630 Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000631 : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000632
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000633 bool hasImm() const {
634 if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
635 return true;
636 return false;
637 }
638 };
639
640 SmallVector<struct Instr, 2> Instructions;
Matt Arsenaultfaeaedf2019-06-24 16:16:12 +0000641 Register ICMPReg = I.getOperand(0).getReg();
642 Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
643 Register LHS = I.getOperand(2).getReg();
644 Register RHS = I.getOperand(3).getReg();
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000645 CmpInst::Predicate Cond =
646 static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
647
648 switch (Cond) {
649 case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
650 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
651 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
652 break;
653 case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
654 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
655 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
656 break;
657 case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS
658 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
659 break;
660 case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
661 Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
662 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
663 break;
664 case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS
665 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
666 break;
667 case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
668 Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
669 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
670 break;
671 case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS
672 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
673 break;
674 case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
675 Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
676 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
677 break;
678 case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS
679 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
680 break;
681 case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
682 Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
683 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
684 break;
685 default:
686 return false;
687 }
688
689 MachineIRBuilder B(I);
690 for (const struct Instr &Instruction : Instructions) {
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000691 MachineInstrBuilder MIB = B.buildInstr(
692 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000693
694 if (Instruction.hasImm())
695 MIB.addImm(Instruction.RHS);
696 else
697 MIB.addUse(Instruction.RHS);
698
699 if (!MIB.constrainAllUses(TII, TRI, RBI))
700 return false;
701 }
702
703 I.eraseFromParent();
704 return true;
705 }
Petar Avramovic22e99c42019-06-05 14:03:13 +0000706 case G_FCMP: {
707 unsigned MipsFCMPCondCode;
708 bool isLogicallyNegated;
709 switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
710 I.getOperand(1).getPredicate())) {
711 case CmpInst::FCMP_UNO: // Unordered
712 case CmpInst::FCMP_ORD: // Ordered (OR)
713 MipsFCMPCondCode = Mips::FCOND_UN;
714 isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
715 break;
716 case CmpInst::FCMP_OEQ: // Equal
717 case CmpInst::FCMP_UNE: // Not Equal (NEQ)
718 MipsFCMPCondCode = Mips::FCOND_OEQ;
719 isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
720 break;
721 case CmpInst::FCMP_UEQ: // Unordered or Equal
722 case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
723 MipsFCMPCondCode = Mips::FCOND_UEQ;
724 isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
725 break;
726 case CmpInst::FCMP_OLT: // Ordered or Less Than
727 case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
728 MipsFCMPCondCode = Mips::FCOND_OLT;
729 isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
730 break;
731 case CmpInst::FCMP_ULT: // Unordered or Less Than
732 case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
733 MipsFCMPCondCode = Mips::FCOND_ULT;
734 isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
735 break;
736 case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
737 case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
738 MipsFCMPCondCode = Mips::FCOND_OLE;
739 isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
740 break;
741 case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
742 case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
743 MipsFCMPCondCode = Mips::FCOND_ULE;
744 isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
745 break;
746 default:
747 return false;
748 }
749
750 // Default compare result in gpr register will be `true`.
751 // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
752 // using MOVF_I. When orignal predicate (Cond) is logically negated
753 // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
754 unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
755
Daniel Sanders0c476112019-08-15 19:22:08 +0000756 Register TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
Petar Avramovic22e99c42019-06-05 14:03:13 +0000757 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
758 .addDef(TrueInReg)
759 .addUse(Mips::ZERO)
760 .addImm(1);
761
762 unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
763 unsigned FCMPOpcode =
764 Size == 32 ? Mips::FCMP_S32
765 : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
766 MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
767 .addUse(I.getOperand(2).getReg())
768 .addUse(I.getOperand(3).getReg())
769 .addImm(MipsFCMPCondCode);
770 if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
771 return false;
772
773 MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
774 .addDef(I.getOperand(0).getReg())
775 .addUse(Mips::ZERO)
776 .addUse(Mips::FCC0)
777 .addUse(TrueInReg);
778 if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
779 return false;
780
781 I.eraseFromParent();
782 return true;
783 }
Petar Avramovica4bfc8d2019-09-05 11:20:32 +0000784 case G_FENCE: {
785 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
786 break;
787 }
Petar Avramovicc063b0b2019-09-23 08:11:41 +0000788 case G_VASTART: {
789 MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
790 int FI = FuncInfo->getVarArgsFrameIndex();
791
792 Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
793 MachineInstr *LEA_ADDiu =
794 BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
795 .addDef(LeaReg)
796 .addFrameIndex(FI)
797 .addImm(0);
798 if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
799 return false;
800
801 MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
802 .addUse(LeaReg)
803 .addUse(I.getOperand(0).getReg())
804 .addImm(0);
805 if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
806 return false;
807
808 I.eraseFromParent();
809 return true;
810 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000811 default:
812 return false;
813 }
814
815 I.eraseFromParent();
816 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000817}
818
819namespace llvm {
820InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
821 MipsSubtarget &Subtarget,
822 MipsRegisterBankInfo &RBI) {
823 return new MipsInstructionSelector(TM, Subtarget, RBI);
824}
825} // end namespace llvm