LLVM  14.0.0git
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 
14 #ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
15 #define LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
16 
26 #include "llvm/CodeGen/Register.h"
27 #include "llvm/Support/Debug.h"
28 
29 #define DEBUG_TYPE "legalizer"
30 using namespace llvm::MIPatternMatch;
31 
32 namespace llvm {
36  const LegalizerInfo &LI;
37 
38  static bool isArtifactCast(unsigned Opc) {
39  switch (Opc) {
40  case TargetOpcode::G_TRUNC:
41  case TargetOpcode::G_SEXT:
42  case TargetOpcode::G_ZEXT:
43  case TargetOpcode::G_ANYEXT:
44  return true;
45  default:
46  return false;
47  }
48  }
49 
50 public:
52  const LegalizerInfo &LI)
53  : Builder(B), MRI(MRI), LI(LI) {}
54 
57  SmallVectorImpl<Register> &UpdatedDefs,
58  GISelObserverWrapper &Observer) {
59  assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);
60 
61  Builder.setInstrAndDebugLoc(MI);
62  Register DstReg = MI.getOperand(0).getReg();
63  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
64 
65  // aext(trunc x) - > aext/copy/trunc x
66  Register TruncSrc;
67  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
68  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
69  if (MRI.getType(DstReg) == MRI.getType(TruncSrc))
70  replaceRegOrBuildCopy(DstReg, TruncSrc, MRI, Builder, UpdatedDefs,
71  Observer);
72  else
73  Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
74  UpdatedDefs.push_back(DstReg);
75  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
76  return true;
77  }
78 
79  // aext([asz]ext x) -> [asz]ext x
80  Register ExtSrc;
81  MachineInstr *ExtMI;
82  if (mi_match(SrcReg, MRI,
83  m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
84  m_GSExt(m_Reg(ExtSrc)),
85  m_GZExt(m_Reg(ExtSrc)))))) {
86  Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
87  UpdatedDefs.push_back(DstReg);
88  markInstAndDefDead(MI, *ExtMI, DeadInsts);
89  return true;
90  }
91 
92  // Try to fold aext(g_constant) when the larger constant type is legal.
93  auto *SrcMI = MRI.getVRegDef(SrcReg);
94  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
95  const LLT DstTy = MRI.getType(DstReg);
96  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
97  auto &CstVal = SrcMI->getOperand(1);
98  Builder.buildConstant(
99  DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
100  UpdatedDefs.push_back(DstReg);
101  markInstAndDefDead(MI, *SrcMI, DeadInsts);
102  return true;
103  }
104  }
105  return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
106  }
107 
110  SmallVectorImpl<Register> &UpdatedDefs,
111  GISelObserverWrapper &Observer) {
112  assert(MI.getOpcode() == TargetOpcode::G_ZEXT);
113 
114  Builder.setInstrAndDebugLoc(MI);
115  Register DstReg = MI.getOperand(0).getReg();
116  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
117 
118  // zext(trunc x) - > and (aext/copy/trunc x), mask
119  // zext(sext x) -> and (sext x), mask
120  Register TruncSrc;
121  Register SextSrc;
122  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc))) ||
123  mi_match(SrcReg, MRI, m_GSExt(m_Reg(SextSrc)))) {
124  LLT DstTy = MRI.getType(DstReg);
125  if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
126  isConstantUnsupported(DstTy))
127  return false;
128  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
129  LLT SrcTy = MRI.getType(SrcReg);
130  APInt MaskVal = APInt::getAllOnes(SrcTy.getScalarSizeInBits());
131  auto Mask = Builder.buildConstant(
132  DstTy, MaskVal.zext(DstTy.getScalarSizeInBits()));
133  if (SextSrc && (DstTy != MRI.getType(SextSrc)))
134  SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
135  if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))
136  TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
137  Builder.buildAnd(DstReg, SextSrc ? SextSrc : TruncSrc, Mask);
138  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
139  return true;
140  }
141 
142  // zext(zext x) -> (zext x)
143  Register ZextSrc;
144  if (mi_match(SrcReg, MRI, m_GZExt(m_Reg(ZextSrc)))) {
145  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
146  Observer.changingInstr(MI);
147  MI.getOperand(1).setReg(ZextSrc);
148  Observer.changedInstr(MI);
149  UpdatedDefs.push_back(DstReg);
150  markDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
151  return true;
152  }
153 
154  // Try to fold zext(g_constant) when the larger constant type is legal.
155  auto *SrcMI = MRI.getVRegDef(SrcReg);
156  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
157  const LLT DstTy = MRI.getType(DstReg);
158  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
159  auto &CstVal = SrcMI->getOperand(1);
160  Builder.buildConstant(
161  DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));
162  UpdatedDefs.push_back(DstReg);
163  markInstAndDefDead(MI, *SrcMI, DeadInsts);
164  return true;
165  }
166  }
167  return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
168  }
169 
172  SmallVectorImpl<Register> &UpdatedDefs) {
173  assert(MI.getOpcode() == TargetOpcode::G_SEXT);
174 
175  Builder.setInstrAndDebugLoc(MI);
176  Register DstReg = MI.getOperand(0).getReg();
177  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
178 
179  // sext(trunc x) - > (sext_inreg (aext/copy/trunc x), c)
180  Register TruncSrc;
181  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
182  LLT DstTy = MRI.getType(DstReg);
183  if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))
184  return false;
185  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
186  LLT SrcTy = MRI.getType(SrcReg);
187  uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
188  if (DstTy != MRI.getType(TruncSrc))
189  TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
190  Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits);
191  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
192  return true;
193  }
194 
195  // sext(zext x) -> (zext x)
196  // sext(sext x) -> (sext x)
197  Register ExtSrc;
198  MachineInstr *ExtMI;
199  if (mi_match(SrcReg, MRI,
200  m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)),
201  m_GSExt(m_Reg(ExtSrc)))))) {
202  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
203  Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
204  UpdatedDefs.push_back(DstReg);
205  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
206  return true;
207  }
208 
209  // Try to fold sext(g_constant) when the larger constant type is legal.
210  auto *SrcMI = MRI.getVRegDef(SrcReg);
211  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
212  const LLT DstTy = MRI.getType(DstReg);
213  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
214  auto &CstVal = SrcMI->getOperand(1);
215  Builder.buildConstant(
216  DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
217  UpdatedDefs.push_back(DstReg);
218  markInstAndDefDead(MI, *SrcMI, DeadInsts);
219  return true;
220  }
221  }
222 
223  return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
224  }
225 
228  SmallVectorImpl<Register> &UpdatedDefs,
229  GISelObserverWrapper &Observer) {
230  assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
231 
232  Builder.setInstr(MI);
233  Register DstReg = MI.getOperand(0).getReg();
234  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
235 
236  // Try to fold trunc(g_constant) when the smaller constant type is legal.
237  auto *SrcMI = MRI.getVRegDef(SrcReg);
238  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
239  const LLT DstTy = MRI.getType(DstReg);
240  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
241  auto &CstVal = SrcMI->getOperand(1);
242  Builder.buildConstant(
243  DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits()));
244  UpdatedDefs.push_back(DstReg);
245  markInstAndDefDead(MI, *SrcMI, DeadInsts);
246  return true;
247  }
248  }
249 
250  // Try to fold trunc(merge) to directly use the source of the merge.
251  // This gets rid of large, difficult to legalize, merges
252  if (auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
253  const Register MergeSrcReg = SrcMerge->getSourceReg(0);
254  const LLT MergeSrcTy = MRI.getType(MergeSrcReg);
255  const LLT DstTy = MRI.getType(DstReg);
256 
257  // We can only fold if the types are scalar
258  const unsigned DstSize = DstTy.getSizeInBits();
259  const unsigned MergeSrcSize = MergeSrcTy.getSizeInBits();
260  if (!DstTy.isScalar() || !MergeSrcTy.isScalar())
261  return false;
262 
263  if (DstSize < MergeSrcSize) {
264  // When the merge source is larger than the destination, we can just
265  // truncate the merge source directly
266  if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
267  return false;
268 
269  LLVM_DEBUG(dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
270  << MI);
271 
272  Builder.buildTrunc(DstReg, MergeSrcReg);
273  UpdatedDefs.push_back(DstReg);
274  } else if (DstSize == MergeSrcSize) {
275  // If the sizes match we can simply try to replace the register
276  LLVM_DEBUG(
277  dbgs() << "Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
278  << MI);
279  replaceRegOrBuildCopy(DstReg, MergeSrcReg, MRI, Builder, UpdatedDefs,
280  Observer);
281  } else if (DstSize % MergeSrcSize == 0) {
282  // If the trunc size is a multiple of the merge source size we can use
283  // a smaller merge instead
284  if (isInstUnsupported(
285  {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
286  return false;
287 
288  LLVM_DEBUG(
289  dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
290  << MI);
291 
292  const unsigned NumSrcs = DstSize / MergeSrcSize;
293  assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
294  "trunc(merge) should require less inputs than merge");
295  SmallVector<Register, 8> SrcRegs(NumSrcs);
296  for (unsigned i = 0; i < NumSrcs; ++i)
297  SrcRegs[i] = SrcMerge->getSourceReg(i);
298 
299  Builder.buildMerge(DstReg, SrcRegs);
300  UpdatedDefs.push_back(DstReg);
301  } else {
302  // Unable to combine
303  return false;
304  }
305 
306  markInstAndDefDead(MI, *SrcMerge, DeadInsts);
307  return true;
308  }
309 
310  // trunc(trunc) -> trunc
311  Register TruncSrc;
312  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
313  // Always combine trunc(trunc) since the eventual resulting trunc must be
314  // legal anyway as it must be legal for all outputs of the consumer type
315  // set.
316  LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_TRUNC): " << MI);
317 
318  Builder.buildTrunc(DstReg, TruncSrc);
319  UpdatedDefs.push_back(DstReg);
320  markInstAndDefDead(MI, *MRI.getVRegDef(TruncSrc), DeadInsts);
321  return true;
322  }
323 
324  return false;
325  }
326 
327  /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
330  SmallVectorImpl<Register> &UpdatedDefs) {
331  unsigned Opcode = MI.getOpcode();
332  assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
333  Opcode == TargetOpcode::G_SEXT);
334 
335  if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
336  MI.getOperand(1).getReg(), MRI)) {
337  Builder.setInstr(MI);
338  Register DstReg = MI.getOperand(0).getReg();
339  LLT DstTy = MRI.getType(DstReg);
340 
341  if (Opcode == TargetOpcode::G_ANYEXT) {
342  // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF
343  if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
344  return false;
345  LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;);
346  Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
347  UpdatedDefs.push_back(DstReg);
348  } else {
349  // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
350  // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
351  if (isConstantUnsupported(DstTy))
352  return false;
353  LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;);
354  Builder.buildConstant(DstReg, 0);
355  UpdatedDefs.push_back(DstReg);
356  }
357 
358  markInstAndDefDead(MI, *DefMI, DeadInsts);
359  return true;
360  }
361  return false;
362  }
363 
366  SmallVectorImpl<Register> &UpdatedDefs) {
367 
368  assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
369 
370  const unsigned CastOpc = CastMI.getOpcode();
371 
372  if (!isArtifactCast(CastOpc))
373  return false;
374 
375  const unsigned NumDefs = MI.getNumOperands() - 1;
376 
377  const Register CastSrcReg = CastMI.getOperand(1).getReg();
378  const LLT CastSrcTy = MRI.getType(CastSrcReg);
379  const LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
380  const LLT SrcTy = MRI.getType(MI.getOperand(NumDefs).getReg());
381 
382  const unsigned CastSrcSize = CastSrcTy.getSizeInBits();
383  const unsigned DestSize = DestTy.getSizeInBits();
384 
385  if (CastOpc == TargetOpcode::G_TRUNC) {
386  if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.getScalarType()) {
387  // %1:_(<4 x s8>) = G_TRUNC %0(<4 x s32>)
388  // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %1
389  // =>
390  // %6:_(s32), %7:_(s32), %8:_(s32), %9:_(s32) = G_UNMERGE_VALUES %0
391  // %2:_(s8) = G_TRUNC %6
392  // %3:_(s8) = G_TRUNC %7
393  // %4:_(s8) = G_TRUNC %8
394  // %5:_(s8) = G_TRUNC %9
395 
396  unsigned UnmergeNumElts =
397  DestTy.isVector() ? CastSrcTy.getNumElements() / NumDefs : 1;
398  LLT UnmergeTy = CastSrcTy.changeElementCount(
399  ElementCount::getFixed(UnmergeNumElts));
400 
401  if (isInstUnsupported(
402  {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}))
403  return false;
404 
405  Builder.setInstr(MI);
406  auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg);
407 
408  for (unsigned I = 0; I != NumDefs; ++I) {
409  Register DefReg = MI.getOperand(I).getReg();
410  UpdatedDefs.push_back(DefReg);
411  Builder.buildTrunc(DefReg, NewUnmerge.getReg(I));
412  }
413 
414  markInstAndDefDead(MI, CastMI, DeadInsts);
415  return true;
416  }
417 
418  if (CastSrcTy.isScalar() && SrcTy.isScalar() && !DestTy.isVector()) {
419  // %1:_(s16) = G_TRUNC %0(s32)
420  // %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %1
421  // =>
422  // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %0
423 
424  // Unmerge(trunc) can be combined if the trunc source size is a multiple
425  // of the unmerge destination size
426  if (CastSrcSize % DestSize != 0)
427  return false;
428 
429  // Check if the new unmerge is supported
430  if (isInstUnsupported(
431  {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
432  return false;
433 
434  // Gather the original destination registers and create new ones for the
435  // unused bits
436  const unsigned NewNumDefs = CastSrcSize / DestSize;
437  SmallVector<Register, 8> DstRegs(NewNumDefs);
438  for (unsigned Idx = 0; Idx < NewNumDefs; ++Idx) {
439  if (Idx < NumDefs)
440  DstRegs[Idx] = MI.getOperand(Idx).getReg();
441  else
442  DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy);
443  }
444 
445  // Build new unmerge
446  Builder.setInstr(MI);
447  Builder.buildUnmerge(DstRegs, CastSrcReg);
448  UpdatedDefs.append(DstRegs.begin(), DstRegs.begin() + NewNumDefs);
449  markInstAndDefDead(MI, CastMI, DeadInsts);
450  return true;
451  }
452  }
453 
454  // TODO: support combines with other casts as well
455  return false;
456  }
457 
458  static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp,
459  LLT OpTy, LLT DestTy) {
460  // Check if we found a definition that is like G_MERGE_VALUES.
461  switch (MergeOp) {
462  default:
463  return false;
464  case TargetOpcode::G_BUILD_VECTOR:
465  case TargetOpcode::G_MERGE_VALUES:
466  // The convert operation that we will need to insert is
467  // going to convert the input of that type of instruction (scalar)
468  // to the destination type (DestTy).
469  // The conversion needs to stay in the same domain (scalar to scalar
470  // and vector to vector), so if we were to allow to fold the merge
471  // we would need to insert some bitcasts.
472  // E.g.,
473  // <2 x s16> = build_vector s16, s16
474  // <2 x s32> = zext <2 x s16>
475  // <2 x s16>, <2 x s16> = unmerge <2 x s32>
476  //
477  // As is the folding would produce:
478  // <2 x s16> = zext s16 <-- scalar to vector
479  // <2 x s16> = zext s16 <-- scalar to vector
480  // Which is invalid.
481  // Instead we would want to generate:
482  // s32 = zext s16
483  // <2 x s16> = bitcast s32
484  // s32 = zext s16
485  // <2 x s16> = bitcast s32
486  //
487  // That is not done yet.
488  if (ConvertOp == 0)
489  return true;
490  return !DestTy.isVector() && OpTy.isVector();
491  case TargetOpcode::G_CONCAT_VECTORS: {
492  if (ConvertOp == 0)
493  return true;
494  if (!DestTy.isVector())
495  return false;
496 
497  const unsigned OpEltSize = OpTy.getElementType().getSizeInBits();
498 
499  // Don't handle scalarization with a cast that isn't in the same
500  // direction as the vector cast. This could be handled, but it would
501  // require more intermediate unmerges.
502  if (ConvertOp == TargetOpcode::G_TRUNC)
503  return DestTy.getSizeInBits() <= OpEltSize;
504  return DestTy.getSizeInBits() >= OpEltSize;
505  }
506  }
507  }
508 
509  /// Try to replace DstReg with SrcReg or build a COPY instruction
510  /// depending on the register constraints.
511  static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg,
514  SmallVectorImpl<Register> &UpdatedDefs,
515  GISelChangeObserver &Observer) {
516  if (!llvm::canReplaceReg(DstReg, SrcReg, MRI)) {
517  Builder.buildCopy(DstReg, SrcReg);
518  UpdatedDefs.push_back(DstReg);
519  return;
520  }
522  // Get the users and notify the observer before replacing.
523  for (auto &UseMI : MRI.use_instructions(DstReg)) {
524  UseMIs.push_back(&UseMI);
525  Observer.changingInstr(UseMI);
526  }
527  // Replace the registers.
528  MRI.replaceRegWith(DstReg, SrcReg);
529  UpdatedDefs.push_back(SrcReg);
530  // Notify the observer that we changed the instructions.
531  for (auto *UseMI : UseMIs)
532  Observer.changedInstr(*UseMI);
533  }
534 
535  /// Return the operand index in \p MI that defines \p Def
536  static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef) {
537  unsigned DefIdx = 0;
538  for (const MachineOperand &Def : MI.defs()) {
539  if (Def.getReg() == SearchDef)
540  break;
541  ++DefIdx;
542  }
543 
544  return DefIdx;
545  }
546 
547  /// This class provides utilities for finding source registers of specific
548  /// bit ranges in an artifact. The routines can look through the source
549  /// registers if they're other artifacts to try to find a non-artifact source
550  /// of a value.
553  MachineIRBuilder &MIB;
554  const LegalizerInfo &LI;
555 
556  // Stores the best register found in the current query so far.
557  Register CurrentBest = Register();
558 
559  /// Given an concat_vector op \p Concat and a start bit and size, try to
560  /// find the origin of the value defined by that start position and size.
561  ///
562  /// \returns a register with the requested size, or the current best
563  /// register found during the current query.
564  Register findValueFromConcat(GConcatVectors &Concat, unsigned StartBit,
565  unsigned Size) {
566  assert(Size > 0);
567 
568  // Find the source operand that provides the bits requested.
569  Register Src1Reg = Concat.getSourceReg(0);
570  unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
571 
572  // Operand index of the source that provides the start of the bit range.
573  unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
574  // Offset into the source at which the bit range starts.
575  unsigned InRegOffset = StartBit % SrcSize;
576  // Check that the bits don't span multiple sources.
577  // FIXME: we might be able return multiple sources? Or create an
578  // appropriate concat to make it fit.
579  if (InRegOffset + Size > SrcSize)
580  return CurrentBest;
581 
582  Register SrcReg = Concat.getReg(StartSrcIdx);
583  if (InRegOffset == 0 && Size == SrcSize) {
584  CurrentBest = SrcReg;
585  return findValueFromDefImpl(SrcReg, 0, Size);
586  }
587 
588  return findValueFromDefImpl(SrcReg, InRegOffset, Size);
589  }
590 
591  /// Given an build_vector op \p BV and a start bit and size, try to find
592  /// the origin of the value defined by that start position and size.
593  ///
594  /// \returns a register with the requested size, or the current best
595  /// register found during the current query.
596  Register findValueFromBuildVector(GBuildVector &BV, unsigned StartBit,
597  unsigned Size) {
598  assert(Size > 0);
599 
600  // Find the source operand that provides the bits requested.
601  Register Src1Reg = BV.getSourceReg(0);
602  unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
603 
604  // Operand index of the source that provides the start of the bit range.
605  unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
606  // Offset into the source at which the bit range starts.
607  unsigned InRegOffset = StartBit % SrcSize;
608 
609  if (InRegOffset != 0)
610  return CurrentBest; // Give up, bits don't start at a scalar source.
611  if (Size < SrcSize)
612  return CurrentBest; // Scalar source is too large for requested bits.
613 
614  // If the bits cover multiple sources evenly, then create a new
615  // build_vector to synthesize the required size, if that's been requested.
616  if (Size > SrcSize) {
617  if (Size % SrcSize > 0)
618  return CurrentBest; // Isn't covered exactly by sources.
619 
620  unsigned NumSrcsUsed = Size / SrcSize;
621  // If we're requesting all of the sources, just return this def.
622  if (NumSrcsUsed == BV.getNumSources())
623  return BV.getReg(0);
624 
625  LLT SrcTy = MRI.getType(Src1Reg);
626  LLT NewBVTy = LLT::fixed_vector(NumSrcsUsed, SrcTy);
627 
628  // Check if the resulting build vector would be legal.
629  LegalizeActionStep ActionStep =
630  LI.getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
631  if (ActionStep.Action != LegalizeActions::Legal)
632  return CurrentBest;
633 
634  SmallVector<Register> NewSrcs;
635  for (unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
636  ++SrcIdx)
637  NewSrcs.push_back(BV.getReg(SrcIdx));
638  MIB.setInstrAndDebugLoc(BV);
639  return MIB.buildBuildVector(NewBVTy, NewSrcs).getReg(0);
640  }
641  // A single source is requested, just return it.
642  return BV.getReg(StartSrcIdx);
643  }
644 
645  /// Given an G_INSERT op \p MI and a start bit and size, try to find
646  /// the origin of the value defined by that start position and size.
647  ///
648  /// \returns a register with the requested size, or the current best
649  /// register found during the current query.
650  Register findValueFromInsert(MachineInstr &MI, unsigned StartBit,
651  unsigned Size) {
652  assert(MI.getOpcode() == TargetOpcode::G_INSERT);
653  assert(Size > 0);
654 
655  Register ContainerSrcReg = MI.getOperand(1).getReg();
656  Register InsertedReg = MI.getOperand(2).getReg();
657  LLT InsertedRegTy = MRI.getType(InsertedReg);
658  unsigned InsertOffset = MI.getOperand(3).getImm();
659 
660  // There are 4 possible container/insertreg + requested bit-range layouts
661  // that the instruction and query could be representing.
662  // For: %_ = G_INSERT %CONTAINER, %INS, InsOff (abbrev. to 'IO')
663  // and a start bit 'SB', with size S, giving an end bit 'EB', we could
664  // have...
665  // Scenario A:
666  // --------------------------
667  // | INS | CONTAINER |
668  // --------------------------
669  // | |
670  // SB EB
671  //
672  // Scenario B:
673  // --------------------------
674  // | INS | CONTAINER |
675  // --------------------------
676  // | |
677  // SB EB
678  //
679  // Scenario C:
680  // --------------------------
681  // | CONTAINER | INS |
682  // --------------------------
683  // | |
684  // SB EB
685  //
686  // Scenario D:
687  // --------------------------
688  // | CONTAINER | INS |
689  // --------------------------
690  // | |
691  // SB EB
692  //
693  // So therefore, A and D are requesting data from the INS operand, while
694  // B and C are requesting from the container operand.
695 
696  unsigned InsertedEndBit = InsertOffset + InsertedRegTy.getSizeInBits();
697  unsigned EndBit = StartBit + Size;
698  unsigned NewStartBit;
699  Register SrcRegToUse;
700  if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
701  SrcRegToUse = ContainerSrcReg;
702  NewStartBit = StartBit;
703  return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size);
704  }
705  if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
706  SrcRegToUse = InsertedReg;
707  NewStartBit = StartBit - InsertOffset;
708  if (NewStartBit == 0 &&
709  Size == MRI.getType(SrcRegToUse).getSizeInBits())
710  CurrentBest = SrcRegToUse;
711  return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size);
712  }
713  // The bit range spans both the inserted and container regions.
714  return Register();
715  }
716 
717  /// Internal implementation for findValueFromDef(). findValueFromDef()
718  /// initializes some data like the CurrentBest register, which this method
719  /// and its callees rely upon.
720  Register findValueFromDefImpl(Register DefReg, unsigned StartBit,
721  unsigned Size) {
723  // If the instruction has a single def, then simply delegate the search.
724  // For unmerge however with multiple defs, we need to compute the offset
725  // into the source of the unmerge.
726  switch (Def->getOpcode()) {
727  case TargetOpcode::G_CONCAT_VECTORS:
728  return findValueFromConcat(cast<GConcatVectors>(*Def), StartBit, Size);
729  case TargetOpcode::G_UNMERGE_VALUES: {
730  unsigned DefStartBit = 0;
731  unsigned DefSize = MRI.getType(DefReg).getSizeInBits();
732  for (const auto &MO : Def->defs()) {
733  if (MO.getReg() == DefReg)
734  break;
735  DefStartBit += DefSize;
736  }
737  Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
738  Register SrcOriginReg =
739  findValueFromDefImpl(SrcReg, StartBit + DefStartBit, Size);
740  if (SrcOriginReg)
741  return SrcOriginReg;
742  // Failed to find a further value. If the StartBit and Size perfectly
743  // covered the requested DefReg, return that since it's better than
744  // nothing.
745  if (StartBit == 0 && Size == DefSize)
746  return DefReg;
747  return CurrentBest;
748  }
749  case TargetOpcode::G_BUILD_VECTOR:
750  return findValueFromBuildVector(cast<GBuildVector>(*Def), StartBit,
751  Size);
752  case TargetOpcode::G_INSERT:
753  return findValueFromInsert(*Def, StartBit, Size);
754  default:
755  return CurrentBest;
756  }
757  }
758 
759  public:
761  const LegalizerInfo &Info)
762  : MRI(Mri), MIB(Builder), LI(Info) {}
763 
764  /// Try to find a source of the value defined in the def \p DefReg, starting
765  /// at position \p StartBit with size \p Size.
766  /// \returns a register with the requested size, or an empty Register if no
767  /// better value could be found.
768  Register findValueFromDef(Register DefReg, unsigned StartBit,
769  unsigned Size) {
770  CurrentBest = Register();
771  Register FoundReg = findValueFromDefImpl(DefReg, StartBit, Size);
772  return FoundReg != DefReg ? FoundReg : Register();
773  }
774 
775  /// Try to combine the defs of an unmerge \p MI by attempting to find
776  /// values that provides the bits for each def reg.
777  /// \returns true if all the defs of the unmerge have been made dead.
779  SmallVectorImpl<Register> &UpdatedDefs) {
780  unsigned NumDefs = MI.getNumDefs();
781  LLT DestTy = MRI.getType(MI.getReg(0));
782 
783  SmallBitVector DeadDefs(NumDefs);
784  for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
785  Register DefReg = MI.getReg(DefIdx);
786  if (MRI.use_nodbg_empty(DefReg)) {
787  DeadDefs[DefIdx] = true;
788  continue;
789  }
790  Register FoundVal = findValueFromDef(DefReg, 0, DestTy.getSizeInBits());
791  if (!FoundVal)
792  continue;
793  if (MRI.getType(FoundVal) != DestTy)
794  continue;
795 
796  replaceRegOrBuildCopy(DefReg, FoundVal, MRI, MIB, UpdatedDefs,
797  Observer);
798  // We only want to replace the uses, not the def of the old reg.
799  Observer.changingInstr(MI);
800  MI.getOperand(DefIdx).setReg(DefReg);
801  Observer.changedInstr(MI);
802  DeadDefs[DefIdx] = true;
803  }
804  return DeadDefs.all();
805  }
806  };
807 
810  SmallVectorImpl<Register> &UpdatedDefs,
811  GISelChangeObserver &Observer) {
812  unsigned NumDefs = MI.getNumDefs();
813  Register SrcReg = MI.getSourceReg();
814  MachineInstr *SrcDef = getDefIgnoringCopies(SrcReg, MRI);
815  if (!SrcDef)
816  return false;
817 
818  LLT OpTy = MRI.getType(SrcReg);
819  LLT DestTy = MRI.getType(MI.getReg(0));
820  unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg);
821 
822  Builder.setInstrAndDebugLoc(MI);
823 
824  if (auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
825  // %0:_(<4 x s16>) = G_FOO
826  // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0
827  // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1
828  //
829  // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0
830  Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
831  LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);
832 
833  // If we need to decrease the number of vector elements in the result type
834  // of an unmerge, this would involve the creation of an equivalent unmerge
835  // to copy back to the original result registers.
836  LegalizeActionStep ActionStep = LI.getAction(
837  {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
838  switch (ActionStep.Action) {
841  break;
844  if (ActionStep.TypeIdx == 1)
845  return false;
846  break;
847  default: {
848  ArtifactValueFinder Finder(MRI, Builder, LI);
849  if (Finder.tryCombineUnmergeDefs(MI, Observer, UpdatedDefs)) {
850  markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);
851  return true;
852  }
853  return false;
854  }
855  }
856 
857  auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
858 
859  // TODO: Should we try to process out the other defs now? If the other
860  // defs of the source unmerge are also unmerged, we end up with a separate
861  // unmerge for each one.
862  for (unsigned I = 0; I != NumDefs; ++I) {
863  Register Def = MI.getReg(I);
864  replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I),
865  MRI, Builder, UpdatedDefs, Observer);
866  }
867 
868  markInstAndDefDead(MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
869  return true;
870  }
871 
872  MachineInstr *MergeI = SrcDef;
873  unsigned ConvertOp = 0;
874 
875  // Handle intermediate conversions
876  unsigned SrcOp = SrcDef->getOpcode();
877  if (isArtifactCast(SrcOp)) {
878  ConvertOp = SrcOp;
879  MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI);
880  }
881 
882  if (!MergeI || !canFoldMergeOpcode(MergeI->getOpcode(),
883  ConvertOp, OpTy, DestTy)) {
884  // We might have a chance to combine later by trying to combine
885  // unmerge(cast) first
886  if (tryFoldUnmergeCast(MI, *SrcDef, DeadInsts, UpdatedDefs))
887  return true;
888 
889  // Try using the value finder.
890  ArtifactValueFinder Finder(MRI, Builder, LI);
891  if (Finder.tryCombineUnmergeDefs(MI, Observer, UpdatedDefs)) {
892  markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);
893  return true;
894  }
895  return false;
896  }
897 
898  const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
899 
900  if (NumMergeRegs < NumDefs) {
901  if (NumDefs % NumMergeRegs != 0)
902  return false;
903 
904  Builder.setInstr(MI);
905  // Transform to UNMERGEs, for example
906  // %1 = G_MERGE_VALUES %4, %5
907  // %9, %10, %11, %12 = G_UNMERGE_VALUES %1
908  // to
909  // %9, %10 = G_UNMERGE_VALUES %4
910  // %11, %12 = G_UNMERGE_VALUES %5
911 
912  const unsigned NewNumDefs = NumDefs / NumMergeRegs;
913  for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
914  SmallVector<Register, 8> DstRegs;
915  for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
916  ++j, ++DefIdx)
917  DstRegs.push_back(MI.getReg(DefIdx));
918 
919  if (ConvertOp) {
920  LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
921 
922  // This is a vector that is being split and casted. Extract to the
923  // element type, and do the conversion on the scalars (or smaller
924  // vectors).
925  LLT MergeEltTy = MergeSrcTy.divide(NewNumDefs);
926 
927  // Handle split to smaller vectors, with conversions.
928  // %2(<8 x s8>) = G_CONCAT_VECTORS %0(<4 x s8>), %1(<4 x s8>)
929  // %3(<8 x s16>) = G_SEXT %2
930  // %4(<2 x s16>), %5(<2 x s16>), %6(<2 x s16>), %7(<2 x s16>) = G_UNMERGE_VALUES %3
931  //
932  // =>
933  //
934  // %8(<2 x s8>), %9(<2 x s8>) = G_UNMERGE_VALUES %0
935  // %10(<2 x s8>), %11(<2 x s8>) = G_UNMERGE_VALUES %1
936  // %4(<2 x s16>) = G_SEXT %8
937  // %5(<2 x s16>) = G_SEXT %9
938  // %6(<2 x s16>) = G_SEXT %10
939  // %7(<2 x s16>)= G_SEXT %11
940 
941  SmallVector<Register, 4> TmpRegs(NewNumDefs);
942  for (unsigned k = 0; k < NewNumDefs; ++k)
943  TmpRegs[k] = MRI.createGenericVirtualRegister(MergeEltTy);
944 
945  Builder.buildUnmerge(TmpRegs, MergeI->getOperand(Idx + 1).getReg());
946 
947  for (unsigned k = 0; k < NewNumDefs; ++k)
948  Builder.buildInstr(ConvertOp, {DstRegs[k]}, {TmpRegs[k]});
949  } else {
950  Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
951  }
952  UpdatedDefs.append(DstRegs.begin(), DstRegs.end());
953  }
954 
955  } else if (NumMergeRegs > NumDefs) {
956  if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
957  return false;
958 
959  Builder.setInstr(MI);
960  // Transform to MERGEs
961  // %6 = G_MERGE_VALUES %17, %18, %19, %20
962  // %7, %8 = G_UNMERGE_VALUES %6
963  // to
964  // %7 = G_MERGE_VALUES %17, %18
965  // %8 = G_MERGE_VALUES %19, %20
966 
967  const unsigned NumRegs = NumMergeRegs / NumDefs;
968  for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
970  for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
971  ++j, ++Idx)
972  Regs.push_back(MergeI->getOperand(Idx).getReg());
973 
974  Register DefReg = MI.getReg(DefIdx);
975  Builder.buildMerge(DefReg, Regs);
976  UpdatedDefs.push_back(DefReg);
977  }
978 
979  } else {
980  LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
981 
982  if (!ConvertOp && DestTy != MergeSrcTy)
983  ConvertOp = TargetOpcode::G_BITCAST;
984 
985  if (ConvertOp) {
986  Builder.setInstr(MI);
987 
988  for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
989  Register MergeSrc = MergeI->getOperand(Idx + 1).getReg();
990  Register DefReg = MI.getOperand(Idx).getReg();
991  Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
992  UpdatedDefs.push_back(DefReg);
993  }
994 
995  markInstAndDefDead(MI, *MergeI, DeadInsts);
996  return true;
997  }
998 
999  assert(DestTy == MergeSrcTy &&
1000  "Bitcast and the other kinds of conversions should "
1001  "have happened earlier");
1002 
1003  Builder.setInstr(MI);
1004  for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1005  Register DstReg = MI.getOperand(Idx).getReg();
1006  Register SrcReg = MergeI->getOperand(Idx + 1).getReg();
1007  replaceRegOrBuildCopy(DstReg, SrcReg, MRI, Builder, UpdatedDefs,
1008  Observer);
1009  }
1010  }
1011 
1012  markInstAndDefDead(MI, *MergeI, DeadInsts);
1013  return true;
1014  }
1015 
1018  SmallVectorImpl<Register> &UpdatedDefs) {
1019  assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
1020 
1021  // Try to use the source registers from a G_MERGE_VALUES
1022  //
1023  // %2 = G_MERGE_VALUES %0, %1
1024  // %3 = G_EXTRACT %2, N
1025  // =>
1026  //
1027  // for N < %2.getSizeInBits() / 2
1028  // %3 = G_EXTRACT %0, N
1029  //
1030  // for N >= %2.getSizeInBits() / 2
1031  // %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
1032 
1033  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
1034  MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
1035  if (!MergeI || !isa<GMergeLikeOp>(MergeI))
1036  return false;
1037 
1038  Register DstReg = MI.getOperand(0).getReg();
1039  LLT DstTy = MRI.getType(DstReg);
1040  LLT SrcTy = MRI.getType(SrcReg);
1041 
1042  // TODO: Do we need to check if the resulting extract is supported?
1043  unsigned ExtractDstSize = DstTy.getSizeInBits();
1044  unsigned Offset = MI.getOperand(2).getImm();
1045  unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
1046  unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
1047  unsigned MergeSrcIdx = Offset / MergeSrcSize;
1048 
1049  // Compute the offset of the last bit the extract needs.
1050  unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
1051 
1052  // Can't handle the case where the extract spans multiple inputs.
1053  if (MergeSrcIdx != EndMergeSrcIdx)
1054  return false;
1055 
1056  // TODO: We could modify MI in place in most cases.
1057  Builder.setInstr(MI);
1058  Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(),
1059  Offset - MergeSrcIdx * MergeSrcSize);
1060  UpdatedDefs.push_back(DstReg);
1061  markInstAndDefDead(MI, *MergeI, DeadInsts);
1062  return true;
1063  }
1064 
1065  /// Try to combine away MI.
1066  /// Returns true if it combined away the MI.
1067  /// Adds instructions that are dead as a result of the combine
1068  /// into DeadInsts, which can include MI.
1071  GISelObserverWrapper &WrapperObserver) {
1072  // This might be a recursive call, and we might have DeadInsts already
1073  // populated. To avoid bad things happening later with multiple vreg defs
1074  // etc, process the dead instructions now if any.
1075  if (!DeadInsts.empty())
1076  deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1077 
1078  // Put here every vreg that was redefined in such a way that it's at least
1079  // possible that one (or more) of its users (immediate or COPY-separated)
1080  // could become artifact combinable with the new definition (or the
1081  // instruction reachable from it through a chain of copies if any).
1082  SmallVector<Register, 4> UpdatedDefs;
1083  bool Changed = false;
1084  switch (MI.getOpcode()) {
1085  default:
1086  return false;
1087  case TargetOpcode::G_ANYEXT:
1088  Changed = tryCombineAnyExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1089  break;
1090  case TargetOpcode::G_ZEXT:
1091  Changed = tryCombineZExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1092  break;
1093  case TargetOpcode::G_SEXT:
1094  Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs);
1095  break;
1096  case TargetOpcode::G_UNMERGE_VALUES:
1097  Changed = tryCombineUnmergeValues(cast<GUnmerge>(MI), DeadInsts,
1098  UpdatedDefs, WrapperObserver);
1099  break;
1100  case TargetOpcode::G_MERGE_VALUES:
1101  case TargetOpcode::G_BUILD_VECTOR:
1102  case TargetOpcode::G_CONCAT_VECTORS:
1103  // If any of the users of this merge are an unmerge, then add them to the
1104  // artifact worklist in case there's folding that can be done looking up.
1105  for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) {
1106  if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1107  U.getOpcode() == TargetOpcode::G_TRUNC) {
1108  UpdatedDefs.push_back(MI.getOperand(0).getReg());
1109  break;
1110  }
1111  }
1112  break;
1113  case TargetOpcode::G_EXTRACT:
1114  Changed = tryCombineExtract(MI, DeadInsts, UpdatedDefs);
1115  break;
1116  case TargetOpcode::G_TRUNC:
1117  Changed = tryCombineTrunc(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1118  if (!Changed) {
1119  // Try to combine truncates away even if they are legal. As all artifact
1120  // combines at the moment look only "up" the def-use chains, we achieve
1121  // that by throwing truncates' users (with look through copies) into the
1122  // ArtifactList again.
1123  UpdatedDefs.push_back(MI.getOperand(0).getReg());
1124  }
1125  break;
1126  }
1127  // If the main loop through the ArtifactList found at least one combinable
1128  // pair of artifacts, not only combine it away (as done above), but also
1129  // follow the def-use chain from there to combine everything that can be
1130  // combined within this def-use chain of artifacts.
1131  while (!UpdatedDefs.empty()) {
1132  Register NewDef = UpdatedDefs.pop_back_val();
1133  assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg");
1134  for (MachineInstr &Use : MRI.use_instructions(NewDef)) {
1135  switch (Use.getOpcode()) {
1136  // Keep this list in sync with the list of all artifact combines.
1137  case TargetOpcode::G_ANYEXT:
1138  case TargetOpcode::G_ZEXT:
1139  case TargetOpcode::G_SEXT:
1140  case TargetOpcode::G_UNMERGE_VALUES:
1141  case TargetOpcode::G_EXTRACT:
1142  case TargetOpcode::G_TRUNC:
1143  // Adding Use to ArtifactList.
1144  WrapperObserver.changedInstr(Use);
1145  break;
1146  case TargetOpcode::COPY: {
1147  Register Copy = Use.getOperand(0).getReg();
1148  if (Copy.isVirtual())
1149  UpdatedDefs.push_back(Copy);
1150  break;
1151  }
1152  default:
1153  // If we do not have an artifact combine for the opcode, there is no
1154  // point in adding it to the ArtifactList as nothing interesting will
1155  // be done to it anyway.
1156  break;
1157  }
1158  }
1159  }
1160  return Changed;
1161  }
1162 
1163 private:
1164  static Register getArtifactSrcReg(const MachineInstr &MI) {
1165  switch (MI.getOpcode()) {
1166  case TargetOpcode::COPY:
1167  case TargetOpcode::G_TRUNC:
1168  case TargetOpcode::G_ZEXT:
1169  case TargetOpcode::G_ANYEXT:
1170  case TargetOpcode::G_SEXT:
1171  case TargetOpcode::G_EXTRACT:
1172  return MI.getOperand(1).getReg();
1173  case TargetOpcode::G_UNMERGE_VALUES:
1174  return MI.getOperand(MI.getNumOperands() - 1).getReg();
1175  default:
1176  llvm_unreachable("Not a legalization artifact happen");
1177  }
1178  }
1179 
1180  /// Mark a def of one of MI's original operands, DefMI, as dead if changing MI
1181  /// (either by killing it or changing operands) results in DefMI being dead
1182  /// too. In-between COPYs or artifact-casts are also collected if they are
1183  /// dead.
1184  /// MI is not marked dead.
1185  void markDefDead(MachineInstr &MI, MachineInstr &DefMI,
1186  SmallVectorImpl<MachineInstr *> &DeadInsts,
1187  unsigned DefIdx = 0) {
1188  // Collect all the copy instructions that are made dead, due to deleting
1189  // this instruction. Collect all of them until the Trunc(DefMI).
1190  // Eg,
1191  // %1(s1) = G_TRUNC %0(s32)
1192  // %2(s1) = COPY %1(s1)
1193  // %3(s1) = COPY %2(s1)
1194  // %4(s32) = G_ANYEXT %3(s1)
1195  // In this case, we would have replaced %4 with a copy of %0,
1196  // and as a result, %3, %2, %1 are dead.
1197  MachineInstr *PrevMI = &MI;
1198  while (PrevMI != &DefMI) {
1199  Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1200 
1201  MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
1202  if (MRI.hasOneUse(PrevRegSrc)) {
1203  if (TmpDef != &DefMI) {
1204  assert((TmpDef->getOpcode() == TargetOpcode::COPY ||
1205  isArtifactCast(TmpDef->getOpcode())) &&
1206  "Expecting copy or artifact cast here");
1207 
1208  DeadInsts.push_back(TmpDef);
1209  }
1210  } else
1211  break;
1212  PrevMI = TmpDef;
1213  }
1214 
1215  if (PrevMI == &DefMI) {
1216  unsigned I = 0;
1217  bool IsDead = true;
1218  for (MachineOperand &Def : DefMI.defs()) {
1219  if (I != DefIdx) {
1220  if (!MRI.use_empty(Def.getReg())) {
1221  IsDead = false;
1222  break;
1223  }
1224  } else {
1225  if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg()))
1226  break;
1227  }
1228 
1229  ++I;
1230  }
1231 
1232  if (IsDead)
1233  DeadInsts.push_back(&DefMI);
1234  }
1235  }
1236 
1237  /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
1238  /// dead due to MI being killed, then mark DefMI as dead too.
1239  /// Some of the combines (extends(trunc)), try to walk through redundant
1240  /// copies in between the extends and the truncs, and this attempts to collect
1241  /// the in between copies if they're dead.
1242  void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
1243  SmallVectorImpl<MachineInstr *> &DeadInsts,
1244  unsigned DefIdx = 0) {
1245  DeadInsts.push_back(&MI);
1246  markDefDead(MI, DefMI, DeadInsts, DefIdx);
1247  }
1248 
1249  /// Erase the dead instructions in the list and call the observer hooks.
1250  /// Normally the Legalizer will deal with erasing instructions that have been
1251  /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to
1252  /// process instructions which have been marked dead, but otherwise break the
1253  /// MIR by introducing multiple vreg defs. For those cases, allow the combines
1254  /// to explicitly delete the instructions before we run into trouble.
1255  void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts,
1256  GISelObserverWrapper &WrapperObserver) {
1257  for (auto *DeadMI : DeadInsts) {
1258  LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");
1259  WrapperObserver.erasingInstr(*DeadMI);
1260  DeadMI->eraseFromParentAndMarkDBGValuesForRemoval();
1261  }
1262  DeadInsts.clear();
1263  }
1264 
1265  /// Checks if the target legalizer info has specified anything about the
1266  /// instruction, or if unsupported.
1267  bool isInstUnsupported(const LegalityQuery &Query) const {
1268  using namespace LegalizeActions;
1269  auto Step = LI.getAction(Query);
1270  return Step.Action == Unsupported || Step.Action == NotFound;
1271  }
1272 
1273  bool isInstLegal(const LegalityQuery &Query) const {
1274  return LI.getAction(Query).Action == LegalizeActions::Legal;
1275  }
1276 
1277  bool isConstantUnsupported(LLT Ty) const {
1278  if (!Ty.isVector())
1279  return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1280 
1281  LLT EltTy = Ty.getElementType();
1282  return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1283  isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
1284  }
1285 
1286  /// Looks through copy instructions and returns the actual
1287  /// source register.
1288  Register lookThroughCopyInstrs(Register Reg) {
1289  Register TmpReg;
1290  while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) {
1291  if (MRI.getType(TmpReg).isValid())
1292  Reg = TmpReg;
1293  else
1294  break;
1295  }
1296  return Reg;
1297  }
1298 };
1299 
1300 } // namespace llvm
1301 
1302 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
i
i
Definition: README.txt:29
MIPatternMatch.h
IsDead
bool IsDead
Definition: SILowerControlFlow.cpp:158
llvm::getDefIgnoringCopies
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition: Utils.cpp:404
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:103
llvm::GBuildVector
Represents a G_BUILD_VECTOR.
Definition: GenericMachineInstrs.h:191
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::tgtok::Def
@ Def
Definition: TGLexer.h:50
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
UseMI
MachineInstrBuilder & UseMI
Definition: AArch64ExpandPseudoInsts.cpp:102
llvm::LLT::getScalarSizeInBits
unsigned getScalarSizeInBits() const
Definition: LowLevelTypeImpl.h:213
llvm::LegalizationArtifactCombiner::tryCombineExtract
bool tryCombineExtract(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Definition: LegalizationArtifactCombiner.h:1016
llvm::MIPatternMatch::m_Reg
operand_type_match m_Reg()
Definition: MIPatternMatch.h:127
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition: MachineRegisterInfo.h:52
llvm::LegalizeActionStep::Action
LegalizeAction Action
The action to take or the final answer.
Definition: LegalizerInfo.h:144
llvm::LegalizationArtifactCombiner::ArtifactValueFinder::ArtifactValueFinder
ArtifactValueFinder(MachineRegisterInfo &Mri, MachineIRBuilder &Builder, const LegalizerInfo &Info)
Definition: LegalizationArtifactCombiner.h:760
llvm::getOpcodeDef
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:418
llvm::LegalizeActionStep
The result of a query.
Definition: LegalizerInfo.h:142
llvm::LegalizationArtifactCombiner::ArtifactValueFinder
This class provides utilities for finding source registers of specific bit ranges in an artifact.
Definition: LegalizationArtifactCombiner.h:551
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::LegalizeActions::NarrowScalar
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
Definition: LegalizerInfo.h:54
llvm::MIPatternMatch::m_GTrunc
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
Definition: MIPatternMatch.h:424
llvm::LegalizationArtifactCombiner::ArtifactValueFinder::findValueFromDef
Register findValueFromDef(Register DefReg, unsigned StartBit, unsigned Size)
Try to find a source of the value defined in the def DefReg, starting at position StartBit with size ...
Definition: LegalizationArtifactCombiner.h:768
llvm::LegalizationArtifactCombiner::tryCombineZExt
bool tryCombineZExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
Definition: LegalizationArtifactCombiner.h:108
llvm::LLT::getScalarType
LLT getScalarType() const
Definition: LowLevelTypeImpl.h:168
llvm::LegalizationArtifactCombiner::tryFoldUnmergeCast
bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Definition: LegalizationArtifactCombiner.h:364
llvm::LegalizationArtifactCombiner::canFoldMergeOpcode
static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp, LLT OpTy, LLT DestTy)
Definition: LegalizationArtifactCombiner.h:458
GenericMachineInstrs.h
llvm::LLT::changeElementCount
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
Definition: LowLevelTypeImpl.h:190
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::MachineIRBuilder::buildBuildVector
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
Definition: MachineIRBuilder.cpp:632
MachineIRBuilder.h
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:635
LegalizerInfo.h
llvm::BitmaskEnumDetail::Mask
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
MachineRegisterInfo.h
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::SmallBitVector
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
Definition: SmallBitVector.h:34
llvm::LLT::fixed_vector
static LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
Definition: LowLevelTypeImpl.h:75
llvm::MIPatternMatch::m_GSExt
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
Definition: MIPatternMatch.h:409
llvm::LegalizationArtifactCombiner::tryCombineSExt
bool tryCombineSExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Definition: LegalizationArtifactCombiner.h:170
llvm::MIPatternMatch::m_GZExt
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
Definition: MIPatternMatch.h:414
llvm::SmallVectorImpl::append
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:648
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:499
llvm::LLT::getSizeInBits
TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelTypeImpl.h:153
llvm::GISelObserverWrapper::changingInstr
void changingInstr(MachineInstr &MI) override
This instruction is about to be mutated in some way.
Definition: GISelChangeObserver.h:92
llvm::APInt::getAllOnes
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition: APInt.h:216
Utils.h
llvm::LegalizationArtifactCombiner::getDefIndex
static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef)
Return the operand index in MI that defines Def.
Definition: LegalizationArtifactCombiner.h:536
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::SmallBitVector::all
bool all() const
Returns true if all bits are set.
Definition: SmallBitVector.h:215
Concat
static constexpr int Concat[]
Definition: X86InterleavedAccess.cpp:239
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::GISelChangeObserver::changingInstr
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
llvm::MIPatternMatch::m_MInstr
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
Definition: MIPatternMatch.h:227
llvm::LegalizationArtifactCombiner::tryCombineUnmergeValues
bool tryCombineUnmergeValues(GUnmerge &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
Definition: LegalizationArtifactCombiner.h:808
llvm::LegalizeActions::Legal
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
Definition: LegalizerInfo.h:49
llvm::LinearPolySize< ElementCount >::getFixed
static ElementCount getFixed(ScalarTy MinVal)
Definition: TypeSize.h:284
llvm::LegalizationArtifactCombiner::tryCombineAnyExt
bool tryCombineAnyExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
Definition: LegalizationArtifactCombiner.h:55
llvm::MachineInstrBuilder::getReg
Register getReg(unsigned Idx) const
Get the register for the operand index.
Definition: MachineInstrBuilder.h:94
llvm::GISelObserverWrapper::changedInstr
void changedInstr(MachineInstr &MI) override
This instruction was mutated in some way.
Definition: GISelChangeObserver.h:96
llvm::MIPatternMatch::m_GAnyExt
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
Definition: MIPatternMatch.h:404
llvm::LegalizationArtifactCombiner::replaceRegOrBuildCopy
static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI, MachineIRBuilder &Builder, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
Try to replace DstReg with SrcReg or build a COPY instruction depending on the register constraints.
Definition: LegalizationArtifactCombiner.h:511
llvm::GISelChangeObserver::changedInstr
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
llvm::Register::isVirtual
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:91
llvm::ISD::Register
@ Register
Definition: ISDOpcodes.h:74
llvm::LLT::divide
LLT divide(int Factor) const
Return a type that is Factor times smaller.
Definition: LowLevelTypeImpl.h:197
llvm::MachineIRBuilder
Helper class to build MachineInstr.
Definition: MachineIRBuilder.h:212
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
uint64_t
llvm::GMergeLikeOp::getSourceReg
Register getSourceReg(unsigned I) const
Returns the I'th source register.
Definition: GenericMachineInstrs.h:160
llvm::MachineIRBuilder::setInstrAndDebugLoc
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
Definition: MachineIRBuilder.h:342
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::LLT::isVector
bool isVector() const
Definition: LowLevelTypeImpl.h:123
llvm::LLT::getNumElements
uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
Definition: LowLevelTypeImpl.h:127
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::LegalizerInfo::getAction
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
Definition: LegalizerInfo.cpp:321
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:360
llvm::LLT::isScalar
bool isScalar() const
Definition: LowLevelTypeImpl.h:119
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:650
llvm::APInt
Class for arbitrary precision integers.
Definition: APInt.h:75
llvm::GConcatVectors
Represents a G_CONCAT_VECTORS.
Definition: GenericMachineInstrs.h:183
llvm::LegalizationArtifactCombiner::tryFoldImplicitDef
bool tryFoldImplicitDef(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
Definition: LegalizationArtifactCombiner.h:328
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:489
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::LegalizationArtifactCombiner::tryCombineTrunc
bool tryCombineTrunc(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
Definition: LegalizationArtifactCombiner.h:226
llvm::MIPatternMatch::m_any_of
Or< Preds... > m_any_of(Preds &&... preds)
Definition: MIPatternMatch.h:171
llvm::GenericMachineInstr::getReg
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
Definition: GenericMachineInstrs.h:31
llvm::GISelChangeObserver
Abstract class that contains various methods for clients to notify about changes.
Definition: GISelChangeObserver.h:29
llvm::MIPatternMatch::m_Copy
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
Definition: MIPatternMatch.h:463
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::GUnmerge
Represents a G_UNMERGE_VALUES.
Definition: GenericMachineInstrs.h:140
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::APInt::zext
APInt zext(unsigned width) const
Zero extend to a new width.
Definition: APInt.cpp:950
j
return j(j<< 16)
llvm::canReplaceReg
bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI)
Check if DstReg can be replaced with SrcReg depending on the register constraints.
Definition: Utils.cpp:180
llvm::LegalizeActions::FewerElements
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
Definition: LegalizerInfo.h:64
llvm::LegacyLegalizeActions::Unsupported
@ Unsupported
This operation is completely unsupported on the target.
Definition: LegacyLegalizerInfo.h:71
Legalizer.h
llvm::GMergeLikeOp::getNumSources
unsigned getNumSources() const
Returns the number of source registers.
Definition: GenericMachineInstrs.h:158
llvm::LegalizationArtifactCombiner::ArtifactValueFinder::tryCombineUnmergeDefs
bool tryCombineUnmergeDefs(GUnmerge &MI, GISelChangeObserver &Observer, SmallVectorImpl< Register > &UpdatedDefs)
Try to combine the defs of an unmerge MI by attempting to find values that provides the bits for each...
Definition: LegalizationArtifactCombiner.h:778
llvm::LegalizationArtifactCombiner
Definition: LegalizationArtifactCombiner.h:33
llvm::LegalizeActionStep::TypeIdx
unsigned TypeIdx
If describing an action, the type index to change. Otherwise zero.
Definition: LegalizerInfo.h:146
SmallBitVector.h
llvm::MIPatternMatch
Definition: MIPatternMatch.h:21
DefMI
MachineInstrBuilder MachineInstrBuilder & DefMI
Definition: AArch64ExpandPseudoInsts.cpp:103
llvm::MachineInstr::getNumOperands
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:492
llvm::LegalizationArtifactCombiner::tryCombineInstruction
bool tryCombineInstruction(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, GISelObserverWrapper &WrapperObserver)
Try to combine away MI.
Definition: LegalizationArtifactCombiner.h:1069
llvm::LegalizeActions::Unsupported
@ Unsupported
This operation is completely unsupported on the target.
Definition: LegalizerInfo.h:90
llvm::SmallVectorImpl< MachineInstr * >
llvm::GISelObserverWrapper
Simple wrapper observer that takes several observers, and calls each one for each event.
Definition: GISelChangeObserver.h:66
llvm::LegalizerInfo
Definition: LegalizerInfo.h:1110
llvm::MIPatternMatch::m_all_of
And< Preds... > m_all_of(Preds &&... preds)
Definition: MIPatternMatch.h:167
Register.h
llvm::MIPatternMatch::mi_match
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
Definition: MIPatternMatch.h:24
GISelChangeObserver.h
llvm::LLT::getElementType
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
Definition: LowLevelTypeImpl.h:237
llvm::LegalizeActions::Lower
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
Definition: LegalizerInfo.h:77
llvm::LegacyLegalizeActions::NotFound
@ NotFound
Sentinel value for when no action was found in the specified table.
Definition: LegacyLegalizerInfo.h:74
Debug.h
llvm::SrcOp
Definition: MachineIRBuilder.h:119
llvm::LegalizationArtifactCombiner::LegalizationArtifactCombiner
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI)
Definition: LegalizationArtifactCombiner.h:51
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
llvm::LLT
Definition: LowLevelTypeImpl.h:40