LLVM 22.0.0git
LegalizationArtifactCombiner.h
Go to the documentation of this file.
1//===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- C++ -*-//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This file contains some helper functions which try to cleanup artifacts
9// such as G_TRUNCs/G_[ZSA]EXTENDS that were created during legalization to make
10// the types match. This file also contains some combines of merges that happens
11// at the end of the legalization.
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
15#define LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
16
28#include "llvm/IR/Constants.h"
30#include "llvm/Support/Debug.h"
31
32#define DEBUG_TYPE "legalizer"
33
34namespace llvm {
36 MachineIRBuilder &Builder;
38 const LegalizerInfo &LI;
40
41 static bool isArtifactCast(unsigned Opc) {
42 switch (Opc) {
43 case TargetOpcode::G_TRUNC:
44 case TargetOpcode::G_SEXT:
45 case TargetOpcode::G_ZEXT:
46 case TargetOpcode::G_ANYEXT:
47 return true;
48 default:
49 return false;
50 }
51 }
52
53public:
55 const LegalizerInfo &LI,
56 GISelValueTracking *VT = nullptr)
57 : Builder(B), MRI(MRI), LI(LI), VT(VT) {}
58
61 SmallVectorImpl<Register> &UpdatedDefs,
62 GISelObserverWrapper &Observer) {
63 using namespace llvm::MIPatternMatch;
64 assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);
65
66 Builder.setInstrAndDebugLoc(MI);
67 Register DstReg = MI.getOperand(0).getReg();
68 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
69
70 // aext(trunc x) - > aext/copy/trunc x
71 Register TruncSrc;
72 if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
73 LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
74 if (MRI.getType(DstReg) == MRI.getType(TruncSrc))
75 replaceRegOrBuildCopy(DstReg, TruncSrc, MRI, Builder, UpdatedDefs,
76 Observer);
77 else
78 Builder.buildAnyExtOrTrunc(DstReg, TruncSrc);
79 UpdatedDefs.push_back(DstReg);
80 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
81 return true;
82 }
83
84 // aext([asz]ext x) -> [asz]ext x
85 Register ExtSrc;
86 MachineInstr *ExtMI;
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)))))) {
91 Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
92 UpdatedDefs.push_back(DstReg);
93 markInstAndDefDead(MI, *ExtMI, DeadInsts);
94 return true;
95 }
96
97 // Try to fold aext(g_constant) when the larger constant type is legal.
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);
103 auto MergedLocation =
104 DebugLoc::getMergedLocation(MI.getDebugLoc(), SrcMI->getDebugLoc());
105 // Set the debug location to the merged location of the SrcMI and the MI
106 // if the aext fold is successful.
107 Builder.setDebugLoc(MergedLocation);
108 Builder.buildConstant(
109 DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
110 UpdatedDefs.push_back(DstReg);
111 markInstAndDefDead(MI, *SrcMI, DeadInsts);
112 return true;
113 }
114 }
115 return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs, Observer);
116 }
117
120 SmallVectorImpl<Register> &UpdatedDefs,
121 GISelObserverWrapper &Observer) {
122 using namespace llvm::MIPatternMatch;
123 assert(MI.getOpcode() == TargetOpcode::G_ZEXT);
124
125 Builder.setInstrAndDebugLoc(MI);
126 Register DstReg = MI.getOperand(0).getReg();
127 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
128
129 // zext(trunc x) - > and (aext/copy/trunc x), mask
130 // zext(sext x) -> and (sext x), mask
131 Register TruncSrc;
132 Register SextSrc;
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))
138 return false;
139 LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
140 LLT SrcTy = MRI.getType(SrcReg);
141 APInt MaskVal = APInt::getAllOnes(SrcTy.getScalarSizeInBits());
142 if (SextSrc && (DstTy != MRI.getType(SextSrc)))
143 SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
144 if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))
145 TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
146 APInt ExtMaskVal = MaskVal.zext(DstTy.getScalarSizeInBits());
147 Register AndSrc = SextSrc ? SextSrc : TruncSrc;
148 // Elide G_AND and mask constant if possible.
149 // The G_AND would also be removed by the post-legalize redundant_and
150 // combine, but in this very common case, eliding early and regardless of
151 // OptLevel results in significant compile-time and O0 code-size
152 // improvements. Inserting unnecessary instructions between boolean defs
153 // and uses hinders a lot of folding during ISel.
154 if (VT && (VT->getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
155 replaceRegOrBuildCopy(DstReg, AndSrc, MRI, Builder, UpdatedDefs,
156 Observer);
157 } else {
158 auto Mask = Builder.buildConstant(DstTy, ExtMaskVal);
159 Builder.buildAnd(DstReg, AndSrc, Mask);
160 }
161 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
162 return true;
163 }
164
165 // zext(zext x) -> (zext x)
166 Register ZextSrc;
167 if (mi_match(SrcReg, MRI, m_GZExt(m_Reg(ZextSrc)))) {
168 LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
169 Observer.changingInstr(MI);
170 MI.getOperand(1).setReg(ZextSrc);
171 Observer.changedInstr(MI);
172 UpdatedDefs.push_back(DstReg);
173 markDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
174 return true;
175 }
176
177 // Try to fold zext(g_constant) when the larger constant type is legal.
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);
183 Builder.buildConstant(
184 DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));
185 UpdatedDefs.push_back(DstReg);
186 markInstAndDefDead(MI, *SrcMI, DeadInsts);
187 return true;
188 }
189 }
190 return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs, Observer);
191 }
192
195 SmallVectorImpl<Register> &UpdatedDefs,
196 GISelObserverWrapper &Observer) {
197 using namespace llvm::MIPatternMatch;
198 assert(MI.getOpcode() == TargetOpcode::G_SEXT);
199
200 Builder.setInstrAndDebugLoc(MI);
201 Register DstReg = MI.getOperand(0).getReg();
202 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
203
204 // sext(trunc x) - > (sext_inreg (aext/copy/trunc x), c)
205 Register TruncSrc;
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}}))
209 return false;
210 LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
211 LLT SrcTy = MRI.getType(SrcReg);
212 uint64_t SizeInBits = SrcTy.getScalarSizeInBits();
213 if (DstTy != MRI.getType(TruncSrc))
214 TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
215 // Elide G_SEXT_INREG if possible. This is similar to eliding G_AND in
216 // tryCombineZExt. Refer to the comment in tryCombineZExt for rationale.
217 if (VT && VT->computeNumSignBits(TruncSrc) >
218 DstTy.getScalarSizeInBits() - SizeInBits)
219 replaceRegOrBuildCopy(DstReg, TruncSrc, MRI, Builder, UpdatedDefs,
220 Observer);
221 else
222 Builder.buildSExtInReg(DstReg, TruncSrc, SizeInBits);
223 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
224 return true;
225 }
226
227 // sext(zext x) -> (zext x)
228 // sext(sext x) -> (sext x)
229 Register ExtSrc;
230 MachineInstr *ExtMI;
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)))))) {
234 LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI);
235 Builder.buildInstr(ExtMI->getOpcode(), {DstReg}, {ExtSrc});
236 UpdatedDefs.push_back(DstReg);
237 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
238 return true;
239 }
240
241 // Try to fold sext(g_constant) when the larger constant type is legal.
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);
247 Builder.buildConstant(
248 DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
249 UpdatedDefs.push_back(DstReg);
250 markInstAndDefDead(MI, *SrcMI, DeadInsts);
251 return true;
252 }
253 }
254
255 return tryFoldImplicitDef(MI, DeadInsts, UpdatedDefs, Observer);
256 }
257
260 SmallVectorImpl<Register> &UpdatedDefs,
261 GISelObserverWrapper &Observer) {
262 using namespace llvm::MIPatternMatch;
263 assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
264
265 Builder.setInstr(MI);
266 Register DstReg = MI.getOperand(0).getReg();
267 const LLT DstTy = MRI.getType(DstReg);
268 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
269
270 // Try to fold trunc(g_constant) when the smaller constant type is legal.
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);
275 Builder.buildConstant(
276 DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits()));
277 UpdatedDefs.push_back(DstReg);
278 markInstAndDefDead(MI, *SrcMI, DeadInsts);
279 return true;
280 }
281 }
282
283 // Try to fold trunc(merge) to directly use the source of the merge.
284 // This gets rid of large, difficult to legalize, merges
285 if (auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
286 const Register MergeSrcReg = SrcMerge->getSourceReg(0);
287 const LLT MergeSrcTy = MRI.getType(MergeSrcReg);
288
289 // We can only fold if the types are scalar
290 const unsigned DstSize = DstTy.getSizeInBits();
291 const unsigned MergeSrcSize = MergeSrcTy.getSizeInBits();
292 if (!DstTy.isScalar() || !MergeSrcTy.isScalar())
293 return false;
294
295 if (DstSize < MergeSrcSize) {
296 // When the merge source is larger than the destination, we can just
297 // truncate the merge source directly
298 if (isInstUnsupported({TargetOpcode::G_TRUNC, {DstTy, MergeSrcTy}}))
299 return false;
300
301 LLVM_DEBUG(dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_TRUNC: "
302 << MI);
303
304 Builder.buildTrunc(DstReg, MergeSrcReg);
305 UpdatedDefs.push_back(DstReg);
306 } else if (DstSize == MergeSrcSize) {
307 // If the sizes match we can simply try to replace the register
309 dbgs() << "Replacing G_TRUNC(G_MERGE_VALUES) with merge input: "
310 << MI);
311 replaceRegOrBuildCopy(DstReg, MergeSrcReg, MRI, Builder, UpdatedDefs,
312 Observer);
313 } else if (DstSize % MergeSrcSize == 0) {
314 // If the trunc size is a multiple of the merge source size we can use
315 // a smaller merge instead
316 if (isInstUnsupported(
317 {TargetOpcode::G_MERGE_VALUES, {DstTy, MergeSrcTy}}))
318 return false;
319
321 dbgs() << "Combining G_TRUNC(G_MERGE_VALUES) to G_MERGE_VALUES: "
322 << MI);
323
324 const unsigned NumSrcs = DstSize / MergeSrcSize;
325 assert(NumSrcs < SrcMI->getNumOperands() - 1 &&
326 "trunc(merge) should require less inputs than merge");
327 SmallVector<Register, 8> SrcRegs(NumSrcs);
328 for (unsigned i = 0; i < NumSrcs; ++i)
329 SrcRegs[i] = SrcMerge->getSourceReg(i);
330
331 Builder.buildMergeValues(DstReg, SrcRegs);
332 UpdatedDefs.push_back(DstReg);
333 } else {
334 // Unable to combine
335 return false;
336 }
337
338 markInstAndDefDead(MI, *SrcMerge, DeadInsts);
339 return true;
340 }
341
342 // trunc(trunc) -> trunc
343 Register TruncSrc;
344 if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
345 // Always combine trunc(trunc) since the eventual resulting trunc must be
346 // legal anyway as it must be legal for all outputs of the consumer type
347 // set.
348 LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_TRUNC): " << MI);
349
350 Builder.buildTrunc(DstReg, TruncSrc);
351 UpdatedDefs.push_back(DstReg);
352 markInstAndDefDead(MI, *MRI.getVRegDef(TruncSrc), DeadInsts);
353 return true;
354 }
355
356 // trunc(ext x) -> x
357 ArtifactValueFinder Finder(MRI, Builder, LI);
358 if (Register FoundReg =
359 Finder.findValueFromDef(DstReg, 0, DstTy.getSizeInBits(), DstTy)) {
360 LLT FoundRegTy = MRI.getType(FoundReg);
361 if (DstTy == FoundRegTy) {
362 LLVM_DEBUG(dbgs() << ".. Combine G_TRUNC(G_[S,Z,ANY]EXT/G_TRUNC...): "
363 << MI);
364
365 replaceRegOrBuildCopy(DstReg, FoundReg, MRI, Builder, UpdatedDefs,
366 Observer);
367 UpdatedDefs.push_back(DstReg);
368 markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
369 return true;
370 }
371 }
372
373 return false;
374 }
375
376 /// Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
379 SmallVectorImpl<Register> &UpdatedDefs,
380 GISelObserverWrapper &Observer) {
381 unsigned Opcode = MI.getOpcode();
382 assert(Opcode == TargetOpcode::G_ANYEXT || Opcode == TargetOpcode::G_ZEXT ||
383 Opcode == TargetOpcode::G_SEXT);
384
385 if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
386 MI.getOperand(1).getReg(), MRI)) {
387 Builder.setInstr(MI);
388 Register DstReg = MI.getOperand(0).getReg();
389 LLT DstTy = MRI.getType(DstReg);
390
391 if (Opcode == TargetOpcode::G_ANYEXT) {
392 // G_ANYEXT (G_IMPLICIT_DEF) -> G_IMPLICIT_DEF
393 if (!isInstLegal({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
394 return false;
395 LLVM_DEBUG(dbgs() << ".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI);
396 auto Impl = Builder.buildUndef(DstTy);
397 replaceRegOrBuildCopy(DstReg, Impl.getReg(0), MRI, Builder, UpdatedDefs,
398 Observer);
399 UpdatedDefs.push_back(DstReg);
400 } else {
401 // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top
402 // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT.
403 if (isConstantUnsupported(DstTy))
404 return false;
405 LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI);
406 auto Cnst = Builder.buildConstant(DstTy, 0);
407 replaceRegOrBuildCopy(DstReg, Cnst.getReg(0), MRI, Builder, UpdatedDefs,
408 Observer);
409 UpdatedDefs.push_back(DstReg);
410 }
411
412 markInstAndDefDead(MI, *DefMI, DeadInsts);
413 return true;
414 }
415 return false;
416 }
417
420 SmallVectorImpl<Register> &UpdatedDefs) {
421
422 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
423
424 const unsigned CastOpc = CastMI.getOpcode();
425
426 if (!isArtifactCast(CastOpc))
427 return false;
428
429 const unsigned NumDefs = MI.getNumOperands() - 1;
430
431 const Register CastSrcReg = CastMI.getOperand(1).getReg();
432 const LLT CastSrcTy = MRI.getType(CastSrcReg);
433 const LLT DestTy = MRI.getType(MI.getOperand(0).getReg());
434 const LLT SrcTy = MRI.getType(MI.getOperand(NumDefs).getReg());
435
436 const unsigned CastSrcSize = CastSrcTy.getSizeInBits();
437 const unsigned DestSize = DestTy.getSizeInBits();
438
439 if (CastOpc == TargetOpcode::G_TRUNC) {
440 if (SrcTy.isVector() && SrcTy.getScalarType() == DestTy.getScalarType()) {
441 // %1:_(<4 x s8>) = G_TRUNC %0(<4 x s32>)
442 // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %1
443 // =>
444 // %6:_(s32), %7:_(s32), %8:_(s32), %9:_(s32) = G_UNMERGE_VALUES %0
445 // %2:_(s8) = G_TRUNC %6
446 // %3:_(s8) = G_TRUNC %7
447 // %4:_(s8) = G_TRUNC %8
448 // %5:_(s8) = G_TRUNC %9
449
450 unsigned UnmergeNumElts =
451 DestTy.isVector() ? CastSrcTy.getNumElements() / NumDefs : 1;
452 LLT UnmergeTy = CastSrcTy.changeElementCount(
453 ElementCount::getFixed(UnmergeNumElts));
454 LLT SrcWideTy =
455 SrcTy.changeElementCount(ElementCount::getFixed(UnmergeNumElts));
456
457 if (isInstUnsupported(
458 {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}) ||
459 LI.getAction({TargetOpcode::G_TRUNC, {SrcWideTy, UnmergeTy}})
461 return false;
462
463 Builder.setInstr(MI);
464 auto NewUnmerge = Builder.buildUnmerge(UnmergeTy, CastSrcReg);
465
466 for (unsigned I = 0; I != NumDefs; ++I) {
467 Register DefReg = MI.getOperand(I).getReg();
468 UpdatedDefs.push_back(DefReg);
469 Builder.buildTrunc(DefReg, NewUnmerge.getReg(I));
470 }
471
472 markInstAndDefDead(MI, CastMI, DeadInsts);
473 return true;
474 }
475
476 if (CastSrcTy.isScalar() && SrcTy.isScalar() && !DestTy.isVector()) {
477 // %1:_(s16) = G_TRUNC %0(s32)
478 // %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %1
479 // =>
480 // %2:_(s8), %3:_(s8), %4:_(s8), %5:_(s8) = G_UNMERGE_VALUES %0
481
482 // Unmerge(trunc) can be combined if the trunc source size is a multiple
483 // of the unmerge destination size
484 if (CastSrcSize % DestSize != 0)
485 return false;
486
487 // Check if the new unmerge is supported
488 if (isInstUnsupported(
489 {TargetOpcode::G_UNMERGE_VALUES, {DestTy, CastSrcTy}}))
490 return false;
491
492 // Gather the original destination registers and create new ones for the
493 // unused bits
494 const unsigned NewNumDefs = CastSrcSize / DestSize;
495 SmallVector<Register, 8> DstRegs(NewNumDefs);
496 for (unsigned Idx = 0; Idx < NewNumDefs; ++Idx) {
497 if (Idx < NumDefs)
498 DstRegs[Idx] = MI.getOperand(Idx).getReg();
499 else
500 DstRegs[Idx] = MRI.createGenericVirtualRegister(DestTy);
501 }
502
503 // Build new unmerge
504 Builder.setInstr(MI);
505 Builder.buildUnmerge(DstRegs, CastSrcReg);
506 UpdatedDefs.append(DstRegs.begin(), DstRegs.begin() + NewNumDefs);
507 markInstAndDefDead(MI, CastMI, DeadInsts);
508 return true;
509 }
510 }
511
512 // TODO: support combines with other casts as well
513 return false;
514 }
515
516 static bool canFoldMergeOpcode(unsigned MergeOp, unsigned ConvertOp,
517 LLT OpTy, LLT DestTy) {
518 // Check if we found a definition that is like G_MERGE_VALUES.
519 switch (MergeOp) {
520 default:
521 return false;
522 case TargetOpcode::G_BUILD_VECTOR:
523 case TargetOpcode::G_MERGE_VALUES:
524 // The convert operation that we will need to insert is
525 // going to convert the input of that type of instruction (scalar)
526 // to the destination type (DestTy).
527 // The conversion needs to stay in the same domain (scalar to scalar
528 // and vector to vector), so if we were to allow to fold the merge
529 // we would need to insert some bitcasts.
530 // E.g.,
531 // <2 x s16> = build_vector s16, s16
532 // <2 x s32> = zext <2 x s16>
533 // <2 x s16>, <2 x s16> = unmerge <2 x s32>
534 //
535 // As is the folding would produce:
536 // <2 x s16> = zext s16 <-- scalar to vector
537 // <2 x s16> = zext s16 <-- scalar to vector
538 // Which is invalid.
539 // Instead we would want to generate:
540 // s32 = zext s16
541 // <2 x s16> = bitcast s32
542 // s32 = zext s16
543 // <2 x s16> = bitcast s32
544 //
545 // That is not done yet.
546 if (ConvertOp == 0)
547 return true;
548 return !DestTy.isVector() && OpTy.isVector() &&
549 DestTy == OpTy.getElementType();
550 case TargetOpcode::G_CONCAT_VECTORS: {
551 if (ConvertOp == 0)
552 return true;
553 if (!DestTy.isVector())
554 return false;
555
556 const unsigned OpEltSize = OpTy.getElementType().getSizeInBits();
557
558 // Don't handle scalarization with a cast that isn't in the same
559 // direction as the vector cast. This could be handled, but it would
560 // require more intermediate unmerges.
561 if (ConvertOp == TargetOpcode::G_TRUNC)
562 return DestTy.getSizeInBits() <= OpEltSize;
563 return DestTy.getSizeInBits() >= OpEltSize;
564 }
565 }
566 }
567
568 /// Try to replace DstReg with SrcReg or build a COPY instruction
569 /// depending on the register constraints.
570 static void replaceRegOrBuildCopy(Register DstReg, Register SrcReg,
572 MachineIRBuilder &Builder,
573 SmallVectorImpl<Register> &UpdatedDefs,
574 GISelChangeObserver &Observer) {
575 if (!llvm::canReplaceReg(DstReg, SrcReg, MRI)) {
576 Builder.buildCopy(DstReg, SrcReg);
577 UpdatedDefs.push_back(DstReg);
578 return;
579 }
581 // Get the users and notify the observer before replacing.
582 for (auto &UseMI : MRI.use_instructions(DstReg)) {
583 UseMIs.push_back(&UseMI);
584 Observer.changingInstr(UseMI);
585 }
586 // Replace the registers.
587 MRI.replaceRegWith(DstReg, SrcReg);
588 UpdatedDefs.push_back(SrcReg);
589 // Notify the observer that we changed the instructions.
590 for (auto *UseMI : UseMIs)
591 Observer.changedInstr(*UseMI);
592 }
593
594 /// Return the operand index in \p MI that defines \p Def
595 static unsigned getDefIndex(const MachineInstr &MI, Register SearchDef) {
596 unsigned DefIdx = 0;
597 for (const MachineOperand &Def : MI.defs()) {
598 if (Def.getReg() == SearchDef)
599 break;
600 ++DefIdx;
601 }
602
603 return DefIdx;
604 }
605
606 /// This class provides utilities for finding source registers of specific
607 /// bit ranges in an artifact. The routines can look through the source
608 /// registers if they're other artifacts to try to find a non-artifact source
609 /// of a value.
612 MachineIRBuilder &MIB;
613 const LegalizerInfo &LI;
614
615 // Stores the best register found in the current query so far.
616 Register CurrentBest = Register();
617
618 /// Given an concat_vector op \p Concat and a start bit and size, try to
619 /// find the origin of the value defined by that start position and size.
620 ///
621 /// \returns a register with the requested size, or the current best
622 /// register found during the current query.
623 Register findValueFromConcat(GConcatVectors &Concat, unsigned StartBit,
624 unsigned Size) {
625 assert(Size > 0);
626
627 // Find the source operand that provides the bits requested.
628 Register Src1Reg = Concat.getSourceReg(0);
629 unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
630
631 // Operand index of the source that provides the start of the bit range.
632 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
633 // Offset into the source at which the bit range starts.
634 unsigned InRegOffset = StartBit % SrcSize;
635 // Check that the bits don't span multiple sources.
636 // FIXME: we might be able return multiple sources? Or create an
637 // appropriate concat to make it fit.
638 if (InRegOffset + Size > SrcSize)
639 return CurrentBest;
640
641 Register SrcReg = Concat.getReg(StartSrcIdx);
642 if (InRegOffset == 0 && Size == SrcSize) {
643 CurrentBest = SrcReg;
644 return findValueFromDefImpl(SrcReg, 0, Size, MRI.getType(SrcReg));
645 }
646
647 return findValueFromDefImpl(SrcReg, InRegOffset, Size,
648 MRI.getType(SrcReg));
649 }
650
651 /// Given an build_vector op \p BV and a start bit and size, try to find
652 /// the origin of the value defined by that start position and size.
653 ///
654 /// \returns a register with the requested size, or the current best
655 /// register found during the current query.
656 Register findValueFromBuildVector(GBuildVector &BV, unsigned StartBit,
657 unsigned Size) {
658 assert(Size > 0);
659
660 // Find the source operand that provides the bits requested.
661 Register Src1Reg = BV.getSourceReg(0);
662 unsigned SrcSize = MRI.getType(Src1Reg).getSizeInBits();
663
664 // Operand index of the source that provides the start of the bit range.
665 unsigned StartSrcIdx = (StartBit / SrcSize) + 1;
666 // Offset into the source at which the bit range starts.
667 unsigned InRegOffset = StartBit % SrcSize;
668
669 if (InRegOffset != 0)
670 return CurrentBest; // Give up, bits don't start at a scalar source.
671 if (Size < SrcSize)
672 return CurrentBest; // Scalar source is too large for requested bits.
673
674 // If the bits cover multiple sources evenly, then create a new
675 // build_vector to synthesize the required size, if that's been requested.
676 if (Size > SrcSize) {
677 if (Size % SrcSize > 0)
678 return CurrentBest; // Isn't covered exactly by sources.
679
680 unsigned NumSrcsUsed = Size / SrcSize;
681 // If we're requesting all of the sources, just return this def.
682 if (NumSrcsUsed == BV.getNumSources())
683 return BV.getReg(0);
684
685 LLT SrcTy = MRI.getType(Src1Reg);
686 LLT NewBVTy = LLT::fixed_vector(NumSrcsUsed, SrcTy);
687
688 // Check if the resulting build vector would be legal.
689 LegalizeActionStep ActionStep =
690 LI.getAction({TargetOpcode::G_BUILD_VECTOR, {NewBVTy, SrcTy}});
691 if (ActionStep.Action != LegalizeActions::Legal)
692 return CurrentBest;
693
694 SmallVector<Register> NewSrcs;
695 for (unsigned SrcIdx = StartSrcIdx; SrcIdx < StartSrcIdx + NumSrcsUsed;
696 ++SrcIdx)
697 NewSrcs.push_back(BV.getReg(SrcIdx));
698 MIB.setInstrAndDebugLoc(BV);
699 return MIB.buildBuildVector(NewBVTy, NewSrcs).getReg(0);
700 }
701 // A single source is requested, just return it.
702 return BV.getReg(StartSrcIdx);
703 }
704
705 /// Given an G_INSERT op \p MI and a start bit and size, try to find
706 /// the origin of the value defined by that start position and size.
707 ///
708 /// \returns a register with the requested size, or the current best
709 /// register found during the current query.
710 Register findValueFromInsert(MachineInstr &MI, unsigned StartBit,
711 unsigned Size) {
712 assert(MI.getOpcode() == TargetOpcode::G_INSERT);
713 assert(Size > 0);
714
715 Register ContainerSrcReg = MI.getOperand(1).getReg();
716 Register InsertedReg = MI.getOperand(2).getReg();
717 LLT InsertedRegTy = MRI.getType(InsertedReg);
718 unsigned InsertOffset = MI.getOperand(3).getImm();
719
720 // There are 4 possible container/insertreg + requested bit-range layouts
721 // that the instruction and query could be representing.
722 // For: %_ = G_INSERT %CONTAINER, %INS, InsOff (abbrev. to 'IO')
723 // and a start bit 'SB', with size S, giving an end bit 'EB', we could
724 // have...
725 // Scenario A:
726 // --------------------------
727 // | INS | CONTAINER |
728 // --------------------------
729 // | |
730 // SB EB
731 //
732 // Scenario B:
733 // --------------------------
734 // | INS | CONTAINER |
735 // --------------------------
736 // | |
737 // SB EB
738 //
739 // Scenario C:
740 // --------------------------
741 // | CONTAINER | INS |
742 // --------------------------
743 // | |
744 // SB EB
745 //
746 // Scenario D:
747 // --------------------------
748 // | CONTAINER | INS |
749 // --------------------------
750 // | |
751 // SB EB
752 //
753 // So therefore, A and D are requesting data from the INS operand, while
754 // B and C are requesting from the container operand.
755
756 unsigned InsertedEndBit = InsertOffset + InsertedRegTy.getSizeInBits();
757 unsigned EndBit = StartBit + Size;
758 unsigned NewStartBit;
759 Register SrcRegToUse;
760 if (EndBit <= InsertOffset || InsertedEndBit <= StartBit) {
761 SrcRegToUse = ContainerSrcReg;
762 NewStartBit = StartBit;
763 return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size,
764 MRI.getType(SrcRegToUse));
765 }
766 if (InsertOffset <= StartBit && EndBit <= InsertedEndBit) {
767 SrcRegToUse = InsertedReg;
768 NewStartBit = StartBit - InsertOffset;
769 if (NewStartBit == 0 &&
770 Size == MRI.getType(SrcRegToUse).getSizeInBits())
771 CurrentBest = SrcRegToUse;
772 return findValueFromDefImpl(SrcRegToUse, NewStartBit, Size,
773 MRI.getType(SrcRegToUse));
774 }
775 // The bit range spans both the inserted and container regions.
776 return Register();
777 }
778
779 /// Given an G_SEXT, G_ZEXT, G_ANYEXT op \p MI and a start bit and
780 /// size, try to find the origin of the value defined by that start
781 /// position and size.
782 ///
783 /// \returns a register with the requested size, or the current best
784 /// register found during the current query.
785 Register findValueFromExt(MachineInstr &MI, unsigned StartBit,
786 unsigned Size) {
787 assert(MI.getOpcode() == TargetOpcode::G_SEXT ||
788 MI.getOpcode() == TargetOpcode::G_ZEXT ||
789 MI.getOpcode() == TargetOpcode::G_ANYEXT);
790 assert(Size > 0);
791
792 Register SrcReg = MI.getOperand(1).getReg();
793 LLT SrcType = MRI.getType(SrcReg);
794 unsigned SrcSize = SrcType.getSizeInBits();
795
796 // Currently we don't go into vectors.
797 if (!SrcType.isScalar())
798 return CurrentBest;
799
800 if (StartBit + Size > SrcSize)
801 return CurrentBest;
802
803 if (StartBit == 0 && SrcType.getSizeInBits() == Size)
804 CurrentBest = SrcReg;
805 return findValueFromDefImpl(SrcReg, StartBit, Size, SrcType);
806 }
807
808 /// Given an G_TRUNC op \p MI and a start bit and size, try to find
809 /// the origin of the value defined by that start position and size.
810 ///
811 /// \returns a register with the requested size, or the current best
812 /// register found during the current query.
813 Register findValueFromTrunc(MachineInstr &MI, unsigned StartBit,
814 unsigned Size) {
815 assert(MI.getOpcode() == TargetOpcode::G_TRUNC);
816 assert(Size > 0);
817
818 Register SrcReg = MI.getOperand(1).getReg();
819 LLT SrcType = MRI.getType(SrcReg);
820
821 // Currently we don't go into vectors.
822 if (!SrcType.isScalar())
823 return CurrentBest;
824
825 return findValueFromDefImpl(SrcReg, StartBit, Size, SrcType);
826 }
827
828 /// Internal implementation for findValueFromDef(). findValueFromDef()
829 /// initializes some data like the CurrentBest register, which this method
830 /// and its callees rely upon.
831 Register findValueFromDefImpl(Register DefReg, unsigned StartBit,
832 unsigned Size, LLT DstTy) {
833 std::optional<DefinitionAndSourceRegister> DefSrcReg =
834 getDefSrcRegIgnoringCopies(DefReg, MRI);
835 MachineInstr *Def = DefSrcReg->MI;
836 DefReg = DefSrcReg->Reg;
837 // If the instruction has a single def, then simply delegate the search.
838 // For unmerge however with multiple defs, we need to compute the offset
839 // into the source of the unmerge.
840 switch (Def->getOpcode()) {
841 case TargetOpcode::G_CONCAT_VECTORS:
842 return findValueFromConcat(cast<GConcatVectors>(*Def), StartBit, Size);
843 case TargetOpcode::G_UNMERGE_VALUES: {
844 unsigned DefStartBit = 0;
845 unsigned DefSize = MRI.getType(DefReg).getSizeInBits();
846 for (const auto &MO : Def->defs()) {
847 if (MO.getReg() == DefReg)
848 break;
849 DefStartBit += DefSize;
850 }
851 Register SrcReg = Def->getOperand(Def->getNumOperands() - 1).getReg();
852 Register SrcOriginReg =
853 findValueFromDefImpl(SrcReg, StartBit + DefStartBit, Size, DstTy);
854 if (SrcOriginReg)
855 return SrcOriginReg;
856 // Failed to find a further value. If the StartBit and Size perfectly
857 // covered the requested DefReg, return that since it's better than
858 // nothing.
859 if (StartBit == 0 && Size == DefSize)
860 return DefReg;
861 return CurrentBest;
862 }
863 case TargetOpcode::G_BUILD_VECTOR:
864 return findValueFromBuildVector(cast<GBuildVector>(*Def), StartBit,
865 Size);
866 case TargetOpcode::G_INSERT:
867 return findValueFromInsert(*Def, StartBit, Size);
868 case TargetOpcode::G_TRUNC:
869 return findValueFromTrunc(*Def, StartBit, Size);
870 case TargetOpcode::G_SEXT:
871 case TargetOpcode::G_ZEXT:
872 case TargetOpcode::G_ANYEXT:
873 return findValueFromExt(*Def, StartBit, Size);
874 case TargetOpcode::G_IMPLICIT_DEF: {
875 if (MRI.getType(DefReg) == DstTy)
876 return DefReg;
877 MIB.setInstrAndDebugLoc(*Def);
878 return MIB.buildUndef(DstTy).getReg(0);
879 }
880 default:
881 return CurrentBest;
882 }
883 }
884
885 public:
887 const LegalizerInfo &Info)
888 : MRI(Mri), MIB(Builder), LI(Info) {}
889
890 /// Try to find a source of the value defined in the def \p DefReg, starting
891 /// at position \p StartBit with size \p Size.
892 /// \returns a register with the requested size, or an empty Register if no
893 /// better value could be found.
894 Register findValueFromDef(Register DefReg, unsigned StartBit, unsigned Size,
895 LLT DstTy) {
896 CurrentBest = Register();
897 Register FoundReg = findValueFromDefImpl(DefReg, StartBit, Size, DstTy);
898 return FoundReg != DefReg ? FoundReg : Register();
899 }
900
901 /// Try to combine the defs of an unmerge \p MI by attempting to find
902 /// values that provides the bits for each def reg.
903 /// \returns true if all the defs of the unmerge have been made dead.
905 SmallVectorImpl<Register> &UpdatedDefs) {
906 unsigned NumDefs = MI.getNumDefs();
907 LLT DestTy = MRI.getType(MI.getReg(0));
908
909 SmallBitVector DeadDefs(NumDefs);
910 for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
911 Register DefReg = MI.getReg(DefIdx);
912 if (MRI.use_nodbg_empty(DefReg)) {
913 DeadDefs[DefIdx] = true;
914 continue;
915 }
916 Register FoundVal =
917 findValueFromDef(DefReg, 0, DestTy.getSizeInBits(), DestTy);
918 if (!FoundVal)
919 continue;
920 if (MRI.getType(FoundVal) != DestTy)
921 continue;
922
923 replaceRegOrBuildCopy(DefReg, FoundVal, MRI, MIB, UpdatedDefs,
924 Observer);
925 // We only want to replace the uses, not the def of the old reg.
926 Observer.changingInstr(MI);
927 MI.getOperand(DefIdx).setReg(DefReg);
928 Observer.changedInstr(MI);
929 DeadDefs[DefIdx] = true;
930 }
931 return DeadDefs.all();
932 }
933
935 unsigned &DefOperandIdx) {
936 if (Register Def = findValueFromDefImpl(Reg, 0, Size, MRI.getType(Reg))) {
937 if (auto *Unmerge = dyn_cast<GUnmerge>(MRI.getVRegDef(Def))) {
938 DefOperandIdx =
939 Unmerge->findRegisterDefOperandIdx(Def, /*TRI=*/nullptr);
940 return Unmerge;
941 }
942 }
943 return nullptr;
944 }
945
946 // Check if sequence of elements from merge-like instruction is defined by
947 // another sequence of elements defined by unmerge. Most often this is the
948 // same sequence. Search for elements using findValueFromDefImpl.
949 bool isSequenceFromUnmerge(GMergeLikeInstr &MI, unsigned MergeStartIdx,
950 GUnmerge *Unmerge, unsigned UnmergeIdxStart,
951 unsigned NumElts, unsigned EltSize,
952 bool AllowUndef) {
953 assert(MergeStartIdx + NumElts <= MI.getNumSources());
954 for (unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
955 unsigned EltUnmergeIdx;
957 MI.getSourceReg(i), EltSize, EltUnmergeIdx);
958 // Check if source i comes from the same Unmerge.
959 if (EltUnmerge == Unmerge) {
960 // Check that source i's def has same index in sequence in Unmerge.
961 if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
962 return false;
963 } else if (!AllowUndef ||
964 MRI.getVRegDef(MI.getSourceReg(i))->getOpcode() !=
965 TargetOpcode::G_IMPLICIT_DEF)
966 return false;
967 }
968 return true;
969 }
970
973 SmallVectorImpl<Register> &UpdatedDefs,
974 GISelChangeObserver &Observer) {
975 Register Elt0 = MI.getSourceReg(0);
976 LLT EltTy = MRI.getType(Elt0);
977 unsigned EltSize = EltTy.getSizeInBits();
978
979 unsigned Elt0UnmergeIdx;
980 // Search for unmerge that will be candidate for combine.
981 auto *Unmerge = findUnmergeThatDefinesReg(Elt0, EltSize, Elt0UnmergeIdx);
982 if (!Unmerge)
983 return false;
984
985 unsigned NumMIElts = MI.getNumSources();
986 Register Dst = MI.getReg(0);
987 LLT DstTy = MRI.getType(Dst);
988 Register UnmergeSrc = Unmerge->getSourceReg();
989 LLT UnmergeSrcTy = MRI.getType(UnmergeSrc);
990
991 // Recognize copy of UnmergeSrc to Dst.
992 // Unmerge UnmergeSrc and reassemble it using merge-like opcode into Dst.
993 //
994 // %0:_(EltTy), %1, ... = G_UNMERGE_VALUES %UnmergeSrc:_(Ty)
995 // %Dst:_(Ty) = G_merge_like_opcode %0:_(EltTy), %1, ...
996 //
997 // %Dst:_(Ty) = COPY %UnmergeSrc:_(Ty)
998 if ((DstTy == UnmergeSrcTy) && (Elt0UnmergeIdx == 0)) {
999 if (!isSequenceFromUnmerge(MI, 0, Unmerge, 0, NumMIElts, EltSize,
1000 /*AllowUndef=*/DstTy.isVector()))
1001 return false;
1002
1003 replaceRegOrBuildCopy(Dst, UnmergeSrc, MRI, MIB, UpdatedDefs, Observer);
1004 DeadInsts.push_back(&MI);
1005 return true;
1006 }
1007
1008 // Recognize UnmergeSrc that can be unmerged to DstTy directly.
1009 // Types have to be either both vector or both non-vector types.
1010 // In case of vector types, the scalar elements need to match.
1011 // Merge-like opcodes are combined one at the time. First one creates new
1012 // unmerge, following should use the same unmerge (builder performs CSE).
1013 //
1014 // %0:_(EltTy), %1, %2, %3 = G_UNMERGE_VALUES %UnmergeSrc:_(UnmergeSrcTy)
1015 // %Dst:_(DstTy) = G_merge_like_opcode %0:_(EltTy), %1
1016 // %AnotherDst:_(DstTy) = G_merge_like_opcode %2:_(EltTy), %3
1017 //
1018 // %Dst:_(DstTy), %AnotherDst = G_UNMERGE_VALUES %UnmergeSrc
1019 if (((!DstTy.isVector() && !UnmergeSrcTy.isVector()) ||
1020 (DstTy.isVector() && UnmergeSrcTy.isVector() &&
1021 DstTy.getScalarType() == UnmergeSrcTy.getScalarType())) &&
1022 (Elt0UnmergeIdx % NumMIElts == 0) &&
1023 getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
1024 if (!isSequenceFromUnmerge(MI, 0, Unmerge, Elt0UnmergeIdx, NumMIElts,
1025 EltSize, false))
1026 return false;
1027 MIB.setInstrAndDebugLoc(MI);
1028 auto NewUnmerge = MIB.buildUnmerge(DstTy, Unmerge->getSourceReg());
1029 unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.getSizeInBits();
1030 replaceRegOrBuildCopy(Dst, NewUnmerge.getReg(DstIdx), MRI, MIB,
1031 UpdatedDefs, Observer);
1032 DeadInsts.push_back(&MI);
1033 return true;
1034 }
1035
1036 // Recognize when multiple unmerged sources with UnmergeSrcTy type
1037 // can be merged into Dst with DstTy type directly.
1038 // Types have to be either both vector or both non-vector types.
1039
1040 // %0:_(EltTy), %1 = G_UNMERGE_VALUES %UnmergeSrc:_(UnmergeSrcTy)
1041 // %2:_(EltTy), %3 = G_UNMERGE_VALUES %AnotherUnmergeSrc:_(UnmergeSrcTy)
1042 // %Dst:_(DstTy) = G_merge_like_opcode %0:_(EltTy), %1, %2, %3
1043 //
1044 // %Dst:_(DstTy) = G_merge_like_opcode %UnmergeSrc, %AnotherUnmergeSrc
1045
1046 if ((DstTy.isVector() == UnmergeSrcTy.isVector()) &&
1047 getCoverTy(DstTy, UnmergeSrcTy) == DstTy) {
1048 SmallVector<Register, 4> ConcatSources;
1049 unsigned NumElts = Unmerge->getNumDefs();
1050 for (unsigned i = 0; i < MI.getNumSources(); i += NumElts) {
1051 unsigned EltUnmergeIdx;
1052 auto *UnmergeI = findUnmergeThatDefinesReg(MI.getSourceReg(i),
1053 EltSize, EltUnmergeIdx);
1054 // All unmerges have to be the same size.
1055 if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
1056 (EltUnmergeIdx != 0))
1057 return false;
1058 if (!isSequenceFromUnmerge(MI, i, UnmergeI, 0, NumElts, EltSize,
1059 false))
1060 return false;
1061 ConcatSources.push_back(UnmergeI->getSourceReg());
1062 }
1063
1064 MIB.setInstrAndDebugLoc(MI);
1065 MIB.buildMergeLikeInstr(Dst, ConcatSources);
1066 DeadInsts.push_back(&MI);
1067 return true;
1068 }
1069
1070 return false;
1071 }
1072 };
1073
1076 SmallVectorImpl<Register> &UpdatedDefs,
1077 GISelChangeObserver &Observer) {
1078 unsigned NumDefs = MI.getNumDefs();
1079 Register SrcReg = MI.getSourceReg();
1080 std::optional<DefinitionAndSourceRegister> DefSrcReg =
1081 getDefSrcRegIgnoringCopies(SrcReg, MRI);
1082 if (!DefSrcReg)
1083 return false;
1084 MachineInstr *SrcDef = DefSrcReg->MI;
1085
1086 LLT OpTy = MRI.getType(SrcReg);
1087 LLT DestTy = MRI.getType(MI.getReg(0));
1088 unsigned SrcDefIdx = getDefIndex(*SrcDef, DefSrcReg->Reg);
1089
1090 Builder.setInstrAndDebugLoc(MI);
1091
1092 ArtifactValueFinder Finder(MRI, Builder, LI);
1093 if (Finder.tryCombineUnmergeDefs(MI, Observer, UpdatedDefs)) {
1094 markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);
1095 return true;
1096 }
1097
1098 if (auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
1099 // %0:_(<4 x s16>) = G_FOO
1100 // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0
1101 // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1
1102 //
1103 // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0
1104 Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
1105 LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);
1106
1107 // If we need to decrease the number of vector elements in the result type
1108 // of an unmerge, this would involve the creation of an equivalent unmerge
1109 // to copy back to the original result registers.
1110 LegalizeActionStep ActionStep = LI.getAction(
1111 {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
1112 switch (ActionStep.Action) {
1114 if (!OpTy.isVector() || !LI.isLegal({TargetOpcode::G_UNMERGE_VALUES,
1115 {DestTy, SrcUnmergeSrcTy}}))
1116 return false;
1117 break;
1120 break;
1123 if (ActionStep.TypeIdx == 1)
1124 return false;
1125 break;
1126 default:
1127 return false;
1128 }
1129
1130 auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
1131
1132 // TODO: Should we try to process out the other defs now? If the other
1133 // defs of the source unmerge are also unmerged, we end up with a separate
1134 // unmerge for each one.
1135 for (unsigned I = 0; I != NumDefs; ++I) {
1136 Register Def = MI.getReg(I);
1137 replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I),
1138 MRI, Builder, UpdatedDefs, Observer);
1139 }
1140
1141 markInstAndDefDead(MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1142 return true;
1143 }
1144
1145 MachineInstr *MergeI = SrcDef;
1146 unsigned ConvertOp = 0;
1147
1148 // Handle intermediate conversions
1149 unsigned SrcOp = SrcDef->getOpcode();
1150 if (isArtifactCast(SrcOp)) {
1151 ConvertOp = SrcOp;
1152 MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI);
1153 }
1154
1155 if (!MergeI || !canFoldMergeOpcode(MergeI->getOpcode(),
1156 ConvertOp, OpTy, DestTy)) {
1157 // We might have a chance to combine later by trying to combine
1158 // unmerge(cast) first
1159 return tryFoldUnmergeCast(MI, *SrcDef, DeadInsts, UpdatedDefs);
1160 }
1161
1162 const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
1163
1164 if (NumMergeRegs < NumDefs) {
1165 if (NumDefs % NumMergeRegs != 0)
1166 return false;
1167
1168 Builder.setInstr(MI);
1169 // Transform to UNMERGEs, for example
1170 // %1 = G_MERGE_VALUES %4, %5
1171 // %9, %10, %11, %12 = G_UNMERGE_VALUES %1
1172 // to
1173 // %9, %10 = G_UNMERGE_VALUES %4
1174 // %11, %12 = G_UNMERGE_VALUES %5
1175
1176 const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1177 for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
1179 for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
1180 ++j, ++DefIdx)
1181 DstRegs.push_back(MI.getReg(DefIdx));
1182
1183 if (ConvertOp) {
1184 LLT MergeDstTy = MRI.getType(SrcDef->getOperand(0).getReg());
1185
1186 // This is a vector that is being split and casted. Extract to the
1187 // element type, and do the conversion on the scalars (or smaller
1188 // vectors).
1189 LLT MergeEltTy = MergeDstTy.divide(NumMergeRegs);
1190
1191 // Handle split to smaller vectors, with conversions.
1192 // %2(<8 x s8>) = G_CONCAT_VECTORS %0(<4 x s8>), %1(<4 x s8>)
1193 // %3(<8 x s16>) = G_SEXT %2
1194 // %4(<2 x s16>), %5(<2 x s16>), %6(<2 x s16>), %7(<2 x s16>) =
1195 // G_UNMERGE_VALUES %3
1196 //
1197 // =>
1198 //
1199 // %8(<4 x s16>) = G_SEXT %0
1200 // %9(<4 x s16>) = G_SEXT %1
1201 // %4(<2 x s16>), %5(<2 x s16>) = G_UNMERGE_VALUES %8
1202 // %7(<2 x s16>), %7(<2 x s16>) = G_UNMERGE_VALUES %9
1203
1204 Register TmpReg = MRI.createGenericVirtualRegister(MergeEltTy);
1205 Builder.buildInstr(ConvertOp, {TmpReg},
1206 {MergeI->getOperand(Idx + 1).getReg()});
1207 Builder.buildUnmerge(DstRegs, TmpReg);
1208 } else {
1209 Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
1210 }
1211 UpdatedDefs.append(DstRegs.begin(), DstRegs.end());
1212 }
1213
1214 } else if (NumMergeRegs > NumDefs) {
1215 if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1216 return false;
1217
1218 Builder.setInstr(MI);
1219 // Transform to MERGEs
1220 // %6 = G_MERGE_VALUES %17, %18, %19, %20
1221 // %7, %8 = G_UNMERGE_VALUES %6
1222 // to
1223 // %7 = G_MERGE_VALUES %17, %18
1224 // %8 = G_MERGE_VALUES %19, %20
1225
1226 const unsigned NumRegs = NumMergeRegs / NumDefs;
1227 for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1229 for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
1230 ++j, ++Idx)
1231 Regs.push_back(MergeI->getOperand(Idx).getReg());
1232
1233 Register DefReg = MI.getReg(DefIdx);
1234 Builder.buildMergeLikeInstr(DefReg, Regs);
1235 UpdatedDefs.push_back(DefReg);
1236 }
1237
1238 } else {
1239 LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
1240
1241 if (!ConvertOp && DestTy != MergeSrcTy) {
1242 if (DestTy.isPointer())
1243 ConvertOp = TargetOpcode::G_INTTOPTR;
1244 else if (MergeSrcTy.isPointer())
1245 ConvertOp = TargetOpcode::G_PTRTOINT;
1246 else
1247 ConvertOp = TargetOpcode::G_BITCAST;
1248 }
1249
1250 if (ConvertOp) {
1251 Builder.setInstr(MI);
1252
1253 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1254 Register DefReg = MI.getOperand(Idx).getReg();
1255 Register MergeSrc = MergeI->getOperand(Idx + 1).getReg();
1256
1257 if (!MRI.use_empty(DefReg)) {
1258 Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1259 UpdatedDefs.push_back(DefReg);
1260 }
1261 }
1262
1263 markInstAndDefDead(MI, *MergeI, DeadInsts);
1264 return true;
1265 }
1266
1267 assert(DestTy == MergeSrcTy &&
1268 "Bitcast and the other kinds of conversions should "
1269 "have happened earlier");
1270
1271 Builder.setInstr(MI);
1272 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1273 Register DstReg = MI.getOperand(Idx).getReg();
1274 Register SrcReg = MergeI->getOperand(Idx + 1).getReg();
1275 replaceRegOrBuildCopy(DstReg, SrcReg, MRI, Builder, UpdatedDefs,
1276 Observer);
1277 }
1278 }
1279
1280 markInstAndDefDead(MI, *MergeI, DeadInsts);
1281 return true;
1282 }
1283
1286 SmallVectorImpl<Register> &UpdatedDefs) {
1287 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
1288
1289 // Try to use the source registers from a G_MERGE_VALUES
1290 //
1291 // %2 = G_MERGE_VALUES %0, %1
1292 // %3 = G_EXTRACT %2, N
1293 // =>
1294 //
1295 // for N < %2.getSizeInBits() / 2
1296 // %3 = G_EXTRACT %0, N
1297 //
1298 // for N >= %2.getSizeInBits() / 2
1299 // %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
1300
1301 Register DstReg = MI.getOperand(0).getReg();
1302 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
1303 MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
1304 if (MergeI && MergeI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) {
1305 Builder.setInstrAndDebugLoc(MI);
1306 Builder.buildUndef(DstReg);
1307 UpdatedDefs.push_back(DstReg);
1308 markInstAndDefDead(MI, *MergeI, DeadInsts);
1309 return true;
1310 }
1311 if (!MergeI || !isa<GMergeLikeInstr>(MergeI))
1312 return false;
1313
1314 LLT DstTy = MRI.getType(DstReg);
1315 LLT SrcTy = MRI.getType(SrcReg);
1316
1317 // TODO: Do we need to check if the resulting extract is supported?
1318 unsigned ExtractDstSize = DstTy.getSizeInBits();
1319 unsigned Offset = MI.getOperand(2).getImm();
1320 unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
1321 unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
1322 unsigned MergeSrcIdx = Offset / MergeSrcSize;
1323
1324 // Compute the offset of the last bit the extract needs.
1325 unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
1326
1327 // Can't handle the case where the extract spans multiple inputs.
1328 if (MergeSrcIdx != EndMergeSrcIdx)
1329 return false;
1330
1331 // TODO: We could modify MI in place in most cases.
1332 Builder.setInstr(MI);
1333 Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(),
1334 Offset - MergeSrcIdx * MergeSrcSize);
1335 UpdatedDefs.push_back(DstReg);
1336 markInstAndDefDead(MI, *MergeI, DeadInsts);
1337 return true;
1338 }
1339
1340 /// Try to combine away MI.
1341 /// Returns true if it combined away the MI.
1342 /// Adds instructions that are dead as a result of the combine
1343 /// into DeadInsts, which can include MI.
1346 GISelObserverWrapper &WrapperObserver) {
1347 ArtifactValueFinder Finder(MRI, Builder, LI);
1348
1349 // This might be a recursive call, and we might have DeadInsts already
1350 // populated. To avoid bad things happening later with multiple vreg defs
1351 // etc, process the dead instructions now if any.
1352 if (!DeadInsts.empty())
1353 deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1354
1355 // Put here every vreg that was redefined in such a way that it's at least
1356 // possible that one (or more) of its users (immediate or COPY-separated)
1357 // could become artifact combinable with the new definition (or the
1358 // instruction reachable from it through a chain of copies if any).
1359 SmallVector<Register, 4> UpdatedDefs;
1360 bool Changed = false;
1361 switch (MI.getOpcode()) {
1362 default:
1363 return false;
1364 case TargetOpcode::G_ANYEXT:
1365 Changed = tryCombineAnyExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1366 break;
1367 case TargetOpcode::G_ZEXT:
1368 Changed = tryCombineZExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1369 break;
1370 case TargetOpcode::G_SEXT:
1371 Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1372 break;
1373 case TargetOpcode::G_UNMERGE_VALUES:
1375 UpdatedDefs, WrapperObserver);
1376 break;
1377 case TargetOpcode::G_MERGE_VALUES:
1378 case TargetOpcode::G_BUILD_VECTOR:
1379 case TargetOpcode::G_CONCAT_VECTORS:
1380 // If any of the users of this merge are an unmerge, then add them to the
1381 // artifact worklist in case there's folding that can be done looking up.
1382 for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) {
1383 if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1384 U.getOpcode() == TargetOpcode::G_TRUNC) {
1385 UpdatedDefs.push_back(MI.getOperand(0).getReg());
1386 break;
1387 }
1388 }
1390 UpdatedDefs, WrapperObserver);
1391 break;
1392 case TargetOpcode::G_EXTRACT:
1393 Changed = tryCombineExtract(MI, DeadInsts, UpdatedDefs);
1394 break;
1395 case TargetOpcode::G_TRUNC:
1396 Changed = tryCombineTrunc(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1397 if (!Changed) {
1398 // Try to combine truncates away even if they are legal. As all artifact
1399 // combines at the moment look only "up" the def-use chains, we achieve
1400 // that by throwing truncates' users (with look through copies) into the
1401 // ArtifactList again.
1402 UpdatedDefs.push_back(MI.getOperand(0).getReg());
1403 }
1404 break;
1405 }
1406 // If the main loop through the ArtifactList found at least one combinable
1407 // pair of artifacts, not only combine it away (as done above), but also
1408 // follow the def-use chain from there to combine everything that can be
1409 // combined within this def-use chain of artifacts.
1410 while (!UpdatedDefs.empty()) {
1411 Register NewDef = UpdatedDefs.pop_back_val();
1412 assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg");
1413 for (MachineInstr &Use : MRI.use_instructions(NewDef)) {
1414 switch (Use.getOpcode()) {
1415 // Keep this list in sync with the list of all artifact combines.
1416 case TargetOpcode::G_ANYEXT:
1417 case TargetOpcode::G_ZEXT:
1418 case TargetOpcode::G_SEXT:
1419 case TargetOpcode::G_UNMERGE_VALUES:
1420 case TargetOpcode::G_EXTRACT:
1421 case TargetOpcode::G_TRUNC:
1422 case TargetOpcode::G_BUILD_VECTOR:
1423 // Adding Use to ArtifactList.
1424 WrapperObserver.changedInstr(Use);
1425 break;
1426 case TargetOpcode::G_ASSERT_SEXT:
1427 case TargetOpcode::G_ASSERT_ZEXT:
1428 case TargetOpcode::G_ASSERT_ALIGN:
1429 case TargetOpcode::COPY: {
1430 Register Copy = Use.getOperand(0).getReg();
1431 if (Copy.isVirtual())
1432 UpdatedDefs.push_back(Copy);
1433 break;
1434 }
1435 default:
1436 // If we do not have an artifact combine for the opcode, there is no
1437 // point in adding it to the ArtifactList as nothing interesting will
1438 // be done to it anyway.
1439 break;
1440 }
1441 }
1442 }
1443 return Changed;
1444 }
1445
1446private:
1447 static Register getArtifactSrcReg(const MachineInstr &MI) {
1448 switch (MI.getOpcode()) {
1449 case TargetOpcode::COPY:
1450 case TargetOpcode::G_TRUNC:
1451 case TargetOpcode::G_ZEXT:
1452 case TargetOpcode::G_ANYEXT:
1453 case TargetOpcode::G_SEXT:
1454 case TargetOpcode::G_EXTRACT:
1455 case TargetOpcode::G_ASSERT_SEXT:
1456 case TargetOpcode::G_ASSERT_ZEXT:
1457 case TargetOpcode::G_ASSERT_ALIGN:
1458 return MI.getOperand(1).getReg();
1459 case TargetOpcode::G_UNMERGE_VALUES:
1460 return MI.getOperand(MI.getNumOperands() - 1).getReg();
1461 default:
1462 llvm_unreachable("Not a legalization artifact happen");
1463 }
1464 }
1465
1466 /// Mark a def of one of MI's original operands, DefMI, as dead if changing MI
1467 /// (either by killing it or changing operands) results in DefMI being dead
1468 /// too. In-between COPYs or artifact-casts are also collected if they are
1469 /// dead.
1470 /// MI is not marked dead.
1471 void markDefDead(MachineInstr &MI, MachineInstr &DefMI,
1473 unsigned DefIdx = 0) {
1474 // Collect all the copy instructions that are made dead, due to deleting
1475 // this instruction. Collect all of them until the Trunc(DefMI).
1476 // Eg,
1477 // %1(s1) = G_TRUNC %0(s32)
1478 // %2(s1) = COPY %1(s1)
1479 // %3(s1) = COPY %2(s1)
1480 // %4(s32) = G_ANYEXT %3(s1)
1481 // In this case, we would have replaced %4 with a copy of %0,
1482 // and as a result, %3, %2, %1 are dead.
1483 MachineInstr *PrevMI = &MI;
1484 while (PrevMI != &DefMI) {
1485 Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1486
1487 MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
1488 if (MRI.hasOneUse(PrevRegSrc)) {
1489 if (TmpDef != &DefMI) {
1490 assert((TmpDef->getOpcode() == TargetOpcode::COPY ||
1491 isArtifactCast(TmpDef->getOpcode()) ||
1493 "Expecting copy or artifact cast here");
1494
1495 DeadInsts.push_back(TmpDef);
1496 }
1497 } else
1498 break;
1499 PrevMI = TmpDef;
1500 }
1501
1502 if (PrevMI == &DefMI) {
1503 unsigned I = 0;
1504 bool IsDead = true;
1505 for (MachineOperand &Def : DefMI.defs()) {
1506 if (I != DefIdx) {
1507 if (!MRI.use_empty(Def.getReg())) {
1508 IsDead = false;
1509 break;
1510 }
1511 } else {
1512 if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg()))
1513 break;
1514 }
1515
1516 ++I;
1517 }
1518
1519 if (IsDead)
1520 DeadInsts.push_back(&DefMI);
1521 }
1522 }
1523
1524 /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
1525 /// dead due to MI being killed, then mark DefMI as dead too.
1526 /// Some of the combines (extends(trunc)), try to walk through redundant
1527 /// copies in between the extends and the truncs, and this attempts to collect
1528 /// the in between copies if they're dead.
1529 void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
1531 unsigned DefIdx = 0) {
1532 DeadInsts.push_back(&MI);
1533 markDefDead(MI, DefMI, DeadInsts, DefIdx);
1534 }
1535
1536 /// Erase the dead instructions in the list and call the observer hooks.
1537 /// Normally the Legalizer will deal with erasing instructions that have been
1538 /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to
1539 /// process instructions which have been marked dead, but otherwise break the
1540 /// MIR by introducing multiple vreg defs. For those cases, allow the combines
1541 /// to explicitly delete the instructions before we run into trouble.
1542 void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts,
1543 GISelObserverWrapper &WrapperObserver) {
1544 for (auto *DeadMI : DeadInsts) {
1545 LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");
1546 WrapperObserver.erasingInstr(*DeadMI);
1547 DeadMI->eraseFromParent();
1548 }
1549 DeadInsts.clear();
1550 }
1551
1552 /// Checks if the target legalizer info has specified anything about the
1553 /// instruction, or if unsupported.
1554 bool isInstUnsupported(const LegalityQuery &Query) const {
1555 using namespace LegalizeActions;
1556 auto Step = LI.getAction(Query);
1557 return Step.Action == Unsupported || Step.Action == NotFound;
1558 }
1559
1560 bool isInstLegal(const LegalityQuery &Query) const {
1561 return LI.getAction(Query).Action == LegalizeActions::Legal;
1562 }
1563
1564 bool isConstantUnsupported(LLT Ty) const {
1565 if (!Ty.isVector())
1566 return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1567
1568 LLT EltTy = Ty.getElementType();
1569 return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1570 isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
1571 }
1572
1573 /// Looks through copy instructions and returns the actual
1574 /// source register.
1575 Register lookThroughCopyInstrs(Register Reg) {
1577 return TmpReg.isValid() ? TmpReg : Reg;
1578 }
1579};
1580
1581} // namespace llvm
1582
1583#endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZATIONARTIFACTCOMBINER_H
unsigned const MachineRegisterInfo * MRI
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")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
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...
IRTranslator LLVM IR MI
Interface for Targets to specify which operations they can successfully select and how the others sho...
#define I(x, y, z)
Definition MD5.cpp:58
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
bool IsDead
This file implements the SmallBitVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:114
static constexpr int Concat[]
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:235
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1012
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...
Definition DebugLoc.cpp:183
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:310
Represents a G_BUILD_VECTOR.
Represents a G_CONCAT_VECTORS.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Simple wrapper observer that takes several observers, and calls each one for each event.
void changedInstr(MachineInstr &MI) override
This instruction was mutated in some way.
void changingInstr(MachineInstr &MI) override
This instruction is about to be mutated in some way.
void erasingInstr(MachineInstr &MI) override
An instruction is about to be erased.
Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES.
Register getSourceReg(unsigned I) const
Returns the I'th source register.
unsigned getNumSources() const
Returns the number of source registers.
Represents a G_UNMERGE_VALUES.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr LLT getScalarType() const
constexpr LLT divide(int Factor) const
Return a type that is Factor times smaller.
This class provides utilities for finding source registers of specific bit ranges in an artifact.
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 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.
Definition Register.h:19
constexpr bool isValid() const
Definition Register.h:107
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:74
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.
Definition Use.h:35
Changed
#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...
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)
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
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
Definition Utils.cpp:651
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:492
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.
Definition Utils.cpp:201
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
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...
Definition Casting.h:547
LLVM_ABI LLVM_READNONE LLT getCoverTy(LLT OrigTy, LLT TargetTy)
Return smallest type that covers both OrigTy and TargetTy and is multiple of TargetTy.
Definition Utils.cpp:1255
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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.
Definition Utils.cpp:467
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:499
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
The result of a query.
LegalizeAction Action
The action to take or the final answer.
unsigned TypeIdx
If describing an action, the type index to change. Otherwise zero.