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), VT(VT) {}
64 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT);
66 Builder.setInstrAndDebugLoc(
MI);
68 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
74 if (MRI.getType(DstReg) == MRI.getType(TruncSrc))
78 Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
80 markInstAndDefDead(
MI, *MRI.getVRegDef(SrcReg), DeadInsts);
91 Builder.buildInstr(ExtMI->
getOpcode(), {DstReg}, {ExtSrc});
93 markInstAndDefDead(
MI, *ExtMI, DeadInsts);
100 const LLT DstTy = MRI.getType(DstReg);
101 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
106 Builder.setDebugLoc(MergedLocation);
107 Builder.buildConstant(DstReg,
110 markInstAndDefDead(
MI, *SrcCst, DeadInsts);
122 assert(
MI.getOpcode() == TargetOpcode::G_ZEXT);
124 Builder.setInstrAndDebugLoc(
MI);
126 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
134 LLT DstTy = MRI.getType(DstReg);
135 if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
136 isConstantUnsupported(DstTy))
139 LLT SrcTy = MRI.getType(SrcReg);
141 if (SextSrc && (DstTy != MRI.getType(SextSrc)))
142 SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
143 if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))
144 TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
146 Register AndSrc = SextSrc ? SextSrc : TruncSrc;
153 if (VT && (VT->getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
157 auto Mask = Builder.buildConstant(DstTy, ExtMaskVal);
158 Builder.buildAnd(DstReg, AndSrc, Mask);
160 markInstAndDefDead(
MI, *MRI.getVRegDef(SrcReg), DeadInsts);
169 MI.getOperand(1).setReg(ZextSrc);
172 markDefDead(
MI, *MRI.getVRegDef(SrcReg), DeadInsts);
179 const LLT DstTy = MRI.getType(DstReg);
180 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
181 Builder.buildConstant(DstReg,
184 markInstAndDefDead(
MI, *SrcCst, DeadInsts);
196 assert(
MI.getOpcode() == TargetOpcode::G_SEXT);
198 Builder.setInstrAndDebugLoc(
MI);
200 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
205 LLT DstTy = MRI.getType(DstReg);
206 LLT SrcTy = MRI.getType(SrcReg);
207 uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
208 if (isInstUnsupported({TargetOpcode::G_SEXT_INREG,
211 {
static_cast<int64_t
>(SizeInBits)}}))
214 if (DstTy != MRI.getType(TruncSrc))
215 TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
218 if (VT && VT->computeNumSignBits(TruncSrc) >
223 Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits);
224 markInstAndDefDead(
MI, *MRI.getVRegDef(SrcReg), DeadInsts);
236 Builder.buildInstr(ExtMI->
getOpcode(), {DstReg}, {ExtSrc});
238 markInstAndDefDead(
MI, *MRI.getVRegDef(SrcReg), DeadInsts);
245 const LLT DstTy = MRI.getType(DstReg);
246 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
247 Builder.buildConstant(DstReg,
250 markInstAndDefDead(
MI, *SrcCst, DeadInsts);
263 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
265 Builder.setInstr(
MI);
267 const LLT DstTy = MRI.getType(DstReg);
268 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
273 if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
274 Builder.buildConstant(DstReg,
277 markInstAndDefDead(
MI, *SrcCst, DeadInsts);
286 const Register MergeSrcReg = SrcMerge->getSourceReg(0);
287 const LLT MergeSrcTy = MRI.getType(MergeSrcReg);
302 if (MergeSrcTy != WorkTy)
303 return Builder.buildBitcast(WorkTy, R).getReg(0);
307 if (DstSize < MergeSrcSize) {
310 if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, WorkTy}}))
313 LLVM_DEBUG(
dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
316 Builder.buildTrunc(DstReg, AsInt(MergeSrcReg));
318 }
else if (DstSize == MergeSrcSize) {
321 dbgs() <<
"Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
324 UpdatedDefs, Observer);
325 }
else if (DstSize % MergeSrcSize == 0) {
328 if (isInstUnsupported({TargetOpcode::G_MERGE_VALUES, {DstTy, WorkTy}}))
332 dbgs() <<
"Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
335 const unsigned NumSrcs = DstSize / MergeSrcSize;
336 assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
337 "trunc(merge) should require less inputs than merge");
339 for (
unsigned i = 0; i < NumSrcs; ++i)
340 SrcRegs[i] = AsInt(SrcMerge->getSourceReg(i));
342 Builder.buildMergeValues(DstReg, SrcRegs);
349 markInstAndDefDead(
MI, *SrcMerge, DeadInsts);
361 Builder.buildTrunc(DstReg, TruncSrc);
363 markInstAndDefDead(
MI, *MRI.getVRegDef(TruncSrc), DeadInsts);
371 LLT FoundRegTy = MRI.getType(FoundReg);
372 if (DstTy == FoundRegTy) {
373 LLVM_DEBUG(
dbgs() <<
".. Combine G_TRUNC(G_[S,Z,ANY]EXT/G_TRUNC...): "
379 markInstAndDefDead(
MI, *MRI.getVRegDef(SrcReg), DeadInsts);
392 unsigned Opcode =
MI.getOpcode();
393 assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
394 Opcode == TargetOpcode::G_SEXT);
397 MI.getOperand(1).getReg(), MRI)) {
398 Builder.setInstr(
MI);
400 LLT DstTy = MRI.getType(DstReg);
402 if (Opcode == TargetOpcode::G_ANYEXT) {
404 if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
407 auto Impl = Builder.buildUndef(DstTy);
414 if (isConstantUnsupported(DstTy))
417 auto Cnst = Builder.buildConstant(DstTy, 0);
423 markInstAndDefDead(
MI, *
DefMI, DeadInsts);
433 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
435 const unsigned CastOpc = CastMI.
getOpcode();
437 if (!isArtifactCast(CastOpc))
440 const unsigned NumDefs =
MI.getNumOperands() - 1;
443 const LLT CastSrcTy = MRI.getType(CastSrcReg);
444 const LLT DestTy = MRI.getType(
MI.getOperand(0).getReg());
445 const LLT SrcTy = MRI.getType(
MI.getOperand(NumDefs).getReg());
450 if (CastOpc == TargetOpcode::G_TRUNC) {
451 if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.
getScalarType()) {
461 unsigned UnmergeNumElts =
468 if (isInstUnsupported(
469 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}) ||
470 LI.getAction({TargetOpcode::G_TRUNC, {SrcWideTy, UnmergeTy}})
474 Builder.setInstr(
MI);
475 auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg);
477 for (
unsigned I = 0;
I != NumDefs; ++
I) {
480 Builder.buildTrunc(DefReg, NewUnmerge.getReg(
I));
483 markInstAndDefDead(
MI, CastMI, DeadInsts);
495 if (CastSrcSize % DestSize != 0)
499 if (isInstUnsupported(
500 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
505 const unsigned NewNumDefs = CastSrcSize / DestSize;
507 for (
unsigned Idx = 0; Idx < NewNumDefs; ++Idx) {
509 DstRegs[Idx] =
MI.getOperand(Idx).getReg();
511 DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy);
515 Builder.setInstr(
MI);
516 Builder.buildUnmerge(DstRegs, CastSrcReg);
518 markInstAndDefDead(
MI, CastMI, DeadInsts);
533 case TargetOpcode::G_BUILD_VECTOR:
534 case TargetOpcode::G_MERGE_VALUES:
560 DestTy ==
OpTy.getElementType();
561 case TargetOpcode::G_CONCAT_VECTORS: {
567 const unsigned OpEltSize =
OpTy.getElementType().getSizeInBits();
572 if (ConvertOp == TargetOpcode::G_TRUNC)
587 Builder.buildCopy(DstReg, SrcReg);
593 for (
auto &
UseMI : MRI.use_instructions(DstReg)) {
598 MRI.replaceRegWith(DstReg, SrcReg);
601 for (
auto *
UseMI : UseMIs)
609 if (Def.getReg() == SearchDef)
640 unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
643 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
645 unsigned InRegOffset = StartBit % SrcSize;
649 if (InRegOffset +
Size > SrcSize)
653 if (InRegOffset == 0 &&
Size == SrcSize) {
654 CurrentBest = SrcReg;
655 return findValueFromDefImpl(SrcReg, 0,
Size, MRI.getType(SrcReg));
658 return findValueFromDefImpl(SrcReg, InRegOffset,
Size,
659 MRI.getType(SrcReg));
673 unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
676 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
678 unsigned InRegOffset = StartBit % SrcSize;
680 if (InRegOffset != 0)
687 if (
Size > SrcSize) {
688 if (
Size % SrcSize > 0)
691 unsigned NumSrcsUsed =
Size / SrcSize;
696 LLT SrcTy = MRI.getType(Src1Reg);
701 LI.getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
706 for (
unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
709 MIB.setInstrAndDebugLoc(BV);
710 return MIB.buildBuildVector(NewBVTy, NewSrcs).getReg(0);
713 return BV.
getReg(StartSrcIdx);
723 assert(
MI.getOpcode() == TargetOpcode::G_INSERT);
726 Register ContainerSrcReg =
MI.getOperand(1).getReg();
727 Register InsertedReg =
MI.getOperand(2).getReg();
728 LLT InsertedRegTy = MRI.getType(InsertedReg);
729 unsigned InsertOffset =
MI.getOperand(3).getImm();
767 unsigned InsertedEndBit = InsertOffset + InsertedRegTy.
getSizeInBits();
768 unsigned EndBit = StartBit +
Size;
769 unsigned NewStartBit;
771 if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
772 SrcRegToUse = ContainerSrcReg;
773 NewStartBit = StartBit;
774 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size,
775 MRI.getType(SrcRegToUse));
777 if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
778 SrcRegToUse = InsertedReg;
779 NewStartBit = StartBit - InsertOffset;
780 if (NewStartBit == 0 &&
781 Size == MRI.getType(SrcRegToUse).getSizeInBits())
782 CurrentBest = SrcRegToUse;
783 return findValueFromDefImpl(SrcRegToUse, NewStartBit,
Size,
784 MRI.getType(SrcRegToUse));
798 assert(
MI.getOpcode() == TargetOpcode::G_SEXT ||
799 MI.getOpcode() == TargetOpcode::G_ZEXT ||
800 MI.getOpcode() == TargetOpcode::G_ANYEXT);
804 LLT SrcType = MRI.getType(SrcReg);
808 if (!SrcType.isScalar())
811 if (StartBit +
Size > SrcSize)
814 if (StartBit == 0 && SrcType.getSizeInBits() ==
Size)
815 CurrentBest = SrcReg;
816 return findValueFromDefImpl(SrcReg, StartBit,
Size, SrcType);
826 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
830 LLT SrcType = MRI.getType(SrcReg);
833 if (!SrcType.isScalar())
836 return findValueFromDefImpl(SrcReg, StartBit,
Size, SrcType);
844 std::optional<DefinitionAndSourceRegister> DefSrcReg =
847 DefReg = DefSrcReg->Reg;
851 switch (Def->getOpcode()) {
852 case TargetOpcode::G_CONCAT_VECTORS:
854 case TargetOpcode::G_UNMERGE_VALUES: {
855 unsigned DefStartBit = 0;
856 unsigned DefSize = MRI.getType(DefReg).getSizeInBits();
857 for (
const auto &MO : Def->defs()) {
858 if (MO.getReg() == DefReg)
860 DefStartBit += DefSize;
862 Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
864 findValueFromDefImpl(SrcReg, StartBit + DefStartBit,
Size, DstTy);
870 if (StartBit == 0 &&
Size == DefSize)
874 case TargetOpcode::G_BUILD_VECTOR:
877 case TargetOpcode::G_INSERT:
878 return findValueFromInsert(*Def, StartBit,
Size);
879 case TargetOpcode::G_TRUNC:
880 return findValueFromTrunc(*Def, StartBit,
Size);
881 case TargetOpcode::G_SEXT:
882 case TargetOpcode::G_ZEXT:
883 case TargetOpcode::G_ANYEXT:
884 return findValueFromExt(*Def, StartBit,
Size);
885 case TargetOpcode::G_IMPLICIT_DEF: {
886 if (MRI.getType(DefReg) == DstTy)
888 MIB.setInstrAndDebugLoc(*Def);
889 return MIB.buildUndef(DstTy).getReg(0);
899 : MRI(Mri), MIB(Builder), LI(Info) {}
908 Register FoundReg = findValueFromDefImpl(DefReg, StartBit,
Size, DstTy);
909 return FoundReg != DefReg ? FoundReg :
Register();
917 unsigned NumDefs =
MI.getNumDefs();
918 LLT DestTy = MRI.getType(
MI.getReg(0));
921 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
923 if (MRI.use_nodbg_empty(DefReg)) {
924 DeadDefs[DefIdx] =
true;
931 if (MRI.getType(FoundVal) != DestTy)
938 MI.getOperand(DefIdx).setReg(DefReg);
940 DeadDefs[DefIdx] =
true;
942 return DeadDefs.
all();
946 unsigned &DefOperandIdx) {
950 Unmerge->findRegisterDefOperandIdx(Def,
nullptr);
961 GUnmerge *Unmerge,
unsigned UnmergeIdxStart,
962 unsigned NumElts,
unsigned EltSize,
965 assert(MergeStartIdx + NumElts <=
MI.getNumSources());
966 for (
unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
967 unsigned EltUnmergeIdx;
969 MI.getSourceReg(i), EltSize, EltUnmergeIdx);
971 if (EltUnmerge == Unmerge) {
973 if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
975 }
else if (!AllowUndef ||
987 LLT EltTy = MRI.getType(Elt0);
990 unsigned Elt0UnmergeIdx;
996 unsigned NumMIElts =
MI.getNumSources();
998 LLT DstTy = MRI.getType(Dst);
999 Register UnmergeSrc = Unmerge->getSourceReg();
1000 LLT UnmergeSrcTy = MRI.getType(UnmergeSrc);
1011 if ((DstSize == UnmergeSrcSize) && (DstTy == UnmergeSrcTy) &&
1012 (Elt0UnmergeIdx == 0)) {
1033 if ((DstSize < UnmergeSrcSize) &&
1037 (Elt0UnmergeIdx % NumMIElts == 0) &&
1038 getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
1042 MIB.setInstrAndDebugLoc(
MI);
1043 auto NewUnmerge = MIB.buildUnmerge(DstTy, Unmerge->getSourceReg());
1044 unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.
getSizeInBits();
1046 UpdatedDefs, Observer);
1061 if ((DstSize > UnmergeSrcSize) &&
1065 unsigned NumElts = Unmerge->getNumDefs();
1066 for (
unsigned i = 0; i <
MI.getNumSources(); i += NumElts) {
1067 unsigned EltUnmergeIdx;
1069 EltSize, EltUnmergeIdx);
1071 if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
1072 (EltUnmergeIdx != 0))
1077 ConcatSources.
push_back(UnmergeI->getSourceReg());
1080 MIB.setInstrAndDebugLoc(
MI);
1081 MIB.buildMergeLikeInstr(Dst, ConcatSources);
1094 unsigned NumDefs =
MI.getNumDefs();
1096 std::optional<DefinitionAndSourceRegister> DefSrcReg =
1102 LLT OpTy = MRI.getType(SrcReg);
1103 LLT DestTy = MRI.getType(
MI.getReg(0));
1104 unsigned SrcDefIdx =
getDefIndex(*SrcDef, DefSrcReg->Reg);
1106 Builder.setInstrAndDebugLoc(
MI);
1110 markInstAndDefDead(
MI, *SrcDef, DeadInsts, SrcDefIdx);
1120 Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
1121 LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);
1127 {TargetOpcode::G_UNMERGE_VALUES, {
OpTy, SrcUnmergeSrcTy}});
1128 switch (ActionStep.
Action) {
1130 if (!
OpTy.isVector() || !LI.isLegal({TargetOpcode::G_UNMERGE_VALUES,
1131 {DestTy, SrcUnmergeSrcTy}}))
1146 auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
1151 for (
unsigned I = 0;
I != NumDefs; ++
I) {
1154 MRI, Builder, UpdatedDefs, Observer);
1157 markInstAndDefDead(
MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1162 unsigned ConvertOp = 0;
1165 unsigned SrcOp = SrcDef->getOpcode();
1166 if (isArtifactCast(
SrcOp)) {
1172 ConvertOp,
OpTy, DestTy)) {
1180 if (NumMergeRegs < NumDefs) {
1181 if (NumDefs % NumMergeRegs != 0)
1184 Builder.setInstr(
MI);
1192 const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1193 for (
unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
1195 for (
unsigned j = 0, DefIdx = Idx * NewNumDefs;
j < NewNumDefs;
1200 LLT MergeDstTy = MRI.getType(SrcDef->getOperand(0).getReg());
1205 LLT MergeEltTy = MergeDstTy.
divide(NumMergeRegs);
1220 Register TmpReg = MRI.createGenericVirtualRegister(MergeEltTy);
1221 Builder.buildInstr(ConvertOp, {TmpReg},
1223 Builder.buildUnmerge(DstRegs, TmpReg);
1227 UpdatedDefs.append(DstRegs.
begin(), DstRegs.
end());
1230 }
else if (NumMergeRegs > NumDefs) {
1231 if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1234 Builder.setInstr(
MI);
1242 const unsigned NumRegs = NumMergeRegs / NumDefs;
1243 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1245 for (
unsigned j = 0, Idx = NumRegs * DefIdx + 1;
j < NumRegs;
1250 Builder.buildMergeLikeInstr(DefReg, Regs);
1251 UpdatedDefs.push_back(DefReg);
1257 if (!ConvertOp && DestTy != MergeSrcTy) {
1258 if (DestTy.isPointer())
1259 ConvertOp = TargetOpcode::G_INTTOPTR;
1261 ConvertOp = TargetOpcode::G_PTRTOINT;
1263 ConvertOp = TargetOpcode::G_BITCAST;
1267 Builder.setInstr(
MI);
1269 for (
unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1270 Register DefReg =
MI.getOperand(Idx).getReg();
1273 if (!MRI.use_empty(DefReg)) {
1274 Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1275 UpdatedDefs.push_back(DefReg);
1279 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1283 assert(DestTy == MergeSrcTy &&
1284 "Bitcast and the other kinds of conversions should "
1285 "have happened earlier");
1287 Builder.setInstr(
MI);
1288 for (
unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1289 Register DstReg =
MI.getOperand(Idx).getReg();
1296 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1303 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT);
1318 Register SrcReg = lookThroughCopyInstrs(
MI.getOperand(1).getReg());
1320 if (MergeI && MergeI->
getOpcode() == TargetOpcode::G_IMPLICIT_DEF) {
1321 Builder.setInstrAndDebugLoc(
MI);
1322 Builder.buildUndef(DstReg);
1324 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1330 LLT DstTy = MRI.getType(DstReg);
1331 LLT SrcTy = MRI.getType(SrcReg);
1335 unsigned Offset =
MI.getOperand(2).getImm();
1337 unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
1338 unsigned MergeSrcIdx =
Offset / MergeSrcSize;
1341 unsigned EndMergeSrcIdx = (
Offset + ExtractDstSize - 1) / MergeSrcSize;
1344 if (MergeSrcIdx != EndMergeSrcIdx)
1348 Builder.setInstr(
MI);
1350 Offset - MergeSrcIdx * MergeSrcSize);
1352 markInstAndDefDead(
MI, *MergeI, DeadInsts);
1368 if (!DeadInsts.
empty())
1369 deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1377 switch (
MI.getOpcode()) {
1380 case TargetOpcode::G_ANYEXT:
1383 case TargetOpcode::G_ZEXT:
1386 case TargetOpcode::G_SEXT:
1389 case TargetOpcode::G_UNMERGE_VALUES:
1391 UpdatedDefs, WrapperObserver);
1393 case TargetOpcode::G_MERGE_VALUES:
1394 case TargetOpcode::G_BUILD_VECTOR:
1395 case TargetOpcode::G_CONCAT_VECTORS:
1398 for (
MachineInstr &U : MRI.use_instructions(
MI.getOperand(0).getReg())) {
1399 if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1400 U.getOpcode() == TargetOpcode::G_TRUNC) {
1406 UpdatedDefs, WrapperObserver);
1408 case TargetOpcode::G_EXTRACT:
1411 case TargetOpcode::G_TRUNC:
1426 while (!UpdatedDefs.
empty()) {
1430 switch (
Use.getOpcode()) {
1432 case TargetOpcode::G_ANYEXT:
1433 case TargetOpcode::G_ZEXT:
1434 case TargetOpcode::G_SEXT:
1435 case TargetOpcode::G_UNMERGE_VALUES:
1436 case TargetOpcode::G_EXTRACT:
1437 case TargetOpcode::G_TRUNC:
1438 case TargetOpcode::G_BUILD_VECTOR:
1442 case TargetOpcode::G_ASSERT_SEXT:
1443 case TargetOpcode::G_ASSERT_ZEXT:
1444 case TargetOpcode::G_ASSERT_ALIGN:
1445 case TargetOpcode::COPY: {
1447 if (Copy.isVirtual())
1464 switch (
MI.getOpcode()) {
1465 case TargetOpcode::COPY:
1466 case TargetOpcode::G_TRUNC:
1467 case TargetOpcode::G_ZEXT:
1468 case TargetOpcode::G_ANYEXT:
1469 case TargetOpcode::G_SEXT:
1470 case TargetOpcode::G_EXTRACT:
1471 case TargetOpcode::G_ASSERT_SEXT:
1472 case TargetOpcode::G_ASSERT_ZEXT:
1473 case TargetOpcode::G_ASSERT_ALIGN:
1474 return MI.getOperand(1).getReg();
1475 case TargetOpcode::G_UNMERGE_VALUES:
1476 return MI.getOperand(
MI.getNumOperands() - 1).getReg();
1489 unsigned DefIdx = 0) {
1500 while (PrevMI != &
DefMI) {
1501 Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1505 if (TmpDef != &
DefMI) {
1509 "Expecting copy or artifact cast here");
1518 if (PrevMI == &
DefMI) {
1547 unsigned DefIdx = 0) {
1549 markDefDead(
MI,
DefMI, DeadInsts, DefIdx);
1560 for (
auto *DeadMI : DeadInsts) {
1563 DeadMI->eraseFromParent();
1580 bool isConstantUnsupported(
LLT Ty)
const {
1582 return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1585 return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1586 isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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
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.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
static LLVM_ABI DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc 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.
const APInt & getValue() const
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.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
LLT getScalarType() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
LLT divide(int Factor) const
Return a type that is Factor times smaller.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
This class provides utilities for finding source registers of specific bit ranges in an artifact.
Register findValueFromDef(Register DefReg, unsigned StartBit, unsigned Size, LLT DstTy)
Try to find a source of the value defined in the def DefReg, starting at position StartBit with size ...
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)
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)
bool tryFoldUnmergeCast(MachineInstr &MI, MachineInstr &CastMI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs)
bool tryFoldImplicitDef(MachineInstr &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelObserverWrapper &Observer)
Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
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)
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI, GISelValueTracking *VT=nullptr)
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 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.
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 DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
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,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
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.
@ 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.
@ NotFound
Sentinel value for when no action was found in the specified table.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
operand_type_match m_Reg()
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
ImplicitDefMatch m_GImplicitDef()
GConstantMatch< GConstant > m_GConstant(GConstant *&Inst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
Or< Preds... > m_any_of(Preds &&... preds)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
And< Preds... > m_all_of(Preds &&... preds)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
bool isPreISelGenericOptimizationHint(unsigned Opcode)
LLVM_ABI bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI)
Check if DstReg can be replaced with SrcReg depending on the register constraints.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI LLVM_READNONE LLT getCoverTy(LLT OrigTy, LLT TargetTy)
Return smallest type that covers both OrigTy and TargetTy and is multiple of TargetTy.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< DefinitionAndSourceRegister > getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, and underlying value Register folding away any copies.
LLVM_ABI 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.