LLVM  4.0.0
LegalizerHelper.cpp
Go to the documentation of this file.
1 //===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
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 //
10 /// \file This file implements the LegalizerHelper class to legalize
11 /// individual instructions and the LegalizeMachineIR wrapper pass for the
12 /// primary legalization.
13 //
14 //===----------------------------------------------------------------------===//
15 
20 #include "llvm/Support/Debug.h"
24 
25 #include <sstream>
26 
27 #define DEBUG_TYPE "legalize-mir"
28 
29 using namespace llvm;
30 
32  : MRI(MF.getRegInfo()) {
33  MIRBuilder.setMF(MF);
34 }
35 
39  auto Action = LegalizerInfo.getAction(MI, MRI);
40  switch (std::get<0>(Action)) {
42  return AlreadyLegal;
44  return libcall(MI);
46  return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
48  return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
50  return lower(MI, std::get<1>(Action), std::get<2>(Action));
52  return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
53  default:
54  return UnableToLegalize;
55  }
56 }
57 
62  MIRBuilder.recordInsertions(
63  [&](MachineInstr *MI) { WorkList.push_back(MI); });
64  WorkList.push_back(&MI);
65 
66  bool Changed = false;
67  LegalizeResult Res;
68  unsigned Idx = 0;
69  do {
70  Res = legalizeInstrStep(*WorkList[Idx], LegalizerInfo);
71  if (Res == UnableToLegalize) {
72  MIRBuilder.stopRecordingInsertions();
73  return UnableToLegalize;
74  }
75  Changed |= Res == Legalized;
76  ++Idx;
77  } while (Idx < WorkList.size());
78 
79  MIRBuilder.stopRecordingInsertions();
80 
81  return Changed ? Legalized : AlreadyLegal;
82 }
83 
84 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
86  unsigned Size = Ty.getSizeInBits();
88  for (int i = 0; i < NumParts; ++i) {
90  Indexes.push_back(i * Size);
91  }
92  MIRBuilder.buildExtract(VRegs, Indexes, Reg);
93 }
94 
97  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
98  unsigned Size = Ty.getSizeInBits();
99  MIRBuilder.setInstr(MI);
100 
101  switch (MI.getOpcode()) {
102  default:
103  return UnableToLegalize;
104  case TargetOpcode::G_FREM: {
105  auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
106  Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
107  auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
108  auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
109  const char *Name =
110  TLI.getLibcallName(Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32);
111 
112  CLI.lowerCall(
113  MIRBuilder, MachineOperand::CreateES(Name),
114  {MI.getOperand(0).getReg(), Ty},
115  {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
116  MI.eraseFromParent();
117  return Legalized;
118  }
119  }
120 }
121 
123  unsigned TypeIdx,
124  LLT NarrowTy) {
125  // FIXME: Don't know how to handle secondary types yet.
126  if (TypeIdx != 0)
127  return UnableToLegalize;
128  switch (MI.getOpcode()) {
129  default:
130  return UnableToLegalize;
131  case TargetOpcode::G_ADD: {
132  // Expand in terms of carry-setting/consuming G_ADDE instructions.
133  unsigned NarrowSize = NarrowTy.getSizeInBits();
134  int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
135  NarrowTy.getSizeInBits();
136 
137  MIRBuilder.setInstr(MI);
138 
139  SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
140  SmallVector<uint64_t, 2> Indexes;
141  extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
142  extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
143 
144  unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
145  MIRBuilder.buildConstant(CarryIn, 0);
146 
147  for (int i = 0; i < NumParts; ++i) {
148  unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
149  unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
150 
151  MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
152  Src2Regs[i], CarryIn);
153 
154  DstRegs.push_back(DstReg);
155  Indexes.push_back(i * NarrowSize);
156  CarryIn = CarryOut;
157  }
158  unsigned DstReg = MI.getOperand(0).getReg();
159  MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
160  MI.eraseFromParent();
161  return Legalized;
162  }
163  }
164 }
165 
167 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
168  MIRBuilder.setInstr(MI);
169 
170  switch (MI.getOpcode()) {
171  default:
172  return UnableToLegalize;
173  case TargetOpcode::G_ADD:
174  case TargetOpcode::G_AND:
175  case TargetOpcode::G_MUL:
176  case TargetOpcode::G_OR:
177  case TargetOpcode::G_XOR:
178  case TargetOpcode::G_SUB: {
179  // Perform operation at larger width (any extension is fine here, high bits
180  // don't affect the result) and then truncate the result back to the
181  // original type.
182  unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
183  unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
184  MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
185  MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
186 
187  unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
188  MIRBuilder.buildInstr(MI.getOpcode())
189  .addDef(DstExt)
190  .addUse(Src1Ext)
191  .addUse(Src2Ext);
192 
193  MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
194  MI.eraseFromParent();
195  return Legalized;
196  }
197  case TargetOpcode::G_SDIV:
198  case TargetOpcode::G_UDIV: {
199  unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV
200  ? TargetOpcode::G_SEXT
201  : TargetOpcode::G_ZEXT;
202 
203  unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
204  MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
205  MI.getOperand(1).getReg());
206 
207  unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
208  MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
209  MI.getOperand(2).getReg());
210 
211  unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
212  MIRBuilder.buildInstr(MI.getOpcode())
213  .addDef(ResExt)
214  .addUse(LHSExt)
215  .addUse(RHSExt);
216 
217  MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
218  MI.eraseFromParent();
219  return Legalized;
220  }
221  case TargetOpcode::G_LOAD: {
222  assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
223  WideTy.getSizeInBits() &&
224  "illegal to increase number of bytes loaded");
225 
226  unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
227  MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
228  **MI.memoperands_begin());
229  MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
230  MI.eraseFromParent();
231  return Legalized;
232  }
233  case TargetOpcode::G_STORE: {
234  assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
235  WideTy.getSizeInBits() &&
236  "illegal to increase number of bytes modified by a store");
237 
238  unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
239  MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
240  MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
241  **MI.memoperands_begin());
242  MI.eraseFromParent();
243  return Legalized;
244  }
245  case TargetOpcode::G_CONSTANT: {
246  unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
247  MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
248  MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
249  MI.eraseFromParent();
250  return Legalized;
251  }
252  case TargetOpcode::G_FCONSTANT: {
253  unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
254  MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
255  MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
256  MI.eraseFromParent();
257  return Legalized;
258  }
259  case TargetOpcode::G_BRCOND: {
260  unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
261  MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
262  MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
263  MI.eraseFromParent();
264  return Legalized;
265  }
266  case TargetOpcode::G_ICMP: {
267  assert(TypeIdx == 1 && "unable to legalize predicate");
268  bool IsSigned = CmpInst::isSigned(
269  static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
270  unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
271  unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
272  if (IsSigned) {
273  MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
274  MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
275  } else {
276  MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
277  MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
278  }
279  MIRBuilder.buildICmp(
280  static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
281  MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
282  MI.eraseFromParent();
283  return Legalized;
284  }
285  case TargetOpcode::G_GEP: {
286  assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
287  unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
288  MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
289  MI.getOperand(2).setReg(OffsetExt);
290  return Legalized;
291  }
292  }
293 }
294 
296 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
297  using namespace TargetOpcode;
298  MIRBuilder.setInstr(MI);
299 
300  switch(MI.getOpcode()) {
301  default:
302  return UnableToLegalize;
303  case TargetOpcode::G_SREM:
304  case TargetOpcode::G_UREM: {
305  unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
306  MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
307  .addDef(QuotReg)
308  .addUse(MI.getOperand(1).getReg())
309  .addUse(MI.getOperand(2).getReg());
310 
311  unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
312  MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
313  MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
314  ProdReg);
315  MI.eraseFromParent();
316  return Legalized;
317  }
318  }
319 }
320 
323  LLT NarrowTy) {
324  // FIXME: Don't know how to handle secondary types yet.
325  if (TypeIdx != 0)
326  return UnableToLegalize;
327  switch (MI.getOpcode()) {
328  default:
329  return UnableToLegalize;
330  case TargetOpcode::G_ADD: {
331  unsigned NarrowSize = NarrowTy.getSizeInBits();
332  unsigned DstReg = MI.getOperand(0).getReg();
333  int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
334 
335  MIRBuilder.setInstr(MI);
336 
337  SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
338  SmallVector<uint64_t, 2> Indexes;
339  extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
340  extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
341 
342  for (int i = 0; i < NumParts; ++i) {
343  unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
344  MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
345  DstRegs.push_back(DstReg);
346  Indexes.push_back(i * NarrowSize);
347  }
348 
349  MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
350  MI.eraseFromParent();
351  return Legalized;
352  }
353  }
354 }
static Type * getDoubleTy(LLVMContext &C)
Definition: Type.cpp:158
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:226
LLT getType(unsigned VReg) const
Get the low-level type of VReg or LLT{} if VReg is not a generic (target independent) virtual registe...
LegalizeResult legalizeInstr(MachineInstr &MI, const LegalizerInfo &LegalizerInfo)
size_t i
const ConstantFP * getFPImm() const
MachineBasicBlock * getMBB() const
MachineInstrBuilder buildZExt(unsigned Res, unsigned Op)
Build and insert Res<def> = G_ZEXT Op.
std::pair< LegalizeAction, LLT > getAction(const InstrAspect &Aspect) const
Determine what action should be taken to legalize the given generic instruction opcode, type-index and type.
bool isSigned() const
Determine if this instruction is using a signed comparison.
Definition: InstrTypes.h:1027
static const MCPhysReg VRegs[32]
MachineInstrBuilder buildTrunc(unsigned Res, unsigned Op)
Build and insert Res<def> = G_TRUNC Op.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:664
MachineInstrBuilder buildAnyExt(unsigned Res, unsigned Op)
Build and insert Res<def> = G_ANYEXT Op0.
virtual const CallLowering * getCallLowering() const
unsigned createGenericVirtualRegister(LLT Ty)
Create and return a new generic virtual register with low-level type Ty.
const MachineInstrBuilder & addDef(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
MachineInstrBuilder buildFPTrunc(unsigned Res, unsigned Op)
Build and insert Res<def> = G_FPTRUNC Op.
LegalizerHelper(MachineFunction &MF)
MachineInstrBuilder buildStore(unsigned Val, unsigned Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
static Type * getFloatTy(LLVMContext &C)
Definition: Type.cpp:157
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineInstrBuilder buildFConstant(unsigned Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
Reg
All possible values of the reg field in the ModR/M byte.
MachineInstrBuilder buildExtract(ArrayRef< unsigned > Results, ArrayRef< uint64_t > Indices, unsigned Src)
Build and insert `Res0<def>, ...
MachineFunction & getMF()
Getter for the function we currently build.
void recordInsertions(std::function< void(MachineInstr *)> InsertedInstr)
Control where instructions we create are recorded (typically for visiting again later during legaliza...
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:51
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:273
unsigned const MachineRegisterInfo * MRI
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
Definition: LegalizerInfo.h:69
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
static unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
Get the size in bits of Reg.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:279
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, unsigned Res, unsigned Op0, unsigned Op1)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
void setInstr(MachineInstr &MI)
Set the insertion point to before MI.
void setMF(MachineFunction &)
Setters for the insertion point.
Some kind of error has occurred and we could not legalize this instruction.
Instruction was already legal and no change was made to the MachineFunction.
MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0, unsigned Op1, unsigned CarryIn)
Build and insert Res<def>, CarryOut<def> = G_UADDE Op0, Op1, CarryIn.
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type...
Definition: LegalizerInfo.h:59
The operation should be implemented as a call to some kind of runtime support library.
Definition: LegalizerInfo.h:84
LegalizeResult libcall(MachineInstr &MI)
Legalize an instruction by emiting a runtime library call instead.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
virtual const TargetLowering * getTargetLowering() const
The operation should be implemented in terms of a wider scalar base-type.
Definition: LegalizerInfo.h:64
unsigned getPredicate() const
LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target...
LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
const ConstantInt * getCImm() const
The operation itself must be expressed in terms of simpler actions on this target.
Definition: LegalizerInfo.h:79
static MachineOperand CreateES(const char *SymName, unsigned char TargetFlags=0)
MachineInstrBuilder buildSExt(unsigned Res, unsigned Op)
Build and insert Res<def> = G_SEXT Op.
The operation is expected to be selectable directly by the target, and no transformation is necessary...
Definition: LegalizerInfo.h:54
MachineInstrBuilder buildSequence(unsigned Res, ArrayRef< unsigned > Ops, ArrayRef< uint64_t > Indices)
Build and insert Res<def> = G_SEQUENCE Op0, Idx0...
Representation of each machine instruction.
Definition: MachineInstr.h:52
Instruction has been legalized and the MachineFunction changed.
MachineInstrBuilder buildAdd(unsigned Res, unsigned Op0, unsigned Op1)
Build and insert Res<def> = G_ADD Op0, Op1.
MachineInstrBuilder buildConstant(unsigned Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
void setReg(unsigned Reg)
Change the register this operand corresponds to.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:135
unsigned getReg() const
getReg - Returns the register number.
LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MachineInstrBuilder & addUse(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
This file describes how to lower LLVM calls to machine code calls.
MachineInstrBuilder buildLoad(unsigned Res, unsigned Addr, MachineMemOperand &MMO)
Build and insert Res<def> = G_LOAD Addr, MMO.
IRTranslator LLVM IR MI
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:104
LegalizeResult legalizeInstrStep(MachineInstr &MI, const LegalizerInfo &LegalizerInfo)
Replace MI by a sequence of legal instructions that can implement the same operation.
This file describes how to lower LLVM code to machine code.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:358
MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB)
Build and insert G_BRCOND Tst, Dest.