LLVM  10.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"
21 
22 #define DEBUG_TYPE "mips-isel"
23 
24 using namespace llvm;
25 
26 namespace {
27 
28 #define GET_GLOBALISEL_PREDICATE_BITSET
29 #include "MipsGenGlobalISel.inc"
30 #undef GET_GLOBALISEL_PREDICATE_BITSET
31 
32 class MipsInstructionSelector : public InstructionSelector {
33 public:
34  MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
35  const MipsRegisterBankInfo &RBI);
36 
37  bool select(MachineInstr &I) override;
38  static const char *getName() { return DEBUG_TYPE; }
39 
40 private:
41  bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
42  bool materialize32BitImm(Register DestReg, APInt Imm,
43  MachineIRBuilder &B) const;
45  const TargetRegisterClass *
46  getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB,
47  const RegisterBankInfo &RBI) const;
48  unsigned selectLoadStoreOpCode(MachineInstr &I,
49  MachineRegisterInfo &MRI) const;
50 
51  const MipsTargetMachine &TM;
52  const MipsSubtarget &STI;
53  const MipsInstrInfo &TII;
54  const MipsRegisterInfo &TRI;
55  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
64 };
65 
66 } // end anonymous namespace
67 
68 #define GET_GLOBALISEL_IMPL
69 #include "MipsGenGlobalISel.inc"
70 #undef GET_GLOBALISEL_IMPL
71 
72 MipsInstructionSelector::MipsInstructionSelector(
73  const MipsTargetMachine &TM, const MipsSubtarget &STI,
74  const MipsRegisterBankInfo &RBI)
75  : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
76  TRI(*STI.getRegisterInfo()), RBI(RBI),
77 
79 #include "MipsGenGlobalISel.inc"
82 #include "MipsGenGlobalISel.inc"
84 {
85 }
86 
88  MachineRegisterInfo &MRI) const {
89  Register DstReg = I.getOperand(0).getReg();
90  if (Register::isPhysicalRegister(DstReg))
91  return true;
92 
93  const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
94  const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
95 
96  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  }
105  if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
106  LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
107  << " operand\n");
108  return false;
109  }
110  return true;
111 }
112 
113 const 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 
129 bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
130  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()) {
134  MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)})
135  .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)) {
146  MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)})
147  .addImm(Imm.getLoBits(16).getLimitedValue());
148  return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI);
149  }
150  // Values that cannot be materialized with single immediate instruction.
151  Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass);
152  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 
163 /// Returning Opc indicates that we failed to select MIPS instruction opcode.
164 unsigned
165 MipsInstructionSelector::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;
173  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) {
200  switch (MemSizeInBytes) {
201  case 4:
202  return isStore ? Mips::SWC1 : Mips::LWC1;
203  case 8:
204  if (STI.isFP64bit())
205  return isStore ? Mips::SDC164 : Mips::LDC164;
206  else
207  return isStore ? Mips::SDC1 : Mips::LDC1;
208  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  }
222  default:
223  return Opc;
224  }
225  }
226  return Opc;
227 }
228 
229 bool MipsInstructionSelector::select(MachineInstr &I) {
230 
231  MachineBasicBlock &MBB = *I.getParent();
232  MachineFunction &MF = *MBB.getParent();
233  MachineRegisterInfo &MRI = MF.getRegInfo();
234 
235  if (!isPreISelGenericOpcode(I.getOpcode())) {
236  if (I.isCopy())
237  return selectCopy(I, MRI);
238 
239  return true;
240  }
241 
242  if (I.getOpcode() == Mips::G_MUL) {
243  MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL))
244  .add(I.getOperand(0))
245  .add(I.getOperand(1))
246  .add(I.getOperand(2));
247  if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI))
248  return false;
249  Mul->getOperand(3).setIsDead(true);
250  Mul->getOperand(4).setIsDead(true);
251 
252  I.eraseFromParent();
253  return true;
254  }
255 
256  if (selectImpl(I, *CoverageInfo))
257  return true;
258 
259  MachineInstr *MI = nullptr;
260  using namespace TargetOpcode;
261 
262  switch (I.getOpcode()) {
263  case G_UMULH: {
264  Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
265  MachineInstr *PseudoMULTu, *PseudoMove;
266 
267  PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu))
268  .addDef(PseudoMULTuReg)
269  .add(I.getOperand(1))
270  .add(I.getOperand(2));
271  if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI))
272  return false;
273 
274  PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI))
275  .addDef(I.getOperand(0).getReg())
276  .addUse(PseudoMULTuReg);
277  if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
278  return false;
279 
280  I.eraseFromParent();
281  return true;
282  }
283  case G_GEP: {
284  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
285  .add(I.getOperand(0))
286  .add(I.getOperand(1))
287  .add(I.getOperand(2));
288  break;
289  }
290  case G_INTTOPTR:
291  case G_PTRTOINT: {
292  I.setDesc(TII.get(COPY));
293  return selectCopy(I, MRI);
294  }
295  case G_FRAME_INDEX: {
296  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
297  .add(I.getOperand(0))
298  .add(I.getOperand(1))
299  .addImm(0);
300  break;
301  }
302  case G_BRCOND: {
303  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE))
304  .add(I.getOperand(0))
305  .addUse(Mips::ZERO)
306  .add(I.getOperand(1));
307  break;
308  }
309  case G_BRJT: {
310  unsigned EntrySize =
312  assert(isPowerOf2_32(EntrySize) &&
313  "Non-power-of-two jump-table entry size not supported.");
314 
315  Register JTIndex = MRI.createVirtualRegister(&Mips::GPR32RegClass);
316  MachineInstr *SLL = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SLL))
317  .addDef(JTIndex)
318  .addUse(I.getOperand(2).getReg())
319  .addImm(Log2_32(EntrySize));
320  if (!constrainSelectedInstRegOperands(*SLL, TII, TRI, RBI))
321  return false;
322 
323  Register DestAddress = MRI.createVirtualRegister(&Mips::GPR32RegClass);
324  MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
325  .addDef(DestAddress)
326  .addUse(I.getOperand(0).getReg())
327  .addUse(JTIndex);
328  if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
329  return false;
330 
331  Register Dest = MRI.createVirtualRegister(&Mips::GPR32RegClass);
332  MachineInstr *LW =
333  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
334  .addDef(Dest)
335  .addUse(DestAddress)
337  .addMemOperand(MF.getMachineMemOperand(
338  MachinePointerInfo(), MachineMemOperand::MOLoad, 4, 4));
339  if (!constrainSelectedInstRegOperands(*LW, TII, TRI, RBI))
340  return false;
341 
342  if (MF.getTarget().isPositionIndependent()) {
343  Register DestTmp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
344  LW->getOperand(0).setReg(DestTmp);
345  MachineInstr *ADDu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
346  .addDef(Dest)
347  .addUse(DestTmp)
350  if (!constrainSelectedInstRegOperands(*ADDu, TII, TRI, RBI))
351  return false;
352  }
353 
355  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
356  .addUse(Dest);
357  if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
358  return false;
359 
360  I.eraseFromParent();
361  return true;
362  }
363  case G_BRINDIRECT: {
364  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch))
365  .add(I.getOperand(0));
366  break;
367  }
368  case G_PHI: {
369  const Register DestReg = I.getOperand(0).getReg();
370  const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
371 
372  const TargetRegisterClass *DefRC = nullptr;
373  if (Register::isPhysicalRegister(DestReg))
374  DefRC = TRI.getRegClass(DestReg);
375  else
376  DefRC = getRegClassForTypeOnBank(OpSize,
377  *RBI.getRegBank(DestReg, MRI, TRI), RBI);
378 
379  I.setDesc(TII.get(TargetOpcode::PHI));
380  return RBI.constrainGenericRegister(DestReg, *DefRC, MRI);
381  }
382  case G_STORE:
383  case G_LOAD:
384  case G_ZEXTLOAD:
385  case G_SEXTLOAD: {
386  const unsigned NewOpc = selectLoadStoreOpCode(I, MRI);
387  if (NewOpc == I.getOpcode())
388  return false;
389 
390  MachineOperand BaseAddr = I.getOperand(1);
391  int64_t SignedOffset = 0;
392  // Try to fold load/store + G_GEP + G_CONSTANT
393  // %SignedOffset:(s32) = G_CONSTANT i32 16_bit_signed_immediate
394  // %Addr:(p0) = G_GEP %BaseAddr, %SignedOffset
395  // %LoadResult/%StoreSrc = load/store %Addr(p0)
396  // into:
397  // %LoadResult/%StoreSrc = NewOpc %BaseAddr(p0), 16_bit_signed_immediate
398 
399  MachineInstr *Addr = MRI.getVRegDef(I.getOperand(1).getReg());
400  if (Addr->getOpcode() == G_GEP) {
401  MachineInstr *Offset = MRI.getVRegDef(Addr->getOperand(2).getReg());
402  if (Offset->getOpcode() == G_CONSTANT) {
403  APInt OffsetValue = Offset->getOperand(1).getCImm()->getValue();
404  if (OffsetValue.isSignedIntN(16)) {
405  BaseAddr = Addr->getOperand(1);
406  SignedOffset = OffsetValue.getSExtValue();
407  }
408  }
409  }
410 
411  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
412  .add(I.getOperand(0))
413  .add(BaseAddr)
414  .addImm(SignedOffset)
415  .addMemOperand(*I.memoperands_begin());
416  break;
417  }
418  case G_UDIV:
419  case G_UREM:
420  case G_SDIV:
421  case G_SREM: {
422  Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
423  bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
424  bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
425 
426  MachineInstr *PseudoDIV, *PseudoMove;
427  PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
428  TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
429  .addDef(HILOReg)
430  .add(I.getOperand(1))
431  .add(I.getOperand(2));
432  if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
433  return false;
434 
435  PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
436  TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
437  .addDef(I.getOperand(0).getReg())
438  .addUse(HILOReg);
439  if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
440  return false;
441 
442  I.eraseFromParent();
443  return true;
444  }
445  case G_SELECT: {
446  // Handle operands with pointer type.
447  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
448  .add(I.getOperand(0))
449  .add(I.getOperand(2))
450  .add(I.getOperand(1))
451  .add(I.getOperand(3));
452  break;
453  }
454  case G_IMPLICIT_DEF: {
455  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::IMPLICIT_DEF))
456  .add(I.getOperand(0));
457 
458  // Set class based on register bank, there can be fpr and gpr implicit def.
459  MRI.setRegClass(MI->getOperand(0).getReg(),
460  getRegClassForTypeOnBank(
461  MRI.getType(I.getOperand(0).getReg()).getSizeInBits(),
462  *RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI),
463  RBI));
464  break;
465  }
466  case G_CONSTANT: {
467  MachineIRBuilder B(I);
468  if (!materialize32BitImm(I.getOperand(0).getReg(),
469  I.getOperand(1).getCImm()->getValue(), B))
470  return false;
471 
472  I.eraseFromParent();
473  return true;
474  }
475  case G_FCONSTANT: {
476  const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
477  APInt APImm = FPimm.bitcastToAPInt();
478  unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
479 
480  if (Size == 32) {
481  Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
482  MachineIRBuilder B(I);
483  if (!materialize32BitImm(GPRReg, APImm, B))
484  return false;
485 
486  MachineInstrBuilder MTC1 =
487  B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
488  if (!MTC1.constrainAllUses(TII, TRI, RBI))
489  return false;
490  }
491  if (Size == 64) {
492  Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
493  Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
494  MachineIRBuilder B(I);
495  if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
496  return false;
497  if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
498  return false;
499 
500  MachineInstrBuilder PairF64 = B.buildInstr(
501  STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
502  {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
503  if (!PairF64.constrainAllUses(TII, TRI, RBI))
504  return false;
505  }
506 
507  I.eraseFromParent();
508  return true;
509  }
510  case G_FABS: {
511  unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
512  unsigned FABSOpcode =
513  Size == 32 ? Mips::FABS_S
514  : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32;
515  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode))
516  .add(I.getOperand(0))
517  .add(I.getOperand(1));
518  break;
519  }
520  case G_FPTOSI: {
521  unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits();
522  unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
523  (void)ToSize;
524  assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI");
525  assert((FromSize == 32 || FromSize == 64) &&
526  "Unsupported floating point size for G_FPTOSI");
527 
528  unsigned Opcode;
529  if (FromSize == 32)
530  Opcode = Mips::TRUNC_W_S;
531  else
532  Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32;
533  Register ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass);
534  MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
535  .addDef(ResultInFPR)
536  .addUse(I.getOperand(1).getReg());
537  if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI))
538  return false;
539 
540  MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1))
541  .addDef(I.getOperand(0).getReg())
542  .addUse(ResultInFPR);
543  if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
544  return false;
545 
546  I.eraseFromParent();
547  return true;
548  }
549  case G_GLOBAL_VALUE: {
550  const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
551  if (MF.getTarget().isPositionIndependent()) {
552  MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
553  .addDef(I.getOperand(0).getReg())
554  .addReg(MF.getInfo<MipsFunctionInfo>()
556  .addGlobalAddress(GVal);
557  // Global Values that don't have local linkage are handled differently
558  // when they are part of call sequence. MipsCallLowering::lowerCall
559  // creates G_GLOBAL_VALUE instruction as part of call sequence and adds
560  // MO_GOT_CALL flag when Callee doesn't have local linkage.
563  else
565  LWGOT->addMemOperand(
566  MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
567  MachineMemOperand::MOLoad, 4, 4));
568  if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI))
569  return false;
570 
571  if (GVal->hasLocalLinkage()) {
572  Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass);
573  LWGOT->getOperand(0).setReg(LWGOTDef);
574 
575  MachineInstr *ADDiu =
576  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
577  .addDef(I.getOperand(0).getReg())
578  .addReg(LWGOTDef)
579  .addGlobalAddress(GVal);
581  if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
582  return false;
583  }
584  } else {
585  Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
586 
587  MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
588  .addDef(LUiReg)
589  .addGlobalAddress(GVal);
591  if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
592  return false;
593 
594  MachineInstr *ADDiu =
595  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
596  .addDef(I.getOperand(0).getReg())
597  .addUse(LUiReg)
598  .addGlobalAddress(GVal);
600  if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
601  return false;
602  }
603  I.eraseFromParent();
604  return true;
605  }
606  case G_JUMP_TABLE: {
607  if (MF.getTarget().isPositionIndependent()) {
608  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW))
609  .addDef(I.getOperand(0).getReg())
610  .addReg(MF.getInfo<MipsFunctionInfo>()
612  .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_GOT)
613  .addMemOperand(
614  MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
615  MachineMemOperand::MOLoad, 4, 4));
616  } else {
617  MI =
618  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
619  .addDef(I.getOperand(0).getReg())
620  .addJumpTableIndex(I.getOperand(1).getIndex(), MipsII::MO_ABS_HI);
621  }
622  break;
623  }
624  case G_ICMP: {
625  struct Instr {
626  unsigned Opcode;
627  Register Def, LHS, RHS;
628  Instr(unsigned Opcode, Register Def, Register LHS, Register RHS)
629  : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
630 
631  bool hasImm() const {
632  if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
633  return true;
634  return false;
635  }
636  };
637 
638  SmallVector<struct Instr, 2> Instructions;
639  Register ICMPReg = I.getOperand(0).getReg();
640  Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
641  Register LHS = I.getOperand(2).getReg();
642  Register RHS = I.getOperand(3).getReg();
643  CmpInst::Predicate Cond =
644  static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
645 
646  switch (Cond) {
647  case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
648  Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
649  Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
650  break;
651  case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
652  Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
653  Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
654  break;
655  case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS
656  Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
657  break;
658  case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
659  Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
660  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
661  break;
662  case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS
663  Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
664  break;
665  case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
666  Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
667  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
668  break;
669  case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS
670  Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
671  break;
672  case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
673  Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
674  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
675  break;
676  case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS
677  Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
678  break;
679  case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
680  Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
681  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
682  break;
683  default:
684  return false;
685  }
686 
687  MachineIRBuilder B(I);
688  for (const struct Instr &Instruction : Instructions) {
690  Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
691 
692  if (Instruction.hasImm())
693  MIB.addImm(Instruction.RHS);
694  else
695  MIB.addUse(Instruction.RHS);
696 
697  if (!MIB.constrainAllUses(TII, TRI, RBI))
698  return false;
699  }
700 
701  I.eraseFromParent();
702  return true;
703  }
704  case G_FCMP: {
705  unsigned MipsFCMPCondCode;
706  bool isLogicallyNegated;
707  switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>(
708  I.getOperand(1).getPredicate())) {
709  case CmpInst::FCMP_UNO: // Unordered
710  case CmpInst::FCMP_ORD: // Ordered (OR)
711  MipsFCMPCondCode = Mips::FCOND_UN;
712  isLogicallyNegated = Cond != CmpInst::FCMP_UNO;
713  break;
714  case CmpInst::FCMP_OEQ: // Equal
715  case CmpInst::FCMP_UNE: // Not Equal (NEQ)
716  MipsFCMPCondCode = Mips::FCOND_OEQ;
717  isLogicallyNegated = Cond != CmpInst::FCMP_OEQ;
718  break;
719  case CmpInst::FCMP_UEQ: // Unordered or Equal
720  case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL)
721  MipsFCMPCondCode = Mips::FCOND_UEQ;
722  isLogicallyNegated = Cond != CmpInst::FCMP_UEQ;
723  break;
724  case CmpInst::FCMP_OLT: // Ordered or Less Than
725  case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE)
726  MipsFCMPCondCode = Mips::FCOND_OLT;
727  isLogicallyNegated = Cond != CmpInst::FCMP_OLT;
728  break;
729  case CmpInst::FCMP_ULT: // Unordered or Less Than
730  case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE)
731  MipsFCMPCondCode = Mips::FCOND_ULT;
732  isLogicallyNegated = Cond != CmpInst::FCMP_ULT;
733  break;
734  case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal
735  case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT)
736  MipsFCMPCondCode = Mips::FCOND_OLE;
737  isLogicallyNegated = Cond != CmpInst::FCMP_OLE;
738  break;
739  case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal
740  case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT)
741  MipsFCMPCondCode = Mips::FCOND_ULE;
742  isLogicallyNegated = Cond != CmpInst::FCMP_ULE;
743  break;
744  default:
745  return false;
746  }
747 
748  // Default compare result in gpr register will be `true`.
749  // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false
750  // using MOVF_I. When orignal predicate (Cond) is logically negated
751  // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used.
752  unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I;
753 
754  Register TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
755  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
756  .addDef(TrueInReg)
757  .addUse(Mips::ZERO)
758  .addImm(1);
759 
760  unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
761  unsigned FCMPOpcode =
762  Size == 32 ? Mips::FCMP_S32
763  : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32;
764  MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode))
765  .addUse(I.getOperand(2).getReg())
766  .addUse(I.getOperand(3).getReg())
767  .addImm(MipsFCMPCondCode);
768  if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI))
769  return false;
770 
771  MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode))
772  .addDef(I.getOperand(0).getReg())
773  .addUse(Mips::ZERO)
774  .addUse(Mips::FCC0)
775  .addUse(TrueInReg);
776  if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI))
777  return false;
778 
779  I.eraseFromParent();
780  return true;
781  }
782  case G_FENCE: {
783  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SYNC)).addImm(0);
784  break;
785  }
786  case G_VASTART: {
787  MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
788  int FI = FuncInfo->getVarArgsFrameIndex();
789 
790  Register LeaReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
791  MachineInstr *LEA_ADDiu =
792  BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LEA_ADDiu))
793  .addDef(LeaReg)
794  .addFrameIndex(FI)
795  .addImm(0);
796  if (!constrainSelectedInstRegOperands(*LEA_ADDiu, TII, TRI, RBI))
797  return false;
798 
799  MachineInstr *Store = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::SW))
800  .addUse(LeaReg)
801  .addUse(I.getOperand(0).getReg())
802  .addImm(0);
803  if (!constrainSelectedInstRegOperands(*Store, TII, TRI, RBI))
804  return false;
805 
806  I.eraseFromParent();
807  return true;
808  }
809  default:
810  return false;
811  }
812 
813  I.eraseFromParent();
814  return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
815 }
816 
817 namespace llvm {
819  MipsSubtarget &Subtarget,
820  MipsRegisterBankInfo &RBI) {
821  return new MipsInstructionSelector(TM, Subtarget, RBI);
822 }
823 } // 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:384
#define DEBUG_TYPE
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
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:865
unsigned const TargetRegisterInfo * TRI
void setIsDead(bool Val=true)
unsigned getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1517
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:570
const HexagonInstrInfo * TII
const ConstantFP * getFPImm() const
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:410
APInt getHiBits(unsigned numBits) const
Compute an APInt containing numBits highbits from this APInt.
Definition: APInt.cpp:565
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.
LLT getElementType() const
Returns the vector&#39;s element type. Only valid for vector types.
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
int64_t getSExtValue() const
Get sign extended value.
Definition: APInt.h:1583
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
static bool isStore(int Opcode)
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
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 setReg(Register Reg)
Change the register this operand corresponds to.
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
bool hasImm(uint64_t TSFlags)
Definition: X86BaseInfo.h:655
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
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.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
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
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:465
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...
const MachineInstrBuilder & addFrameIndex(int Idx) const
bool isCopy() const
This class contains a discriminated union of information about pointers in memory operands...
#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:551
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
Definition: FileCheck.cpp:215
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
MachineOperand class - Representation of each machine instruction operand.
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:111
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
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:585
Class for arbitrary precision integers.
Definition: APInt.h:69
unsigned getEntrySize(const DataLayout &TD) const
getEntrySize - Return the size of each entry in the jump table.
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:255
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:63
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
#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
void setRegClass(unsigned Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
APInt bitcastToAPInt() const
Definition: APFloat.h:1109
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 MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:415
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:19
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47
unsigned getPredicate() const