LLVM  9.0.0svn
MipsInstructionSelector.cpp
Go to the documentation of this file.
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 
15 #include "MipsMachineFunction.h"
16 #include "MipsRegisterBankInfo.h"
17 #include "MipsTargetMachine.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(Register DestReg, APInt Imm,
42  MachineIRBuilder &B) const;
44  const TargetRegisterClass *
45  getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB,
46  const RegisterBankInfo &RBI) const;
47 
48  const MipsTargetMachine &TM;
49  const MipsSubtarget &STI;
50  const MipsInstrInfo &TII;
51  const MipsRegisterInfo &TRI;
52  const MipsRegisterBankInfo &RBI;
53 
54 #define GET_GLOBALISEL_PREDICATES_DECL
55 #include "MipsGenGlobalISel.inc"
56 #undef GET_GLOBALISEL_PREDICATES_DECL
57 
58 #define GET_GLOBALISEL_TEMPORARIES_DECL
59 #include "MipsGenGlobalISel.inc"
60 #undef GET_GLOBALISEL_TEMPORARIES_DECL
61 };
62 
63 } // end anonymous namespace
64 
65 #define GET_GLOBALISEL_IMPL
66 #include "MipsGenGlobalISel.inc"
67 #undef GET_GLOBALISEL_IMPL
68 
69 MipsInstructionSelector::MipsInstructionSelector(
70  const MipsTargetMachine &TM, const MipsSubtarget &STI,
71  const MipsRegisterBankInfo &RBI)
72  : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
73  TRI(*STI.getRegisterInfo()), RBI(RBI),
74 
76 #include "MipsGenGlobalISel.inc"
79 #include "MipsGenGlobalISel.inc"
81 {
82 }
83 
85  MachineRegisterInfo &MRI) const {
86  Register DstReg = I.getOperand(0).getReg();
87  if (TargetRegisterInfo::isPhysicalRegister(DstReg))
88  return true;
89 
90  const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
91  const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
92 
93  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
94  if (RegBank->getID() == Mips::FPRBRegBankID) {
95  if (DstSize == 32)
96  RC = &Mips::FGR32RegClass;
97  else if (DstSize == 64)
98  RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
99  else
100  llvm_unreachable("Unsupported destination size");
101  }
102  if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
103  LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
104  << " operand\n");
105  return false;
106  }
107  return true;
108 }
109 
110 const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank(
111  unsigned OpSize, const RegisterBank &RB,
112  const RegisterBankInfo &RBI) const {
113  if (RB.getID() == Mips::GPRBRegBankID)
114  return &Mips::GPR32RegClass;
115 
116  if (RB.getID() == Mips::FPRBRegBankID)
117  return OpSize == 32
118  ? &Mips::FGR32RegClass
119  : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass
120  : &Mips::AFGR64RegClass;
121 
122  llvm_unreachable("getRegClassForTypeOnBank can't find register class.");
123  return nullptr;
124 }
125 
126 bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
127  MachineIRBuilder &B) const {
128  assert(Imm.getBitWidth() == 32 && "Unsupported immediate size.");
129  // Ori zero extends immediate. Used for values with zeros in high 16 bits.
130  if (Imm.getHiBits(16).isNullValue()) {
131  MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
132  .addImm(Imm.getLoBits(16).getLimitedValue());
133  return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
134  }
135  // Lui places immediate in high 16 bits and sets low 16 bits to zero.
136  if (Imm.getLoBits(16).isNullValue()) {
137  MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {})
138  .addImm(Imm.getHiBits(16).getLimitedValue());
139  return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
140  }
141  // ADDiu sign extends immediate. Used for values with 1s in high 17 bits.
142  if (Imm.isSignedIntN(16)) {
143  MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
144  .addImm(Imm.getLoBits(16).getLimitedValue());
145  return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
146  }
147  // Values that cannot be materialized with single immediate instruction.
148  Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
149  MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {})
150  .addImm(Imm.getHiBits(16).getLimitedValue());
151  MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg})
152  .addImm(Imm.getLoBits(16).getLimitedValue());
153  if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
154  return false;
155  if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
156  return false;
157  return true;
158 }
159 
160 /// Returning Opc indicates that we failed to select MIPS instruction opcode.
161 static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes,
162  unsigned RegBank, bool isFP64) {
163  bool isStore = Opc == TargetOpcode::G_STORE;
164  if (RegBank == Mips::GPRBRegBankID) {
165  if (isStore)
166  switch (MemSizeInBytes) {
167  case 4:
168  return Mips::SW;
169  case 2:
170  return Mips::SH;
171  case 1:
172  return Mips::SB;
173  default:
174  return Opc;
175  }
176  else
177  // Unspecified extending load is selected into zeroExtending load.
178  switch (MemSizeInBytes) {
179  case 4:
180  return Mips::LW;
181  case 2:
182  return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
183  case 1:
184  return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
185  default:
186  return Opc;
187  }
188  }
189 
190  if (RegBank == Mips::FPRBRegBankID) {
191  switch (MemSizeInBytes) {
192  case 4:
193  return isStore ? Mips::SWC1 : Mips::LWC1;
194  case 8:
195  if (isFP64)
196  return isStore ? Mips::SDC164 : Mips::LDC164;
197  else
198  return isStore ? Mips::SDC1 : Mips::LDC1;
199  default:
200  return Opc;
201  }
202  }
203  return Opc;
204 }
205 
206 bool MipsInstructionSelector::select(MachineInstr &I,
207  CodeGenCoverage &CoverageInfo) const {
208 
209  MachineBasicBlock &MBB = *I.getParent();
210  MachineFunction &MF = *MBB.getParent();
211  MachineRegisterInfo &MRI = MF.getRegInfo();
212 
213  if (!isPreISelGenericOpcode(I.getOpcode())) {
214  if (I.isCopy())
215  return selectCopy(I, MRI);
216 
217  return true;
218  }
219 
220  if (I.getOpcode() == Mips::G_MUL) {
221  MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
222  .add(I.getOperand(0))
223  .add(I.getOperand(1))
224  .add(I.getOperand(2));
225  if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
226  return false;
227  Mul->getOperand(3).setIsDead(true);
228  Mul->getOperand(4).setIsDead(true);
229 
230  I.eraseFromParent();
231  return true;
232  }
233 
234  if (selectImpl(I, CoverageInfo))
235  return true;
236 
237  MachineInstr *MI = nullptr;
238  using namespace TargetOpcode;
239 
240  switch (I.getOpcode()) {
241  case G_UMULH: {
242  Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
243  MachineInstr *PseudoMULTu, *PseudoMove;
244 
245  PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
246  .addDef(PseudoMULTuReg)
247  .add(I.getOperand(1))
248  .add(I.getOperand(2));
249  if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
250  return false;
251 
252  PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
253  .addDef(I.getOperand(0).getReg())
254  .addUse(PseudoMULTuReg);
255  if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
256  return false;
257 
258  I.eraseFromParent();
259  return true;
260  }
261  case G_GEP: {
262  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
263  .add(I.getOperand(0))
264  .add(I.getOperand(1))
265  .add(I.getOperand(2));
266  break;
267  }
268  case G_FRAME_INDEX: {
269  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
270  .add(I.getOperand(0))
271  .add(I.getOperand(1))
272  .addImm(0);
273  break;
274  }
275  case G_BRCOND: {
276  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
277  .add(I.getOperand(0))
278  .addUse(Mips::ZERO)
279  .add(I.getOperand(1));
280  break;
281  }
282  case G_PHI: {
283  const Register DestReg = I.getOperand(0).getReg();
284  const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
285 
286  const TargetRegisterClass *DefRC = nullptr;
287  if (TargetRegisterInfo::isPhysicalRegister(DestReg))
288  DefRC = TRI.getRegClass(DestReg);
289  else
290  DefRC = getRegClassForTypeOnBank(OpSize,
291  *RBI.getRegBank(DestReg, MRI, TRI), RBI);
292 
293  I.setDesc(TII.get(TargetOpcode::PHI));
294  return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
295  }
296  case G_STORE:
297  case G_LOAD:
298  case G_ZEXTLOAD:
299  case G_SEXTLOAD: {
300  const Register DestReg = I.getOperand(0).getReg();
301  const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
302  const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
303  const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();
304 
305  if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32)
306  return false;
307 
308  if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64)
309  return false;
310 
311  const unsigned NewOpc = selectLoadStoreOpCode(
312  I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit());
313  if (NewOpc == I.getOpcode())
314  return false;
315 
316  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
317  .add(I.getOperand(0))
318  .add(I.getOperand(1))
319  .addImm(0)
320  .addMemOperand(*I.memoperands_begin());
321  break;
322  }
323  case G_UDIV:
324  case G_UREM:
325  case G_SDIV:
326  case G_SREM: {
327  Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
328  bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
329  bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
330 
331  MachineInstr *PseudoDIV, *PseudoMove;
332  PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
333  TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
334  .addDef(HILOReg)
335  .add(I.getOperand(1))
336  .add(I.getOperand(2));
337  if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
338  return false;
339 
340  PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
341  TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
342  .addDef(I.getOperand(0).getReg())
343  .addUse(HILOReg);
344  if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
345  return false;
346 
347  I.eraseFromParent();
348  return true;
349  }
350  case G_SELECT: {
351  // Handle operands with pointer type.
352  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
353  .add(I.getOperand(0))
354  .add(I.getOperand(2))
355  .add(I.getOperand(1))
356  .add(I.getOperand(3));
357  break;
358  }
359  case G_CONSTANT: {
360  MachineIRBuilder B(I);
361  if (!materialize32BitImm(I.getOperand(0).getReg(),
362  I.getOperand(1).getCImm()->getValue(), B))
363  return false;
364 
365  I.eraseFromParent();
366  return true;
367  }
368  case G_FCONSTANT: {
369  const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
370  APInt APImm = FPimm.bitcastToAPInt();
371  unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
372 
373  if (Size == 32) {
374  Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
375  MachineIRBuilder B(I);
376  if (!materialize32BitImm(GPRReg, APImm, B))
377  return false;
378 
379  MachineInstrBuilder MTC1 =
380  B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
381  if (!MTC1.constrainAllUses(TII, TRI, RBI))
382  return false;
383  }
384  if (Size == 64) {
385  Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
386  Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
387  MachineIRBuilder B(I);
388  if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
389  return false;
390  if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
391  return false;
392 
393  MachineInstrBuilder PairF64 = B.buildInstr(
394  STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
395  {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
396  if (!PairF64.constrainAllUses(TII, TRI, RBI))
397  return false;
398  }
399 
400  I.eraseFromParent();
401  return true;
402  }
403  case G_FABS: {
404  unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
405  unsigned FABSOpcode =
406  Size == 32 ? Mips::FABS_S
407  : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
408  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
409  .add(I.getOperand(0))
410  .add(I.getOperand(1));
411  break;
412  }
413  case G_FPTOSI: {
414  unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
415  unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
416  (void)ToSize;
417  assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
418  assert((FromSize == 32 || FromSize == 64) &&
419  "Unsupported floating point size for G_FPTOSI");
420 
421  unsigned Opcode;
422  if (FromSize == 32)
423  Opcode = Mips::TRUNC_W_S;
424  else
425  Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
426  unsigned ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
427  MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
428  .addDef(ResultInFPR)
429  .addUse(I.getOperand(1).getReg());
430  if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
431  return false;
432 
433  MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
434  .addDef(I.getOperand(0).getReg())
435  .addUse(ResultInFPR);
436  if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
437  return false;
438 
439  I.eraseFromParent();
440  return true;
441  }
442  case G_GLOBAL_VALUE: {
443  const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
444  if (MF.getTarget().isPositionIndependent()) {
445  MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
446  .addDef(I.getOperand(0).getReg())
447  .addReg(MF.getInfo<MipsFunctionInfo>()
449  .addGlobalAddress(GVal);
450  // Global Values that don't have local linkage are handled differently
451  // when they are part of call sequence. MipsCallLowering::lowerCall
452  // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
453  // MO_GOT_CALL flag when Callee doesn't have local linkage.
456  else
458  LWGOT->addMemOperand(
459  MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
460  MachineMemOperand::MOLoad, 4, 4));
461  if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
462  return false;
463 
464  if (GVal->hasLocalLinkage()) {
465  Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
466  LWGOT->getOperand(0).setReg(LWGOTDef);
467 
468  MachineInstr *ADDiu =
469  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
470  .addDef(I.getOperand(0).getReg())
471  .addReg(LWGOTDef)
472  .addGlobalAddress(GVal);
474  if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
475  return false;
476  }
477  } else {
478  Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
479 
480  MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
481  .addDef(LUiReg)
482  .addGlobalAddress(GVal);
484  if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
485  return false;
486 
487  MachineInstr *ADDiu =
488  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
489  .addDef(I.getOperand(0).getReg())
490  .addUse(LUiReg)
491  .addGlobalAddress(GVal);
493  if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
494  return false;
495  }
496  I.eraseFromParent();
497  return true;
498  }
499  case G_ICMP: {
500  struct Instr {
501  unsigned Opcode;
502  Register Def, LHS, RHS;
503  Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
504  : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
505 
506  bool hasImm() const {
507  if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
508  return true;
509  return false;
510  }
511  };
512 
513  SmallVector<struct Instr, 2> Instructions;
514  Register ICMPReg = I.getOperand(0).getReg();
515  Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
516  Register LHS = I.getOperand(2).getReg();
517  Register RHS = I.getOperand(3).getReg();
518  CmpInst::Predicate Cond =
519  static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
520 
521  switch (Cond) {
522  case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
523  Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
524  Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
525  break;
526  case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
527  Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
528  Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
529  break;
530  case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS
531  Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
532  break;
533  case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
534  Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
535  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
536  break;
537  case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS
538  Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
539  break;
540  case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
541  Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
542  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
543  break;
544  case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS
545  Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
546  break;
547  case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
548  Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
549  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
550  break;
551  case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS
552  Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
553  break;
554  case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
555  Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
556  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
557  break;
558  default:
559  return false;
560  }
561 
562  MachineIRBuilder B(I);
563  for (const struct Instr &Instruction : Instructions) {
565  Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
566 
567  if (Instruction.hasImm())
568  MIB.addImm(Instruction.RHS);
569  else
570  MIB.addUse(Instruction.RHS);
571 
572  if (!MIB.constrainAllUses(TII, TRI, RBI))
573  return false;
574  }
575 
576  I.eraseFromParent();
577  return true;
578  }
579  case G_FCMP: {
580  unsigned MipsFCMPCondCode;
581  bool isLogicallyNegated;
582  switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
583  I.getOperand(1).getPredicate())) {
584  case CmpInst::FCMP_UNO: // Unordered
585  case CmpInst::FCMP_ORD: // Ordered (OR)
586  MipsFCMPCondCode = Mips::FCOND_UN;
587  isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
588  break;
589  case CmpInst::FCMP_OEQ: // Equal
590  case CmpInst::FCMP_UNE: // Not Equal (NEQ)
591  MipsFCMPCondCode = Mips::FCOND_OEQ;
592  isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
593  break;
594  case CmpInst::FCMP_UEQ: // Unordered or Equal
595  case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
596  MipsFCMPCondCode = Mips::FCOND_UEQ;
597  isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
598  break;
599  case CmpInst::FCMP_OLT: // Ordered or Less Than
600  case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
601  MipsFCMPCondCode = Mips::FCOND_OLT;
602  isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
603  break;
604  case CmpInst::FCMP_ULT: // Unordered or Less Than
605  case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
606  MipsFCMPCondCode = Mips::FCOND_ULT;
607  isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
608  break;
609  case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
610  case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
611  MipsFCMPCondCode = Mips::FCOND_OLE;
612  isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
613  break;
614  case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
615  case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
616  MipsFCMPCondCode = Mips::FCOND_ULE;
617  isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
618  break;
619  default:
620  return false;
621  }
622 
623  // Default compare result in gpr register will be `true`.
624  // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
625  // using MOVF_I. When orignal predicate (Cond) is logically negated
626  // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
627  unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
628 
629  unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
630  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
631  .addDef(TrueInReg)
632  .addUse(Mips::ZERO)
633  .addImm(1);
634 
635  unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
636  unsigned FCMPOpcode =
637  Size == 32 ? Mips::FCMP_S32
638  : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
639  MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
640  .addUse(I.getOperand(2).getReg())
641  .addUse(I.getOperand(3).getReg())
642  .addImm(MipsFCMPCondCode);
643  if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
644  return false;
645 
646  MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
647  .addDef(I.getOperand(0).getReg())
648  .addUse(Mips::ZERO)
649  .addUse(Mips::FCC0)
650  .addUse(TrueInReg);
651  if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
652  return false;
653 
654  I.eraseFromParent();
655  return true;
656  }
657  default:
658  return false;
659  }
660 
661  I.eraseFromParent();
662  return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
663 }
664 
665 namespace llvm {
667  MipsSubtarget &Subtarget,
668  MipsRegisterBankInfo &RBI) {
669  return new MipsInstructionSelector(TM, Subtarget, RBI);
670 }
671 } // end namespace llvm
unsigned getTargetFlags() const
const MachineInstrBuilder & add(const MachineOperand &MO) const
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:641
bool hasLocalLinkage() const
Definition: GlobalValue.h:445
This class represents lattice values for constants.
Definition: AllocatorList.h:23
void setTargetFlags(unsigned F)
#define GET_GLOBALISEL_TEMPORARIES_INIT
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:385
#define DEBUG_TYPE
static uint64_t selectImpl(uint64_t CandidateMask, uint64_t &NextInSequenceMask)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
APInt trunc(unsigned width) const
Truncate to new width.
Definition: APInt.cpp:813
unsigned const TargetRegisterInfo * TRI
void setIsDead(bool Val=true)
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1508
Holds all the information related to register banks.
APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
Definition: APInt.cpp:518
const HexagonInstrInfo * TII
const ConstantFP * getFPImm() const
const MachineInstrBuilder & addUse(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
static StringRef getName(Value *V)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
APInt getHiBits(unsigned numBits) const
Compute an APInt containing numBits highbits from this APInt.
Definition: APInt.cpp:513
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, unsigned base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
static bool isStore(int Opcode)
This file declares the targeting of the RegisterBankInfo class for Mips.
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition: Constants.h:137
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
bool hasImm(uint64_t TSFlags)
Definition: X86BaseInfo.h:655
InstructionSelector * createMipsInstructionSelector(const MipsTargetMachine &, MipsSubtarget &, MipsRegisterBankInfo &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineRegisterInfo * getMRI()
Getter for MRI.
MO_GOT_CALL - Represents the offset into the global offset table at which the address of a call site ...
Definition: MipsBaseInfo.h:43
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
const GlobalValue * getGlobal() const
Helper class to build MachineInstr.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:732
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
bool isCopy() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const APFloat & getValueAPF() const
Definition: Constants.h:302
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:536
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
Definition: FileCheck.cpp:218
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Promote Memory to Register
Definition: Mem2Reg.cpp:109
This class provides the information for the target register banks.
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition: Utils.cpp:113
This class implements the register bank concept.
Definition: RegisterBank.h:28
This file declares the MachineIRBuilder class.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
Class for arbitrary precision integers.
Definition: APInt.h:69
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:256
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Provides the logic to select generic machine instructions.
Representation of each machine instruction.
Definition: MachineInstr.h:64
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isPositionIndependent() const
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value...
Definition: APInt.h:481
void setReg(unsigned Reg)
Change the register this operand corresponds to.
#define I(x, y, z)
Definition: MD5.cpp:58
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
uint32_t Size
Definition: Profile.cpp:46
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
Definition: APInt.h:455
#define GET_GLOBALISEL_PREDICATES_INIT
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
Definition: TargetOpcodes.h:30
IRTranslator LLVM IR MI
APInt bitcastToAPInt() const
Definition: APFloat.h:1104
Register getReg() const
getReg - Returns the register number.
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
#define LLVM_DEBUG(X)
Definition: Debug.h:122
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416
const ConstantInt * getCImm() const
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
bool isNullValue() const
Determine if all bits are clear.
Definition: APInt.h:405
Wrapper class representing virtual and physical registers.
Definition: Register.h:18
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47
unsigned getPredicate() const