blob: a03e7ef57b7bf26e4290e56af708ead3093dedbb [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
14#include "MipsRegisterBankInfo.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000015#include "MipsTargetMachine.h"
Petar Jovanovic366857a2018-04-11 15:12:32 +000016#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +000017#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
Petar Jovanovicfac93e22018-02-23 11:06:40 +000018
Petar Jovanovic366857a2018-04-11 15:12:32 +000019#define DEBUG_TYPE "mips-isel"
20
Petar Jovanovicfac93e22018-02-23 11:06:40 +000021using namespace llvm;
22
23namespace {
24
Petar Jovanovic366857a2018-04-11 15:12:32 +000025#define GET_GLOBALISEL_PREDICATE_BITSET
26#include "MipsGenGlobalISel.inc"
27#undef GET_GLOBALISEL_PREDICATE_BITSET
28
Petar Jovanovicfac93e22018-02-23 11:06:40 +000029class MipsInstructionSelector : public InstructionSelector {
30public:
31 MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
32 const MipsRegisterBankInfo &RBI);
33
34 bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
Petar Jovanovic366857a2018-04-11 15:12:32 +000035 static const char *getName() { return DEBUG_TYPE; }
Petar Jovanovicfac93e22018-02-23 11:06:40 +000036
37private:
Petar Jovanovic366857a2018-04-11 15:12:32 +000038 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
Petar Avramovic3e0da142019-03-15 07:07:50 +000039 bool materialize32BitImm(unsigned DestReg, APInt Imm,
40 MachineIRBuilder &B) const;
Petar Avramovica034a642019-03-25 11:38:06 +000041 bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
Petar Jovanovic366857a2018-04-11 15:12:32 +000042
43 const MipsTargetMachine &TM;
44 const MipsSubtarget &STI;
Petar Jovanovicfac93e22018-02-23 11:06:40 +000045 const MipsInstrInfo &TII;
46 const MipsRegisterInfo &TRI;
Petar Jovanovic366857a2018-04-11 15:12:32 +000047 const MipsRegisterBankInfo &RBI;
48
49#define GET_GLOBALISEL_PREDICATES_DECL
50#include "MipsGenGlobalISel.inc"
51#undef GET_GLOBALISEL_PREDICATES_DECL
52
53#define GET_GLOBALISEL_TEMPORARIES_DECL
54#include "MipsGenGlobalISel.inc"
55#undef GET_GLOBALISEL_TEMPORARIES_DECL
Petar Jovanovicfac93e22018-02-23 11:06:40 +000056};
57
58} // end anonymous namespace
59
Petar Jovanovic366857a2018-04-11 15:12:32 +000060#define GET_GLOBALISEL_IMPL
61#include "MipsGenGlobalISel.inc"
62#undef GET_GLOBALISEL_IMPL
63
Petar Jovanovicfac93e22018-02-23 11:06:40 +000064MipsInstructionSelector::MipsInstructionSelector(
65 const MipsTargetMachine &TM, const MipsSubtarget &STI,
66 const MipsRegisterBankInfo &RBI)
Petar Jovanovic366857a2018-04-11 15:12:32 +000067 : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
68 TRI(*STI.getRegisterInfo()), RBI(RBI),
69
70#define GET_GLOBALISEL_PREDICATES_INIT
71#include "MipsGenGlobalISel.inc"
72#undef GET_GLOBALISEL_PREDICATES_INIT
73#define GET_GLOBALISEL_TEMPORARIES_INIT
74#include "MipsGenGlobalISel.inc"
75#undef GET_GLOBALISEL_TEMPORARIES_INIT
76{
77}
78
Petar Avramovica034a642019-03-25 11:38:06 +000079bool MipsInstructionSelector::selectCopy(MachineInstr &I,
80 MachineRegisterInfo &MRI) const {
Petar Jovanovic366857a2018-04-11 15:12:32 +000081 unsigned DstReg = I.getOperand(0).getReg();
82 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
83 return true;
84
Petar Avramovica034a642019-03-25 11:38:06 +000085 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
86 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
Petar Jovanovic366857a2018-04-11 15:12:32 +000087
Petar Avramovica034a642019-03-25 11:38:06 +000088 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
89 if (RegBank->getID() == Mips::FPRBRegBankID) {
90 if (DstSize == 32)
91 RC = &Mips::FGR32RegClass;
92 else if (DstSize == 64)
93 RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
94 else
95 llvm_unreachable("Unsupported destination size");
96 }
Petar Jovanovic366857a2018-04-11 15:12:32 +000097 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +000098 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
99 << " operand\n");
Petar Jovanovic366857a2018-04-11 15:12:32 +0000100 return false;
101 }
102 return true;
103}
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000104
Petar Avramovic3e0da142019-03-15 07:07:50 +0000105bool MipsInstructionSelector::materialize32BitImm(unsigned DestReg, APInt Imm,
106 MachineIRBuilder &B) const {
107 assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
108 // Ori zero extends immediate. Used for values with zeros in high 16 bits.
109 if (Imm.getHiBits(16).isNullValue()) {
110 MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Mips::ZERO})
111 .addImm(Imm.getLoBits(16).getLimitedValue());
112 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
113 }
114 // Lui places immediate in high 16 bits and sets low 16 bits to zero.
115 if (Imm.getLoBits(16).isNullValue()) {
116 MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
117 .addImm(Imm.getHiBits(16).getLimitedValue());
118 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
119 }
120 // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
121 if (Imm.isSignedIntN(16)) {
122 MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Mips::ZERO})
123 .addImm(Imm.getLoBits(16).getLimitedValue());
124 return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
125 }
126 // Values that cannot be materialized with single immediate instruction.
127 unsigned LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
128 MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
129 .addImm(Imm.getHiBits(16).getLimitedValue());
130 MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
131 .addImm(Imm.getLoBits(16).getLimitedValue());
132 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
133 return false;
134 if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
135 return false;
136 return true;
137}
138
Petar Avramovic79df8592019-01-24 10:27:21 +0000139/// Returning Opc indicates that we failed to select MIPS instruction opcode.
140static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes) {
141 if (Opc == TargetOpcode::G_STORE)
142 switch (MemSizeInBytes) {
143 case 4:
144 return Mips::SW;
Petar Avramovicc98b26d2019-02-08 14:27:23 +0000145 case 2:
146 return Mips::SH;
147 case 1:
148 return Mips::SB;
Petar Avramovic79df8592019-01-24 10:27:21 +0000149 default:
150 return Opc;
151 }
152 else
Petar Avramovicc98b26d2019-02-08 14:27:23 +0000153 // Unspecified extending load is selected into zeroExtending load.
Petar Avramovic79df8592019-01-24 10:27:21 +0000154 switch (MemSizeInBytes) {
155 case 4:
156 return Mips::LW;
157 case 2:
158 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
159 case 1:
160 return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
161 default:
162 return Opc;
163 }
164}
165
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000166bool MipsInstructionSelector::select(MachineInstr &I,
167 CodeGenCoverage &CoverageInfo) const {
168
Petar Jovanovic366857a2018-04-11 15:12:32 +0000169 MachineBasicBlock &MBB = *I.getParent();
170 MachineFunction &MF = *MBB.getParent();
171 MachineRegisterInfo &MRI = MF.getRegInfo();
172
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000173 if (!isPreISelGenericOpcode(I.getOpcode())) {
Petar Jovanovic366857a2018-04-11 15:12:32 +0000174 if (I.isCopy())
Petar Avramovica034a642019-03-25 11:38:06 +0000175 return selectCopy(I, MRI);
Petar Jovanovic366857a2018-04-11 15:12:32 +0000176
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000177 return true;
178 }
179
Petar Avramovic3d3120d2019-03-07 13:28:29 +0000180 if (I.getOpcode() == Mips::G_MUL) {
181 MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
182 .add(I.getOperand(0))
183 .add(I.getOperand(1))
184 .add(I.getOperand(2));
185 if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
186 return false;
187 Mul->getOperand(3).setIsDead(true);
188 Mul->getOperand(4).setIsDead(true);
189
190 I.eraseFromParent();
Petar Jovanovic366857a2018-04-11 15:12:32 +0000191 return true;
192 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000193
Petar Avramovic3d3120d2019-03-07 13:28:29 +0000194 if (selectImpl(I, CoverageInfo))
195 return true;
196
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000197 MachineInstr *MI = nullptr;
198 using namespace TargetOpcode;
199
200 switch (I.getOpcode()) {
Petar Avramovica48285a2019-03-01 07:25:44 +0000201 case G_UMULH: {
202 unsigned PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
203 MachineInstr *PseudoMULTu, *PseudoMove;
204
205 PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
206 .addDef(PseudoMULTuReg)
207 .add(I.getOperand(1))
208 .add(I.getOperand(2));
209 if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
210 return false;
211
212 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
213 .addDef(I.getOperand(0).getReg())
214 .addUse(PseudoMULTuReg);
215 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
216 return false;
217
218 I.eraseFromParent();
219 return true;
220 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000221 case G_GEP: {
222 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
223 .add(I.getOperand(0))
224 .add(I.getOperand(1))
225 .add(I.getOperand(2));
226 break;
227 }
228 case G_FRAME_INDEX: {
229 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
230 .add(I.getOperand(0))
231 .add(I.getOperand(1))
232 .addImm(0);
233 break;
234 }
Petar Avramovic5d9b8ee2019-02-14 11:39:53 +0000235 case G_BRCOND: {
236 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
237 .add(I.getOperand(0))
238 .addUse(Mips::ZERO)
239 .add(I.getOperand(1));
240 break;
241 }
Petar Avramovic14c7ecf2019-02-14 12:36:19 +0000242 case G_PHI: {
243 const unsigned DestReg = I.getOperand(0).getReg();
244 const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
245 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
246
247 if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
248 return false;
249
250 const TargetRegisterClass *DefRC = &Mips::GPR32RegClass;
251 I.setDesc(TII.get(TargetOpcode::PHI));
252 return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
253 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000254 case G_STORE:
Petar Avramovic79df8592019-01-24 10:27:21 +0000255 case G_LOAD:
256 case G_ZEXTLOAD:
257 case G_SEXTLOAD: {
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000258 const unsigned DestReg = I.getOperand(0).getReg();
259 const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
260 const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
Petar Avramovic79df8592019-01-24 10:27:21 +0000261 const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000262
263 if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
264 return false;
265
Petar Avramovic79df8592019-01-24 10:27:21 +0000266 const unsigned NewOpc =
267 selectLoadStoreOpCode(I.getOpcode(), OpMemSizeInBytes);
268 if (NewOpc == I.getOpcode())
269 return false;
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000270
271 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
272 .add(I.getOperand(0))
273 .add(I.getOperand(1))
274 .addImm(0)
275 .addMemOperand(*I.memoperands_begin());
276 break;
277 }
Petar Avramovic0a5e4eb2018-12-18 15:59:51 +0000278 case G_UDIV:
279 case G_UREM:
280 case G_SDIV:
281 case G_SREM: {
282 unsigned HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
283 bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
284 bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
285
286 MachineInstr *PseudoDIV, *PseudoMove;
287 PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
288 TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
289 .addDef(HILOReg)
290 .add(I.getOperand(1))
291 .add(I.getOperand(2));
292 if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
293 return false;
294
295 PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
296 TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
297 .addDef(I.getOperand(0).getReg())
298 .addUse(HILOReg);
299 if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
300 return false;
301
302 I.eraseFromParent();
303 return true;
304 }
Petar Avramovic09dff332018-12-25 14:42:30 +0000305 case G_SELECT: {
306 // Handle operands with pointer type.
307 MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
308 .add(I.getOperand(0))
309 .add(I.getOperand(2))
310 .add(I.getOperand(1))
311 .add(I.getOperand(3));
312 break;
313 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000314 case G_CONSTANT: {
Petar Avramovic3e0da142019-03-15 07:07:50 +0000315 MachineIRBuilder B(I);
316 if (!materialize32BitImm(I.getOperand(0).getReg(),
317 I.getOperand(1).getCImm()->getValue(), B))
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000318 return false;
319
320 I.eraseFromParent();
321 return true;
322 }
Petar Avramovic1af05df2019-03-28 16:58:12 +0000323 case G_FCONSTANT: {
324 const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
325 APInt APImm = FPimm.bitcastToAPInt();
326 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
327
328 if (Size == 32) {
329 unsigned GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
330 MachineIRBuilder B(I);
331 if (!materialize32BitImm(GPRReg, APImm, B))
332 return false;
333
334 MachineInstrBuilder MTC1 =
335 B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
336 if (!MTC1.constrainAllUses(TII, TRI, RBI))
337 return false;
338 }
339 if (Size == 64) {
340 unsigned GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
341 unsigned GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
342 MachineIRBuilder B(I);
343 if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
344 return false;
345 if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
346 return false;
347
348 MachineInstrBuilder PairF64 = B.buildInstr(
349 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
350 {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
351 if (!PairF64.constrainAllUses(TII, TRI, RBI))
352 return false;
353 }
354
355 I.eraseFromParent();
356 return true;
357 }
Petar Jovanovic64c10ba2018-08-01 09:03:23 +0000358 case G_GLOBAL_VALUE: {
359 if (MF.getTarget().isPositionIndependent())
360 return false;
361
362 const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
363 unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
364 MachineInstr *LUi, *ADDiu;
365
366 LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
367 .addDef(LUiReg)
368 .addGlobalAddress(GVal);
369 LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI);
370
371 ADDiu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
372 .addDef(I.getOperand(0).getReg())
373 .addUse(LUiReg)
374 .addGlobalAddress(GVal);
375 ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO);
376
377 if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
378 return false;
379 if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
380 return false;
381
382 I.eraseFromParent();
383 return true;
384 }
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000385 case G_ICMP: {
386 struct Instr {
387 unsigned Opcode, Def, LHS, RHS;
388 Instr(unsigned Opcode, unsigned Def, unsigned LHS, unsigned RHS)
389 : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000390
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000391 bool hasImm() const {
392 if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
393 return true;
394 return false;
395 }
396 };
397
398 SmallVector<struct Instr, 2> Instructions;
399 unsigned ICMPReg = I.getOperand(0).getReg();
400 unsigned Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
401 unsigned LHS = I.getOperand(2).getReg();
402 unsigned RHS = I.getOperand(3).getReg();
403 CmpInst::Predicate Cond =
404 static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
405
406 switch (Cond) {
407 case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
408 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
409 Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
410 break;
411 case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
412 Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
413 Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
414 break;
415 case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS
416 Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
417 break;
418 case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
419 Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
420 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
421 break;
422 case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS
423 Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
424 break;
425 case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
426 Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
427 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
428 break;
429 case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS
430 Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
431 break;
432 case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
433 Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
434 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
435 break;
436 case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS
437 Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
438 break;
439 case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
440 Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
441 Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
442 break;
443 default:
444 return false;
445 }
446
447 MachineIRBuilder B(I);
448 for (const struct Instr &Instruction : Instructions) {
Aditya Nandakumarcef44a22018-12-11 00:48:50 +0000449 MachineInstrBuilder MIB = B.buildInstr(
450 Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
Petar Jovanovicce4dd0a2018-09-10 15:56:52 +0000451
452 if (Instruction.hasImm())
453 MIB.addImm(Instruction.RHS);
454 else
455 MIB.addUse(Instruction.RHS);
456
457 if (!MIB.constrainAllUses(TII, TRI, RBI))
458 return false;
459 }
460
461 I.eraseFromParent();
462 return true;
463 }
Petar Jovanovic021e4c82018-07-16 13:29:32 +0000464 default:
465 return false;
466 }
467
468 I.eraseFromParent();
469 return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
Petar Jovanovicfac93e22018-02-23 11:06:40 +0000470}
471
472namespace llvm {
473InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM,
474 MipsSubtarget &Subtarget,
475 MipsRegisterBankInfo &RBI) {
476 return new MipsInstructionSelector(TM, Subtarget, RBI);
477}
478} // end namespace llvm