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