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
1005 // Recognize copy of UnmergeSrc to Dst.
1006 // Unmerge UnmergeSrc and reassemble it using merge-like opcode into Dst.
1007 //
1008 // %0:_(EltTy), %1, ... = G_UNMERGE_VALUES %UnmergeSrc:_(Ty)
1009 // %Dst:_(Ty) = G_merge_like_opcode %0:_(EltTy), %1, ...
1010 //
1011 // %Dst:_(Ty) = COPY %UnmergeSrc:_(Ty)
1012 if ((DstTy == UnmergeSrcTy) && (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 (((!DstTy.isVector() && !UnmergeSrcTy.isVector()) ||
1034 (DstTy.isVector() && UnmergeSrcTy.isVector() &&
1035 DstTy.getScalarType() == UnmergeSrcTy.getScalarType())) &&
1036 (Elt0UnmergeIdx % NumMIElts == 0) &&
1037 getCoverTy(UnmergeSrcTy, DstTy) == UnmergeSrcTy) {
1038 if (!isSequenceFromUnmerge(MI, 0, Unmerge, Elt0UnmergeIdx, NumMIElts,
1039 EltSize, false))
1040 return false;
1041 MIB.setInstrAndDebugLoc(MI);
1042 auto NewUnmerge = MIB.buildUnmerge(DstTy, Unmerge->getSourceReg());
1043 unsigned DstIdx = (Elt0UnmergeIdx * EltSize) / DstTy.getSizeInBits();
1044 replaceRegOrBuildCopy(Dst, NewUnmerge.getReg(DstIdx), MRI, MIB,
1045 UpdatedDefs, Observer);
1046 DeadInsts.push_back(&MI);
1047 return true;
1048 }
1049
1050 // Recognize when multiple unmerged sources with UnmergeSrcTy type
1051 // can be merged into Dst with DstTy type directly.
1052 // Types have to be either both vector or both non-vector types.
1053
1054 // %0:_(EltTy), %1 = G_UNMERGE_VALUES %UnmergeSrc:_(UnmergeSrcTy)
1055 // %2:_(EltTy), %3 = G_UNMERGE_VALUES %AnotherUnmergeSrc:_(UnmergeSrcTy)
1056 // %Dst:_(DstTy) = G_merge_like_opcode %0:_(EltTy), %1, %2, %3
1057 //
1058 // %Dst:_(DstTy) = G_merge_like_opcode %UnmergeSrc, %AnotherUnmergeSrc
1059
1060 if ((DstTy.isVector() == UnmergeSrcTy.isVector()) &&
1061 getCoverTy(DstTy, UnmergeSrcTy) == DstTy) {
1062 SmallVector<Register, 4> ConcatSources;
1063 unsigned NumElts = Unmerge->getNumDefs();
1064 for (unsigned i = 0; i < MI.getNumSources(); i += NumElts) {
1065 unsigned EltUnmergeIdx;
1066 auto *UnmergeI = findUnmergeThatDefinesReg(MI.getSourceReg(i),
1067 EltSize, EltUnmergeIdx);
1068 // All unmerges have to be the same size.
1069 if ((!UnmergeI) || (UnmergeI->getNumDefs() != NumElts) ||
1070 (EltUnmergeIdx != 0))
1071 return false;
1072 if (!isSequenceFromUnmerge(MI, i, UnmergeI, 0, NumElts, EltSize,
1073 false))
1074 return false;
1075 ConcatSources.push_back(UnmergeI->getSourceReg());
1076 }
1077
1078 MIB.setInstrAndDebugLoc(MI);
1079 MIB.buildMergeLikeInstr(Dst, ConcatSources);
1080 DeadInsts.push_back(&MI);
1081 return true;
1082 }
1083
1084 return false;
1085 }
1086 };
1087
1090 SmallVectorImpl<Register> &UpdatedDefs,
1091 GISelChangeObserver &Observer) {
1092 unsigned NumDefs = MI.getNumDefs();
1093 Register SrcReg = MI.getSourceReg();
1094 std::optional<DefinitionAndSourceRegister> DefSrcReg =
1095 getDefSrcRegIgnoringCopies(SrcReg, MRI);
1096 if (!DefSrcReg)
1097 return false;
1098 MachineInstr *SrcDef = DefSrcReg->MI;
1099
1100 LLT OpTy = MRI.getType(SrcReg);
1101 LLT DestTy = MRI.getType(MI.getReg(0));
1102 unsigned SrcDefIdx = getDefIndex(*SrcDef, DefSrcReg->Reg);
1103
1104 Builder.setInstrAndDebugLoc(MI);
1105
1106 ArtifactValueFinder Finder(MRI, Builder, LI);
1107 if (Finder.tryCombineUnmergeDefs(MI, Observer, UpdatedDefs)) {
1108 markInstAndDefDead(MI, *SrcDef, DeadInsts, SrcDefIdx);
1109 return true;
1110 }
1111
1112 if (auto *SrcUnmerge = dyn_cast<GUnmerge>(SrcDef)) {
1113 // %0:_(<4 x s16>) = G_FOO
1114 // %1:_(<2 x s16>), %2:_(<2 x s16>) = G_UNMERGE_VALUES %0
1115 // %3:_(s16), %4:_(s16) = G_UNMERGE_VALUES %1
1116 //
1117 // %3:_(s16), %4:_(s16), %5:_(s16), %6:_(s16) = G_UNMERGE_VALUES %0
1118 Register SrcUnmergeSrc = SrcUnmerge->getSourceReg();
1119 LLT SrcUnmergeSrcTy = MRI.getType(SrcUnmergeSrc);
1120
1121 // If we need to decrease the number of vector elements in the result type
1122 // of an unmerge, this would involve the creation of an equivalent unmerge
1123 // to copy back to the original result registers.
1124 LegalizeActionStep ActionStep = LI.getAction(
1125 {TargetOpcode::G_UNMERGE_VALUES, {OpTy, SrcUnmergeSrcTy}});
1126 switch (ActionStep.Action) {
1128 if (!OpTy.isVector() || !LI.isLegal({TargetOpcode::G_UNMERGE_VALUES,
1129 {DestTy, SrcUnmergeSrcTy}}))
1130 return false;
1131 break;
1134 break;
1137 if (ActionStep.TypeIdx == 1)
1138 return false;
1139 break;
1140 default:
1141 return false;
1142 }
1143
1144 auto NewUnmerge = Builder.buildUnmerge(DestTy, SrcUnmergeSrc);
1145
1146 // TODO: Should we try to process out the other defs now? If the other
1147 // defs of the source unmerge are also unmerged, we end up with a separate
1148 // unmerge for each one.
1149 for (unsigned I = 0; I != NumDefs; ++I) {
1150 Register Def = MI.getReg(I);
1151 replaceRegOrBuildCopy(Def, NewUnmerge.getReg(SrcDefIdx * NumDefs + I),
1152 MRI, Builder, UpdatedDefs, Observer);
1153 }
1154
1155 markInstAndDefDead(MI, *SrcUnmerge, DeadInsts, SrcDefIdx);
1156 return true;
1157 }
1158
1159 MachineInstr *MergeI = SrcDef;
1160 unsigned ConvertOp = 0;
1161
1162 // Handle intermediate conversions
1163 unsigned SrcOp = SrcDef->getOpcode();
1164 if (isArtifactCast(SrcOp)) {
1165 ConvertOp = SrcOp;
1166 MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI);
1167 }
1168
1169 if (!MergeI || !canFoldMergeOpcode(MergeI->getOpcode(),
1170 ConvertOp, OpTy, DestTy)) {
1171 // We might have a chance to combine later by trying to combine
1172 // unmerge(cast) first
1173 return tryFoldUnmergeCast(MI, *SrcDef, DeadInsts, UpdatedDefs);
1174 }
1175
1176 const unsigned NumMergeRegs = MergeI->getNumOperands() - 1;
1177
1178 if (NumMergeRegs < NumDefs) {
1179 if (NumDefs % NumMergeRegs != 0)
1180 return false;
1181
1182 Builder.setInstr(MI);
1183 // Transform to UNMERGEs, for example
1184 // %1 = G_MERGE_VALUES %4, %5
1185 // %9, %10, %11, %12 = G_UNMERGE_VALUES %1
1186 // to
1187 // %9, %10 = G_UNMERGE_VALUES %4
1188 // %11, %12 = G_UNMERGE_VALUES %5
1189
1190 const unsigned NewNumDefs = NumDefs / NumMergeRegs;
1191 for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
1193 for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
1194 ++j, ++DefIdx)
1195 DstRegs.push_back(MI.getReg(DefIdx));
1196
1197 if (ConvertOp) {
1198 LLT MergeDstTy = MRI.getType(SrcDef->getOperand(0).getReg());
1199
1200 // This is a vector that is being split and casted. Extract to the
1201 // element type, and do the conversion on the scalars (or smaller
1202 // vectors).
1203 LLT MergeEltTy = MergeDstTy.divide(NumMergeRegs);
1204
1205 // Handle split to smaller vectors, with conversions.
1206 // %2(<8 x s8>) = G_CONCAT_VECTORS %0(<4 x s8>), %1(<4 x s8>)
1207 // %3(<8 x s16>) = G_SEXT %2
1208 // %4(<2 x s16>), %5(<2 x s16>), %6(<2 x s16>), %7(<2 x s16>) =
1209 // G_UNMERGE_VALUES %3
1210 //
1211 // =>
1212 //
1213 // %8(<4 x s16>) = G_SEXT %0
1214 // %9(<4 x s16>) = G_SEXT %1
1215 // %4(<2 x s16>), %5(<2 x s16>) = G_UNMERGE_VALUES %8
1216 // %7(<2 x s16>), %7(<2 x s16>) = G_UNMERGE_VALUES %9
1217
1218 Register TmpReg = MRI.createGenericVirtualRegister(MergeEltTy);
1219 Builder.buildInstr(ConvertOp, {TmpReg},
1220 {MergeI->getOperand(Idx + 1).getReg()});
1221 Builder.buildUnmerge(DstRegs, TmpReg);
1222 } else {
1223 Builder.buildUnmerge(DstRegs, MergeI->getOperand(Idx + 1).getReg());
1224 }
1225 UpdatedDefs.append(DstRegs.begin(), DstRegs.end());
1226 }
1227
1228 } else if (NumMergeRegs > NumDefs) {
1229 if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0)
1230 return false;
1231
1232 Builder.setInstr(MI);
1233 // Transform to MERGEs
1234 // %6 = G_MERGE_VALUES %17, %18, %19, %20
1235 // %7, %8 = G_UNMERGE_VALUES %6
1236 // to
1237 // %7 = G_MERGE_VALUES %17, %18
1238 // %8 = G_MERGE_VALUES %19, %20
1239
1240 const unsigned NumRegs = NumMergeRegs / NumDefs;
1241 for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
1243 for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
1244 ++j, ++Idx)
1245 Regs.push_back(MergeI->getOperand(Idx).getReg());
1246
1247 Register DefReg = MI.getReg(DefIdx);
1248 Builder.buildMergeLikeInstr(DefReg, Regs);
1249 UpdatedDefs.push_back(DefReg);
1250 }
1251
1252 } else {
1253 LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg());
1254
1255 if (!ConvertOp && DestTy != MergeSrcTy) {
1256 if (DestTy.isPointer())
1257 ConvertOp = TargetOpcode::G_INTTOPTR;
1258 else if (MergeSrcTy.isPointer())
1259 ConvertOp = TargetOpcode::G_PTRTOINT;
1260 else
1261 ConvertOp = TargetOpcode::G_BITCAST;
1262 }
1263
1264 if (ConvertOp) {
1265 Builder.setInstr(MI);
1266
1267 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1268 Register DefReg = MI.getOperand(Idx).getReg();
1269 Register MergeSrc = MergeI->getOperand(Idx + 1).getReg();
1270
1271 if (!MRI.use_empty(DefReg)) {
1272 Builder.buildInstr(ConvertOp, {DefReg}, {MergeSrc});
1273 UpdatedDefs.push_back(DefReg);
1274 }
1275 }
1276
1277 markInstAndDefDead(MI, *MergeI, DeadInsts);
1278 return true;
1279 }
1280
1281 assert(DestTy == MergeSrcTy &&
1282 "Bitcast and the other kinds of conversions should "
1283 "have happened earlier");
1284
1285 Builder.setInstr(MI);
1286 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1287 Register DstReg = MI.getOperand(Idx).getReg();
1288 Register SrcReg = MergeI->getOperand(Idx + 1).getReg();
1289 replaceRegOrBuildCopy(DstReg, SrcReg, MRI, Builder, UpdatedDefs,
1290 Observer);
1291 }
1292 }
1293
1294 markInstAndDefDead(MI, *MergeI, DeadInsts);
1295 return true;
1296 }
1297
1300 SmallVectorImpl<Register> &UpdatedDefs) {
1301 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT);
1302
1303 // Try to use the source registers from a G_MERGE_VALUES
1304 //
1305 // %2 = G_MERGE_VALUES %0, %1
1306 // %3 = G_EXTRACT %2, N
1307 // =>
1308 //
1309 // for N < %2.getSizeInBits() / 2
1310 // %3 = G_EXTRACT %0, N
1311 //
1312 // for N >= %2.getSizeInBits() / 2
1313 // %3 = G_EXTRACT %1, (N - %0.getSizeInBits()
1314
1315 Register DstReg = MI.getOperand(0).getReg();
1316 Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
1317 MachineInstr *MergeI = MRI.getVRegDef(SrcReg);
1318 if (MergeI && MergeI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) {
1319 Builder.setInstrAndDebugLoc(MI);
1320 Builder.buildUndef(DstReg);
1321 UpdatedDefs.push_back(DstReg);
1322 markInstAndDefDead(MI, *MergeI, DeadInsts);
1323 return true;
1324 }
1325 if (!MergeI || !isa<GMergeLikeInstr>(MergeI))
1326 return false;
1327
1328 LLT DstTy = MRI.getType(DstReg);
1329 LLT SrcTy = MRI.getType(SrcReg);
1330
1331 // TODO: Do we need to check if the resulting extract is supported?
1332 unsigned ExtractDstSize = DstTy.getSizeInBits();
1333 unsigned Offset = MI.getOperand(2).getImm();
1334 unsigned NumMergeSrcs = MergeI->getNumOperands() - 1;
1335 unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs;
1336 unsigned MergeSrcIdx = Offset / MergeSrcSize;
1337
1338 // Compute the offset of the last bit the extract needs.
1339 unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize;
1340
1341 // Can't handle the case where the extract spans multiple inputs.
1342 if (MergeSrcIdx != EndMergeSrcIdx)
1343 return false;
1344
1345 // TODO: We could modify MI in place in most cases.
1346 Builder.setInstr(MI);
1347 Builder.buildExtract(DstReg, MergeI->getOperand(MergeSrcIdx + 1).getReg(),
1348 Offset - MergeSrcIdx * MergeSrcSize);
1349 UpdatedDefs.push_back(DstReg);
1350 markInstAndDefDead(MI, *MergeI, DeadInsts);
1351 return true;
1352 }
1353
1354 /// Try to combine away MI.
1355 /// Returns true if it combined away the MI.
1356 /// Adds instructions that are dead as a result of the combine
1357 /// into DeadInsts, which can include MI.
1360 GISelObserverWrapper &WrapperObserver) {
1361 ArtifactValueFinder Finder(MRI, Builder, LI);
1362
1363 // This might be a recursive call, and we might have DeadInsts already
1364 // populated. To avoid bad things happening later with multiple vreg defs
1365 // etc, process the dead instructions now if any.
1366 if (!DeadInsts.empty())
1367 deleteMarkedDeadInsts(DeadInsts, WrapperObserver);
1368
1369 // Put here every vreg that was redefined in such a way that it's at least
1370 // possible that one (or more) of its users (immediate or COPY-separated)
1371 // could become artifact combinable with the new definition (or the
1372 // instruction reachable from it through a chain of copies if any).
1373 SmallVector<Register, 4> UpdatedDefs;
1374 bool Changed = false;
1375 switch (MI.getOpcode()) {
1376 default:
1377 return false;
1378 case TargetOpcode::G_ANYEXT:
1379 Changed = tryCombineAnyExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1380 break;
1381 case TargetOpcode::G_ZEXT:
1382 Changed = tryCombineZExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1383 break;
1384 case TargetOpcode::G_SEXT:
1385 Changed = tryCombineSExt(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1386 break;
1387 case TargetOpcode::G_UNMERGE_VALUES:
1389 UpdatedDefs, WrapperObserver);
1390 break;
1391 case TargetOpcode::G_MERGE_VALUES:
1392 case TargetOpcode::G_BUILD_VECTOR:
1393 case TargetOpcode::G_CONCAT_VECTORS:
1394 // If any of the users of this merge are an unmerge, then add them to the
1395 // artifact worklist in case there's folding that can be done looking up.
1396 for (MachineInstr &U : MRI.use_instructions(MI.getOperand(0).getReg())) {
1397 if (U.getOpcode() == TargetOpcode::G_UNMERGE_VALUES ||
1398 U.getOpcode() == TargetOpcode::G_TRUNC) {
1399 UpdatedDefs.push_back(MI.getOperand(0).getReg());
1400 break;
1401 }
1402 }
1404 UpdatedDefs, WrapperObserver);
1405 break;
1406 case TargetOpcode::G_EXTRACT:
1407 Changed = tryCombineExtract(MI, DeadInsts, UpdatedDefs);
1408 break;
1409 case TargetOpcode::G_TRUNC:
1410 Changed = tryCombineTrunc(MI, DeadInsts, UpdatedDefs, WrapperObserver);
1411 if (!Changed) {
1412 // Try to combine truncates away even if they are legal. As all artifact
1413 // combines at the moment look only "up" the def-use chains, we achieve
1414 // that by throwing truncates' users (with look through copies) into the
1415 // ArtifactList again.
1416 UpdatedDefs.push_back(MI.getOperand(0).getReg());
1417 }
1418 break;
1419 }
1420 // If the main loop through the ArtifactList found at least one combinable
1421 // pair of artifacts, not only combine it away (as done above), but also
1422 // follow the def-use chain from there to combine everything that can be
1423 // combined within this def-use chain of artifacts.
1424 while (!UpdatedDefs.empty()) {
1425 Register NewDef = UpdatedDefs.pop_back_val();
1426 assert(NewDef.isVirtual() && "Unexpected redefinition of a physreg");
1427 for (MachineInstr &Use : MRI.use_instructions(NewDef)) {
1428 switch (Use.getOpcode()) {
1429 // Keep this list in sync with the list of all artifact combines.
1430 case TargetOpcode::G_ANYEXT:
1431 case TargetOpcode::G_ZEXT:
1432 case TargetOpcode::G_SEXT:
1433 case TargetOpcode::G_UNMERGE_VALUES:
1434 case TargetOpcode::G_EXTRACT:
1435 case TargetOpcode::G_TRUNC:
1436 case TargetOpcode::G_BUILD_VECTOR:
1437 // Adding Use to ArtifactList.
1438 WrapperObserver.changedInstr(Use);
1439 break;
1440 case TargetOpcode::G_ASSERT_SEXT:
1441 case TargetOpcode::G_ASSERT_ZEXT:
1442 case TargetOpcode::G_ASSERT_ALIGN:
1443 case TargetOpcode::COPY: {
1444 Register Copy = Use.getOperand(0).getReg();
1445 if (Copy.isVirtual())
1446 UpdatedDefs.push_back(Copy);
1447 break;
1448 }
1449 default:
1450 // If we do not have an artifact combine for the opcode, there is no
1451 // point in adding it to the ArtifactList as nothing interesting will
1452 // be done to it anyway.
1453 break;
1454 }
1455 }
1456 }
1457 return Changed;
1458 }
1459
1460private:
1461 static Register getArtifactSrcReg(const MachineInstr &MI) {
1462 switch (MI.getOpcode()) {
1463 case TargetOpcode::COPY:
1464 case TargetOpcode::G_TRUNC:
1465 case TargetOpcode::G_ZEXT:
1466 case TargetOpcode::G_ANYEXT:
1467 case TargetOpcode::G_SEXT:
1468 case TargetOpcode::G_EXTRACT:
1469 case TargetOpcode::G_ASSERT_SEXT:
1470 case TargetOpcode::G_ASSERT_ZEXT:
1471 case TargetOpcode::G_ASSERT_ALIGN:
1472 return MI.getOperand(1).getReg();
1473 case TargetOpcode::G_UNMERGE_VALUES:
1474 return MI.getOperand(MI.getNumOperands() - 1).getReg();
1475 default:
1476 llvm_unreachable("Not a legalization artifact happen");
1477 }
1478 }
1479
1480 /// Mark a def of one of MI's original operands, DefMI, as dead if changing MI
1481 /// (either by killing it or changing operands) results in DefMI being dead
1482 /// too. In-between COPYs or artifact-casts are also collected if they are
1483 /// dead.
1484 /// MI is not marked dead.
1485 void markDefDead(MachineInstr &MI, MachineInstr &DefMI,
1487 unsigned DefIdx = 0) {
1488 // Collect all the copy instructions that are made dead, due to deleting
1489 // this instruction. Collect all of them until the Trunc(DefMI).
1490 // Eg,
1491 // %1(s1) = G_TRUNC %0(s32)
1492 // %2(s1) = COPY %1(s1)
1493 // %3(s1) = COPY %2(s1)
1494 // %4(s32) = G_ANYEXT %3(s1)
1495 // In this case, we would have replaced %4 with a copy of %0,
1496 // and as a result, %3, %2, %1 are dead.
1497 MachineInstr *PrevMI = &MI;
1498 while (PrevMI != &DefMI) {
1499 Register PrevRegSrc = getArtifactSrcReg(*PrevMI);
1500
1501 MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc);
1502 if (MRI.hasOneUse(PrevRegSrc)) {
1503 if (TmpDef != &DefMI) {
1504 assert((TmpDef->getOpcode() == TargetOpcode::COPY ||
1505 isArtifactCast(TmpDef->getOpcode()) ||
1507 "Expecting copy or artifact cast here");
1508
1509 DeadInsts.push_back(TmpDef);
1510 }
1511 } else
1512 break;
1513 PrevMI = TmpDef;
1514 }
1515
1516 if (PrevMI == &DefMI) {
1517 unsigned I = 0;
1518 bool IsDead = true;
1519 for (MachineOperand &Def : DefMI.defs()) {
1520 if (I != DefIdx) {
1521 if (!MRI.use_empty(Def.getReg())) {
1522 IsDead = false;
1523 break;
1524 }
1525 } else {
1526 if (!MRI.hasOneUse(DefMI.getOperand(DefIdx).getReg()))
1527 break;
1528 }
1529
1530 ++I;
1531 }
1532
1533 if (IsDead)
1534 DeadInsts.push_back(&DefMI);
1535 }
1536 }
1537
1538 /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be
1539 /// dead due to MI being killed, then mark DefMI as dead too.
1540 /// Some of the combines (extends(trunc)), try to walk through redundant
1541 /// copies in between the extends and the truncs, and this attempts to collect
1542 /// the in between copies if they're dead.
1543 void markInstAndDefDead(MachineInstr &MI, MachineInstr &DefMI,
1545 unsigned DefIdx = 0) {
1546 DeadInsts.push_back(&MI);
1547 markDefDead(MI, DefMI, DeadInsts, DefIdx);
1548 }
1549
1550 /// Erase the dead instructions in the list and call the observer hooks.
1551 /// Normally the Legalizer will deal with erasing instructions that have been
1552 /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to
1553 /// process instructions which have been marked dead, but otherwise break the
1554 /// MIR by introducing multiple vreg defs. For those cases, allow the combines
1555 /// to explicitly delete the instructions before we run into trouble.
1556 void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts,
1557 GISelObserverWrapper &WrapperObserver) {
1558 for (auto *DeadMI : DeadInsts) {
1559 LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n");
1560 WrapperObserver.erasingInstr(*DeadMI);
1561 DeadMI->eraseFromParent();
1562 }
1563 DeadInsts.clear();
1564 }
1565
1566 /// Checks if the target legalizer info has specified anything about the
1567 /// instruction, or if unsupported.
1568 bool isInstUnsupported(const LegalityQuery &Query) const {
1569 using namespace LegalizeActions;
1570 auto Step = LI.getAction(Query);
1571 return Step.Action == Unsupported || Step.Action == NotFound;
1572 }
1573
1574 bool isInstLegal(const LegalityQuery &Query) const {
1575 return LI.getAction(Query).Action == LegalizeActions::Legal;
1576 }
1577
1578 bool isConstantUnsupported(LLT Ty) const {
1579 if (!Ty.isVector())
1580 return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}});
1581
1582 LLT EltTy = Ty.getElementType();
1583 return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) ||
1584 isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}});
1585 }
1586
1587 /// Looks through copy instructions and returns the actual
1588 /// source register.
1589 Register lookThroughCopyInstrs(Register Reg) {
1590 Register TmpReg = getSrcRegIgnoringCopies(Reg, MRI);
1591 return TmpReg.isValid() ? TmpReg : Reg;
1592 }
1593};
1594
1595} // namespace llvm
1596
1597#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.