14#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
15#define LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
32#define DEBUG_TYPE "legalizer"
41 static bool isArtifactCast(
unsigned Opc) {
43 case TargetOpcode::G_TRUNC:
44 case TargetOpcode::G_SEXT:
45 case TargetOpcode::G_ZEXT:
46 case TargetOpcode::G_ANYEXT:
57 : Builder(
B),
MRI(
MRI), LI(LI), KB(KB) {}
64 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT);
68 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
72 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
74 if (
MRI.getType(DstReg) ==
MRI.getType(TruncSrc))
80 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
87 if (mi_match(SrcReg,
MRI,
88 m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)),
89 m_GSExt(m_Reg(ExtSrc)),
90 m_GZExt(m_Reg(ExtSrc)))))) {
93 markInstAndDefDead(
MI, *ExtMI, DeadInsts);
98 auto *SrcMI =
MRI.getVRegDef(SrcReg);
99 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
100 const LLT DstTy =
MRI.getType(DstReg);
101 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
102 auto &CstVal = SrcMI->getOperand(1);
104 MI.getDebugLoc().get(), SrcMI->getDebugLoc().get());
109 DstReg, CstVal.getCImm()->getValue().sext(DstTy.
getSizeInBits()));
111 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
123 assert(
MI.getOpcode() == TargetOpcode::G_ZEXT);
127 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
133 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc))) ||
134 mi_match(SrcReg,
MRI, m_GSExt(m_Reg(SextSrc)))) {
135 LLT DstTy =
MRI.getType(DstReg);
136 if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
137 isConstantUnsupported(DstTy))
140 LLT SrcTy =
MRI.getType(SrcReg);
142 if (SextSrc && (DstTy !=
MRI.getType(SextSrc)))
144 if (TruncSrc && (DstTy !=
MRI.getType(TruncSrc)))
147 Register AndSrc = SextSrc ? SextSrc : TruncSrc;
154 if (KB && (KB->
getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
159 Builder.
buildAnd(DstReg, AndSrc, Mask);
161 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
167 if (mi_match(SrcReg,
MRI, m_GZExt(m_Reg(ZextSrc)))) {
170 MI.getOperand(1).setReg(ZextSrc);
173 markDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
178 auto *SrcMI =
MRI.getVRegDef(SrcReg);
179 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
180 const LLT DstTy =
MRI.getType(DstReg);
181 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
182 auto &CstVal = SrcMI->getOperand(1);
184 DstReg, CstVal.getCImm()->getValue().zext(DstTy.
getSizeInBits()));
186 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
198 assert(
MI.getOpcode() == TargetOpcode::G_SEXT);
202 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
206 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
207 LLT DstTy =
MRI.getType(DstReg);
208 if (isInstUnsupported({TargetOpcode::G_SEXT_INREG, {DstTy}}))
211 LLT SrcTy =
MRI.getType(SrcReg);
212 uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
213 if (DstTy !=
MRI.getType(TruncSrc))
223 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
231 if (mi_match(SrcReg,
MRI,
232 m_all_of(m_MInstr(ExtMI), m_any_of(m_GZExt(m_Reg(ExtSrc)),
233 m_GSExt(m_Reg(ExtSrc)))))) {
237 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
242 auto *SrcMI =
MRI.getVRegDef(SrcReg);
243 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
244 const LLT DstTy =
MRI.getType(DstReg);
245 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
246 auto &CstVal = SrcMI->getOperand(1);
248 DstReg, CstVal.getCImm()->getValue().sext(DstTy.
getSizeInBits()));
250 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
263 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
267 const LLT DstTy =
MRI.getType(DstReg);
268 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
271 auto *SrcMI =
MRI.getVRegDef(SrcReg);
272 if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
273 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
274 auto &CstVal = SrcMI->getOperand(1);
276 DstReg, CstVal.getCImm()->getValue().trunc(DstTy.
getSizeInBits()));
278 markInstAndDefDead(
MI, *SrcMI, DeadInsts);
285 if (
auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
286 const Register MergeSrcReg = SrcMerge->getSourceReg(0);
287 const LLT MergeSrcTy =
MRI.getType(MergeSrcReg);
295 if (DstSize < MergeSrcSize) {
298 if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
301 LLVM_DEBUG(
dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
306 }
else if (DstSize == MergeSrcSize) {
309 dbgs() <<
"Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
313 }
else if (DstSize % MergeSrcSize == 0) {
316 if (isInstUnsupported(
317 {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
321 dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
324 const unsigned NumSrcs = DstSize / MergeSrcSize;
325 assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
326 "trunc(merge) should require less inputs than merge");
328 for (
unsigned i = 0; i < NumSrcs; ++i)
329 SrcRegs[i] = SrcMerge->getSourceReg(i);
338 markInstAndDefDead(
MI, *SrcMerge, DeadInsts);
344 if (mi_match(SrcReg,
MRI, m_GTrunc(m_Reg(TruncSrc)))) {
352 markInstAndDefDead(
MI, *
MRI.getVRegDef(TruncSrc), DeadInsts);
360 LLT FoundRegTy =
MRI.getType(FoundReg);
361 if (DstTy == FoundRegTy) {
362 LLVM_DEBUG(
dbgs() <<
".. Combine G_TRUNC(G_[S,Z,ANY]EXT/G_TRUNC...): "
368 markInstAndDefDead(
MI, *
MRI.getVRegDef(SrcReg), DeadInsts);
380 unsigned Opcode =
MI.getOpcode();
381 assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
382 Opcode == TargetOpcode::G_SEXT);
385 MI.getOperand(1).getReg(),
MRI)) {
388 LLT DstTy =
MRI.getType(DstReg);
390 if (Opcode == TargetOpcode::G_ANYEXT) {
392 if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
395 Builder.
buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
400 if (isConstantUnsupported(DstTy))
407 markInstAndDefDead(
MI, *
DefMI, DeadInsts);
417 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
419 const unsigned CastOpc = CastMI.
getOpcode();
421 if (!isArtifactCast(CastOpc))
424 const unsigned NumDefs =
MI.getNumOperands() - 1;
427 const LLT CastSrcTy =
MRI.getType(CastSrcReg);
428 const LLT DestTy =
MRI.getType(
MI.getOperand(0).getReg());
429 const LLT SrcTy =
MRI.getType(
MI.getOperand(NumDefs).getReg());
434 if (CastOpc == TargetOpcode::G_TRUNC) {
445 unsigned UnmergeNumElts =
452 if (isInstUnsupported(
453 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}) ||
454 LI.
getAction({TargetOpcode::G_TRUNC, {SrcWideTy, UnmergeTy}})
459 auto NewUnmerge = Builder.
buildUnmerge(UnmergeTy, CastSrcReg);
461 for (
unsigned I = 0;
I != NumDefs; ++
I) {
467 markInstAndDefDead(
MI, CastMI, DeadInsts);
479 if (CastSrcSize % DestSize != 0)
483 if (isInstUnsupported(
484 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
489 const unsigned NewNumDefs = CastSrcSize / DestSize;
491 for (
unsigned Idx = 0;
Idx < NewNumDefs; ++
Idx) {
493 DstRegs[
Idx] =
MI.getOperand(
Idx).getReg();
495 DstRegs[
Idx] =
MRI.createGenericVirtualRegister(DestTy);
502 markInstAndDefDead(
MI, CastMI, DeadInsts);
517 case TargetOpcode::G_BUILD_VECTOR:
518 case TargetOpcode::G_MERGE_VALUES:
545 case TargetOpcode::G_CONCAT_VECTORS: {
556 if (ConvertOp == TargetOpcode::G_TRUNC)
577 for (
auto &
UseMI :
MRI.use_instructions(DstReg)) {
582 MRI.replaceRegWith(DstReg, SrcReg);
585 for (
auto *
UseMI : UseMIs)
593 if (Def.getReg() == SearchDef)
624 unsigned SrcSize =
MRI.getType(Src1Reg).getSizeInBits();
627 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
629 unsigned InRegOffset = StartBit % SrcSize;
633 if (InRegOffset +
Size > SrcSize)
637 if (InRegOffset == 0 &&
Size == SrcSize) {
638 CurrentBest = SrcReg;
639 return findValueFromDefImpl(SrcReg, 0,
Size);
642 return findValueFromDefImpl(SrcReg, InRegOffset,
Size);
656 unsigned SrcSize =
MRI.getType(Src1Reg).getSizeInBits();
659 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
661 unsigned InRegOffset = StartBit % SrcSize;
663 if (InRegOffset != 0)
670 if (
Size > SrcSize) {
671 if (
Size % SrcSize > 0)
674 unsigned NumSrcsUsed =
Size / SrcSize;
679 LLT SrcTy =
MRI.getType(Src1Reg);
680 LLT NewBVTy = LLT::fixed_vector(NumSrcsUsed, SrcTy);
684 LI.
getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
685 if (ActionStep.
Action != LegalizeActions::Legal)
689 for (
unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
696 return BV.
getReg(StartSrcIdx);
706 assert(
MI.getOpcode() == TargetOpcode::G_INSERT);
709 Register ContainerSrcReg =
MI.getOperand(1).getReg();
710 Register InsertedReg =
MI.getOperand(2).getReg();
711 LLT InsertedRegTy =
MRI.getType(InsertedReg);
712 unsigned InsertOffset =
MI.getOperand(3).getImm();
750 unsigned InsertedEndBit = InsertOffset + InsertedRegTy.
getSizeInBits();
751 unsigned EndBit = StartBit +
Size;
752 unsigned NewStartBit;
754 if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
755 SrcRegToUse = ContainerSrcReg;
756 NewStartBit = StartBit;
757 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size);
759 if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
760 SrcRegToUse = InsertedReg;
761 NewStartBit = StartBit - InsertOffset;
762 if (NewStartBit == 0 &&
763 Size ==
MRI.getType(SrcRegToUse).getSizeInBits())
764 CurrentBest = SrcRegToUse;
765 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size);
779 assert(
MI.getOpcode() == TargetOpcode::G_SEXT ||
780 MI.getOpcode() == TargetOpcode::G_ZEXT ||
781 MI.getOpcode() == TargetOpcode::G_ANYEXT);
785 LLT SrcType =
MRI.getType(SrcReg);
792 if (StartBit +
Size > SrcSize)
796 CurrentBest = SrcReg;
797 return findValueFromDefImpl(SrcReg, StartBit,
Size);
807 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
811 LLT SrcType =
MRI.getType(SrcReg);
817 return findValueFromDefImpl(SrcReg, StartBit,
Size);
825 std::optional<DefinitionAndSourceRegister> DefSrcReg =
828 DefReg = DefSrcReg->Reg;
832 switch (Def->getOpcode()) {
833 case TargetOpcode::G_CONCAT_VECTORS:
834 return findValueFromConcat(cast<GConcatVectors>(*Def), StartBit,
Size);
835 case TargetOpcode::G_UNMERGE_VALUES: {
836 unsigned DefStartBit = 0;
837 unsigned DefSize =
MRI.getType(DefReg).getSizeInBits();
838 for (
const auto &MO : Def->defs()) {
839 if (MO.getReg() == DefReg)
841 DefStartBit += DefSize;
843 Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
845 findValueFromDefImpl(SrcReg, StartBit + DefStartBit,
Size);
851 if (StartBit == 0 &&
Size == DefSize)
855 case TargetOpcode::G_BUILD_VECTOR:
856 return findValueFromBuildVector(cast<GBuildVector>(*Def), StartBit,
858 case TargetOpcode::G_INSERT:
859 return findValueFromInsert(*Def, StartBit,
Size);
860 case TargetOpcode::G_TRUNC:
861 return findValueFromTrunc(*Def, StartBit,
Size);
862 case TargetOpcode::G_SEXT:
863 case TargetOpcode::G_ZEXT:
864 case TargetOpcode::G_ANYEXT:
865 return findValueFromExt(*Def, StartBit,
Size);
874 :
MRI(Mri), MIB(Builder), LI(
Info) {}
883 Register FoundReg = findValueFromDefImpl(DefReg, StartBit,
Size);
884 return FoundReg != DefReg ? FoundReg :
Register();
892 unsigned NumDefs =
MI.getNumDefs();
893 LLT DestTy =
MRI.getType(
MI.getReg(0));
896 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
898 if (
MRI.use_nodbg_empty(DefReg)) {
899 DeadDefs[DefIdx] =
true;
905 if (
MRI.getType(FoundVal) != DestTy)
908 replaceRegOrBuildCopy(DefReg, FoundVal,
MRI, MIB, UpdatedDefs,
912 MI.getOperand(DefIdx).setReg(DefReg);
914 DeadDefs[DefIdx] =
true;
916 return DeadDefs.
all();
920 unsigned &DefOperandIdx) {
922 if (
auto *Unmerge = dyn_cast<GUnmerge>(
MRI.getVRegDef(Def))) {
924 Unmerge->findRegisterDefOperandIdx(Def,
nullptr);
935 GUnmerge *Unmerge,
unsigned UnmergeIdxStart,
936 unsigned NumElts,
unsigned EltSize,
938 assert(MergeStartIdx + NumElts <=
MI.getNumSources());
939 for (
unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
940 unsigned EltUnmergeIdx;
941 GUnmerge *EltUnmerge = findUnmergeThatDefinesReg(
942 MI.getSourceReg(i), EltSize, EltUnmergeIdx);
944 if (EltUnmerge == Unmerge) {
946 if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
948 }
else if (!AllowUndef ||
949 MRI.getVRegDef(
MI.getSourceReg(i))->getOpcode() !=
950 TargetOpcode::G_IMPLICIT_DEF)
961 LLT EltTy =
MRI.getType(Elt0);
964 unsigned Elt0UnmergeIdx;
966 auto *Unmerge = findUnmergeThatDefinesReg(Elt0, EltSize, Elt0UnmergeIdx);
970 unsigned NumMIElts =
MI.getNumSources();
972 LLT DstTy =
MRI.getType(Dst);
973 Register UnmergeSrc = Unmerge->getSourceReg();
974 LLT UnmergeSrcTy =
MRI.getType(UnmergeSrc);
983 if ((DstTy == UnmergeSrcTy) && (Elt0UnmergeIdx == 0)) {
984 if (!isSequenceFromUnmerge(
MI, 0, Unmerge, 0, NumMIElts, EltSize,
988 replaceRegOrBuildCopy(Dst, UnmergeSrc,
MRI, MIB, UpdatedDefs, Observer);
1004 (Elt0UnmergeIdx % NumMIElts == 0) &&
1005 getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
1006 if (!isSequenceFromUnmerge(
MI, 0, Unmerge, Elt0UnmergeIdx, NumMIElts,
1010 auto NewUnmerge = MIB.
buildUnmerge(DstTy, Unmerge->getSourceReg());
1011 unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.
getSizeInBits();
1012 replaceRegOrBuildCopy(Dst, NewUnmerge.getReg(DstIdx),
MRI, MIB,
1013 UpdatedDefs, Observer);
1031 unsigned NumElts = Unmerge->getNumDefs();
1032 for (
unsigned i = 0; i <
MI.getNumSources(); i += NumElts) {
1033 unsigned EltUnmergeIdx;
1034 auto *UnmergeI = findUnmergeThatDefinesReg(
MI.getSourceReg(i),
1035 EltSize, EltUnmergeIdx);
1037 if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
1038 (EltUnmergeIdx != 0))
1040 if (!isSequenceFromUnmerge(
MI, i, UnmergeI, 0, NumElts, EltSize,
1043 ConcatSources.
push_back(UnmergeI->getSourceReg());
1060 unsigned NumDefs =
MI.getNumDefs();
1066 LLT OpTy =
MRI.getType(SrcReg);
1067 LLT DestTy =
MRI.getType(
MI.getReg(0));
1068 unsigned SrcDefIdx = getDefIndex(*SrcDef, SrcReg);
1070 Builder.setInstrAndDebugLoc(
MI);
1074 markInstAndDefDead(
MI, *SrcDef, DeadInsts, SrcDefIdx);
1078 if (
auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
1084 Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
1085 LLT SrcUnmergeSrcTy =
MRI.getType(SrcUnmergeSrc);
1091 {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
1092 switch (ActionStep.
Action) {
1105 auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
1110 for (
unsigned I = 0;
I != NumDefs; ++
I) {
1112 replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs +
I),
1113 MRI, Builder, UpdatedDefs, Observer);
1116 markInstAndDefDead(
MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1121 unsigned ConvertOp = 0;
1125 if (isArtifactCast(
SrcOp)) {
1130 if (!MergeI || !canFoldMergeOpcode(MergeI->
getOpcode(),
1131 ConvertOp, OpTy, DestTy)) {
1134 return tryFoldUnmergeCast(
MI, *SrcDef, DeadInsts, UpdatedDefs);
1139 if (NumMergeRegs < NumDefs) {
1140 if (NumDefs % NumMergeRegs != 0)
1143 Builder.setInstr(
MI);
1151 const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1152 for (
unsigned Idx = 0;
Idx < NumMergeRegs; ++
Idx) {
1154 for (
unsigned j = 0, DefIdx =
Idx * NewNumDefs; j < NewNumDefs;
1164 LLT MergeEltTy = MergeDstTy.
divide(NumMergeRegs);
1179 Register TmpReg =
MRI.createGenericVirtualRegister(MergeEltTy);
1180 Builder.buildInstr(ConvertOp, {TmpReg},
1182 Builder.buildUnmerge(DstRegs, TmpReg);
1189 }
else if (NumMergeRegs > NumDefs) {
1190 if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1193 Builder.setInstr(
MI);
1201 const unsigned NumRegs = NumMergeRegs / NumDefs;
1202 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1204 for (
unsigned j = 0,
Idx = NumRegs * DefIdx + 1; j < NumRegs;
1209 Builder.buildMergeLikeInstr(DefReg, Regs);
1216 if (!ConvertOp && DestTy != MergeSrcTy)
1217 ConvertOp = TargetOpcode::G_BITCAST;
1220 Builder.setInstr(
MI);
1222 for (
unsigned Idx = 0;
Idx < NumDefs; ++
Idx) {
1226 if (!
MRI.use_empty(DefReg)) {
1227 Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1232 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1236 assert(DestTy == MergeSrcTy &&
1237 "Bitcast and the other kinds of conversions should "
1238 "have happened earlier");
1240 Builder.setInstr(
MI);
1241 for (
unsigned Idx = 0;
Idx < NumDefs; ++
Idx) {
1244 replaceRegOrBuildCopy(DstReg, SrcReg,
MRI, Builder, UpdatedDefs,
1249 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1256 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT);
1270 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
1272 if (!MergeI || !isa<GMergeLikeInstr>(MergeI))
1276 LLT DstTy =
MRI.getType(DstReg);
1277 LLT SrcTy =
MRI.getType(SrcReg);
1281 unsigned Offset =
MI.getOperand(2).getImm();
1283 unsigned MergeSrcSize = SrcTy.
getSizeInBits() / NumMergeSrcs;
1284 unsigned MergeSrcIdx =
Offset / MergeSrcSize;
1287 unsigned EndMergeSrcIdx = (
Offset + ExtractDstSize - 1) / MergeSrcSize;
1290 if (MergeSrcIdx != EndMergeSrcIdx)
1294 Builder.setInstr(
MI);
1296 Offset - MergeSrcIdx * MergeSrcSize);
1298 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1314 if (!DeadInsts.
empty())
1315 deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1322 bool Changed =
false;
1323 switch (
MI.getOpcode()) {
1326 case TargetOpcode::G_ANYEXT:
1327 Changed = tryCombineAnyExt(
MI, DeadInsts, UpdatedDefs, WrapperObserver);
1329 case TargetOpcode::G_ZEXT:
1330 Changed = tryCombineZExt(
MI, DeadInsts, UpdatedDefs, WrapperObserver);
1332 case TargetOpcode::G_SEXT:
1333 Changed = tryCombineSExt(
MI, DeadInsts, UpdatedDefs, WrapperObserver);
1335 case TargetOpcode::G_UNMERGE_VALUES:
1336 Changed = tryCombineUnmergeValues(cast<GUnmerge>(
MI), DeadInsts,
1337 UpdatedDefs, WrapperObserver);
1339 case TargetOpcode::G_MERGE_VALUES:
1340 case TargetOpcode::G_BUILD_VECTOR:
1341 case TargetOpcode::G_CONCAT_VECTORS:
1345 if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1346 U.getOpcode() == TargetOpcode::G_TRUNC) {
1352 UpdatedDefs, WrapperObserver);
1354 case TargetOpcode::G_EXTRACT:
1355 Changed = tryCombineExtract(
MI, DeadInsts, UpdatedDefs);
1357 case TargetOpcode::G_TRUNC:
1358 Changed = tryCombineTrunc(
MI, DeadInsts, UpdatedDefs, WrapperObserver);
1372 while (!UpdatedDefs.
empty()) {
1376 switch (
Use.getOpcode()) {
1378 case TargetOpcode::G_ANYEXT:
1379 case TargetOpcode::G_ZEXT:
1380 case TargetOpcode::G_SEXT:
1381 case TargetOpcode::G_UNMERGE_VALUES:
1382 case TargetOpcode::G_EXTRACT:
1383 case TargetOpcode::G_TRUNC:
1384 case TargetOpcode::G_BUILD_VECTOR:
1388 case TargetOpcode::G_ASSERT_SEXT:
1389 case TargetOpcode::G_ASSERT_ZEXT:
1390 case TargetOpcode::G_ASSERT_ALIGN:
1391 case TargetOpcode::COPY: {
1393 if (Copy.isVirtual())
1410 switch (
MI.getOpcode()) {
1411 case TargetOpcode::COPY:
1412 case TargetOpcode::G_TRUNC:
1413 case TargetOpcode::G_ZEXT:
1414 case TargetOpcode::G_ANYEXT:
1415 case TargetOpcode::G_SEXT:
1416 case TargetOpcode::G_EXTRACT:
1417 case TargetOpcode::G_ASSERT_SEXT:
1418 case TargetOpcode::G_ASSERT_ZEXT:
1419 case TargetOpcode::G_ASSERT_ALIGN:
1420 return MI.getOperand(1).getReg();
1421 case TargetOpcode::G_UNMERGE_VALUES:
1422 return MI.getOperand(
MI.getNumOperands() - 1).getReg();
1435 unsigned DefIdx = 0) {
1446 while (PrevMI != &
DefMI) {
1447 Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1450 if (
MRI.hasOneUse(PrevRegSrc)) {
1451 if (TmpDef != &
DefMI) {
1455 "Expecting copy or artifact cast here");
1464 if (PrevMI == &
DefMI) {
1469 if (!
MRI.use_empty(
Def.getReg())) {
1493 unsigned DefIdx = 0) {
1495 markDefDead(
MI,
DefMI, DeadInsts, DefIdx);
1506 for (
auto *DeadMI : DeadInsts) {
1509 DeadMI->eraseFromParent();
1517 using namespace LegalizeActions;
1518 auto Step = LI.getAction(Query);
1526 bool isConstantUnsupported(
LLT Ty)
const {
1528 return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1531 return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1532 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 DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
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.
unsigned computeNumSignBits(Register R, const APInt &DemandedElts, unsigned Depth=0)
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)
bool tryCombineSExt(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp, LLT OpTy, LLT DestTy)
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, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
void setDebugLoc(const DebugLoc &DL)
Set the debug location to DL for all the next build instructions.
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.