14#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
15#define LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
31#define DEBUG_TYPE "legalizer"
40 static bool isArtifactCast(
unsigned Opc) {
42 case TargetOpcode::G_TRUNC:
43 case TargetOpcode::G_SEXT:
44 case TargetOpcode::G_ZEXT:
45 case TargetOpcode::G_ANYEXT:
56 : Builder(
B),
MRI(
MRI), LI(LI), KB(KB) {}
63 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT);
67 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
71 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
73 if (
MRI.getType(DstReg) ==
MRI.getType(TruncSrc))
79 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
86 if (mi_match(SrcReg,
MRI,
87 m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
88 m_GSExt(m_Reg(ExtSrc)),
89 m_GZExt(m_Reg(ExtSrc)))))) {
92 markInstAndDefDead(
MI, *ExtMI, DeadInsts);
97 auto *SrcMI =
MRI.getVRegDef(SrcReg);
98 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
99 const LLT DstTy =
MRI.getType(DstReg);
100 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
101 auto &CstVal = SrcMI->getOperand(1);
103 DstReg, CstVal.getCImm()->getValue().sext(DstTy.
getSizeInBits()));
105 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
117 assert(
MI.getOpcode() == TargetOpcode::G_ZEXT);
121 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
127 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc))) ||
128 mi_match(SrcReg,
MRI, m_GSExt(m_Reg(SextSrc)))) {
129 LLT DstTy =
MRI.getType(DstReg);
130 if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
131 isConstantUnsupported(DstTy))
134 LLT SrcTy =
MRI.getType(SrcReg);
136 if (SextSrc && (DstTy !=
MRI.getType(SextSrc)))
138 if (TruncSrc && (DstTy !=
MRI.getType(TruncSrc)))
141 Register AndSrc = SextSrc ? SextSrc : TruncSrc;
148 if (KB && (KB->
getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
153 Builder.
buildAnd(DstReg, AndSrc, Mask);
155 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
161 if (mi_match(SrcReg,
MRI, m_GZExt(m_Reg(ZextSrc)))) {
164 MI.getOperand(1).setReg(ZextSrc);
167 markDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
172 auto *SrcMI =
MRI.getVRegDef(SrcReg);
173 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
174 const LLT DstTy =
MRI.getType(DstReg);
175 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
176 auto &CstVal = SrcMI->getOperand(1);
178 DstReg, CstVal.getCImm()->getValue().zext(DstTy.
getSizeInBits()));
180 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
191 assert(
MI.getOpcode() == TargetOpcode::G_SEXT);
195 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
199 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
200 LLT DstTy =
MRI.getType(DstReg);
201 if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))
204 LLT SrcTy =
MRI.getType(SrcReg);
205 uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
206 if (DstTy !=
MRI.getType(TruncSrc))
209 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
217 if (mi_match(SrcReg,
MRI,
218 m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)),
219 m_GSExt(m_Reg(ExtSrc)))))) {
223 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
228 auto *SrcMI =
MRI.getVRegDef(SrcReg);
229 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
230 const LLT DstTy =
MRI.getType(DstReg);
231 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
232 auto &CstVal = SrcMI->getOperand(1);
234 DstReg, CstVal.getCImm()->getValue().sext(DstTy.
getSizeInBits()));
236 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
249 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
253 const LLT DstTy =
MRI.getType(DstReg);
254 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
257 auto *SrcMI =
MRI.getVRegDef(SrcReg);
258 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
259 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
260 auto &CstVal = SrcMI->getOperand(1);
262 DstReg, CstVal.getCImm()->getValue().trunc(DstTy.
getSizeInBits()));
264 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
271 if (
auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
272 const Register MergeSrcReg = SrcMerge->getSourceReg(0);
273 const LLT MergeSrcTy =
MRI.getType(MergeSrcReg);
281 if (DstSize < MergeSrcSize) {
284 if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
287 LLVM_DEBUG(
dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
292 }
else if (DstSize == MergeSrcSize) {
295 dbgs() <<
"Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
299 }
else if (DstSize % MergeSrcSize == 0) {
302 if (isInstUnsupported(
303 {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
307 dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
310 const unsigned NumSrcs = DstSize / MergeSrcSize;
311 assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
312 "trunc(merge) should require less inputs than merge");
314 for (
unsigned i = 0; i < NumSrcs; ++i)
315 SrcRegs[i] = SrcMerge->getSourceReg(i);
324 markInstAndDefDead(
MI, *SrcMerge, DeadInsts);
330 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
338 markInstAndDefDead(
MI, *
MRI.getVRegDef(TruncSrc), DeadInsts);
346 LLT FoundRegTy =
MRI.getType(FoundReg);
347 if (DstTy == FoundRegTy) {
348 LLVM_DEBUG(
dbgs() <<
".. Combine G_TRUNC(G_[S,Z,ANY]EXT/G_TRUNC...): "
354 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
366 unsigned Opcode =
MI.getOpcode();
367 assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
368 Opcode == TargetOpcode::G_SEXT);
371 MI.getOperand(1).getReg(),
MRI)) {
374 LLT DstTy =
MRI.getType(DstReg);
376 if (Opcode == TargetOpcode::G_ANYEXT) {
378 if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
381 Builder.
buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
386 if (isConstantUnsupported(DstTy))
393 markInstAndDefDead(
MI, *
DefMI, DeadInsts);
403 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
405 const unsigned CastOpc = CastMI.
getOpcode();
407 if (!isArtifactCast(CastOpc))
410 const unsigned NumDefs =
MI.getNumOperands() - 1;
413 const LLT CastSrcTy =
MRI.getType(CastSrcReg);
414 const LLT DestTy =
MRI.getType(
MI.getOperand(0).getReg());
415 const LLT SrcTy =
MRI.getType(
MI.getOperand(NumDefs).getReg());
420 if (CastOpc == TargetOpcode::G_TRUNC) {
431 unsigned UnmergeNumElts =
438 if (isInstUnsupported(
439 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}) ||
440 LI.
getAction({TargetOpcode::G_TRUNC, {SrcWideTy, UnmergeTy}})
445 auto NewUnmerge = Builder.
buildUnmerge(UnmergeTy, CastSrcReg);
447 for (
unsigned I = 0;
I != NumDefs; ++
I) {
453 markInstAndDefDead(
MI, CastMI, DeadInsts);
465 if (CastSrcSize % DestSize != 0)
469 if (isInstUnsupported(
470 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
475 const unsigned NewNumDefs = CastSrcSize / DestSize;
477 for (
unsigned Idx = 0;
Idx < NewNumDefs; ++
Idx) {
479 DstRegs[
Idx] =
MI.getOperand(
Idx).getReg();
481 DstRegs[
Idx] =
MRI.createGenericVirtualRegister(DestTy);
488 markInstAndDefDead(
MI, CastMI, DeadInsts);
503 case TargetOpcode::G_BUILD_VECTOR:
504 case TargetOpcode::G_MERGE_VALUES:
531 case TargetOpcode::G_CONCAT_VECTORS: {
542 if (ConvertOp == TargetOpcode::G_TRUNC)
563 for (
auto &
UseMI :
MRI.use_instructions(DstReg)) {
568 MRI.replaceRegWith(DstReg, SrcReg);
571 for (
auto *
UseMI : UseMIs)
579 if (Def.getReg() == SearchDef)
610 unsigned SrcSize =
MRI.getType(Src1Reg).getSizeInBits();
613 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
615 unsigned InRegOffset = StartBit % SrcSize;
619 if (InRegOffset +
Size > SrcSize)
623 if (InRegOffset == 0 &&
Size == SrcSize) {
624 CurrentBest = SrcReg;
625 return findValueFromDefImpl(SrcReg, 0,
Size);
628 return findValueFromDefImpl(SrcReg, InRegOffset,
Size);
642 unsigned SrcSize =
MRI.getType(Src1Reg).getSizeInBits();
645 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
647 unsigned InRegOffset = StartBit % SrcSize;
649 if (InRegOffset != 0)
656 if (
Size > SrcSize) {
657 if (
Size % SrcSize > 0)
660 unsigned NumSrcsUsed =
Size / SrcSize;
665 LLT SrcTy =
MRI.getType(Src1Reg);
666 LLT NewBVTy = LLT::fixed_vector(NumSrcsUsed, SrcTy);
670 LI.
getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
671 if (ActionStep.
Action != LegalizeActions::Legal)
675 for (
unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
682 return BV.
getReg(StartSrcIdx);
692 assert(
MI.getOpcode() == TargetOpcode::G_INSERT);
695 Register ContainerSrcReg =
MI.getOperand(1).getReg();
696 Register InsertedReg =
MI.getOperand(2).getReg();
697 LLT InsertedRegTy =
MRI.getType(InsertedReg);
698 unsigned InsertOffset =
MI.getOperand(3).getImm();
736 unsigned InsertedEndBit = InsertOffset + InsertedRegTy.
getSizeInBits();
737 unsigned EndBit = StartBit +
Size;
738 unsigned NewStartBit;
740 if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
741 SrcRegToUse = ContainerSrcReg;
742 NewStartBit = StartBit;
743 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size);
745 if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
746 SrcRegToUse = InsertedReg;
747 NewStartBit = StartBit - InsertOffset;
748 if (NewStartBit == 0 &&
749 Size ==
MRI.getType(SrcRegToUse).getSizeInBits())
750 CurrentBest = SrcRegToUse;
751 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size);
765 assert(
MI.getOpcode() == TargetOpcode::G_SEXT ||
766 MI.getOpcode() == TargetOpcode::G_ZEXT ||
767 MI.getOpcode() == TargetOpcode::G_ANYEXT);
771 LLT SrcType =
MRI.getType(SrcReg);
778 if (StartBit +
Size > SrcSize)
782 CurrentBest = SrcReg;
783 return findValueFromDefImpl(SrcReg, StartBit,
Size);
793 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
797 LLT SrcType =
MRI.getType(SrcReg);
803 return findValueFromDefImpl(SrcReg, StartBit,
Size);
811 std::optional<DefinitionAndSourceRegister> DefSrcReg =
814 DefReg = DefSrcReg->Reg;
818 switch (Def->getOpcode()) {
819 case TargetOpcode::G_CONCAT_VECTORS:
820 return findValueFromConcat(cast<GConcatVectors>(*Def), StartBit,
Size);
821 case TargetOpcode::G_UNMERGE_VALUES: {
822 unsigned DefStartBit = 0;
823 unsigned DefSize =
MRI.getType(DefReg).getSizeInBits();
824 for (
const auto &MO : Def->defs()) {
825 if (MO.getReg() == DefReg)
827 DefStartBit += DefSize;
829 Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
831 findValueFromDefImpl(SrcReg, StartBit + DefStartBit,
Size);
837 if (StartBit == 0 &&
Size == DefSize)
841 case TargetOpcode::G_BUILD_VECTOR:
842 return findValueFromBuildVector(cast<GBuildVector>(*Def), StartBit,
844 case TargetOpcode::G_INSERT:
845 return findValueFromInsert(*Def, StartBit,
Size);
846 case TargetOpcode::G_TRUNC:
847 return findValueFromTrunc(*Def, StartBit,
Size);
848 case TargetOpcode::G_SEXT:
849 case TargetOpcode::G_ZEXT:
850 case TargetOpcode::G_ANYEXT:
851 return findValueFromExt(*Def, StartBit,
Size);
860 :
MRI(Mri), MIB(Builder), LI(
Info) {}
869 Register FoundReg = findValueFromDefImpl(DefReg, StartBit,
Size);
870 return FoundReg != DefReg ? FoundReg :
Register();
878 unsigned NumDefs =
MI.getNumDefs();
879 LLT DestTy =
MRI.getType(
MI.getReg(0));
882 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
884 if (
MRI.use_nodbg_empty(DefReg)) {
885 DeadDefs[DefIdx] =
true;
891 if (
MRI.getType(FoundVal) != DestTy)
894 replaceRegOrBuildCopy(DefReg, FoundVal,
MRI, MIB, UpdatedDefs,
898 MI.getOperand(DefIdx).setReg(DefReg);
900 DeadDefs[DefIdx] =
true;
902 return DeadDefs.
all();
906 unsigned &DefOperandIdx) {
908 if (
auto *Unmerge = dyn_cast<GUnmerge>(
MRI.getVRegDef(Def))) {
909 DefOperandIdx = Unmerge->findRegisterDefOperandIdx(Def);
920 GUnmerge *Unmerge,
unsigned UnmergeIdxStart,
921 unsigned NumElts,
unsigned EltSize,
923 assert(MergeStartIdx + NumElts <=
MI.getNumSources());
924 for (
unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
925 unsigned EltUnmergeIdx;
926 GUnmerge *EltUnmerge = findUnmergeThatDefinesReg(
927 MI.getSourceReg(i), EltSize, EltUnmergeIdx);
929 if (EltUnmerge == Unmerge) {
931 if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
933 }
else if (!AllowUndef ||
934 MRI.getVRegDef(
MI.getSourceReg(i))->getOpcode() !=
935 TargetOpcode::G_IMPLICIT_DEF)
946 LLT EltTy =
MRI.getType(Elt0);
949 unsigned Elt0UnmergeIdx;
951 auto *Unmerge = findUnmergeThatDefinesReg(Elt0, EltSize, Elt0UnmergeIdx);
955 unsigned NumMIElts =
MI.getNumSources();
957 LLT DstTy =
MRI.getType(Dst);
958 Register UnmergeSrc = Unmerge->getSourceReg();
959 LLT UnmergeSrcTy =
MRI.getType(UnmergeSrc);
968 if ((DstTy == UnmergeSrcTy) && (Elt0UnmergeIdx == 0)) {
969 if (!isSequenceFromUnmerge(
MI, 0, Unmerge, 0, NumMIElts, EltSize,
973 replaceRegOrBuildCopy(Dst, UnmergeSrc,
MRI, MIB, UpdatedDefs, Observer);
989 (Elt0UnmergeIdx % NumMIElts == 0) &&
990 getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
991 if (!isSequenceFromUnmerge(
MI, 0, Unmerge, Elt0UnmergeIdx, NumMIElts,
995 auto NewUnmerge = MIB.
buildUnmerge(DstTy, Unmerge->getSourceReg());
996 unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.
getSizeInBits();
997 replaceRegOrBuildCopy(Dst, NewUnmerge.getReg(DstIdx),
MRI, MIB,
998 UpdatedDefs, Observer);
1016 unsigned NumElts = Unmerge->getNumDefs();
1017 for (
unsigned i = 0; i <
MI.getNumSources(); i += NumElts) {
1018 unsigned EltUnmergeIdx;
1019 auto *UnmergeI = findUnmergeThatDefinesReg(
MI.getSourceReg(i),
1020 EltSize, EltUnmergeIdx);
1022 if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
1023 (EltUnmergeIdx != 0))
1025 if (!isSequenceFromUnmerge(
MI, i, UnmergeI, 0, NumElts, EltSize,
1028 ConcatSources.
push_back(UnmergeI->getSourceReg());
1045 unsigned NumDefs =
MI.getNumDefs();
1051 LLT OpTy =
MRI.getType(SrcReg);
1052 LLT DestTy =
MRI.getType(
MI.getReg(0));
1053 unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg);
1055 Builder.setInstrAndDebugLoc(
MI);
1059 markInstAndDefDead(
MI, *SrcDef, DeadInsts, SrcDefIdx);
1063 if (
auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
1069 Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
1070 LLT SrcUnmergeSrcTy =
MRI.getType(SrcUnmergeSrc);
1076 {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
1077 switch (ActionStep.
Action) {
1090 auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
1095 for (
unsigned I = 0;
I != NumDefs; ++
I) {
1097 replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs +
I),
1098 MRI, Builder, UpdatedDefs, Observer);
1101 markInstAndDefDead(
MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1106 unsigned ConvertOp = 0;
1110 if (isArtifactCast(
SrcOp)) {
1115 if (!MergeI || !canFoldMergeOpcode(MergeI->
getOpcode(),
1116 ConvertOp, OpTy, DestTy)) {
1119 return tryFoldUnmergeCast(
MI, *SrcDef, DeadInsts, UpdatedDefs);
1124 if (NumMergeRegs < NumDefs) {
1125 if (NumDefs % NumMergeRegs != 0)
1128 Builder.setInstr(
MI);
1136 const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1137 for (
unsigned Idx = 0;
Idx < NumMergeRegs; ++
Idx) {
1139 for (
unsigned j = 0, DefIdx =
Idx * NewNumDefs; j < NewNumDefs;
1149 LLT MergeEltTy = MergeDstTy.
divide(NumMergeRegs);
1164 Register TmpReg =
MRI.createGenericVirtualRegister(MergeEltTy);
1165 Builder.buildInstr(ConvertOp, {TmpReg},
1167 Builder.buildUnmerge(DstRegs, TmpReg);
1174 }
else if (NumMergeRegs > NumDefs) {
1175 if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1178 Builder.setInstr(
MI);
1186 const unsigned NumRegs = NumMergeRegs / NumDefs;
1187 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1189 for (
unsigned j = 0,
Idx = NumRegs * DefIdx + 1; j < NumRegs;
1194 Builder.buildMergeLikeInstr(DefReg, Regs);
1201 if (!ConvertOp && DestTy != MergeSrcTy)
1202 ConvertOp = TargetOpcode::G_BITCAST;
1205 Builder.setInstr(
MI);
1207 for (
unsigned Idx = 0;
Idx < NumDefs; ++
Idx) {
1211 if (!
MRI.use_empty(DefReg)) {
1212 Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1217 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1221 assert(DestTy == MergeSrcTy &&
1222 "Bitcast and the other kinds of conversions should "
1223 "have happened earlier");
1225 Builder.setInstr(
MI);
1226 for (
unsigned Idx = 0;
Idx < NumDefs; ++
Idx) {
1229 replaceRegOrBuildCopy(DstReg, SrcReg,
MRI, Builder, UpdatedDefs,
1234 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1241 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT);
1255 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
1257 if (!MergeI || !isa<GMergeLikeInstr>(MergeI))
1261 LLT DstTy =
MRI.getType(DstReg);
1262 LLT SrcTy =
MRI.getType(SrcReg);
1266 unsigned Offset =
MI.getOperand(2).getImm();
1268 unsigned MergeSrcSize = SrcTy.
getSizeInBits() / NumMergeSrcs;
1269 unsigned MergeSrcIdx =
Offset / MergeSrcSize;
1272 unsigned EndMergeSrcIdx = (
Offset + ExtractDstSize - 1) / MergeSrcSize;
1275 if (MergeSrcIdx != EndMergeSrcIdx)
1279 Builder.setInstr(
MI);
1281 Offset - MergeSrcIdx * MergeSrcSize);
1283 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1299 if (!DeadInsts.
empty())
1300 deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1307 bool Changed =
false;
1308 switch (
MI.getOpcode()) {
1311 case TargetOpcode::G_ANYEXT:
1312 Changed = tryCombineAnyExt(
MI, DeadInsts, UpdatedDefs, WrapperObserver);
1314 case TargetOpcode::G_ZEXT:
1315 Changed = tryCombineZExt(
MI, DeadInsts, UpdatedDefs, WrapperObserver);
1317 case TargetOpcode::G_SEXT:
1318 Changed = tryCombineSExt(
MI, DeadInsts, UpdatedDefs);
1320 case TargetOpcode::G_UNMERGE_VALUES:
1321 Changed = tryCombineUnmergeValues(cast<GUnmerge>(
MI), DeadInsts,
1322 UpdatedDefs, WrapperObserver);
1324 case TargetOpcode::G_MERGE_VALUES:
1325 case TargetOpcode::G_BUILD_VECTOR:
1326 case TargetOpcode::G_CONCAT_VECTORS:
1330 if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1331 U.getOpcode() == TargetOpcode::G_TRUNC) {
1337 UpdatedDefs, WrapperObserver);
1339 case TargetOpcode::G_EXTRACT:
1340 Changed = tryCombineExtract(
MI, DeadInsts, UpdatedDefs);
1342 case TargetOpcode::G_TRUNC:
1343 Changed = tryCombineTrunc(
MI, DeadInsts, UpdatedDefs, WrapperObserver);
1357 while (!UpdatedDefs.
empty()) {
1361 switch (
Use.getOpcode()) {
1363 case TargetOpcode::G_ANYEXT:
1364 case TargetOpcode::G_ZEXT:
1365 case TargetOpcode::G_SEXT:
1366 case TargetOpcode::G_UNMERGE_VALUES:
1367 case TargetOpcode::G_EXTRACT:
1368 case TargetOpcode::G_TRUNC:
1369 case TargetOpcode::G_BUILD_VECTOR:
1373 case TargetOpcode::G_ASSERT_SEXT:
1374 case TargetOpcode::G_ASSERT_ZEXT:
1375 case TargetOpcode::G_ASSERT_ALIGN:
1376 case TargetOpcode::COPY: {
1378 if (Copy.isVirtual())
1395 switch (
MI.getOpcode()) {
1396 case TargetOpcode::COPY:
1397 case TargetOpcode::G_TRUNC:
1398 case TargetOpcode::G_ZEXT:
1399 case TargetOpcode::G_ANYEXT:
1400 case TargetOpcode::G_SEXT:
1401 case TargetOpcode::G_EXTRACT:
1402 case TargetOpcode::G_ASSERT_SEXT:
1403 case TargetOpcode::G_ASSERT_ZEXT:
1404 case TargetOpcode::G_ASSERT_ALIGN:
1405 return MI.getOperand(1).getReg();
1406 case TargetOpcode::G_UNMERGE_VALUES:
1407 return MI.getOperand(
MI.getNumOperands() - 1).getReg();
1420 unsigned DefIdx = 0) {
1431 while (PrevMI != &
DefMI) {
1432 Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1435 if (
MRI.hasOneUse(PrevRegSrc)) {
1436 if (TmpDef != &
DefMI) {
1440 "Expecting copy or artifact cast here");
1449 if (PrevMI == &
DefMI) {
1454 if (!
MRI.use_empty(
Def.getReg())) {
1478 unsigned DefIdx = 0) {
1480 markDefDead(
MI,
DefMI, DeadInsts, DefIdx);
1491 for (
auto *DeadMI : DeadInsts) {
1494 DeadMI->eraseFromParent();
1502 using namespace LegalizeActions;
1503 auto Step = LI.getAction(Query);
1511 bool isConstantUnsupported(
LLT Ty)
const {
1513 return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1516 return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1517 isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
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.
Promote Memory to Register
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
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.
APInt getKnownZeroes(Register R)
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.
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...
bool isSequenceFromUnmerge(GMergeLikeInstr &MI, unsigned MergeStartIdx, GUnmerge *Unmerge, unsigned UnmergeIdxStart, unsigned NumElts, unsigned EltSize, bool AllowUndef)
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)
ArtifactValueFinder(MachineRegisterInfo &Mri, MachineIRBuilder &Builder, const LegalizerInfo &Info)
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI, GISelKnownBits *KB=nullptr)
bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
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 buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Res = COPY Op depending on the differing sizes of Res and Op.
MachineInstrBuilder buildSExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_SEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
void setInstr(MachineInstr &MI)
Set the insertion point to before MI.
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...
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
MachineInstrBuilder buildMergeValues(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ...
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
MachineInstrBuilder buildSExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and insert Res = G_SEXT_INREG Op, ImmOp.
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.
constexpr bool isValid() const
constexpr 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.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
NodeAddr< DefNode * > Def
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 isPreISelGenericOptimizationHint(unsigned Opcode)
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.
Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial 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.