xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
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 
17 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
18 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
19 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
20 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
21 #include "llvm/CodeGen/GlobalISel/Utils.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/Support/Debug.h"
24 
25 #define DEBUG_TYPE "legalizer"
26 using namespace llvm::MIPatternMatch;
27 
28 namespace llvm {
29 class LegalizationArtifactCombiner {
30   MachineIRBuilder &Builder;
31   MachineRegisterInfo &MRI;
32   const LegalizerInfo &LI;
33 
isArtifactCast(unsigned Opc)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:
LegalizationArtifactCombiner(MachineIRBuilder & B,MachineRegisterInfo & MRI,const LegalizerInfo & LI)47   LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI,
48                     const LegalizerInfo &LI)
49       : Builder(B), MRI(MRI), LI(LI) {}
50 
tryCombineAnyExt(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)51   bool tryCombineAnyExt(MachineInstr &MI,
52                         SmallVectorImpl<MachineInstr *> &DeadInsts,
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 
tryCombineZExt(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelObserverWrapper & Observer)99   bool tryCombineZExt(MachineInstr &MI,
100                       SmallVectorImpl<MachineInstr *> &DeadInsts,
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 
tryCombineSExt(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)159   bool tryCombineSExt(MachineInstr &MI,
160                       SmallVectorImpl<MachineInstr *> &DeadInsts,
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 
tryCombineTrunc(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelObserverWrapper & Observer)215   bool tryCombineTrunc(MachineInstr &MI,
216                        SmallVectorImpl<MachineInstr *> &DeadInsts,
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).
tryFoldImplicitDef(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)317   bool tryFoldImplicitDef(MachineInstr &MI,
318                           SmallVectorImpl<MachineInstr *> &DeadInsts,
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 
tryFoldUnmergeCast(MachineInstr & MI,MachineInstr & CastMI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)353   bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI,
354                           SmallVectorImpl<MachineInstr *> &DeadInsts,
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 
canFoldMergeOpcode(unsigned MergeOp,unsigned ConvertOp,LLT OpTy,LLT DestTy)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.
replaceRegOrBuildCopy(Register DstReg,Register SrcReg,MachineRegisterInfo & MRI,MachineIRBuilder & Builder,SmallVectorImpl<Register> & UpdatedDefs,GISelChangeObserver & Observer)499   static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg,
500                                     MachineRegisterInfo &MRI,
501                                     MachineIRBuilder &Builder,
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     }
509     SmallVector<MachineInstr *, 4> UseMIs;
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
getDefIndex(const MachineInstr & MI,Register SearchDef)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 
tryCombineUnmergeValues(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelChangeObserver & Observer)535   bool tryCombineUnmergeValues(MachineInstr &MI,
536                                SmallVectorImpl<MachineInstr *> &DeadInsts,
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) {
566       case LegalizeActions::Lower:
567       case LegalizeActions::Unsupported:
568         break;
569       case LegalizeActions::FewerElements:
570       case LegalizeActions::NarrowScalar:
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) {
683         SmallVector<Register, 8> Regs;
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 
isMergeLikeOpcode(unsigned Opc)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 
tryCombineExtract(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)741   bool tryCombineExtract(MachineInstr &MI,
742                          SmallVectorImpl<MachineInstr *> &DeadInsts,
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.
tryCombineInstruction(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,GISelObserverWrapper & WrapperObserver)794   bool tryCombineInstruction(MachineInstr &MI,
795                              SmallVectorImpl<MachineInstr *> &DeadInsts,
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:
getArtifactSrcReg(const MachineInstr & MI)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.
deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr * > & DeadInsts,GISelObserverWrapper & WrapperObserver)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.
isInstUnsupported(const LegalityQuery & Query)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 
isInstLegal(const LegalityQuery & Query)998   bool isInstLegal(const LegalityQuery &Query) const {
999     return LI.getAction(Query).Action == LegalizeActions::Legal;
1000   }
1001 
isConstantUnsupported(LLT Ty)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.
lookThroughCopyInstrs(Register Reg)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
1028