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