Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:24

0001 //===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- C++ -*-//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 // This file contains some helper functions which try to cleanup artifacts
0009 // such as G_TRUNCs/G_[ZSA]EXTENDS that were created during legalization to make
0010 // the types match. This file also contains some combines of merges that happens
0011 // at the end of the legalization.
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
0015 #define LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
0016 
0017 #include "llvm/ADT/SmallBitVector.h"
0018 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
0019 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
0020 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
0021 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
0022 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
0023 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
0024 #include "llvm/CodeGen/GlobalISel/Utils.h"
0025 #include "llvm/CodeGen/MachineRegisterInfo.h"
0026 #include "llvm/CodeGen/Register.h"
0027 #include "llvm/CodeGen/TargetOpcodes.h"
0028 #include "llvm/IR/Constants.h"
0029 #include "llvm/IR/DebugInfoMetadata.h"
0030 #include "llvm/Support/Debug.h"
0031 
0032 #define DEBUG_TYPE "legalizer"
0033 
0034 namespace llvm {
0035 class LegalizationArtifactCombiner {
0036   MachineIRBuilder &Builder;
0037   MachineRegisterInfo &MRI;
0038   const LegalizerInfo &LI;
0039   GISelKnownBits *KB;
0040 
0041   static bool isArtifactCast(unsigned Opc) {
0042     switch (Opc) {
0043     case TargetOpcode::G_TRUNC:
0044     case TargetOpcode::G_SEXT:
0045     case TargetOpcode::G_ZEXT:
0046     case TargetOpcode::G_ANYEXT:
0047       return true;
0048     default:
0049       return false;
0050     }
0051   }
0052 
0053 public:
0054   LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI,
0055                                const LegalizerInfo &LI,
0056                                GISelKnownBits *KB = nullptr)
0057       : Builder(B), MRI(MRI), LI(LI), KB(KB) {}
0058 
0059   bool tryCombineAnyExt(MachineInstr &MI,
0060                         SmallVectorImpl<MachineInstr *> &DeadInsts,
0061                         SmallVectorImpl<Register> &UpdatedDefs,
0062                         GISelObserverWrapper &Observer) {
0063     using namespace llvm::MIPatternMatch;
0064     assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);
0065 
0066     Builder.setInstrAndDebugLoc(MI);
0067     Register DstReg = MI.getOperand(0).getReg();
0068     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
0069 
0070     // aext(trunc x) - > aext/copy/trunc x
0071     Register TruncSrc;
0072     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
0073       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
0074       if (MRI.getType(DstReg) == MRI.getType(TruncSrc))
0075         replaceRegOrBuildCopy(DstReg, TruncSrc, MRI, Builder, UpdatedDefs,
0076                               Observer);
0077       else
0078         Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
0079       UpdatedDefs.push_back(DstReg);
0080       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
0081       return true;
0082     }
0083 
0084     // aext([asz]ext x) -> [asz]ext x
0085     Register ExtSrc;
0086     MachineInstr *ExtMI;
0087     if (mi_match(SrcReg, MRI,
0088                  m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
0089                                                     m_GSExt(m_Reg(ExtSrc)),
0090                                                     m_GZExt(m_Reg(ExtSrc)))))) {
0091       Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
0092       UpdatedDefs.push_back(DstReg);
0093       markInstAndDefDead(MI, *ExtMI, DeadInsts);
0094       return true;
0095     }
0096 
0097     // Try to fold aext(g_constant) when the larger constant type is legal.
0098     auto *SrcMI = MRI.getVRegDef(SrcReg);
0099     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
0100       const LLT DstTy = MRI.getType(DstReg);
0101       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
0102         auto &CstVal = SrcMI->getOperand(1);
0103         auto *MergedLocation = DILocation::getMergedLocation(
0104             MI.getDebugLoc().get(), SrcMI->getDebugLoc().get());
0105         // Set the debug location to the merged location of the SrcMI and the MI
0106         // if the aext fold is successful.
0107         Builder.setDebugLoc(MergedLocation);
0108         Builder.buildConstant(
0109             DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
0110         UpdatedDefs.push_back(DstReg);
0111         markInstAndDefDead(MI, *SrcMI, DeadInsts);
0112         return true;
0113       }
0114     }
0115     return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs, Observer);
0116   }
0117 
0118   bool tryCombineZExt(MachineInstr &MI,
0119                       SmallVectorImpl<MachineInstr *> &DeadInsts,
0120                       SmallVectorImpl<Register> &UpdatedDefs,
0121                       GISelObserverWrapper &Observer) {
0122     using namespace llvm::MIPatternMatch;
0123     assert(MI.getOpcode() == TargetOpcode::G_ZEXT);
0124 
0125     Builder.setInstrAndDebugLoc(MI);
0126     Register DstReg = MI.getOperand(0).getReg();
0127     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
0128 
0129     // zext(trunc x) - > and (aext/copy/trunc x), mask
0130     // zext(sext x) -> and (sext x), mask
0131     Register TruncSrc;
0132     Register SextSrc;
0133     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc))) ||
0134         mi_match(SrcReg, MRI, m_GSExt(m_Reg(SextSrc)))) {
0135       LLT DstTy = MRI.getType(DstReg);
0136       if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
0137           isConstantUnsupported(DstTy))
0138         return false;
0139       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
0140       LLT SrcTy = MRI.getType(SrcReg);
0141       APInt MaskVal = APInt::getAllOnes(SrcTy.getScalarSizeInBits());
0142       if (SextSrc && (DstTy != MRI.getType(SextSrc)))
0143         SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
0144       if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))
0145         TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
0146       APInt ExtMaskVal = MaskVal.zext(DstTy.getScalarSizeInBits());
0147       Register AndSrc = SextSrc ? SextSrc : TruncSrc;
0148       // Elide G_AND and mask constant if possible.
0149       // The G_AND would also be removed by the post-legalize redundant_and
0150       // combine, but in this very common case, eliding early and regardless of
0151       // OptLevel results in significant compile-time and O0 code-size
0152       // improvements. Inserting unnecessary instructions between boolean defs
0153       // and uses hinders a lot of folding during ISel.
0154       if (KB && (KB->getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
0155         replaceRegOrBuildCopy(DstReg, AndSrc, MRI, Builder, UpdatedDefs,
0156                               Observer);
0157       } else {
0158         auto Mask = Builder.buildConstant(DstTy, ExtMaskVal);
0159         Builder.buildAnd(DstReg, AndSrc, Mask);
0160       }
0161       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
0162       return true;
0163     }
0164 
0165     // zext(zext x) -> (zext x)
0166     Register ZextSrc;
0167     if (mi_match(SrcReg, MRI, m_GZExt(m_Reg(ZextSrc)))) {
0168       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
0169       Observer.changingInstr(MI);
0170       MI.getOperand(1).setReg(ZextSrc);
0171       Observer.changedInstr(MI);
0172       UpdatedDefs.push_back(DstReg);
0173       markDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
0174       return true;
0175     }
0176 
0177     // Try to fold zext(g_constant) when the larger constant type is legal.
0178     auto *SrcMI = MRI.getVRegDef(SrcReg);
0179     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
0180       const LLT DstTy = MRI.getType(DstReg);
0181       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
0182         auto &CstVal = SrcMI->getOperand(1);
0183         Builder.buildConstant(
0184             DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));
0185         UpdatedDefs.push_back(DstReg);
0186         markInstAndDefDead(MI, *SrcMI, DeadInsts);
0187         return true;
0188       }
0189     }
0190     return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs, Observer);
0191   }
0192 
0193   bool tryCombineSExt(MachineInstr &MI,
0194                       SmallVectorImpl<MachineInstr *> &DeadInsts,
0195                       SmallVectorImpl<Register> &UpdatedDefs,
0196                       GISelObserverWrapper &Observer) {
0197     using namespace llvm::MIPatternMatch;
0198     assert(MI.getOpcode() == TargetOpcode::G_SEXT);
0199 
0200     Builder.setInstrAndDebugLoc(MI);
0201     Register DstReg = MI.getOperand(0).getReg();
0202     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
0203 
0204     // sext(trunc x) - > (sext_inreg (aext/copy/trunc x), c)
0205     Register TruncSrc;
0206     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
0207       LLT DstTy = MRI.getType(DstReg);
0208       if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))
0209         return false;
0210       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
0211       LLT SrcTy = MRI.getType(SrcReg);
0212       uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
0213       if (DstTy != MRI.getType(TruncSrc))
0214         TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
0215       // Elide G_SEXT_INREG if possible. This is similar to eliding G_AND in
0216       // tryCombineZExt. Refer to the comment in tryCombineZExt for rationale.
0217       if (KB && KB->computeNumSignBits(TruncSrc) >
0218                     DstTy.getScalarSizeInBits() - SizeInBits)
0219         replaceRegOrBuildCopy(DstReg, TruncSrc, MRI, Builder, UpdatedDefs,
0220                               Observer);
0221       else
0222         Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits);
0223       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
0224       return true;
0225     }
0226 
0227     // sext(zext x) -> (zext x)
0228     // sext(sext x) -> (sext x)
0229     Register ExtSrc;
0230     MachineInstr *ExtMI;
0231     if (mi_match(SrcReg, MRI,
0232                  m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)),
0233                                                     m_GSExt(m_Reg(ExtSrc)))))) {
0234       LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
0235       Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
0236       UpdatedDefs.push_back(DstReg);
0237       markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
0238       return true;
0239     }
0240 
0241     // Try to fold sext(g_constant) when the larger constant type is legal.
0242     auto *SrcMI = MRI.getVRegDef(SrcReg);
0243     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
0244       const LLT DstTy = MRI.getType(DstReg);
0245       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
0246         auto &CstVal = SrcMI->getOperand(1);
0247         Builder.buildConstant(
0248             DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
0249         UpdatedDefs.push_back(DstReg);
0250         markInstAndDefDead(MI, *SrcMI, DeadInsts);
0251         return true;
0252       }
0253     }
0254 
0255     return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs, Observer);
0256   }
0257 
0258   bool tryCombineTrunc(MachineInstr &MI,
0259                        SmallVectorImpl<MachineInstr *> &DeadInsts,
0260                        SmallVectorImpl<Register> &UpdatedDefs,
0261                        GISelObserverWrapper &Observer) {
0262     using namespace llvm::MIPatternMatch;
0263     assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
0264 
0265     Builder.setInstr(MI);
0266     Register DstReg = MI.getOperand(0).getReg();
0267     const LLT DstTy = MRI.getType(DstReg);
0268     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
0269 
0270     // Try to fold trunc(g_constant) when the smaller constant type is legal.
0271     auto *SrcMI = MRI.getVRegDef(SrcReg);
0272     if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
0273       if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
0274         auto &CstVal = SrcMI->getOperand(1);
0275         Builder.buildConstant(
0276             DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits()));
0277         UpdatedDefs.push_back(DstReg);
0278         markInstAndDefDead(MI, *SrcMI, DeadInsts);
0279         return true;
0280       }
0281     }
0282 
0283     // Try to fold trunc(merge) to directly use the source of the merge.
0284     // This gets rid of large, difficult to legalize, merges
0285     if (auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
0286       const Register MergeSrcReg = SrcMerge->getSourceReg(0);
0287       const LLT MergeSrcTy = MRI.getType(MergeSrcReg);
0288 
0289       // We can only fold if the types are scalar
0290       const unsigned DstSize = DstTy.getSizeInBits();
0291       const unsigned MergeSrcSize = MergeSrcTy.getSizeInBits();
0292       if (!DstTy.isScalar() || !MergeSrcTy.isScalar())
0293         return false;
0294 
0295       if (DstSize < MergeSrcSize) {
0296         // When the merge source is larger than the destination, we can just
0297         // truncate the merge source directly
0298         if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
0299           return false;
0300 
0301         LLVM_DEBUG(dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
0302                           << MI);
0303 
0304         Builder.buildTrunc(DstReg, MergeSrcReg);
0305         UpdatedDefs.push_back(DstReg);
0306       } else if (DstSize == MergeSrcSize) {
0307         // If the sizes match we can simply try to replace the register
0308         LLVM_DEBUG(
0309             dbgs() << "Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
0310                    << MI);
0311         replaceRegOrBuildCopy(DstReg, MergeSrcReg, MRI, Builder, UpdatedDefs,
0312                               Observer);
0313       } else if (DstSize % MergeSrcSize == 0) {
0314         // If the trunc size is a multiple of the merge source size we can use
0315         // a smaller merge instead
0316         if (isInstUnsupported(
0317                 {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
0318           return false;
0319 
0320         LLVM_DEBUG(
0321             dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
0322                    << MI);
0323 
0324         const unsigned NumSrcs = DstSize / MergeSrcSize;
0325         assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
0326                "trunc(merge) should require less inputs than merge");
0327         SmallVector<Register, 8> SrcRegs(NumSrcs);
0328         for (unsigned i = 0; i < NumSrcs; ++i)
0329           SrcRegs[i] = SrcMerge->getSourceReg(i);
0330 
0331         Builder.buildMergeValues(DstReg, SrcRegs);
0332         UpdatedDefs.push_back(DstReg);
0333       } else {
0334         // Unable to combine
0335         return false;
0336       }
0337 
0338       markInstAndDefDead(MI, *SrcMerge, DeadInsts);
0339       return true;
0340     }
0341 
0342     // trunc(trunc) -> trunc
0343     Register TruncSrc;
0344     if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
0345       // Always combine trunc(trunc) since the eventual resulting trunc must be
0346       // legal anyway as it must be legal for all outputs of the consumer type
0347       // set.
0348       LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_TRUNC): " << MI);
0349 
0350       Builder.buildTrunc(DstReg, TruncSrc);
0351       UpdatedDefs.push_back(DstReg);
0352       markInstAndDefDead(MI, *MRI.getVRegDef(TruncSrc), DeadInsts);
0353       return true;
0354     }
0355 
0356     // trunc(ext x) -> x
0357     ArtifactValueFinder Finder(MRI, Builder, LI);
0358     if (Register FoundReg =
0359             Finder.findValueFromDef(DstReg, 0, DstTy.getSizeInBits())) {
0360       LLT FoundRegTy = MRI.getType(FoundReg);
0361       if (DstTy == FoundRegTy) {
0362         LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_[S,Z,ANY]EXT/G_TRUNC...): "
0363                           << MI);
0364 
0365         replaceRegOrBuildCopy(DstReg, FoundReg, MRI, Builder, UpdatedDefs,
0366                               Observer);
0367         UpdatedDefs.push_back(DstReg);
0368         markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
0369         return true;
0370       }
0371     }
0372 
0373     return false;
0374   }
0375 
0376   /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
0377   bool tryFoldImplicitDef(MachineInstr &MI,
0378                           SmallVectorImpl<MachineInstr *> &DeadInsts,
0379                           SmallVectorImpl<Register> &UpdatedDefs,
0380                           GISelObserverWrapper &Observer) {
0381     unsigned Opcode = MI.getOpcode();
0382     assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
0383            Opcode == TargetOpcode::G_SEXT);
0384 
0385     if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
0386                                            MI.getOperand(1).getReg(), MRI)) {
0387       Builder.setInstr(MI);
0388       Register DstReg = MI.getOperand(0).getReg();
0389       LLT DstTy = MRI.getType(DstReg);
0390 
0391       if (Opcode == TargetOpcode::G_ANYEXT) {
0392         // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF
0393         if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
0394           return false;
0395         LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI);
0396         auto Impl = Builder.buildUndef(DstTy);
0397         replaceRegOrBuildCopy(DstReg, Impl.getReg(0), MRI, Builder, UpdatedDefs,
0398                               Observer);
0399         UpdatedDefs.push_back(DstReg);
0400       } else {
0401         // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
0402         // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
0403         if (isConstantUnsupported(DstTy))
0404           return false;
0405         LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI);
0406         auto Cnst = Builder.buildConstant(DstTy, 0);
0407         replaceRegOrBuildCopy(DstReg, Cnst.getReg(0), MRI, Builder, UpdatedDefs,
0408                               Observer);
0409         UpdatedDefs.push_back(DstReg);
0410       }
0411 
0412       markInstAndDefDead(MI, *DefMI, DeadInsts);
0413       return true;
0414     }
0415     return false;
0416   }
0417 
0418   bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI,
0419                           SmallVectorImpl<MachineInstr *> &DeadInsts,
0420                           SmallVectorImpl<Register> &UpdatedDefs) {
0421 
0422     assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
0423 
0424     const unsigned CastOpc = CastMI.getOpcode();
0425 
0426     if (!isArtifactCast(CastOpc))
0427       return false;
0428 
0429     const unsigned NumDefs = MI.getNumOperands() - 1;
0430 
0431     const Register CastSrcReg = CastMI.getOperand(1).getReg();
0432     const LLT CastSrcTy = MRI.getType(CastSrcReg);
0433     const LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
0434     const LLT SrcTy = MRI.getType(MI.getOperand(NumDefs).getReg());
0435 
0436     const unsigned CastSrcSize = CastSrcTy.getSizeInBits();
0437     const unsigned DestSize = DestTy.getSizeInBits();
0438 
0439     if (CastOpc == TargetOpcode::G_TRUNC) {
0440       if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.getScalarType()) {
0441         //  %1:_(<4 x s8>) = G_TRUNC %0(<4 x s32>)
0442         //  %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %1
0443         // =>
0444         //  %6:_(s32), %7:_(s32), %8:_(s32), %9:_(s32) = G_UNMERGE_VALUES %0
0445         //  %2:_(s8) = G_TRUNC %6
0446         //  %3:_(s8) = G_TRUNC %7
0447         //  %4:_(s8) = G_TRUNC %8
0448         //  %5:_(s8) = G_TRUNC %9
0449 
0450         unsigned UnmergeNumElts =
0451             DestTy.isVector() ? CastSrcTy.getNumElements() / NumDefs : 1;
0452         LLT UnmergeTy = CastSrcTy.changeElementCount(
0453             ElementCount::getFixed(UnmergeNumElts));
0454         LLT SrcWideTy =
0455             SrcTy.changeElementCount(ElementCount::getFixed(UnmergeNumElts));
0456 
0457         if (isInstUnsupported(
0458                 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}) ||
0459             LI.getAction({TargetOpcode::G_TRUNC, {SrcWideTy, UnmergeTy}})
0460                     .Action == LegalizeActions::MoreElements)
0461           return false;
0462 
0463         Builder.setInstr(MI);
0464         auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg);
0465 
0466         for (unsigned I = 0; I != NumDefs; ++I) {
0467           Register DefReg = MI.getOperand(I).getReg();
0468           UpdatedDefs.push_back(DefReg);
0469           Builder.buildTrunc(DefReg, NewUnmerge.getReg(I));
0470         }
0471 
0472         markInstAndDefDead(MI, CastMI, DeadInsts);
0473         return true;
0474       }
0475 
0476       if (CastSrcTy.isScalar() && SrcTy.isScalar() && !DestTy.isVector()) {
0477         //  %1:_(s16) = G_TRUNC %0(s32)
0478         //  %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %1
0479         // =>
0480         //  %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %0
0481 
0482         // Unmerge(trunc) can be combined if the trunc source size is a multiple
0483         // of the unmerge destination size
0484         if (CastSrcSize % DestSize != 0)
0485           return false;
0486 
0487         // Check if the new unmerge is supported
0488         if (isInstUnsupported(
0489                 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
0490           return false;
0491 
0492         // Gather the original destination registers and create new ones for the
0493         // unused bits
0494         const unsigned NewNumDefs = CastSrcSize / DestSize;
0495         SmallVector<Register, 8> DstRegs(NewNumDefs);
0496         for (unsigned Idx = 0; Idx < NewNumDefs; ++Idx) {
0497           if (Idx < NumDefs)
0498             DstRegs[Idx] = MI.getOperand(Idx).getReg();
0499           else
0500             DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy);
0501         }
0502 
0503         // Build new unmerge
0504         Builder.setInstr(MI);
0505         Builder.buildUnmerge(DstRegs, CastSrcReg);
0506         UpdatedDefs.append(DstRegs.begin(), DstRegs.begin() + NewNumDefs);
0507         markInstAndDefDead(MI, CastMI, DeadInsts);
0508         return true;
0509       }
0510     }
0511 
0512     // TODO: support combines with other casts as well
0513     return false;
0514   }
0515 
0516   static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp,
0517                                  LLT OpTy, LLT DestTy) {
0518     // Check if we found a definition that is like G_MERGE_VALUES.
0519     switch (MergeOp) {
0520     default:
0521       return false;
0522     case TargetOpcode::G_BUILD_VECTOR:
0523     case TargetOpcode::G_MERGE_VALUES:
0524       // The convert operation that we will need to insert is
0525       // going to convert the input of that type of instruction (scalar)
0526       // to the destination type (DestTy).
0527       // The conversion needs to stay in the same domain (scalar to scalar
0528       // and vector to vector), so if we were to allow to fold the merge
0529       // we would need to insert some bitcasts.
0530       // E.g.,
0531       // <2 x s16> = build_vector s16, s16
0532       // <2 x s32> = zext <2 x s16>
0533       // <2 x s16>, <2 x s16> = unmerge <2 x s32>
0534       //
0535       // As is the folding would produce:
0536       // <2 x s16> = zext s16  <-- scalar to vector
0537       // <2 x s16> = zext s16  <-- scalar to vector
0538       // Which is invalid.
0539       // Instead we would want to generate:
0540       // s32 = zext s16
0541       // <2 x s16> = bitcast s32
0542       // s32 = zext s16
0543       // <2 x s16> = bitcast s32
0544       //
0545       // That is not done yet.
0546       if (ConvertOp == 0)
0547         return true;
0548       return !DestTy.isVector() && OpTy.isVector() &&
0549              DestTy == OpTy.getElementType();
0550     case TargetOpcode::G_CONCAT_VECTORS: {
0551       if (ConvertOp == 0)
0552         return true;
0553       if (!DestTy.isVector())
0554         return false;
0555 
0556       const unsigned OpEltSize = OpTy.getElementType().getSizeInBits();
0557 
0558       // Don't handle scalarization with a cast that isn't in the same
0559       // direction as the vector cast. This could be handled, but it would
0560       // require more intermediate unmerges.
0561       if (ConvertOp == TargetOpcode::G_TRUNC)
0562         return DestTy.getSizeInBits() <= OpEltSize;
0563       return DestTy.getSizeInBits() >= OpEltSize;
0564     }
0565     }
0566   }
0567 
0568   /// Try to replace DstReg with SrcReg or build a COPY instruction
0569   /// depending on the register constraints.
0570   static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg,
0571                                     MachineRegisterInfo &MRI,
0572                                     MachineIRBuilder &Builder,
0573                                     SmallVectorImpl<Register> &UpdatedDefs,
0574                                     GISelChangeObserver &Observer) {
0575     if (!llvm::canReplaceReg(DstReg, SrcReg, MRI)) {
0576       Builder.buildCopy(DstReg, SrcReg);
0577       UpdatedDefs.push_back(DstReg);
0578       return;
0579     }
0580     SmallVector<MachineInstr *, 4> UseMIs;
0581     // Get the users and notify the observer before replacing.
0582     for (auto &UseMI : MRI.use_instructions(DstReg)) {
0583       UseMIs.push_back(&UseMI);
0584       Observer.changingInstr(UseMI);
0585     }
0586     // Replace the registers.
0587     MRI.replaceRegWith(DstReg, SrcReg);
0588     UpdatedDefs.push_back(SrcReg);
0589     // Notify the observer that we changed the instructions.
0590     for (auto *UseMI : UseMIs)
0591       Observer.changedInstr(*UseMI);
0592   }
0593 
0594   /// Return the operand index in \p MI that defines \p Def
0595   static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef) {
0596     unsigned DefIdx = 0;
0597     for (const MachineOperand &Def : MI.defs()) {
0598       if (Def.getReg() == SearchDef)
0599         break;
0600       ++DefIdx;
0601     }
0602 
0603     return DefIdx;
0604   }
0605 
0606   /// This class provides utilities for finding source registers of specific
0607   /// bit ranges in an artifact. The routines can look through the source
0608   /// registers if they're other artifacts to try to find a non-artifact source
0609   /// of a value.
0610   class ArtifactValueFinder {
0611     MachineRegisterInfo &MRI;
0612     MachineIRBuilder &MIB;
0613     const LegalizerInfo &LI;
0614 
0615     // Stores the best register found in the current query so far.
0616     Register CurrentBest = Register();
0617 
0618     /// Given an concat_vector op \p Concat and a start bit and size, try to
0619     /// find the origin of the value defined by that start position and size.
0620     ///
0621     /// \returns a register with the requested size, or the current best
0622     /// register found during the current query.
0623     Register findValueFromConcat(GConcatVectors &Concat, unsigned StartBit,
0624                                  unsigned Size) {
0625       assert(Size > 0);
0626 
0627       // Find the source operand that provides the bits requested.
0628       Register Src1Reg = Concat.getSourceReg(0);
0629       unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
0630 
0631       // Operand index of the source that provides the start of the bit range.
0632       unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
0633       // Offset into the source at which the bit range starts.
0634       unsigned InRegOffset = StartBit % SrcSize;
0635       // Check that the bits don't span multiple sources.
0636       // FIXME: we might be able return multiple sources? Or create an
0637       // appropriate concat to make it fit.
0638       if (InRegOffset + Size > SrcSize)
0639         return CurrentBest;
0640 
0641       Register SrcReg = Concat.getReg(StartSrcIdx);
0642       if (InRegOffset == 0 && Size == SrcSize) {
0643         CurrentBest = SrcReg;
0644         return findValueFromDefImpl(SrcReg, 0, Size);
0645       }
0646 
0647       return findValueFromDefImpl(SrcReg, InRegOffset, Size);
0648     }
0649 
0650     /// Given an build_vector op \p BV and a start bit and size, try to find
0651     /// the origin of the value defined by that start position and size.
0652     ///
0653     /// \returns a register with the requested size, or the current best
0654     /// register found during the current query.
0655     Register findValueFromBuildVector(GBuildVector &BV, unsigned StartBit,
0656                                       unsigned Size) {
0657       assert(Size > 0);
0658 
0659       // Find the source operand that provides the bits requested.
0660       Register Src1Reg = BV.getSourceReg(0);
0661       unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
0662 
0663       // Operand index of the source that provides the start of the bit range.
0664       unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
0665       // Offset into the source at which the bit range starts.
0666       unsigned InRegOffset = StartBit % SrcSize;
0667 
0668       if (InRegOffset != 0)
0669         return CurrentBest; // Give up, bits don't start at a scalar source.
0670       if (Size < SrcSize)
0671         return CurrentBest; // Scalar source is too large for requested bits.
0672 
0673       // If the bits cover multiple sources evenly, then create a new
0674       // build_vector to synthesize the required size, if that's been requested.
0675       if (Size > SrcSize) {
0676         if (Size % SrcSize > 0)
0677           return CurrentBest; // Isn't covered exactly by sources.
0678 
0679         unsigned NumSrcsUsed = Size / SrcSize;
0680         // If we're requesting all of the sources, just return this def.
0681         if (NumSrcsUsed == BV.getNumSources())
0682           return BV.getReg(0);
0683 
0684         LLT SrcTy = MRI.getType(Src1Reg);
0685         LLT NewBVTy = LLT::fixed_vector(NumSrcsUsed, SrcTy);
0686 
0687         // Check if the resulting build vector would be legal.
0688         LegalizeActionStep ActionStep =
0689             LI.getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
0690         if (ActionStep.Action != LegalizeActions::Legal)
0691           return CurrentBest;
0692 
0693         SmallVector<Register> NewSrcs;
0694         for (unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
0695              ++SrcIdx)
0696           NewSrcs.push_back(BV.getReg(SrcIdx));
0697         MIB.setInstrAndDebugLoc(BV);
0698         return MIB.buildBuildVector(NewBVTy, NewSrcs).getReg(0);
0699       }
0700       // A single source is requested, just return it.
0701       return BV.getReg(StartSrcIdx);
0702     }
0703 
0704     /// Given an G_INSERT op \p MI and a start bit and size, try to find
0705     /// the origin of the value defined by that start position and size.
0706     ///
0707     /// \returns a register with the requested size, or the current best
0708     /// register found during the current query.
0709     Register findValueFromInsert(MachineInstr &MI, unsigned StartBit,
0710                                  unsigned Size) {
0711       assert(MI.getOpcode() == TargetOpcode::G_INSERT);
0712       assert(Size > 0);
0713 
0714       Register ContainerSrcReg = MI.getOperand(1).getReg();
0715       Register InsertedReg = MI.getOperand(2).getReg();
0716       LLT InsertedRegTy = MRI.getType(InsertedReg);
0717       unsigned InsertOffset = MI.getOperand(3).getImm();
0718 
0719       // There are 4 possible container/insertreg + requested bit-range layouts
0720       // that the instruction and query could be representing.
0721       // For: %_ = G_INSERT %CONTAINER, %INS, InsOff (abbrev. to 'IO')
0722       // and a start bit 'SB', with size S, giving an end bit 'EB', we could
0723       // have...
0724       // Scenario A:
0725       //   --------------------------
0726       //  |  INS    |  CONTAINER     |
0727       //   --------------------------
0728       //       |   |
0729       //       SB  EB
0730       //
0731       // Scenario B:
0732       //   --------------------------
0733       //  |  INS    |  CONTAINER     |
0734       //   --------------------------
0735       //                |    |
0736       //                SB   EB
0737       //
0738       // Scenario C:
0739       //   --------------------------
0740       //  |  CONTAINER    |  INS     |
0741       //   --------------------------
0742       //       |    |
0743       //       SB   EB
0744       //
0745       // Scenario D:
0746       //   --------------------------
0747       //  |  CONTAINER    |  INS     |
0748       //   --------------------------
0749       //                     |   |
0750       //                     SB  EB
0751       //
0752       // So therefore, A and D are requesting data from the INS operand, while
0753       // B and C are requesting from the container operand.
0754 
0755       unsigned InsertedEndBit = InsertOffset + InsertedRegTy.getSizeInBits();
0756       unsigned EndBit = StartBit + Size;
0757       unsigned NewStartBit;
0758       Register SrcRegToUse;
0759       if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
0760         SrcRegToUse = ContainerSrcReg;
0761         NewStartBit = StartBit;
0762         return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size);
0763       }
0764       if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
0765         SrcRegToUse = InsertedReg;
0766         NewStartBit = StartBit - InsertOffset;
0767         if (NewStartBit == 0 &&
0768             Size == MRI.getType(SrcRegToUse).getSizeInBits())
0769           CurrentBest = SrcRegToUse;
0770         return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size);
0771       }
0772       // The bit range spans both the inserted and container regions.
0773       return Register();
0774     }
0775 
0776     /// Given an G_SEXT, G_ZEXT, G_ANYEXT op \p MI and a start bit and
0777     /// size, try to find the origin of the value defined by that start
0778     /// position and size.
0779     ///
0780     /// \returns a register with the requested size, or the current best
0781     /// register found during the current query.
0782     Register findValueFromExt(MachineInstr &MI, unsigned StartBit,
0783                               unsigned Size) {
0784       assert(MI.getOpcode() == TargetOpcode::G_SEXT ||
0785              MI.getOpcode() == TargetOpcode::G_ZEXT ||
0786              MI.getOpcode() == TargetOpcode::G_ANYEXT);
0787       assert(Size > 0);
0788 
0789       Register SrcReg = MI.getOperand(1).getReg();
0790       LLT SrcType = MRI.getType(SrcReg);
0791       unsigned SrcSize = SrcType.getSizeInBits();
0792 
0793       // Currently we don't go into vectors.
0794       if (!SrcType.isScalar())
0795         return CurrentBest;
0796 
0797       if (StartBit + Size > SrcSize)
0798         return CurrentBest;
0799 
0800       if (StartBit == 0 && SrcType.getSizeInBits() == Size)
0801         CurrentBest = SrcReg;
0802       return findValueFromDefImpl(SrcReg, StartBit, Size);
0803     }
0804 
0805     /// Given an G_TRUNC op \p MI and a start bit and size, try to find
0806     /// the origin of the value defined by that start position and size.
0807     ///
0808     /// \returns a register with the requested size, or the current best
0809     /// register found during the current query.
0810     Register findValueFromTrunc(MachineInstr &MI, unsigned StartBit,
0811                                 unsigned Size) {
0812       assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
0813       assert(Size > 0);
0814 
0815       Register SrcReg = MI.getOperand(1).getReg();
0816       LLT SrcType = MRI.getType(SrcReg);
0817 
0818       // Currently we don't go into vectors.
0819       if (!SrcType.isScalar())
0820         return CurrentBest;
0821 
0822       return findValueFromDefImpl(SrcReg, StartBit, Size);
0823     }
0824 
0825     /// Internal implementation for findValueFromDef(). findValueFromDef()
0826     /// initializes some data like the CurrentBest register, which this method
0827     /// and its callees rely upon.
0828     Register findValueFromDefImpl(Register DefReg, unsigned StartBit,
0829                                   unsigned Size) {
0830       std::optional<DefinitionAndSourceRegister> DefSrcReg =
0831           getDefSrcRegIgnoringCopies(DefReg, MRI);
0832       MachineInstr *Def = DefSrcReg->MI;
0833       DefReg = DefSrcReg->Reg;
0834       // If the instruction has a single def, then simply delegate the search.
0835       // For unmerge however with multiple defs, we need to compute the offset
0836       // into the source of the unmerge.
0837       switch (Def->getOpcode()) {
0838       case TargetOpcode::G_CONCAT_VECTORS:
0839         return findValueFromConcat(cast<GConcatVectors>(*Def), StartBit, Size);
0840       case TargetOpcode::G_UNMERGE_VALUES: {
0841         unsigned DefStartBit = 0;
0842         unsigned DefSize = MRI.getType(DefReg).getSizeInBits();
0843         for (const auto &MO : Def->defs()) {
0844           if (MO.getReg() == DefReg)
0845             break;
0846           DefStartBit += DefSize;
0847         }
0848         Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
0849         Register SrcOriginReg =
0850             findValueFromDefImpl(SrcReg, StartBit + DefStartBit, Size);
0851         if (SrcOriginReg)
0852           return SrcOriginReg;
0853         // Failed to find a further value. If the StartBit and Size perfectly
0854         // covered the requested DefReg, return that since it's better than
0855         // nothing.
0856         if (StartBit == 0 && Size == DefSize)
0857           return DefReg;
0858         return CurrentBest;
0859       }
0860       case TargetOpcode::G_BUILD_VECTOR:
0861         return findValueFromBuildVector(cast<GBuildVector>(*Def), StartBit,
0862                                         Size);
0863       case TargetOpcode::G_INSERT:
0864         return findValueFromInsert(*Def, StartBit, Size);
0865       case TargetOpcode::G_TRUNC:
0866         return findValueFromTrunc(*Def, StartBit, Size);
0867       case TargetOpcode::G_SEXT:
0868       case TargetOpcode::G_ZEXT:
0869       case TargetOpcode::G_ANYEXT:
0870         return findValueFromExt(*Def, StartBit, Size);
0871       default:
0872         return CurrentBest;
0873       }
0874     }
0875 
0876   public:
0877     ArtifactValueFinder(MachineRegisterInfo &Mri, MachineIRBuilder &Builder,
0878                         const LegalizerInfo &Info)
0879         : MRI(Mri), MIB(Builder), LI(Info) {}
0880 
0881     /// Try to find a source of the value defined in the def \p DefReg, starting
0882     /// at position \p StartBit with size \p Size.
0883     /// \returns a register with the requested size, or an empty Register if no
0884     /// better value could be found.
0885     Register findValueFromDef(Register DefReg, unsigned StartBit,
0886                               unsigned Size) {
0887       CurrentBest = Register();
0888       Register FoundReg = findValueFromDefImpl(DefReg, StartBit, Size);
0889       return FoundReg != DefReg ? FoundReg : Register();
0890     }
0891 
0892     /// Try to combine the defs of an unmerge \p MI by attempting to find
0893     /// values that provides the bits for each def reg.
0894     /// \returns true if all the defs of the unmerge have been made dead.
0895     bool tryCombineUnmergeDefs(GUnmerge &MI, GISelChangeObserver &Observer,
0896                                SmallVectorImpl<Register> &UpdatedDefs) {
0897       unsigned NumDefs = MI.getNumDefs();
0898       LLT DestTy = MRI.getType(MI.getReg(0));
0899 
0900       SmallBitVector DeadDefs(NumDefs);
0901       for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
0902         Register DefReg = MI.getReg(DefIdx);
0903         if (MRI.use_nodbg_empty(DefReg)) {
0904           DeadDefs[DefIdx] = true;
0905           continue;
0906         }
0907         Register FoundVal = findValueFromDef(DefReg, 0, DestTy.getSizeInBits());
0908         if (!FoundVal)
0909           continue;
0910         if (MRI.getType(FoundVal) != DestTy)
0911           continue;
0912 
0913         replaceRegOrBuildCopy(DefReg, FoundVal, MRI, MIB, UpdatedDefs,
0914                               Observer);
0915         // We only want to replace the uses, not the def of the old reg.
0916         Observer.changingInstr(MI);
0917         MI.getOperand(DefIdx).setReg(DefReg);
0918         Observer.changedInstr(MI);
0919         DeadDefs[DefIdx] = true;
0920       }
0921       return DeadDefs.all();
0922     }
0923 
0924     GUnmerge *findUnmergeThatDefinesReg(Register Reg, unsigned Size,
0925                                         unsigned &DefOperandIdx) {
0926       if (Register Def = findValueFromDefImpl(Reg, 0, Size)) {
0927         if (auto *Unmerge = dyn_cast<GUnmerge>(MRI.getVRegDef(Def))) {
0928           DefOperandIdx =
0929               Unmerge->findRegisterDefOperandIdx(Def, /*TRI=*/nullptr);
0930           return Unmerge;
0931         }
0932       }
0933       return nullptr;
0934     }
0935 
0936     // Check if sequence of elements from merge-like instruction is defined by
0937     // another sequence of elements defined by unmerge. Most often this is the
0938     // same sequence. Search for elements using findValueFromDefImpl.
0939     bool isSequenceFromUnmerge(GMergeLikeInstr &MI, unsigned MergeStartIdx,
0940                                GUnmerge *Unmerge, unsigned UnmergeIdxStart,
0941                                unsigned NumElts, unsigned EltSize,
0942                                bool AllowUndef) {
0943       assert(MergeStartIdx + NumElts <= MI.getNumSources());
0944       for (unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
0945         unsigned EltUnmergeIdx;
0946         GUnmerge *EltUnmerge = findUnmergeThatDefinesReg(
0947             MI.getSourceReg(i), EltSize, EltUnmergeIdx);
0948         // Check if source i comes from the same Unmerge.
0949         if (EltUnmerge == Unmerge) {
0950           // Check that source i's def has same index in sequence in Unmerge.
0951           if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
0952             return false;
0953         } else if (!AllowUndef ||
0954                    MRI.getVRegDef(MI.getSourceReg(i))->getOpcode() !=
0955                        TargetOpcode::G_IMPLICIT_DEF)
0956           return false;
0957       }
0958       return true;
0959     }
0960 
0961     bool tryCombineMergeLike(GMergeLikeInstr &MI,
0962                              SmallVectorImpl<MachineInstr *> &DeadInsts,
0963                              SmallVectorImpl<Register> &UpdatedDefs,
0964                              GISelChangeObserver &Observer) {
0965       Register Elt0 = MI.getSourceReg(0);
0966       LLT EltTy = MRI.getType(Elt0);
0967       unsigned EltSize = EltTy.getSizeInBits();
0968 
0969       unsigned Elt0UnmergeIdx;
0970       // Search for unmerge that will be candidate for combine.
0971       auto *Unmerge = findUnmergeThatDefinesReg(Elt0, EltSize, Elt0UnmergeIdx);
0972       if (!Unmerge)
0973         return false;
0974 
0975       unsigned NumMIElts = MI.getNumSources();
0976       Register Dst = MI.getReg(0);
0977       LLT DstTy = MRI.getType(Dst);
0978       Register UnmergeSrc = Unmerge->getSourceReg();
0979       LLT UnmergeSrcTy = MRI.getType(UnmergeSrc);
0980 
0981       // Recognize copy of UnmergeSrc to Dst.
0982       // Unmerge UnmergeSrc and reassemble it using merge-like opcode into Dst.
0983       //
0984       // %0:_(EltTy), %1, ... = G_UNMERGE_VALUES %UnmergeSrc:_(Ty)
0985       // %Dst:_(Ty) = G_merge_like_opcode %0:_(EltTy), %1, ...
0986       //
0987       // %Dst:_(Ty) = COPY %UnmergeSrc:_(Ty)
0988       if ((DstTy == UnmergeSrcTy) && (Elt0UnmergeIdx == 0)) {
0989         if (!isSequenceFromUnmerge(MI, 0, Unmerge, 0, NumMIElts, EltSize,
0990                                    /*AllowUndef=*/DstTy.isVector()))
0991           return false;
0992 
0993         replaceRegOrBuildCopy(Dst, UnmergeSrc, MRI, MIB, UpdatedDefs, Observer);
0994         DeadInsts.push_back(&MI);
0995         return true;
0996       }
0997 
0998       // Recognize UnmergeSrc that can be unmerged to DstTy directly.
0999       // Types have to be either both vector or both non-vector types.
1000       // Merge-like opcodes are combined one at the time. First one creates new
1001       // unmerge, following should use the same unmerge (builder performs CSE).
1002       //
1003       // %0:_(EltTy), %1, %2, %3 = G_UNMERGE_VALUES %UnmergeSrc:_(UnmergeSrcTy)
1004       // %Dst:_(DstTy) = G_merge_like_opcode %0:_(EltTy), %1
1005       // %AnotherDst:_(DstTy) = G_merge_like_opcode %2:_(EltTy), %3
1006       //
1007       // %Dst:_(DstTy), %AnotherDst = G_UNMERGE_VALUES %UnmergeSrc
1008       if ((DstTy.isVector() == UnmergeSrcTy.isVector()) &&
1009           (Elt0UnmergeIdx % NumMIElts == 0) &&
1010           getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
1011         if (!isSequenceFromUnmerge(MI, 0, Unmerge, Elt0UnmergeIdx, NumMIElts,
1012                                    EltSize, false))
1013           return false;
1014         MIB.setInstrAndDebugLoc(MI);
1015         auto NewUnmerge = MIB.buildUnmerge(DstTy, Unmerge->getSourceReg());
1016         unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.getSizeInBits();
1017         replaceRegOrBuildCopy(Dst, NewUnmerge.getReg(DstIdx), MRI, MIB,
1018                               UpdatedDefs, Observer);
1019         DeadInsts.push_back(&MI);
1020         return true;
1021       }
1022 
1023       // Recognize when multiple unmerged sources with UnmergeSrcTy type
1024       // can be merged into Dst with DstTy type directly.
1025       // Types have to be either both vector or both non-vector types.
1026 
1027       // %0:_(EltTy), %1 = G_UNMERGE_VALUES %UnmergeSrc:_(UnmergeSrcTy)
1028       // %2:_(EltTy), %3 = G_UNMERGE_VALUES %AnotherUnmergeSrc:_(UnmergeSrcTy)
1029       // %Dst:_(DstTy) = G_merge_like_opcode %0:_(EltTy), %1, %2, %3
1030       //
1031       // %Dst:_(DstTy) = G_merge_like_opcode %UnmergeSrc, %AnotherUnmergeSrc
1032 
1033       if ((DstTy.isVector() == UnmergeSrcTy.isVector()) &&
1034           getCoverTy(DstTy, UnmergeSrcTy) == DstTy) {
1035         SmallVector<Register, 4> ConcatSources;
1036         unsigned NumElts = Unmerge->getNumDefs();
1037         for (unsigned i = 0; i < MI.getNumSources(); i += NumElts) {
1038           unsigned EltUnmergeIdx;
1039           auto *UnmergeI = findUnmergeThatDefinesReg(MI.getSourceReg(i),
1040                                                      EltSize, EltUnmergeIdx);
1041           // All unmerges have to be the same size.
1042           if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
1043               (EltUnmergeIdx != 0))
1044             return false;
1045           if (!isSequenceFromUnmerge(MI, i, UnmergeI, 0, NumElts, EltSize,
1046                                      false))
1047             return false;
1048           ConcatSources.push_back(UnmergeI->getSourceReg());
1049         }
1050 
1051         MIB.setInstrAndDebugLoc(MI);
1052         MIB.buildMergeLikeInstr(Dst, ConcatSources);
1053         DeadInsts.push_back(&MI);
1054         return true;
1055       }
1056 
1057       return false;
1058     }
1059   };
1060 
1061   bool tryCombineUnmergeValues(GUnmerge &MI,
1062                                SmallVectorImpl<MachineInstr *> &DeadInsts,
1063                                SmallVectorImpl<Register> &UpdatedDefs,
1064                                GISelChangeObserver &Observer) {
1065     unsigned NumDefs = MI.getNumDefs();
1066     Register SrcReg = MI.getSourceReg();
1067     MachineInstr *SrcDef = getDefIgnoringCopies(SrcReg, MRI);
1068     if (!SrcDef)
1069       return false;
1070 
1071     LLT OpTy = MRI.getType(SrcReg);
1072     LLT DestTy = MRI.getType(MI.getReg(0));
1073     unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg);
1074 
1075     Builder.setInstrAndDebugLoc(MI);
1076 
1077     ArtifactValueFinder Finder(MRI, Builder, LI);
1078     if (Finder.tryCombineUnmergeDefs(MI, Observer, UpdatedDefs)) {
1079       markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);
1080       return true;
1081     }
1082 
1083     if (auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
1084       // %0:_(<4 x s16>) = G_FOO
1085       // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0
1086       // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1
1087       //
1088       // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0
1089       Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
1090       LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);
1091 
1092       // If we need to decrease the number of vector elements in the result type
1093       // of an unmerge, this would involve the creation of an equivalent unmerge
1094       // to copy back to the original result registers.
1095       LegalizeActionStep ActionStep = LI.getAction(
1096           {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
1097       switch (ActionStep.Action) {
1098       case LegalizeActions::Legal:
1099         if (!OpTy.isVector() || !LI.isLegal({TargetOpcode::G_UNMERGE_VALUES,
1100                                              {DestTy, SrcUnmergeSrcTy}}))
1101           return false;
1102         break;
1103       case LegalizeActions::Lower:
1104       case LegalizeActions::Unsupported:
1105         break;
1106       case LegalizeActions::FewerElements:
1107       case LegalizeActions::NarrowScalar:
1108         if (ActionStep.TypeIdx == 1)
1109           return false;
1110         break;
1111       default:
1112         return false;
1113       }
1114 
1115       auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
1116 
1117       // TODO: Should we try to process out the other defs now? If the other
1118       // defs of the source unmerge are also unmerged, we end up with a separate
1119       // unmerge for each one.
1120       for (unsigned I = 0; I != NumDefs; ++I) {
1121         Register Def = MI.getReg(I);
1122         replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I),
1123                               MRI, Builder, UpdatedDefs, Observer);
1124       }
1125 
1126       markInstAndDefDead(MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1127       return true;
1128     }
1129 
1130     MachineInstr *MergeI = SrcDef;
1131     unsigned ConvertOp = 0;
1132 
1133     // Handle intermediate conversions
1134     unsigned SrcOp = SrcDef->getOpcode();
1135     if (isArtifactCast(SrcOp)) {
1136       ConvertOp = SrcOp;
1137       MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI);
1138     }
1139 
1140     if (!MergeI || !canFoldMergeOpcode(MergeI->getOpcode(),
1141                                        ConvertOp, OpTy, DestTy)) {
1142       // We might have a chance to combine later by trying to combine
1143       // unmerge(cast) first
1144       return tryFoldUnmergeCast(MI, *SrcDef, DeadInsts, UpdatedDefs);
1145     }
1146 
1147     const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
1148 
1149     if (NumMergeRegs < NumDefs) {
1150       if (NumDefs % NumMergeRegs != 0)
1151         return false;
1152 
1153       Builder.setInstr(MI);
1154       // Transform to UNMERGEs, for example
1155       //   %1 = G_MERGE_VALUES %4, %5
1156       //   %9, %10, %11, %12 = G_UNMERGE_VALUES %1
1157       // to
1158       //   %9, %10 = G_UNMERGE_VALUES %4
1159       //   %11, %12 = G_UNMERGE_VALUES %5
1160 
1161       const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1162       for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
1163         SmallVector<Register, 8> DstRegs;
1164         for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
1165              ++j, ++DefIdx)
1166           DstRegs.push_back(MI.getReg(DefIdx));
1167 
1168         if (ConvertOp) {
1169           LLT MergeDstTy = MRI.getType(SrcDef->getOperand(0).getReg());
1170 
1171           // This is a vector that is being split and casted. Extract to the
1172           // element type, and do the conversion on the scalars (or smaller
1173           // vectors).
1174           LLT MergeEltTy = MergeDstTy.divide(NumMergeRegs);
1175 
1176           // Handle split to smaller vectors, with conversions.
1177           // %2(<8 x s8>) = G_CONCAT_VECTORS %0(<4 x s8>), %1(<4 x s8>)
1178           // %3(<8 x s16>) = G_SEXT %2
1179           // %4(<2 x s16>), %5(<2 x s16>), %6(<2 x s16>), %7(<2 x s16>) =
1180           // G_UNMERGE_VALUES %3
1181           //
1182           // =>
1183           //
1184           // %8(<4 x s16>) = G_SEXT %0
1185           // %9(<4 x s16>) = G_SEXT %1
1186           // %4(<2 x s16>), %5(<2 x s16>) = G_UNMERGE_VALUES %8
1187           // %7(<2 x s16>), %7(<2 x s16>) = G_UNMERGE_VALUES %9
1188 
1189           Register TmpReg = MRI.createGenericVirtualRegister(MergeEltTy);
1190           Builder.buildInstr(ConvertOp, {TmpReg},
1191                              {MergeI->getOperand(Idx + 1).getReg()});
1192           Builder.buildUnmerge(DstRegs, TmpReg);
1193         } else {
1194           Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
1195         }
1196         UpdatedDefs.append(DstRegs.begin(), DstRegs.end());
1197       }
1198 
1199     } else if (NumMergeRegs > NumDefs) {
1200       if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1201         return false;
1202 
1203       Builder.setInstr(MI);
1204       // Transform to MERGEs
1205       //   %6 = G_MERGE_VALUES %17, %18, %19, %20
1206       //   %7, %8 = G_UNMERGE_VALUES %6
1207       // to
1208       //   %7 = G_MERGE_VALUES %17, %18
1209       //   %8 = G_MERGE_VALUES %19, %20
1210 
1211       const unsigned NumRegs = NumMergeRegs / NumDefs;
1212       for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1213         SmallVector<Register, 8> Regs;
1214         for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
1215              ++j, ++Idx)
1216           Regs.push_back(MergeI->getOperand(Idx).getReg());
1217 
1218         Register DefReg = MI.getReg(DefIdx);
1219         Builder.buildMergeLikeInstr(DefReg, Regs);
1220         UpdatedDefs.push_back(DefReg);
1221       }
1222 
1223     } else {
1224       LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
1225 
1226       if (!ConvertOp && DestTy != MergeSrcTy) {
1227         if (DestTy.isPointer())
1228           ConvertOp = TargetOpcode::G_INTTOPTR;
1229         else if (MergeSrcTy.isPointer())
1230           ConvertOp = TargetOpcode::G_PTRTOINT;
1231         else
1232           ConvertOp = TargetOpcode::G_BITCAST;
1233       }
1234 
1235       if (ConvertOp) {
1236         Builder.setInstr(MI);
1237 
1238         for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1239           Register DefReg = MI.getOperand(Idx).getReg();
1240           Register MergeSrc = MergeI->getOperand(Idx + 1).getReg();
1241 
1242           if (!MRI.use_empty(DefReg)) {
1243             Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1244             UpdatedDefs.push_back(DefReg);
1245           }
1246         }
1247 
1248         markInstAndDefDead(MI, *MergeI, DeadInsts);
1249         return true;
1250       }
1251 
1252       assert(DestTy == MergeSrcTy &&
1253              "Bitcast and the other kinds of conversions should "
1254              "have happened earlier");
1255 
1256       Builder.setInstr(MI);
1257       for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1258         Register DstReg = MI.getOperand(Idx).getReg();
1259         Register SrcReg = MergeI->getOperand(Idx + 1).getReg();
1260         replaceRegOrBuildCopy(DstReg, SrcReg, MRI, Builder, UpdatedDefs,
1261                               Observer);
1262       }
1263     }
1264 
1265     markInstAndDefDead(MI, *MergeI, DeadInsts);
1266     return true;
1267   }
1268 
1269   bool tryCombineExtract(MachineInstr &MI,
1270                          SmallVectorImpl<MachineInstr *> &DeadInsts,
1271                          SmallVectorImpl<Register> &UpdatedDefs) {
1272     assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
1273 
1274     // Try to use the source registers from a G_MERGE_VALUES
1275     //
1276     // %2 = G_MERGE_VALUES %0, %1
1277     // %3 = G_EXTRACT %2, N
1278     // =>
1279     //
1280     // for N < %2.getSizeInBits() / 2
1281     //     %3 = G_EXTRACT %0, N
1282     //
1283     // for N >= %2.getSizeInBits() / 2
1284     //    %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
1285 
1286     Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
1287     MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
1288     if (!MergeI || !isa<GMergeLikeInstr>(MergeI))
1289       return false;
1290 
1291     Register DstReg = MI.getOperand(0).getReg();
1292     LLT DstTy = MRI.getType(DstReg);
1293     LLT SrcTy = MRI.getType(SrcReg);
1294 
1295     // TODO: Do we need to check if the resulting extract is supported?
1296     unsigned ExtractDstSize = DstTy.getSizeInBits();
1297     unsigned Offset = MI.getOperand(2).getImm();
1298     unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
1299     unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
1300     unsigned MergeSrcIdx = Offset / MergeSrcSize;
1301 
1302     // Compute the offset of the last bit the extract needs.
1303     unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
1304 
1305     // Can't handle the case where the extract spans multiple inputs.
1306     if (MergeSrcIdx != EndMergeSrcIdx)
1307       return false;
1308 
1309     // TODO: We could modify MI in place in most cases.
1310     Builder.setInstr(MI);
1311     Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(),
1312                          Offset - MergeSrcIdx * MergeSrcSize);
1313     UpdatedDefs.push_back(DstReg);
1314     markInstAndDefDead(MI, *MergeI, DeadInsts);
1315     return true;
1316   }
1317 
1318   /// Try to combine away MI.
1319   /// Returns true if it combined away the MI.
1320   /// Adds instructions that are dead as a result of the combine
1321   /// into DeadInsts, which can include MI.
1322   bool tryCombineInstruction(MachineInstr &MI,
1323                              SmallVectorImpl<MachineInstr *> &DeadInsts,
1324                              GISelObserverWrapper &WrapperObserver) {
1325     ArtifactValueFinder Finder(MRI, Builder, LI);
1326 
1327     // This might be a recursive call, and we might have DeadInsts already
1328     // populated. To avoid bad things happening later with multiple vreg defs
1329     // etc, process the dead instructions now if any.
1330     if (!DeadInsts.empty())
1331       deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1332 
1333     // Put here every vreg that was redefined in such a way that it's at least
1334     // possible that one (or more) of its users (immediate or COPY-separated)
1335     // could become artifact combinable with the new definition (or the
1336     // instruction reachable from it through a chain of copies if any).
1337     SmallVector<Register, 4> UpdatedDefs;
1338     bool Changed = false;
1339     switch (MI.getOpcode()) {
1340     default:
1341       return false;
1342     case TargetOpcode::G_ANYEXT:
1343       Changed = tryCombineAnyExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1344       break;
1345     case TargetOpcode::G_ZEXT:
1346       Changed = tryCombineZExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1347       break;
1348     case TargetOpcode::G_SEXT:
1349       Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1350       break;
1351     case TargetOpcode::G_UNMERGE_VALUES:
1352       Changed = tryCombineUnmergeValues(cast<GUnmerge>(MI), DeadInsts,
1353                                         UpdatedDefs, WrapperObserver);
1354       break;
1355     case TargetOpcode::G_MERGE_VALUES:
1356     case TargetOpcode::G_BUILD_VECTOR:
1357     case TargetOpcode::G_CONCAT_VECTORS:
1358       // If any of the users of this merge are an unmerge, then add them to the
1359       // artifact worklist in case there's folding that can be done looking up.
1360       for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) {
1361         if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1362             U.getOpcode() == TargetOpcode::G_TRUNC) {
1363           UpdatedDefs.push_back(MI.getOperand(0).getReg());
1364           break;
1365         }
1366       }
1367       Changed = Finder.tryCombineMergeLike(cast<GMergeLikeInstr>(MI), DeadInsts,
1368                                            UpdatedDefs, WrapperObserver);
1369       break;
1370     case TargetOpcode::G_EXTRACT:
1371       Changed = tryCombineExtract(MI, DeadInsts, UpdatedDefs);
1372       break;
1373     case TargetOpcode::G_TRUNC:
1374       Changed = tryCombineTrunc(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1375       if (!Changed) {
1376         // Try to combine truncates away even if they are legal. As all artifact
1377         // combines at the moment look only "up" the def-use chains, we achieve
1378         // that by throwing truncates' users (with look through copies) into the
1379         // ArtifactList again.
1380         UpdatedDefs.push_back(MI.getOperand(0).getReg());
1381       }
1382       break;
1383     }
1384     // If the main loop through the ArtifactList found at least one combinable
1385     // pair of artifacts, not only combine it away (as done above), but also
1386     // follow the def-use chain from there to combine everything that can be
1387     // combined within this def-use chain of artifacts.
1388     while (!UpdatedDefs.empty()) {
1389       Register NewDef = UpdatedDefs.pop_back_val();
1390       assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg");
1391       for (MachineInstr &Use : MRI.use_instructions(NewDef)) {
1392         switch (Use.getOpcode()) {
1393         // Keep this list in sync with the list of all artifact combines.
1394         case TargetOpcode::G_ANYEXT:
1395         case TargetOpcode::G_ZEXT:
1396         case TargetOpcode::G_SEXT:
1397         case TargetOpcode::G_UNMERGE_VALUES:
1398         case TargetOpcode::G_EXTRACT:
1399         case TargetOpcode::G_TRUNC:
1400         case TargetOpcode::G_BUILD_VECTOR:
1401           // Adding Use to ArtifactList.
1402           WrapperObserver.changedInstr(Use);
1403           break;
1404         case TargetOpcode::G_ASSERT_SEXT:
1405         case TargetOpcode::G_ASSERT_ZEXT:
1406         case TargetOpcode::G_ASSERT_ALIGN:
1407         case TargetOpcode::COPY: {
1408           Register Copy = Use.getOperand(0).getReg();
1409           if (Copy.isVirtual())
1410             UpdatedDefs.push_back(Copy);
1411           break;
1412         }
1413         default:
1414           // If we do not have an artifact combine for the opcode, there is no
1415           // point in adding it to the ArtifactList as nothing interesting will
1416           // be done to it anyway.
1417           break;
1418         }
1419       }
1420     }
1421     return Changed;
1422   }
1423 
1424 private:
1425   static Register getArtifactSrcReg(const MachineInstr &MI) {
1426     switch (MI.getOpcode()) {
1427     case TargetOpcode::COPY:
1428     case TargetOpcode::G_TRUNC:
1429     case TargetOpcode::G_ZEXT:
1430     case TargetOpcode::G_ANYEXT:
1431     case TargetOpcode::G_SEXT:
1432     case TargetOpcode::G_EXTRACT:
1433     case TargetOpcode::G_ASSERT_SEXT:
1434     case TargetOpcode::G_ASSERT_ZEXT:
1435     case TargetOpcode::G_ASSERT_ALIGN:
1436       return MI.getOperand(1).getReg();
1437     case TargetOpcode::G_UNMERGE_VALUES:
1438       return MI.getOperand(MI.getNumOperands() - 1).getReg();
1439     default:
1440       llvm_unreachable("Not a legalization artifact happen");
1441     }
1442   }
1443 
1444   /// Mark a def of one of MI's original operands, DefMI, as dead if changing MI
1445   /// (either by killing it or changing operands) results in DefMI being dead
1446   /// too. In-between COPYs or artifact-casts are also collected if they are
1447   /// dead.
1448   /// MI is not marked dead.
1449   void markDefDead(MachineInstr &MI, MachineInstr &DefMI,
1450                    SmallVectorImpl<MachineInstr *> &DeadInsts,
1451                    unsigned DefIdx = 0) {
1452     // Collect all the copy instructions that are made dead, due to deleting
1453     // this instruction. Collect all of them until the Trunc(DefMI).
1454     // Eg,
1455     // %1(s1) = G_TRUNC %0(s32)
1456     // %2(s1) = COPY %1(s1)
1457     // %3(s1) = COPY %2(s1)
1458     // %4(s32) = G_ANYEXT %3(s1)
1459     // In this case, we would have replaced %4 with a copy of %0,
1460     // and as a result, %3, %2, %1 are dead.
1461     MachineInstr *PrevMI = &MI;
1462     while (PrevMI != &DefMI) {
1463       Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1464 
1465       MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
1466       if (MRI.hasOneUse(PrevRegSrc)) {
1467         if (TmpDef != &DefMI) {
1468           assert((TmpDef->getOpcode() == TargetOpcode::COPY ||
1469                   isArtifactCast(TmpDef->getOpcode()) ||
1470                   isPreISelGenericOptimizationHint(TmpDef->getOpcode())) &&
1471                  "Expecting copy or artifact cast here");
1472 
1473           DeadInsts.push_back(TmpDef);
1474         }
1475       } else
1476         break;
1477       PrevMI = TmpDef;
1478     }
1479 
1480     if (PrevMI == &DefMI) {
1481       unsigned I = 0;
1482       bool IsDead = true;
1483       for (MachineOperand &Def : DefMI.defs()) {
1484         if (I != DefIdx) {
1485           if (!MRI.use_empty(Def.getReg())) {
1486             IsDead = false;
1487             break;
1488           }
1489         } else {
1490           if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg()))
1491             break;
1492         }
1493 
1494         ++I;
1495       }
1496 
1497       if (IsDead)
1498         DeadInsts.push_back(&DefMI);
1499     }
1500   }
1501 
1502   /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
1503   /// dead due to MI being killed, then mark DefMI as dead too.
1504   /// Some of the combines (extends(trunc)), try to walk through redundant
1505   /// copies in between the extends and the truncs, and this attempts to collect
1506   /// the in between copies if they're dead.
1507   void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
1508                           SmallVectorImpl<MachineInstr *> &DeadInsts,
1509                           unsigned DefIdx = 0) {
1510     DeadInsts.push_back(&MI);
1511     markDefDead(MI, DefMI, DeadInsts, DefIdx);
1512   }
1513 
1514   /// Erase the dead instructions in the list and call the observer hooks.
1515   /// Normally the Legalizer will deal with erasing instructions that have been
1516   /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to
1517   /// process instructions which have been marked dead, but otherwise break the
1518   /// MIR by introducing multiple vreg defs. For those cases, allow the combines
1519   /// to explicitly delete the instructions before we run into trouble.
1520   void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts,
1521                              GISelObserverWrapper &WrapperObserver) {
1522     for (auto *DeadMI : DeadInsts) {
1523       LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");
1524       WrapperObserver.erasingInstr(*DeadMI);
1525       DeadMI->eraseFromParent();
1526     }
1527     DeadInsts.clear();
1528   }
1529 
1530   /// Checks if the target legalizer info has specified anything about the
1531   /// instruction, or if unsupported.
1532   bool isInstUnsupported(const LegalityQuery &Query) const {
1533     using namespace LegalizeActions;
1534     auto Step = LI.getAction(Query);
1535     return Step.Action == Unsupported || Step.Action == NotFound;
1536   }
1537 
1538   bool isInstLegal(const LegalityQuery &Query) const {
1539     return LI.getAction(Query).Action == LegalizeActions::Legal;
1540   }
1541 
1542   bool isConstantUnsupported(LLT Ty) const {
1543     if (!Ty.isVector())
1544       return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1545 
1546     LLT EltTy = Ty.getElementType();
1547     return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1548            isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
1549   }
1550 
1551   /// Looks through copy instructions and returns the actual
1552   /// source register.
1553   Register lookThroughCopyInstrs(Register Reg) {
1554     Register TmpReg = getSrcRegIgnoringCopies(Reg, MRI);
1555     return TmpReg.isValid() ? TmpReg : Reg;
1556   }
1557 };
1558 
1559 } // namespace llvm
1560 
1561 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H