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