LLVM  8.0.1
MipsInstructionSelector.cpp
Go to the documentation of this file.
1 //===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the InstructionSelector class for
11 /// Mips.
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
14 
15 #include "MipsRegisterBankInfo.h"
16 #include "MipsTargetMachine.h"
19 
20 #define DEBUG_TYPE "mips-isel"
21 
22 using namespace llvm;
23 
24 namespace {
25 
26 #define GET_GLOBALISEL_PREDICATE_BITSET
27 #include "MipsGenGlobalISel.inc"
28 #undef GET_GLOBALISEL_PREDICATE_BITSET
29 
30 class MipsInstructionSelector : public InstructionSelector {
31 public:
32  MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
33  const MipsRegisterBankInfo &RBI);
34 
35  bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
36  static const char *getName() { return DEBUG_TYPE; }
37 
38 private:
39  bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
40 
41  const MipsTargetMachine &TM;
42  const MipsSubtarget &STI;
43  const MipsInstrInfo &TII;
44  const MipsRegisterInfo &TRI;
45  const MipsRegisterBankInfo &RBI;
46 
47 #define GET_GLOBALISEL_PREDICATES_DECL
48 #include "MipsGenGlobalISel.inc"
49 #undef GET_GLOBALISEL_PREDICATES_DECL
50 
51 #define GET_GLOBALISEL_TEMPORARIES_DECL
52 #include "MipsGenGlobalISel.inc"
53 #undef GET_GLOBALISEL_TEMPORARIES_DECL
54 };
55 
56 } // end anonymous namespace
57 
58 #define GET_GLOBALISEL_IMPL
59 #include "MipsGenGlobalISel.inc"
60 #undef GET_GLOBALISEL_IMPL
61 
62 MipsInstructionSelector::MipsInstructionSelector(
63  const MipsTargetMachine &TM, const MipsSubtarget &STI,
64  const MipsRegisterBankInfo &RBI)
65  : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
66  TRI(*STI.getRegisterInfo()), RBI(RBI),
67 
69 #include "MipsGenGlobalISel.inc"
72 #include "MipsGenGlobalISel.inc"
74 {
75 }
76 
77 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
79  const RegisterBankInfo &RBI) {
80  unsigned DstReg = I.getOperand(0).getReg();
81  if (TargetRegisterInfo::isPhysicalRegister(DstReg))
82  return true;
83 
84  const TargetRegisterClass *RC = &Mips::GPR32RegClass;
85 
86  if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
87  LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
88  << " operand\n");
89  return false;
90  }
91  return true;
92 }
93 
94 bool MipsInstructionSelector::select(MachineInstr &I,
95  CodeGenCoverage &CoverageInfo) const {
96 
97  MachineBasicBlock &MBB = *I.getParent();
98  MachineFunction &MF = *MBB.getParent();
99  MachineRegisterInfo &MRI = MF.getRegInfo();
100 
101  if (!isPreISelGenericOpcode(I.getOpcode())) {
102  if (I.isCopy())
103  return selectCopy(I, TII, MRI, TRI, RBI);
104 
105  return true;
106  }
107 
108  if (selectImpl(I, CoverageInfo)) {
109  return true;
110  }
111 
112  MachineInstr *MI = nullptr;
113  using namespace TargetOpcode;
114 
115  switch (I.getOpcode()) {
116  case G_GEP: {
117  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu))
118  .add(I.getOperand(0))
119  .add(I.getOperand(1))
120  .add(I.getOperand(2));
121  break;
122  }
123  case G_FRAME_INDEX: {
124  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
125  .add(I.getOperand(0))
126  .add(I.getOperand(1))
127  .addImm(0);
128  break;
129  }
130  case G_STORE:
131  case G_LOAD: {
132  const unsigned DestReg = I.getOperand(0).getReg();
133  const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID();
134  const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
135 
136  if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
137  return false;
138 
139  const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW;
140 
141  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
142  .add(I.getOperand(0))
143  .add(I.getOperand(1))
144  .addImm(0)
145  .addMemOperand(*I.memoperands_begin());
146  break;
147  }
148  case G_UDIV:
149  case G_UREM:
150  case G_SDIV:
151  case G_SREM: {
152  unsigned HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass);
153  bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV;
154  bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV;
155 
156  MachineInstr *PseudoDIV, *PseudoMove;
157  PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(),
158  TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV))
159  .addDef(HILOReg)
160  .add(I.getOperand(1))
161  .add(I.getOperand(2));
162  if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI))
163  return false;
164 
165  PseudoMove = BuildMI(MBB, I, I.getDebugLoc(),
166  TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI))
167  .addDef(I.getOperand(0).getReg())
168  .addUse(HILOReg);
169  if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI))
170  return false;
171 
172  I.eraseFromParent();
173  return true;
174  }
175  case G_SELECT: {
176  // Handle operands with pointer type.
177  MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I))
178  .add(I.getOperand(0))
179  .add(I.getOperand(2))
180  .add(I.getOperand(1))
181  .add(I.getOperand(3));
182  break;
183  }
184  case G_CONSTANT: {
185  int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue();
186  unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
187  MachineInstr *LUi, *ORi;
188 
189  LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
190  .addDef(LUiReg)
191  .addImm(Imm >> 16);
192 
193  ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi))
194  .addDef(I.getOperand(0).getReg())
195  .addUse(LUiReg)
196  .addImm(Imm & 0xFFFF);
197 
198  if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
199  return false;
200  if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI))
201  return false;
202 
203  I.eraseFromParent();
204  return true;
205  }
206  case G_GLOBAL_VALUE: {
207  if (MF.getTarget().isPositionIndependent())
208  return false;
209 
210  const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal();
211  unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
212  MachineInstr *LUi, *ADDiu;
213 
214  LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi))
215  .addDef(LUiReg)
216  .addGlobalAddress(GVal);
218 
219  ADDiu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu))
220  .addDef(I.getOperand(0).getReg())
221  .addUse(LUiReg)
222  .addGlobalAddress(GVal);
224 
225  if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI))
226  return false;
227  if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI))
228  return false;
229 
230  I.eraseFromParent();
231  return true;
232  }
233  case G_ICMP: {
234  struct Instr {
235  unsigned Opcode, Def, LHS, RHS;
236  Instr(unsigned Opcode, unsigned Def, unsigned LHS, unsigned RHS)
237  : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){};
238 
239  bool hasImm() const {
240  if (Opcode == Mips::SLTiu || Opcode == Mips::XORi)
241  return true;
242  return false;
243  }
244  };
245 
246  SmallVector<struct Instr, 2> Instructions;
247  unsigned ICMPReg = I.getOperand(0).getReg();
248  unsigned Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass);
249  unsigned LHS = I.getOperand(2).getReg();
250  unsigned RHS = I.getOperand(3).getReg();
251  CmpInst::Predicate Cond =
252  static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
253 
254  switch (Cond) {
255  case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1
256  Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
257  Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1);
258  break;
259  case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS)
260  Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS);
261  Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp);
262  break;
263  case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS
264  Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS);
265  break;
266  case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS)
267  Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS);
268  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
269  break;
270  case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS
271  Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS);
272  break;
273  case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS)
274  Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS);
275  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
276  break;
277  case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS
278  Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS);
279  break;
280  case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS)
281  Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS);
282  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
283  break;
284  case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS
285  Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS);
286  break;
287  case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS)
288  Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS);
289  Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1);
290  break;
291  default:
292  return false;
293  }
294 
295  MachineIRBuilder B(I);
296  for (const struct Instr &Instruction : Instructions) {
298  Instruction.Opcode, {Instruction.Def}, {Instruction.LHS});
299 
300  if (Instruction.hasImm())
301  MIB.addImm(Instruction.RHS);
302  else
303  MIB.addUse(Instruction.RHS);
304 
305  if (!MIB.constrainAllUses(TII, TRI, RBI))
306  return false;
307  }
308 
309  I.eraseFromParent();
310  return true;
311  }
312  default:
313  return false;
314  }
315 
316  I.eraseFromParent();
317  return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
318 }
319 
320 namespace llvm {
322  MipsSubtarget &Subtarget,
323  MipsRegisterBankInfo &RBI) {
324  return new MipsInstructionSelector(TM, Subtarget, RBI);
325 }
326 } // end namespace llvm
const MachineInstrBuilder & add(const MachineOperand &MO) const
This class represents lattice values for constants.
Definition: AllocatorList.h:24
void setTargetFlags(unsigned F)
#define GET_GLOBALISEL_TEMPORARIES_INIT
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:383
#define DEBUG_TYPE
unsigned getReg() const
getReg - Returns the register number.
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...
unsigned const TargetRegisterInfo * TRI
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
Holds all the information related to register banks.
const HexagonInstrInfo * TII
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:409
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:138
bool hasImm(uint64_t TSFlags)
Definition: X86BaseInfo.h:592
InstructionSelector * createMipsInstructionSelector(const MipsTargetMachine &, MipsSubtarget &, MipsRegisterBankInfo &)
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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:646
bool isCopy() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition: MCInstrInfo.h:51
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:534
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:847
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
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:88
This file declares the MachineIRBuilder class.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:254
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.
void emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:652
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:482
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
#define I(x, y, z)
Definition: MD5.cpp:58
static const TargetRegisterClass * constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
#define GET_GLOBALISEL_PREDICATES_INIT
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
Definition: TargetOpcodes.h:31
IRTranslator LLVM IR MI
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
#define LLVM_DEBUG(X)
Definition: Debug.h:123
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
const ConstantInt * getCImm() const
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:48
unsigned getPredicate() const