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