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