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