LLVM  10.0.0svn
LegalizationArtifactCombiner.h
Go to the documentation of this file.
1 //===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- 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 // This file contains some helper functions which try to cleanup artifacts
9 // such as G_TRUNCs/G_[ZSA]EXTENDS that were created during legalization to make
10 // the types match. This file also contains some combines of merges that happens
11 // at the end of the legalization.
12 //===----------------------------------------------------------------------===//
13 
20 #include "llvm/Support/Debug.h"
21 
22 #define DEBUG_TYPE "legalizer"
23 using namespace llvm::MIPatternMatch;
24 
25 namespace llvm {
27  MachineIRBuilder &Builder;
29  const LegalizerInfo &LI;
30 
31  static bool isArtifactCast(unsigned Opc) {
32  switch (Opc) {
33  case TargetOpcode::G_TRUNC:
34  case TargetOpcode::G_SEXT:
35  case TargetOpcode::G_ZEXT:
36  case TargetOpcode::G_ANYEXT:
37  return true;
38  default:
39  return false;
40  }
41  }
42 
43 public:
45  const LegalizerInfo &LI)
46  : Builder(B), MRI(MRI), LI(LI) {}
47 
50  if (MI.getOpcode() != TargetOpcode::G_ANYEXT)
51  return false;
52 
53  Builder.setInstr(MI);
54  Register DstReg = MI.getOperand(0).getReg();
55  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
56 
57  // aext(trunc x) - > aext/copy/trunc x
58  Register TruncSrc;
59  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
60  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
61  Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
62  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
63  return true;
64  }
65 
66  // aext([asz]ext x) -> [asz]ext x
67  Register ExtSrc;
68  MachineInstr *ExtMI;
69  if (mi_match(SrcReg, MRI,
70  m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
71  m_GSExt(m_Reg(ExtSrc)),
72  m_GZExt(m_Reg(ExtSrc)))))) {
73  Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
74  markInstAndDefDead(MI, *ExtMI, DeadInsts);
75  return true;
76  }
77 
78  // Try to fold aext(g_constant) when the larger constant type is legal.
79  // Can't use MIPattern because we don't have a specific constant in mind.
80  auto *SrcMI = MRI.getVRegDef(SrcReg);
81  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
82  const LLT &DstTy = MRI.getType(DstReg);
83  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
84  auto &CstVal = SrcMI->getOperand(1);
85  Builder.buildConstant(
86  DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
87  markInstAndDefDead(MI, *SrcMI, DeadInsts);
88  return true;
89  }
90  }
91  return tryFoldImplicitDef(MI, DeadInsts);
92  }
93 
96 
97  if (MI.getOpcode() != TargetOpcode::G_ZEXT)
98  return false;
99 
100  Builder.setInstr(MI);
101  Register DstReg = MI.getOperand(0).getReg();
102  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
103 
104  // zext(trunc x) - > and (aext/copy/trunc x), mask
105  Register TruncSrc;
106  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
107  LLT DstTy = MRI.getType(DstReg);
108  if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
109  isConstantUnsupported(DstTy))
110  return false;
111  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
112  LLT SrcTy = MRI.getType(SrcReg);
113  APInt Mask = APInt::getAllOnesValue(SrcTy.getScalarSizeInBits());
114  auto MIBMask = Builder.buildConstant(DstTy, Mask.getZExtValue());
115  Builder.buildAnd(DstReg, Builder.buildAnyExtOrTrunc(DstTy, TruncSrc),
116  MIBMask);
117  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
118  return true;
119  }
120 
121  // Try to fold zext(g_constant) when the larger constant type is legal.
122  // Can't use MIPattern because we don't have a specific constant in mind.
123  auto *SrcMI = MRI.getVRegDef(SrcReg);
124  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
125  const LLT &DstTy = MRI.getType(DstReg);
126  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
127  auto &CstVal = SrcMI->getOperand(1);
128  Builder.buildConstant(
129  DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));
130  markInstAndDefDead(MI, *SrcMI, DeadInsts);
131  return true;
132  }
133  }
134  return tryFoldImplicitDef(MI, DeadInsts);
135  }
136 
138  SmallVectorImpl<MachineInstr *> &DeadInsts) {
139 
140  if (MI.getOpcode() != TargetOpcode::G_SEXT)
141  return false;
142 
143  Builder.setInstr(MI);
144  Register DstReg = MI.getOperand(0).getReg();
145  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
146 
147  // sext(trunc x) - > ashr (shl (aext/copy/trunc x), c), c
148  Register TruncSrc;
149  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
150  LLT DstTy = MRI.getType(DstReg);
151  // Guess on the RHS shift amount type, which should be re-legalized if
152  // applicable.
153  if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy, DstTy}}) ||
154  isInstUnsupported({TargetOpcode::G_ASHR, {DstTy, DstTy}}) ||
155  isConstantUnsupported(DstTy))
156  return false;
157  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
158  LLT SrcTy = MRI.getType(SrcReg);
159  unsigned ShAmt = DstTy.getScalarSizeInBits() - SrcTy.getScalarSizeInBits();
160  auto MIBShAmt = Builder.buildConstant(DstTy, ShAmt);
161  auto MIBShl = Builder.buildInstr(
162  TargetOpcode::G_SHL, {DstTy},
163  {Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), MIBShAmt});
164  Builder.buildInstr(TargetOpcode::G_ASHR, {DstReg}, {MIBShl, MIBShAmt});
165  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
166  return true;
167  }
168  return tryFoldImplicitDef(MI, DeadInsts);
169  }
170 
171  /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
173  SmallVectorImpl<MachineInstr *> &DeadInsts) {
174  unsigned Opcode = MI.getOpcode();
175  if (Opcode != TargetOpcode::G_ANYEXT && Opcode != TargetOpcode::G_ZEXT &&
176  Opcode != TargetOpcode::G_SEXT)
177  return false;
178 
179  if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
180  MI.getOperand(1).getReg(), MRI)) {
181  Builder.setInstr(MI);
182  Register DstReg = MI.getOperand(0).getReg();
183  LLT DstTy = MRI.getType(DstReg);
184 
185  if (Opcode == TargetOpcode::G_ANYEXT) {
186  // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF
187  if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
188  return false;
189  LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;);
190  Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
191  } else {
192  // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
193  // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
194  if (isConstantUnsupported(DstTy))
195  return false;
196  LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;);
197  Builder.buildConstant(DstReg, 0);
198  }
199 
200  markInstAndDefDead(MI, *DefMI, DeadInsts);
201  return true;
202  }
203  return false;
204  }
205 
206  static unsigned getMergeOpcode(LLT OpTy, LLT DestTy) {
207  if (OpTy.isVector() && DestTy.isVector())
208  return TargetOpcode::G_CONCAT_VECTORS;
209 
210  if (OpTy.isVector() && !DestTy.isVector())
211  return TargetOpcode::G_BUILD_VECTOR;
212 
213  return TargetOpcode::G_MERGE_VALUES;
214  }
215 
217  SmallVectorImpl<MachineInstr *> &DeadInsts) {
218 
219  if (MI.getOpcode() != TargetOpcode::G_UNMERGE_VALUES)
220  return false;
221 
222  unsigned NumDefs = MI.getNumOperands() - 1;
223  MachineInstr *SrcDef =
224  getDefIgnoringCopies(MI.getOperand(NumDefs).getReg(), MRI);
225  if (!SrcDef)
226  return false;
227 
228  LLT OpTy = MRI.getType(MI.getOperand(NumDefs).getReg());
229  LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
230  MachineInstr *MergeI = SrcDef;
231  unsigned ConvertOp = 0;
232 
233  // Handle intermediate conversions
234  unsigned SrcOp = SrcDef->getOpcode();
235  if (isArtifactCast(SrcOp)) {
236  ConvertOp = SrcOp;
237  MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI);
238  }
239 
240  // FIXME: Handle scalarizing concat_vectors (scalar result type with vector
241  // source)
242  unsigned MergingOpcode = getMergeOpcode(OpTy, DestTy);
243  if (!MergeI || MergeI->getOpcode() != MergingOpcode)
244  return false;
245 
246  const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
247 
248  if (NumMergeRegs < NumDefs) {
249  if (ConvertOp != 0 || NumDefs % NumMergeRegs != 0)
250  return false;
251 
252  Builder.setInstr(MI);
253  // Transform to UNMERGEs, for example
254  // %1 = G_MERGE_VALUES %4, %5
255  // %9, %10, %11, %12 = G_UNMERGE_VALUES %1
256  // to
257  // %9, %10 = G_UNMERGE_VALUES %4
258  // %11, %12 = G_UNMERGE_VALUES %5
259 
260  const unsigned NewNumDefs = NumDefs / NumMergeRegs;
261  for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
262  SmallVector<Register, 2> DstRegs;
263  for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
264  ++j, ++DefIdx)
265  DstRegs.push_back(MI.getOperand(DefIdx).getReg());
266 
267  Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
268  }
269 
270  } else if (NumMergeRegs > NumDefs) {
271  if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
272  return false;
273 
274  Builder.setInstr(MI);
275  // Transform to MERGEs
276  // %6 = G_MERGE_VALUES %17, %18, %19, %20
277  // %7, %8 = G_UNMERGE_VALUES %6
278  // to
279  // %7 = G_MERGE_VALUES %17, %18
280  // %8 = G_MERGE_VALUES %19, %20
281 
282  const unsigned NumRegs = NumMergeRegs / NumDefs;
283  for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
285  for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
286  ++j, ++Idx)
287  Regs.push_back(MergeI->getOperand(Idx).getReg());
288 
289  Builder.buildMerge(MI.getOperand(DefIdx).getReg(), Regs);
290  }
291 
292  } else {
293  LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
294  if (ConvertOp) {
295  Builder.setInstr(MI);
296 
297  for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
298  Register MergeSrc = MergeI->getOperand(Idx + 1).getReg();
299  Builder.buildInstr(ConvertOp, {MI.getOperand(Idx).getReg()},
300  {MergeSrc});
301  }
302 
303  markInstAndDefDead(MI, *MergeI, DeadInsts);
304  return true;
305  }
306  // FIXME: is a COPY appropriate if the types mismatch? We know both
307  // registers are allocatable by now.
308  if (DestTy != MergeSrcTy)
309  return false;
310 
311  for (unsigned Idx = 0; Idx < NumDefs; ++Idx)
312  MRI.replaceRegWith(MI.getOperand(Idx).getReg(),
313  MergeI->getOperand(Idx + 1).getReg());
314  }
315 
316  markInstAndDefDead(MI, *MergeI, DeadInsts);
317  return true;
318  }
319 
320  static bool isMergeLikeOpcode(unsigned Opc) {
321  switch (Opc) {
322  case TargetOpcode::G_MERGE_VALUES:
323  case TargetOpcode::G_BUILD_VECTOR:
324  case TargetOpcode::G_CONCAT_VECTORS:
325  return true;
326  default:
327  return false;
328  }
329  }
330 
332  SmallVectorImpl<MachineInstr *> &DeadInsts) {
333  assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
334 
335  // Try to use the source registers from a G_MERGE_VALUES
336  //
337  // %2 = G_MERGE_VALUES %0, %1
338  // %3 = G_EXTRACT %2, N
339  // =>
340  //
341  // for N < %2.getSizeInBits() / 2
342  // %3 = G_EXTRACT %0, N
343  //
344  // for N >= %2.getSizeInBits() / 2
345  // %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
346 
347  unsigned Src = lookThroughCopyInstrs(MI.getOperand(1).getReg());
348  MachineInstr *MergeI = MRI.getVRegDef(Src);
349  if (!MergeI || !isMergeLikeOpcode(MergeI->getOpcode()))
350  return false;
351 
352  LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
353  LLT SrcTy = MRI.getType(Src);
354 
355  // TODO: Do we need to check if the resulting extract is supported?
356  unsigned ExtractDstSize = DstTy.getSizeInBits();
357  unsigned Offset = MI.getOperand(2).getImm();
358  unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
359  unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
360  unsigned MergeSrcIdx = Offset / MergeSrcSize;
361 
362  // Compute the offset of the last bit the extract needs.
363  unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
364 
365  // Can't handle the case where the extract spans multiple inputs.
366  if (MergeSrcIdx != EndMergeSrcIdx)
367  return false;
368 
369  // TODO: We could modify MI in place in most cases.
370  Builder.setInstr(MI);
371  Builder.buildExtract(
372  MI.getOperand(0).getReg(),
373  MergeI->getOperand(MergeSrcIdx + 1).getReg(),
374  Offset - MergeSrcIdx * MergeSrcSize);
375  markInstAndDefDead(MI, *MergeI, DeadInsts);
376  return true;
377  }
378 
379  /// Try to combine away MI.
380  /// Returns true if it combined away the MI.
381  /// Adds instructions that are dead as a result of the combine
382  /// into DeadInsts, which can include MI.
385  GISelObserverWrapper &WrapperObserver) {
386  // This might be a recursive call, and we might have DeadInsts already
387  // populated. To avoid bad things happening later with multiple vreg defs
388  // etc, process the dead instructions now if any.
389  if (!DeadInsts.empty())
390  deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
391  switch (MI.getOpcode()) {
392  default:
393  return false;
394  case TargetOpcode::G_ANYEXT:
395  return tryCombineAnyExt(MI, DeadInsts);
396  case TargetOpcode::G_ZEXT:
397  return tryCombineZExt(MI, DeadInsts);
398  case TargetOpcode::G_SEXT:
399  return tryCombineSExt(MI, DeadInsts);
400  case TargetOpcode::G_UNMERGE_VALUES:
401  return tryCombineMerges(MI, DeadInsts);
402  case TargetOpcode::G_EXTRACT:
403  return tryCombineExtract(MI, DeadInsts);
404  case TargetOpcode::G_TRUNC: {
405  bool Changed = false;
406  for (auto &Use : MRI.use_instructions(MI.getOperand(0).getReg()))
407  Changed |= tryCombineInstruction(Use, DeadInsts, WrapperObserver);
408  return Changed;
409  }
410  }
411  }
412 
413 private:
414 
415  static unsigned getArtifactSrcReg(const MachineInstr &MI) {
416  switch (MI.getOpcode()) {
417  case TargetOpcode::COPY:
418  case TargetOpcode::G_TRUNC:
419  case TargetOpcode::G_ZEXT:
420  case TargetOpcode::G_ANYEXT:
421  case TargetOpcode::G_SEXT:
422  case TargetOpcode::G_UNMERGE_VALUES:
423  return MI.getOperand(MI.getNumOperands() - 1).getReg();
424  case TargetOpcode::G_EXTRACT:
425  return MI.getOperand(1).getReg();
426  default:
427  llvm_unreachable("Not a legalization artifact happen");
428  }
429  }
430 
431  /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
432  /// dead due to MI being killed, then mark DefMI as dead too.
433  /// Some of the combines (extends(trunc)), try to walk through redundant
434  /// copies in between the extends and the truncs, and this attempts to collect
435  /// the in between copies if they're dead.
436  void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
437  SmallVectorImpl<MachineInstr *> &DeadInsts) {
438  DeadInsts.push_back(&MI);
439 
440  // Collect all the copy instructions that are made dead, due to deleting
441  // this instruction. Collect all of them until the Trunc(DefMI).
442  // Eg,
443  // %1(s1) = G_TRUNC %0(s32)
444  // %2(s1) = COPY %1(s1)
445  // %3(s1) = COPY %2(s1)
446  // %4(s32) = G_ANYEXT %3(s1)
447  // In this case, we would have replaced %4 with a copy of %0,
448  // and as a result, %3, %2, %1 are dead.
449  MachineInstr *PrevMI = &MI;
450  while (PrevMI != &DefMI) {
451  unsigned PrevRegSrc = getArtifactSrcReg(*PrevMI);
452 
453  MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
454  if (MRI.hasOneUse(PrevRegSrc)) {
455  if (TmpDef != &DefMI) {
456  assert((TmpDef->getOpcode() == TargetOpcode::COPY ||
457  isArtifactCast(TmpDef->getOpcode())) &&
458  "Expecting copy or artifact cast here");
459 
460  DeadInsts.push_back(TmpDef);
461  }
462  } else
463  break;
464  PrevMI = TmpDef;
465  }
466  if (PrevMI == &DefMI && MRI.hasOneUse(DefMI.getOperand(0).getReg()))
467  DeadInsts.push_back(&DefMI);
468  }
469 
470  /// Erase the dead instructions in the list and call the observer hooks.
471  /// Normally the Legalizer will deal with erasing instructions that have been
472  /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to
473  /// process instructions which have been marked dead, but otherwise break the
474  /// MIR by introducing multiple vreg defs. For those cases, allow the combines
475  /// to explicitly delete the instructions before we run into trouble.
476  void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts,
477  GISelObserverWrapper &WrapperObserver) {
478  for (auto *DeadMI : DeadInsts) {
479  LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");
480  WrapperObserver.erasingInstr(*DeadMI);
481  DeadMI->eraseFromParentAndMarkDBGValuesForRemoval();
482  }
483  DeadInsts.clear();
484  }
485 
486  /// Checks if the target legalizer info has specified anything about the
487  /// instruction, or if unsupported.
488  bool isInstUnsupported(const LegalityQuery &Query) const {
489  using namespace LegalizeActions;
490  auto Step = LI.getAction(Query);
491  return Step.Action == Unsupported || Step.Action == NotFound;
492  }
493 
494  bool isInstLegal(const LegalityQuery &Query) const {
495  return LI.getAction(Query).Action == LegalizeActions::Legal;
496  }
497 
498  bool isConstantUnsupported(LLT Ty) const {
499  if (!Ty.isVector())
500  return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
501 
502  LLT EltTy = Ty.getElementType();
503  return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
504  isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
505  }
506 
507  /// Looks through copy instructions and returns the actual
508  /// source register.
509  unsigned lookThroughCopyInstrs(Register Reg) {
510  Register TmpReg;
511  while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) {
512  if (MRI.getType(TmpReg).isValid())
513  Reg = TmpReg;
514  else
515  break;
516  }
517  return Reg;
518  }
519 };
520 
521 } // namespace llvm
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1562
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ...
static APInt getAllOnesValue(unsigned numBits)
Get the all-ones value.
Definition: APInt.h:561
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
static unsigned getMergeOpcode(LLT OpTy, LLT DestTy)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
unsigned getScalarSizeInBits() const
The LegalityQuery object bundles together all the information that&#39;s needed to decide whether a given...
bool tryCombineMerges(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
unsigned Reg
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition: Utils.cpp:287
void erasingInstr(MachineInstr &MI) override
An instruction is about to be erased.
MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index)
Build and insert `Res0, ...
bool tryCombineInstruction(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts, GISelObserverWrapper &WrapperObserver)
Try to combine away MI.
Or< Preds... > m_any_of(Preds &&... preds)
bool isVector() const
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:414
A Use represents the edge between a Value definition and its users.
Definition: Use.h:55
MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Res = COPY Op depending on the differing sizes of Res and Op.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
This operation is completely unsupported on the target.
Definition: LegalizerInfo.h:85
LLT getElementType() const
Returns the vector&#39;s element type. Only valid for vector types.
bool tryCombineAnyExt(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
bool mi_match(Reg R, MachineRegisterInfo &MRI, Pattern &&P)
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
And< Preds... > m_all_of(Preds &&... preds)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
Sentinel value for when no action was found in the specified table.
Definition: LegalizerInfo.h:88
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
Helper class to build MachineInstr.
void setInstr(MachineInstr &MI)
Set the insertion point to before MI.
bool isValid() const
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI)
bool tryFoldImplicitDef(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
Definition: Utils.cpp:303
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
MachineInstrBuilder MachineInstrBuilder & DefMI
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
int64_t getImm() const
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
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
void replaceRegWith(unsigned FromReg, unsigned ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:64
bool tryCombineSExt(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
LegalizeAction Action
The action to take or the final answer.
bool hasOneUse(unsigned RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
bool tryCombineZExt(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
iterator_range< use_instr_iterator > use_instructions(unsigned Reg) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
operand_type_match m_Reg()
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:80
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ...
IRTranslator LLVM IR MI
Simple wrapper observer that takes several observers, and calls each one for each event...
Register getReg() const
getReg - Returns the register number.
#define LLVM_DEBUG(X)
Definition: Debug.h:122
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416
bool tryCombineExtract(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
The operation is expected to be selectable directly by the target, and no transformation is necessary...
Definition: LegalizerInfo.h:47
Wrapper class representing virtual and physical registers.
Definition: Register.h:18