LLVM  13.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 
23 #include "llvm/Support/Debug.h"
24 
25 #define DEBUG_TYPE "legalizer"
26 using namespace llvm::MIPatternMatch;
27 
28 namespace llvm {
32  const LegalizerInfo &LI;
33 
34  static bool isArtifactCast(unsigned Opc) {
35  switch (Opc) {
36  case TargetOpcode::G_TRUNC:
37  case TargetOpcode::G_SEXT:
38  case TargetOpcode::G_ZEXT:
39  case TargetOpcode::G_ANYEXT:
40  return true;
41  default:
42  return false;
43  }
44  }
45 
46 public:
48  const LegalizerInfo &LI)
49  : Builder(B), MRI(MRI), LI(LI) {}
50 
53  SmallVectorImpl<Register> &UpdatedDefs) {
54  assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);
55 
56  Builder.setInstrAndDebugLoc(MI);
57  Register DstReg = MI.getOperand(0).getReg();
58  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
59 
60  // aext(trunc x) - > aext/copy/trunc x
61  Register TruncSrc;
62  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
63  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
64  Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
65  UpdatedDefs.push_back(DstReg);
66  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
67  return true;
68  }
69 
70  // aext([asz]ext x) -> [asz]ext x
71  Register ExtSrc;
72  MachineInstr *ExtMI;
73  if (mi_match(SrcReg, MRI,
74  m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
75  m_GSExt(m_Reg(ExtSrc)),
76  m_GZExt(m_Reg(ExtSrc)))))) {
77  Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
78  UpdatedDefs.push_back(DstReg);
79  markInstAndDefDead(MI, *ExtMI, DeadInsts);
80  return true;
81  }
82 
83  // Try to fold aext(g_constant) when the larger constant type is legal.
84  auto *SrcMI = MRI.getVRegDef(SrcReg);
85  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
86  const LLT DstTy = MRI.getType(DstReg);
87  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
88  auto &CstVal = SrcMI->getOperand(1);
89  Builder.buildConstant(
90  DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
91  UpdatedDefs.push_back(DstReg);
92  markInstAndDefDead(MI, *SrcMI, DeadInsts);
93  return true;
94  }
95  }
96  return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
97  }
98 
101  SmallVectorImpl<Register> &UpdatedDefs,
102  GISelObserverWrapper &Observer) {
103  assert(MI.getOpcode() == TargetOpcode::G_ZEXT);
104 
105  Builder.setInstrAndDebugLoc(MI);
106  Register DstReg = MI.getOperand(0).getReg();
107  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
108 
109  // zext(trunc x) - > and (aext/copy/trunc x), mask
110  // zext(sext x) -> and (sext x), mask
111  Register TruncSrc;
112  Register SextSrc;
113  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc))) ||
114  mi_match(SrcReg, MRI, m_GSExt(m_Reg(SextSrc)))) {
115  LLT DstTy = MRI.getType(DstReg);
116  if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
117  isConstantUnsupported(DstTy))
118  return false;
119  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
120  LLT SrcTy = MRI.getType(SrcReg);
121  APInt MaskVal = APInt::getAllOnesValue(SrcTy.getScalarSizeInBits());
122  auto Mask = Builder.buildConstant(
123  DstTy, MaskVal.zext(DstTy.getScalarSizeInBits()));
124  auto Extended = SextSrc ? Builder.buildSExtOrTrunc(DstTy, SextSrc) :
125  Builder.buildAnyExtOrTrunc(DstTy, TruncSrc);
126  Builder.buildAnd(DstReg, Extended, Mask);
127  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
128  return true;
129  }
130 
131  // zext(zext x) -> (zext x)
132  Register ZextSrc;
133  if (mi_match(SrcReg, MRI, m_GZExt(m_Reg(ZextSrc)))) {
134  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
135  Observer.changingInstr(MI);
136  MI.getOperand(1).setReg(ZextSrc);
137  Observer.changedInstr(MI);
138  UpdatedDefs.push_back(DstReg);
139  markDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
140  return true;
141  }
142 
143  // Try to fold zext(g_constant) when the larger constant type is legal.
144  auto *SrcMI = MRI.getVRegDef(SrcReg);
145  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
146  const LLT DstTy = MRI.getType(DstReg);
147  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
148  auto &CstVal = SrcMI->getOperand(1);
149  Builder.buildConstant(
150  DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));
151  UpdatedDefs.push_back(DstReg);
152  markInstAndDefDead(MI, *SrcMI, DeadInsts);
153  return true;
154  }
155  }
156  return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
157  }
158 
161  SmallVectorImpl<Register> &UpdatedDefs) {
162  assert(MI.getOpcode() == TargetOpcode::G_SEXT);
163 
164  Builder.setInstrAndDebugLoc(MI);
165  Register DstReg = MI.getOperand(0).getReg();
166  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
167 
168  // sext(trunc x) - > (sext_inreg (aext/copy/trunc x), c)
169  Register TruncSrc;
170  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
171  LLT DstTy = MRI.getType(DstReg);
172  if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))
173  return false;
174  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
175  LLT SrcTy = MRI.getType(SrcReg);
176  uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
177  Builder.buildInstr(
178  TargetOpcode::G_SEXT_INREG, {DstReg},
179  {Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), SizeInBits});
180  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
181  return true;
182  }
183 
184  // sext(zext x) -> (zext x)
185  // sext(sext x) -> (sext x)
186  Register ExtSrc;
187  MachineInstr *ExtMI;
188  if (mi_match(SrcReg, MRI,
189  m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)),
190  m_GSExt(m_Reg(ExtSrc)))))) {
191  LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
192  Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
193  UpdatedDefs.push_back(DstReg);
194  markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
195  return true;
196  }
197 
198  // Try to fold sext(g_constant) when the larger constant type is legal.
199  auto *SrcMI = MRI.getVRegDef(SrcReg);
200  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
201  const LLT DstTy = MRI.getType(DstReg);
202  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
203  auto &CstVal = SrcMI->getOperand(1);
204  Builder.buildConstant(
205  DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
206  UpdatedDefs.push_back(DstReg);
207  markInstAndDefDead(MI, *SrcMI, DeadInsts);
208  return true;
209  }
210  }
211 
212  return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
213  }
214 
217  SmallVectorImpl<Register> &UpdatedDefs,
218  GISelObserverWrapper &Observer) {
219  assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
220 
221  Builder.setInstr(MI);
222  Register DstReg = MI.getOperand(0).getReg();
223  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
224 
225  // Try to fold trunc(g_constant) when the smaller constant type is legal.
226  auto *SrcMI = MRI.getVRegDef(SrcReg);
227  if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
228  const LLT DstTy = MRI.getType(DstReg);
229  if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
230  auto &CstVal = SrcMI->getOperand(1);
231  Builder.buildConstant(
232  DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits()));
233  UpdatedDefs.push_back(DstReg);
234  markInstAndDefDead(MI, *SrcMI, DeadInsts);
235  return true;
236  }
237  }
238 
239  // Try to fold trunc(merge) to directly use the source of the merge.
240  // This gets rid of large, difficult to legalize, merges
241  if (SrcMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) {
242  const Register MergeSrcReg = SrcMI->getOperand(1).getReg();
243  const LLT MergeSrcTy = MRI.getType(MergeSrcReg);
244  const LLT DstTy = MRI.getType(DstReg);
245 
246  // We can only fold if the types are scalar
247  const unsigned DstSize = DstTy.getSizeInBits();
248  const unsigned MergeSrcSize = MergeSrcTy.getSizeInBits();
249  if (!DstTy.isScalar() || !MergeSrcTy.isScalar())
250  return false;
251 
252  if (DstSize < MergeSrcSize) {
253  // When the merge source is larger than the destination, we can just
254  // truncate the merge source directly
255  if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
256  return false;
257 
258  LLVM_DEBUG(dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
259  << MI);
260 
261  Builder.buildTrunc(DstReg, MergeSrcReg);
262  UpdatedDefs.push_back(DstReg);
263  } else if (DstSize == MergeSrcSize) {
264  // If the sizes match we can simply try to replace the register
265  LLVM_DEBUG(
266  dbgs() << "Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
267  << MI);
268  replaceRegOrBuildCopy(DstReg, MergeSrcReg, MRI, Builder, UpdatedDefs,
269  Observer);
270  } else if (DstSize % MergeSrcSize == 0) {
271  // If the trunc size is a multiple of the merge source size we can use
272  // a smaller merge instead
273  if (isInstUnsupported(
274  {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
275  return false;
276 
277  LLVM_DEBUG(
278  dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
279  << MI);
280 
281  const unsigned NumSrcs = DstSize / MergeSrcSize;
282  assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
283  "trunc(merge) should require less inputs than merge");
284  SmallVector<Register, 8> SrcRegs(NumSrcs);
285  for (unsigned i = 0; i < NumSrcs; ++i)
286  SrcRegs[i] = SrcMI->getOperand(i + 1).getReg();
287 
288  Builder.buildMerge(DstReg, SrcRegs);
289  UpdatedDefs.push_back(DstReg);
290  } else {
291  // Unable to combine
292  return false;
293  }
294 
295  markInstAndDefDead(MI, *SrcMI, DeadInsts);
296  return true;
297  }
298 
299  // trunc(trunc) -> trunc
300  Register TruncSrc;
301  if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
302  // Always combine trunc(trunc) since the eventual resulting trunc must be
303  // legal anyway as it must be legal for all outputs of the consumer type
304  // set.
305  LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_TRUNC): " << MI);
306 
307  Builder.buildTrunc(DstReg, TruncSrc);
308  UpdatedDefs.push_back(DstReg);
309  markInstAndDefDead(MI, *MRI.getVRegDef(TruncSrc), DeadInsts);
310  return true;
311  }
312 
313  return false;
314  }
315 
316  /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
319  SmallVectorImpl<Register> &UpdatedDefs) {
320  unsigned Opcode = MI.getOpcode();
321  assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
322  Opcode == TargetOpcode::G_SEXT);
323 
324  if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
325  MI.getOperand(1).getReg(), MRI)) {
326  Builder.setInstr(MI);
327  Register DstReg = MI.getOperand(0).getReg();
328  LLT DstTy = MRI.getType(DstReg);
329 
330  if (Opcode == TargetOpcode::G_ANYEXT) {
331  // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF
332  if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
333  return false;
334  LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;);
335  Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
336  UpdatedDefs.push_back(DstReg);
337  } else {
338  // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
339  // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
340  if (isConstantUnsupported(DstTy))
341  return false;
342  LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;);
343  Builder.buildConstant(DstReg, 0);
344  UpdatedDefs.push_back(DstReg);
345  }
346 
347  markInstAndDefDead(MI, *DefMI, DeadInsts);
348  return true;
349  }
350  return false;
351  }
352 
355  SmallVectorImpl<Register> &UpdatedDefs) {
356 
357  assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
358 
359  const unsigned CastOpc = CastMI.getOpcode();
360 
361  if (!isArtifactCast(CastOpc))
362  return false;
363 
364  const unsigned NumDefs = MI.getNumOperands() - 1;
365 
366  const Register CastSrcReg = CastMI.getOperand(1).getReg();
367  const LLT CastSrcTy = MRI.getType(CastSrcReg);
368  const LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
369  const LLT SrcTy = MRI.getType(MI.getOperand(NumDefs).getReg());
370 
371  const unsigned CastSrcSize = CastSrcTy.getSizeInBits();
372  const unsigned DestSize = DestTy.getSizeInBits();
373 
374  if (CastOpc == TargetOpcode::G_TRUNC) {
375  if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.getScalarType()) {
376  // %1:_(<4 x s8>) = G_TRUNC %0(<4 x s32>)
377  // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %1
378  // =>
379  // %6:_(s32), %7:_(s32), %8:_(s32), %9:_(s32) = G_UNMERGE_VALUES %0
380  // %2:_(s8) = G_TRUNC %6
381  // %3:_(s8) = G_TRUNC %7
382  // %4:_(s8) = G_TRUNC %8
383  // %5:_(s8) = G_TRUNC %9
384 
385  unsigned UnmergeNumElts =
386  DestTy.isVector() ? CastSrcTy.getNumElements() / NumDefs : 1;
387  LLT UnmergeTy = CastSrcTy.changeNumElements(UnmergeNumElts);
388 
389  if (isInstUnsupported(
390  {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}))
391  return false;
392 
393  Builder.setInstr(MI);
394  auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg);
395 
396  for (unsigned I = 0; I != NumDefs; ++I) {
397  Register DefReg = MI.getOperand(I).getReg();
398  UpdatedDefs.push_back(DefReg);
399  Builder.buildTrunc(DefReg, NewUnmerge.getReg(I));
400  }
401 
402  markInstAndDefDead(MI, CastMI, DeadInsts);
403  return true;
404  }
405 
406  if (CastSrcTy.isScalar() && SrcTy.isScalar() && !DestTy.isVector()) {
407  // %1:_(s16) = G_TRUNC %0(s32)
408  // %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %1
409  // =>
410  // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %0
411 
412  // Unmerge(trunc) can be combined if the trunc source size is a multiple
413  // of the unmerge destination size
414  if (CastSrcSize % DestSize != 0)
415  return false;
416 
417  // Check if the new unmerge is supported
418  if (isInstUnsupported(
419  {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
420  return false;
421 
422  // Gather the original destination registers and create new ones for the
423  // unused bits
424  const unsigned NewNumDefs = CastSrcSize / DestSize;
425  SmallVector<Register, 8> DstRegs(NewNumDefs);
426  for (unsigned Idx = 0; Idx < NewNumDefs; ++Idx) {
427  if (Idx < NumDefs)
428  DstRegs[Idx] = MI.getOperand(Idx).getReg();
429  else
430  DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy);
431  }
432 
433  // Build new unmerge
434  Builder.setInstr(MI);
435  Builder.buildUnmerge(DstRegs, CastSrcReg);
436  UpdatedDefs.append(DstRegs.begin(), DstRegs.begin() + NewNumDefs);
437  markInstAndDefDead(MI, CastMI, DeadInsts);
438  return true;
439  }
440  }
441 
442  // TODO: support combines with other casts as well
443  return false;
444  }
445 
446  static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp,
447  LLT OpTy, LLT DestTy) {
448  // Check if we found a definition that is like G_MERGE_VALUES.
449  switch (MergeOp) {
450  default:
451  return false;
452  case TargetOpcode::G_BUILD_VECTOR:
453  case TargetOpcode::G_MERGE_VALUES:
454  // The convert operation that we will need to insert is
455  // going to convert the input of that type of instruction (scalar)
456  // to the destination type (DestTy).
457  // The conversion needs to stay in the same domain (scalar to scalar
458  // and vector to vector), so if we were to allow to fold the merge
459  // we would need to insert some bitcasts.
460  // E.g.,
461  // <2 x s16> = build_vector s16, s16
462  // <2 x s32> = zext <2 x s16>
463  // <2 x s16>, <2 x s16> = unmerge <2 x s32>
464  //
465  // As is the folding would produce:
466  // <2 x s16> = zext s16 <-- scalar to vector
467  // <2 x s16> = zext s16 <-- scalar to vector
468  // Which is invalid.
469  // Instead we would want to generate:
470  // s32 = zext s16
471  // <2 x s16> = bitcast s32
472  // s32 = zext s16
473  // <2 x s16> = bitcast s32
474  //
475  // That is not done yet.
476  if (ConvertOp == 0)
477  return true;
478  return !DestTy.isVector() && OpTy.isVector();
479  case TargetOpcode::G_CONCAT_VECTORS: {
480  if (ConvertOp == 0)
481  return true;
482  if (!DestTy.isVector())
483  return false;
484 
485  const unsigned OpEltSize = OpTy.getElementType().getSizeInBits();
486 
487  // Don't handle scalarization with a cast that isn't in the same
488  // direction as the vector cast. This could be handled, but it would
489  // require more intermediate unmerges.
490  if (ConvertOp == TargetOpcode::G_TRUNC)
491  return DestTy.getSizeInBits() <= OpEltSize;
492  return DestTy.getSizeInBits() >= OpEltSize;
493  }
494  }
495  }
496 
497  /// Try to replace DstReg with SrcReg or build a COPY instruction
498  /// depending on the register constraints.
499  static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg,
502  SmallVectorImpl<Register> &UpdatedDefs,
503  GISelChangeObserver &Observer) {
504  if (!llvm::canReplaceReg(DstReg, SrcReg, MRI)) {
505  Builder.buildCopy(DstReg, SrcReg);
506  UpdatedDefs.push_back(DstReg);
507  return;
508  }
510  // Get the users and notify the observer before replacing.
511  for (auto &UseMI : MRI.use_instructions(DstReg)) {
512  UseMIs.push_back(&UseMI);
513  Observer.changingInstr(UseMI);
514  }
515  // Replace the registers.
516  MRI.replaceRegWith(DstReg, SrcReg);
517  UpdatedDefs.push_back(SrcReg);
518  // Notify the observer that we changed the instructions.
519  for (auto *UseMI : UseMIs)
520  Observer.changedInstr(*UseMI);
521  }
522 
523  /// Return the operand index in \p MI that defines \p Def
524  static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef) {
525  unsigned DefIdx = 0;
526  for (const MachineOperand &Def : MI.defs()) {
527  if (Def.getReg() == SearchDef)
528  break;
529  ++DefIdx;
530  }
531 
532  return DefIdx;
533  }
534 
537  SmallVectorImpl<Register> &UpdatedDefs,
538  GISelChangeObserver &Observer) {
539  assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
540 
541  unsigned NumDefs = MI.getNumOperands() - 1;
542  Register SrcReg = MI.getOperand(NumDefs).getReg();
543  MachineInstr *SrcDef = getDefIgnoringCopies(SrcReg, MRI);
544  if (!SrcDef)
545  return false;
546 
547  LLT OpTy = MRI.getType(MI.getOperand(NumDefs).getReg());
548  LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
549 
550  if (SrcDef->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
551  // %0:_(<4 x s16>) = G_FOO
552  // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0
553  // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1
554  //
555  // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0
556  const unsigned NumSrcOps = SrcDef->getNumOperands();
557  Register SrcUnmergeSrc = SrcDef->getOperand(NumSrcOps - 1).getReg();
558  LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);
559 
560  // If we need to decrease the number of vector elements in the result type
561  // of an unmerge, this would involve the creation of an equivalent unmerge
562  // to copy back to the original result registers.
563  LegalizeActionStep ActionStep = LI.getAction(
564  {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
565  switch (ActionStep.Action) {
568  break;
571  if (ActionStep.TypeIdx == 1)
572  return false;
573  break;
574  default:
575  return false;
576  }
577 
578  Builder.setInstrAndDebugLoc(MI);
579  auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
580 
581  // TODO: Should we try to process out the other defs now? If the other
582  // defs of the source unmerge are also unmerged, we end up with a separate
583  // unmerge for each one.
584  unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg);
585  for (unsigned I = 0; I != NumDefs; ++I) {
586  Register Def = MI.getOperand(I).getReg();
587  replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I),
588  MRI, Builder, UpdatedDefs, Observer);
589  }
590 
591  markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);
592  return true;
593  }
594 
595  MachineInstr *MergeI = SrcDef;
596  unsigned ConvertOp = 0;
597 
598  // Handle intermediate conversions
599  unsigned SrcOp = SrcDef->getOpcode();
600  if (isArtifactCast(SrcOp)) {
601  ConvertOp = SrcOp;
602  MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI);
603  }
604 
605  if (!MergeI || !canFoldMergeOpcode(MergeI->getOpcode(),
606  ConvertOp, OpTy, DestTy)) {
607  // We might have a chance to combine later by trying to combine
608  // unmerge(cast) first
609  return tryFoldUnmergeCast(MI, *SrcDef, DeadInsts, UpdatedDefs);
610  }
611 
612  const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
613 
614  if (NumMergeRegs < NumDefs) {
615  if (NumDefs % NumMergeRegs != 0)
616  return false;
617 
618  Builder.setInstr(MI);
619  // Transform to UNMERGEs, for example
620  // %1 = G_MERGE_VALUES %4, %5
621  // %9, %10, %11, %12 = G_UNMERGE_VALUES %1
622  // to
623  // %9, %10 = G_UNMERGE_VALUES %4
624  // %11, %12 = G_UNMERGE_VALUES %5
625 
626  const unsigned NewNumDefs = NumDefs / NumMergeRegs;
627  for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
628  SmallVector<Register, 8> DstRegs;
629  for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
630  ++j, ++DefIdx)
631  DstRegs.push_back(MI.getOperand(DefIdx).getReg());
632 
633  if (ConvertOp) {
634  LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
635 
636  // This is a vector that is being split and casted. Extract to the
637  // element type, and do the conversion on the scalars (or smaller
638  // vectors).
639  LLT MergeEltTy = MergeSrcTy.divide(NewNumDefs);
640 
641  // Handle split to smaller vectors, with conversions.
642  // %2(<8 x s8>) = G_CONCAT_VECTORS %0(<4 x s8>), %1(<4 x s8>)
643  // %3(<8 x s16>) = G_SEXT %2
644  // %4(<2 x s16>), %5(<2 x s16>), %6(<2 x s16>), %7(<2 x s16>) = G_UNMERGE_VALUES %3
645  //
646  // =>
647  //
648  // %8(<2 x s8>), %9(<2 x s8>) = G_UNMERGE_VALUES %0
649  // %10(<2 x s8>), %11(<2 x s8>) = G_UNMERGE_VALUES %1
650  // %4(<2 x s16>) = G_SEXT %8
651  // %5(<2 x s16>) = G_SEXT %9
652  // %6(<2 x s16>) = G_SEXT %10
653  // %7(<2 x s16>)= G_SEXT %11
654 
655  SmallVector<Register, 4> TmpRegs(NewNumDefs);
656  for (unsigned k = 0; k < NewNumDefs; ++k)
657  TmpRegs[k] = MRI.createGenericVirtualRegister(MergeEltTy);
658 
659  Builder.buildUnmerge(TmpRegs, MergeI->getOperand(Idx + 1).getReg());
660 
661  for (unsigned k = 0; k < NewNumDefs; ++k)
662  Builder.buildInstr(ConvertOp, {DstRegs[k]}, {TmpRegs[k]});
663  } else {
664  Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
665  }
666  UpdatedDefs.append(DstRegs.begin(), DstRegs.end());
667  }
668 
669  } else if (NumMergeRegs > NumDefs) {
670  if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
671  return false;
672 
673  Builder.setInstr(MI);
674  // Transform to MERGEs
675  // %6 = G_MERGE_VALUES %17, %18, %19, %20
676  // %7, %8 = G_UNMERGE_VALUES %6
677  // to
678  // %7 = G_MERGE_VALUES %17, %18
679  // %8 = G_MERGE_VALUES %19, %20
680 
681  const unsigned NumRegs = NumMergeRegs / NumDefs;
682  for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
684  for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
685  ++j, ++Idx)
686  Regs.push_back(MergeI->getOperand(Idx).getReg());
687 
688  Register DefReg = MI.getOperand(DefIdx).getReg();
689  Builder.buildMerge(DefReg, Regs);
690  UpdatedDefs.push_back(DefReg);
691  }
692 
693  } else {
694  LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
695 
696  if (!ConvertOp && DestTy != MergeSrcTy)
697  ConvertOp = TargetOpcode::G_BITCAST;
698 
699  if (ConvertOp) {
700  Builder.setInstr(MI);
701 
702  for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
703  Register MergeSrc = MergeI->getOperand(Idx + 1).getReg();
704  Register DefReg = MI.getOperand(Idx).getReg();
705  Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
706  UpdatedDefs.push_back(DefReg);
707  }
708 
709  markInstAndDefDead(MI, *MergeI, DeadInsts);
710  return true;
711  }
712 
713  assert(DestTy == MergeSrcTy &&
714  "Bitcast and the other kinds of conversions should "
715  "have happened earlier");
716 
717  Builder.setInstr(MI);
718  for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
719  Register DstReg = MI.getOperand(Idx).getReg();
720  Register SrcReg = MergeI->getOperand(Idx + 1).getReg();
721  replaceRegOrBuildCopy(DstReg, SrcReg, MRI, Builder, UpdatedDefs,
722  Observer);
723  }
724  }
725 
726  markInstAndDefDead(MI, *MergeI, DeadInsts);
727  return true;
728  }
729 
730  static bool isMergeLikeOpcode(unsigned Opc) {
731  switch (Opc) {
732  case TargetOpcode::G_MERGE_VALUES:
733  case TargetOpcode::G_BUILD_VECTOR:
734  case TargetOpcode::G_CONCAT_VECTORS:
735  return true;
736  default:
737  return false;
738  }
739  }
740 
743  SmallVectorImpl<Register> &UpdatedDefs) {
744  assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
745 
746  // Try to use the source registers from a G_MERGE_VALUES
747  //
748  // %2 = G_MERGE_VALUES %0, %1
749  // %3 = G_EXTRACT %2, N
750  // =>
751  //
752  // for N < %2.getSizeInBits() / 2
753  // %3 = G_EXTRACT %0, N
754  //
755  // for N >= %2.getSizeInBits() / 2
756  // %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
757 
758  Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
759  MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
760  if (!MergeI || !isMergeLikeOpcode(MergeI->getOpcode()))
761  return false;
762 
763  Register DstReg = MI.getOperand(0).getReg();
764  LLT DstTy = MRI.getType(DstReg);
765  LLT SrcTy = MRI.getType(SrcReg);
766 
767  // TODO: Do we need to check if the resulting extract is supported?
768  unsigned ExtractDstSize = DstTy.getSizeInBits();
769  unsigned Offset = MI.getOperand(2).getImm();
770  unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
771  unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
772  unsigned MergeSrcIdx = Offset / MergeSrcSize;
773 
774  // Compute the offset of the last bit the extract needs.
775  unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
776 
777  // Can't handle the case where the extract spans multiple inputs.
778  if (MergeSrcIdx != EndMergeSrcIdx)
779  return false;
780 
781  // TODO: We could modify MI in place in most cases.
782  Builder.setInstr(MI);
783  Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(),
784  Offset - MergeSrcIdx * MergeSrcSize);
785  UpdatedDefs.push_back(DstReg);
786  markInstAndDefDead(MI, *MergeI, DeadInsts);
787  return true;
788  }
789 
790  /// Try to combine away MI.
791  /// Returns true if it combined away the MI.
792  /// Adds instructions that are dead as a result of the combine
793  /// into DeadInsts, which can include MI.
796  GISelObserverWrapper &WrapperObserver) {
797  // This might be a recursive call, and we might have DeadInsts already
798  // populated. To avoid bad things happening later with multiple vreg defs
799  // etc, process the dead instructions now if any.
800  if (!DeadInsts.empty())
801  deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
802 
803  // Put here every vreg that was redefined in such a way that it's at least
804  // possible that one (or more) of its users (immediate or COPY-separated)
805  // could become artifact combinable with the new definition (or the
806  // instruction reachable from it through a chain of copies if any).
807  SmallVector<Register, 4> UpdatedDefs;
808  bool Changed = false;
809  switch (MI.getOpcode()) {
810  default:
811  return false;
812  case TargetOpcode::G_ANYEXT:
813  Changed = tryCombineAnyExt(MI, DeadInsts, UpdatedDefs);
814  break;
815  case TargetOpcode::G_ZEXT:
816  Changed = tryCombineZExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
817  break;
818  case TargetOpcode::G_SEXT:
819  Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs);
820  break;
821  case TargetOpcode::G_UNMERGE_VALUES:
822  Changed =
823  tryCombineUnmergeValues(MI, DeadInsts, UpdatedDefs, WrapperObserver);
824  break;
825  case TargetOpcode::G_MERGE_VALUES:
826  case TargetOpcode::G_BUILD_VECTOR:
827  case TargetOpcode::G_CONCAT_VECTORS:
828  // If any of the users of this merge are an unmerge, then add them to the
829  // artifact worklist in case there's folding that can be done looking up.
830  for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) {
831  if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
832  U.getOpcode() == TargetOpcode::G_TRUNC) {
833  UpdatedDefs.push_back(MI.getOperand(0).getReg());
834  break;
835  }
836  }
837  break;
838  case TargetOpcode::G_EXTRACT:
839  Changed = tryCombineExtract(MI, DeadInsts, UpdatedDefs);
840  break;
841  case TargetOpcode::G_TRUNC:
842  Changed = tryCombineTrunc(MI, DeadInsts, UpdatedDefs, WrapperObserver);
843  if (!Changed) {
844  // Try to combine truncates away even if they are legal. As all artifact
845  // combines at the moment look only "up" the def-use chains, we achieve
846  // that by throwing truncates' users (with look through copies) into the
847  // ArtifactList again.
848  UpdatedDefs.push_back(MI.getOperand(0).getReg());
849  }
850  break;
851  }
852  // If the main loop through the ArtifactList found at least one combinable
853  // pair of artifacts, not only combine it away (as done above), but also
854  // follow the def-use chain from there to combine everything that can be
855  // combined within this def-use chain of artifacts.
856  while (!UpdatedDefs.empty()) {
857  Register NewDef = UpdatedDefs.pop_back_val();
858  assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg");
859  for (MachineInstr &Use : MRI.use_instructions(NewDef)) {
860  switch (Use.getOpcode()) {
861  // Keep this list in sync with the list of all artifact combines.
862  case TargetOpcode::G_ANYEXT:
863  case TargetOpcode::G_ZEXT:
864  case TargetOpcode::G_SEXT:
865  case TargetOpcode::G_UNMERGE_VALUES:
866  case TargetOpcode::G_EXTRACT:
867  case TargetOpcode::G_TRUNC:
868  // Adding Use to ArtifactList.
869  WrapperObserver.changedInstr(Use);
870  break;
871  case TargetOpcode::COPY: {
872  Register Copy = Use.getOperand(0).getReg();
873  if (Copy.isVirtual())
874  UpdatedDefs.push_back(Copy);
875  break;
876  }
877  default:
878  // If we do not have an artifact combine for the opcode, there is no
879  // point in adding it to the ArtifactList as nothing interesting will
880  // be done to it anyway.
881  break;
882  }
883  }
884  }
885  return Changed;
886  }
887 
888 private:
889  static Register getArtifactSrcReg(const MachineInstr &MI) {
890  switch (MI.getOpcode()) {
891  case TargetOpcode::COPY:
892  case TargetOpcode::G_TRUNC:
893  case TargetOpcode::G_ZEXT:
894  case TargetOpcode::G_ANYEXT:
895  case TargetOpcode::G_SEXT:
896  case TargetOpcode::G_EXTRACT:
897  return MI.getOperand(1).getReg();
898  case TargetOpcode::G_UNMERGE_VALUES:
899  return MI.getOperand(MI.getNumOperands() - 1).getReg();
900  default:
901  llvm_unreachable("Not a legalization artifact happen");
902  }
903  }
904 
905  /// Mark a def of one of MI's original operands, DefMI, as dead if changing MI
906  /// (either by killing it or changing operands) results in DefMI being dead
907  /// too. In-between COPYs or artifact-casts are also collected if they are
908  /// dead.
909  /// MI is not marked dead.
910  void markDefDead(MachineInstr &MI, MachineInstr &DefMI,
911  SmallVectorImpl<MachineInstr *> &DeadInsts,
912  unsigned DefIdx = 0) {
913  // Collect all the copy instructions that are made dead, due to deleting
914  // this instruction. Collect all of them until the Trunc(DefMI).
915  // Eg,
916  // %1(s1) = G_TRUNC %0(s32)
917  // %2(s1) = COPY %1(s1)
918  // %3(s1) = COPY %2(s1)
919  // %4(s32) = G_ANYEXT %3(s1)
920  // In this case, we would have replaced %4 with a copy of %0,
921  // and as a result, %3, %2, %1 are dead.
922  MachineInstr *PrevMI = &MI;
923  while (PrevMI != &DefMI) {
924  Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
925 
926  MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
927  if (MRI.hasOneUse(PrevRegSrc)) {
928  if (TmpDef != &DefMI) {
929  assert((TmpDef->getOpcode() == TargetOpcode::COPY ||
930  isArtifactCast(TmpDef->getOpcode())) &&
931  "Expecting copy or artifact cast here");
932 
933  DeadInsts.push_back(TmpDef);
934  }
935  } else
936  break;
937  PrevMI = TmpDef;
938  }
939 
940  if (PrevMI == &DefMI) {
941  unsigned I = 0;
942  bool IsDead = true;
943  for (MachineOperand &Def : DefMI.defs()) {
944  if (I != DefIdx) {
945  if (!MRI.use_empty(Def.getReg())) {
946  IsDead = false;
947  break;
948  }
949  } else {
950  if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg()))
951  break;
952  }
953 
954  ++I;
955  }
956 
957  if (IsDead)
958  DeadInsts.push_back(&DefMI);
959  }
960  }
961 
962  /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
963  /// dead due to MI being killed, then mark DefMI as dead too.
964  /// Some of the combines (extends(trunc)), try to walk through redundant
965  /// copies in between the extends and the truncs, and this attempts to collect
966  /// the in between copies if they're dead.
967  void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
968  SmallVectorImpl<MachineInstr *> &DeadInsts,
969  unsigned DefIdx = 0) {
970  DeadInsts.push_back(&MI);
971  markDefDead(MI, DefMI, DeadInsts, DefIdx);
972  }
973 
974  /// Erase the dead instructions in the list and call the observer hooks.
975  /// Normally the Legalizer will deal with erasing instructions that have been
976  /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to
977  /// process instructions which have been marked dead, but otherwise break the
978  /// MIR by introducing multiple vreg defs. For those cases, allow the combines
979  /// to explicitly delete the instructions before we run into trouble.
980  void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts,
981  GISelObserverWrapper &WrapperObserver) {
982  for (auto *DeadMI : DeadInsts) {
983  LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");
984  WrapperObserver.erasingInstr(*DeadMI);
985  DeadMI->eraseFromParentAndMarkDBGValuesForRemoval();
986  }
987  DeadInsts.clear();
988  }
989 
990  /// Checks if the target legalizer info has specified anything about the
991  /// instruction, or if unsupported.
992  bool isInstUnsupported(const LegalityQuery &Query) const {
993  using namespace LegalizeActions;
994  auto Step = LI.getAction(Query);
995  return Step.Action == Unsupported || Step.Action == NotFound;
996  }
997 
998  bool isInstLegal(const LegalityQuery &Query) const {
999  return LI.getAction(Query).Action == LegalizeActions::Legal;
1000  }
1001 
1002  bool isConstantUnsupported(LLT Ty) const {
1003  if (!Ty.isVector())
1004  return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1005 
1006  LLT EltTy = Ty.getElementType();
1007  return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1008  isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
1009  }
1010 
1011  /// Looks through copy instructions and returns the actual
1012  /// source register.
1013  Register lookThroughCopyInstrs(Register Reg) {
1014  Register TmpReg;
1015  while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) {
1016  if (MRI.getType(TmpReg).isValid())
1017  Reg = TmpReg;
1018  else
1019  break;
1020  }
1021  return Reg;
1022  }
1023 };
1024 
1025 } // namespace llvm
1026 
1027 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
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:396
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:100
llvm
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:100
llvm::LLT::getScalarSizeInBits
unsigned getScalarSizeInBits() const
Definition: LowLevelTypeImpl.h:163
llvm::LegalizationArtifactCombiner::tryCombineAnyExt
bool tryCombineAnyExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Definition: LegalizationArtifactCombiner.h:51
llvm::LegalizationArtifactCombiner::tryCombineExtract
bool tryCombineExtract(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Definition: LegalizationArtifactCombiner.h:741
llvm::MIPatternMatch::m_Reg
operand_type_match m_Reg()
Definition: MIPatternMatch.h:106
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:152
llvm::LegalizationArtifactCombiner::tryCombineUnmergeValues
bool tryCombineUnmergeValues(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
Definition: LegalizationArtifactCombiner.h:535
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:410
llvm::LegalizeActionStep
The result of a query.
Definition: LegalizerInfo.h:150
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:53
llvm::MIPatternMatch::m_GTrunc
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
Definition: MIPatternMatch.h:361
llvm::LegalizationArtifactCombiner::tryCombineZExt
bool tryCombineZExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
Definition: LegalizationArtifactCombiner.h:99
llvm::LLT::getScalarType
LLT getScalarType() const
Definition: LowLevelTypeImpl.h:121
llvm::LegalizationArtifactCombiner::tryFoldUnmergeCast
bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Definition: LegalizationArtifactCombiner.h:353
llvm::LegalizationArtifactCombiner::canFoldMergeOpcode
static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp, LLT OpTy, LLT DestTy)
Definition: LegalizationArtifactCombiner.h:446
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
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:122
MachineRegisterInfo.h
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
llvm::MIPatternMatch::m_GSExt
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
Definition: MIPatternMatch.h:346
llvm::LegalizationArtifactCombiner::tryCombineSExt
bool tryCombineSExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Definition: LegalizationArtifactCombiner.h:159
llvm::MIPatternMatch::m_GZExt
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
Definition: MIPatternMatch.h:351
llvm::LegalizeActions::NotFound
@ NotFound
Sentinel value for when no action was found in the specified table.
Definition: LegalizerInfo.h:92
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::LLT::changeNumElements
LLT changeNumElements(unsigned NewNumElts) const
Return a vector or scalar with the same element type and the new number of elements.
Definition: LowLevelTypeImpl.h:143
llvm::LLT::getSizeInBits
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelTypeImpl.h:109
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:488
llvm::GISelObserverWrapper::changingInstr
void changingInstr(MachineInstr &MI) override
This instruction is about to be mutated in some way.
Definition: GISelChangeObserver.h:92
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:524
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::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:201
llvm::LegalizeActions::Legal
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
Definition: LegalizerInfo.h:48
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:341
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:499
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:67
llvm::LLT::divide
LLT divide(int Factor) const
Return a type that is Factor times smaller.
Definition: LowLevelTypeImpl.h:150
llvm::MachineIRBuilder
Helper class to build MachineInstr.
Definition: MachineIRBuilder.h:220
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::LegalizationArtifactCombiner::isMergeLikeOpcode
static bool isMergeLikeOpcode(unsigned Opc)
Definition: LegalizationArtifactCombiner.h:730
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::LLT::isVector
bool isVector() const
Definition: LowLevelTypeImpl.h:96
llvm::LLT::getNumElements
uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
Definition: LowLevelTypeImpl.h:100
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:466
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:357
llvm::LLT::isScalar
bool isScalar() const
Definition: LowLevelTypeImpl.h:92
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:649
llvm::APInt
Class for arbitrary precision integers.
Definition: APInt.h:70
llvm::APInt::getAllOnesValue
static APInt getAllOnesValue(unsigned numBits)
Get the all-ones value.
Definition: APInt.h:567
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:317
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:478
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:215
llvm::MIPatternMatch::m_any_of
Or< Preds... > m_any_of(Preds &&... preds)
Definition: MIPatternMatch.h:150
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:400
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
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:930
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:63
Legalizer.h
llvm::LegalizationArtifactCombiner
Definition: LegalizationArtifactCombiner.h:29
llvm::LegalizeActionStep::TypeIdx
unsigned TypeIdx
If describing an action, the type index to change. Otherwise zero.
Definition: LegalizerInfo.h:154
llvm::MIPatternMatch
Definition: MIPatternMatch.h:21
DefMI
MachineInstrBuilder MachineInstrBuilder & DefMI
Definition: AArch64ExpandPseudoInsts.cpp:101
llvm::MachineInstr::getNumOperands
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:481
llvm::LegalizationArtifactCombiner::tryCombineInstruction
bool tryCombineInstruction(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, GISelObserverWrapper &WrapperObserver)
Try to combine away MI.
Definition: LegalizationArtifactCombiner.h:794
llvm::LegalizeActions::Unsupported
@ Unsupported
This operation is completely unsupported on the target.
Definition: LegalizerInfo.h:89
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:1041
llvm::MIPatternMatch::m_all_of
And< Preds... > m_all_of(Preds &&... preds)
Definition: MIPatternMatch.h:146
llvm::MIPatternMatch::mi_match
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
Definition: MIPatternMatch.h:24
llvm::LLT::getElementType
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
Definition: LowLevelTypeImpl.h:188
llvm::LegalizeActions::Lower
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
Definition: LegalizerInfo.h:76
Debug.h
llvm::SrcOp
Definition: MachineIRBuilder.h:119
llvm::LegalizationArtifactCombiner::LegalizationArtifactCombiner
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI)
Definition: LegalizationArtifactCombiner.h:47
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
llvm::LLT
Definition: LowLevelTypeImpl.h:40