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/ADT/SmallBitVector.h"
18 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
19 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
20 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
21 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
22 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
23 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
24 #include "llvm/CodeGen/GlobalISel/Utils.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/CodeGen/Register.h"
27 #include "llvm/CodeGen/TargetOpcodes.h"
28 #include "llvm/IR/Constants.h"
29 #include "llvm/Support/Debug.h"
30 
31 #define DEBUG_TYPE "legalizer"
32 
33 namespace llvm {
34 class LegalizationArtifactCombiner {
35   MachineIRBuilder &Builder;
36   MachineRegisterInfo &MRI;
37   const LegalizerInfo &LI;
38   GISelKnownBits *KB;
39 
isArtifactCast(unsigned Opc)40   static bool isArtifactCast(unsigned Opc) {
41     switch (Opc) {
42     case TargetOpcode::G_TRUNC:
43     case TargetOpcode::G_SEXT:
44     case TargetOpcode::G_ZEXT:
45     case TargetOpcode::G_ANYEXT:
46       return true;
47     default:
48       return false;
49     }
50   }
51 
52 public:
53   LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI,
54                                const LegalizerInfo &LI,
55                                GISelKnownBits *KB = nullptr)
Builder(B)56       : Builder(B), MRI(MRI), LI(LI), KB(KB) {}
57 
tryCombineAnyExt(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelObserverWrapper & Observer)58   bool tryCombineAnyExt(MachineInstr &MI,
59                         SmallVectorImpl<MachineInstr *> &DeadInsts,
60                         SmallVectorImpl<Register> &UpdatedDefs,
61                         GISelObserverWrapper &Observer) {
62     using namespace llvm::MIPatternMatch;
63     assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);
64 
65     Builder.setInstrAndDebugLoc(MI);
66     Register DstReg = MI.getOperand(0).getReg();
67     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
68 
69     // aext(trunc x) - > aext/copy/trunc x
70     Register TruncSrc;
71     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
72       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
73       if (MRI.getType(DstReg) == MRI.getType(TruncSrc))
74         replaceRegOrBuildCopy(DstReg, TruncSrc, MRI, Builder, UpdatedDefs,
75                               Observer);
76       else
77         Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
78       UpdatedDefs.push_back(DstReg);
79       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
80       return true;
81     }
82 
83     // aext([asz]ext x) -> [asz]ext x
84     Register ExtSrc;
85     MachineInstr *ExtMI;
86     if (mi_match(SrcReg, MRI,
87                  m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
88                                                     m_GSExt(m_Reg(ExtSrc)),
89                                                     m_GZExt(m_Reg(ExtSrc)))))) {
90       Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
91       UpdatedDefs.push_back(DstReg);
92       markInstAndDefDead(MI, *ExtMI, DeadInsts);
93       return true;
94     }
95 
96     // Try to fold aext(g_constant) when the larger constant type is legal.
97     auto *SrcMI = MRI.getVRegDef(SrcReg);
98     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
99       const LLT DstTy = MRI.getType(DstReg);
100       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
101         auto &CstVal = SrcMI->getOperand(1);
102         Builder.buildConstant(
103             DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
104         UpdatedDefs.push_back(DstReg);
105         markInstAndDefDead(MI, *SrcMI, DeadInsts);
106         return true;
107       }
108     }
109     return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
110   }
111 
tryCombineZExt(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelObserverWrapper & Observer)112   bool tryCombineZExt(MachineInstr &MI,
113                       SmallVectorImpl<MachineInstr *> &DeadInsts,
114                       SmallVectorImpl<Register> &UpdatedDefs,
115                       GISelObserverWrapper &Observer) {
116     using namespace llvm::MIPatternMatch;
117     assert(MI.getOpcode() == TargetOpcode::G_ZEXT);
118 
119     Builder.setInstrAndDebugLoc(MI);
120     Register DstReg = MI.getOperand(0).getReg();
121     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
122 
123     // zext(trunc x) - > and (aext/copy/trunc x), mask
124     // zext(sext x) -> and (sext x), mask
125     Register TruncSrc;
126     Register SextSrc;
127     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc))) ||
128         mi_match(SrcReg, MRI, m_GSExt(m_Reg(SextSrc)))) {
129       LLT DstTy = MRI.getType(DstReg);
130       if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
131           isConstantUnsupported(DstTy))
132         return false;
133       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
134       LLT SrcTy = MRI.getType(SrcReg);
135       APInt MaskVal = APInt::getAllOnes(SrcTy.getScalarSizeInBits());
136       if (SextSrc && (DstTy != MRI.getType(SextSrc)))
137         SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
138       if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))
139         TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
140       APInt ExtMaskVal = MaskVal.zext(DstTy.getScalarSizeInBits());
141       Register AndSrc = SextSrc ? SextSrc : TruncSrc;
142       // Elide G_AND and mask constant if possible.
143       // The G_AND would also be removed by the post-legalize redundant_and
144       // combine, but in this very common case, eliding early and regardless of
145       // OptLevel results in significant compile-time and O0 code-size
146       // improvements. Inserting unnecessary instructions between boolean defs
147       // and uses hinders a lot of folding during ISel.
148       if (KB && (KB->getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
149         replaceRegOrBuildCopy(DstReg, AndSrc, MRI, Builder, UpdatedDefs,
150                               Observer);
151       } else {
152         auto Mask = Builder.buildConstant(DstTy, ExtMaskVal);
153         Builder.buildAnd(DstReg, AndSrc, Mask);
154       }
155       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
156       return true;
157     }
158 
159     // zext(zext x) -> (zext x)
160     Register ZextSrc;
161     if (mi_match(SrcReg, MRI, m_GZExt(m_Reg(ZextSrc)))) {
162       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
163       Observer.changingInstr(MI);
164       MI.getOperand(1).setReg(ZextSrc);
165       Observer.changedInstr(MI);
166       UpdatedDefs.push_back(DstReg);
167       markDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
168       return true;
169     }
170 
171     // Try to fold zext(g_constant) when the larger constant type is legal.
172     auto *SrcMI = MRI.getVRegDef(SrcReg);
173     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
174       const LLT DstTy = MRI.getType(DstReg);
175       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
176         auto &CstVal = SrcMI->getOperand(1);
177         Builder.buildConstant(
178             DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));
179         UpdatedDefs.push_back(DstReg);
180         markInstAndDefDead(MI, *SrcMI, DeadInsts);
181         return true;
182       }
183     }
184     return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
185   }
186 
tryCombineSExt(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)187   bool tryCombineSExt(MachineInstr &MI,
188                       SmallVectorImpl<MachineInstr *> &DeadInsts,
189                       SmallVectorImpl<Register> &UpdatedDefs) {
190     using namespace llvm::MIPatternMatch;
191     assert(MI.getOpcode() == TargetOpcode::G_SEXT);
192 
193     Builder.setInstrAndDebugLoc(MI);
194     Register DstReg = MI.getOperand(0).getReg();
195     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
196 
197     // sext(trunc x) - > (sext_inreg (aext/copy/trunc x), c)
198     Register TruncSrc;
199     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
200       LLT DstTy = MRI.getType(DstReg);
201       if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))
202         return false;
203       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
204       LLT SrcTy = MRI.getType(SrcReg);
205       uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
206       if (DstTy != MRI.getType(TruncSrc))
207         TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
208       Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits);
209       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
210       return true;
211     }
212 
213     // sext(zext x) -> (zext x)
214     // sext(sext x) -> (sext x)
215     Register ExtSrc;
216     MachineInstr *ExtMI;
217     if (mi_match(SrcReg, MRI,
218                  m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)),
219                                                     m_GSExt(m_Reg(ExtSrc)))))) {
220       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
221       Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
222       UpdatedDefs.push_back(DstReg);
223       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
224       return true;
225     }
226 
227     // Try to fold sext(g_constant) when the larger constant type is legal.
228     auto *SrcMI = MRI.getVRegDef(SrcReg);
229     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
230       const LLT DstTy = MRI.getType(DstReg);
231       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
232         auto &CstVal = SrcMI->getOperand(1);
233         Builder.buildConstant(
234             DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
235         UpdatedDefs.push_back(DstReg);
236         markInstAndDefDead(MI, *SrcMI, DeadInsts);
237         return true;
238       }
239     }
240 
241     return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs);
242   }
243 
tryCombineTrunc(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelObserverWrapper & Observer)244   bool tryCombineTrunc(MachineInstr &MI,
245                        SmallVectorImpl<MachineInstr *> &DeadInsts,
246                        SmallVectorImpl<Register> &UpdatedDefs,
247                        GISelObserverWrapper &Observer) {
248     using namespace llvm::MIPatternMatch;
249     assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
250 
251     Builder.setInstr(MI);
252     Register DstReg = MI.getOperand(0).getReg();
253     const LLT DstTy = MRI.getType(DstReg);
254     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
255 
256     // Try to fold trunc(g_constant) when the smaller constant type is legal.
257     auto *SrcMI = MRI.getVRegDef(SrcReg);
258     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
259       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
260         auto &CstVal = SrcMI->getOperand(1);
261         Builder.buildConstant(
262             DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits()));
263         UpdatedDefs.push_back(DstReg);
264         markInstAndDefDead(MI, *SrcMI, DeadInsts);
265         return true;
266       }
267     }
268 
269     // Try to fold trunc(merge) to directly use the source of the merge.
270     // This gets rid of large, difficult to legalize, merges
271     if (auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
272       const Register MergeSrcReg = SrcMerge->getSourceReg(0);
273       const LLT MergeSrcTy = MRI.getType(MergeSrcReg);
274 
275       // We can only fold if the types are scalar
276       const unsigned DstSize = DstTy.getSizeInBits();
277       const unsigned MergeSrcSize = MergeSrcTy.getSizeInBits();
278       if (!DstTy.isScalar() || !MergeSrcTy.isScalar())
279         return false;
280 
281       if (DstSize < MergeSrcSize) {
282         // When the merge source is larger than the destination, we can just
283         // truncate the merge source directly
284         if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
285           return false;
286 
287         LLVM_DEBUG(dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
288                           << MI);
289 
290         Builder.buildTrunc(DstReg, MergeSrcReg);
291         UpdatedDefs.push_back(DstReg);
292       } else if (DstSize == MergeSrcSize) {
293         // If the sizes match we can simply try to replace the register
294         LLVM_DEBUG(
295             dbgs() << "Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
296                    << MI);
297         replaceRegOrBuildCopy(DstReg, MergeSrcReg, MRI, Builder, UpdatedDefs,
298                               Observer);
299       } else if (DstSize % MergeSrcSize == 0) {
300         // If the trunc size is a multiple of the merge source size we can use
301         // a smaller merge instead
302         if (isInstUnsupported(
303                 {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
304           return false;
305 
306         LLVM_DEBUG(
307             dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
308                    << MI);
309 
310         const unsigned NumSrcs = DstSize / MergeSrcSize;
311         assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
312                "trunc(merge) should require less inputs than merge");
313         SmallVector<Register, 8> SrcRegs(NumSrcs);
314         for (unsigned i = 0; i < NumSrcs; ++i)
315           SrcRegs[i] = SrcMerge->getSourceReg(i);
316 
317         Builder.buildMergeValues(DstReg, SrcRegs);
318         UpdatedDefs.push_back(DstReg);
319       } else {
320         // Unable to combine
321         return false;
322       }
323 
324       markInstAndDefDead(MI, *SrcMerge, DeadInsts);
325       return true;
326     }
327 
328     // trunc(trunc) -> trunc
329     Register TruncSrc;
330     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
331       // Always combine trunc(trunc) since the eventual resulting trunc must be
332       // legal anyway as it must be legal for all outputs of the consumer type
333       // set.
334       LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_TRUNC): " << MI);
335 
336       Builder.buildTrunc(DstReg, TruncSrc);
337       UpdatedDefs.push_back(DstReg);
338       markInstAndDefDead(MI, *MRI.getVRegDef(TruncSrc), DeadInsts);
339       return true;
340     }
341 
342     // trunc(ext x) -> x
343     ArtifactValueFinder Finder(MRI, Builder, LI);
344     if (Register FoundReg =
345             Finder.findValueFromDef(DstReg, 0, DstTy.getSizeInBits())) {
346       LLT FoundRegTy = MRI.getType(FoundReg);
347       if (DstTy == FoundRegTy) {
348         LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_[S,Z,ANY]EXT/G_TRUNC...): "
349                           << MI;);
350 
351         replaceRegOrBuildCopy(DstReg, FoundReg, MRI, Builder, UpdatedDefs,
352                               Observer);
353         UpdatedDefs.push_back(DstReg);
354         markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
355         return true;
356       }
357     }
358 
359     return false;
360   }
361 
362   /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
tryFoldImplicitDef(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)363   bool tryFoldImplicitDef(MachineInstr &MI,
364                           SmallVectorImpl<MachineInstr *> &DeadInsts,
365                           SmallVectorImpl<Register> &UpdatedDefs) {
366     unsigned Opcode = MI.getOpcode();
367     assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
368            Opcode == TargetOpcode::G_SEXT);
369 
370     if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
371                                            MI.getOperand(1).getReg(), MRI)) {
372       Builder.setInstr(MI);
373       Register DstReg = MI.getOperand(0).getReg();
374       LLT DstTy = MRI.getType(DstReg);
375 
376       if (Opcode == TargetOpcode::G_ANYEXT) {
377         // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF
378         if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
379           return false;
380         LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;);
381         Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
382         UpdatedDefs.push_back(DstReg);
383       } else {
384         // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
385         // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
386         if (isConstantUnsupported(DstTy))
387           return false;
388         LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;);
389         Builder.buildConstant(DstReg, 0);
390         UpdatedDefs.push_back(DstReg);
391       }
392 
393       markInstAndDefDead(MI, *DefMI, DeadInsts);
394       return true;
395     }
396     return false;
397   }
398 
tryFoldUnmergeCast(MachineInstr & MI,MachineInstr & CastMI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)399   bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI,
400                           SmallVectorImpl<MachineInstr *> &DeadInsts,
401                           SmallVectorImpl<Register> &UpdatedDefs) {
402 
403     assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
404 
405     const unsigned CastOpc = CastMI.getOpcode();
406 
407     if (!isArtifactCast(CastOpc))
408       return false;
409 
410     const unsigned NumDefs = MI.getNumOperands() - 1;
411 
412     const Register CastSrcReg = CastMI.getOperand(1).getReg();
413     const LLT CastSrcTy = MRI.getType(CastSrcReg);
414     const LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
415     const LLT SrcTy = MRI.getType(MI.getOperand(NumDefs).getReg());
416 
417     const unsigned CastSrcSize = CastSrcTy.getSizeInBits();
418     const unsigned DestSize = DestTy.getSizeInBits();
419 
420     if (CastOpc == TargetOpcode::G_TRUNC) {
421       if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.getScalarType()) {
422         //  %1:_(<4 x s8>) = G_TRUNC %0(<4 x s32>)
423         //  %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %1
424         // =>
425         //  %6:_(s32), %7:_(s32), %8:_(s32), %9:_(s32) = G_UNMERGE_VALUES %0
426         //  %2:_(s8) = G_TRUNC %6
427         //  %3:_(s8) = G_TRUNC %7
428         //  %4:_(s8) = G_TRUNC %8
429         //  %5:_(s8) = G_TRUNC %9
430 
431         unsigned UnmergeNumElts =
432             DestTy.isVector() ? CastSrcTy.getNumElements() / NumDefs : 1;
433         LLT UnmergeTy = CastSrcTy.changeElementCount(
434             ElementCount::getFixed(UnmergeNumElts));
435 
436         if (isInstUnsupported(
437                 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}))
438           return false;
439 
440         Builder.setInstr(MI);
441         auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg);
442 
443         for (unsigned I = 0; I != NumDefs; ++I) {
444           Register DefReg = MI.getOperand(I).getReg();
445           UpdatedDefs.push_back(DefReg);
446           Builder.buildTrunc(DefReg, NewUnmerge.getReg(I));
447         }
448 
449         markInstAndDefDead(MI, CastMI, DeadInsts);
450         return true;
451       }
452 
453       if (CastSrcTy.isScalar() && SrcTy.isScalar() && !DestTy.isVector()) {
454         //  %1:_(s16) = G_TRUNC %0(s32)
455         //  %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %1
456         // =>
457         //  %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %0
458 
459         // Unmerge(trunc) can be combined if the trunc source size is a multiple
460         // of the unmerge destination size
461         if (CastSrcSize % DestSize != 0)
462           return false;
463 
464         // Check if the new unmerge is supported
465         if (isInstUnsupported(
466                 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
467           return false;
468 
469         // Gather the original destination registers and create new ones for the
470         // unused bits
471         const unsigned NewNumDefs = CastSrcSize / DestSize;
472         SmallVector<Register, 8> DstRegs(NewNumDefs);
473         for (unsigned Idx = 0; Idx < NewNumDefs; ++Idx) {
474           if (Idx < NumDefs)
475             DstRegs[Idx] = MI.getOperand(Idx).getReg();
476           else
477             DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy);
478         }
479 
480         // Build new unmerge
481         Builder.setInstr(MI);
482         Builder.buildUnmerge(DstRegs, CastSrcReg);
483         UpdatedDefs.append(DstRegs.begin(), DstRegs.begin() + NewNumDefs);
484         markInstAndDefDead(MI, CastMI, DeadInsts);
485         return true;
486       }
487     }
488 
489     // TODO: support combines with other casts as well
490     return false;
491   }
492 
canFoldMergeOpcode(unsigned MergeOp,unsigned ConvertOp,LLT OpTy,LLT DestTy)493   static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp,
494                                  LLT OpTy, LLT DestTy) {
495     // Check if we found a definition that is like G_MERGE_VALUES.
496     switch (MergeOp) {
497     default:
498       return false;
499     case TargetOpcode::G_BUILD_VECTOR:
500     case TargetOpcode::G_MERGE_VALUES:
501       // The convert operation that we will need to insert is
502       // going to convert the input of that type of instruction (scalar)
503       // to the destination type (DestTy).
504       // The conversion needs to stay in the same domain (scalar to scalar
505       // and vector to vector), so if we were to allow to fold the merge
506       // we would need to insert some bitcasts.
507       // E.g.,
508       // <2 x s16> = build_vector s16, s16
509       // <2 x s32> = zext <2 x s16>
510       // <2 x s16>, <2 x s16> = unmerge <2 x s32>
511       //
512       // As is the folding would produce:
513       // <2 x s16> = zext s16  <-- scalar to vector
514       // <2 x s16> = zext s16  <-- scalar to vector
515       // Which is invalid.
516       // Instead we would want to generate:
517       // s32 = zext s16
518       // <2 x s16> = bitcast s32
519       // s32 = zext s16
520       // <2 x s16> = bitcast s32
521       //
522       // That is not done yet.
523       if (ConvertOp == 0)
524         return true;
525       return !DestTy.isVector() && OpTy.isVector() &&
526              DestTy == OpTy.getElementType();
527     case TargetOpcode::G_CONCAT_VECTORS: {
528       if (ConvertOp == 0)
529         return true;
530       if (!DestTy.isVector())
531         return false;
532 
533       const unsigned OpEltSize = OpTy.getElementType().getSizeInBits();
534 
535       // Don't handle scalarization with a cast that isn't in the same
536       // direction as the vector cast. This could be handled, but it would
537       // require more intermediate unmerges.
538       if (ConvertOp == TargetOpcode::G_TRUNC)
539         return DestTy.getSizeInBits() <= OpEltSize;
540       return DestTy.getSizeInBits() >= OpEltSize;
541     }
542     }
543   }
544 
545   /// Try to replace DstReg with SrcReg or build a COPY instruction
546   /// depending on the register constraints.
replaceRegOrBuildCopy(Register DstReg,Register SrcReg,MachineRegisterInfo & MRI,MachineIRBuilder & Builder,SmallVectorImpl<Register> & UpdatedDefs,GISelChangeObserver & Observer)547   static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg,
548                                     MachineRegisterInfo &MRI,
549                                     MachineIRBuilder &Builder,
550                                     SmallVectorImpl<Register> &UpdatedDefs,
551                                     GISelChangeObserver &Observer) {
552     if (!llvm::canReplaceReg(DstReg, SrcReg, MRI)) {
553       Builder.buildCopy(DstReg, SrcReg);
554       UpdatedDefs.push_back(DstReg);
555       return;
556     }
557     SmallVector<MachineInstr *, 4> UseMIs;
558     // Get the users and notify the observer before replacing.
559     for (auto &UseMI : MRI.use_instructions(DstReg)) {
560       UseMIs.push_back(&UseMI);
561       Observer.changingInstr(UseMI);
562     }
563     // Replace the registers.
564     MRI.replaceRegWith(DstReg, SrcReg);
565     UpdatedDefs.push_back(SrcReg);
566     // Notify the observer that we changed the instructions.
567     for (auto *UseMI : UseMIs)
568       Observer.changedInstr(*UseMI);
569   }
570 
571   /// Return the operand index in \p MI that defines \p Def
getDefIndex(const MachineInstr & MI,Register SearchDef)572   static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef) {
573     unsigned DefIdx = 0;
574     for (const MachineOperand &Def : MI.defs()) {
575       if (Def.getReg() == SearchDef)
576         break;
577       ++DefIdx;
578     }
579 
580     return DefIdx;
581   }
582 
583   /// This class provides utilities for finding source registers of specific
584   /// bit ranges in an artifact. The routines can look through the source
585   /// registers if they're other artifacts to try to find a non-artifact source
586   /// of a value.
587   class ArtifactValueFinder {
588     MachineRegisterInfo &MRI;
589     MachineIRBuilder &MIB;
590     const LegalizerInfo &LI;
591 
592     // Stores the best register found in the current query so far.
593     Register CurrentBest = Register();
594 
595     /// Given an concat_vector op \p Concat and a start bit and size, try to
596     /// find the origin of the value defined by that start position and size.
597     ///
598     /// \returns a register with the requested size, or the current best
599     /// register found during the current query.
findValueFromConcat(GConcatVectors & Concat,unsigned StartBit,unsigned Size)600     Register findValueFromConcat(GConcatVectors &Concat, unsigned StartBit,
601                                  unsigned Size) {
602       assert(Size > 0);
603 
604       // Find the source operand that provides the bits requested.
605       Register Src1Reg = Concat.getSourceReg(0);
606       unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
607 
608       // Operand index of the source that provides the start of the bit range.
609       unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
610       // Offset into the source at which the bit range starts.
611       unsigned InRegOffset = StartBit % SrcSize;
612       // Check that the bits don't span multiple sources.
613       // FIXME: we might be able return multiple sources? Or create an
614       // appropriate concat to make it fit.
615       if (InRegOffset + Size > SrcSize)
616         return CurrentBest;
617 
618       Register SrcReg = Concat.getReg(StartSrcIdx);
619       if (InRegOffset == 0 && Size == SrcSize) {
620         CurrentBest = SrcReg;
621         return findValueFromDefImpl(SrcReg, 0, Size);
622       }
623 
624       return findValueFromDefImpl(SrcReg, InRegOffset, Size);
625     }
626 
627     /// Given an build_vector op \p BV and a start bit and size, try to find
628     /// the origin of the value defined by that start position and size.
629     ///
630     /// \returns a register with the requested size, or the current best
631     /// register found during the current query.
findValueFromBuildVector(GBuildVector & BV,unsigned StartBit,unsigned Size)632     Register findValueFromBuildVector(GBuildVector &BV, unsigned StartBit,
633                                       unsigned Size) {
634       assert(Size > 0);
635 
636       // Find the source operand that provides the bits requested.
637       Register Src1Reg = BV.getSourceReg(0);
638       unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
639 
640       // Operand index of the source that provides the start of the bit range.
641       unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
642       // Offset into the source at which the bit range starts.
643       unsigned InRegOffset = StartBit % SrcSize;
644 
645       if (InRegOffset != 0)
646         return CurrentBest; // Give up, bits don't start at a scalar source.
647       if (Size < SrcSize)
648         return CurrentBest; // Scalar source is too large for requested bits.
649 
650       // If the bits cover multiple sources evenly, then create a new
651       // build_vector to synthesize the required size, if that's been requested.
652       if (Size > SrcSize) {
653         if (Size % SrcSize > 0)
654           return CurrentBest; // Isn't covered exactly by sources.
655 
656         unsigned NumSrcsUsed = Size / SrcSize;
657         // If we're requesting all of the sources, just return this def.
658         if (NumSrcsUsed == BV.getNumSources())
659           return BV.getReg(0);
660 
661         LLT SrcTy = MRI.getType(Src1Reg);
662         LLT NewBVTy = LLT::fixed_vector(NumSrcsUsed, SrcTy);
663 
664         // Check if the resulting build vector would be legal.
665         LegalizeActionStep ActionStep =
666             LI.getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
667         if (ActionStep.Action != LegalizeActions::Legal)
668           return CurrentBest;
669 
670         SmallVector<Register> NewSrcs;
671         for (unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
672              ++SrcIdx)
673           NewSrcs.push_back(BV.getReg(SrcIdx));
674         MIB.setInstrAndDebugLoc(BV);
675         return MIB.buildBuildVector(NewBVTy, NewSrcs).getReg(0);
676       }
677       // A single source is requested, just return it.
678       return BV.getReg(StartSrcIdx);
679     }
680 
681     /// Given an G_INSERT op \p MI and a start bit and size, try to find
682     /// the origin of the value defined by that start position and size.
683     ///
684     /// \returns a register with the requested size, or the current best
685     /// register found during the current query.
findValueFromInsert(MachineInstr & MI,unsigned StartBit,unsigned Size)686     Register findValueFromInsert(MachineInstr &MI, unsigned StartBit,
687                                  unsigned Size) {
688       assert(MI.getOpcode() == TargetOpcode::G_INSERT);
689       assert(Size > 0);
690 
691       Register ContainerSrcReg = MI.getOperand(1).getReg();
692       Register InsertedReg = MI.getOperand(2).getReg();
693       LLT InsertedRegTy = MRI.getType(InsertedReg);
694       unsigned InsertOffset = MI.getOperand(3).getImm();
695 
696       // There are 4 possible container/insertreg + requested bit-range layouts
697       // that the instruction and query could be representing.
698       // For: %_ = G_INSERT %CONTAINER, %INS, InsOff (abbrev. to 'IO')
699       // and a start bit 'SB', with size S, giving an end bit 'EB', we could
700       // have...
701       // Scenario A:
702       //   --------------------------
703       //  |  INS    |  CONTAINER     |
704       //   --------------------------
705       //       |   |
706       //       SB  EB
707       //
708       // Scenario B:
709       //   --------------------------
710       //  |  INS    |  CONTAINER     |
711       //   --------------------------
712       //                |    |
713       //                SB   EB
714       //
715       // Scenario C:
716       //   --------------------------
717       //  |  CONTAINER    |  INS     |
718       //   --------------------------
719       //       |    |
720       //       SB   EB
721       //
722       // Scenario D:
723       //   --------------------------
724       //  |  CONTAINER    |  INS     |
725       //   --------------------------
726       //                     |   |
727       //                     SB  EB
728       //
729       // So therefore, A and D are requesting data from the INS operand, while
730       // B and C are requesting from the container operand.
731 
732       unsigned InsertedEndBit = InsertOffset + InsertedRegTy.getSizeInBits();
733       unsigned EndBit = StartBit + Size;
734       unsigned NewStartBit;
735       Register SrcRegToUse;
736       if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
737         SrcRegToUse = ContainerSrcReg;
738         NewStartBit = StartBit;
739         return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size);
740       }
741       if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
742         SrcRegToUse = InsertedReg;
743         NewStartBit = StartBit - InsertOffset;
744         if (NewStartBit == 0 &&
745             Size == MRI.getType(SrcRegToUse).getSizeInBits())
746           CurrentBest = SrcRegToUse;
747         return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size);
748       }
749       // The bit range spans both the inserted and container regions.
750       return Register();
751     }
752 
753     /// Given an G_SEXT, G_ZEXT, G_ANYEXT op \p MI and a start bit and
754     /// size, try to find the origin of the value defined by that start
755     /// position and size.
756     ///
757     /// \returns a register with the requested size, or the current best
758     /// register found during the current query.
findValueFromExt(MachineInstr & MI,unsigned StartBit,unsigned Size)759     Register findValueFromExt(MachineInstr &MI, unsigned StartBit,
760                               unsigned Size) {
761       assert(MI.getOpcode() == TargetOpcode::G_SEXT ||
762              MI.getOpcode() == TargetOpcode::G_ZEXT ||
763              MI.getOpcode() == TargetOpcode::G_ANYEXT);
764       assert(Size > 0);
765 
766       Register SrcReg = MI.getOperand(1).getReg();
767       LLT SrcType = MRI.getType(SrcReg);
768       unsigned SrcSize = SrcType.getSizeInBits();
769 
770       // Currently we don't go into vectors.
771       if (!SrcType.isScalar())
772         return CurrentBest;
773 
774       if (StartBit + Size > SrcSize)
775         return CurrentBest;
776 
777       if (StartBit == 0 && SrcType.getSizeInBits() == Size)
778         CurrentBest = SrcReg;
779       return findValueFromDefImpl(SrcReg, StartBit, Size);
780     }
781 
782     /// Given an G_TRUNC op \p MI and a start bit and size, try to find
783     /// the origin of the value defined by that start position and size.
784     ///
785     /// \returns a register with the requested size, or the current best
786     /// register found during the current query.
findValueFromTrunc(MachineInstr & MI,unsigned StartBit,unsigned Size)787     Register findValueFromTrunc(MachineInstr &MI, unsigned StartBit,
788                                 unsigned Size) {
789       assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
790       assert(Size > 0);
791 
792       Register SrcReg = MI.getOperand(1).getReg();
793       LLT SrcType = MRI.getType(SrcReg);
794 
795       // Currently we don't go into vectors.
796       if (!SrcType.isScalar())
797         return CurrentBest;
798 
799       return findValueFromDefImpl(SrcReg, StartBit, Size);
800     }
801 
802     /// Internal implementation for findValueFromDef(). findValueFromDef()
803     /// initializes some data like the CurrentBest register, which this method
804     /// and its callees rely upon.
findValueFromDefImpl(Register DefReg,unsigned StartBit,unsigned Size)805     Register findValueFromDefImpl(Register DefReg, unsigned StartBit,
806                                   unsigned Size) {
807       std::optional<DefinitionAndSourceRegister> DefSrcReg =
808           getDefSrcRegIgnoringCopies(DefReg, MRI);
809       MachineInstr *Def = DefSrcReg->MI;
810       DefReg = DefSrcReg->Reg;
811       // If the instruction has a single def, then simply delegate the search.
812       // For unmerge however with multiple defs, we need to compute the offset
813       // into the source of the unmerge.
814       switch (Def->getOpcode()) {
815       case TargetOpcode::G_CONCAT_VECTORS:
816         return findValueFromConcat(cast<GConcatVectors>(*Def), StartBit, Size);
817       case TargetOpcode::G_UNMERGE_VALUES: {
818         unsigned DefStartBit = 0;
819         unsigned DefSize = MRI.getType(DefReg).getSizeInBits();
820         for (const auto &MO : Def->defs()) {
821           if (MO.getReg() == DefReg)
822             break;
823           DefStartBit += DefSize;
824         }
825         Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
826         Register SrcOriginReg =
827             findValueFromDefImpl(SrcReg, StartBit + DefStartBit, Size);
828         if (SrcOriginReg)
829           return SrcOriginReg;
830         // Failed to find a further value. If the StartBit and Size perfectly
831         // covered the requested DefReg, return that since it's better than
832         // nothing.
833         if (StartBit == 0 && Size == DefSize)
834           return DefReg;
835         return CurrentBest;
836       }
837       case TargetOpcode::G_BUILD_VECTOR:
838         return findValueFromBuildVector(cast<GBuildVector>(*Def), StartBit,
839                                         Size);
840       case TargetOpcode::G_INSERT:
841         return findValueFromInsert(*Def, StartBit, Size);
842       case TargetOpcode::G_TRUNC:
843         return findValueFromTrunc(*Def, StartBit, Size);
844       case TargetOpcode::G_SEXT:
845       case TargetOpcode::G_ZEXT:
846       case TargetOpcode::G_ANYEXT:
847         return findValueFromExt(*Def, StartBit, Size);
848       default:
849         return CurrentBest;
850       }
851     }
852 
853   public:
ArtifactValueFinder(MachineRegisterInfo & Mri,MachineIRBuilder & Builder,const LegalizerInfo & Info)854     ArtifactValueFinder(MachineRegisterInfo &Mri, MachineIRBuilder &Builder,
855                         const LegalizerInfo &Info)
856         : MRI(Mri), MIB(Builder), LI(Info) {}
857 
858     /// Try to find a source of the value defined in the def \p DefReg, starting
859     /// at position \p StartBit with size \p Size.
860     /// \returns a register with the requested size, or an empty Register if no
861     /// better value could be found.
findValueFromDef(Register DefReg,unsigned StartBit,unsigned Size)862     Register findValueFromDef(Register DefReg, unsigned StartBit,
863                               unsigned Size) {
864       CurrentBest = Register();
865       Register FoundReg = findValueFromDefImpl(DefReg, StartBit, Size);
866       return FoundReg != DefReg ? FoundReg : Register();
867     }
868 
869     /// Try to combine the defs of an unmerge \p MI by attempting to find
870     /// values that provides the bits for each def reg.
871     /// \returns true if all the defs of the unmerge have been made dead.
tryCombineUnmergeDefs(GUnmerge & MI,GISelChangeObserver & Observer,SmallVectorImpl<Register> & UpdatedDefs)872     bool tryCombineUnmergeDefs(GUnmerge &MI, GISelChangeObserver &Observer,
873                                SmallVectorImpl<Register> &UpdatedDefs) {
874       unsigned NumDefs = MI.getNumDefs();
875       LLT DestTy = MRI.getType(MI.getReg(0));
876 
877       SmallBitVector DeadDefs(NumDefs);
878       for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
879         Register DefReg = MI.getReg(DefIdx);
880         if (MRI.use_nodbg_empty(DefReg)) {
881           DeadDefs[DefIdx] = true;
882           continue;
883         }
884         Register FoundVal = findValueFromDef(DefReg, 0, DestTy.getSizeInBits());
885         if (!FoundVal)
886           continue;
887         if (MRI.getType(FoundVal) != DestTy)
888           continue;
889 
890         replaceRegOrBuildCopy(DefReg, FoundVal, MRI, MIB, UpdatedDefs,
891                               Observer);
892         // We only want to replace the uses, not the def of the old reg.
893         Observer.changingInstr(MI);
894         MI.getOperand(DefIdx).setReg(DefReg);
895         Observer.changedInstr(MI);
896         DeadDefs[DefIdx] = true;
897       }
898       return DeadDefs.all();
899     }
900 
findUnmergeThatDefinesReg(Register Reg,unsigned Size,unsigned & DefOperandIdx)901     GUnmerge *findUnmergeThatDefinesReg(Register Reg, unsigned Size,
902                                         unsigned &DefOperandIdx) {
903       if (Register Def = findValueFromDefImpl(Reg, 0, Size)) {
904         if (auto *Unmerge = dyn_cast<GUnmerge>(MRI.getVRegDef(Def))) {
905           DefOperandIdx = Unmerge->findRegisterDefOperandIdx(Def);
906           return Unmerge;
907         }
908       }
909       return nullptr;
910     }
911 
912     // Check if sequence of elements from merge-like instruction is defined by
913     // another sequence of elements defined by unmerge. Most often this is the
914     // same sequence. Search for elements using findValueFromDefImpl.
isSequenceFromUnmerge(GMergeLikeInstr & MI,unsigned MergeStartIdx,GUnmerge * Unmerge,unsigned UnmergeIdxStart,unsigned NumElts,unsigned EltSize,bool AllowUndef)915     bool isSequenceFromUnmerge(GMergeLikeInstr &MI, unsigned MergeStartIdx,
916                                GUnmerge *Unmerge, unsigned UnmergeIdxStart,
917                                unsigned NumElts, unsigned EltSize,
918                                bool AllowUndef) {
919       assert(MergeStartIdx + NumElts <= MI.getNumSources());
920       for (unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
921         unsigned EltUnmergeIdx;
922         GUnmerge *EltUnmerge = findUnmergeThatDefinesReg(
923             MI.getSourceReg(i), EltSize, EltUnmergeIdx);
924         // Check if source i comes from the same Unmerge.
925         if (EltUnmerge == Unmerge) {
926           // Check that source i's def has same index in sequence in Unmerge.
927           if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
928             return false;
929         } else if (!AllowUndef ||
930                    MRI.getVRegDef(MI.getSourceReg(i))->getOpcode() !=
931                        TargetOpcode::G_IMPLICIT_DEF)
932           return false;
933       }
934       return true;
935     }
936 
tryCombineMergeLike(GMergeLikeInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelChangeObserver & Observer)937     bool tryCombineMergeLike(GMergeLikeInstr &MI,
938                              SmallVectorImpl<MachineInstr *> &DeadInsts,
939                              SmallVectorImpl<Register> &UpdatedDefs,
940                              GISelChangeObserver &Observer) {
941       Register Elt0 = MI.getSourceReg(0);
942       LLT EltTy = MRI.getType(Elt0);
943       unsigned EltSize = EltTy.getSizeInBits();
944 
945       unsigned Elt0UnmergeIdx;
946       // Search for unmerge that will be candidate for combine.
947       auto *Unmerge = findUnmergeThatDefinesReg(Elt0, EltSize, Elt0UnmergeIdx);
948       if (!Unmerge)
949         return false;
950 
951       unsigned NumMIElts = MI.getNumSources();
952       Register Dst = MI.getReg(0);
953       LLT DstTy = MRI.getType(Dst);
954       Register UnmergeSrc = Unmerge->getSourceReg();
955       LLT UnmergeSrcTy = MRI.getType(UnmergeSrc);
956 
957       // Recognize copy of UnmergeSrc to Dst.
958       // Unmerge UnmergeSrc and reassemble it using merge-like opcode into Dst.
959       //
960       // %0:_(EltTy), %1, ... = G_UNMERGE_VALUES %UnmergeSrc:_(Ty)
961       // %Dst:_(Ty) = G_merge_like_opcode %0:_(EltTy), %1, ...
962       //
963       // %Dst:_(Ty) = COPY %UnmergeSrc:_(Ty)
964       if ((DstTy == UnmergeSrcTy) && (Elt0UnmergeIdx == 0)) {
965         if (!isSequenceFromUnmerge(MI, 0, Unmerge, 0, NumMIElts, EltSize,
966                                    /*AllowUndef=*/DstTy.isVector()))
967           return false;
968 
969         replaceRegOrBuildCopy(Dst, UnmergeSrc, MRI, MIB, UpdatedDefs, Observer);
970         DeadInsts.push_back(&MI);
971         return true;
972       }
973 
974       // Recognize UnmergeSrc that can be unmerged to DstTy directly.
975       // Types have to be either both vector or both non-vector types.
976       // Merge-like opcodes are combined one at the time. First one creates new
977       // unmerge, following should use the same unmerge (builder performs CSE).
978       //
979       // %0:_(EltTy), %1, %2, %3 = G_UNMERGE_VALUES %UnmergeSrc:_(UnmergeSrcTy)
980       // %Dst:_(DstTy) = G_merge_like_opcode %0:_(EltTy), %1
981       // %AnotherDst:_(DstTy) = G_merge_like_opcode %2:_(EltTy), %3
982       //
983       // %Dst:_(DstTy), %AnotherDst = G_UNMERGE_VALUES %UnmergeSrc
984       if ((DstTy.isVector() == UnmergeSrcTy.isVector()) &&
985           (Elt0UnmergeIdx % NumMIElts == 0) &&
986           getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
987         if (!isSequenceFromUnmerge(MI, 0, Unmerge, Elt0UnmergeIdx, NumMIElts,
988                                    EltSize, false))
989           return false;
990         MIB.setInstrAndDebugLoc(MI);
991         auto NewUnmerge = MIB.buildUnmerge(DstTy, Unmerge->getSourceReg());
992         unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.getSizeInBits();
993         replaceRegOrBuildCopy(Dst, NewUnmerge.getReg(DstIdx), MRI, MIB,
994                               UpdatedDefs, Observer);
995         DeadInsts.push_back(&MI);
996         return true;
997       }
998 
999       // Recognize when multiple unmerged sources with UnmergeSrcTy type
1000       // can be merged into Dst with DstTy type directly.
1001       // Types have to be either both vector or both non-vector types.
1002 
1003       // %0:_(EltTy), %1 = G_UNMERGE_VALUES %UnmergeSrc:_(UnmergeSrcTy)
1004       // %2:_(EltTy), %3 = G_UNMERGE_VALUES %AnotherUnmergeSrc:_(UnmergeSrcTy)
1005       // %Dst:_(DstTy) = G_merge_like_opcode %0:_(EltTy), %1, %2, %3
1006       //
1007       // %Dst:_(DstTy) = G_merge_like_opcode %UnmergeSrc, %AnotherUnmergeSrc
1008 
1009       if ((DstTy.isVector() == UnmergeSrcTy.isVector()) &&
1010           getCoverTy(DstTy, UnmergeSrcTy) == DstTy) {
1011         SmallVector<Register, 4> ConcatSources;
1012         unsigned NumElts = Unmerge->getNumDefs();
1013         for (unsigned i = 0; i < MI.getNumSources(); i += NumElts) {
1014           unsigned EltUnmergeIdx;
1015           auto *UnmergeI = findUnmergeThatDefinesReg(MI.getSourceReg(i),
1016                                                      EltSize, EltUnmergeIdx);
1017           // All unmerges have to be the same size.
1018           if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
1019               (EltUnmergeIdx != 0))
1020             return false;
1021           if (!isSequenceFromUnmerge(MI, i, UnmergeI, 0, NumElts, EltSize,
1022                                      false))
1023             return false;
1024           ConcatSources.push_back(UnmergeI->getSourceReg());
1025         }
1026 
1027         MIB.setInstrAndDebugLoc(MI);
1028         MIB.buildMergeLikeInstr(Dst, ConcatSources);
1029         DeadInsts.push_back(&MI);
1030         return true;
1031       }
1032 
1033       return false;
1034     }
1035   };
1036 
tryCombineUnmergeValues(GUnmerge & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs,GISelChangeObserver & Observer)1037   bool tryCombineUnmergeValues(GUnmerge &MI,
1038                                SmallVectorImpl<MachineInstr *> &DeadInsts,
1039                                SmallVectorImpl<Register> &UpdatedDefs,
1040                                GISelChangeObserver &Observer) {
1041     unsigned NumDefs = MI.getNumDefs();
1042     Register SrcReg = MI.getSourceReg();
1043     MachineInstr *SrcDef = getDefIgnoringCopies(SrcReg, MRI);
1044     if (!SrcDef)
1045       return false;
1046 
1047     LLT OpTy = MRI.getType(SrcReg);
1048     LLT DestTy = MRI.getType(MI.getReg(0));
1049     unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg);
1050 
1051     Builder.setInstrAndDebugLoc(MI);
1052 
1053     ArtifactValueFinder Finder(MRI, Builder, LI);
1054     if (Finder.tryCombineUnmergeDefs(MI, Observer, UpdatedDefs)) {
1055       markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);
1056       return true;
1057     }
1058 
1059     if (auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
1060       // %0:_(<4 x s16>) = G_FOO
1061       // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0
1062       // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1
1063       //
1064       // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0
1065       Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
1066       LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);
1067 
1068       // If we need to decrease the number of vector elements in the result type
1069       // of an unmerge, this would involve the creation of an equivalent unmerge
1070       // to copy back to the original result registers.
1071       LegalizeActionStep ActionStep = LI.getAction(
1072           {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
1073       switch (ActionStep.Action) {
1074       case LegalizeActions::Lower:
1075       case LegalizeActions::Unsupported:
1076         break;
1077       case LegalizeActions::FewerElements:
1078       case LegalizeActions::NarrowScalar:
1079         if (ActionStep.TypeIdx == 1)
1080           return false;
1081         break;
1082       default:
1083         return false;
1084       }
1085 
1086       auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
1087 
1088       // TODO: Should we try to process out the other defs now? If the other
1089       // defs of the source unmerge are also unmerged, we end up with a separate
1090       // unmerge for each one.
1091       for (unsigned I = 0; I != NumDefs; ++I) {
1092         Register Def = MI.getReg(I);
1093         replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I),
1094                               MRI, Builder, UpdatedDefs, Observer);
1095       }
1096 
1097       markInstAndDefDead(MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1098       return true;
1099     }
1100 
1101     MachineInstr *MergeI = SrcDef;
1102     unsigned ConvertOp = 0;
1103 
1104     // Handle intermediate conversions
1105     unsigned SrcOp = SrcDef->getOpcode();
1106     if (isArtifactCast(SrcOp)) {
1107       ConvertOp = SrcOp;
1108       MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI);
1109     }
1110 
1111     if (!MergeI || !canFoldMergeOpcode(MergeI->getOpcode(),
1112                                        ConvertOp, OpTy, DestTy)) {
1113       // We might have a chance to combine later by trying to combine
1114       // unmerge(cast) first
1115       return tryFoldUnmergeCast(MI, *SrcDef, DeadInsts, UpdatedDefs);
1116     }
1117 
1118     const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
1119 
1120     if (NumMergeRegs < NumDefs) {
1121       if (NumDefs % NumMergeRegs != 0)
1122         return false;
1123 
1124       Builder.setInstr(MI);
1125       // Transform to UNMERGEs, for example
1126       //   %1 = G_MERGE_VALUES %4, %5
1127       //   %9, %10, %11, %12 = G_UNMERGE_VALUES %1
1128       // to
1129       //   %9, %10 = G_UNMERGE_VALUES %4
1130       //   %11, %12 = G_UNMERGE_VALUES %5
1131 
1132       const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1133       for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
1134         SmallVector<Register, 8> DstRegs;
1135         for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
1136              ++j, ++DefIdx)
1137           DstRegs.push_back(MI.getReg(DefIdx));
1138 
1139         if (ConvertOp) {
1140           LLT MergeDstTy = MRI.getType(SrcDef->getOperand(0).getReg());
1141 
1142           // This is a vector that is being split and casted. Extract to the
1143           // element type, and do the conversion on the scalars (or smaller
1144           // vectors).
1145           LLT MergeEltTy = MergeDstTy.divide(NumMergeRegs);
1146 
1147           // Handle split to smaller vectors, with conversions.
1148           // %2(<8 x s8>) = G_CONCAT_VECTORS %0(<4 x s8>), %1(<4 x s8>)
1149           // %3(<8 x s16>) = G_SEXT %2
1150           // %4(<2 x s16>), %5(<2 x s16>), %6(<2 x s16>), %7(<2 x s16>) =
1151           // G_UNMERGE_VALUES %3
1152           //
1153           // =>
1154           //
1155           // %8(<4 x s16>) = G_SEXT %0
1156           // %9(<4 x s16>) = G_SEXT %1
1157           // %4(<2 x s16>), %5(<2 x s16>) = G_UNMERGE_VALUES %8
1158           // %7(<2 x s16>), %7(<2 x s16>) = G_UNMERGE_VALUES %9
1159 
1160           Register TmpReg = MRI.createGenericVirtualRegister(MergeEltTy);
1161           Builder.buildInstr(ConvertOp, {TmpReg},
1162                              {MergeI->getOperand(Idx + 1).getReg()});
1163           Builder.buildUnmerge(DstRegs, TmpReg);
1164         } else {
1165           Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
1166         }
1167         UpdatedDefs.append(DstRegs.begin(), DstRegs.end());
1168       }
1169 
1170     } else if (NumMergeRegs > NumDefs) {
1171       if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1172         return false;
1173 
1174       Builder.setInstr(MI);
1175       // Transform to MERGEs
1176       //   %6 = G_MERGE_VALUES %17, %18, %19, %20
1177       //   %7, %8 = G_UNMERGE_VALUES %6
1178       // to
1179       //   %7 = G_MERGE_VALUES %17, %18
1180       //   %8 = G_MERGE_VALUES %19, %20
1181 
1182       const unsigned NumRegs = NumMergeRegs / NumDefs;
1183       for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1184         SmallVector<Register, 8> Regs;
1185         for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
1186              ++j, ++Idx)
1187           Regs.push_back(MergeI->getOperand(Idx).getReg());
1188 
1189         Register DefReg = MI.getReg(DefIdx);
1190         Builder.buildMergeLikeInstr(DefReg, Regs);
1191         UpdatedDefs.push_back(DefReg);
1192       }
1193 
1194     } else {
1195       LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
1196 
1197       if (!ConvertOp && DestTy != MergeSrcTy)
1198         ConvertOp = TargetOpcode::G_BITCAST;
1199 
1200       if (ConvertOp) {
1201         Builder.setInstr(MI);
1202 
1203         for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1204           Register DefReg = MI.getOperand(Idx).getReg();
1205           Register MergeSrc = MergeI->getOperand(Idx + 1).getReg();
1206 
1207           if (!MRI.use_empty(DefReg)) {
1208             Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1209             UpdatedDefs.push_back(DefReg);
1210           }
1211         }
1212 
1213         markInstAndDefDead(MI, *MergeI, DeadInsts);
1214         return true;
1215       }
1216 
1217       assert(DestTy == MergeSrcTy &&
1218              "Bitcast and the other kinds of conversions should "
1219              "have happened earlier");
1220 
1221       Builder.setInstr(MI);
1222       for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1223         Register DstReg = MI.getOperand(Idx).getReg();
1224         Register SrcReg = MergeI->getOperand(Idx + 1).getReg();
1225         replaceRegOrBuildCopy(DstReg, SrcReg, MRI, Builder, UpdatedDefs,
1226                               Observer);
1227       }
1228     }
1229 
1230     markInstAndDefDead(MI, *MergeI, DeadInsts);
1231     return true;
1232   }
1233 
tryCombineExtract(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,SmallVectorImpl<Register> & UpdatedDefs)1234   bool tryCombineExtract(MachineInstr &MI,
1235                          SmallVectorImpl<MachineInstr *> &DeadInsts,
1236                          SmallVectorImpl<Register> &UpdatedDefs) {
1237     assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
1238 
1239     // Try to use the source registers from a G_MERGE_VALUES
1240     //
1241     // %2 = G_MERGE_VALUES %0, %1
1242     // %3 = G_EXTRACT %2, N
1243     // =>
1244     //
1245     // for N < %2.getSizeInBits() / 2
1246     //     %3 = G_EXTRACT %0, N
1247     //
1248     // for N >= %2.getSizeInBits() / 2
1249     //    %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
1250 
1251     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
1252     MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
1253     if (!MergeI || !isa<GMergeLikeInstr>(MergeI))
1254       return false;
1255 
1256     Register DstReg = MI.getOperand(0).getReg();
1257     LLT DstTy = MRI.getType(DstReg);
1258     LLT SrcTy = MRI.getType(SrcReg);
1259 
1260     // TODO: Do we need to check if the resulting extract is supported?
1261     unsigned ExtractDstSize = DstTy.getSizeInBits();
1262     unsigned Offset = MI.getOperand(2).getImm();
1263     unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
1264     unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
1265     unsigned MergeSrcIdx = Offset / MergeSrcSize;
1266 
1267     // Compute the offset of the last bit the extract needs.
1268     unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
1269 
1270     // Can't handle the case where the extract spans multiple inputs.
1271     if (MergeSrcIdx != EndMergeSrcIdx)
1272       return false;
1273 
1274     // TODO: We could modify MI in place in most cases.
1275     Builder.setInstr(MI);
1276     Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(),
1277                          Offset - MergeSrcIdx * MergeSrcSize);
1278     UpdatedDefs.push_back(DstReg);
1279     markInstAndDefDead(MI, *MergeI, DeadInsts);
1280     return true;
1281   }
1282 
1283   /// Try to combine away MI.
1284   /// Returns true if it combined away the MI.
1285   /// Adds instructions that are dead as a result of the combine
1286   /// into DeadInsts, which can include MI.
tryCombineInstruction(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & DeadInsts,GISelObserverWrapper & WrapperObserver)1287   bool tryCombineInstruction(MachineInstr &MI,
1288                              SmallVectorImpl<MachineInstr *> &DeadInsts,
1289                              GISelObserverWrapper &WrapperObserver) {
1290     ArtifactValueFinder Finder(MRI, Builder, LI);
1291 
1292     // This might be a recursive call, and we might have DeadInsts already
1293     // populated. To avoid bad things happening later with multiple vreg defs
1294     // etc, process the dead instructions now if any.
1295     if (!DeadInsts.empty())
1296       deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1297 
1298     // Put here every vreg that was redefined in such a way that it's at least
1299     // possible that one (or more) of its users (immediate or COPY-separated)
1300     // could become artifact combinable with the new definition (or the
1301     // instruction reachable from it through a chain of copies if any).
1302     SmallVector<Register, 4> UpdatedDefs;
1303     bool Changed = false;
1304     switch (MI.getOpcode()) {
1305     default:
1306       return false;
1307     case TargetOpcode::G_ANYEXT:
1308       Changed = tryCombineAnyExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1309       break;
1310     case TargetOpcode::G_ZEXT:
1311       Changed = tryCombineZExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1312       break;
1313     case TargetOpcode::G_SEXT:
1314       Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs);
1315       break;
1316     case TargetOpcode::G_UNMERGE_VALUES:
1317       Changed = tryCombineUnmergeValues(cast<GUnmerge>(MI), DeadInsts,
1318                                         UpdatedDefs, WrapperObserver);
1319       break;
1320     case TargetOpcode::G_MERGE_VALUES:
1321     case TargetOpcode::G_BUILD_VECTOR:
1322     case TargetOpcode::G_CONCAT_VECTORS:
1323       // If any of the users of this merge are an unmerge, then add them to the
1324       // artifact worklist in case there's folding that can be done looking up.
1325       for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) {
1326         if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1327             U.getOpcode() == TargetOpcode::G_TRUNC) {
1328           UpdatedDefs.push_back(MI.getOperand(0).getReg());
1329           break;
1330         }
1331       }
1332       Changed = Finder.tryCombineMergeLike(cast<GMergeLikeInstr>(MI), DeadInsts,
1333                                            UpdatedDefs, WrapperObserver);
1334       break;
1335     case TargetOpcode::G_EXTRACT:
1336       Changed = tryCombineExtract(MI, DeadInsts, UpdatedDefs);
1337       break;
1338     case TargetOpcode::G_TRUNC:
1339       Changed = tryCombineTrunc(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1340       if (!Changed) {
1341         // Try to combine truncates away even if they are legal. As all artifact
1342         // combines at the moment look only "up" the def-use chains, we achieve
1343         // that by throwing truncates' users (with look through copies) into the
1344         // ArtifactList again.
1345         UpdatedDefs.push_back(MI.getOperand(0).getReg());
1346       }
1347       break;
1348     }
1349     // If the main loop through the ArtifactList found at least one combinable
1350     // pair of artifacts, not only combine it away (as done above), but also
1351     // follow the def-use chain from there to combine everything that can be
1352     // combined within this def-use chain of artifacts.
1353     while (!UpdatedDefs.empty()) {
1354       Register NewDef = UpdatedDefs.pop_back_val();
1355       assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg");
1356       for (MachineInstr &Use : MRI.use_instructions(NewDef)) {
1357         switch (Use.getOpcode()) {
1358         // Keep this list in sync with the list of all artifact combines.
1359         case TargetOpcode::G_ANYEXT:
1360         case TargetOpcode::G_ZEXT:
1361         case TargetOpcode::G_SEXT:
1362         case TargetOpcode::G_UNMERGE_VALUES:
1363         case TargetOpcode::G_EXTRACT:
1364         case TargetOpcode::G_TRUNC:
1365         case TargetOpcode::G_BUILD_VECTOR:
1366           // Adding Use to ArtifactList.
1367           WrapperObserver.changedInstr(Use);
1368           break;
1369         case TargetOpcode::G_ASSERT_SEXT:
1370         case TargetOpcode::G_ASSERT_ZEXT:
1371         case TargetOpcode::G_ASSERT_ALIGN:
1372         case TargetOpcode::COPY: {
1373           Register Copy = Use.getOperand(0).getReg();
1374           if (Copy.isVirtual())
1375             UpdatedDefs.push_back(Copy);
1376           break;
1377         }
1378         default:
1379           // If we do not have an artifact combine for the opcode, there is no
1380           // point in adding it to the ArtifactList as nothing interesting will
1381           // be done to it anyway.
1382           break;
1383         }
1384       }
1385     }
1386     return Changed;
1387   }
1388 
1389 private:
getArtifactSrcReg(const MachineInstr & MI)1390   static Register getArtifactSrcReg(const MachineInstr &MI) {
1391     switch (MI.getOpcode()) {
1392     case TargetOpcode::COPY:
1393     case TargetOpcode::G_TRUNC:
1394     case TargetOpcode::G_ZEXT:
1395     case TargetOpcode::G_ANYEXT:
1396     case TargetOpcode::G_SEXT:
1397     case TargetOpcode::G_EXTRACT:
1398     case TargetOpcode::G_ASSERT_SEXT:
1399     case TargetOpcode::G_ASSERT_ZEXT:
1400     case TargetOpcode::G_ASSERT_ALIGN:
1401       return MI.getOperand(1).getReg();
1402     case TargetOpcode::G_UNMERGE_VALUES:
1403       return MI.getOperand(MI.getNumOperands() - 1).getReg();
1404     default:
1405       llvm_unreachable("Not a legalization artifact happen");
1406     }
1407   }
1408 
1409   /// Mark a def of one of MI's original operands, DefMI, as dead if changing MI
1410   /// (either by killing it or changing operands) results in DefMI being dead
1411   /// too. In-between COPYs or artifact-casts are also collected if they are
1412   /// dead.
1413   /// MI is not marked dead.
1414   void markDefDead(MachineInstr &MI, MachineInstr &DefMI,
1415                    SmallVectorImpl<MachineInstr *> &DeadInsts,
1416                    unsigned DefIdx = 0) {
1417     // Collect all the copy instructions that are made dead, due to deleting
1418     // this instruction. Collect all of them until the Trunc(DefMI).
1419     // Eg,
1420     // %1(s1) = G_TRUNC %0(s32)
1421     // %2(s1) = COPY %1(s1)
1422     // %3(s1) = COPY %2(s1)
1423     // %4(s32) = G_ANYEXT %3(s1)
1424     // In this case, we would have replaced %4 with a copy of %0,
1425     // and as a result, %3, %2, %1 are dead.
1426     MachineInstr *PrevMI = &MI;
1427     while (PrevMI != &DefMI) {
1428       Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1429 
1430       MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
1431       if (MRI.hasOneUse(PrevRegSrc)) {
1432         if (TmpDef != &DefMI) {
1433           assert((TmpDef->getOpcode() == TargetOpcode::COPY ||
1434                   isArtifactCast(TmpDef->getOpcode()) ||
1435                   isPreISelGenericOptimizationHint(TmpDef->getOpcode())) &&
1436                  "Expecting copy or artifact cast here");
1437 
1438           DeadInsts.push_back(TmpDef);
1439         }
1440       } else
1441         break;
1442       PrevMI = TmpDef;
1443     }
1444 
1445     if (PrevMI == &DefMI) {
1446       unsigned I = 0;
1447       bool IsDead = true;
1448       for (MachineOperand &Def : DefMI.defs()) {
1449         if (I != DefIdx) {
1450           if (!MRI.use_empty(Def.getReg())) {
1451             IsDead = false;
1452             break;
1453           }
1454         } else {
1455           if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg()))
1456             break;
1457         }
1458 
1459         ++I;
1460       }
1461 
1462       if (IsDead)
1463         DeadInsts.push_back(&DefMI);
1464     }
1465   }
1466 
1467   /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
1468   /// dead due to MI being killed, then mark DefMI as dead too.
1469   /// Some of the combines (extends(trunc)), try to walk through redundant
1470   /// copies in between the extends and the truncs, and this attempts to collect
1471   /// the in between copies if they're dead.
1472   void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
1473                           SmallVectorImpl<MachineInstr *> &DeadInsts,
1474                           unsigned DefIdx = 0) {
1475     DeadInsts.push_back(&MI);
1476     markDefDead(MI, DefMI, DeadInsts, DefIdx);
1477   }
1478 
1479   /// Erase the dead instructions in the list and call the observer hooks.
1480   /// Normally the Legalizer will deal with erasing instructions that have been
1481   /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to
1482   /// process instructions which have been marked dead, but otherwise break the
1483   /// MIR by introducing multiple vreg defs. For those cases, allow the combines
1484   /// to explicitly delete the instructions before we run into trouble.
deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr * > & DeadInsts,GISelObserverWrapper & WrapperObserver)1485   void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts,
1486                              GISelObserverWrapper &WrapperObserver) {
1487     for (auto *DeadMI : DeadInsts) {
1488       LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");
1489       WrapperObserver.erasingInstr(*DeadMI);
1490       DeadMI->eraseFromParent();
1491     }
1492     DeadInsts.clear();
1493   }
1494 
1495   /// Checks if the target legalizer info has specified anything about the
1496   /// instruction, or if unsupported.
isInstUnsupported(const LegalityQuery & Query)1497   bool isInstUnsupported(const LegalityQuery &Query) const {
1498     using namespace LegalizeActions;
1499     auto Step = LI.getAction(Query);
1500     return Step.Action == Unsupported || Step.Action == NotFound;
1501   }
1502 
isInstLegal(const LegalityQuery & Query)1503   bool isInstLegal(const LegalityQuery &Query) const {
1504     return LI.getAction(Query).Action == LegalizeActions::Legal;
1505   }
1506 
isConstantUnsupported(LLT Ty)1507   bool isConstantUnsupported(LLT Ty) const {
1508     if (!Ty.isVector())
1509       return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1510 
1511     LLT EltTy = Ty.getElementType();
1512     return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1513            isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
1514   }
1515 
1516   /// Looks through copy instructions and returns the actual
1517   /// source register.
lookThroughCopyInstrs(Register Reg)1518   Register lookThroughCopyInstrs(Register Reg) {
1519     Register TmpReg = getSrcRegIgnoringCopies(Reg, MRI);
1520     return TmpReg.isValid() ? TmpReg : Reg;
1521   }
1522 };
1523 
1524 } // namespace llvm
1525 
1526 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
1527