14#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
15#define LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
30#define DEBUG_TYPE "legalizer"
38 static bool isArtifactCast(
unsigned Opc) {
40 case TargetOpcode::G_TRUNC:
41 case TargetOpcode::G_SEXT:
42 case TargetOpcode::G_ZEXT:
43 case TargetOpcode::G_ANYEXT:
60 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT);
64 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
68 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
70 if (
MRI.getType(DstReg) ==
MRI.getType(TruncSrc))
74 Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
76 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
83 if (mi_match(SrcReg,
MRI,
84 m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
85 m_GSExt(m_Reg(ExtSrc)),
86 m_GZExt(m_Reg(ExtSrc)))))) {
89 markInstAndDefDead(
MI, *ExtMI, DeadInsts);
94 auto *SrcMI =
MRI.getVRegDef(SrcReg);
95 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
96 const LLT DstTy =
MRI.getType(DstReg);
97 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
98 auto &CstVal = SrcMI->getOperand(1);
100 DstReg, CstVal.getCImm()->getValue().sext(DstTy.
getSizeInBits()));
102 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
114 assert(
MI.getOpcode() == TargetOpcode::G_ZEXT);
118 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
124 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc))) ||
125 mi_match(SrcReg,
MRI, m_GSExt(m_Reg(SextSrc)))) {
126 LLT DstTy =
MRI.getType(DstReg);
127 if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
128 isConstantUnsupported(DstTy))
131 LLT SrcTy =
MRI.getType(SrcReg);
133 auto Mask =
Builder.buildConstant(
135 if (SextSrc && (DstTy !=
MRI.getType(SextSrc)))
136 SextSrc =
Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
137 if (TruncSrc && (DstTy !=
MRI.getType(TruncSrc)))
138 TruncSrc =
Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
139 Builder.buildAnd(DstReg, SextSrc ? SextSrc : TruncSrc, Mask);
140 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
146 if (mi_match(SrcReg,
MRI, m_GZExt(m_Reg(ZextSrc)))) {
149 MI.getOperand(1).setReg(ZextSrc);
152 markDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
157 auto *SrcMI =
MRI.getVRegDef(SrcReg);
158 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
159 const LLT DstTy =
MRI.getType(DstReg);
160 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
161 auto &CstVal = SrcMI->getOperand(1);
163 DstReg, CstVal.getCImm()->getValue().zext(DstTy.
getSizeInBits()));
165 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
176 assert(
MI.getOpcode() == TargetOpcode::G_SEXT);
180 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
184 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
185 LLT DstTy =
MRI.getType(DstReg);
186 if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))
189 LLT SrcTy =
MRI.getType(SrcReg);
190 uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
191 if (DstTy !=
MRI.getType(TruncSrc))
192 TruncSrc =
Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
193 Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits);
194 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
202 if (mi_match(SrcReg,
MRI,
203 m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)),
204 m_GSExt(m_Reg(ExtSrc)))))) {
208 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
213 auto *SrcMI =
MRI.getVRegDef(SrcReg);
214 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
215 const LLT DstTy =
MRI.getType(DstReg);
216 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
217 auto &CstVal = SrcMI->getOperand(1);
219 DstReg, CstVal.getCImm()->getValue().sext(DstTy.
getSizeInBits()));
221 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
234 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
238 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
241 auto *SrcMI =
MRI.getVRegDef(SrcReg);
242 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
243 const LLT DstTy =
MRI.getType(DstReg);
244 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
245 auto &CstVal = SrcMI->getOperand(1);
247 DstReg, CstVal.getCImm()->getValue().trunc(DstTy.
getSizeInBits()));
249 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
256 if (
auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
257 const Register MergeSrcReg = SrcMerge->getSourceReg(0);
258 const LLT MergeSrcTy =
MRI.getType(MergeSrcReg);
259 const LLT DstTy =
MRI.getType(DstReg);
267 if (DstSize < MergeSrcSize) {
270 if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
273 LLVM_DEBUG(
dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
276 Builder.buildTrunc(DstReg, MergeSrcReg);
278 }
else if (DstSize == MergeSrcSize) {
281 dbgs() <<
"Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
285 }
else if (DstSize % MergeSrcSize == 0) {
288 if (isInstUnsupported(
289 {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
293 dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
296 const unsigned NumSrcs = DstSize / MergeSrcSize;
297 assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
298 "trunc(merge) should require less inputs than merge");
300 for (
unsigned i = 0; i < NumSrcs; ++i)
301 SrcRegs[i] = SrcMerge->getSourceReg(i);
303 Builder.buildMergeValues(DstReg, SrcRegs);
310 markInstAndDefDead(
MI, *SrcMerge, DeadInsts);
316 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
322 Builder.buildTrunc(DstReg, TruncSrc);
324 markInstAndDefDead(
MI, *
MRI.getVRegDef(TruncSrc), DeadInsts);
335 unsigned Opcode =
MI.getOpcode();
336 assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
337 Opcode == TargetOpcode::G_SEXT);
340 MI.getOperand(1).getReg(),
MRI)) {
343 LLT DstTy =
MRI.getType(DstReg);
345 if (Opcode == TargetOpcode::G_ANYEXT) {
347 if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
350 Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
355 if (isConstantUnsupported(DstTy))
358 Builder.buildConstant(DstReg, 0);
362 markInstAndDefDead(
MI, *
DefMI, DeadInsts);
372 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
374 const unsigned CastOpc = CastMI.
getOpcode();
376 if (!isArtifactCast(CastOpc))
379 const unsigned NumDefs =
MI.getNumOperands() - 1;
382 const LLT CastSrcTy =
MRI.getType(CastSrcReg);
383 const LLT DestTy =
MRI.getType(
MI.getOperand(0).getReg());
384 const LLT SrcTy =
MRI.getType(
MI.getOperand(NumDefs).getReg());
389 if (CastOpc == TargetOpcode::G_TRUNC) {
400 unsigned UnmergeNumElts =
405 if (isInstUnsupported(
406 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}))
410 auto NewUnmerge =
Builder.buildUnmerge(UnmergeTy, CastSrcReg);
412 for (
unsigned I = 0;
I != NumDefs; ++
I) {
415 Builder.buildTrunc(DefReg, NewUnmerge.getReg(
I));
418 markInstAndDefDead(
MI, CastMI, DeadInsts);
430 if (CastSrcSize % DestSize != 0)
434 if (isInstUnsupported(
435 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
440 const unsigned NewNumDefs = CastSrcSize / DestSize;
442 for (
unsigned Idx = 0;
Idx < NewNumDefs; ++
Idx) {
444 DstRegs[
Idx] =
MI.getOperand(
Idx).getReg();
446 DstRegs[
Idx] =
MRI.createGenericVirtualRegister(DestTy);
451 Builder.buildUnmerge(DstRegs, CastSrcReg);
453 markInstAndDefDead(
MI, CastMI, DeadInsts);
468 case TargetOpcode::G_BUILD_VECTOR:
469 case TargetOpcode::G_MERGE_VALUES:
496 case TargetOpcode::G_CONCAT_VECTORS: {
507 if (ConvertOp == TargetOpcode::G_TRUNC)
522 Builder.buildCopy(DstReg, SrcReg);
528 for (
auto &
UseMI :
MRI.use_instructions(DstReg)) {
533 MRI.replaceRegWith(DstReg, SrcReg);
536 for (
auto *
UseMI : UseMIs)
544 if (Def.getReg() == SearchDef)
575 unsigned SrcSize =
MRI.getType(Src1Reg).getSizeInBits();
578 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
580 unsigned InRegOffset = StartBit % SrcSize;
584 if (InRegOffset +
Size > SrcSize)
588 if (InRegOffset == 0 &&
Size == SrcSize) {
589 CurrentBest = SrcReg;
590 return findValueFromDefImpl(SrcReg, 0,
Size);
593 return findValueFromDefImpl(SrcReg, InRegOffset,
Size);
607 unsigned SrcSize =
MRI.getType(Src1Reg).getSizeInBits();
610 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
612 unsigned InRegOffset = StartBit % SrcSize;
614 if (InRegOffset != 0)
621 if (
Size > SrcSize) {
622 if (
Size % SrcSize > 0)
625 unsigned NumSrcsUsed =
Size / SrcSize;
630 LLT SrcTy =
MRI.getType(Src1Reg);
635 LI.
getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
640 for (
unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
647 return BV.
getReg(StartSrcIdx);
657 assert(
MI.getOpcode() == TargetOpcode::G_INSERT);
660 Register ContainerSrcReg =
MI.getOperand(1).getReg();
661 Register InsertedReg =
MI.getOperand(2).getReg();
662 LLT InsertedRegTy =
MRI.getType(InsertedReg);
663 unsigned InsertOffset =
MI.getOperand(3).getImm();
701 unsigned InsertedEndBit = InsertOffset + InsertedRegTy.
getSizeInBits();
702 unsigned EndBit = StartBit +
Size;
703 unsigned NewStartBit;
705 if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
706 SrcRegToUse = ContainerSrcReg;
707 NewStartBit = StartBit;
708 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size);
710 if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
711 SrcRegToUse = InsertedReg;
712 NewStartBit = StartBit - InsertOffset;
713 if (NewStartBit == 0 &&
714 Size ==
MRI.getType(SrcRegToUse).getSizeInBits())
715 CurrentBest = SrcRegToUse;
716 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size);
727 std::optional<DefinitionAndSourceRegister> DefSrcReg =
730 DefReg = DefSrcReg->Reg;
734 switch (Def->getOpcode()) {
735 case TargetOpcode::G_CONCAT_VECTORS:
736 return findValueFromConcat(cast<GConcatVectors>(*Def), StartBit,
Size);
737 case TargetOpcode::G_UNMERGE_VALUES: {
738 unsigned DefStartBit = 0;
739 unsigned DefSize =
MRI.getType(DefReg).getSizeInBits();
740 for (
const auto &MO : Def->defs()) {
741 if (MO.getReg() == DefReg)
743 DefStartBit += DefSize;
745 Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
747 findValueFromDefImpl(SrcReg, StartBit + DefStartBit,
Size);
753 if (StartBit == 0 &&
Size == DefSize)
757 case TargetOpcode::G_BUILD_VECTOR:
758 return findValueFromBuildVector(cast<GBuildVector>(*Def), StartBit,
760 case TargetOpcode::G_INSERT:
761 return findValueFromInsert(*Def, StartBit,
Size);
779 Register FoundReg = findValueFromDefImpl(DefReg, StartBit,
Size);
780 return FoundReg != DefReg ? FoundReg :
Register();
788 unsigned NumDefs =
MI.getNumDefs();
789 LLT DestTy =
MRI.getType(
MI.getReg(0));
792 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
794 if (
MRI.use_nodbg_empty(DefReg)) {
795 DeadDefs[DefIdx] =
true;
801 if (
MRI.getType(FoundVal) != DestTy)
808 MI.getOperand(DefIdx).setReg(DefReg);
810 DeadDefs[DefIdx] =
true;
812 return DeadDefs.
all();
816 unsigned &DefOperandIdx) {
818 if (
auto *Unmerge = dyn_cast<GUnmerge>(
MRI.getVRegDef(Def))) {
819 DefOperandIdx = Unmerge->findRegisterDefOperandIdx(Def);
830 GUnmerge *Unmerge,
unsigned UnmergeIdxStart,
831 unsigned NumElts,
unsigned EltSize) {
832 assert(MergeStartIdx + NumElts <=
MI.getNumSources());
833 for (
unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
834 unsigned EltUnmergeIdx;
836 MI.getSourceReg(i), EltSize, EltUnmergeIdx);
838 if (!EltUnmerge || EltUnmerge != Unmerge)
841 if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
852 LLT EltTy =
MRI.getType(Elt0);
855 unsigned Elt0UnmergeIdx;
861 unsigned NumMIElts =
MI.getNumSources();
863 LLT DstTy =
MRI.getType(Dst);
864 Register UnmergeSrc = Unmerge->getSourceReg();
865 LLT UnmergeSrcTy =
MRI.getType(UnmergeSrc);
874 if ((DstTy == UnmergeSrcTy) && (Elt0UnmergeIdx == 0)) {
893 (Elt0UnmergeIdx % NumMIElts == 0) &&
894 getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
899 auto NewUnmerge = MIB.
buildUnmerge(DstTy, Unmerge->getSourceReg());
900 unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.
getSizeInBits();
902 UpdatedDefs, Observer);
920 unsigned NumElts = Unmerge->getNumDefs();
921 for (
unsigned i = 0; i <
MI.getNumSources(); i += NumElts) {
922 unsigned EltUnmergeIdx;
924 EltSize, EltUnmergeIdx);
926 if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
927 (EltUnmergeIdx != 0))
931 ConcatSources.
push_back(UnmergeI->getSourceReg());
948 unsigned NumDefs =
MI.getNumDefs();
954 LLT OpTy =
MRI.getType(SrcReg);
955 LLT DestTy =
MRI.getType(
MI.getReg(0));
962 markInstAndDefDead(
MI, *SrcDef, DeadInsts, SrcDefIdx);
966 if (
auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
972 Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
973 LLT SrcUnmergeSrcTy =
MRI.getType(SrcUnmergeSrc);
979 {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
980 switch (ActionStep.
Action) {
993 auto NewUnmerge =
Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
998 for (
unsigned I = 0;
I != NumDefs; ++
I) {
1004 markInstAndDefDead(
MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1009 unsigned ConvertOp = 0;
1013 if (isArtifactCast(
SrcOp)) {
1019 ConvertOp, OpTy, DestTy)) {
1027 if (NumMergeRegs < NumDefs) {
1028 if (NumDefs % NumMergeRegs != 0)
1039 const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1040 for (
unsigned Idx = 0;
Idx < NumMergeRegs; ++
Idx) {
1042 for (
unsigned j = 0, DefIdx =
Idx * NewNumDefs; j < NewNumDefs;
1052 LLT MergeEltTy = MergeSrcTy.
divide(NewNumDefs);
1069 for (
unsigned k = 0; k < NewNumDefs; ++k)
1070 TmpRegs[k] =
MRI.createGenericVirtualRegister(MergeEltTy);
1074 for (
unsigned k = 0; k < NewNumDefs; ++k)
1075 Builder.buildInstr(ConvertOp, {DstRegs[k]}, {TmpRegs[k]});
1082 }
else if (NumMergeRegs > NumDefs) {
1083 if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1094 const unsigned NumRegs = NumMergeRegs / NumDefs;
1095 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1097 for (
unsigned j = 0,
Idx = NumRegs * DefIdx + 1; j < NumRegs;
1102 Builder.buildMergeLikeInstr(DefReg, Regs);
1109 if (!ConvertOp && DestTy != MergeSrcTy)
1110 ConvertOp = TargetOpcode::G_BITCAST;
1115 for (
unsigned Idx = 0;
Idx < NumDefs; ++
Idx) {
1119 if (!
MRI.use_empty(DefReg)) {
1120 Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1125 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1129 assert(DestTy == MergeSrcTy &&
1130 "Bitcast and the other kinds of conversions should "
1131 "have happened earlier");
1134 for (
unsigned Idx = 0;
Idx < NumDefs; ++
Idx) {
1142 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1149 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT);
1163 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
1165 if (!MergeI || !isa<GMergeLikeInstr>(MergeI))
1169 LLT DstTy =
MRI.getType(DstReg);
1170 LLT SrcTy =
MRI.getType(SrcReg);
1174 unsigned Offset =
MI.getOperand(2).getImm();
1176 unsigned MergeSrcSize = SrcTy.
getSizeInBits() / NumMergeSrcs;
1177 unsigned MergeSrcIdx =
Offset / MergeSrcSize;
1180 unsigned EndMergeSrcIdx = (
Offset + ExtractDstSize - 1) / MergeSrcSize;
1183 if (MergeSrcIdx != EndMergeSrcIdx)
1189 Offset - MergeSrcIdx * MergeSrcSize);
1191 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1207 if (!DeadInsts.
empty())
1208 deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1215 bool Changed =
false;
1216 switch (
MI.getOpcode()) {
1219 case TargetOpcode::G_ANYEXT:
1222 case TargetOpcode::G_ZEXT:
1225 case TargetOpcode::G_SEXT:
1228 case TargetOpcode::G_UNMERGE_VALUES:
1230 UpdatedDefs, WrapperObserver);
1232 case TargetOpcode::G_MERGE_VALUES:
1233 case TargetOpcode::G_BUILD_VECTOR:
1234 case TargetOpcode::G_CONCAT_VECTORS:
1238 if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1239 U.getOpcode() == TargetOpcode::G_TRUNC) {
1245 UpdatedDefs, WrapperObserver);
1247 case TargetOpcode::G_EXTRACT:
1250 case TargetOpcode::G_TRUNC:
1265 while (!UpdatedDefs.
empty()) {
1269 switch (
Use.getOpcode()) {
1271 case TargetOpcode::G_ANYEXT:
1272 case TargetOpcode::G_ZEXT:
1273 case TargetOpcode::G_SEXT:
1274 case TargetOpcode::G_UNMERGE_VALUES:
1275 case TargetOpcode::G_EXTRACT:
1276 case TargetOpcode::G_TRUNC:
1277 case TargetOpcode::G_BUILD_VECTOR:
1281 case TargetOpcode::COPY: {
1283 if (Copy.isVirtual())
1300 switch (
MI.getOpcode()) {
1301 case TargetOpcode::COPY:
1302 case TargetOpcode::G_TRUNC:
1303 case TargetOpcode::G_ZEXT:
1304 case TargetOpcode::G_ANYEXT:
1305 case TargetOpcode::G_SEXT:
1306 case TargetOpcode::G_EXTRACT:
1307 return MI.getOperand(1).getReg();
1308 case TargetOpcode::G_UNMERGE_VALUES:
1309 return MI.getOperand(
MI.getNumOperands() - 1).getReg();
1322 unsigned DefIdx = 0) {
1333 while (PrevMI != &
DefMI) {
1334 Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1337 if (
MRI.hasOneUse(PrevRegSrc)) {
1338 if (TmpDef != &
DefMI) {
1341 "Expecting copy or artifact cast here");
1350 if (PrevMI == &
DefMI) {
1355 if (!
MRI.use_empty(
Def.getReg())) {
1360 if (!
MRI.hasOneUse(
DefMI.getOperand(DefIdx).getReg()))
1379 unsigned DefIdx = 0) {
1381 markDefDead(
MI,
DefMI, DeadInsts, DefIdx);
1392 for (
auto *DeadMI : DeadInsts) {
1395 DeadMI->eraseFromParent();
1403 using namespace LegalizeActions;
1412 bool isConstantUnsupported(
LLT Ty)
const {
1414 return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1417 return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1418 isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
1428 if (
MRI.getType(TmpReg).isValid())
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This contains common code to allow clients to notify changes to machine instr.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
Interface for Targets to specify which operations they can successfully select and how the others sho...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the SmallBitVector class.
static constexpr int Concat[]
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
APInt zext(unsigned width) const
Zero extend to a new width.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Represents a G_BUILD_VECTOR.
Represents a G_CONCAT_VECTORS.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Simple wrapper observer that takes several observers, and calls each one for each event.
void changedInstr(MachineInstr &MI) override
This instruction was mutated in some way.
void changingInstr(MachineInstr &MI) override
This instruction is about to be mutated in some way.
void erasingInstr(MachineInstr &MI) override
An instruction is about to be erased.
Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES.
Register getSourceReg(unsigned I) const
Returns the I'th source register.
unsigned getNumSources() const
Returns the number of source registers.
Represents a G_UNMERGE_VALUES.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr LLT getScalarType() const
constexpr LLT divide(int Factor) const
Return a type that is Factor times smaller.
This class provides utilities for finding source registers of specific bit ranges in an artifact.
bool tryCombineUnmergeDefs(GUnmerge &MI, GISelChangeObserver &Observer, SmallVectorImpl< Register > &UpdatedDefs)
Try to combine the defs of an unmerge MI by attempting to find values that provides the bits for each...
Register findValueFromDef(Register DefReg, unsigned StartBit, unsigned Size)
Try to find a source of the value defined in the def DefReg, starting at position StartBit with size ...
GUnmerge * findUnmergeThatDefinesReg(Register Reg, unsigned Size, unsigned &DefOperandIdx)
bool tryCombineMergeLike(GMergeLikeInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
bool isSequenceFromUnmerge(GMergeLikeInstr &MI, unsigned MergeStartIdx, GUnmerge *Unmerge, unsigned UnmergeIdxStart, unsigned NumElts, unsigned EltSize)
ArtifactValueFinder(MachineRegisterInfo &Mri, MachineIRBuilder &Builder, const LegalizerInfo &Info)
bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI)
bool tryCombineZExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
bool tryCombineInstruction(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, GISelObserverWrapper &WrapperObserver)
Try to combine away MI.
bool tryCombineTrunc(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp, LLT OpTy, LLT DestTy)
bool tryCombineSExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef)
Return the operand index in MI that defines Def.
static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI, MachineIRBuilder &Builder, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
Try to replace DstReg with SrcReg or build a COPY instruction depending on the register constraints.
bool tryCombineUnmergeValues(GUnmerge &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
bool tryCombineExtract(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
bool tryFoldImplicitDef(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
bool tryCombineAnyExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
Helper class to build MachineInstr.
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ... = G_UNMERGE_VALUES Op.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool all() const
Returns true if all bits are set.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Unsupported
This operation is completely unsupported on the target.
@ NotFound
Sentinel value for when no action was found in the specified table.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Unsupported
This operation is completely unsupported on the target.
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
operand_type_match m_Reg()
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI)
Check if DstReg can be replaced with SrcReg depending on the register constraints.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_READNONE LLT getCoverTy(LLT OrigTy, LLT TargetTy)
Return smallest type that covers both OrigTy and TargetTy and is multiple of TargetTy.
std::optional< DefinitionAndSourceRegister > getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, and underlying value Register folding away any copies.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
LegalizeAction Action
The action to take or the final answer.
unsigned TypeIdx
If describing an action, the type index to change. Otherwise zero.