LLVM 24.0.0git
CombinerHelper.cpp
Go to the documentation of this file.
1//===-- lib/CodeGen/GlobalISel/GICombinerHelper.cpp -----------------------===//
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//===----------------------------------------------------------------------===//
9#include "llvm/ADT/APFloat.h"
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/SetVector.h"
37#include "llvm/IR/DataLayout.h"
38#include "llvm/IR/InstrTypes.h"
45#include <cmath>
46#include <optional>
47#include <tuple>
48
49#define DEBUG_TYPE "gi-combiner"
50
51using namespace llvm;
52using namespace MIPatternMatch;
53
54// Option to allow testing of the combiner while no targets know about indexed
55// addressing.
56static cl::opt<bool>
57 ForceLegalIndexing("force-legal-indexing", cl::Hidden, cl::init(false),
58 cl::desc("Force all indexed operations to be "
59 "legal for the GlobalISel combiner"));
60
65 const LegalizerInfo *LI)
66 : Builder(B), MRI(Builder.getMF().getRegInfo()), Observer(Observer), VT(VT),
68 TII(Builder.getMF().getSubtarget().getInstrInfo()),
69 RBI(Builder.getMF().getSubtarget().getRegBankInfo()),
70 TRI(Builder.getMF().getSubtarget().getRegisterInfo()) {
71 (void)this->VT;
72}
73
75 return *Builder.getMF().getSubtarget().getTargetLowering();
76}
77
79 return Builder.getMF();
80}
81
82LLVMContext &CombinerHelper::getContext() const { return Builder.getContext(); }
83
84/// \returns The little endian in-memory byte position of byte \p I in a
85/// \p ByteWidth bytes wide type.
86///
87/// E.g. Given a 4-byte type x, x[0] -> byte 0
88static unsigned littleEndianByteAt(const unsigned ByteWidth, const unsigned I) {
89 assert(I < ByteWidth && "I must be in [0, ByteWidth)");
90 return I;
91}
92
93/// Determines the LogBase2 value for a non-null input value using the
94/// transform: LogBase2(V) = (EltBits - 1) - ctlz(V).
96 auto &MRI = *MIB.getMRI();
97 LLT Ty = MRI.getType(V);
98 auto Ctlz = MIB.buildCTLZ(Ty, V);
99 auto Base = MIB.buildConstant(Ty, Ty.getScalarSizeInBits() - 1);
100 return MIB.buildSub(Ty, Base, Ctlz).getReg(0);
101}
102
103/// \returns The big endian in-memory byte position of byte \p I in a
104/// \p ByteWidth bytes wide type.
105///
106/// E.g. Given a 4-byte type x, x[0] -> byte 3
107static unsigned bigEndianByteAt(const unsigned ByteWidth, const unsigned I) {
108 assert(I < ByteWidth && "I must be in [0, ByteWidth)");
109 return ByteWidth - I - 1;
110}
111
112/// Given a map from byte offsets in memory to indices in a load/store,
113/// determine if that map corresponds to a little or big endian byte pattern.
114///
115/// \param MemOffset2Idx maps memory offsets to address offsets.
116/// \param LowestIdx is the lowest index in \p MemOffset2Idx.
117///
118/// \returns true if the map corresponds to a big endian byte pattern, false if
119/// it corresponds to a little endian byte pattern, and std::nullopt otherwise.
120///
121/// E.g. given a 32-bit type x, and x[AddrOffset], the in-memory byte patterns
122/// are as follows:
123///
124/// AddrOffset Little endian Big endian
125/// 0 0 3
126/// 1 1 2
127/// 2 2 1
128/// 3 3 0
129static std::optional<bool>
131 int64_t LowestIdx) {
132 // Need at least two byte positions to decide on endianness.
133 unsigned Width = MemOffset2Idx.size();
134 if (Width < 2)
135 return std::nullopt;
136 bool BigEndian = true, LittleEndian = true;
137 for (unsigned MemOffset = 0; MemOffset < Width; ++ MemOffset) {
138 auto MemOffsetAndIdx = MemOffset2Idx.find(MemOffset);
139 if (MemOffsetAndIdx == MemOffset2Idx.end())
140 return std::nullopt;
141 const int64_t Idx = MemOffsetAndIdx->second - LowestIdx;
142 assert(Idx >= 0 && "Expected non-negative byte offset?");
143 LittleEndian &= Idx == littleEndianByteAt(Width, MemOffset);
144 BigEndian &= Idx == bigEndianByteAt(Width, MemOffset);
145 if (!BigEndian && !LittleEndian)
146 return std::nullopt;
147 }
148
149 assert((BigEndian != LittleEndian) &&
150 "Pattern cannot be both big and little endian!");
151 return BigEndian;
152}
153
155
156bool CombinerHelper::isLegal(const LegalityQuery &Query) const {
157 assert(LI && "Must have LegalizerInfo to query isLegal!");
158 return LI->getAction(Query).Action == LegalizeActions::Legal;
159}
160
162 const LegalityQuery &Query) const {
163 return isPreLegalize() || isLegal(Query);
164}
165
167 return isLegal(Query) ||
168 LI->getAction(Query).Action == LegalizeActions::WidenScalar;
169}
170
172 const LegalityQuery &Query) const {
173 LegalizeAction Action = LI->getAction(Query).Action;
174 return Action == LegalizeActions::Legal ||
176}
177
178bool CombinerHelper::isImmConstantLegalOrBeforeLegalizer(unsigned Opc,
179 const LLT Ty) const {
180 if (!Ty.isVector())
181 return isLegalOrBeforeLegalizer({Opc, {Ty}});
182 if (isPreLegalize())
183 return true;
184 // Scalable vectors cannot be constant folded here.
185 if (!Ty.isFixedVector())
186 return false;
187 LLT EltTy = Ty.getElementType();
188 return isLegal({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}}) &&
189 isLegal({Opc, {EltTy}});
190}
191
193 return isImmConstantLegalOrBeforeLegalizer(TargetOpcode::G_CONSTANT, Ty);
194}
195
197 return isImmConstantLegalOrBeforeLegalizer(TargetOpcode::G_FCONSTANT, Ty);
198}
199
201 Register ToReg) const {
202 Observer.changingAllUsesOfReg(MRI, FromReg);
203
204 if (MRI.constrainRegAttrs(ToReg, FromReg))
205 MRI.replaceRegWith(FromReg, ToReg);
206 else
207 Builder.buildCopy(FromReg, ToReg);
208
209 Observer.finishedChangingAllUsesOfReg();
210}
211
213 MachineOperand &FromRegOp,
214 Register ToReg) const {
215 assert(FromRegOp.getParent() && "Expected an operand in an MI");
216 Observer.changingInstr(*FromRegOp.getParent());
217
218 FromRegOp.setReg(ToReg);
219
220 Observer.changedInstr(*FromRegOp.getParent());
221}
222
224 unsigned ToOpcode) const {
225 Observer.changingInstr(FromMI);
226
227 FromMI.setDesc(Builder.getTII().get(ToOpcode));
228
229 Observer.changedInstr(FromMI);
230}
231
233 return RBI->getRegBank(Reg, MRI, *TRI);
234}
235
237 const RegisterBank *RegBank) const {
238 if (RegBank)
239 MRI.setRegBank(Reg, *RegBank);
240}
241
243 if (MI.getOpcode() != TargetOpcode::COPY)
244 return false;
245 Register DstReg = MI.getOperand(0).getReg();
246 Register SrcReg = MI.getOperand(1).getReg();
247 return canReplaceReg(DstReg, SrcReg, MRI);
248}
250 Register DstReg = MI.getOperand(0).getReg();
251 Register SrcReg = MI.getOperand(1).getReg();
252 replaceRegWith(MRI, DstReg, SrcReg);
253 MI.eraseFromParent();
254}
255
257 MachineInstr &MI, BuildFnTy &MatchInfo) const {
258 assert(MI.getOpcode() == TargetOpcode::G_FREEZE && "Invalid instruction");
259
260 // Ported from InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating.
261 Register DstOp = MI.getOperand(0).getReg();
262 Register OrigOp = MI.getOperand(1).getReg();
263
264 if (!MRI.hasOneNonDBGUse(OrigOp))
265 return false;
266
267 MachineInstr *OrigDef;
268 if (!mi_match(OrigOp, MRI, m_MInstr(OrigDef)))
269 return false;
270 // Even if only a single operand of the PHI is not guaranteed non-poison,
271 // moving freeze() backwards across a PHI can cause optimization issues for
272 // other users of that operand.
273 //
274 // Moving freeze() from one of the output registers of a G_UNMERGE_VALUES to
275 // the source register is unprofitable because it makes the freeze() more
276 // strict than is necessary (it would affect the whole register instead of
277 // just the subreg being frozen).
278 if (OrigDef->isPHI() || isa<GUnmerge>(OrigDef))
279 return false;
280
281 if (canCreateUndefOrPoison(OrigOp, MRI,
282 /*ConsiderFlagsAndMetadata=*/false))
283 return false;
284
285 std::optional<MachineOperand> MaybePoisonOperand;
286 for (MachineOperand &Operand : OrigDef->uses()) {
287 if (!Operand.isReg())
288 return false;
289
290 if (isGuaranteedNotToBeUndefOrPoison(Operand.getReg(), MRI))
291 continue;
292
293 if (!MaybePoisonOperand)
294 MaybePoisonOperand = Operand;
295 else {
296 // We have more than one maybe-poison operand. Moving the freeze is
297 // unsafe.
298 return false;
299 }
300 }
301
302 // Eliminate freeze if all operands are guaranteed non-poison.
303 if (!MaybePoisonOperand) {
304 MatchInfo = [=](MachineIRBuilder &B) {
305 Observer.changingInstr(*OrigDef);
306 cast<GenericMachineInstr>(OrigDef)->dropPoisonGeneratingFlags();
307 Observer.changedInstr(*OrigDef);
308 B.buildCopy(DstOp, OrigOp);
309 };
310 return true;
311 }
312
313 Register MaybePoisonOperandReg = MaybePoisonOperand->getReg();
314 LLT MaybePoisonOperandRegTy = MRI.getType(MaybePoisonOperandReg);
315
317 {TargetOpcode::G_FREEZE, {MaybePoisonOperandRegTy}}))
318 return false;
319
320 MatchInfo = [=](MachineIRBuilder &B) mutable {
321 Observer.changingInstr(*OrigDef);
322 cast<GenericMachineInstr>(OrigDef)->dropPoisonGeneratingFlags();
323 Observer.changedInstr(*OrigDef);
324 B.setInsertPt(*OrigDef->getParent(), OrigDef->getIterator());
325 auto Freeze = B.buildFreeze(MaybePoisonOperandRegTy, MaybePoisonOperandReg);
327 MRI, *OrigDef->findRegisterUseOperand(MaybePoisonOperandReg, TRI),
328 Freeze.getReg(0));
329 replaceRegWith(MRI, DstOp, OrigOp);
330 };
331 return true;
332}
333
336 assert(MI.getOpcode() == TargetOpcode::G_CONCAT_VECTORS &&
337 "Invalid instruction");
338 bool IsUndef = true;
339 MachineInstr *Undef = nullptr;
340
341 // Walk over all the operands of concat vectors and check if they are
342 // build_vector themselves or undef.
343 // Then collect their operands in Ops.
344 for (const MachineOperand &MO : MI.uses()) {
345 Register Reg = MO.getReg();
346 MachineInstr *Def;
347 if (!mi_match(Reg, MRI, m_MInstr(Def)))
348 return false;
349 if (!MRI.hasOneNonDBGUse(Reg))
350 return false;
351 switch (Def->getOpcode()) {
352 case TargetOpcode::G_BUILD_VECTOR:
353 IsUndef = false;
354 // Remember the operands of the build_vector to fold
355 // them into the yet-to-build flattened concat vectors.
356 for (const MachineOperand &BuildVecMO : Def->uses())
357 Ops.push_back(BuildVecMO.getReg());
358 break;
359 case TargetOpcode::G_IMPLICIT_DEF: {
360 LLT OpType = MRI.getType(Reg);
361 // Keep one undef value for all the undef operands.
362 if (!Undef) {
363 Builder.setInsertPt(*MI.getParent(), MI);
364 Undef = Builder.buildUndef(OpType.getScalarType());
365 }
366 assert(MRI.getType(Undef->getOperand(0).getReg()) ==
367 OpType.getScalarType() &&
368 "All undefs should have the same type");
369 // Break the undef vector in as many scalar elements as needed
370 // for the flattening.
371 for (unsigned EltIdx = 0, EltEnd = OpType.getNumElements();
372 EltIdx != EltEnd; ++EltIdx)
373 Ops.push_back(Undef->getOperand(0).getReg());
374 break;
375 }
376 default:
377 return false;
378 }
379 }
380
381 // Check if the combine is illegal
382 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
384 {TargetOpcode::G_BUILD_VECTOR, {DstTy, MRI.getType(Ops[0])}})) {
385 return false;
386 }
387
388 if (IsUndef)
389 Ops.clear();
390
391 return true;
392}
395 // We determined that the concat_vectors can be flatten.
396 // Generate the flattened build_vector.
397 Register DstReg = MI.getOperand(0).getReg();
398 Builder.setInsertPt(*MI.getParent(), MI);
399 Register NewDstReg = MRI.cloneVirtualRegister(DstReg);
400
401 // Note: IsUndef is sort of redundant. We could have determine it by
402 // checking that at all Ops are undef. Alternatively, we could have
403 // generate a build_vector of undefs and rely on another combine to
404 // clean that up. For now, given we already gather this information
405 // in matchCombineConcatVectors, just save compile time and issue the
406 // right thing.
407 if (Ops.empty())
408 Builder.buildUndef(NewDstReg);
409 else
410 Builder.buildBuildVector(NewDstReg, Ops);
411 replaceRegWith(MRI, DstReg, NewDstReg);
412 MI.eraseFromParent();
413}
414
417 auto &BV = cast<GBuildVector>(MI);
418
419 // Look at the first operand for a unmerge(bitcast) from a scalar type.
420 GUnmerge *Unmerge = getOpcodeDef<GUnmerge>(BV.getSourceReg(0), MRI);
421 if (!Unmerge || Unmerge->getReg(0) != BV.getSourceReg(0))
422 return false;
423 Register BCSrc;
424 if (!mi_match(Unmerge->getSourceReg(), MRI, m_GBitcast(m_Reg(BCSrc))))
425 return false;
426 LLT InputTy = MRI.getType(BCSrc);
427 unsigned Factor = Unmerge->getNumDefs();
428 if (!InputTy.isScalar() || BV.getNumSources() % Factor != 0)
429 return false;
430
431 // Check if the build_vector is legal
432 LLT BVDstTy = LLT::fixed_vector(BV.getNumSources() / Factor, InputTy);
433 if (!isLegal({TargetOpcode::G_BUILD_VECTOR, {BVDstTy, InputTy}}))
434 return false;
435
436 // Check all other operands are bitcasts or undef.
437 for (unsigned Idx = 0; Idx < BV.getNumSources(); Idx += Factor) {
438 GUnmerge *Unmerge = getOpcodeDef<GUnmerge>(BV.getSourceReg(Idx), MRI);
439 if (!all_of(iota_range<unsigned>(0, Factor, false), [&](unsigned J) {
440 if (mi_match(BV.getSourceReg(Idx + J), MRI, m_GImplicitDef()))
441 return true;
442 return Unmerge && BV.getSourceReg(Idx + J) == Unmerge->getReg(J);
443 }))
444 return false;
445 if (!Unmerge)
446 Ops.push_back(0);
447 else {
448 Register BCSrc;
449 if (!mi_match(
450 Unmerge->getSourceReg(), MRI,
451 m_GBitcast(m_all_of(m_Reg(BCSrc), m_SpecificType(InputTy)))))
452 return false;
453 Ops.push_back(BCSrc);
454 }
455 }
456
457 return true;
458}
459
462 LLT SrcTy = MRI.getType(Ops[0]);
463 // Build undef if any operations require it.
464 Register Undef = 0;
465 for (Register &Op : Ops) {
466 if (!Op) {
467 if (!Undef)
468 Undef = Builder.buildUndef(SrcTy).getReg(0);
469 Op = Undef;
470 }
471 }
472
473 LLT BVDstTy = LLT::fixed_vector(Ops.size(), SrcTy);
474 auto BV = Builder.buildBuildVector(BVDstTy, Ops);
475 Builder.buildBitcast(MI.getOperand(0).getReg(), BV);
476 MI.eraseFromParent();
477}
478
480 auto &Shuffle = cast<GShuffleVector>(MI);
481
482 Register SrcVec1 = Shuffle.getSrc1Reg();
483 Register SrcVec2 = Shuffle.getSrc2Reg();
484 LLT EltTy = MRI.getType(SrcVec1).getElementType();
485 int Width = MRI.getType(SrcVec1).getNumElements();
486
487 auto Unmerge1 = Builder.buildUnmerge(EltTy, SrcVec1);
488 auto Unmerge2 = Builder.buildUnmerge(EltTy, SrcVec2);
489
490 SmallVector<Register> Extracts;
491 // Select only applicable elements from unmerged values.
492 for (int Val : Shuffle.getMask()) {
493 if (Val == -1)
494 Extracts.push_back(Builder.buildUndef(EltTy).getReg(0));
495 else if (Val < Width)
496 Extracts.push_back(Unmerge1.getReg(Val));
497 else
498 Extracts.push_back(Unmerge2.getReg(Val - Width));
499 }
500 assert(Extracts.size() > 0 && "Expected at least one element in the shuffle");
501 if (Extracts.size() == 1)
502 Builder.buildCopy(MI.getOperand(0).getReg(), Extracts[0]);
503 else
504 Builder.buildBuildVector(MI.getOperand(0).getReg(), Extracts);
505 MI.eraseFromParent();
506}
507
509 auto &Shuffle = cast<GShuffleVector>(MI);
510 Register SrcVec1 = Shuffle.getSrc1Reg();
511 Register SrcVec2 = Shuffle.getSrc2Reg();
512 auto *BuildMI1 = getOpcodeDef<GBuildVector>(SrcVec1, MRI);
513 auto *BuildMI2 = getOpcodeDef<GBuildVector>(SrcVec2, MRI);
514 assert((BuildMI1 && (BuildMI2 || MRI.getVRegDef(SrcVec2)->getOpcode() ==
515 TargetOpcode::G_IMPLICIT_DEF)) &&
516 "Unexpected input to applyCombineShuffleOfBuildVector");
517 LLT EltTy = MRI.getType(SrcVec1).getElementType();
518 int NumElts = MRI.getType(SrcVec1).getNumElements();
519
520 SmallVector<Register> Extracts;
521 for (int Val : Shuffle.getMask()) {
522 if (Val == -1)
523 Extracts.push_back(Builder.buildUndef(EltTy).getReg(0));
524 else if (Val < NumElts)
525 Extracts.push_back(BuildMI1->getSourceReg(Val));
526 else if (BuildMI2)
527 Extracts.push_back(BuildMI2->getSourceReg(Val - NumElts));
528 else
529 Extracts.push_back(Builder.buildUndef(EltTy).getReg(0));
530 }
531
532 if (Extracts.size() == 1)
533 Builder.buildCopy(MI.getOperand(0).getReg(), Extracts[0]);
534 else
535 Builder.buildBuildVector(MI.getOperand(0).getReg(), Extracts);
536 MI.eraseFromParent();
537}
538
541 ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
542 GConcatVectors *ConcatMI1, *ConcatMI2;
543 if (!mi_match(MI.getOperand(1).getReg(), MRI, m_GConcatVectors(ConcatMI1)) ||
544 !mi_match(MI.getOperand(2).getReg(), MRI, m_GConcatVectors(ConcatMI2)))
545 return false;
546
547 // Check that the sources of the Concat instructions have the same type
548 if (MRI.getType(ConcatMI1->getSourceReg(0)) !=
549 MRI.getType(ConcatMI2->getSourceReg(0)))
550 return false;
551
552 LLT ConcatSrcTy = MRI.getType(ConcatMI1->getReg(1));
553 LLT ShuffleSrcTy1 = MRI.getType(MI.getOperand(1).getReg());
554 unsigned ConcatSrcNumElt = ConcatSrcTy.getNumElements();
555 for (unsigned i = 0; i < Mask.size(); i += ConcatSrcNumElt) {
556 // Check if the index takes a whole source register from G_CONCAT_VECTORS
557 // Assumes that all Sources of G_CONCAT_VECTORS are the same type
558 if (Mask[i] == -1) {
559 for (unsigned j = 1; j < ConcatSrcNumElt; j++) {
560 if (i + j >= Mask.size())
561 return false;
562 if (Mask[i + j] != -1)
563 return false;
564 }
566 {TargetOpcode::G_IMPLICIT_DEF, {ConcatSrcTy}}))
567 return false;
568 Ops.push_back(0);
569 } else if (Mask[i] % ConcatSrcNumElt == 0) {
570 for (unsigned j = 1; j < ConcatSrcNumElt; j++) {
571 if (i + j >= Mask.size())
572 return false;
573 if (Mask[i + j] != Mask[i] + static_cast<int>(j))
574 return false;
575 }
576 // Retrieve the source register from its respective G_CONCAT_VECTORS
577 // instruction
578 if (Mask[i] < ShuffleSrcTy1.getNumElements()) {
579 Ops.push_back(ConcatMI1->getSourceReg(Mask[i] / ConcatSrcNumElt));
580 } else {
581 Ops.push_back(ConcatMI2->getSourceReg(Mask[i] / ConcatSrcNumElt -
582 ConcatMI1->getNumSources()));
583 }
584 } else {
585 return false;
586 }
587 }
588
590 {TargetOpcode::G_CONCAT_VECTORS,
591 {MRI.getType(MI.getOperand(0).getReg()), ConcatSrcTy}}))
592 return false;
593
594 return !Ops.empty();
595}
596
599 LLT SrcTy;
600 for (Register &Reg : Ops) {
601 if (Reg != 0)
602 SrcTy = MRI.getType(Reg);
603 }
604 assert(SrcTy.isValid() && "Unexpected full undef vector in concat combine");
605
606 Register UndefReg = 0;
607
608 for (Register &Reg : Ops) {
609 if (Reg == 0) {
610 if (UndefReg == 0)
611 UndefReg = Builder.buildUndef(SrcTy).getReg(0);
612 Reg = UndefReg;
613 }
614 }
615
616 if (Ops.size() > 1)
617 Builder.buildConcatVectors(MI.getOperand(0).getReg(), Ops);
618 else
619 Builder.buildCopy(MI.getOperand(0).getReg(), Ops[0]);
620 MI.eraseFromParent();
621}
622
625 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
626 "Invalid instruction kind");
627 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
628 Register Src1 = MI.getOperand(1).getReg();
629 LLT SrcType = MRI.getType(Src1);
630
631 unsigned DstNumElts = DstType.getNumElements();
632 unsigned SrcNumElts = SrcType.getNumElements();
633
634 // If the resulting vector is smaller than the size of the source
635 // vectors being concatenated, we won't be able to replace the
636 // shuffle vector into a concat_vectors.
637 //
638 // Note: We may still be able to produce a concat_vectors fed by
639 // extract_vector_elt and so on. It is less clear that would
640 // be better though, so don't bother for now.
641 //
642 // If the destination is a scalar, the size of the sources doesn't
643 // matter. we will lower the shuffle to a plain copy. This will
644 // work only if the source and destination have the same size. But
645 // that's covered by the next condition.
646 //
647 // TODO: If the size between the source and destination don't match
648 // we could still emit an extract vector element in that case.
649 if (DstNumElts < 2 * SrcNumElts)
650 return false;
651
652 // Check that the shuffle mask can be broken evenly between the
653 // different sources.
654 if (DstNumElts % SrcNumElts != 0)
655 return false;
656
657 // Mask length is a multiple of the source vector length.
658 // Check if the shuffle is some kind of concatenation of the input
659 // vectors.
660 unsigned NumConcat = DstNumElts / SrcNumElts;
661 SmallVector<int, 8> ConcatSrcs(NumConcat, -1);
662 ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
663 for (unsigned i = 0; i != DstNumElts; ++i) {
664 int Idx = Mask[i];
665 // Undef value.
666 if (Idx < 0)
667 continue;
668 // Ensure the indices in each SrcType sized piece are sequential and that
669 // the same source is used for the whole piece.
670 if ((Idx % SrcNumElts != (i % SrcNumElts)) ||
671 (ConcatSrcs[i / SrcNumElts] >= 0 &&
672 ConcatSrcs[i / SrcNumElts] != (int)(Idx / SrcNumElts)))
673 return false;
674 // Remember which source this index came from.
675 ConcatSrcs[i / SrcNumElts] = Idx / SrcNumElts;
676 }
677
678 // The shuffle is concatenating multiple vectors together.
679 // Collect the different operands for that.
680 Register UndefReg;
681 Register Src2 = MI.getOperand(2).getReg();
682 for (auto Src : ConcatSrcs) {
683 if (Src < 0) {
684 if (!UndefReg) {
685 Builder.setInsertPt(*MI.getParent(), MI);
686 UndefReg = Builder.buildUndef(SrcType).getReg(0);
687 }
688 Ops.push_back(UndefReg);
689 } else if (Src == 0)
690 Ops.push_back(Src1);
691 else
692 Ops.push_back(Src2);
693 }
694 return true;
695}
696
698 ArrayRef<Register> Ops) const {
699 Register DstReg = MI.getOperand(0).getReg();
700 Builder.setInsertPt(*MI.getParent(), MI);
701 Register NewDstReg = MRI.cloneVirtualRegister(DstReg);
702
703 if (Ops.size() == 1)
704 Builder.buildCopy(NewDstReg, Ops[0]);
705 else
706 Builder.buildMergeLikeInstr(NewDstReg, Ops);
707
708 replaceRegWith(MRI, DstReg, NewDstReg);
709 MI.eraseFromParent();
710}
711
712namespace {
713
714/// Select a preference between two uses. CurrentUse is the current preference
715/// while *ForCandidate is attributes of the candidate under consideration.
716PreferredTuple ChoosePreferredUse(MachineInstr &LoadMI,
717 PreferredTuple &CurrentUse,
718 const LLT TyForCandidate,
719 unsigned OpcodeForCandidate,
720 MachineInstr *MIForCandidate) {
721 if (!CurrentUse.Ty.isValid()) {
722 if (CurrentUse.ExtendOpcode == OpcodeForCandidate ||
723 CurrentUse.ExtendOpcode == TargetOpcode::G_ANYEXT)
724 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
725 return CurrentUse;
726 }
727
728 // We permit the extend to hoist through basic blocks but this is only
729 // sensible if the target has extending loads. If you end up lowering back
730 // into a load and extend during the legalizer then the end result is
731 // hoisting the extend up to the load.
732
733 // Prefer defined extensions to undefined extensions as these are more
734 // likely to reduce the number of instructions.
735 if (OpcodeForCandidate == TargetOpcode::G_ANYEXT &&
736 CurrentUse.ExtendOpcode != TargetOpcode::G_ANYEXT)
737 return CurrentUse;
738 else if (CurrentUse.ExtendOpcode == TargetOpcode::G_ANYEXT &&
739 OpcodeForCandidate != TargetOpcode::G_ANYEXT)
740 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
741
742 // Prefer sign extensions to zero extensions as sign-extensions tend to be
743 // more expensive. Don't do this if the load is already a zero-extend load
744 // though, otherwise we'll rewrite a zero-extend load into a sign-extend
745 // later.
746 if (!isa<GZExtLoad>(LoadMI) && CurrentUse.Ty == TyForCandidate) {
747 if (CurrentUse.ExtendOpcode == TargetOpcode::G_SEXT &&
748 OpcodeForCandidate == TargetOpcode::G_ZEXT)
749 return CurrentUse;
750 else if (CurrentUse.ExtendOpcode == TargetOpcode::G_ZEXT &&
751 OpcodeForCandidate == TargetOpcode::G_SEXT)
752 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
753 }
754
755 // This is potentially target specific. We've chosen the largest type
756 // because G_TRUNC is usually free. One potential catch with this is that
757 // some targets have a reduced number of larger registers than smaller
758 // registers and this choice potentially increases the live-range for the
759 // larger value.
760 if (TyForCandidate.getSizeInBits() > CurrentUse.Ty.getSizeInBits()) {
761 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
762 }
763 return CurrentUse;
764}
765
766/// Find a suitable place to insert some instructions and insert them. This
767/// function accounts for special cases like inserting before a PHI node.
768/// The current strategy for inserting before PHI's is to duplicate the
769/// instructions for each predecessor. However, while that's ok for G_TRUNC
770/// on most targets since it generally requires no code, other targets/cases may
771/// want to try harder to find a dominating block.
772static void InsertInsnsWithoutSideEffectsBeforeUse(
775 MachineOperand &UseMO)>
776 Inserter) {
777 MachineInstr &UseMI = *UseMO.getParent();
778
779 MachineBasicBlock *InsertBB = UseMI.getParent();
780
781 // If the use is a PHI then we want the predecessor block instead.
782 if (UseMI.isPHI()) {
783 MachineOperand *PredBB = std::next(&UseMO);
784 InsertBB = PredBB->getMBB();
785 }
786
787 // If the block is the same block as the def then we want to insert just after
788 // the def instead of at the start of the block.
789 if (InsertBB == DefMI.getParent()) {
791 Inserter(InsertBB, std::next(InsertPt), UseMO);
792 return;
793 }
794
795 // Otherwise we want the start of the BB
796 Inserter(InsertBB, InsertBB->getFirstNonPHI(), UseMO);
797}
798} // end anonymous namespace
799
801 PreferredTuple Preferred;
802 if (matchCombineExtendingLoads(MI, Preferred)) {
803 applyCombineExtendingLoads(MI, Preferred);
804 return true;
805 }
806 return false;
807}
808
809static unsigned getExtLoadOpcForExtend(unsigned ExtOpc) {
810 unsigned CandidateLoadOpc;
811 switch (ExtOpc) {
812 case TargetOpcode::G_ANYEXT:
813 CandidateLoadOpc = TargetOpcode::G_LOAD;
814 break;
815 case TargetOpcode::G_SEXT:
816 CandidateLoadOpc = TargetOpcode::G_SEXTLOAD;
817 break;
818 case TargetOpcode::G_ZEXT:
819 CandidateLoadOpc = TargetOpcode::G_ZEXTLOAD;
820 break;
821 default:
822 llvm_unreachable("Unexpected extend opc");
823 }
824 return CandidateLoadOpc;
825}
826
828 MachineInstr &MI, PreferredTuple &Preferred) const {
829 // We match the loads and follow the uses to the extend instead of matching
830 // the extends and following the def to the load. This is because the load
831 // must remain in the same position for correctness (unless we also add code
832 // to find a safe place to sink it) whereas the extend is freely movable.
833 // It also prevents us from duplicating the load for the volatile case or just
834 // for performance.
835 GAnyLoad *LoadMI = dyn_cast<GAnyLoad>(&MI);
836 if (!LoadMI)
837 return false;
838
839 Register LoadReg = LoadMI->getDstReg();
840
841 LLT LoadValueTy = MRI.getType(LoadReg);
842 if (!LoadValueTy.isScalar())
843 return false;
844
845 // Most architectures are going to legalize <s8 loads into at least a 1 byte
846 // load, and the MMOs can only describe memory accesses in multiples of bytes.
847 // If we try to perform extload combining on those, we can end up with
848 // %a(s8) = extload %ptr (load 1 byte from %ptr)
849 // ... which is an illegal extload instruction.
850 if (LoadValueTy.getSizeInBits() < 8)
851 return false;
852
853 // For non power-of-2 types, they will very likely be legalized into multiple
854 // loads. Don't bother trying to match them into extending loads.
856 return false;
857
858 // Find the preferred type aside from the any-extends (unless it's the only
859 // one) and non-extending ops. We'll emit an extending load to that type and
860 // and emit a variant of (extend (trunc X)) for the others according to the
861 // relative type sizes. At the same time, pick an extend to use based on the
862 // extend involved in the chosen type.
863 unsigned PreferredOpcode =
864 isa<GLoad>(&MI)
865 ? TargetOpcode::G_ANYEXT
866 : isa<GSExtLoad>(&MI) ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
867 Preferred = {LLT(), PreferredOpcode, nullptr};
868 for (auto &UseMI : MRI.use_nodbg_instructions(LoadReg)) {
869 if (UseMI.getOpcode() == TargetOpcode::G_SEXT ||
870 UseMI.getOpcode() == TargetOpcode::G_ZEXT ||
871 (UseMI.getOpcode() == TargetOpcode::G_ANYEXT)) {
872 const auto &MMO = LoadMI->getMMO();
873 // Don't do anything for atomics.
874 if (MMO.isAtomic())
875 continue;
876 // Check for legality.
877 if (!isPreLegalize()) {
878 LegalityQuery::MemDesc MMDesc(MMO);
879 unsigned CandidateLoadOpc = getExtLoadOpcForExtend(UseMI.getOpcode());
880 LLT UseTy = MRI.getType(UseMI.getOperand(0).getReg());
881 LLT SrcTy = MRI.getType(LoadMI->getPointerReg());
882 if (LI->getAction({CandidateLoadOpc, {UseTy, SrcTy}, {MMDesc}})
883 .Action != LegalizeActions::Legal)
884 continue;
885 }
886 Preferred = ChoosePreferredUse(MI, Preferred,
887 MRI.getType(UseMI.getOperand(0).getReg()),
888 UseMI.getOpcode(), &UseMI);
889 }
890 }
891
892 // There were no extends
893 if (!Preferred.MI)
894 return false;
895 // It should be impossible to chose an extend without selecting a different
896 // type since by definition the result of an extend is larger.
897 assert(Preferred.Ty != LoadValueTy && "Extending to same type?");
898
899 LLVM_DEBUG(dbgs() << "Preferred use is: " << *Preferred.MI);
900 return true;
901}
902
904 MachineInstr &MI, PreferredTuple &Preferred) const {
905 // Rewrite the load to the chosen extending load.
906 Register ChosenDstReg = Preferred.MI->getOperand(0).getReg();
907
908 // Inserter to insert a truncate back to the original type at a given point
909 // with some basic CSE to limit truncate duplication to one per BB.
911 auto InsertTruncAt = [&](MachineBasicBlock *InsertIntoBB,
912 MachineBasicBlock::iterator InsertBefore,
913 MachineOperand &UseMO) {
914 MachineInstr *PreviouslyEmitted = EmittedInsns.lookup(InsertIntoBB);
915 if (PreviouslyEmitted) {
916 Observer.changingInstr(*UseMO.getParent());
917 UseMO.setReg(PreviouslyEmitted->getOperand(0).getReg());
918 Observer.changedInstr(*UseMO.getParent());
919 return;
920 }
921
922 Builder.setInsertPt(*InsertIntoBB, InsertBefore);
923 Register NewDstReg = MRI.cloneVirtualRegister(MI.getOperand(0).getReg());
924 MachineInstr *NewMI = Builder.buildTrunc(NewDstReg, ChosenDstReg);
925 EmittedInsns[InsertIntoBB] = NewMI;
926 replaceRegOpWith(MRI, UseMO, NewDstReg);
927 };
928
929 Observer.changingInstr(MI);
930 unsigned LoadOpc = getExtLoadOpcForExtend(Preferred.ExtendOpcode);
931 MI.setDesc(Builder.getTII().get(LoadOpc));
932
933 // Rewrite all the uses to fix up the types.
934 auto &LoadValue = MI.getOperand(0);
936 llvm::make_pointer_range(MRI.use_operands(LoadValue.getReg())));
937
938 for (auto *UseMO : Uses) {
939 MachineInstr *UseMI = UseMO->getParent();
940
941 // If the extend is compatible with the preferred extend then we should fix
942 // up the type and extend so that it uses the preferred use.
943 if (UseMI->getOpcode() == Preferred.ExtendOpcode ||
944 UseMI->getOpcode() == TargetOpcode::G_ANYEXT) {
945 Register UseDstReg = UseMI->getOperand(0).getReg();
946 MachineOperand &UseSrcMO = UseMI->getOperand(1);
947 const LLT UseDstTy = MRI.getType(UseDstReg);
948 if (UseDstReg != ChosenDstReg) {
949 if (Preferred.Ty == UseDstTy) {
950 // If the use has the same type as the preferred use, then merge
951 // the vregs and erase the extend. For example:
952 // %1:_(s8) = G_LOAD ...
953 // %2:_(s32) = G_SEXT %1(s8)
954 // %3:_(s32) = G_ANYEXT %1(s8)
955 // ... = ... %3(s32)
956 // rewrites to:
957 // %2:_(s32) = G_SEXTLOAD ...
958 // ... = ... %2(s32)
959 replaceRegWith(MRI, UseDstReg, ChosenDstReg);
960 Observer.erasingInstr(*UseMO->getParent());
961 UseMO->getParent()->eraseFromParent();
962 } else if (Preferred.Ty.getSizeInBits() < UseDstTy.getSizeInBits()) {
963 // If the preferred size is smaller, then keep the extend but extend
964 // from the result of the extending load. For example:
965 // %1:_(s8) = G_LOAD ...
966 // %2:_(s32) = G_SEXT %1(s8)
967 // %3:_(s64) = G_ANYEXT %1(s8)
968 // ... = ... %3(s64)
969 /// rewrites to:
970 // %2:_(s32) = G_SEXTLOAD ...
971 // %3:_(s64) = G_ANYEXT %2:_(s32)
972 // ... = ... %3(s64)
973 replaceRegOpWith(MRI, UseSrcMO, ChosenDstReg);
974 } else {
975 // If the preferred size is large, then insert a truncate. For
976 // example:
977 // %1:_(s8) = G_LOAD ...
978 // %2:_(s64) = G_SEXT %1(s8)
979 // %3:_(s32) = G_ZEXT %1(s8)
980 // ... = ... %3(s32)
981 /// rewrites to:
982 // %2:_(s64) = G_SEXTLOAD ...
983 // %4:_(s8) = G_TRUNC %2:_(s32)
984 // %3:_(s64) = G_ZEXT %2:_(s8)
985 // ... = ... %3(s64)
986 InsertInsnsWithoutSideEffectsBeforeUse(Builder, MI, *UseMO,
987 InsertTruncAt);
988 }
989 continue;
990 }
991 // The use is (one of) the uses of the preferred use we chose earlier.
992 // We're going to update the load to def this value later so just erase
993 // the old extend.
994 Observer.erasingInstr(*UseMO->getParent());
995 UseMO->getParent()->eraseFromParent();
996 continue;
997 }
998
999 // The use isn't an extend. Truncate back to the type we originally loaded.
1000 // This is free on many targets.
1001 InsertInsnsWithoutSideEffectsBeforeUse(Builder, MI, *UseMO, InsertTruncAt);
1002 }
1003
1004 MI.getOperand(0).setReg(ChosenDstReg);
1005 Observer.changedInstr(MI);
1006}
1007
1009 BuildFnTy &MatchInfo) const {
1010 assert(MI.getOpcode() == TargetOpcode::G_AND);
1011
1012 // If we have the following code:
1013 // %mask = G_CONSTANT 255
1014 // %ld = G_LOAD %ptr, (load s16)
1015 // %and = G_AND %ld, %mask
1016 //
1017 // Try to fold it into
1018 // %ld = G_ZEXTLOAD %ptr, (load s8)
1019
1020 Register Dst = MI.getOperand(0).getReg();
1021 if (MRI.getType(Dst).isVector())
1022 return false;
1023
1024 auto MaybeMask =
1025 getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
1026 if (!MaybeMask)
1027 return false;
1028
1029 APInt MaskVal = MaybeMask->Value;
1030
1031 if (!MaskVal.isMask())
1032 return false;
1033
1034 Register SrcReg = MI.getOperand(1).getReg();
1035 // Don't use getOpcodeDef() here since intermediate instructions may have
1036 // multiple users.
1037 GAnyLoad *LoadMI;
1038 Register PtrReg;
1039 const MachineMemOperand *MMO;
1040 if (!mi_match(SrcReg, MRI, m_GAnyLoad(LoadMI, m_Reg(PtrReg), m_MMO(MMO))))
1041 return false;
1042
1043 Register LoadReg = LoadMI->getDstReg();
1044 LLT RegTy = MRI.getType(LoadReg);
1045 unsigned RegSize = RegTy.getSizeInBits();
1046 unsigned LoadSizeBits = MMO->getSizeInBits().getValue();
1047 unsigned MaskSizeBits = MaskVal.countr_one();
1048
1049 if ((isa<GSExtLoad>(LoadMI) || MaskSizeBits < LoadSizeBits) &&
1050 !MRI.hasOneNonDBGUse(LoadReg))
1051 return false;
1052
1053 // The mask may not be larger than the in-memory type, as it might cover sign
1054 // extended bits
1055 if (MaskSizeBits > LoadSizeBits)
1056 return false;
1057
1058 // If the mask covers the whole destination register, there's nothing to
1059 // extend
1060 if (MaskSizeBits >= RegSize)
1061 return false;
1062
1063 // Most targets cannot deal with loads of size < 8 and need to re-legalize to
1064 // at least byte loads. Avoid creating such loads here
1065 if (MaskSizeBits < 8 || !isPowerOf2_32(MaskSizeBits))
1066 return false;
1067
1068 LegalityQuery::MemDesc MemDesc(*MMO);
1069
1070 // Don't modify the memory access size if this is atomic/volatile, but we can
1071 // still adjust the opcode to indicate the high bit behavior.
1072 if (!MMO->isAtomic() && !MMO->isVolatile())
1073 MemDesc.MemoryTy = LLT::scalar(MaskSizeBits);
1074 else if (LoadSizeBits > MaskSizeBits || LoadSizeBits == RegSize)
1075 return false;
1076
1077 // TODO: Could check if it's legal with the reduced or original memory size.
1079 {TargetOpcode::G_ZEXTLOAD, {RegTy, MRI.getType(PtrReg)}, {MemDesc}}))
1080 return false;
1081
1082 MatchInfo = [=](MachineIRBuilder &B) {
1083 B.setInstrAndDebugLoc(*LoadMI);
1084 auto &MF = B.getMF();
1085 auto PtrInfo = MMO->getPointerInfo();
1086 auto *NewMMO = MF.getMachineMemOperand(MMO, PtrInfo, MemDesc.MemoryTy);
1087 B.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, Dst, PtrReg, *NewMMO);
1088 replaceRegWith(MRI, LoadReg, Dst);
1089 LoadMI->eraseFromParent();
1090 };
1091 return true;
1092}
1093
1095 const MachineInstr &UseMI) const {
1096 assert(!DefMI.isDebugInstr() && !UseMI.isDebugInstr() &&
1097 "shouldn't consider debug uses");
1098 assert(DefMI.getParent() == UseMI.getParent());
1099 if (&DefMI == &UseMI)
1100 return true;
1101 const MachineBasicBlock &MBB = *DefMI.getParent();
1102 auto DefOrUse = find_if(MBB, [&DefMI, &UseMI](const MachineInstr &MI) {
1103 return &MI == &DefMI || &MI == &UseMI;
1104 });
1105 if (DefOrUse == MBB.end())
1106 llvm_unreachable("Block must contain both DefMI and UseMI!");
1107 return &*DefOrUse == &DefMI;
1108}
1109
1111 const MachineInstr &UseMI) const {
1112 assert(!DefMI.isDebugInstr() && !UseMI.isDebugInstr() &&
1113 "shouldn't consider debug uses");
1114 if (MDT)
1115 return MDT->dominates(&DefMI, &UseMI);
1116 else if (DefMI.getParent() != UseMI.getParent())
1117 return false;
1118
1119 return isPredecessor(DefMI, UseMI);
1120}
1121
1123 assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1124 Register SrcReg = MI.getOperand(1).getReg();
1125 Register LoadUser = SrcReg;
1126
1127 if (MRI.getType(SrcReg).isVector())
1128 return false;
1129
1130 Register TruncSrc;
1131 if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc))))
1132 LoadUser = TruncSrc;
1133
1134 uint64_t SizeInBits = MI.getOperand(2).getImm();
1135 // If the source is a G_SEXTLOAD from the same bit width, then we don't
1136 // need any extend at all, just a truncate.
1137 if (auto *LoadMI = getOpcodeDef<GSExtLoad>(LoadUser, MRI)) {
1138 // If truncating more than the original extended value, abort.
1139 auto LoadSizeBits = LoadMI->getMemSizeInBits();
1140 if (TruncSrc &&
1141 MRI.getType(TruncSrc).getSizeInBits() < LoadSizeBits.getValue())
1142 return false;
1143 if (LoadSizeBits == SizeInBits)
1144 return true;
1145 }
1146 return false;
1147}
1148
1150 MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo) const {
1151 assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1152
1153 Register DstReg = MI.getOperand(0).getReg();
1154 LLT RegTy = MRI.getType(DstReg);
1155
1156 // Only supports scalars for now.
1157 if (RegTy.isVector())
1158 return false;
1159
1160 Register SrcReg = MI.getOperand(1).getReg();
1161 Register PtrReg;
1162 const MachineMemOperand *MMO;
1163 if (!mi_match(SrcReg, MRI, m_GLoad(m_Reg(PtrReg), m_MMO(MMO))))
1164 return false;
1165
1166 uint64_t MemBits = MMO->getSizeInBits().getValue();
1167 uint64_t ExtFrom = MI.getOperand(2).getImm();
1168
1169 if (MemBits > ExtFrom && !MRI.hasOneNonDBGUse(SrcReg))
1170 return false;
1171
1172 // If the sign extend extends from a narrower width than the load's width,
1173 // then we can narrow the load width when we combine to a G_SEXTLOAD.
1174 // Avoid widening the load at all.
1175 unsigned NewSizeBits = std::min(ExtFrom, MemBits);
1176
1177 // Don't generate G_SEXTLOADs with a < 1 byte width.
1178 if (NewSizeBits < 8)
1179 return false;
1180 // Don't bother creating a non-power-2 sextload, it will likely be broken up
1181 // anyway for most targets.
1182 if (!isPowerOf2_32(NewSizeBits))
1183 return false;
1184
1185 LegalityQuery::MemDesc MMDesc(*MMO);
1186
1187 // Don't modify the memory access size if this is atomic/volatile, but we can
1188 // still adjust the opcode to indicate the high bit behavior.
1189 if (!MMO->isAtomic() && !MMO->isVolatile())
1190 MMDesc.MemoryTy = LLT::scalar(NewSizeBits);
1191 else if (MemBits > NewSizeBits || MemBits == RegTy.getSizeInBits())
1192 return false;
1193
1194 // TODO: Could check if it's legal with the reduced or original memory size.
1196 {TargetOpcode::G_SEXTLOAD, {RegTy, MRI.getType(PtrReg)}, {MMDesc}}))
1197 return false;
1198
1199 MatchInfo = std::make_tuple(SrcReg, NewSizeBits);
1200 return true;
1201}
1202
1204 MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo) const {
1205 assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1206 Register LoadReg;
1207 unsigned ScalarSizeBits;
1208 std::tie(LoadReg, ScalarSizeBits) = MatchInfo;
1209 GLoad *LoadDef = cast<GLoad>(MRI.getVRegDef(LoadReg));
1210
1211 // If we have the following:
1212 // %ld = G_LOAD %ptr, (load 2)
1213 // %ext = G_SEXT_INREG %ld, 8
1214 // ==>
1215 // %ld = G_SEXTLOAD %ptr (load 1)
1216
1217 auto &MMO = LoadDef->getMMO();
1218 Builder.setInstrAndDebugLoc(*LoadDef);
1219 auto &MF = Builder.getMF();
1220 auto PtrInfo = MMO.getPointerInfo();
1221 auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, ScalarSizeBits / 8);
1222 Builder.buildLoadInstr(TargetOpcode::G_SEXTLOAD, MI.getOperand(0).getReg(),
1223 LoadDef->getPointerReg(), *NewMMO);
1224 replaceRegWith(MRI, LoadReg, MI.getOperand(0).getReg());
1225 MI.eraseFromParent();
1226
1227 // Not all loads can be deleted, so make sure the old one is removed.
1228 LoadDef->eraseFromParent();
1229}
1230
1231/// Return true if 'MI' is a load or a store that may be fold it's address
1232/// operand into the load / store addressing mode.
1236 auto *MF = MI->getMF();
1237 auto *Addr = getOpcodeDef<GPtrAdd>(MI->getPointerReg(), MRI);
1238 if (!Addr)
1239 return false;
1240
1241 AM.HasBaseReg = true;
1242 if (auto CstOff = getIConstantVRegVal(Addr->getOffsetReg(), MRI))
1243 AM.BaseOffs = CstOff->getSExtValue(); // [reg +/- imm]
1244 else
1245 AM.Scale = 1; // [reg +/- reg]
1246
1247 return TLI.isLegalAddressingMode(
1248 MF->getDataLayout(), AM,
1249 getTypeForLLT(MI->getMMO().getMemoryType(),
1250 MF->getFunction().getContext()),
1251 MI->getMMO().getAddrSpace());
1252}
1253
1254static unsigned getIndexedOpc(unsigned LdStOpc) {
1255 switch (LdStOpc) {
1256 case TargetOpcode::G_LOAD:
1257 return TargetOpcode::G_INDEXED_LOAD;
1258 case TargetOpcode::G_STORE:
1259 return TargetOpcode::G_INDEXED_STORE;
1260 case TargetOpcode::G_ZEXTLOAD:
1261 return TargetOpcode::G_INDEXED_ZEXTLOAD;
1262 case TargetOpcode::G_SEXTLOAD:
1263 return TargetOpcode::G_INDEXED_SEXTLOAD;
1264 default:
1265 llvm_unreachable("Unexpected opcode");
1266 }
1267}
1268
1269bool CombinerHelper::isIndexedLoadStoreLegal(GLoadStore &LdSt) const {
1270 // Check for legality.
1271 LLT PtrTy = MRI.getType(LdSt.getPointerReg());
1272 LLT Ty = MRI.getType(LdSt.getReg(0));
1273 LLT MemTy = LdSt.getMMO().getMemoryType();
1275 {{MemTy, MemTy.getSizeInBits().getKnownMinValue(),
1277 unsigned IndexedOpc = getIndexedOpc(LdSt.getOpcode());
1278 SmallVector<LLT> OpTys;
1279 if (IndexedOpc == TargetOpcode::G_INDEXED_STORE)
1280 OpTys = {PtrTy, Ty, Ty};
1281 else
1282 OpTys = {Ty, PtrTy}; // For G_INDEXED_LOAD, G_INDEXED_[SZ]EXTLOAD
1283
1284 LegalityQuery Q(IndexedOpc, OpTys, MemDescrs);
1285 return isLegal(Q);
1286}
1287
1289 "post-index-use-threshold", cl::Hidden, cl::init(32),
1290 cl::desc("Number of uses of a base pointer to check before it is no longer "
1291 "considered for post-indexing."));
1292
1293bool CombinerHelper::findPostIndexCandidate(GLoadStore &LdSt, Register &Addr,
1295 bool &RematOffset) const {
1296 // We're looking for the following pattern, for either load or store:
1297 // %baseptr:_(p0) = ...
1298 // G_STORE %val(s64), %baseptr(p0)
1299 // %offset:_(s64) = G_CONSTANT i64 -256
1300 // %new_addr:_(p0) = G_PTR_ADD %baseptr, %offset(s64)
1301 const auto &TLI = getTargetLowering();
1302
1303 Register Ptr = LdSt.getPointerReg();
1304 // If the store is the only use, don't bother.
1305 if (MRI.hasOneNonDBGUse(Ptr))
1306 return false;
1307
1308 if (!isIndexedLoadStoreLegal(LdSt))
1309 return false;
1310
1311 if (getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Ptr, MRI))
1312 return false;
1313
1314 MachineInstr *StoredValDef = getDefIgnoringCopies(LdSt.getReg(0), MRI);
1315 MachineInstr *PtrDef;
1316 if (!mi_match(Ptr, MRI, m_MInstr(PtrDef)))
1317 return false;
1318
1319 unsigned NumUsesChecked = 0;
1320 for (auto &Use : MRI.use_nodbg_instructions(Ptr)) {
1321 if (++NumUsesChecked > PostIndexUseThreshold)
1322 return false; // Try to avoid exploding compile time.
1323
1324 auto *PtrAdd = dyn_cast<GPtrAdd>(&Use);
1325 // The use itself might be dead. This can happen during combines if DCE
1326 // hasn't had a chance to run yet. Don't allow it to form an indexed op.
1327 if (!PtrAdd || MRI.use_nodbg_empty(PtrAdd->getReg(0)))
1328 continue;
1329
1330 // Check the user of this isn't the store, otherwise we'd be generate a
1331 // indexed store defining its own use.
1332 if (StoredValDef == &Use)
1333 continue;
1334
1335 Offset = PtrAdd->getOffsetReg();
1336 if (!ForceLegalIndexing &&
1337 !TLI.isIndexingLegal(LdSt, PtrAdd->getBaseReg(), Offset,
1338 /*IsPre*/ false, MRI))
1339 continue;
1340
1341 // Make sure the offset calculation is before the potentially indexed op.
1342 MachineInstr *OffsetDef;
1343 if (!mi_match(Offset, MRI, m_MInstr(OffsetDef)))
1344 continue;
1345 RematOffset = false;
1346 if (!dominates(*OffsetDef, LdSt)) {
1347 // If the offset however is just a G_CONSTANT, we can always just
1348 // rematerialize it where we need it.
1349 if (OffsetDef->getOpcode() != TargetOpcode::G_CONSTANT)
1350 continue;
1351 RematOffset = true;
1352 }
1353
1354 for (auto &BasePtrUse : MRI.use_nodbg_instructions(PtrAdd->getBaseReg())) {
1355 if (&BasePtrUse == PtrDef)
1356 continue;
1357
1358 // If the user is a later load/store that can be post-indexed, then don't
1359 // combine this one.
1360 auto *BasePtrLdSt = dyn_cast<GLoadStore>(&BasePtrUse);
1361 if (BasePtrLdSt && BasePtrLdSt != &LdSt &&
1362 dominates(LdSt, *BasePtrLdSt) &&
1363 isIndexedLoadStoreLegal(*BasePtrLdSt))
1364 return false;
1365
1366 // Now we're looking for the key G_PTR_ADD instruction, which contains
1367 // the offset add that we want to fold.
1368 if (auto *BasePtrUseDef = dyn_cast<GPtrAdd>(&BasePtrUse)) {
1369 Register PtrAddDefReg = BasePtrUseDef->getReg(0);
1370 for (auto &BaseUseUse : MRI.use_nodbg_instructions(PtrAddDefReg)) {
1371 // If the use is in a different block, then we may produce worse code
1372 // due to the extra register pressure.
1373 if (BaseUseUse.getParent() != LdSt.getParent())
1374 return false;
1375
1376 if (auto *UseUseLdSt = dyn_cast<GLoadStore>(&BaseUseUse))
1377 if (canFoldInAddressingMode(UseUseLdSt, TLI, MRI))
1378 return false;
1379 }
1380 if (!dominates(LdSt, BasePtrUse))
1381 return false; // All use must be dominated by the load/store.
1382 }
1383 }
1384
1385 Addr = PtrAdd->getReg(0);
1386 Base = PtrAdd->getBaseReg();
1387 return true;
1388 }
1389
1390 return false;
1391}
1392
1393bool CombinerHelper::findPreIndexCandidate(GLoadStore &LdSt, Register &Addr,
1394 Register &Base,
1395 Register &Offset) const {
1396 auto &MF = *LdSt.getParent()->getParent();
1397 const auto &TLI = *MF.getSubtarget().getTargetLowering();
1398
1399 Addr = LdSt.getPointerReg();
1400 if (!mi_match(Addr, MRI, m_GPtrAdd(m_Reg(Base), m_Reg(Offset))) ||
1401 MRI.hasOneNonDBGUse(Addr))
1402 return false;
1403
1404 if (!ForceLegalIndexing &&
1405 !TLI.isIndexingLegal(LdSt, Base, Offset, /*IsPre*/ true, MRI))
1406 return false;
1407
1408 if (!isIndexedLoadStoreLegal(LdSt))
1409 return false;
1410
1411 MachineInstr *BaseDef = getDefIgnoringCopies(Base, MRI);
1412 if (BaseDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
1413 return false;
1414
1415 if (auto *St = dyn_cast<GStore>(&LdSt)) {
1416 // Would require a copy.
1417 if (Base == St->getValueReg())
1418 return false;
1419
1420 // We're expecting one use of Addr in MI, but it could also be the
1421 // value stored, which isn't actually dominated by the instruction.
1422 if (St->getValueReg() == Addr)
1423 return false;
1424 }
1425
1426 // Avoid increasing cross-block register pressure.
1427 for (auto &AddrUse : MRI.use_nodbg_instructions(Addr))
1428 if (AddrUse.getParent() != LdSt.getParent())
1429 return false;
1430
1431 // FIXME: check whether all uses of the base pointer are constant PtrAdds.
1432 // That might allow us to end base's liveness here by adjusting the constant.
1433 bool RealUse = false;
1434 for (auto &AddrUse : MRI.use_nodbg_instructions(Addr)) {
1435 if (!dominates(LdSt, AddrUse))
1436 return false; // All use must be dominated by the load/store.
1437
1438 // If Ptr may be folded in addressing mode of other use, then it's
1439 // not profitable to do this transformation.
1440 if (auto *UseLdSt = dyn_cast<GLoadStore>(&AddrUse)) {
1441 if (!canFoldInAddressingMode(UseLdSt, TLI, MRI))
1442 RealUse = true;
1443 } else {
1444 RealUse = true;
1445 }
1446 }
1447 return RealUse;
1448}
1449
1451 MachineInstr &MI, BuildFnTy &MatchInfo) const {
1452 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT);
1453
1454 // Check if there is a load that defines the vector being extracted from.
1455 auto *LoadMI = getOpcodeDef<GLoad>(MI.getOperand(1).getReg(), MRI);
1456 if (!LoadMI)
1457 return false;
1458
1459 Register Vector = MI.getOperand(1).getReg();
1460 LLT VecEltTy = MRI.getType(Vector).getElementType();
1461
1462 assert(MRI.getType(MI.getOperand(0).getReg()) == VecEltTy);
1463
1464 // Checking whether we should reduce the load width.
1465 if (!MRI.hasOneNonDBGUse(Vector))
1466 return false;
1467
1468 // Check if the defining load is simple.
1469 if (!LoadMI->isSimple())
1470 return false;
1471
1472 // If the vector element type is not a multiple of a byte then we are unable
1473 // to correctly compute an address to load only the extracted element as a
1474 // scalar.
1475 if (!VecEltTy.isByteSized())
1476 return false;
1477
1478 // Check for load fold barriers between the extraction and the load.
1479 if (MI.getParent() != LoadMI->getParent())
1480 return false;
1481 const unsigned MaxIter = 20;
1482 unsigned Iter = 0;
1483 for (const auto &Instr :
1484 instructionsWithoutDebug(LoadMI->getIterator(), MI.getIterator())) {
1485 if (Instr.isLoadFoldBarrier())
1486 return false;
1487 if (Iter++ == MaxIter)
1488 return false;
1489 }
1490
1491 // Check if the new load that we are going to create is legal
1492 // if we are in the post-legalization phase.
1493 MachineMemOperand MMO = LoadMI->getMMO();
1494 Align Alignment = MMO.getAlign();
1495 MachinePointerInfo PtrInfo;
1496 uint64_t Offset;
1497
1498 // Finding the appropriate PtrInfo if offset is a known constant.
1499 // This is required to create the memory operand for the narrowed load.
1500 // This machine memory operand object helps us infer about legality
1501 // before we proceed to combine the instruction.
1502 if (auto CVal = getIConstantVRegVal(Vector, MRI)) {
1503 int Elt = CVal->getZExtValue();
1504 // FIXME: should be (ABI size)*Elt.
1505 Offset = VecEltTy.getSizeInBits() * Elt / 8;
1506 PtrInfo = MMO.getPointerInfo().getWithOffset(Offset);
1507 } else {
1508 // Discard the pointer info except the address space because the memory
1509 // operand can't represent this new access since the offset is variable.
1510 Offset = VecEltTy.getSizeInBits() / 8;
1512 }
1513
1514 Alignment = commonAlignment(Alignment, Offset);
1515
1516 Register VecPtr = LoadMI->getPointerReg();
1517 LLT PtrTy = MRI.getType(VecPtr);
1518
1519 MachineFunction &MF = *MI.getMF();
1520 auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, VecEltTy);
1521
1522 LegalityQuery::MemDesc MMDesc(*NewMMO);
1523
1525 {TargetOpcode::G_LOAD, {VecEltTy, PtrTy}, {MMDesc}}))
1526 return false;
1527
1528 // Load must be allowed and fast on the target.
1530 auto &DL = MF.getDataLayout();
1531 unsigned Fast = 0;
1532 if (!getTargetLowering().allowsMemoryAccess(C, DL, VecEltTy, *NewMMO,
1533 &Fast) ||
1534 !Fast)
1535 return false;
1536
1537 Register Result = MI.getOperand(0).getReg();
1538 Register Index = MI.getOperand(2).getReg();
1539
1540 MatchInfo = [=](MachineIRBuilder &B) {
1541 GISelObserverWrapper DummyObserver;
1542 LegalizerHelper Helper(B.getMF(), DummyObserver, B);
1543 //// Get pointer to the vector element.
1544 Register finalPtr = Helper.getVectorElementPointer(
1545 LoadMI->getPointerReg(), MRI.getType(LoadMI->getOperand(0).getReg()),
1546 Index);
1547 // New G_LOAD instruction.
1548 B.buildLoad(Result, finalPtr, PtrInfo, Alignment);
1549 // Remove original GLOAD instruction.
1550 LoadMI->eraseFromParent();
1551 };
1552
1553 return true;
1554}
1555
1557 MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const {
1558 auto &LdSt = cast<GLoadStore>(MI);
1559
1560 if (LdSt.isAtomic())
1561 return false;
1562
1563 MatchInfo.IsPre = findPreIndexCandidate(LdSt, MatchInfo.Addr, MatchInfo.Base,
1564 MatchInfo.Offset);
1565 if (!MatchInfo.IsPre &&
1566 !findPostIndexCandidate(LdSt, MatchInfo.Addr, MatchInfo.Base,
1567 MatchInfo.Offset, MatchInfo.RematOffset))
1568 return false;
1569
1570 return true;
1571}
1572
1574 MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const {
1575 MachineInstr &AddrDef = *MRI.getVRegDef(MatchInfo.Addr);
1576 unsigned Opcode = MI.getOpcode();
1577 bool IsStore = Opcode == TargetOpcode::G_STORE;
1578 unsigned NewOpcode = getIndexedOpc(Opcode);
1579
1580 // If the offset constant didn't happen to dominate the load/store, we can
1581 // just clone it as needed.
1582 if (MatchInfo.RematOffset) {
1583 auto *OldCst = MRI.getVRegDef(MatchInfo.Offset);
1584 auto NewCst = Builder.buildConstant(MRI.getType(MatchInfo.Offset),
1585 *OldCst->getOperand(1).getCImm());
1586 MatchInfo.Offset = NewCst.getReg(0);
1587 }
1588
1589 auto MIB = Builder.buildInstr(NewOpcode);
1590 if (IsStore) {
1591 MIB.addDef(MatchInfo.Addr);
1592 MIB.addUse(MI.getOperand(0).getReg());
1593 } else {
1594 MIB.addDef(MI.getOperand(0).getReg());
1595 MIB.addDef(MatchInfo.Addr);
1596 }
1597
1598 MIB.addUse(MatchInfo.Base);
1599 MIB.addUse(MatchInfo.Offset);
1600 MIB.addImm(MatchInfo.IsPre);
1601 MIB->cloneMemRefs(*MI.getMF(), MI);
1602 MI.eraseFromParent();
1603 AddrDef.eraseFromParent();
1604
1605 LLVM_DEBUG(dbgs() << " Combinined to indexed operation");
1606}
1607
1609 MachineInstr *&OtherMI) const {
1610 unsigned Opcode = MI.getOpcode();
1611 bool IsDiv, IsSigned;
1612
1613 switch (Opcode) {
1614 default:
1615 llvm_unreachable("Unexpected opcode!");
1616 case TargetOpcode::G_SDIV:
1617 case TargetOpcode::G_UDIV: {
1618 IsDiv = true;
1619 IsSigned = Opcode == TargetOpcode::G_SDIV;
1620 break;
1621 }
1622 case TargetOpcode::G_SREM:
1623 case TargetOpcode::G_UREM: {
1624 IsDiv = false;
1625 IsSigned = Opcode == TargetOpcode::G_SREM;
1626 break;
1627 }
1628 }
1629
1630 Register Src1 = MI.getOperand(1).getReg();
1631 unsigned DivOpcode, RemOpcode, DivremOpcode;
1632 if (IsSigned) {
1633 DivOpcode = TargetOpcode::G_SDIV;
1634 RemOpcode = TargetOpcode::G_SREM;
1635 DivremOpcode = TargetOpcode::G_SDIVREM;
1636 } else {
1637 DivOpcode = TargetOpcode::G_UDIV;
1638 RemOpcode = TargetOpcode::G_UREM;
1639 DivremOpcode = TargetOpcode::G_UDIVREM;
1640 }
1641
1642 if (!isLegalOrBeforeLegalizer({DivremOpcode, {MRI.getType(Src1)}}))
1643 return false;
1644
1645 // Combine:
1646 // %div:_ = G_[SU]DIV %src1:_, %src2:_
1647 // %rem:_ = G_[SU]REM %src1:_, %src2:_
1648 // into:
1649 // %div:_, %rem:_ = G_[SU]DIVREM %src1:_, %src2:_
1650
1651 // Combine:
1652 // %rem:_ = G_[SU]REM %src1:_, %src2:_
1653 // %div:_ = G_[SU]DIV %src1:_, %src2:_
1654 // into:
1655 // %div:_, %rem:_ = G_[SU]DIVREM %src1:_, %src2:_
1656
1657 for (auto &UseMI : MRI.use_nodbg_instructions(Src1)) {
1658 if (MI.getParent() == UseMI.getParent() &&
1659 ((IsDiv && UseMI.getOpcode() == RemOpcode) ||
1660 (!IsDiv && UseMI.getOpcode() == DivOpcode)) &&
1661 matchEqualDefs(MI.getOperand(2), UseMI.getOperand(2)) &&
1662 matchEqualDefs(MI.getOperand(1), UseMI.getOperand(1))) {
1663 OtherMI = &UseMI;
1664 return true;
1665 }
1666 }
1667
1668 return false;
1669}
1670
1672 MachineInstr *&OtherMI) const {
1673 unsigned Opcode = MI.getOpcode();
1674 assert(OtherMI && "OtherMI shouldn't be empty.");
1675
1676 Register DestDivReg, DestRemReg;
1677 if (Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_UDIV) {
1678 DestDivReg = MI.getOperand(0).getReg();
1679 DestRemReg = OtherMI->getOperand(0).getReg();
1680 } else {
1681 DestDivReg = OtherMI->getOperand(0).getReg();
1682 DestRemReg = MI.getOperand(0).getReg();
1683 }
1684
1685 bool IsSigned =
1686 Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_SREM;
1687
1688 // Check which instruction is first in the block so we don't break def-use
1689 // deps by "moving" the instruction incorrectly. Also keep track of which
1690 // instruction is first so we pick it's operands, avoiding use-before-def
1691 // bugs.
1692 MachineInstr *FirstInst = dominates(MI, *OtherMI) ? &MI : OtherMI;
1693 Builder.setInstrAndDebugLoc(*FirstInst);
1694
1695 Builder.buildInstr(IsSigned ? TargetOpcode::G_SDIVREM
1696 : TargetOpcode::G_UDIVREM,
1697 {DestDivReg, DestRemReg},
1698 { FirstInst->getOperand(1), FirstInst->getOperand(2) });
1699 MI.eraseFromParent();
1700 OtherMI->eraseFromParent();
1701}
1702
1704 MachineInstr &MI, MachineInstr *&BrCond) const {
1705 assert(MI.getOpcode() == TargetOpcode::G_BR);
1706
1707 // Try to match the following:
1708 // bb1:
1709 // G_BRCOND %c1, %bb2
1710 // G_BR %bb3
1711 // bb2:
1712 // ...
1713 // bb3:
1714
1715 // The above pattern does not have a fall through to the successor bb2, always
1716 // resulting in a branch no matter which path is taken. Here we try to find
1717 // and replace that pattern with conditional branch to bb3 and otherwise
1718 // fallthrough to bb2. This is generally better for branch predictors.
1719
1720 MachineBasicBlock *MBB = MI.getParent();
1722 if (BrIt == MBB->begin())
1723 return false;
1724 assert(std::next(BrIt) == MBB->end() && "expected G_BR to be a terminator");
1725
1726 BrCond = &*std::prev(BrIt);
1727 if (BrCond->getOpcode() != TargetOpcode::G_BRCOND)
1728 return false;
1729
1730 // Check that the next block is the conditional branch target. Also make sure
1731 // that it isn't the same as the G_BR's target (otherwise, this will loop.)
1732 MachineBasicBlock *BrCondTarget = BrCond->getOperand(1).getMBB();
1733 return BrCondTarget != MI.getOperand(0).getMBB() &&
1734 MBB->isLayoutSuccessor(BrCondTarget);
1735}
1736
1738 MachineInstr &MI, MachineInstr *&BrCond) const {
1739 MachineBasicBlock *BrTarget = MI.getOperand(0).getMBB();
1740 Builder.setInstrAndDebugLoc(*BrCond);
1741 LLT Ty = MRI.getType(BrCond->getOperand(0).getReg());
1742 // FIXME: Does int/fp matter for this? If so, we might need to restrict
1743 // this to i1 only since we might not know for sure what kind of
1744 // compare generated the condition value.
1745 auto True = Builder.buildConstant(
1746 Ty, getICmpTrueVal(getTargetLowering(), false, false));
1747 auto Xor = Builder.buildXor(Ty, BrCond->getOperand(0), True);
1748
1749 auto *FallthroughBB = BrCond->getOperand(1).getMBB();
1750 Observer.changingInstr(MI);
1751 MI.getOperand(0).setMBB(FallthroughBB);
1752 Observer.changedInstr(MI);
1753
1754 // Change the conditional branch to use the inverted condition and
1755 // new target block.
1756 Observer.changingInstr(*BrCond);
1757 BrCond->getOperand(0).setReg(Xor.getReg(0));
1758 BrCond->getOperand(1).setMBB(BrTarget);
1759 Observer.changedInstr(*BrCond);
1760}
1761
1764 unsigned MaxLen) const {
1765 auto &[Dst, Src, KnownLen, Alignment, DstAlignCanChange, MemOps] = MatchInfo;
1766 return canLowerMemCpyFamily(MI, MRI, MaxLen, Dst, Src, KnownLen, Alignment,
1767 DstAlignCanChange, MemOps);
1768}
1769
1771 MachineInstr &MI, MemCpyFamilyLoweringInfo &MatchInfo) const {
1772 auto &[Dst, Src, KnownLen, Alignment, DstAlignCanChange, MemOps] = MatchInfo;
1773 MachineIRBuilder HelperBuilder(MI);
1774 GISelObserverWrapper DummyObserver;
1775 LegalizerHelper Helper(HelperBuilder.getMF(), DummyObserver, HelperBuilder);
1776 bool Changed = Helper.lowerMemCpyFamily(MI, Dst, Src, KnownLen, Alignment,
1777 DstAlignCanChange, MemOps) ==
1779 assert(Changed && "expected memcpy-family instruction to lower");
1780 (void)Changed;
1781}
1782
1784 unsigned MaxLen) const {
1785 MachineIRBuilder HelperBuilder(MI);
1786 GISelObserverWrapper DummyObserver;
1787 LegalizerHelper Helper(HelperBuilder.getMF(), DummyObserver, HelperBuilder);
1788 return Helper.lowerMemCpyFamily(MI, MaxLen) ==
1790}
1791
1793 PtrAddChain &MatchInfo) const {
1794 // We're trying to match the following pattern:
1795 // %t1 = G_PTR_ADD %base, G_CONSTANT imm1
1796 // %root = G_PTR_ADD %t1, G_CONSTANT imm2
1797 // -->
1798 // %root = G_PTR_ADD %base, G_CONSTANT (imm1 + imm2)
1799
1800 if (MI.getOpcode() != TargetOpcode::G_PTR_ADD)
1801 return false;
1802
1803 Register Add2 = MI.getOperand(1).getReg();
1804 Register Imm1 = MI.getOperand(2).getReg();
1805 auto MaybeImmVal = getIConstantVRegValWithLookThrough(Imm1, MRI);
1806 if (!MaybeImmVal)
1807 return false;
1808
1809 Register Base, Imm2;
1810 uint32_t LHSPtrAddFlags;
1811 if (!mi_match(Add2, MRI,
1812 m_GPtrAdd(m_Reg(Base), m_Reg(Imm2), m_MIFlags(LHSPtrAddFlags))))
1813 return false;
1814
1815 auto MaybeImm2Val = getIConstantVRegValWithLookThrough(Imm2, MRI);
1816 if (!MaybeImm2Val)
1817 return false;
1818
1819 // Check if the new combined immediate forms an illegal addressing mode.
1820 // Do not combine if it was legal before but would get illegal.
1821 // To do so, we need to find a load/store user of the pointer to get
1822 // the access type.
1823 Type *AccessTy = nullptr;
1824 auto &MF = *MI.getMF();
1825 for (auto &UseMI : MRI.use_nodbg_instructions(MI.getOperand(0).getReg())) {
1826 if (auto *LdSt = dyn_cast<GLoadStore>(&UseMI)) {
1827 AccessTy = getTypeForLLT(MRI.getType(LdSt->getReg(0)),
1828 MF.getFunction().getContext());
1829 break;
1830 }
1831 }
1833 APInt CombinedImm = MaybeImmVal->Value + MaybeImm2Val->Value;
1834 AMNew.BaseOffs = CombinedImm.getSExtValue();
1835 if (AccessTy) {
1836 AMNew.HasBaseReg = true;
1838 AMOld.BaseOffs = MaybeImmVal->Value.getSExtValue();
1839 AMOld.HasBaseReg = true;
1840 unsigned AS = MRI.getType(Add2).getAddressSpace();
1841 const auto &TLI = *MF.getSubtarget().getTargetLowering();
1842 if (TLI.isLegalAddressingMode(MF.getDataLayout(), AMOld, AccessTy, AS) &&
1843 !TLI.isLegalAddressingMode(MF.getDataLayout(), AMNew, AccessTy, AS))
1844 return false;
1845 }
1846
1847 // Reassociating nuw additions preserves nuw. If both original G_PTR_ADDs are
1848 // inbounds, reaching the same result in one G_PTR_ADD is also inbounds.
1849 // The nusw constraints are satisfied because imm1+imm2 cannot exceed the
1850 // largest signed integer that fits into the index type, which is the maximum
1851 // size of allocated objects according to the IR Language Reference.
1852 unsigned PtrAddFlags = MI.getFlags();
1853 bool IsNoUWrap = PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::NoUWrap;
1854 bool IsInBounds =
1855 PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::InBounds;
1856 unsigned Flags = 0;
1857 if (IsNoUWrap)
1859 if (IsInBounds) {
1862 }
1863
1864 // Pass the combined immediate to the apply function.
1865 MatchInfo.Imm = AMNew.BaseOffs;
1866 MatchInfo.Base = Base;
1867 MatchInfo.Bank = getRegBank(Imm2);
1868 MatchInfo.Flags = Flags;
1869 return true;
1870}
1871
1873 PtrAddChain &MatchInfo) const {
1874 assert(MI.getOpcode() == TargetOpcode::G_PTR_ADD && "Expected G_PTR_ADD");
1875 MachineIRBuilder MIB(MI);
1876 LLT OffsetTy = MRI.getType(MI.getOperand(2).getReg());
1877 auto NewOffset = MIB.buildConstant(OffsetTy, MatchInfo.Imm);
1878 setRegBank(NewOffset.getReg(0), MatchInfo.Bank);
1879 Observer.changingInstr(MI);
1880 MI.getOperand(1).setReg(MatchInfo.Base);
1881 MI.getOperand(2).setReg(NewOffset.getReg(0));
1882 MI.setFlags(MatchInfo.Flags);
1883 Observer.changedInstr(MI);
1884}
1885
1887 RegisterImmPair &MatchInfo) const {
1888 // We're trying to match the following pattern with any of
1889 // G_SHL/G_ASHR/G_LSHR/G_SSHLSAT/G_USHLSAT shift instructions:
1890 // %t1 = SHIFT %base, G_CONSTANT imm1
1891 // %root = SHIFT %t1, G_CONSTANT imm2
1892 // -->
1893 // %root = SHIFT %base, G_CONSTANT (imm1 + imm2)
1894
1895 unsigned Opcode = MI.getOpcode();
1896 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
1897 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_SSHLSAT ||
1898 Opcode == TargetOpcode::G_USHLSAT) &&
1899 "Expected G_SHL, G_ASHR, G_LSHR, G_SSHLSAT or G_USHLSAT");
1900
1901 Register Shl2 = MI.getOperand(1).getReg();
1902 Register Imm1 = MI.getOperand(2).getReg();
1903 auto MaybeImmVal = getIConstantVRegValWithLookThrough(Imm1, MRI);
1904 if (!MaybeImmVal)
1905 return false;
1906
1907 MachineInstr *Shl2Def;
1908 if (!mi_match(Shl2, MRI, m_MInstr(Shl2Def)) || Shl2Def->getOpcode() != Opcode)
1909 return false;
1910
1911 Register Base = Shl2Def->getOperand(1).getReg();
1912 Register Imm2 = Shl2Def->getOperand(2).getReg();
1913 auto MaybeImm2Val = getIConstantVRegValWithLookThrough(Imm2, MRI);
1914 if (!MaybeImm2Val)
1915 return false;
1916
1917 // Pass the combined immediate to the apply function.
1918 MatchInfo.Imm =
1919 (MaybeImmVal->Value.getZExtValue() + MaybeImm2Val->Value).getZExtValue();
1920 MatchInfo.Reg = Base;
1921
1922 // There is no simple replacement for a saturating unsigned left shift that
1923 // exceeds the scalar size.
1924 if (Opcode == TargetOpcode::G_USHLSAT &&
1925 MatchInfo.Imm >= MRI.getType(Shl2).getScalarSizeInBits())
1926 return false;
1927
1928 return true;
1929}
1930
1932 RegisterImmPair &MatchInfo) const {
1933 unsigned Opcode = MI.getOpcode();
1934 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
1935 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_SSHLSAT ||
1936 Opcode == TargetOpcode::G_USHLSAT) &&
1937 "Expected G_SHL, G_ASHR, G_LSHR, G_SSHLSAT or G_USHLSAT");
1938
1939 LLT Ty = MRI.getType(MI.getOperand(1).getReg());
1940 unsigned const ScalarSizeInBits = Ty.getScalarSizeInBits();
1941 auto Imm = MatchInfo.Imm;
1942
1943 if (Imm >= ScalarSizeInBits) {
1944 // Any logical shift that exceeds scalar size will produce zero.
1945 if (Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR) {
1946 Builder.buildConstant(MI.getOperand(0), 0);
1947 MI.eraseFromParent();
1948 return;
1949 }
1950 // Arithmetic shift and saturating signed left shift have no effect beyond
1951 // scalar size.
1952 Imm = ScalarSizeInBits - 1;
1953 }
1954
1955 LLT ImmTy = MRI.getType(MI.getOperand(2).getReg());
1956 Register NewImm = Builder.buildConstant(ImmTy, Imm).getReg(0);
1957 Observer.changingInstr(MI);
1958 MI.getOperand(1).setReg(MatchInfo.Reg);
1959 MI.getOperand(2).setReg(NewImm);
1960 Observer.changedInstr(MI);
1961}
1962
1964 MachineInstr &MI, ShiftOfShiftedLogic &MatchInfo) const {
1965 // We're trying to match the following pattern with any of
1966 // G_SHL/G_ASHR/G_LSHR/G_USHLSAT/G_SSHLSAT shift instructions in combination
1967 // with any of G_AND/G_OR/G_XOR logic instructions.
1968 // %t1 = SHIFT %X, G_CONSTANT C0
1969 // %t2 = LOGIC %t1, %Y
1970 // %root = SHIFT %t2, G_CONSTANT C1
1971 // -->
1972 // %t3 = SHIFT %X, G_CONSTANT (C0+C1)
1973 // %t4 = SHIFT %Y, G_CONSTANT C1
1974 // %root = LOGIC %t3, %t4
1975 unsigned ShiftOpcode = MI.getOpcode();
1976 assert((ShiftOpcode == TargetOpcode::G_SHL ||
1977 ShiftOpcode == TargetOpcode::G_ASHR ||
1978 ShiftOpcode == TargetOpcode::G_LSHR ||
1979 ShiftOpcode == TargetOpcode::G_USHLSAT ||
1980 ShiftOpcode == TargetOpcode::G_SSHLSAT) &&
1981 "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
1982
1983 // Match a one-use bitwise logic op.
1984 Register LogicDest = MI.getOperand(1).getReg();
1985 if (!MRI.hasOneNonDBGUse(LogicDest))
1986 return false;
1987
1988 MachineInstr *LogicMI;
1989 if (!mi_match(LogicDest, MRI, m_MInstr(LogicMI)))
1990 return false;
1991 unsigned LogicOpcode = LogicMI->getOpcode();
1992 if (LogicOpcode != TargetOpcode::G_AND && LogicOpcode != TargetOpcode::G_OR &&
1993 LogicOpcode != TargetOpcode::G_XOR)
1994 return false;
1995
1996 // Find a matching one-use shift by constant.
1997 const Register C1 = MI.getOperand(2).getReg();
1998 auto MaybeImmVal = getIConstantVRegValWithLookThrough(C1, MRI);
1999 if (!MaybeImmVal || MaybeImmVal->Value == 0)
2000 return false;
2001
2002 const uint64_t C1Val = MaybeImmVal->Value.getZExtValue();
2003
2004 auto matchFirstShift = [&](const MachineInstr *MI, uint64_t &ShiftVal) {
2005 // Shift should match previous one and should be a one-use.
2006 if (MI->getOpcode() != ShiftOpcode ||
2007 !MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
2008 return false;
2009
2010 // Must be a constant.
2011 auto MaybeImmVal =
2012 getIConstantVRegValWithLookThrough(MI->getOperand(2).getReg(), MRI);
2013 if (!MaybeImmVal)
2014 return false;
2015
2016 ShiftVal = MaybeImmVal->Value.getSExtValue();
2017 return true;
2018 };
2019
2020 // Logic ops are commutative, so check each operand for a match.
2021 Register LogicMIReg1 = LogicMI->getOperand(1).getReg();
2022 MachineInstr *LogicMIOp1;
2023 Register LogicMIReg2 = LogicMI->getOperand(2).getReg();
2024 MachineInstr *LogicMIOp2;
2025 if (!mi_match(LogicMIReg1, MRI, m_MInstr(LogicMIOp1)) ||
2026 !mi_match(LogicMIReg2, MRI, m_MInstr(LogicMIOp2)))
2027 return false;
2028 uint64_t C0Val;
2029
2030 if (matchFirstShift(LogicMIOp1, C0Val)) {
2031 MatchInfo.LogicNonShiftReg = LogicMIReg2;
2032 MatchInfo.Shift2 = LogicMIOp1;
2033 } else if (matchFirstShift(LogicMIOp2, C0Val)) {
2034 MatchInfo.LogicNonShiftReg = LogicMIReg1;
2035 MatchInfo.Shift2 = LogicMIOp2;
2036 } else
2037 return false;
2038
2039 MatchInfo.ValSum = C0Val + C1Val;
2040
2041 // The fold is not valid if the sum of the shift values exceeds bitwidth.
2042 if (MatchInfo.ValSum >= MRI.getType(LogicDest).getScalarSizeInBits())
2043 return false;
2044
2045 MatchInfo.Logic = LogicMI;
2046 return true;
2047}
2048
2050 MachineInstr &MI, ShiftOfShiftedLogic &MatchInfo) const {
2051 unsigned Opcode = MI.getOpcode();
2052 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
2053 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_USHLSAT ||
2054 Opcode == TargetOpcode::G_SSHLSAT) &&
2055 "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
2056
2057 LLT ShlType = MRI.getType(MI.getOperand(2).getReg());
2058 LLT DestType = MRI.getType(MI.getOperand(0).getReg());
2059
2060 Register Const = Builder.buildConstant(ShlType, MatchInfo.ValSum).getReg(0);
2061
2062 Register Shift1Base = MatchInfo.Shift2->getOperand(1).getReg();
2063 Register Shift1 =
2064 Builder.buildInstr(Opcode, {DestType}, {Shift1Base, Const}).getReg(0);
2065
2066 // If LogicNonShiftReg is the same to Shift1Base, and shift1 const is the same
2067 // to MatchInfo.Shift2 const, CSEMIRBuilder will reuse the old shift1 when
2068 // build shift2. So, if we erase MatchInfo.Shift2 at the end, actually we
2069 // remove old shift1. And it will cause crash later. So erase it earlier to
2070 // avoid the crash.
2071 MatchInfo.Shift2->eraseFromParent();
2072
2073 Register Shift2Const = MI.getOperand(2).getReg();
2074 Register Shift2 = Builder
2075 .buildInstr(Opcode, {DestType},
2076 {MatchInfo.LogicNonShiftReg, Shift2Const})
2077 .getReg(0);
2078
2079 Register Dest = MI.getOperand(0).getReg();
2080 Builder.buildInstr(MatchInfo.Logic->getOpcode(), {Dest}, {Shift1, Shift2});
2081
2082 // This was one use so it's safe to remove it.
2083 MatchInfo.Logic->eraseFromParent();
2084
2085 MI.eraseFromParent();
2086}
2087
2093
2095 LshrOfTruncOfLshr &MatchInfo,
2096 MachineInstr &ShiftMI) const {
2097 assert(MI.getOpcode() == TargetOpcode::G_LSHR && "Expected a G_LSHR");
2098
2099 Register N0 = MI.getOperand(1).getReg();
2100 Register N1 = MI.getOperand(2).getReg();
2101 unsigned OpSizeInBits = MRI.getType(N0).getScalarSizeInBits();
2102
2103 APInt N1C, N001C;
2104 if (!mi_match(N1, MRI, m_ICstOrSplat(N1C)))
2105 return false;
2106 auto N001 = ShiftMI.getOperand(2).getReg();
2107 if (!mi_match(N001, MRI, m_ICstOrSplat(N001C)))
2108 return false;
2109
2110 if (N001C.getBitWidth() > N1C.getBitWidth())
2111 N1C = N1C.zext(N001C.getBitWidth());
2112 else
2113 N001C = N001C.zext(N1C.getBitWidth());
2114
2115 Register InnerShift = ShiftMI.getOperand(0).getReg();
2116 LLT InnerShiftTy = MRI.getType(InnerShift);
2117 uint64_t InnerShiftSize = InnerShiftTy.getScalarSizeInBits();
2118 if ((N1C + N001C).ult(InnerShiftSize)) {
2119 MatchInfo.Src = ShiftMI.getOperand(1).getReg();
2120 MatchInfo.ShiftAmt = N1C + N001C;
2121 MatchInfo.ShiftAmtTy = MRI.getType(N001);
2122 MatchInfo.InnerShiftTy = InnerShiftTy;
2123
2124 if ((N001C + OpSizeInBits) == InnerShiftSize)
2125 return true;
2126 if (MRI.hasOneUse(N0) && MRI.hasOneUse(InnerShift)) {
2127 MatchInfo.Mask = true;
2128 MatchInfo.MaskVal = APInt(N1C.getBitWidth(), OpSizeInBits) - N1C;
2129 return true;
2130 }
2131 }
2132 return false;
2133}
2134
2136 MachineInstr &MI, LshrOfTruncOfLshr &MatchInfo) const {
2137 assert(MI.getOpcode() == TargetOpcode::G_LSHR && "Expected a G_LSHR");
2138
2139 Register Dst = MI.getOperand(0).getReg();
2140 auto ShiftAmt =
2141 Builder.buildConstant(MatchInfo.ShiftAmtTy, MatchInfo.ShiftAmt);
2142 auto Shift =
2143 Builder.buildLShr(MatchInfo.InnerShiftTy, MatchInfo.Src, ShiftAmt);
2144 if (MatchInfo.Mask == true) {
2145 APInt MaskVal =
2147 MatchInfo.MaskVal.getZExtValue());
2148 auto Mask = Builder.buildConstant(MatchInfo.InnerShiftTy, MaskVal);
2149 auto And = Builder.buildAnd(MatchInfo.InnerShiftTy, Shift, Mask);
2150 Builder.buildTrunc(Dst, And);
2151 } else
2152 Builder.buildTrunc(Dst, Shift);
2153 MI.eraseFromParent();
2154}
2155
2157 unsigned &ShiftVal) const {
2158 assert(MI.getOpcode() == TargetOpcode::G_MUL && "Expected a G_MUL");
2159 auto MaybeImmVal =
2160 getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
2161 if (!MaybeImmVal)
2162 return false;
2163
2164 ShiftVal = MaybeImmVal->Value.exactLogBase2();
2165 return (static_cast<int32_t>(ShiftVal) != -1);
2166}
2167
2169 unsigned &ShiftVal) const {
2170 assert(MI.getOpcode() == TargetOpcode::G_MUL && "Expected a G_MUL");
2171 MachineIRBuilder MIB(MI);
2172 LLT ShiftTy = MRI.getType(MI.getOperand(0).getReg());
2173 auto ShiftCst = MIB.buildConstant(ShiftTy, ShiftVal);
2174 Observer.changingInstr(MI);
2175 MI.setDesc(MIB.getTII().get(TargetOpcode::G_SHL));
2176 MI.getOperand(2).setReg(ShiftCst.getReg(0));
2177 if (ShiftVal == ShiftTy.getScalarSizeInBits() - 1)
2179 Observer.changedInstr(MI);
2180}
2181
2183 BuildFnTy &MatchInfo) const {
2184 GSub &Sub = cast<GSub>(MI);
2185
2186 LLT Ty = MRI.getType(Sub.getReg(0));
2187
2188 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {Ty}}))
2189 return false;
2190
2192 return false;
2193
2194 APInt Imm = getIConstantFromReg(Sub.getRHSReg(), MRI);
2195
2196 MatchInfo = [=, &MI](MachineIRBuilder &B) {
2197 auto NegCst = B.buildConstant(Ty, -Imm);
2198 Observer.changingInstr(MI);
2199 MI.setDesc(B.getTII().get(TargetOpcode::G_ADD));
2200 MI.getOperand(2).setReg(NegCst.getReg(0));
2202 if (Imm.isMinSignedValue())
2204 Observer.changedInstr(MI);
2205 };
2206 return true;
2207}
2208
2209// shl ([sza]ext x), y => zext (shl x, y), if shift does not overflow source
2211 RegisterImmPair &MatchData) const {
2212 assert(MI.getOpcode() == TargetOpcode::G_SHL && VT);
2213 if (!getTargetLowering().isDesirableToPullExtFromShl(MI))
2214 return false;
2215
2216 Register LHS = MI.getOperand(1).getReg();
2217
2218 Register ExtSrc;
2219 if (!mi_match(LHS, MRI, m_GAnyExt(m_Reg(ExtSrc))) &&
2220 !mi_match(LHS, MRI, m_GZExt(m_Reg(ExtSrc))) &&
2221 !mi_match(LHS, MRI, m_GSExt(m_Reg(ExtSrc))))
2222 return false;
2223
2224 Register RHS = MI.getOperand(2).getReg();
2225 auto MaybeShiftAmtVal = isConstantOrConstantSplatVector(RHS, MRI);
2226 if (!MaybeShiftAmtVal)
2227 return false;
2228
2229 if (LI) {
2230 LLT SrcTy = MRI.getType(ExtSrc);
2231
2232 // We only really care about the legality with the shifted value. We can
2233 // pick any type the constant shift amount, so ask the target what to
2234 // use. Otherwise we would have to guess and hope it is reported as legal.
2235 LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(SrcTy);
2236 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SHL, {SrcTy, ShiftAmtTy}}))
2237 return false;
2238 }
2239
2240 int64_t ShiftAmt = MaybeShiftAmtVal->getSExtValue();
2241 MatchData.Reg = ExtSrc;
2242 MatchData.Imm = ShiftAmt;
2243
2244 unsigned MinLeadingZeros = VT->getKnownZeroes(ExtSrc).countl_one();
2245 unsigned SrcTySize = MRI.getType(ExtSrc).getScalarSizeInBits();
2246 return MinLeadingZeros >= ShiftAmt && ShiftAmt < SrcTySize;
2247}
2248
2250 MachineInstr &MI, const RegisterImmPair &MatchData) const {
2251 Register ExtSrcReg = MatchData.Reg;
2252 int64_t ShiftAmtVal = MatchData.Imm;
2253
2254 LLT ExtSrcTy = MRI.getType(ExtSrcReg);
2255 auto ShiftAmt = Builder.buildConstant(ExtSrcTy, ShiftAmtVal);
2256 auto NarrowShift =
2257 Builder.buildShl(ExtSrcTy, ExtSrcReg, ShiftAmt, MI.getFlags());
2258 Builder.buildZExt(MI.getOperand(0), NarrowShift);
2259 MI.eraseFromParent();
2260}
2261
2263 const MachineRegisterInfo &MRI) {
2264 while (mi_match(Reg, MRI, m_GBitcast(m_Reg(Reg))))
2265 ;
2266
2267 return Reg;
2268}
2269
2272 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2273 "Expected an unmerge");
2274 auto &Unmerge = cast<GUnmerge>(MI);
2275 Register SrcReg = peekThroughBitcast(Unmerge.getSourceReg(), MRI);
2276
2277 auto *SrcInstr = getOpcodeDef<GMergeLikeInstr>(SrcReg, MRI);
2278 if (!SrcInstr)
2279 return false;
2280
2281 // Check the source type of the merge.
2282 LLT SrcMergeTy = MRI.getType(SrcInstr->getSourceReg(0));
2283 LLT Dst0Ty = MRI.getType(Unmerge.getReg(0));
2284 bool SameSize = Dst0Ty.getSizeInBits() == SrcMergeTy.getSizeInBits();
2285 if (SrcMergeTy != Dst0Ty && !SameSize)
2286 return false;
2287 // They are the same now (modulo a bitcast).
2288 // We can collect all the src registers.
2289 for (unsigned Idx = 0; Idx < SrcInstr->getNumSources(); ++Idx)
2290 Operands.push_back(SrcInstr->getSourceReg(Idx));
2291 return true;
2292}
2293
2296 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2297 "Expected an unmerge");
2298 assert((MI.getNumOperands() - 1 == Operands.size()) &&
2299 "Not enough operands to replace all defs");
2300 unsigned NumElems = MI.getNumOperands() - 1;
2301
2302 LLT SrcTy = MRI.getType(Operands[0]);
2303 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
2304 bool CanReuseInputDirectly = DstTy == SrcTy;
2305 for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
2306 Register DstReg = MI.getOperand(Idx).getReg();
2307 Register SrcReg = Operands[Idx];
2308
2309 // This combine may run after RegBankSelect, so we need to be aware of
2310 // register banks.
2311 const auto &DstCB = MRI.getRegClassOrRegBank(DstReg);
2312 if (!DstCB.isNull() && DstCB != MRI.getRegClassOrRegBank(SrcReg)) {
2313 SrcReg = Builder.buildCopy(MRI.getType(SrcReg), SrcReg).getReg(0);
2314 MRI.setRegClassOrRegBank(SrcReg, DstCB);
2315 }
2316
2317 if (CanReuseInputDirectly)
2318 replaceRegWith(MRI, DstReg, SrcReg);
2319 else
2320 Builder.buildCast(DstReg, SrcReg);
2321 }
2322 MI.eraseFromParent();
2323}
2324
2326 MachineInstr &MI, SmallVectorImpl<APInt> &Csts) const {
2327 unsigned SrcIdx = MI.getNumOperands() - 1;
2328 Register SrcReg = MI.getOperand(SrcIdx).getReg();
2329 // Break down the big constant in smaller ones.
2330 APInt Val;
2331 if (!mi_match(SrcReg, MRI, m_GConstantOrFConstantBits(Val)))
2332 return false;
2333
2334 LLT Dst0Ty = MRI.getType(MI.getOperand(0).getReg());
2335 unsigned ShiftAmt = Dst0Ty.getSizeInBits();
2336 // Unmerge a constant.
2337 for (unsigned Idx = 0; Idx != SrcIdx; ++Idx) {
2338 Csts.emplace_back(Val.trunc(ShiftAmt));
2339 Val = Val.lshr(ShiftAmt);
2340 }
2341
2342 return true;
2343}
2344
2346 MachineInstr &MI, SmallVectorImpl<APInt> &Csts) const {
2347 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2348 "Expected an unmerge");
2349 assert((MI.getNumOperands() - 1 == Csts.size()) &&
2350 "Not enough operands to replace all defs");
2351 unsigned NumElems = MI.getNumOperands() - 1;
2352 for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
2353 Register DstReg = MI.getOperand(Idx).getReg();
2354 Builder.buildConstant(DstReg, Csts[Idx]);
2355 }
2356
2357 MI.eraseFromParent();
2358}
2359
2362 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
2363 unsigned SrcIdx = MI.getNumOperands() - 1;
2364 Register SrcReg = MI.getOperand(SrcIdx).getReg();
2365 MatchInfo = [&MI](MachineIRBuilder &B) {
2366 unsigned NumElems = MI.getNumOperands() - 1;
2367 for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
2368 Register DstReg = MI.getOperand(Idx).getReg();
2369 B.buildUndef(DstReg);
2370 }
2371 };
2372 return mi_match(SrcReg, MRI, m_GImplicitDef());
2373}
2374
2376 MachineInstr &MI) const {
2377 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2378 "Expected an unmerge");
2379 if (!MRI.getType(MI.getOperand(0).getReg()).isScalar() ||
2380 !MRI.getType(MI.getOperand(MI.getNumDefs()).getReg()).isScalar())
2381 return false;
2382 // Check that all the lanes are dead except the first one.
2383 for (unsigned Idx = 1, EndIdx = MI.getNumDefs(); Idx != EndIdx; ++Idx) {
2384 if (!MRI.use_nodbg_empty(MI.getOperand(Idx).getReg()))
2385 return false;
2386 }
2387 return true;
2388}
2389
2391 MachineInstr &MI) const {
2392 Register SrcReg = MI.getOperand(MI.getNumDefs()).getReg();
2393 Register Dst0Reg = MI.getOperand(0).getReg();
2394 Builder.buildTrunc(Dst0Reg, SrcReg);
2395 MI.eraseFromParent();
2396}
2397
2399 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2400 "Expected an unmerge");
2401 Register Dst0Reg = MI.getOperand(0).getReg();
2402 LLT Dst0Ty = MRI.getType(Dst0Reg);
2403 // G_ZEXT on vector applies to each lane, so it will
2404 // affect all destinations. Therefore we won't be able
2405 // to simplify the unmerge to just the first definition.
2406 if (Dst0Ty.isVector())
2407 return false;
2408 Register SrcReg = MI.getOperand(MI.getNumDefs()).getReg();
2409 LLT SrcTy = MRI.getType(SrcReg);
2410 if (SrcTy.isVector())
2411 return false;
2412
2413 Register ZExtSrcReg;
2414 if (!mi_match(SrcReg, MRI, m_GZExt(m_Reg(ZExtSrcReg))))
2415 return false;
2416
2417 // Finally we can replace the first definition with
2418 // a zext of the source if the definition is big enough to hold
2419 // all of ZExtSrc bits.
2420 LLT ZExtSrcTy = MRI.getType(ZExtSrcReg);
2421 return ZExtSrcTy.getSizeInBits() <= Dst0Ty.getSizeInBits();
2422}
2423
2425 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2426 "Expected an unmerge");
2427
2428 Register Dst0Reg = MI.getOperand(0).getReg();
2429
2430 GZext *ZExtInstr =
2431 cast<GZext>(MRI.getVRegDef(MI.getOperand(MI.getNumDefs()).getReg()));
2432 Register ZExtSrcReg = ZExtInstr->getSrcReg();
2433 LLT Dst0Ty = MRI.getType(Dst0Reg);
2434 LLT ZExtSrcTy = MRI.getType(ZExtSrcReg);
2435
2436 if (Dst0Ty.getSizeInBits() > ZExtSrcTy.getSizeInBits()) {
2437 Builder.buildZExt(Dst0Reg, ZExtSrcReg);
2438 } else {
2439 assert(Dst0Ty.getSizeInBits() == ZExtSrcTy.getSizeInBits() &&
2440 "ZExt src doesn't fit in destination");
2441 replaceRegWith(MRI, Dst0Reg, ZExtSrcReg);
2442 }
2443
2444 Register ZeroReg;
2445 for (unsigned Idx = 1, EndIdx = MI.getNumDefs(); Idx != EndIdx; ++Idx) {
2446 if (!ZeroReg)
2447 ZeroReg = Builder.buildConstant(Dst0Ty, 0).getReg(0);
2448 replaceRegWith(MRI, MI.getOperand(Idx).getReg(), ZeroReg);
2449 }
2450 MI.eraseFromParent();
2451}
2452
2454 unsigned TargetShiftSize,
2455 unsigned &ShiftVal) const {
2456 assert((MI.getOpcode() == TargetOpcode::G_SHL ||
2457 MI.getOpcode() == TargetOpcode::G_LSHR ||
2458 MI.getOpcode() == TargetOpcode::G_ASHR) && "Expected a shift");
2459
2460 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2461 if (Ty.isVector()) // TODO:
2462 return false;
2463
2464 // Don't narrow further than the requested size.
2465 unsigned Size = Ty.getSizeInBits();
2466 if (Size <= TargetShiftSize)
2467 return false;
2468
2469 auto MaybeImmVal =
2470 getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
2471 if (!MaybeImmVal)
2472 return false;
2473
2474 ShiftVal = MaybeImmVal->Value.getSExtValue();
2475 return ShiftVal >= Size / 2 && ShiftVal < Size;
2476}
2477
2479 MachineInstr &MI, const unsigned &ShiftVal) const {
2480 Register DstReg = MI.getOperand(0).getReg();
2481 Register SrcReg = MI.getOperand(1).getReg();
2482 LLT Ty = MRI.getType(SrcReg);
2483 unsigned Size = Ty.getSizeInBits();
2484 unsigned HalfSize = Size / 2;
2485 assert(ShiftVal >= HalfSize);
2486
2487 LLT HalfTy = Ty.changeElementSize(HalfSize);
2488
2489 auto Unmerge = Builder.buildUnmerge(HalfTy, SrcReg);
2490 unsigned NarrowShiftAmt = ShiftVal - HalfSize;
2491
2492 if (MI.getOpcode() == TargetOpcode::G_LSHR) {
2493 Register Narrowed = Unmerge.getReg(1);
2494
2495 // dst = G_LSHR s64:x, C for C >= 32
2496 // =>
2497 // lo, hi = G_UNMERGE_VALUES x
2498 // dst = G_MERGE_VALUES (G_LSHR hi, C - 32), 0
2499
2500 if (NarrowShiftAmt != 0) {
2501 Narrowed = Builder.buildLShr(HalfTy, Narrowed,
2502 Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
2503 }
2504
2505 auto Zero = Builder.buildConstant(HalfTy, 0);
2506 Builder.buildMergeLikeInstr(DstReg, {Narrowed, Zero});
2507 } else if (MI.getOpcode() == TargetOpcode::G_SHL) {
2508 Register Narrowed = Unmerge.getReg(0);
2509 // dst = G_SHL s64:x, C for C >= 32
2510 // =>
2511 // lo, hi = G_UNMERGE_VALUES x
2512 // dst = G_MERGE_VALUES 0, (G_SHL hi, C - 32)
2513 if (NarrowShiftAmt != 0) {
2514 Narrowed = Builder.buildShl(HalfTy, Narrowed,
2515 Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
2516 }
2517
2518 auto Zero = Builder.buildConstant(HalfTy, 0);
2519 Builder.buildMergeLikeInstr(DstReg, {Zero, Narrowed});
2520 } else {
2521 assert(MI.getOpcode() == TargetOpcode::G_ASHR);
2522 auto Hi = Builder.buildAShr(
2523 HalfTy, Unmerge.getReg(1),
2524 Builder.buildConstant(HalfTy, HalfSize - 1));
2525
2526 if (ShiftVal == HalfSize) {
2527 // (G_ASHR i64:x, 32) ->
2528 // G_MERGE_VALUES hi_32(x), (G_ASHR hi_32(x), 31)
2529 Builder.buildMergeLikeInstr(DstReg, {Unmerge.getReg(1), Hi});
2530 } else if (ShiftVal == Size - 1) {
2531 // Don't need a second shift.
2532 // (G_ASHR i64:x, 63) ->
2533 // %narrowed = (G_ASHR hi_32(x), 31)
2534 // G_MERGE_VALUES %narrowed, %narrowed
2535 Builder.buildMergeLikeInstr(DstReg, {Hi, Hi});
2536 } else {
2537 auto Lo = Builder.buildAShr(
2538 HalfTy, Unmerge.getReg(1),
2539 Builder.buildConstant(HalfTy, ShiftVal - HalfSize));
2540
2541 // (G_ASHR i64:x, C) ->, for C >= 32
2542 // G_MERGE_VALUES (G_ASHR hi_32(x), C - 32), (G_ASHR hi_32(x), 31)
2543 Builder.buildMergeLikeInstr(DstReg, {Lo, Hi});
2544 }
2545 }
2546
2547 MI.eraseFromParent();
2548}
2549
2551 MachineInstr &MI, unsigned TargetShiftAmount) const {
2552 unsigned ShiftAmt;
2553 if (matchCombineShiftToUnmerge(MI, TargetShiftAmount, ShiftAmt)) {
2554 applyCombineShiftToUnmerge(MI, ShiftAmt);
2555 return true;
2556 }
2557
2558 return false;
2559}
2560
2562 Register &Reg) const {
2563 assert(MI.getOpcode() == TargetOpcode::G_ANYEXT && "Expected a G_ANYEXT");
2564 Register DstReg = MI.getOperand(0).getReg();
2565 Register SrcReg = MI.getOperand(1).getReg();
2566 Register OriginalSrcReg = getSrcRegIgnoringCopies(SrcReg, MRI);
2567 if (OriginalSrcReg.isValid())
2568 SrcReg = OriginalSrcReg;
2569 LLT DstTy = MRI.getType(DstReg);
2570 return mi_match(SrcReg, MRI,
2571 m_GTrunc(m_all_of(m_Reg(Reg), m_SpecificType(DstTy)))) &&
2572 canReplaceReg(DstReg, Reg, MRI);
2573}
2574
2576 Register &Reg) const {
2577 assert(MI.getOpcode() == TargetOpcode::G_ZEXT && "Expected a G_ZEXT");
2578 Register DstReg = MI.getOperand(0).getReg();
2579 Register SrcReg = MI.getOperand(1).getReg();
2580 LLT DstTy = MRI.getType(DstReg);
2581 if (mi_match(SrcReg, MRI,
2582 m_GTrunc(m_all_of(m_Reg(Reg), m_SpecificType(DstTy)))) &&
2583 canReplaceReg(DstReg, Reg, MRI)) {
2584 unsigned DstSize = DstTy.getScalarSizeInBits();
2585 unsigned SrcSize = MRI.getType(SrcReg).getScalarSizeInBits();
2586 return VT->getKnownBits(Reg).countMinLeadingZeros() >= DstSize - SrcSize;
2587 }
2588 return false;
2589}
2590
2592 const unsigned ShiftSize = ShiftTy.getScalarSizeInBits();
2593 const unsigned TruncSize = TruncTy.getScalarSizeInBits();
2594
2595 // ShiftTy > 32 > TruncTy -> 32
2596 if (ShiftSize > 32 && TruncSize < 32)
2597 return ShiftTy.changeElementSize(32);
2598
2599 // TODO: We could also reduce to 16 bits, but that's more target-dependent.
2600 // Some targets like it, some don't, some only like it under certain
2601 // conditions/processor versions, etc.
2602 // A TL hook might be needed for this.
2603
2604 // Don't combine
2605 return ShiftTy;
2606}
2607
2609 MachineInstr &MI, std::pair<MachineInstr *, LLT> &MatchInfo) const {
2610 assert(MI.getOpcode() == TargetOpcode::G_TRUNC && "Expected a G_TRUNC");
2611 Register DstReg = MI.getOperand(0).getReg();
2612 Register SrcReg = MI.getOperand(1).getReg();
2613
2614 if (!MRI.hasOneNonDBGUse(SrcReg))
2615 return false;
2616
2617 LLT SrcTy = MRI.getType(SrcReg);
2618 LLT DstTy = MRI.getType(DstReg);
2619
2620 MachineInstr *SrcMI = getDefIgnoringCopies(SrcReg, MRI);
2621 const auto &TL = getTargetLowering();
2622
2623 LLT NewShiftTy;
2624 switch (SrcMI->getOpcode()) {
2625 default:
2626 return false;
2627 case TargetOpcode::G_SHL: {
2628 NewShiftTy = DstTy;
2629
2630 // Make sure new shift amount is legal.
2631 KnownBits Known = VT->getKnownBits(SrcMI->getOperand(2).getReg());
2632 if (Known.getMaxValue().uge(NewShiftTy.getScalarSizeInBits()))
2633 return false;
2634 break;
2635 }
2636 case TargetOpcode::G_LSHR:
2637 case TargetOpcode::G_ASHR: {
2638 // For right shifts, we conservatively do not do the transform if the TRUNC
2639 // has any STORE users. The reason is that if we change the type of the
2640 // shift, we may break the truncstore combine.
2641 //
2642 // TODO: Fix truncstore combine to handle (trunc(lshr (trunc x), k)).
2643 for (auto &User : MRI.use_instructions(DstReg))
2644 if (User.getOpcode() == TargetOpcode::G_STORE)
2645 return false;
2646
2647 NewShiftTy = getMidVTForTruncRightShiftCombine(SrcTy, DstTy);
2648 if (NewShiftTy == SrcTy)
2649 return false;
2650
2651 // Make sure we won't lose information by truncating the high bits.
2652 KnownBits Known = VT->getKnownBits(SrcMI->getOperand(2).getReg());
2653 if (Known.getMaxValue().ugt(NewShiftTy.getScalarSizeInBits() -
2654 DstTy.getScalarSizeInBits()))
2655 return false;
2656 break;
2657 }
2658 }
2659
2661 {SrcMI->getOpcode(),
2662 {NewShiftTy, TL.getPreferredShiftAmountTy(NewShiftTy)}}))
2663 return false;
2664
2665 MatchInfo = std::make_pair(SrcMI, NewShiftTy);
2666 return true;
2667}
2668
2670 MachineInstr &MI, std::pair<MachineInstr *, LLT> &MatchInfo) const {
2671 MachineInstr *ShiftMI = MatchInfo.first;
2672 LLT NewShiftTy = MatchInfo.second;
2673
2674 Register Dst = MI.getOperand(0).getReg();
2675 LLT DstTy = MRI.getType(Dst);
2676
2677 Register ShiftAmt = ShiftMI->getOperand(2).getReg();
2678 Register ShiftSrc = ShiftMI->getOperand(1).getReg();
2679 ShiftSrc = Builder.buildTrunc(NewShiftTy, ShiftSrc).getReg(0);
2680
2681 const auto &TL = getTargetLowering();
2682 LLT PrefShiftTy = TL.getPreferredShiftAmountTy(NewShiftTy);
2683 if (MRI.getType(ShiftAmt) != PrefShiftTy)
2684 ShiftAmt = Builder.buildZExtOrTrunc(PrefShiftTy, ShiftAmt).getReg(0);
2685
2686 Register NewShift =
2687 Builder
2688 .buildInstr(ShiftMI->getOpcode(), {NewShiftTy}, {ShiftSrc, ShiftAmt})
2689 .getReg(0);
2690
2691 if (NewShiftTy == DstTy)
2692 replaceRegWith(MRI, Dst, NewShift);
2693 else
2694 Builder.buildTrunc(Dst, NewShift);
2695
2696 eraseInst(MI);
2697}
2698
2700 return all_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
2701 return !MO.isReg() ||
2702 getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
2703 });
2704}
2705
2707 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
2708 ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
2709 return all_of(Mask, [](int Elt) { return Elt < 0; });
2710}
2711
2713 MachineInstr &MI) const {
2714 assert((MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT ||
2715 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT) &&
2716 "Expected an insert/extract element op");
2717 LLT VecTy = MRI.getType(MI.getOperand(1).getReg());
2718 if (VecTy.isScalableVector())
2719 return false;
2720
2721 unsigned IdxIdx =
2722 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
2723 auto Idx = getIConstantVRegVal(MI.getOperand(IdxIdx).getReg(), MRI);
2724 if (!Idx)
2725 return false;
2726 return Idx->getZExtValue() >= VecTy.getNumElements();
2727}
2728
2729void CombinerHelper::eraseInst(MachineInstr &MI) const { MI.eraseFromParent(); }
2730
2732 const MachineOperand &MOP2) const {
2733 if (!MOP1.isReg() || !MOP2.isReg())
2734 return false;
2735 auto InstAndDef1 = getDefSrcRegIgnoringCopies(MOP1.getReg(), MRI);
2736 if (!InstAndDef1)
2737 return false;
2738 auto InstAndDef2 = getDefSrcRegIgnoringCopies(MOP2.getReg(), MRI);
2739 if (!InstAndDef2)
2740 return false;
2741 MachineInstr *I1 = InstAndDef1->MI;
2742 MachineInstr *I2 = InstAndDef2->MI;
2743
2744 // Handle a case like this:
2745 //
2746 // %0:_(s64), %1:_(s64) = G_UNMERGE_VALUES %2:_(<2 x s64>)
2747 //
2748 // Even though %0 and %1 are produced by the same instruction they are not
2749 // the same values.
2750 if (I1 == I2)
2751 return MOP1.getReg() == MOP2.getReg();
2752
2753 // If we have an instruction which loads or stores, we can't guarantee that
2754 // it is identical.
2755 //
2756 // For example, we may have
2757 //
2758 // %x1 = G_LOAD %addr (load N from @somewhere)
2759 // ...
2760 // call @foo
2761 // ...
2762 // %x2 = G_LOAD %addr (load N from @somewhere)
2763 // ...
2764 // %or = G_OR %x1, %x2
2765 //
2766 // It's possible that @foo will modify whatever lives at the address we're
2767 // loading from. To be safe, let's just assume that all loads and stores
2768 // are different (unless we have something which is guaranteed to not
2769 // change.)
2770 if (I1->mayLoadOrStore() && !I1->isDereferenceableInvariantLoad())
2771 return false;
2772
2773 // If both instructions are loads or stores, they are equal only if both
2774 // are dereferenceable invariant loads with the same number of bits.
2775 if (I1->mayLoadOrStore() && I2->mayLoadOrStore()) {
2778 if (!LS1 || !LS2)
2779 return false;
2780
2781 if (!I2->isDereferenceableInvariantLoad() ||
2782 (LS1->getMemSizeInBits() != LS2->getMemSizeInBits()))
2783 return false;
2784 }
2785
2786 // Check for physical registers on the instructions first to avoid cases
2787 // like this:
2788 //
2789 // %a = COPY $physreg
2790 // ...
2791 // SOMETHING implicit-def $physreg
2792 // ...
2793 // %b = COPY $physreg
2794 //
2795 // These copies are not equivalent.
2796 if (any_of(I1->uses(), [](const MachineOperand &MO) {
2797 return MO.isReg() && MO.getReg().isPhysical();
2798 })) {
2799 // Check if we have a case like this:
2800 //
2801 // %a = COPY $physreg
2802 // %b = COPY %a
2803 //
2804 // In this case, I1 and I2 will both be equal to %a = COPY $physreg.
2805 // From that, we know that they must have the same value, since they must
2806 // have come from the same COPY.
2807 return I1->isIdenticalTo(*I2);
2808 }
2809
2810 // We don't have any physical registers, so we don't necessarily need the
2811 // same vreg defs.
2812 //
2813 // On the off-chance that there's some target instruction feeding into the
2814 // instruction, let's use produceSameValue instead of isIdenticalTo.
2815 if (Builder.getTII().produceSameValue(*I1, *I2, &MRI)) {
2816 // Handle instructions with multiple defs that produce same values. Values
2817 // are same for operands with same index.
2818 // %0:_(s8), %1:_(s8), %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %4:_(<4 x s8>)
2819 // %5:_(s8), %6:_(s8), %7:_(s8), %8:_(s8) = G_UNMERGE_VALUES %4:_(<4 x s8>)
2820 // I1 and I2 are different instructions but produce same values,
2821 // %1 and %6 are same, %1 and %7 are not the same value.
2822 return I1->findRegisterDefOperandIdx(InstAndDef1->Reg, /*TRI=*/nullptr) ==
2823 I2->findRegisterDefOperandIdx(InstAndDef2->Reg, /*TRI=*/nullptr);
2824 }
2825 return false;
2826}
2827
2829 int64_t C) const {
2830 if (!MOP.isReg())
2831 return false;
2832 auto MaybeCst = isConstantOrConstantSplatVector(MOP.getReg(), MRI);
2833 // Compare as APInt so constants wider than 64 bits (e.g. i128 2) still match.
2834 return MaybeCst &&
2835 APInt::isSameValue(*MaybeCst, APInt(64, C, /*isSigned=*/true),
2836 /*SignedCompare=*/true);
2837}
2838
2840 double C) const {
2841 if (!MOP.isReg())
2842 return false;
2843 std::optional<FPValueAndVReg> MaybeCst;
2844 if (!mi_match(MOP.getReg(), MRI, m_GFCstOrSplat(MaybeCst)))
2845 return false;
2846
2847 return MaybeCst->Value.isExactlyValue(C);
2848}
2849
2851 unsigned OpIdx) const {
2852 assert(MI.getNumExplicitDefs() == 1 && "Expected one explicit def?");
2853 Register OldReg = MI.getOperand(0).getReg();
2854 Register Replacement = MI.getOperand(OpIdx).getReg();
2855 assert(canReplaceReg(OldReg, Replacement, MRI) && "Cannot replace register?");
2856 replaceRegWith(MRI, OldReg, Replacement);
2857 MI.eraseFromParent();
2858}
2859
2861 Register Replacement) const {
2862 assert(MI.getNumExplicitDefs() == 1 && "Expected one explicit def?");
2863 Register OldReg = MI.getOperand(0).getReg();
2864 assert(canReplaceReg(OldReg, Replacement, MRI) && "Cannot replace register?");
2865 replaceRegWith(MRI, OldReg, Replacement);
2866 MI.eraseFromParent();
2867}
2868
2870 unsigned ConstIdx) const {
2871 Register ConstReg = MI.getOperand(ConstIdx).getReg();
2872 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
2873
2874 // Get the shift amount
2875 auto VRegAndVal = getIConstantVRegValWithLookThrough(ConstReg, MRI);
2876 if (!VRegAndVal)
2877 return false;
2878
2879 // Return true of shift amount >= Bitwidth
2880 return (VRegAndVal->Value.uge(DstTy.getSizeInBits()));
2881}
2882
2884 assert((MI.getOpcode() == TargetOpcode::G_FSHL ||
2885 MI.getOpcode() == TargetOpcode::G_FSHR) &&
2886 "This is not a funnel shift operation");
2887
2888 Register ConstReg = MI.getOperand(3).getReg();
2889 LLT ConstTy = MRI.getType(ConstReg);
2890 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
2891
2892 auto VRegAndVal = getIConstantVRegValWithLookThrough(ConstReg, MRI);
2893 assert((VRegAndVal) && "Value is not a constant");
2894
2895 // Calculate the new Shift Amount = Old Shift Amount % BitWidth
2896 APInt NewConst = VRegAndVal->Value.urem(
2897 APInt(ConstTy.getSizeInBits(), DstTy.getScalarSizeInBits()));
2898
2899 auto NewConstInstr = Builder.buildConstant(ConstTy, NewConst.getZExtValue());
2900 Builder.buildInstr(
2901 MI.getOpcode(), {MI.getOperand(0)},
2902 {MI.getOperand(1), MI.getOperand(2), NewConstInstr.getReg(0)});
2903
2904 MI.eraseFromParent();
2905}
2906
2908 assert(MI.getOpcode() == TargetOpcode::G_SELECT);
2909 // Match (cond ? x : x)
2910 return matchEqualDefs(MI.getOperand(2), MI.getOperand(3)) &&
2911 canReplaceReg(MI.getOperand(0).getReg(), MI.getOperand(2).getReg(),
2912 MRI);
2913}
2914
2916 const MachineOperand &MO, bool OrNegative, bool OrZero) const {
2917 return isKnownToBeAPowerOfTwo(MO.getReg(), MRI, VT, OrNegative, OrZero);
2918}
2919
2921 double C) const {
2922 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2923 Builder.buildFConstant(MI.getOperand(0), C);
2924 MI.eraseFromParent();
2925}
2926
2928 int64_t C) const {
2929 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2930 Builder.buildConstant(MI.getOperand(0), C);
2931 MI.eraseFromParent();
2932}
2933
2935 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2936 Builder.buildConstant(MI.getOperand(0), C);
2937 MI.eraseFromParent();
2938}
2939
2941 ConstantFP *CFP) const {
2942 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2943 Builder.buildFConstant(MI.getOperand(0), CFP->getValueAPF());
2944 MI.eraseFromParent();
2945}
2946
2948 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2949 Builder.buildUndef(MI.getOperand(0));
2950 MI.eraseFromParent();
2951}
2952
2954 MachineInstr &MI, SmallVectorImpl<Register> &MatchInfo) const {
2955 assert(MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT &&
2956 "Invalid opcode");
2957 Register DstReg = MI.getOperand(0).getReg();
2958 LLT DstTy = MRI.getType(DstReg);
2959 assert(DstTy.isVector() && "Invalid G_INSERT_VECTOR_ELT?");
2960
2961 if (DstTy.isScalableVector())
2962 return false;
2963
2964 unsigned NumElts = DstTy.getNumElements();
2965 // If this MI is part of a sequence of insert_vec_elts, then
2966 // don't do the combine in the middle of the sequence.
2967 if (MRI.hasOneUse(DstReg) && MRI.use_instr_begin(DstReg)->getOpcode() ==
2968 TargetOpcode::G_INSERT_VECTOR_ELT)
2969 return false;
2970 MachineInstr *CurrInst = &MI;
2971 MachineInstr *TmpInst;
2972 int64_t IntImm;
2973 Register TmpReg;
2974 MatchInfo.resize(NumElts);
2975 while (mi_match(
2976 *CurrInst, MRI,
2977 m_GInsertVecElt(m_MInstr(TmpInst), m_Reg(TmpReg), m_ICst(IntImm)))) {
2978 if (IntImm >= NumElts || IntImm < 0)
2979 return false;
2980 if (!MatchInfo[IntImm])
2981 MatchInfo[IntImm] = TmpReg;
2982 CurrInst = TmpInst;
2983 }
2984 // Variable index.
2985 if (CurrInst->getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
2986 return false;
2987 if (TmpInst->getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
2988 for (unsigned I = 1; I < TmpInst->getNumOperands(); ++I) {
2989 if (!MatchInfo[I - 1].isValid())
2990 MatchInfo[I - 1] = TmpInst->getOperand(I).getReg();
2991 }
2992 return true;
2993 }
2994 // If we didn't end in a G_IMPLICIT_DEF and the source is not fully
2995 // overwritten, bail out.
2996 return TmpInst->getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
2997 all_of(MatchInfo, [](Register Reg) { return !!Reg; });
2998}
2999
3001 MachineInstr &MI, SmallVectorImpl<Register> &MatchInfo) const {
3002 Register UndefReg;
3003 auto GetUndef = [&]() {
3004 if (UndefReg)
3005 return UndefReg;
3006 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
3007 UndefReg = Builder.buildUndef(DstTy.getScalarType()).getReg(0);
3008 return UndefReg;
3009 };
3010 for (Register &Reg : MatchInfo) {
3011 if (!Reg)
3012 Reg = GetUndef();
3013 }
3014 Builder.buildBuildVector(MI.getOperand(0).getReg(), MatchInfo);
3015 MI.eraseFromParent();
3016}
3017
3018bool CombinerHelper::matchBinopWithNegInner(Register MInner, Register Other,
3019 unsigned RootOpc, Register Dst,
3020 LLT Ty,
3021 BuildFnTy &MatchInfo) const {
3022 /// Helper function for matchBinopWithNeg: tries to match one commuted form
3023 /// of `a bitwiseop (~b +/- c)` -> `a bitwiseop ~(b -/+ c)`.
3024 MachineInstr *InnerDef;
3025 if (!mi_match(MInner, MRI, m_MInstr(InnerDef)))
3026 return false;
3027
3028 unsigned InnerOpc = InnerDef->getOpcode();
3029 if (InnerOpc != TargetOpcode::G_ADD && InnerOpc != TargetOpcode::G_SUB)
3030 return false;
3031
3032 if (!MRI.hasOneNonDBGUse(MInner))
3033 return false;
3034
3035 Register InnerLHS = InnerDef->getOperand(1).getReg();
3036 Register InnerRHS = InnerDef->getOperand(2).getReg();
3037 Register NotSrc;
3038 Register B, C;
3039
3040 // Check if either operand is ~b
3041 auto TryMatch = [&](Register MaybeNot, Register Other) {
3042 if (mi_match(MaybeNot, MRI, m_Not(m_Reg(NotSrc)))) {
3043 if (!MRI.hasOneNonDBGUse(MaybeNot))
3044 return false;
3045 B = NotSrc;
3046 C = Other;
3047 return true;
3048 }
3049 return false;
3050 };
3051
3052 // For SUB, the not must be the LHS. For ADD, it can be either operand.
3053 if (!TryMatch(InnerLHS, InnerRHS) &&
3054 !(InnerOpc == TargetOpcode::G_ADD && TryMatch(InnerRHS, InnerLHS)))
3055 return false;
3056
3057 // Flip add/sub
3058 unsigned FlippedOpc = (InnerOpc == TargetOpcode::G_ADD) ? TargetOpcode::G_SUB
3059 : TargetOpcode::G_ADD;
3060
3061 Register A = Other;
3062 MatchInfo = [=](MachineIRBuilder &Builder) {
3063 auto NewInner = Builder.buildInstr(FlippedOpc, {Ty}, {B, C});
3064 auto NewNot = Builder.buildNot(Ty, NewInner);
3065 Builder.buildInstr(RootOpc, {Dst}, {A, NewNot});
3066 };
3067 return true;
3068}
3069
3071 BuildFnTy &MatchInfo) const {
3072 // Fold `a bitwiseop (~b +/- c)` -> `a bitwiseop ~(b -/+ c)`
3073 // Root MI is one of G_AND, G_OR, G_XOR.
3074 // We also look for commuted forms of operations. Pattern shouldn't apply
3075 // if there are multiple reasons of inner operations.
3076
3077 unsigned RootOpc = MI.getOpcode();
3078 Register Dst = MI.getOperand(0).getReg();
3079 LLT Ty = MRI.getType(Dst);
3080
3081 Register LHS = MI.getOperand(1).getReg();
3082 Register RHS = MI.getOperand(2).getReg();
3083 // Check the commuted and uncommuted forms of the operation.
3084 return matchBinopWithNegInner(LHS, RHS, RootOpc, Dst, Ty, MatchInfo) ||
3085 matchBinopWithNegInner(RHS, LHS, RootOpc, Dst, Ty, MatchInfo);
3086}
3087
3089 MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const {
3090 // Matches: logic (hand x, ...), (hand y, ...) -> hand (logic x, y), ...
3091 //
3092 // Creates the new hand + logic instruction (but does not insert them.)
3093 //
3094 // On success, MatchInfo is populated with the new instructions. These are
3095 // inserted in applyHoistLogicOpWithSameOpcodeHands.
3096 unsigned LogicOpcode = MI.getOpcode();
3097 assert(LogicOpcode == TargetOpcode::G_AND ||
3098 LogicOpcode == TargetOpcode::G_OR ||
3099 LogicOpcode == TargetOpcode::G_XOR);
3100 MachineIRBuilder MIB(MI);
3101 Register Dst = MI.getOperand(0).getReg();
3102 Register LHSReg = MI.getOperand(1).getReg();
3103 Register RHSReg = MI.getOperand(2).getReg();
3104
3105 // Don't recompute anything.
3106 if (!MRI.hasOneNonDBGUse(LHSReg) || !MRI.hasOneNonDBGUse(RHSReg))
3107 return false;
3108
3109 // Make sure we have (hand x, ...), (hand y, ...)
3110 MachineInstr *LeftHandInst = getDefIgnoringCopies(LHSReg, MRI);
3111 MachineInstr *RightHandInst = getDefIgnoringCopies(RHSReg, MRI);
3112 if (!LeftHandInst || !RightHandInst)
3113 return false;
3114 unsigned HandOpcode = LeftHandInst->getOpcode();
3115 if (HandOpcode != RightHandInst->getOpcode())
3116 return false;
3117 if (LeftHandInst->getNumOperands() < 2 ||
3118 !LeftHandInst->getOperand(1).isReg() ||
3119 RightHandInst->getNumOperands() < 2 ||
3120 !RightHandInst->getOperand(1).isReg())
3121 return false;
3122
3123 // Make sure the types match up, and if we're doing this post-legalization,
3124 // we end up with legal types.
3125 Register X = LeftHandInst->getOperand(1).getReg();
3126 Register Y = RightHandInst->getOperand(1).getReg();
3127 LLT XTy = MRI.getType(X);
3128 LLT YTy = MRI.getType(Y);
3129 if (!XTy.isValid() || XTy != YTy)
3130 return false;
3131
3132 // Optional extra source register.
3133 Register ExtraHandOpSrcReg;
3134 switch (HandOpcode) {
3135 default:
3136 return false;
3137 case TargetOpcode::G_ANYEXT:
3138 case TargetOpcode::G_SEXT:
3139 case TargetOpcode::G_ZEXT: {
3140 // Match: logic (ext X), (ext Y) --> ext (logic X, Y)
3141 break;
3142 }
3143 case TargetOpcode::G_TRUNC: {
3144 // Match: logic (trunc X), (trunc Y) -> trunc (logic X, Y)
3145 const MachineFunction *MF = MI.getMF();
3146 LLVMContext &Ctx = MF->getFunction().getContext();
3147
3148 LLT DstTy = MRI.getType(Dst);
3150
3151 // Be extra careful sinking truncate. If it's free, there's no benefit in
3152 // widening a binop.
3153 if (TLI.isZExtFree(DstTy, XTy, Ctx) && TLI.isTruncateFree(XTy, DstTy, Ctx))
3154 return false;
3155 break;
3156 }
3157 case TargetOpcode::G_AND:
3158 case TargetOpcode::G_ASHR:
3159 case TargetOpcode::G_LSHR:
3160 case TargetOpcode::G_SHL: {
3161 // Match: logic (binop x, z), (binop y, z) -> binop (logic x, y), z
3162 MachineOperand &ZOp = LeftHandInst->getOperand(2);
3163 if (!matchEqualDefs(ZOp, RightHandInst->getOperand(2)))
3164 return false;
3165 ExtraHandOpSrcReg = ZOp.getReg();
3166 break;
3167 }
3168 }
3169
3170 if (!isLegalOrBeforeLegalizer({LogicOpcode, {XTy, YTy}}))
3171 return false;
3172
3173 // Record the steps to build the new instructions.
3174 //
3175 // Steps to build (logic x, y)
3176 auto NewLogicDst = MRI.createGenericVirtualRegister(XTy);
3177 OperandBuildSteps LogicBuildSteps = {
3178 [=](MachineInstrBuilder &MIB) { MIB.addDef(NewLogicDst); },
3179 [=](MachineInstrBuilder &MIB) { MIB.addReg(X); },
3180 [=](MachineInstrBuilder &MIB) { MIB.addReg(Y); }};
3181 InstructionBuildSteps LogicSteps(LogicOpcode, LogicBuildSteps);
3182
3183 // Steps to build hand (logic x, y), ...z
3184 OperandBuildSteps HandBuildSteps = {
3185 [=](MachineInstrBuilder &MIB) { MIB.addDef(Dst); },
3186 [=](MachineInstrBuilder &MIB) { MIB.addReg(NewLogicDst); }};
3187 if (ExtraHandOpSrcReg.isValid())
3188 HandBuildSteps.push_back(
3189 [=](MachineInstrBuilder &MIB) { MIB.addReg(ExtraHandOpSrcReg); });
3190 InstructionBuildSteps HandSteps(HandOpcode, HandBuildSteps);
3191
3192 MatchInfo = InstructionStepsMatchInfo({LogicSteps, HandSteps});
3193 return true;
3194}
3195
3197 MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const {
3198 assert(MatchInfo.InstrsToBuild.size() &&
3199 "Expected at least one instr to build?");
3200 for (auto &InstrToBuild : MatchInfo.InstrsToBuild) {
3201 assert(InstrToBuild.Opcode && "Expected a valid opcode?");
3202 assert(InstrToBuild.OperandFns.size() && "Expected at least one operand?");
3203 MachineInstrBuilder Instr = Builder.buildInstr(InstrToBuild.Opcode);
3204 for (auto &OperandFn : InstrToBuild.OperandFns)
3205 OperandFn(Instr);
3206 }
3207 MI.eraseFromParent();
3208}
3209
3211 MachineInstr &MI, std::tuple<Register, int64_t> &MatchInfo) const {
3212 assert(MI.getOpcode() == TargetOpcode::G_ASHR);
3213 int64_t ShlCst, AshrCst;
3214 Register Src;
3215 if (!mi_match(MI.getOperand(0).getReg(), MRI,
3216 m_GAShr(m_GShl(m_Reg(Src), m_ICstOrSplat(ShlCst)),
3217 m_ICstOrSplat(AshrCst))))
3218 return false;
3219 if (ShlCst != AshrCst)
3220 return false;
3222 {TargetOpcode::G_SEXT_INREG,
3223 {MRI.getType(Src)},
3224 {},
3225 {MRI.getType(Src).getScalarSizeInBits() - ShlCst}}))
3226 return false;
3227 MatchInfo = std::make_tuple(Src, ShlCst);
3228 return true;
3229}
3230
3232 MachineInstr &MI, std::tuple<Register, int64_t> &MatchInfo) const {
3233 assert(MI.getOpcode() == TargetOpcode::G_ASHR);
3234 Register Src;
3235 int64_t ShiftAmt;
3236 std::tie(Src, ShiftAmt) = MatchInfo;
3237 unsigned Size = MRI.getType(Src).getScalarSizeInBits();
3238 Builder.buildSExtInReg(MI.getOperand(0).getReg(), Src, Size - ShiftAmt);
3239 MI.eraseFromParent();
3240}
3241
3242/// and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0
3245 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
3246 assert(MI.getOpcode() == TargetOpcode::G_AND);
3247
3248 Register Dst = MI.getOperand(0).getReg();
3249 LLT Ty = MRI.getType(Dst);
3250
3251 Register R;
3252 int64_t C1;
3253 int64_t C2;
3254 if (!mi_match(
3255 Dst, MRI,
3256 m_GAnd(m_GAnd(m_Reg(R), m_ICst(C1)), m_ICst(C2))))
3257 return false;
3258
3259 MatchInfo = [=](MachineIRBuilder &B) {
3260 if (C1 & C2) {
3261 B.buildAnd(Dst, R, B.buildConstant(Ty, C1 & C2));
3262 return;
3263 }
3264 auto Zero = B.buildConstant(Ty, 0);
3265 replaceRegWith(MRI, Dst, Zero->getOperand(0).getReg());
3266 };
3267 return true;
3268}
3269
3271 Register &Replacement) const {
3272 // Given
3273 //
3274 // %y:_(sN) = G_SOMETHING
3275 // %x:_(sN) = G_SOMETHING
3276 // %res:_(sN) = G_AND %x, %y
3277 //
3278 // Eliminate the G_AND when it is known that x & y == x or x & y == y.
3279 //
3280 // Patterns like this can appear as a result of legalization. E.g.
3281 //
3282 // %cmp:_(s32) = G_ICMP intpred(pred), %x(s32), %y
3283 // %one:_(s32) = G_CONSTANT i32 1
3284 // %and:_(s32) = G_AND %cmp, %one
3285 //
3286 // In this case, G_ICMP only produces a single bit, so x & 1 == x.
3287 assert(MI.getOpcode() == TargetOpcode::G_AND);
3288 if (!VT)
3289 return false;
3290
3291 Register AndDst = MI.getOperand(0).getReg();
3292 Register LHS = MI.getOperand(1).getReg();
3293 Register RHS = MI.getOperand(2).getReg();
3294
3295 // Check the RHS (maybe a constant) first, and if we have no KnownBits there,
3296 // we can't do anything. If we do, then it depends on whether we have
3297 // KnownBits on the LHS.
3298 KnownBits RHSBits = VT->getKnownBits(RHS);
3299 if (RHSBits.isUnknown())
3300 return false;
3301
3302 KnownBits LHSBits = VT->getKnownBits(LHS);
3303
3304 // Check that x & Mask == x.
3305 // x & 1 == x, always
3306 // x & 0 == x, only if x is also 0
3307 // Meaning Mask has no effect if every bit is either one in Mask or zero in x.
3308 //
3309 // Check if we can replace AndDst with the LHS of the G_AND
3310 if (canReplaceReg(AndDst, LHS, MRI) &&
3311 (LHSBits.Zero | RHSBits.One).isAllOnes()) {
3312 Replacement = LHS;
3313 return true;
3314 }
3315
3316 // Check if we can replace AndDst with the RHS of the G_AND
3317 if (canReplaceReg(AndDst, RHS, MRI) &&
3318 (LHSBits.One | RHSBits.Zero).isAllOnes()) {
3319 Replacement = RHS;
3320 return true;
3321 }
3322
3323 return false;
3324}
3325
3327 Register &Replacement) const {
3328 // Given
3329 //
3330 // %y:_(sN) = G_SOMETHING
3331 // %x:_(sN) = G_SOMETHING
3332 // %res:_(sN) = G_OR %x, %y
3333 //
3334 // Eliminate the G_OR when it is known that x | y == x or x | y == y.
3335 assert(MI.getOpcode() == TargetOpcode::G_OR);
3336 if (!VT)
3337 return false;
3338
3339 Register OrDst = MI.getOperand(0).getReg();
3340 Register LHS = MI.getOperand(1).getReg();
3341 Register RHS = MI.getOperand(2).getReg();
3342
3343 KnownBits LHSBits = VT->getKnownBits(LHS);
3344 KnownBits RHSBits = VT->getKnownBits(RHS);
3345
3346 // Check that x | Mask == x.
3347 // x | 0 == x, always
3348 // x | 1 == x, only if x is also 1
3349 // Meaning Mask has no effect if every bit is either zero in Mask or one in x.
3350 //
3351 // Check if we can replace OrDst with the LHS of the G_OR
3352 if (canReplaceReg(OrDst, LHS, MRI) &&
3353 (LHSBits.One | RHSBits.Zero).isAllOnes()) {
3354 Replacement = LHS;
3355 return true;
3356 }
3357
3358 // Check if we can replace OrDst with the RHS of the G_OR
3359 if (canReplaceReg(OrDst, RHS, MRI) &&
3360 (LHSBits.Zero | RHSBits.One).isAllOnes()) {
3361 Replacement = RHS;
3362 return true;
3363 }
3364
3365 return false;
3366}
3367
3369 // If the input is already sign extended, just drop the extension.
3370 Register Src = MI.getOperand(1).getReg();
3371 unsigned ExtBits = MI.getOperand(2).getImm();
3372 unsigned TypeSize = MRI.getType(Src).getScalarSizeInBits();
3373 return VT->computeNumSignBits(Src) >= (TypeSize - ExtBits + 1);
3374}
3375
3376static bool isConstValidTrue(const TargetLowering &TLI, unsigned ScalarSizeBits,
3377 int64_t Cst, bool IsVector, bool IsFP) {
3378 // For i1, Cst will always be -1 regardless of boolean contents.
3379 return (ScalarSizeBits == 1 && Cst == -1) ||
3380 isConstTrueVal(TLI, Cst, IsVector, IsFP);
3381}
3382
3383// This pattern aims to match the following shape to avoid extra mov
3384// instructions
3385// G_BUILD_VECTOR(
3386// G_UNMERGE_VALUES(src, 0)
3387// G_UNMERGE_VALUES(src, 1)
3388// G_IMPLICIT_DEF
3389// G_IMPLICIT_DEF
3390// )
3391// ->
3392// G_CONCAT_VECTORS(
3393// src,
3394// undef
3395// )
3398 Register &UnmergeSrc) const {
3399 auto &BV = cast<GBuildVector>(MI);
3400
3401 unsigned BuildUseCount = BV.getNumSources();
3402 if (BuildUseCount % 2 != 0)
3403 return false;
3404
3405 unsigned NumUnmerge = BuildUseCount / 2;
3406
3407 auto *Unmerge = getOpcodeDef<GUnmerge>(BV.getSourceReg(0), MRI);
3408
3409 // Check the first operand is an unmerge and has the correct number of
3410 // operands
3411 if (!Unmerge || Unmerge->getNumDefs() != NumUnmerge)
3412 return false;
3413
3414 UnmergeSrc = Unmerge->getSourceReg();
3415
3416 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
3417 LLT UnmergeSrcTy = MRI.getType(UnmergeSrc);
3418
3419 if (!UnmergeSrcTy.isVector())
3420 return false;
3421
3422 // Ensure we only generate legal instructions post-legalizer
3423 if (!IsPreLegalize &&
3424 !isLegal({TargetOpcode::G_CONCAT_VECTORS, {DstTy, UnmergeSrcTy}}))
3425 return false;
3426
3427 // Check that all of the operands before the midpoint come from the same
3428 // unmerge and are in the same order as they are used in the build_vector
3429 for (unsigned I = 0; I < NumUnmerge; ++I) {
3430 auto MaybeUnmergeReg = BV.getSourceReg(I);
3431 auto *LoopUnmerge = getOpcodeDef<GUnmerge>(MaybeUnmergeReg, MRI);
3432
3433 if (!LoopUnmerge || LoopUnmerge != Unmerge)
3434 return false;
3435
3436 if (LoopUnmerge->getOperand(I).getReg() != MaybeUnmergeReg)
3437 return false;
3438 }
3439
3440 // Check that all of the unmerged values are used
3441 if (Unmerge->getNumDefs() != NumUnmerge)
3442 return false;
3443
3444 // Check that all of the operands after the mid point are undefs.
3445 for (unsigned I = NumUnmerge; I < BuildUseCount; ++I) {
3446 auto *Undef = getDefIgnoringCopies(BV.getSourceReg(I), MRI);
3447
3448 if (Undef->getOpcode() != TargetOpcode::G_IMPLICIT_DEF)
3449 return false;
3450 }
3451
3452 return true;
3453}
3454
3458 Register &UnmergeSrc) const {
3459 assert(UnmergeSrc && "Expected there to be one matching G_UNMERGE_VALUES");
3460 B.setInstrAndDebugLoc(MI);
3461
3462 Register UndefVec = B.buildUndef(MRI.getType(UnmergeSrc)).getReg(0);
3463 B.buildConcatVectors(MI.getOperand(0), {UnmergeSrc, UndefVec});
3464
3465 MI.eraseFromParent();
3466}
3467
3468// This combine tries to reduce the number of scalarised G_TRUNC instructions by
3469// using vector truncates instead
3470//
3471// EXAMPLE:
3472// %a(i32), %b(i32) = G_UNMERGE_VALUES %src(<2 x i32>)
3473// %T_a(i16) = G_TRUNC %a(i32)
3474// %T_b(i16) = G_TRUNC %b(i32)
3475// %Undef(i16) = G_IMPLICIT_DEF(i16)
3476// %dst(v4i16) = G_BUILD_VECTORS %T_a(i16), %T_b(i16), %Undef(i16), %Undef(i16)
3477//
3478// ===>
3479// %Undef(<2 x i32>) = G_IMPLICIT_DEF(<2 x i32>)
3480// %Mid(<4 x s32>) = G_CONCAT_VECTORS %src(<2 x i32>), %Undef(<2 x i32>)
3481// %dst(<4 x s16>) = G_TRUNC %Mid(<4 x s32>)
3482//
3483// Only matches sources made up of G_TRUNCs followed by G_IMPLICIT_DEFs
3485 Register &MatchInfo) const {
3486 auto BuildMI = cast<GBuildVector>(&MI);
3487 unsigned NumOperands = BuildMI->getNumSources();
3488 LLT DstTy = MRI.getType(BuildMI->getReg(0));
3489
3490 // Check the G_BUILD_VECTOR sources
3491 unsigned I;
3492 GUnmerge *UnmergeMI = nullptr;
3493
3494 // Check all source TRUNCs come from the same UNMERGE instruction
3495 // and that the element order matches (BUILD_VECTOR position I
3496 // corresponds to UNMERGE result I)
3497 for (I = 0; I < NumOperands; ++I) {
3498 // Check if the G_TRUNC instructions all come from the same MI
3499 Register TruncSrcReg;
3500 if (!mi_match(BuildMI->getSourceReg(I), MRI, m_GTrunc(m_Reg(TruncSrcReg))))
3501 break;
3502
3503 if (!UnmergeMI) {
3504 if (!mi_match(TruncSrcReg, MRI, m_GUnmerge(UnmergeMI)))
3505 return false;
3506 } else {
3507 MachineInstr *UnmergeSrcMI;
3508 if (!mi_match(TruncSrcReg, MRI, m_MInstr(UnmergeSrcMI)) ||
3509 UnmergeMI != UnmergeSrcMI)
3510 return false;
3511 }
3512 // Element order must match: position I must use UNMERGE result I.
3513 if (UnmergeMI->getOperand(I).getReg() != TruncSrcReg)
3514 return false;
3515 }
3516 if (I < 2)
3517 return false;
3518
3519 // Check the remaining source elements are only G_IMPLICIT_DEF
3520 for (; I < NumOperands; ++I) {
3521 if (!mi_match(BuildMI->getSourceReg(I), MRI, m_GImplicitDef()))
3522 return false;
3523 }
3524
3525 // Check the size of unmerge source
3526 MatchInfo = UnmergeMI->getSourceReg();
3527 LLT UnmergeSrcTy = MRI.getType(MatchInfo);
3528 if (!UnmergeSrcTy.isVector())
3529 return false;
3530
3531 if (!DstTy.getElementCount().isKnownMultipleOf(UnmergeSrcTy.getNumElements()))
3532 return false;
3533
3534 // Check the unmerge source and destination element types match
3535 LLT UnmergeSrcEltTy = UnmergeSrcTy.getElementType();
3536 Register UnmergeDstReg = UnmergeMI->getOperand(0).getReg();
3537 LLT UnmergeDstEltTy = MRI.getType(UnmergeDstReg);
3538 if (UnmergeSrcEltTy != UnmergeDstEltTy)
3539 return false;
3540
3541 // Only generate legal instructions post-legalizer
3542 if (!IsPreLegalize) {
3543 LLT MidTy = DstTy.changeElementType(UnmergeSrcTy.getScalarType());
3544
3545 if (DstTy.getElementCount() != UnmergeSrcTy.getElementCount() &&
3546 !isLegal({TargetOpcode::G_CONCAT_VECTORS, {MidTy, UnmergeSrcTy}}))
3547 return false;
3548
3549 if (!isLegal({TargetOpcode::G_TRUNC, {DstTy, MidTy}}))
3550 return false;
3551 }
3552
3553 return true;
3554}
3555
3557 Register &MatchInfo) const {
3558 Register MidReg;
3559 auto BuildMI = cast<GBuildVector>(&MI);
3560 Register DstReg = BuildMI->getReg(0);
3561 LLT DstTy = MRI.getType(DstReg);
3562 LLT UnmergeSrcTy = MRI.getType(MatchInfo);
3563 unsigned DstTyNumElt = DstTy.getNumElements();
3564 unsigned UnmergeSrcTyNumElt = UnmergeSrcTy.getNumElements();
3565
3566 // No need to pad vector if only G_TRUNC is needed
3567 if (DstTyNumElt / UnmergeSrcTyNumElt == 1) {
3568 MidReg = MatchInfo;
3569 } else {
3570 Register UndefReg = Builder.buildUndef(UnmergeSrcTy).getReg(0);
3571 SmallVector<Register> ConcatRegs = {MatchInfo};
3572 for (unsigned I = 1; I < DstTyNumElt / UnmergeSrcTyNumElt; ++I)
3573 ConcatRegs.push_back(UndefReg);
3574
3575 auto MidTy = DstTy.changeElementType(UnmergeSrcTy.getScalarType());
3576 MidReg = Builder.buildConcatVectors(MidTy, ConcatRegs).getReg(0);
3577 }
3578
3579 Builder.buildTrunc(DstReg, MidReg);
3580 MI.eraseFromParent();
3581}
3582
3584 MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate) const {
3585 assert(MI.getOpcode() == TargetOpcode::G_XOR);
3586 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3587 const auto &TLI = *Builder.getMF().getSubtarget().getTargetLowering();
3588 Register XorSrc;
3589 Register CstReg;
3590 // We match xor(src, true) here.
3591 if (!mi_match(MI.getOperand(0).getReg(), MRI,
3592 m_GXor(m_Reg(XorSrc), m_Reg(CstReg))))
3593 return false;
3594
3595 if (!MRI.hasOneNonDBGUse(XorSrc))
3596 return false;
3597
3598 // Check that XorSrc is the root of a tree of comparisons combined with ANDs
3599 // and ORs. The suffix of RegsToNegate starting from index I is used a work
3600 // list of tree nodes to visit.
3601 RegsToNegate.push_back(XorSrc);
3602 // Remember whether the comparisons are all integer or all floating point.
3603 bool IsInt = false;
3604 bool IsFP = false;
3605 for (unsigned I = 0; I < RegsToNegate.size(); ++I) {
3606 Register Reg = RegsToNegate[I];
3607 if (!MRI.hasOneNonDBGUse(Reg))
3608 return false;
3609 MachineInstr *Def;
3610 if (!mi_match(Reg, MRI, m_MInstr(Def)))
3611 return false;
3612 switch (Def->getOpcode()) {
3613 default:
3614 // Don't match if the tree contains anything other than ANDs, ORs and
3615 // comparisons.
3616 return false;
3617 case TargetOpcode::G_ICMP:
3618 if (IsFP)
3619 return false;
3620 IsInt = true;
3621 // When we apply the combine we will invert the predicate.
3622 break;
3623 case TargetOpcode::G_FCMP:
3624 if (IsInt)
3625 return false;
3626 IsFP = true;
3627 // When we apply the combine we will invert the predicate.
3628 break;
3629 case TargetOpcode::G_AND:
3630 case TargetOpcode::G_OR:
3631 // Implement De Morgan's laws:
3632 // ~(x & y) -> ~x | ~y
3633 // ~(x | y) -> ~x & ~y
3634 // When we apply the combine we will change the opcode and recursively
3635 // negate the operands.
3636 RegsToNegate.push_back(Def->getOperand(1).getReg());
3637 RegsToNegate.push_back(Def->getOperand(2).getReg());
3638 break;
3639 }
3640 }
3641
3642 // Now we know whether the comparisons are integer or floating point, check
3643 // the constant in the xor.
3644 int64_t Cst;
3645 if (Ty.isVector()) {
3646 int64_t SplatCst;
3647 if (!mi_match(CstReg, MRI, m_ICstOrSplat(SplatCst)))
3648 return false;
3649 if (!isConstValidTrue(TLI, Ty.getScalarSizeInBits(), SplatCst, true, IsFP))
3650 return false;
3651 } else {
3652 if (!mi_match(CstReg, MRI, m_ICst(Cst)))
3653 return false;
3654 if (!isConstValidTrue(TLI, Ty.getSizeInBits(), Cst, false, IsFP))
3655 return false;
3656 }
3657
3658 return true;
3659}
3660
3662 MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate) const {
3663 for (Register Reg : RegsToNegate) {
3664 MachineInstr *Def = MRI.getVRegDef(Reg);
3665 Observer.changingInstr(*Def);
3666 // For each comparison, invert the opcode. For each AND and OR, change the
3667 // opcode.
3668 switch (Def->getOpcode()) {
3669 default:
3670 llvm_unreachable("Unexpected opcode");
3671 case TargetOpcode::G_ICMP:
3672 case TargetOpcode::G_FCMP: {
3673 MachineOperand &PredOp = Def->getOperand(1);
3676 PredOp.setPredicate(NewP);
3677 break;
3678 }
3679 case TargetOpcode::G_AND:
3680 Def->setDesc(Builder.getTII().get(TargetOpcode::G_OR));
3681 break;
3682 case TargetOpcode::G_OR:
3683 Def->setDesc(Builder.getTII().get(TargetOpcode::G_AND));
3684 break;
3685 }
3686 Observer.changedInstr(*Def);
3687 }
3688
3689 replaceRegWith(MRI, MI.getOperand(0).getReg(), MI.getOperand(1).getReg());
3690 MI.eraseFromParent();
3691}
3692
3694 MachineInstr &MI, std::pair<Register, Register> &MatchInfo) const {
3695 // Match (xor (and x, y), y) (or any of its commuted cases)
3696 assert(MI.getOpcode() == TargetOpcode::G_XOR);
3697 Register &X = MatchInfo.first;
3698 Register &Y = MatchInfo.second;
3699 Register AndReg = MI.getOperand(1).getReg();
3700 Register SharedReg = MI.getOperand(2).getReg();
3701
3702 // Find a G_AND on either side of the G_XOR.
3703 // Look for one of
3704 //
3705 // (xor (and x, y), SharedReg)
3706 // (xor SharedReg, (and x, y))
3707 if (!mi_match(AndReg, MRI, m_GAnd(m_Reg(X), m_Reg(Y)))) {
3708 std::swap(AndReg, SharedReg);
3709 if (!mi_match(AndReg, MRI, m_GAnd(m_Reg(X), m_Reg(Y))))
3710 return false;
3711 }
3712
3713 // Only do this if we'll eliminate the G_AND.
3714 if (!MRI.hasOneNonDBGUse(AndReg))
3715 return false;
3716
3717 // We can combine if SharedReg is the same as either the LHS or RHS of the
3718 // G_AND.
3719 if (Y != SharedReg)
3720 std::swap(X, Y);
3721 return Y == SharedReg;
3722}
3723
3725 MachineInstr &MI, std::pair<Register, Register> &MatchInfo) const {
3726 // Fold (xor (and x, y), y) -> (and (not x), y)
3727 Register X, Y;
3728 std::tie(X, Y) = MatchInfo;
3729 auto Not = Builder.buildNot(MRI.getType(X), X);
3730 Observer.changingInstr(MI);
3731 MI.setDesc(Builder.getTII().get(TargetOpcode::G_AND));
3732 MI.getOperand(1).setReg(Not->getOperand(0).getReg());
3733 MI.getOperand(2).setReg(Y);
3734 Observer.changedInstr(MI);
3735}
3736
3738 auto &PtrAdd = cast<GPtrAdd>(MI);
3739 Register DstReg = PtrAdd.getReg(0);
3740 LLT Ty = MRI.getType(DstReg);
3741 const DataLayout &DL = Builder.getMF().getDataLayout();
3742
3743 if (DL.isNonIntegralAddressSpace(Ty.getScalarType().getAddressSpace()))
3744 return false;
3745
3746 if (!Ty.isVector())
3747 return false;
3748 const MachineInstr *VecMI;
3749 if (!mi_match(PtrAdd.getBaseReg(), MRI, m_MInstr(VecMI)))
3750 return false;
3751 return isBuildVectorAllZeros(*VecMI, MRI);
3752}
3753
3754/// The second source operand is known to be a power of 2.
3756 Register DstReg = MI.getOperand(0).getReg();
3757 Register Src0 = MI.getOperand(1).getReg();
3758 Register Pow2Src1 = MI.getOperand(2).getReg();
3759 LLT Ty = MRI.getType(DstReg);
3760
3761 // Fold (urem x, pow2) -> (and x, pow2-1)
3762 auto NegOne = Builder.buildConstant(Ty, -1);
3763 auto Add = Builder.buildAdd(Ty, Pow2Src1, NegOne);
3764 Builder.buildAnd(DstReg, Src0, Add);
3765 MI.eraseFromParent();
3766}
3767
3769 unsigned &SelectOpNo) const {
3770 Register LHS = MI.getOperand(1).getReg();
3771 Register RHS = MI.getOperand(2).getReg();
3772
3773 Register OtherOperandReg = RHS;
3774 SelectOpNo = 1;
3775 Register SelectTrue, SelectFalse;
3776
3777 // Don't do this unless the old select is going away. We want to eliminate the
3778 // binary operator, not replace a binop with a select.
3779 if (!mi_match(LHS, MRI,
3780 m_GISelect(m_Reg(), m_Reg(SelectTrue), m_Reg(SelectFalse))) ||
3781 !MRI.hasOneNonDBGUse(LHS)) {
3782 OtherOperandReg = LHS;
3783 SelectOpNo = 2;
3784 if (!mi_match(RHS, MRI,
3785 m_GISelect(m_Reg(), m_Reg(SelectTrue), m_Reg(SelectFalse))) ||
3786 !MRI.hasOneNonDBGUse(RHS))
3787 return false;
3788 }
3789
3790 MachineInstr *SelectLHS, *SelectRHS;
3791 if (!mi_match(SelectTrue, MRI, m_MInstr(SelectLHS)) ||
3792 !mi_match(SelectFalse, MRI, m_MInstr(SelectRHS)))
3793 return false;
3794
3795 if (!isConstantOrConstantVector(*SelectLHS, MRI,
3796 /*AllowFP*/ true,
3797 /*AllowOpaqueConstants*/ false))
3798 return false;
3799 if (!isConstantOrConstantVector(*SelectRHS, MRI,
3800 /*AllowFP*/ true,
3801 /*AllowOpaqueConstants*/ false))
3802 return false;
3803
3804 unsigned BinOpcode = MI.getOpcode();
3805
3806 // We know that one of the operands is a select of constants. Now verify that
3807 // the other binary operator operand is either a constant, or we can handle a
3808 // variable.
3809 bool CanFoldNonConst =
3810 (BinOpcode == TargetOpcode::G_AND || BinOpcode == TargetOpcode::G_OR) &&
3811 (isNullOrNullSplat(*SelectLHS, MRI) ||
3812 isAllOnesOrAllOnesSplat(*SelectLHS, MRI)) &&
3813 (isNullOrNullSplat(*SelectRHS, MRI) ||
3814 isAllOnesOrAllOnesSplat(*SelectRHS, MRI));
3815 if (CanFoldNonConst)
3816 return true;
3817
3818 MachineInstr *OtherOperandDef;
3819 if (!mi_match(OtherOperandReg, MRI, m_MInstr(OtherOperandDef)))
3820 return false;
3821 return isConstantOrConstantVector(*OtherOperandDef, MRI,
3822 /*AllowFP*/ true,
3823 /*AllowOpaqueConstants*/ false);
3824}
3825
3826/// \p SelectOperand is the operand in binary operator \p MI that is the select
3827/// to fold.
3829 MachineInstr &MI, const unsigned &SelectOperand) const {
3830 Register Dst = MI.getOperand(0).getReg();
3831 Register LHS = MI.getOperand(1).getReg();
3832 Register RHS = MI.getOperand(2).getReg();
3833 GSelect *Select =
3834 cast<GSelect>(MRI.getVRegDef(MI.getOperand(SelectOperand).getReg()));
3835
3836 Register SelectCond = Select->getCondReg();
3837 Register SelectTrue = Select->getTrueReg();
3838 Register SelectFalse = Select->getFalseReg();
3839
3840 LLT Ty = MRI.getType(Dst);
3841 unsigned BinOpcode = MI.getOpcode();
3842
3843 Register FoldTrue, FoldFalse;
3844
3845 // We have a select-of-constants followed by a binary operator with a
3846 // constant. Eliminate the binop by pulling the constant math into the select.
3847 // Example: add (select Cond, CT, CF), CBO --> select Cond, CT + CBO, CF + CBO
3848 if (SelectOperand == 1) {
3849 // TODO: SelectionDAG verifies this actually constant folds before
3850 // committing to the combine.
3851
3852 FoldTrue = Builder.buildInstr(BinOpcode, {Ty}, {SelectTrue, RHS}).getReg(0);
3853 FoldFalse =
3854 Builder.buildInstr(BinOpcode, {Ty}, {SelectFalse, RHS}).getReg(0);
3855 } else {
3856 FoldTrue = Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectTrue}).getReg(0);
3857 FoldFalse =
3858 Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectFalse}).getReg(0);
3859 }
3860
3861 Builder.buildSelect(Dst, SelectCond, FoldTrue, FoldFalse, MI.getFlags());
3862 MI.eraseFromParent();
3863}
3864
3865std::optional<SmallVector<Register, 8>>
3866CombinerHelper::findCandidatesForLoadOrCombine(const MachineInstr *Root) const {
3867 assert(Root->getOpcode() == TargetOpcode::G_OR && "Expected G_OR only!");
3868 // We want to detect if Root is part of a tree which represents a bunch
3869 // of loads being merged into a larger load. We'll try to recognize patterns
3870 // like, for example:
3871 //
3872 // Reg Reg
3873 // \ /
3874 // OR_1 Reg
3875 // \ /
3876 // OR_2
3877 // \ Reg
3878 // .. /
3879 // Root
3880 //
3881 // Reg Reg Reg Reg
3882 // \ / \ /
3883 // OR_1 OR_2
3884 // \ /
3885 // \ /
3886 // ...
3887 // Root
3888 //
3889 // Each "Reg" may have been produced by a load + some arithmetic. This
3890 // function will save each of them.
3891 SmallVector<Register, 8> RegsToVisit;
3893
3894 // In the "worst" case, we're dealing with a load for each byte. So, there
3895 // are at most #bytes - 1 ORs.
3896 const unsigned MaxIter =
3897 MRI.getType(Root->getOperand(0).getReg()).getSizeInBytes() - 1;
3898 for (unsigned Iter = 0; Iter < MaxIter; ++Iter) {
3899 if (Ors.empty())
3900 break;
3901 const MachineInstr *Curr = Ors.pop_back_val();
3902 Register OrLHS = Curr->getOperand(1).getReg();
3903 Register OrRHS = Curr->getOperand(2).getReg();
3904
3905 // In the combine, we want to elimate the entire tree.
3906 if (!MRI.hasOneNonDBGUse(OrLHS) || !MRI.hasOneNonDBGUse(OrRHS))
3907 return std::nullopt;
3908
3909 // If it's a G_OR, save it and continue to walk. If it's not, then it's
3910 // something that may be a load + arithmetic.
3911 if (const MachineInstr *Or = getOpcodeDef(TargetOpcode::G_OR, OrLHS, MRI))
3912 Ors.push_back(Or);
3913 else
3914 RegsToVisit.push_back(OrLHS);
3915 if (const MachineInstr *Or = getOpcodeDef(TargetOpcode::G_OR, OrRHS, MRI))
3916 Ors.push_back(Or);
3917 else
3918 RegsToVisit.push_back(OrRHS);
3919 }
3920
3921 // We're going to try and merge each register into a wider power-of-2 type,
3922 // so we ought to have an even number of registers.
3923 if (RegsToVisit.empty() || RegsToVisit.size() % 2 != 0)
3924 return std::nullopt;
3925 return RegsToVisit;
3926}
3927
3928/// Helper function for findLoadOffsetsForLoadOrCombine.
3929///
3930/// Check if \p Reg is the result of loading a \p MemSizeInBits wide value,
3931/// and then moving that value into a specific byte offset.
3932///
3933/// e.g. x[i] << 24
3934///
3935/// \returns The load instruction and the byte offset it is moved into.
3936static std::optional<std::pair<GZExtLoad *, int64_t>>
3937matchLoadAndBytePosition(Register Reg, unsigned MemSizeInBits,
3938 const MachineRegisterInfo &MRI) {
3939 assert(MRI.hasOneNonDBGUse(Reg) &&
3940 "Expected Reg to only have one non-debug use?");
3941 Register MaybeLoad;
3942 int64_t Shift;
3943 if (!mi_match(Reg, MRI, m_OneUse(m_GShl(m_Reg(MaybeLoad), m_ICst(Shift))))) {
3944 Shift = 0;
3945 MaybeLoad = Reg;
3946 }
3947
3948 if (Shift % MemSizeInBits != 0)
3949 return std::nullopt;
3950
3951 // TODO: Handle other types of loads.
3952 auto *Load = getOpcodeDef<GZExtLoad>(MaybeLoad, MRI);
3953 if (!Load)
3954 return std::nullopt;
3955
3956 if (!Load->isUnordered() || Load->getMemSizeInBits() != MemSizeInBits)
3957 return std::nullopt;
3958
3959 return std::make_pair(Load, Shift / MemSizeInBits);
3960}
3961
3962std::optional<std::tuple<GZExtLoad *, int64_t, GZExtLoad *>>
3963CombinerHelper::findLoadOffsetsForLoadOrCombine(
3965 const SmallVector<Register, 8> &RegsToVisit,
3966 const unsigned MemSizeInBits) const {
3967
3968 // Each load found for the pattern. There should be one for each RegsToVisit.
3969 SmallSetVector<const MachineInstr *, 8> Loads;
3970
3971 // The lowest index used in any load. (The lowest "i" for each x[i].)
3972 int64_t LowestIdx = INT64_MAX;
3973
3974 // The load which uses the lowest index.
3975 GZExtLoad *LowestIdxLoad = nullptr;
3976
3977 // Keeps track of the load indices we see. We shouldn't see any indices twice.
3978 SmallSet<int64_t, 8> SeenIdx;
3979
3980 // Ensure each load is in the same MBB.
3981 // TODO: Support multiple MachineBasicBlocks.
3982 MachineBasicBlock *MBB = nullptr;
3983 const MachineMemOperand *MMO = nullptr;
3984
3985 // Earliest instruction-order load in the pattern.
3986 GZExtLoad *EarliestLoad = nullptr;
3987
3988 // Latest instruction-order load in the pattern.
3989 GZExtLoad *LatestLoad = nullptr;
3990
3991 // Base pointer which every load should share.
3993
3994 // We want to find a load for each register. Each load should have some
3995 // appropriate bit twiddling arithmetic. During this loop, we will also keep
3996 // track of the load which uses the lowest index. Later, we will check if we
3997 // can use its pointer in the final, combined load.
3998 for (auto Reg : RegsToVisit) {
3999 // Find the load, and find the position that it will end up in (e.g. a
4000 // shifted) value.
4001 auto LoadAndPos = matchLoadAndBytePosition(Reg, MemSizeInBits, MRI);
4002 if (!LoadAndPos)
4003 return std::nullopt;
4004 GZExtLoad *Load;
4005 int64_t DstPos;
4006 std::tie(Load, DstPos) = *LoadAndPos;
4007
4008 // TODO: Handle multiple MachineBasicBlocks. Currently not handled because
4009 // it is difficult to check for stores/calls/etc between loads.
4010 MachineBasicBlock *LoadMBB = Load->getParent();
4011 if (!MBB)
4012 MBB = LoadMBB;
4013 if (LoadMBB != MBB)
4014 return std::nullopt;
4015
4016 // Make sure that the MachineMemOperands of every seen load are compatible.
4017 auto &LoadMMO = Load->getMMO();
4018 if (!MMO)
4019 MMO = &LoadMMO;
4020 if (MMO->getAddrSpace() != LoadMMO.getAddrSpace())
4021 return std::nullopt;
4022
4023 // Find out what the base pointer and index for the load is.
4024 Register LoadPtr;
4025 int64_t Idx;
4026 if (!mi_match(Load->getOperand(1).getReg(), MRI,
4027 m_GPtrAdd(m_Reg(LoadPtr), m_ICst(Idx)))) {
4028 LoadPtr = Load->getOperand(1).getReg();
4029 Idx = 0;
4030 }
4031
4032 // Don't combine things like a[i], a[i] -> a bigger load.
4033 if (!SeenIdx.insert(Idx).second)
4034 return std::nullopt;
4035
4036 // Every load must share the same base pointer; don't combine things like:
4037 //
4038 // a[i], b[i + 1] -> a bigger load.
4039 if (!BasePtr.isValid())
4040 BasePtr = LoadPtr;
4041 if (BasePtr != LoadPtr)
4042 return std::nullopt;
4043
4044 if (Idx < LowestIdx) {
4045 LowestIdx = Idx;
4046 LowestIdxLoad = Load;
4047 }
4048
4049 // Keep track of the byte offset that this load ends up at. If we have seen
4050 // the byte offset, then stop here. We do not want to combine:
4051 //
4052 // a[i] << 16, a[i + k] << 16 -> a bigger load.
4053 if (!MemOffset2Idx.try_emplace(DstPos, Idx).second)
4054 return std::nullopt;
4055 Loads.insert(Load);
4056
4057 // Keep track of the position of the earliest/latest loads in the pattern.
4058 // We will check that there are no load fold barriers between them later
4059 // on.
4060 //
4061 // FIXME: Is there a better way to check for load fold barriers?
4062 if (!EarliestLoad || dominates(*Load, *EarliestLoad))
4063 EarliestLoad = Load;
4064 if (!LatestLoad || dominates(*LatestLoad, *Load))
4065 LatestLoad = Load;
4066 }
4067
4068 // We found a load for each register. Let's check if each load satisfies the
4069 // pattern.
4070 assert(Loads.size() == RegsToVisit.size() &&
4071 "Expected to find a load for each register?");
4072 assert(EarliestLoad != LatestLoad && EarliestLoad &&
4073 LatestLoad && "Expected at least two loads?");
4074
4075 // Check if there are any stores, calls, etc. between any of the loads. If
4076 // there are, then we can't safely perform the combine.
4077 //
4078 // MaxIter is chosen based off the (worst case) number of iterations it
4079 // typically takes to succeed in the LLVM test suite plus some padding.
4080 //
4081 // FIXME: Is there a better way to check for load fold barriers?
4082 const unsigned MaxIter = 20;
4083 unsigned Iter = 0;
4084 for (const auto &MI : instructionsWithoutDebug(EarliestLoad->getIterator(),
4085 LatestLoad->getIterator())) {
4086 if (Loads.count(&MI))
4087 continue;
4088 if (MI.isLoadFoldBarrier())
4089 return std::nullopt;
4090 if (Iter++ == MaxIter)
4091 return std::nullopt;
4092 }
4093
4094 return std::make_tuple(LowestIdxLoad, LowestIdx, LatestLoad);
4095}
4096
4099 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4100 assert(MI.getOpcode() == TargetOpcode::G_OR);
4101 MachineFunction &MF = *MI.getMF();
4102 // Assuming a little-endian target, transform:
4103 // s8 *a = ...
4104 // s32 val = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24)
4105 // =>
4106 // s32 val = *((i32)a)
4107 //
4108 // s8 *a = ...
4109 // s32 val = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]
4110 // =>
4111 // s32 val = BSWAP(*((s32)a))
4112 Register Dst = MI.getOperand(0).getReg();
4113 LLT Ty = MRI.getType(Dst);
4114 if (Ty.isVector())
4115 return false;
4116
4117 // We need to combine at least two loads into this type. Since the smallest
4118 // possible load is into a byte, we need at least a 16-bit wide type.
4119 const unsigned WideMemSizeInBits = Ty.getSizeInBits();
4120 if (WideMemSizeInBits < 16 || WideMemSizeInBits % 8 != 0)
4121 return false;
4122
4123 // Match a collection of non-OR instructions in the pattern.
4124 auto RegsToVisit = findCandidatesForLoadOrCombine(&MI);
4125 if (!RegsToVisit)
4126 return false;
4127
4128 // We have a collection of non-OR instructions. Figure out how wide each of
4129 // the small loads should be based off of the number of potential loads we
4130 // found.
4131 const unsigned NarrowMemSizeInBits = WideMemSizeInBits / RegsToVisit->size();
4132 if (NarrowMemSizeInBits % 8 != 0)
4133 return false;
4134
4135 // Check if each register feeding into each OR is a load from the same
4136 // base pointer + some arithmetic.
4137 //
4138 // e.g. a[0], a[1] << 8, a[2] << 16, etc.
4139 //
4140 // Also verify that each of these ends up putting a[i] into the same memory
4141 // offset as a load into a wide type would.
4143 GZExtLoad *LowestIdxLoad, *LatestLoad;
4144 int64_t LowestIdx;
4145 auto MaybeLoadInfo = findLoadOffsetsForLoadOrCombine(
4146 MemOffset2Idx, *RegsToVisit, NarrowMemSizeInBits);
4147 if (!MaybeLoadInfo)
4148 return false;
4149 std::tie(LowestIdxLoad, LowestIdx, LatestLoad) = *MaybeLoadInfo;
4150
4151 // We have a bunch of loads being OR'd together. Using the addresses + offsets
4152 // we found before, check if this corresponds to a big or little endian byte
4153 // pattern. If it does, then we can represent it using a load + possibly a
4154 // BSWAP.
4155 bool IsBigEndianTarget = MF.getDataLayout().isBigEndian();
4156 std::optional<bool> IsBigEndian = isBigEndian(MemOffset2Idx, LowestIdx);
4157 if (!IsBigEndian)
4158 return false;
4159 bool NeedsBSwap = IsBigEndianTarget != *IsBigEndian;
4160 if (NeedsBSwap && !isLegalOrBeforeLegalizer({TargetOpcode::G_BSWAP, {Ty}}))
4161 return false;
4162
4163 // Make sure that the load from the lowest index produces offset 0 in the
4164 // final value.
4165 //
4166 // This ensures that we won't combine something like this:
4167 //
4168 // load x[i] -> byte 2
4169 // load x[i+1] -> byte 0 ---> wide_load x[i]
4170 // load x[i+2] -> byte 1
4171 const unsigned NumLoadsInTy = WideMemSizeInBits / NarrowMemSizeInBits;
4172 const unsigned ZeroByteOffset =
4173 *IsBigEndian
4174 ? bigEndianByteAt(NumLoadsInTy, 0)
4175 : littleEndianByteAt(NumLoadsInTy, 0);
4176 auto ZeroOffsetIdx = MemOffset2Idx.find(ZeroByteOffset);
4177 if (ZeroOffsetIdx == MemOffset2Idx.end() ||
4178 ZeroOffsetIdx->second != LowestIdx)
4179 return false;
4180
4181 // We wil reuse the pointer from the load which ends up at byte offset 0. It
4182 // may not use index 0.
4183 Register Ptr = LowestIdxLoad->getPointerReg();
4184 const MachineMemOperand &MMO = LowestIdxLoad->getMMO();
4185 LegalityQuery::MemDesc MMDesc(MMO);
4186 MMDesc.MemoryTy = Ty;
4188 {TargetOpcode::G_LOAD, {Ty, MRI.getType(Ptr)}, {MMDesc}}))
4189 return false;
4190 auto PtrInfo = MMO.getPointerInfo();
4191 auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, WideMemSizeInBits / 8);
4192
4193 // Load must be allowed and fast on the target.
4195 auto &DL = MF.getDataLayout();
4196 unsigned Fast = 0;
4197 if (!getTargetLowering().allowsMemoryAccess(C, DL, Ty, *NewMMO, &Fast) ||
4198 !Fast)
4199 return false;
4200
4201 MatchInfo = [=](MachineIRBuilder &MIB) {
4202 MIB.setInstrAndDebugLoc(*LatestLoad);
4203 Register LoadDst = NeedsBSwap ? MRI.cloneVirtualRegister(Dst) : Dst;
4204 MIB.buildLoad(LoadDst, Ptr, *NewMMO);
4205 if (NeedsBSwap)
4206 MIB.buildBSwap(Dst, LoadDst);
4207 };
4208 return true;
4209}
4210
4212 MachineInstr *&ExtMI) const {
4213 auto &PHI = cast<GPhi>(MI);
4214 Register DstReg = PHI.getReg(0);
4215
4216 // TODO: Extending a vector may be expensive, don't do this until heuristics
4217 // are better.
4218 if (MRI.getType(DstReg).isVector())
4219 return false;
4220
4221 // Try to match a phi, whose only use is an extend.
4222 if (!MRI.hasOneNonDBGUse(DstReg))
4223 return false;
4224 ExtMI = &*MRI.use_instr_nodbg_begin(DstReg);
4225 switch (ExtMI->getOpcode()) {
4226 case TargetOpcode::G_ANYEXT:
4227 return true; // G_ANYEXT is usually free.
4228 case TargetOpcode::G_ZEXT:
4229 case TargetOpcode::G_SEXT:
4230 break;
4231 default:
4232 return false;
4233 }
4234
4235 // If the target is likely to fold this extend away, don't propagate.
4236 if (Builder.getTII().isExtendLikelyToBeFolded(*ExtMI, MRI))
4237 return false;
4238
4239 // We don't want to propagate the extends unless there's a good chance that
4240 // they'll be optimized in some way.
4241 // Collect the unique incoming values.
4243 for (unsigned I = 0; I < PHI.getNumIncomingValues(); ++I) {
4244 auto *DefMI = getDefIgnoringCopies(PHI.getIncomingValue(I), MRI);
4245 switch (DefMI->getOpcode()) {
4246 case TargetOpcode::G_LOAD:
4247 case TargetOpcode::G_TRUNC:
4248 case TargetOpcode::G_SEXT:
4249 case TargetOpcode::G_ZEXT:
4250 case TargetOpcode::G_ANYEXT:
4251 case TargetOpcode::G_CONSTANT:
4252 InSrcs.insert(DefMI);
4253 // Don't try to propagate if there are too many places to create new
4254 // extends, chances are it'll increase code size.
4255 if (InSrcs.size() > 2)
4256 return false;
4257 break;
4258 default:
4259 return false;
4260 }
4261 }
4262 return true;
4263}
4264
4266 MachineInstr *&ExtMI) const {
4267 auto &PHI = cast<GPhi>(MI);
4268 Register DstReg = ExtMI->getOperand(0).getReg();
4269 LLT ExtTy = MRI.getType(DstReg);
4270
4271 // Propagate the extension into the block of each incoming reg's block.
4272 // Use a SetVector here because PHIs can have duplicate edges, and we want
4273 // deterministic iteration order.
4276 for (unsigned I = 0; I < PHI.getNumIncomingValues(); ++I) {
4277 auto SrcReg = PHI.getIncomingValue(I);
4278 MachineInstr *SrcMI;
4279 if (!mi_match(SrcReg, MRI, m_MInstr(SrcMI)))
4280 continue;
4281 if (!SrcMIs.insert(SrcMI))
4282 continue;
4283
4284 // Build an extend after each src inst.
4285 auto *MBB = SrcMI->getParent();
4286 MachineBasicBlock::iterator InsertPt = ++SrcMI->getIterator();
4287 if (InsertPt != MBB->end() && InsertPt->isPHI())
4288 InsertPt = MBB->getFirstNonPHI();
4289
4290 Builder.setInsertPt(*SrcMI->getParent(), InsertPt);
4291 Builder.setDebugLoc(MI.getDebugLoc());
4292 auto NewExt = Builder.buildExtOrTrunc(ExtMI->getOpcode(), ExtTy, SrcReg);
4293 OldToNewSrcMap[SrcMI] = NewExt;
4294 }
4295
4296 // Create a new phi with the extended inputs.
4297 Builder.setInstrAndDebugLoc(MI);
4298 auto NewPhi = Builder.buildInstrNoInsert(TargetOpcode::G_PHI);
4299 NewPhi.addDef(DstReg);
4300 for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) {
4301 if (!MO.isReg()) {
4302 NewPhi.addMBB(MO.getMBB());
4303 continue;
4304 }
4305 auto *NewSrc = OldToNewSrcMap[MRI.getVRegDef(MO.getReg())];
4306 NewPhi.addUse(NewSrc->getOperand(0).getReg());
4307 }
4308 Builder.insertInstr(NewPhi);
4309 ExtMI->eraseFromParent();
4310}
4311
4313 Register &Reg) const {
4314 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT);
4315 // If we have a constant index, look for a G_BUILD_VECTOR source
4316 // and find the source register that the index maps to.
4317 Register SrcVec = MI.getOperand(1).getReg();
4318 LLT SrcTy = MRI.getType(SrcVec);
4319 if (SrcTy.isScalableVector())
4320 return false;
4321
4322 auto Cst = getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
4323 if (!Cst || Cst->Value.getZExtValue() >= SrcTy.getNumElements())
4324 return false;
4325
4326 unsigned VecIdx = Cst->Value.getZExtValue();
4327
4328 // Check if we have a build_vector or build_vector_trunc with an optional
4329 // trunc in front.
4330 MachineInstr *SrcVecMI;
4331 Register TruncSrc;
4332 if (mi_match(SrcVec, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
4333 if (!mi_match(TruncSrc, MRI, m_MInstr(SrcVecMI)))
4334 return false;
4335 } else if (!mi_match(SrcVec, MRI, m_MInstr(SrcVecMI)))
4336 return false;
4337
4338 if (SrcVecMI->getOpcode() != TargetOpcode::G_BUILD_VECTOR &&
4339 SrcVecMI->getOpcode() != TargetOpcode::G_BUILD_VECTOR_TRUNC)
4340 return false;
4341
4342 EVT Ty(getMVTForLLT(SrcTy));
4343 if (!MRI.hasOneNonDBGUse(SrcVec) &&
4344 !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty))
4345 return false;
4346
4347 Reg = SrcVecMI->getOperand(VecIdx + 1).getReg();
4348 return true;
4349}
4350
4352 Register &Reg) const {
4353 // Check the type of the register, since it may have come from a
4354 // G_BUILD_VECTOR_TRUNC.
4355 LLT ScalarTy = MRI.getType(Reg);
4356 Register DstReg = MI.getOperand(0).getReg();
4357 LLT DstTy = MRI.getType(DstReg);
4358
4359 if (ScalarTy != DstTy) {
4360 assert(ScalarTy.getSizeInBits() > DstTy.getSizeInBits());
4361 Builder.buildTrunc(DstReg, Reg);
4362 MI.eraseFromParent();
4363 return;
4364 }
4366}
4367
4370 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs) const {
4371 assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4372 // This combine tries to find build_vector's which have every source element
4373 // extracted using G_EXTRACT_VECTOR_ELT. This can happen when transforms like
4374 // the masked load scalarization is run late in the pipeline. There's already
4375 // a combine for a similar pattern starting from the extract, but that
4376 // doesn't attempt to do it if there are multiple uses of the build_vector,
4377 // which in this case is true. Starting the combine from the build_vector
4378 // feels more natural than trying to find sibling nodes of extracts.
4379 // E.g.
4380 // %vec(<4 x s32>) = G_BUILD_VECTOR %s1(s32), %s2, %s3, %s4
4381 // %ext1 = G_EXTRACT_VECTOR_ELT %vec, 0
4382 // %ext2 = G_EXTRACT_VECTOR_ELT %vec, 1
4383 // %ext3 = G_EXTRACT_VECTOR_ELT %vec, 2
4384 // %ext4 = G_EXTRACT_VECTOR_ELT %vec, 3
4385 // ==>
4386 // replace ext{1,2,3,4} with %s{1,2,3,4}
4387
4388 Register DstReg = MI.getOperand(0).getReg();
4389 LLT DstTy = MRI.getType(DstReg);
4390 unsigned NumElts = DstTy.getNumElements();
4391
4392 SmallBitVector ExtractedElts(NumElts);
4393 for (MachineInstr &II : MRI.use_nodbg_instructions(DstReg)) {
4394 if (II.getOpcode() != TargetOpcode::G_EXTRACT_VECTOR_ELT)
4395 return false;
4396 auto Cst = getIConstantVRegVal(II.getOperand(2).getReg(), MRI);
4397 if (!Cst)
4398 return false;
4399 unsigned Idx = Cst->getZExtValue();
4400 if (Idx >= NumElts)
4401 return false; // Out of range.
4402 ExtractedElts.set(Idx);
4403 SrcDstPairs.emplace_back(
4404 std::make_pair(MI.getOperand(Idx + 1).getReg(), &II));
4405 }
4406 // Match if every element was extracted.
4407 return ExtractedElts.all();
4408}
4409
4412 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs) const {
4413 assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4414 for (auto &Pair : SrcDstPairs) {
4415 auto *ExtMI = Pair.second;
4416 replaceRegWith(MRI, ExtMI->getOperand(0).getReg(), Pair.first);
4417 ExtMI->eraseFromParent();
4418 }
4419 MI.eraseFromParent();
4420}
4421
4424 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4425 applyBuildFnNoErase(MI, MatchInfo);
4426 MI.eraseFromParent();
4427}
4428
4431 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4432 MatchInfo(Builder);
4433}
4434
4436 bool AllowScalarConstants,
4437 BuildFnTy &MatchInfo) const {
4438 assert(MI.getOpcode() == TargetOpcode::G_OR);
4439
4440 Register Dst = MI.getOperand(0).getReg();
4441 LLT Ty = MRI.getType(Dst);
4442 unsigned BitWidth = Ty.getScalarSizeInBits();
4443
4444 Register ShlSrc, ShlAmt, LShrSrc, LShrAmt, Amt;
4445 unsigned FshOpc = 0;
4446
4447 // Match (or (shl ...), (lshr ...)).
4448 if (!mi_match(Dst, MRI,
4449 // m_GOr() handles the commuted version as well.
4450 m_GOr(m_GShl(m_Reg(ShlSrc), m_Reg(ShlAmt)),
4451 m_GLShr(m_Reg(LShrSrc), m_Reg(LShrAmt)))))
4452 return false;
4453
4454 // Given constants C0 and C1 such that C0 + C1 is bit-width:
4455 // (or (shl x, C0), (lshr y, C1)) -> (fshl x, y, C0) or (fshr x, y, C1)
4456 int64_t CstShlAmt = 0, CstLShrAmt;
4457 if (mi_match(ShlAmt, MRI, m_ICstOrSplat(CstShlAmt)) &&
4458 mi_match(LShrAmt, MRI, m_ICstOrSplat(CstLShrAmt)) &&
4459 CstShlAmt + CstLShrAmt == BitWidth) {
4460 FshOpc = TargetOpcode::G_FSHR;
4461 Amt = LShrAmt;
4462 } else if (mi_match(LShrAmt, MRI,
4464 ShlAmt == Amt) {
4465 // (or (shl x, amt), (lshr y, (sub bw, amt))) -> (fshl x, y, amt)
4466 FshOpc = TargetOpcode::G_FSHL;
4467 } else if (mi_match(ShlAmt, MRI,
4469 LShrAmt == Amt) {
4470 // (or (shl x, (sub bw, amt)), (lshr y, amt)) -> (fshr x, y, amt)
4471 FshOpc = TargetOpcode::G_FSHR;
4472 } else {
4473 return false;
4474 }
4475
4476 LLT AmtTy = MRI.getType(Amt);
4477 if (!isLegalOrBeforeLegalizer({FshOpc, {Ty, AmtTy}}) &&
4478 (!AllowScalarConstants || CstShlAmt == 0 || !Ty.isScalar()))
4479 return false;
4480
4481 MatchInfo = [=](MachineIRBuilder &B) {
4482 B.buildInstr(FshOpc, {Dst}, {ShlSrc, LShrSrc, Amt});
4483 };
4484 return true;
4485}
4486
4487// Fold (rot x, c) -> (rot x, c % BitSize)
4489 assert(MI.getOpcode() == TargetOpcode::G_ROTL ||
4490 MI.getOpcode() == TargetOpcode::G_ROTR);
4491 unsigned Bitsize =
4492 MRI.getType(MI.getOperand(0).getReg()).getScalarSizeInBits();
4493 Register AmtReg = MI.getOperand(2).getReg();
4494 bool OutOfRange = false;
4495 auto MatchOutOfRange = [Bitsize, &OutOfRange](const Constant *C) {
4496 if (auto *CI = dyn_cast<ConstantInt>(C))
4497 OutOfRange |= CI->getValue().uge(Bitsize);
4498 return true;
4499 };
4500 return matchUnaryPredicate(MRI, AmtReg, MatchOutOfRange) && OutOfRange;
4501}
4502
4504 assert(MI.getOpcode() == TargetOpcode::G_ROTL ||
4505 MI.getOpcode() == TargetOpcode::G_ROTR);
4506 unsigned Bitsize =
4507 MRI.getType(MI.getOperand(0).getReg()).getScalarSizeInBits();
4508 Register Amt = MI.getOperand(2).getReg();
4509 LLT AmtTy = MRI.getType(Amt);
4510 auto Bits = Builder.buildConstant(AmtTy, Bitsize);
4511 Amt = Builder.buildURem(AmtTy, MI.getOperand(2).getReg(), Bits).getReg(0);
4512 Observer.changingInstr(MI);
4513 MI.getOperand(2).setReg(Amt);
4514 Observer.changedInstr(MI);
4515}
4516
4518 int64_t &MatchInfo) const {
4519 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
4520 auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
4521
4522 // We want to avoid calling KnownBits on the LHS if possible, as this combine
4523 // has no filter and runs on every G_ICMP instruction. We can avoid calling
4524 // KnownBits on the LHS in two cases:
4525 //
4526 // - The RHS is unknown: Constants are always on RHS. If the RHS is unknown
4527 // we cannot do any transforms so we can safely bail out early.
4528 // - The RHS is zero: we don't need to know the LHS to do unsigned <0 and
4529 // >=0.
4530 auto KnownRHS = VT->getKnownBits(MI.getOperand(3).getReg());
4531 if (KnownRHS.isUnknown())
4532 return false;
4533
4534 std::optional<bool> KnownVal;
4535 if (KnownRHS.isZero()) {
4536 // ? uge 0 -> always true
4537 // ? ult 0 -> always false
4538 if (Pred == CmpInst::ICMP_UGE)
4539 KnownVal = true;
4540 else if (Pred == CmpInst::ICMP_ULT)
4541 KnownVal = false;
4542 }
4543
4544 if (!KnownVal) {
4545 auto KnownLHS = VT->getKnownBits(MI.getOperand(2).getReg());
4546 KnownVal = ICmpInst::compare(KnownLHS, KnownRHS, Pred);
4547 }
4548
4549 if (!KnownVal)
4550 return false;
4551 MatchInfo =
4552 *KnownVal
4554 /*IsVector = */
4555 MRI.getType(MI.getOperand(0).getReg()).isVector(),
4556 /* IsFP = */ false)
4557 : 0;
4558 return true;
4559}
4560
4563 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4564 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
4565 // Given:
4566 //
4567 // %x = G_WHATEVER (... x is known to be 0 or 1 ...)
4568 // %cmp = G_ICMP ne %x, 0
4569 //
4570 // Or:
4571 //
4572 // %x = G_WHATEVER (... x is known to be 0 or 1 ...)
4573 // %cmp = G_ICMP eq %x, 1
4574 //
4575 // We can replace %cmp with %x assuming true is 1 on the target.
4576 auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
4577 if (!CmpInst::isEquality(Pred))
4578 return false;
4579 Register Dst = MI.getOperand(0).getReg();
4580 LLT DstTy = MRI.getType(Dst);
4582 /* IsFP = */ false) != 1)
4583 return false;
4584 int64_t OneOrZero = Pred == CmpInst::ICMP_EQ;
4585 if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICst(OneOrZero)))
4586 return false;
4587 Register LHS = MI.getOperand(2).getReg();
4588 auto KnownLHS = VT->getKnownBits(LHS);
4589 if (KnownLHS.getMinValue() != 0 || KnownLHS.getMaxValue() != 1)
4590 return false;
4591 // Make sure replacing Dst with the LHS is a legal operation.
4592 LLT LHSTy = MRI.getType(LHS);
4593 unsigned LHSSize = LHSTy.getSizeInBits();
4594 unsigned DstSize = DstTy.getSizeInBits();
4595 unsigned Op = TargetOpcode::COPY;
4596 if (DstSize != LHSSize)
4597 Op = DstSize < LHSSize ? TargetOpcode::G_TRUNC : TargetOpcode::G_ZEXT;
4598 if (!isLegalOrBeforeLegalizer({Op, {DstTy, LHSTy}}))
4599 return false;
4600 MatchInfo = [=](MachineIRBuilder &B) { B.buildInstr(Op, {Dst}, {LHS}); };
4601 return true;
4602}
4603
4604// Replace (and (or x, c1), c2) with (and x, c2) iff c1 & c2 == 0
4607 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4608 assert(MI.getOpcode() == TargetOpcode::G_AND);
4609
4610 // Ignore vector types to simplify matching the two constants.
4611 // TODO: do this for vectors and scalars via a demanded bits analysis.
4612 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4613 if (Ty.isVector())
4614 return false;
4615
4616 Register Src;
4617 Register AndMaskReg;
4618 int64_t AndMaskBits;
4619 int64_t OrMaskBits;
4620 if (!mi_match(MI, MRI,
4621 m_GAnd(m_GOr(m_Reg(Src), m_ICst(OrMaskBits)),
4622 m_all_of(m_ICst(AndMaskBits), m_Reg(AndMaskReg)))))
4623 return false;
4624
4625 // Check if OrMask could turn on any bits in Src.
4626 if (AndMaskBits & OrMaskBits)
4627 return false;
4628
4629 MatchInfo = [=, &MI](MachineIRBuilder &B) {
4630 Observer.changingInstr(MI);
4631 // Canonicalize the result to have the constant on the RHS.
4632 if (MI.getOperand(1).getReg() == AndMaskReg)
4633 MI.getOperand(2).setReg(AndMaskReg);
4634 MI.getOperand(1).setReg(Src);
4635 Observer.changedInstr(MI);
4636 };
4637 return true;
4638}
4639
4640/// Form a G_SBFX from a G_SEXT_INREG fed by a right shift.
4643 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4644 assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
4645 Register Dst = MI.getOperand(0).getReg();
4646 Register Src = MI.getOperand(1).getReg();
4647 LLT Ty = MRI.getType(Src);
4649 if (!LI || !LI->isLegalOrCustom({TargetOpcode::G_SBFX, {Ty, ExtractTy}}))
4650 return false;
4651 int64_t Width = MI.getOperand(2).getImm();
4652 Register ShiftSrc;
4653 int64_t ShiftImm;
4654 if (!mi_match(Src, MRI,
4655 m_OneUse(m_any_of(m_GAShr(m_Reg(ShiftSrc), m_ICst(ShiftImm)),
4656 m_GLShr(m_Reg(ShiftSrc), m_ICst(ShiftImm))))))
4657 return false;
4658 if (ShiftImm < 0 || ShiftImm + Width > Ty.getScalarSizeInBits())
4659 return false;
4660
4661 MatchInfo = [=](MachineIRBuilder &B) {
4662 auto Cst1 = B.buildConstant(ExtractTy, ShiftImm);
4663 auto Cst2 = B.buildConstant(ExtractTy, Width);
4664 B.buildSbfx(Dst, ShiftSrc, Cst1, Cst2);
4665 };
4666 return true;
4667}
4668
4669/// Form a G_UBFX from "(a srl b) & mask", where b and mask are constants.
4671 BuildFnTy &MatchInfo) const {
4672 GAnd *And = cast<GAnd>(&MI);
4673 Register Dst = And->getReg(0);
4674 LLT Ty = MRI.getType(Dst);
4676 // Note that isLegalOrBeforeLegalizer is stricter and does not take custom
4677 // into account.
4678 if (LI && !LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
4679 return false;
4680
4681 int64_t AndImm, LSBImm;
4682 Register ShiftSrc;
4683 const unsigned Size = Ty.getScalarSizeInBits();
4684 if (!mi_match(And->getReg(0), MRI,
4685 m_GAnd(m_OneUse(m_GLShr(m_Reg(ShiftSrc), m_ICst(LSBImm))),
4686 m_ICst(AndImm))))
4687 return false;
4688
4689 // AndImm is sign-extended to 64 bits by m_ICst; restrict it to the operand
4690 // width so an all-ones mask (a redundant AND) is not misread as a wider mask.
4691 uint64_t MaybeMask = static_cast<uint64_t>(AndImm);
4692 if (Size < 64)
4693 MaybeMask &= maskTrailingOnes<uint64_t>(Size);
4694
4695 // The mask is a mask of the low bits iff imm & (imm+1) == 0.
4696 if (MaybeMask & (MaybeMask + 1))
4697 return false;
4698
4699 // LSB must fit within the register.
4700 if (static_cast<uint64_t>(LSBImm) >= Size)
4701 return false;
4702
4703 uint64_t Width = APInt(Size, MaybeMask).countr_one();
4704 // The extracted field [LSB, LSB+Width) must fit within the register.
4705 // Otherwise this is a redundant AND (e.g. an all-ones mask combined with a
4706 // non-zero shift) that is better handled by other combines, and would form
4707 // an out-of-range bitfield extract.
4708 if (static_cast<uint64_t>(LSBImm) + Width > Size)
4709 return false;
4710
4711 MatchInfo = [=](MachineIRBuilder &B) {
4712 auto WidthCst = B.buildConstant(ExtractTy, Width);
4713 auto LSBCst = B.buildConstant(ExtractTy, LSBImm);
4714 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {ShiftSrc, LSBCst, WidthCst});
4715 };
4716 return true;
4717}
4718
4721 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4722 const unsigned Opcode = MI.getOpcode();
4723 assert(Opcode == TargetOpcode::G_ASHR || Opcode == TargetOpcode::G_LSHR);
4724
4725 const Register Dst = MI.getOperand(0).getReg();
4726
4727 const unsigned ExtrOpcode = Opcode == TargetOpcode::G_ASHR
4728 ? TargetOpcode::G_SBFX
4729 : TargetOpcode::G_UBFX;
4730
4731 // Check if the type we would use for the extract is legal
4732 LLT Ty = MRI.getType(Dst);
4734 if (!LI || !LI->isLegalOrCustom({ExtrOpcode, {Ty, ExtractTy}}))
4735 return false;
4736
4737 Register ShlSrc;
4738 int64_t ShrAmt;
4739 int64_t ShlAmt;
4740 const unsigned Size = Ty.getScalarSizeInBits();
4741
4742 // Try to match shr (shl x, c1), c2
4743 if (!mi_match(Dst, MRI,
4744 m_BinOp(Opcode, m_OneUse(m_GShl(m_Reg(ShlSrc), m_ICst(ShlAmt))),
4745 m_ICst(ShrAmt))))
4746 return false;
4747
4748 // Make sure that the shift sizes can fit a bitfield extract
4749 if (ShlAmt < 0 || ShlAmt > ShrAmt || ShrAmt >= Size)
4750 return false;
4751
4752 // Skip this combine if the G_SEXT_INREG combine could handle it
4753 if (Opcode == TargetOpcode::G_ASHR && ShlAmt == ShrAmt)
4754 return false;
4755
4756 // Calculate start position and width of the extract
4757 const int64_t Pos = ShrAmt - ShlAmt;
4758 const int64_t Width = Size - ShrAmt;
4759
4760 MatchInfo = [=](MachineIRBuilder &B) {
4761 auto WidthCst = B.buildConstant(ExtractTy, Width);
4762 auto PosCst = B.buildConstant(ExtractTy, Pos);
4763 B.buildInstr(ExtrOpcode, {Dst}, {ShlSrc, PosCst, WidthCst});
4764 };
4765 return true;
4766}
4767
4770 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4771 const unsigned Opcode = MI.getOpcode();
4772 assert(Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_ASHR);
4773
4774 const Register Dst = MI.getOperand(0).getReg();
4775 LLT Ty = MRI.getType(Dst);
4777 if (LI && !LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
4778 return false;
4779
4780 // Try to match shr (and x, c1), c2
4781 Register AndSrc;
4782 int64_t ShrAmt;
4783 int64_t SMask;
4784 if (!mi_match(Dst, MRI,
4785 m_BinOp(Opcode, m_OneUse(m_GAnd(m_Reg(AndSrc), m_ICst(SMask))),
4786 m_ICst(ShrAmt))))
4787 return false;
4788
4789 const unsigned Size = Ty.getScalarSizeInBits();
4790 if (ShrAmt < 0 || ShrAmt >= Size)
4791 return false;
4792
4793 // If the shift subsumes the mask, emit the 0 directly.
4794 if (0 == (SMask >> ShrAmt)) {
4795 MatchInfo = [=](MachineIRBuilder &B) {
4796 B.buildConstant(Dst, 0);
4797 };
4798 return true;
4799 }
4800
4801 // Check that ubfx can do the extraction, with no holes in the mask.
4802 uint64_t UMask = SMask;
4803 UMask |= maskTrailingOnes<uint64_t>(ShrAmt);
4805 if (!isMask_64(UMask))
4806 return false;
4807
4808 // Calculate start position and width of the extract.
4809 const int64_t Pos = ShrAmt;
4810 const int64_t Width = llvm::countr_one(UMask) - ShrAmt;
4811
4812 // It's preferable to keep the shift, rather than form G_SBFX.
4813 // TODO: remove the G_AND via demanded bits analysis.
4814 if (Opcode == TargetOpcode::G_ASHR && Width + ShrAmt == Size)
4815 return false;
4816
4817 MatchInfo = [=](MachineIRBuilder &B) {
4818 auto WidthCst = B.buildConstant(ExtractTy, Width);
4819 auto PosCst = B.buildConstant(ExtractTy, Pos);
4820 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {AndSrc, PosCst, WidthCst});
4821 };
4822 return true;
4823}
4824
4825bool CombinerHelper::reassociationCanBreakAddressingModePattern(
4826 MachineInstr &MI) const {
4827 auto &PtrAdd = cast<GPtrAdd>(MI);
4828
4829 Register Src1Reg = PtrAdd.getBaseReg();
4830 auto *Src1Def = getOpcodeDef<GPtrAdd>(Src1Reg, MRI);
4831 if (!Src1Def)
4832 return false;
4833
4834 Register Src2Reg = PtrAdd.getOffsetReg();
4835
4836 if (MRI.hasOneNonDBGUse(Src1Reg))
4837 return false;
4838
4839 auto C1 = getIConstantVRegVal(Src1Def->getOffsetReg(), MRI);
4840 if (!C1)
4841 return false;
4842 auto C2 = getIConstantVRegVal(Src2Reg, MRI);
4843 if (!C2)
4844 return false;
4845
4846 const APInt &C1APIntVal = *C1;
4847 const APInt &C2APIntVal = *C2;
4848 const int64_t CombinedValue = (C1APIntVal + C2APIntVal).getSExtValue();
4849
4850 for (auto &UseMI : MRI.use_nodbg_instructions(PtrAdd.getReg(0))) {
4851 // This combine may end up running before ptrtoint/inttoptr combines
4852 // manage to eliminate redundant conversions, so try to look through them.
4853 MachineInstr *ConvUseMI = &UseMI;
4854 unsigned ConvUseOpc = ConvUseMI->getOpcode();
4855 while (ConvUseOpc == TargetOpcode::G_INTTOPTR ||
4856 ConvUseOpc == TargetOpcode::G_PTRTOINT) {
4857 Register DefReg = ConvUseMI->getOperand(0).getReg();
4858 if (!MRI.hasOneNonDBGUse(DefReg))
4859 break;
4860 ConvUseMI = &*MRI.use_instr_nodbg_begin(DefReg);
4861 ConvUseOpc = ConvUseMI->getOpcode();
4862 }
4863 auto *LdStMI = dyn_cast<GLoadStore>(ConvUseMI);
4864 if (!LdStMI)
4865 continue;
4866 // Is x[offset2] already not a legal addressing mode? If so then
4867 // reassociating the constants breaks nothing (we test offset2 because
4868 // that's the one we hope to fold into the load or store).
4869 TargetLoweringBase::AddrMode AM;
4870 AM.HasBaseReg = true;
4871 AM.BaseOffs = C2APIntVal.getSExtValue();
4872 unsigned AS = MRI.getType(LdStMI->getPointerReg()).getAddressSpace();
4873 Type *AccessTy = getTypeForLLT(LdStMI->getMMO().getMemoryType(),
4874 PtrAdd.getMF()->getFunction().getContext());
4875 const auto &TLI = *PtrAdd.getMF()->getSubtarget().getTargetLowering();
4876 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
4877 AccessTy, AS))
4878 continue;
4879
4880 // Would x[offset1+offset2] still be a legal addressing mode?
4881 AM.BaseOffs = CombinedValue;
4882 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
4883 AccessTy, AS))
4884 return true;
4885 }
4886
4887 return false;
4888}
4889
4891 MachineInstr *RHS,
4892 BuildFnTy &MatchInfo) const {
4893 // G_PTR_ADD(BASE, G_ADD(X, C)) -> G_PTR_ADD(G_PTR_ADD(BASE, X), C)
4894 Register Src1Reg = MI.getOperand(1).getReg();
4895 if (RHS->getOpcode() != TargetOpcode::G_ADD)
4896 return false;
4897 auto C2 = getIConstantVRegVal(RHS->getOperand(2).getReg(), MRI);
4898 if (!C2)
4899 return false;
4900
4901 // If both additions are nuw, the reassociated additions are also nuw.
4902 // If the original G_PTR_ADD is additionally nusw, X and C are both not
4903 // negative, so BASE+X is between BASE and BASE+(X+C). The new G_PTR_ADDs are
4904 // therefore also nusw.
4905 // If the original G_PTR_ADD is additionally inbounds (which implies nusw),
4906 // the new G_PTR_ADDs are then also inbounds.
4907 unsigned PtrAddFlags = MI.getFlags();
4908 unsigned AddFlags = RHS->getFlags();
4909 bool IsNoUWrap = PtrAddFlags & AddFlags & MachineInstr::MIFlag::NoUWrap;
4910 bool IsNoUSWrap = IsNoUWrap && (PtrAddFlags & MachineInstr::MIFlag::NoUSWrap);
4911 bool IsInBounds = IsNoUWrap && (PtrAddFlags & MachineInstr::MIFlag::InBounds);
4912 unsigned Flags = 0;
4913 if (IsNoUWrap)
4915 if (IsNoUSWrap)
4917 if (IsInBounds)
4919
4920 MatchInfo = [=, &MI](MachineIRBuilder &B) {
4921 LLT PtrTy = MRI.getType(MI.getOperand(0).getReg());
4922
4923 auto NewBase =
4924 Builder.buildPtrAdd(PtrTy, Src1Reg, RHS->getOperand(1).getReg(), Flags);
4925 Observer.changingInstr(MI);
4926 MI.getOperand(1).setReg(NewBase.getReg(0));
4927 MI.getOperand(2).setReg(RHS->getOperand(2).getReg());
4928 MI.setFlags(Flags);
4929 Observer.changedInstr(MI);
4930 };
4931 return !reassociationCanBreakAddressingModePattern(MI);
4932}
4933
4935 MachineInstr *LHS,
4936 MachineInstr *RHS,
4937 BuildFnTy &MatchInfo) const {
4938 // G_PTR_ADD (G_PTR_ADD X, C), Y) -> (G_PTR_ADD (G_PTR_ADD(X, Y), C)
4939 // if and only if (G_PTR_ADD X, C) has one use.
4940 Register LHSBase;
4941 std::optional<ValueAndVReg> LHSCstOff;
4942 if (!mi_match(MI.getBaseReg(), MRI,
4943 m_OneUse(m_GPtrAdd(m_Reg(LHSBase), m_GCst(LHSCstOff)))))
4944 return false;
4945
4946 auto *LHSPtrAdd = cast<GPtrAdd>(LHS);
4947
4948 // Reassociating nuw additions preserves nuw. If both original G_PTR_ADDs are
4949 // nuw and inbounds (which implies nusw), the offsets are both non-negative,
4950 // so the new G_PTR_ADDs are also inbounds.
4951 unsigned PtrAddFlags = MI.getFlags();
4952 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
4953 bool IsNoUWrap = PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::NoUWrap;
4954 bool IsNoUSWrap = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
4956 bool IsInBounds = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
4958 unsigned Flags = 0;
4959 if (IsNoUWrap)
4961 if (IsNoUSWrap)
4963 if (IsInBounds)
4965
4966 MatchInfo = [=, &MI](MachineIRBuilder &B) {
4967 // When we change LHSPtrAdd's offset register we might cause it to use a reg
4968 // before its def. Sink the instruction so the outer PTR_ADD to ensure this
4969 // doesn't happen.
4970 LHSPtrAdd->moveBefore(&MI);
4971 Register RHSReg = MI.getOffsetReg();
4972 // set VReg will cause type mismatch if it comes from extend/trunc
4973 auto NewCst = B.buildConstant(MRI.getType(RHSReg), LHSCstOff->Value);
4974 Observer.changingInstr(MI);
4975 MI.getOperand(2).setReg(NewCst.getReg(0));
4976 MI.setFlags(Flags);
4977 Observer.changedInstr(MI);
4978 Observer.changingInstr(*LHSPtrAdd);
4979 LHSPtrAdd->getOperand(2).setReg(RHSReg);
4980 LHSPtrAdd->setFlags(Flags);
4981 Observer.changedInstr(*LHSPtrAdd);
4982 };
4983 return !reassociationCanBreakAddressingModePattern(MI);
4984}
4985
4987 GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS,
4988 BuildFnTy &MatchInfo) const {
4989 // G_PTR_ADD(G_PTR_ADD(BASE, C1), C2) -> G_PTR_ADD(BASE, C1+C2)
4990 auto *LHSPtrAdd = dyn_cast<GPtrAdd>(LHS);
4991 if (!LHSPtrAdd)
4992 return false;
4993
4994 Register Src2Reg = MI.getOperand(2).getReg();
4995 Register LHSSrc1 = LHSPtrAdd->getBaseReg();
4996 Register LHSSrc2 = LHSPtrAdd->getOffsetReg();
4997 auto C1 = getIConstantVRegVal(LHSSrc2, MRI);
4998 if (!C1)
4999 return false;
5000 auto C2 = getIConstantVRegVal(Src2Reg, MRI);
5001 if (!C2)
5002 return false;
5003
5004 // Reassociating nuw additions preserves nuw. If both original G_PTR_ADDs are
5005 // inbounds, reaching the same result in one G_PTR_ADD is also inbounds.
5006 // The nusw constraints are satisfied because imm1+imm2 cannot exceed the
5007 // largest signed integer that fits into the index type, which is the maximum
5008 // size of allocated objects according to the IR Language Reference.
5009 unsigned PtrAddFlags = MI.getFlags();
5010 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
5011 bool IsNoUWrap = PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::NoUWrap;
5012 bool IsInBounds =
5013 PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::InBounds;
5014 unsigned Flags = 0;
5015 if (IsNoUWrap)
5017 if (IsInBounds) {
5020 }
5021
5022 MatchInfo = [=, &MI](MachineIRBuilder &B) {
5023 auto NewCst = B.buildConstant(MRI.getType(Src2Reg), *C1 + *C2);
5024 Observer.changingInstr(MI);
5025 MI.getOperand(1).setReg(LHSSrc1);
5026 MI.getOperand(2).setReg(NewCst.getReg(0));
5027 MI.setFlags(Flags);
5028 Observer.changedInstr(MI);
5029 };
5030 return !reassociationCanBreakAddressingModePattern(MI);
5031}
5032
5034 BuildFnTy &MatchInfo) const {
5035 auto &PtrAdd = cast<GPtrAdd>(MI);
5036 // We're trying to match a few pointer computation patterns here for
5037 // re-association opportunities.
5038 // 1) Isolating a constant operand to be on the RHS, e.g.:
5039 // G_PTR_ADD(BASE, G_ADD(X, C)) -> G_PTR_ADD(G_PTR_ADD(BASE, X), C)
5040 //
5041 // 2) Folding two constants in each sub-tree as long as such folding
5042 // doesn't break a legal addressing mode.
5043 // G_PTR_ADD(G_PTR_ADD(BASE, C1), C2) -> G_PTR_ADD(BASE, C1+C2)
5044 //
5045 // 3) Move a constant from the LHS of an inner op to the RHS of the outer.
5046 // G_PTR_ADD (G_PTR_ADD X, C), Y) -> G_PTR_ADD (G_PTR_ADD(X, Y), C)
5047 // iif (G_PTR_ADD X, C) has one use.
5048 MachineInstr *LHS, *RHS;
5049 if (!mi_match(PtrAdd.getBaseReg(), MRI, m_MInstr(LHS)) ||
5050 !mi_match(PtrAdd.getOffsetReg(), MRI, m_MInstr(RHS)))
5051 return false;
5052
5053 // Try to match example 2.
5054 if (matchReassocFoldConstantsInSubTree(PtrAdd, LHS, RHS, MatchInfo))
5055 return true;
5056
5057 // Try to match example 3.
5058 if (matchReassocConstantInnerLHS(PtrAdd, LHS, RHS, MatchInfo))
5059 return true;
5060
5061 // Try to match example 1.
5062 if (matchReassocConstantInnerRHS(PtrAdd, RHS, MatchInfo))
5063 return true;
5064
5065 return false;
5066}
5068 Register OpLHS, Register OpRHS,
5069 BuildFnTy &MatchInfo) const {
5070 LLT OpRHSTy = MRI.getType(OpRHS);
5071 MachineInstr *OpLHSDef;
5072 if (!mi_match(OpLHS, MRI, m_MInstr(OpLHSDef)) || OpLHSDef->getOpcode() != Opc)
5073 return false;
5074
5075 Register OpLHSLHS = OpLHSDef->getOperand(1).getReg();
5076 Register OpLHSRHS = OpLHSDef->getOperand(2).getReg();
5077
5078 // If the inner op is (X op C), pull the constant out so it can be folded with
5079 // other constants in the expression tree. Folding is not guaranteed so we
5080 // might have (C1 op C2). In that case do not pull a constant out because it
5081 // won't help and can lead to infinite loops.
5082 if (isConstantOrConstantSplatVector(OpLHSRHS, MRI) &&
5085 // (Opc (Opc X, C1), C2) -> (Opc X, (Opc C1, C2))
5086 MatchInfo = [=](MachineIRBuilder &B) {
5087 auto NewCst = B.buildInstr(Opc, {OpRHSTy}, {OpLHSRHS, OpRHS});
5088 B.buildInstr(Opc, {DstReg}, {OpLHSLHS, NewCst});
5089 };
5090 return true;
5091 }
5092 if (getTargetLowering().isReassocProfitable(MRI, OpLHS, OpRHS)) {
5093 // Reassociate: (op (op x, c1), y) -> (op (op x, y), c1)
5094 // iff (op x, c1) has one use
5095 MatchInfo = [=](MachineIRBuilder &B) {
5096 auto NewLHSLHS = B.buildInstr(Opc, {OpRHSTy}, {OpLHSLHS, OpRHS});
5097 B.buildInstr(Opc, {DstReg}, {NewLHSLHS, OpLHSRHS});
5098 };
5099 return true;
5100 }
5101 }
5102
5103 return false;
5104}
5105
5107 BuildFnTy &MatchInfo) const {
5108 // We don't check if the reassociation will break a legal addressing mode
5109 // here since pointer arithmetic is handled by G_PTR_ADD.
5110 unsigned Opc = MI.getOpcode();
5111 Register DstReg = MI.getOperand(0).getReg();
5112 Register LHSReg = MI.getOperand(1).getReg();
5113 Register RHSReg = MI.getOperand(2).getReg();
5114
5115 if (tryReassocBinOp(Opc, DstReg, LHSReg, RHSReg, MatchInfo))
5116 return true;
5117 if (tryReassocBinOp(Opc, DstReg, RHSReg, LHSReg, MatchInfo))
5118 return true;
5119 return false;
5120}
5121
5123 BuildFnTy &MatchInfo) const {
5124 Register Dst = MI.getOperand(0).getReg();
5125 Register SrcOp = MI.getOperand(1).getReg();
5126 LLT DstTy = MRI.getType(Dst);
5127 unsigned Opc = MI.getOpcode();
5128
5130 return false;
5131
5132 if (DstTy.isScalableVector())
5133 return false;
5134
5135 if (DstTy.isFixedVector()) {
5137 if (!BV)
5138 return false;
5139 SmallVector<APInt> Csts;
5140 for (unsigned I = 0, E = BV->getNumSources(); I != E; ++I) {
5141 auto MaybeCst = ConstantFoldCastOp(Opc, DstTy, BV->getSourceReg(I), MRI);
5142 if (!MaybeCst)
5143 return false;
5144 Csts.push_back(*MaybeCst);
5145 }
5146 MatchInfo = [Dst, Csts = std::move(Csts)](MachineIRBuilder &B) {
5147 B.buildBuildVectorConstant(Dst, Csts);
5148 };
5149 return true;
5150 }
5151
5152 if (auto MaybeCst = ConstantFoldCastOp(Opc, DstTy, SrcOp, MRI)) {
5153 MatchInfo = [Dst, Cst = *MaybeCst](MachineIRBuilder &B) {
5154 B.buildConstant(Dst, Cst);
5155 };
5156 return true;
5157 }
5158
5159 return false;
5160}
5161
5163 BuildFnTy &MatchInfo) const {
5164 Register Dst = MI.getOperand(0).getReg();
5165 LLT DstTy = MRI.getType(Dst);
5166
5168 MI.getOpcode(), DstTy, MI.getOperand(1).getReg(), MRI);
5169 if (Csts.empty())
5170 return false;
5171
5172 MatchInfo = [Dst, Csts = std::move(Csts)](MachineIRBuilder &B) {
5173 if (Csts.size() == 1)
5174 B.buildConstant(Dst, Csts[0]);
5175 else
5176 B.buildBuildVectorConstant(Dst, Csts);
5177 };
5178 return true;
5179}
5180
5182 BuildFnTy &MatchInfo) const {
5183 Register Dst = MI.getOperand(0).getReg();
5184 Register Op1 = MI.getOperand(1).getReg();
5185 Register Op2 = MI.getOperand(2).getReg();
5186 LLT DstTy = MRI.getType(Dst);
5187
5188 // Scalable and pointer-element vectors have no G_BUILD_VECTOR of
5189 // G_CONSTANT to fold to.
5190 if (DstTy.isScalableVector() ||
5191 (DstTy.isVector() && DstTy.getElementType().isPointer()))
5192 return false;
5193
5194 if (DstTy.isFixedVector()) {
5195 SmallVector<APInt> Csts =
5196 ConstantFoldVectorBinop(MI.getOpcode(), Op1, Op2, MRI);
5197 if (Csts.empty())
5198 return false;
5199 MatchInfo = [Dst, Csts = std::move(Csts)](MachineIRBuilder &B) {
5200 B.buildBuildVectorConstant(Dst, Csts);
5201 };
5202 return true;
5203 }
5204
5205 auto MaybeCst = ConstantFoldBinOp(MI.getOpcode(), Op1, Op2, MRI);
5206 if (!MaybeCst)
5207 return false;
5208 MatchInfo = [Dst, Cst = *MaybeCst](MachineIRBuilder &B) {
5209 B.buildConstant(Dst, Cst);
5210 };
5211 return true;
5212}
5213
5214// Vector FP constant folding assumes IEEE denormal arithmetic. Flush-to-zero
5215// and dynamic modes can produce a different value, so skip those folds.
5216// Targets such as RISC-V represent FP values as untyped scalars
5217// (s16/s32/s64/s128). getFltSemanticForLLT maps those onto the IEEE formats.
5218//
5219// TODO: Honor non-IEEE and dynamic denormal modes instead of skipping the
5220// vector folds. Scalar folds have the same limitation and stay unchanged here.
5222 LLT ScalarTy = Ty.getScalarType();
5223 if (!ScalarTy.isFloat() && !ScalarTy.isAnyScalar())
5224 return true;
5225 return MF.getDenormalMode(getFltSemanticForLLT(ScalarTy)) ==
5227}
5228
5230 BuildFnTy &MatchInfo) const {
5231 Register Dst = MI.getOperand(0).getReg();
5232 Register Op1 = MI.getOperand(1).getReg();
5233 Register Op2 = MI.getOperand(2).getReg();
5234 LLT DstTy = MRI.getType(Dst);
5235
5236 if (DstTy.isScalableVector())
5237 return false;
5238
5239 if (DstTy.isFixedVector()) {
5241 return false;
5243 ConstantFoldVectorFPBinop(MI.getOpcode(), Op1, Op2, MRI);
5244 if (Csts.empty())
5245 return false;
5246 MatchInfo = [Dst, Csts = std::move(Csts)](MachineIRBuilder &B) {
5247 B.buildBuildVectorFConstant(Dst, Csts);
5248 };
5249 return true;
5250 }
5251
5252 auto MaybeCst = ConstantFoldFPBinOp(MI.getOpcode(), Op1, Op2, MRI);
5253 if (!MaybeCst)
5254 return false;
5255 MatchInfo = [Dst, Cst = *MaybeCst](MachineIRBuilder &B) {
5256 B.buildFConstant(Dst, Cst);
5257 };
5258 return true;
5259}
5260
5262 BuildFnTy &MatchInfo) const {
5263 Register Dst = MI.getOperand(0).getReg();
5264 Register Src = MI.getOperand(1).getReg();
5265 LLT DstTy = MRI.getType(Dst);
5266 LLT SrcTy = MRI.getType(Src);
5267
5269 return false;
5270
5271 // Source and destination element types can differ (G_FPEXT/G_FPTRUNC) and
5272 // can have different denormal modes.
5273 if (SrcTy.isVector() &&
5276 return false;
5277
5279 ConstantFoldUnaryFPOp(MI.getOpcode(), DstTy, Src, MRI);
5280 if (Csts.empty())
5281 return false;
5282 MatchInfo = [Dst, Csts = std::move(Csts)](MachineIRBuilder &B) {
5283 if (Csts.size() == 1)
5284 B.buildFConstant(Dst, Csts[0]);
5285 else
5286 B.buildBuildVectorFConstant(Dst, Csts);
5287 };
5288 return true;
5289}
5290
5292 BuildFnTy &MatchInfo) const {
5293 assert(MI.getOpcode() == TargetOpcode::G_FMA ||
5294 MI.getOpcode() == TargetOpcode::G_FMAD);
5295 Register Dst = MI.getOperand(0).getReg();
5296 auto [_, Op1, Op2, Op3] = MI.getFirst4Regs();
5297 LLT DstTy = MRI.getType(Dst);
5298
5299 auto FoldFMA = [](const APFloat &A, const APFloat &B,
5300 const APFloat &C) -> APFloat {
5301 APFloat Res(A);
5303 return Res;
5304 };
5305
5306 if (DstTy.isScalableVector())
5307 return false;
5308
5309 if (DstTy.isFixedVector()) {
5311 return false;
5312 auto *BV1 = getOpcodeDef<GBuildVector>(Op1, MRI);
5313 auto *BV2 = getOpcodeDef<GBuildVector>(Op2, MRI);
5314 auto *BV3 = getOpcodeDef<GBuildVector>(Op3, MRI);
5315 if (!BV1 || !BV2 || !BV3)
5316 return false;
5317 unsigned NumElts = BV1->getNumSources();
5318 if (BV2->getNumSources() != NumElts || BV3->getNumSources() != NumElts)
5319 return false;
5321 for (unsigned I = 0; I != NumElts; ++I) {
5322 const ConstantFP *C1 = getConstantFPVRegVal(BV1->getSourceReg(I), MRI);
5323 const ConstantFP *C2 = getConstantFPVRegVal(BV2->getSourceReg(I), MRI);
5324 const ConstantFP *C3 = getConstantFPVRegVal(BV3->getSourceReg(I), MRI);
5325 if (!C1 || !C2 || !C3)
5326 return false;
5327 Csts.push_back(
5328 FoldFMA(C1->getValueAPF(), C2->getValueAPF(), C3->getValueAPF()));
5329 }
5330 MatchInfo = [Dst, Csts = std::move(Csts)](MachineIRBuilder &B) {
5331 B.buildBuildVectorFConstant(Dst, Csts);
5332 };
5333 return true;
5334 }
5335
5336 const ConstantFP *Op3Cst = getConstantFPVRegVal(Op3, MRI);
5337 const ConstantFP *Op2Cst = getConstantFPVRegVal(Op2, MRI);
5338 const ConstantFP *Op1Cst = getConstantFPVRegVal(Op1, MRI);
5339 if (!Op1Cst || !Op2Cst || !Op3Cst)
5340 return false;
5341
5342 APFloat Res = FoldFMA(Op1Cst->getValueAPF(), Op2Cst->getValueAPF(),
5343 Op3Cst->getValueAPF());
5344 MatchInfo = [Dst, Res](MachineIRBuilder &B) { B.buildFConstant(Dst, Res); };
5345 return true;
5346}
5347
5350 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
5351 // Look for a binop feeding into an AND with a mask:
5352 //
5353 // %add = G_ADD %lhs, %rhs
5354 // %and = G_AND %add, 000...11111111
5355 //
5356 // Check if it's possible to perform the binop at a narrower width and zext
5357 // back to the original width like so:
5358 //
5359 // %narrow_lhs = G_TRUNC %lhs
5360 // %narrow_rhs = G_TRUNC %rhs
5361 // %narrow_add = G_ADD %narrow_lhs, %narrow_rhs
5362 // %new_add = G_ZEXT %narrow_add
5363 // %and = G_AND %new_add, 000...11111111
5364 //
5365 // This can allow later combines to eliminate the G_AND if it turns out
5366 // that the mask is irrelevant.
5367 assert(MI.getOpcode() == TargetOpcode::G_AND);
5368 Register Dst = MI.getOperand(0).getReg();
5369 Register AndLHS = MI.getOperand(1).getReg();
5370 Register AndRHS = MI.getOperand(2).getReg();
5371 LLT WideTy = MRI.getType(Dst);
5372
5373 // If the potential binop has more than one use, then it's possible that one
5374 // of those uses will need its full width.
5375 if (!WideTy.isScalar() || !MRI.hasOneNonDBGUse(AndLHS))
5376 return false;
5377
5378 // Check if the LHS feeding the AND is impacted by the high bits that we're
5379 // masking out.
5380 //
5381 // e.g. for 64-bit x, y:
5382 //
5383 // add_64(x, y) & 65535 == zext(add_16(trunc(x), trunc(y))) & 65535
5384 MachineInstr *LHSInst = getDefIgnoringCopies(AndLHS, MRI);
5385 if (!LHSInst)
5386 return false;
5387 unsigned LHSOpc = LHSInst->getOpcode();
5388 switch (LHSOpc) {
5389 default:
5390 return false;
5391 case TargetOpcode::G_ADD:
5392 case TargetOpcode::G_SUB:
5393 case TargetOpcode::G_MUL:
5394 case TargetOpcode::G_AND:
5395 case TargetOpcode::G_OR:
5396 case TargetOpcode::G_XOR:
5397 break;
5398 }
5399
5400 // Find the mask on the RHS.
5401 auto Cst = getIConstantVRegValWithLookThrough(AndRHS, MRI);
5402 if (!Cst)
5403 return false;
5404 auto Mask = Cst->Value;
5405 if (!Mask.isMask())
5406 return false;
5407
5408 // No point in combining if there's nothing to truncate.
5409 unsigned NarrowWidth = Mask.countr_one();
5410 if (NarrowWidth == WideTy.getSizeInBits())
5411 return false;
5412 LLT NarrowTy = LLT::integer(NarrowWidth);
5413
5414 // Check if adding the zext + truncates could be harmful.
5415 auto &MF = *MI.getMF();
5416 const auto &TLI = getTargetLowering();
5417 LLVMContext &Ctx = MF.getFunction().getContext();
5418 if (!TLI.isTruncateFree(WideTy, NarrowTy, Ctx) ||
5419 !TLI.isZExtFree(NarrowTy, WideTy, Ctx))
5420 return false;
5421 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {NarrowTy, WideTy}}) ||
5422 !isLegalOrBeforeLegalizer({TargetOpcode::G_ZEXT, {WideTy, NarrowTy}}))
5423 return false;
5424 Register BinOpLHS = LHSInst->getOperand(1).getReg();
5425 Register BinOpRHS = LHSInst->getOperand(2).getReg();
5426 MatchInfo = [=, &MI](MachineIRBuilder &B) {
5427 auto NarrowLHS = Builder.buildTrunc(NarrowTy, BinOpLHS);
5428 auto NarrowRHS = Builder.buildTrunc(NarrowTy, BinOpRHS);
5429 auto NarrowBinOp =
5430 Builder.buildInstr(LHSOpc, {NarrowTy}, {NarrowLHS, NarrowRHS});
5431 auto Ext = Builder.buildZExt(WideTy, NarrowBinOp);
5432 Observer.changingInstr(MI);
5433 MI.getOperand(1).setReg(Ext.getReg(0));
5434 Observer.changedInstr(MI);
5435 };
5436 return true;
5437}
5438
5440 BuildFnTy &MatchInfo) const {
5441 // (G_*MULO x, 0) -> 0 + no carry out
5442 assert(MI.getOpcode() == TargetOpcode::G_UMULO ||
5443 MI.getOpcode() == TargetOpcode::G_SMULO);
5444 if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICstOrSplat(0)))
5445 return false;
5446 Register Dst = MI.getOperand(0).getReg();
5447 Register Carry = MI.getOperand(1).getReg();
5448 if (!isConstantLegalOrBeforeLegalizer(MRI.getType(Dst)) ||
5449 !isConstantLegalOrBeforeLegalizer(MRI.getType(Carry)))
5450 return false;
5451 MatchInfo = [=](MachineIRBuilder &B) {
5452 B.buildConstant(Dst, 0);
5453 B.buildConstant(Carry, 0);
5454 };
5455 return true;
5456}
5457
5461 if (SrcA.isValid() && SrcA == SrcB)
5462 return true;
5463 int64_t Cst;
5464 return mi_match(A, MRI, m_ICstOrSplat(Cst)) &&
5466}
5467
5469 unsigned Opcode = MI.getOpcode();
5470 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5471 auto &UDivorRem = cast<GenericMachineInstr>(MI);
5472 Register Dst = UDivorRem.getReg(0);
5473 Register LHS = UDivorRem.getReg(1);
5474 Register RHS = UDivorRem.getReg(2);
5475 LLT Ty = MRI.getType(Dst);
5476 LLT ScalarTy = Ty.getScalarType();
5477 const unsigned EltBits = ScalarTy.getScalarSizeInBits();
5479 LLT ScalarShiftAmtTy = ShiftAmtTy.getScalarType();
5480
5481 auto &MIB = Builder;
5482
5483 bool UseSRL = false;
5484 SmallVector<Register, 16> Shifts, Factors;
5485 auto *RHSDefInstr = cast<GenericMachineInstr>(getDefIgnoringCopies(RHS, MRI));
5486 bool IsSplat = getIConstantSplatVal(*RHSDefInstr, MRI).has_value();
5487
5488 auto BuildExactUDIVPattern = [&](const Constant *C) {
5489 // Don't recompute inverses for each splat element.
5490 if (IsSplat && !Factors.empty()) {
5491 Shifts.push_back(Shifts[0]);
5492 Factors.push_back(Factors[0]);
5493 return true;
5494 }
5495
5496 auto *CI = cast<ConstantInt>(C);
5497 APInt Divisor = CI->getValue();
5498 unsigned Shift = Divisor.countr_zero();
5499 if (Shift) {
5500 Divisor.lshrInPlace(Shift);
5501 UseSRL = true;
5502 }
5503
5504 // Calculate the multiplicative inverse modulo BW.
5505 APInt Factor = Divisor.multiplicativeInverse();
5506 Shifts.push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
5507 Factors.push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
5508 return true;
5509 };
5510
5511 if (MI.getFlag(MachineInstr::MIFlag::IsExact)) {
5512 // Collect all magic values from the build vector.
5513 if (!matchUnaryPredicate(MRI, RHS, BuildExactUDIVPattern))
5514 llvm_unreachable("Expected unary predicate match to succeed");
5515
5516 Register Shift, Factor;
5517 if (Ty.isVector()) {
5518 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
5519 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
5520 } else {
5521 Shift = Shifts[0];
5522 Factor = Factors[0];
5523 }
5524
5525 Register Res = LHS;
5526
5527 if (UseSRL)
5528 Res = MIB.buildLShr(Ty, Res, Shift, MachineInstr::IsExact).getReg(0);
5529
5530 return MIB.buildMul(Ty, Res, Factor);
5531 }
5532
5533 unsigned KnownLeadingZeros =
5534 VT ? VT->getKnownBits(LHS).countMinLeadingZeros() : 0;
5535
5536 bool UseNPQ = false;
5537 SmallVector<Register, 16> PreShifts, PostShifts, MagicFactors, NPQFactors;
5538 auto BuildUDIVPattern = [&](const Constant *C) {
5539 auto *CI = cast<ConstantInt>(C);
5540 const APInt &Divisor = CI->getValue();
5541
5542 bool SelNPQ = false;
5543 APInt Magic(Divisor.getBitWidth(), 0);
5544 unsigned PreShift = 0, PostShift = 0;
5545
5546 // Magic algorithm doesn't work for division by 1. We need to emit a select
5547 // at the end.
5548 // TODO: Use undef values for divisor of 1.
5549 if (!Divisor.isOne()) {
5550
5551 // UnsignedDivisionByConstantInfo doesn't work correctly if leading zeros
5552 // in the dividend exceeds the leading zeros for the divisor.
5555 Divisor, std::min(KnownLeadingZeros, Divisor.countl_zero()));
5556
5557 Magic = std::move(magics.Magic);
5558
5559 assert(magics.PreShift < Divisor.getBitWidth() &&
5560 "We shouldn't generate an undefined shift!");
5561 assert(magics.PostShift < Divisor.getBitWidth() &&
5562 "We shouldn't generate an undefined shift!");
5563 assert((!magics.IsAdd || magics.PreShift == 0) && "Unexpected pre-shift");
5564 PreShift = magics.PreShift;
5565 PostShift = magics.PostShift;
5566 SelNPQ = magics.IsAdd;
5567 }
5568
5569 PreShifts.push_back(
5570 MIB.buildConstant(ScalarShiftAmtTy, PreShift).getReg(0));
5571 MagicFactors.push_back(MIB.buildConstant(ScalarTy, Magic).getReg(0));
5572 NPQFactors.push_back(
5573 MIB.buildConstant(ScalarTy,
5574 SelNPQ ? APInt::getOneBitSet(EltBits, EltBits - 1)
5575 : APInt::getZero(EltBits))
5576 .getReg(0));
5577 PostShifts.push_back(
5578 MIB.buildConstant(ScalarShiftAmtTy, PostShift).getReg(0));
5579 UseNPQ |= SelNPQ;
5580 return true;
5581 };
5582
5583 // Collect the shifts/magic values from each element.
5584 bool Matched = matchUnaryPredicate(MRI, RHS, BuildUDIVPattern);
5585 (void)Matched;
5586 assert(Matched && "Expected unary predicate match to succeed");
5587
5588 Register PreShift, PostShift, MagicFactor, NPQFactor;
5589 auto *RHSDef = getOpcodeDef<GBuildVector>(RHS, MRI);
5590 if (RHSDef) {
5591 PreShift = MIB.buildBuildVector(ShiftAmtTy, PreShifts).getReg(0);
5592 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
5593 NPQFactor = MIB.buildBuildVector(Ty, NPQFactors).getReg(0);
5594 PostShift = MIB.buildBuildVector(ShiftAmtTy, PostShifts).getReg(0);
5595 } else {
5596 assert(MRI.getType(RHS).isScalar() &&
5597 "Non-build_vector operation should have been a scalar");
5598 PreShift = PreShifts[0];
5599 MagicFactor = MagicFactors[0];
5600 PostShift = PostShifts[0];
5601 }
5602
5603 Register Q = LHS;
5604 Q = MIB.buildLShr(Ty, Q, PreShift).getReg(0);
5605
5606 // Multiply the numerator (operand 0) by the magic value.
5607 Q = MIB.buildUMulH(Ty, Q, MagicFactor).getReg(0);
5608
5609 if (UseNPQ) {
5610 Register NPQ = MIB.buildSub(Ty, LHS, Q).getReg(0);
5611
5612 // For vectors we might have a mix of non-NPQ/NPQ paths, so use
5613 // G_UMULH to act as a SRL-by-1 for NPQ, else multiply by zero.
5614 if (Ty.isVector())
5615 NPQ = MIB.buildUMulH(Ty, NPQ, NPQFactor).getReg(0);
5616 else
5617 NPQ = MIB.buildLShr(Ty, NPQ, MIB.buildConstant(ShiftAmtTy, 1)).getReg(0);
5618
5619 Q = MIB.buildAdd(Ty, NPQ, Q).getReg(0);
5620 }
5621
5622 Q = MIB.buildLShr(Ty, Q, PostShift).getReg(0);
5623 auto One = MIB.buildConstant(Ty, 1);
5624 auto IsOne = MIB.buildICmp(
5626 Ty.isScalar() ? LLT::integer(1) : Ty.changeElementType(LLT::integer(1)),
5627 RHS, One);
5628 auto ret = MIB.buildSelect(Ty, IsOne, LHS, Q);
5629
5630 if (Opcode == TargetOpcode::G_UREM) {
5631 auto Prod = MIB.buildMul(Ty, ret, RHS);
5632 return MIB.buildSub(Ty, LHS, Prod);
5633 }
5634 return ret;
5635}
5636
5638 unsigned Opcode = MI.getOpcode();
5639 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5640 Register Dst = MI.getOperand(0).getReg();
5641 Register RHS = MI.getOperand(2).getReg();
5642 LLT DstTy = MRI.getType(Dst);
5643
5644 auto &MF = *MI.getMF();
5645 AttributeList Attr = MF.getFunction().getAttributes();
5646 const auto &TLI = getTargetLowering();
5647 LLVMContext &Ctx = MF.getFunction().getContext();
5648 if (DstTy.getScalarSizeInBits() == 1 ||
5649 TLI.isIntDivCheap(getApproximateEVTForLLT(DstTy, Ctx), Attr))
5650 return false;
5651
5652 // Don't do this for minsize because the instruction sequence is usually
5653 // larger.
5654 if (MF.getFunction().hasMinSize())
5655 return false;
5656
5657 if (Opcode == TargetOpcode::G_UDIV &&
5659 return matchUnaryPredicate(
5660 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5661 }
5662
5663 MachineInstr *RHSDef;
5664 if (!mi_match(RHS, MRI, m_MInstr(RHSDef)) ||
5666 return false;
5667
5668 // Don't do this if the types are not going to be legal.
5669 if (LI) {
5670 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_MUL, {DstTy, DstTy}}))
5671 return false;
5672 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMULH, {DstTy}}))
5673 return false;
5675 {TargetOpcode::G_ICMP,
5676 {DstTy.isVector() ? DstTy.changeElementSize(1) : LLT::scalar(1),
5677 DstTy}}))
5678 return false;
5679 if (Opcode == TargetOpcode::G_UREM &&
5680 !isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy, DstTy}}))
5681 return false;
5682 }
5683
5684 return matchUnaryPredicate(
5685 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5686}
5687
5689 auto *NewMI = buildUDivOrURemUsingMul(MI);
5690 replaceSingleDefInstWithReg(MI, NewMI->getOperand(0).getReg());
5691}
5692
5694 unsigned Opcode = MI.getOpcode();
5695 assert(Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_SREM);
5696 Register Dst = MI.getOperand(0).getReg();
5697 Register RHS = MI.getOperand(2).getReg();
5698 LLT DstTy = MRI.getType(Dst);
5699 auto SizeInBits = DstTy.getScalarSizeInBits();
5700 LLT WideTy = DstTy.changeElementSize(SizeInBits * 2);
5701
5702 auto &MF = *MI.getMF();
5703 AttributeList Attr = MF.getFunction().getAttributes();
5704 const auto &TLI = getTargetLowering();
5705 LLVMContext &Ctx = MF.getFunction().getContext();
5706 if (DstTy.getScalarSizeInBits() < 3 ||
5707 TLI.isIntDivCheap(getApproximateEVTForLLT(DstTy, Ctx), Attr))
5708 return false;
5709
5710 // Don't do this for minsize because the instruction sequence is usually
5711 // larger.
5712 if (MF.getFunction().hasMinSize())
5713 return false;
5714
5715 // If the sdiv has an 'exact' flag we can use a simpler lowering.
5716 if (Opcode == TargetOpcode::G_SDIV &&
5718 return matchUnaryPredicate(
5719 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5720 }
5721
5722 MachineInstr *RHSDef;
5723 if (!mi_match(RHS, MRI, m_MInstr(RHSDef)) ||
5725 return false;
5726
5727 // Don't do this if the types are not going to be legal.
5728 if (LI) {
5729 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_MUL, {DstTy, DstTy}}))
5730 return false;
5731 if (!isLegalOrHasFewerElements({TargetOpcode::G_SMULH, {DstTy}}) &&
5732 !isLegalOrHasWidenScalar({TargetOpcode::G_MUL, {WideTy, WideTy}}))
5733 return false;
5734 if (Opcode == TargetOpcode::G_SREM &&
5735 !isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy, DstTy}}))
5736 return false;
5737 }
5738
5739 return matchUnaryPredicate(
5740 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5741}
5742
5744 auto *NewMI = buildSDivOrSRemUsingMul(MI);
5745 replaceSingleDefInstWithReg(MI, NewMI->getOperand(0).getReg());
5746}
5747
5749 unsigned Opcode = MI.getOpcode();
5750 assert(MI.getOpcode() == TargetOpcode::G_SDIV ||
5751 Opcode == TargetOpcode::G_SREM);
5752 auto &SDivorRem = cast<GenericMachineInstr>(MI);
5753 Register Dst = SDivorRem.getReg(0);
5754 Register LHS = SDivorRem.getReg(1);
5755 Register RHS = SDivorRem.getReg(2);
5756 LLT Ty = MRI.getType(Dst);
5757 LLT ScalarTy = Ty.getScalarType();
5758 const unsigned EltBits = ScalarTy.getScalarSizeInBits();
5760 LLT ScalarShiftAmtTy = ShiftAmtTy.getScalarType();
5761 auto &MIB = Builder;
5762
5763 bool UseSRA = false;
5764 SmallVector<Register, 16> ExactShifts, ExactFactors;
5765
5766 auto *RHSDefInstr = cast<GenericMachineInstr>(getDefIgnoringCopies(RHS, MRI));
5767 bool IsSplat = getIConstantSplatVal(*RHSDefInstr, MRI).has_value();
5768
5769 auto BuildExactSDIVPattern = [&](const Constant *C) {
5770 // Don't recompute inverses for each splat element.
5771 if (IsSplat && !ExactFactors.empty()) {
5772 ExactShifts.push_back(ExactShifts[0]);
5773 ExactFactors.push_back(ExactFactors[0]);
5774 return true;
5775 }
5776
5777 auto *CI = cast<ConstantInt>(C);
5778 APInt Divisor = CI->getValue();
5779 unsigned Shift = Divisor.countr_zero();
5780 if (Shift) {
5781 Divisor.ashrInPlace(Shift);
5782 UseSRA = true;
5783 }
5784
5785 // Calculate the multiplicative inverse modulo BW.
5786 // 2^W requires W + 1 bits, so we have to extend and then truncate.
5787 APInt Factor = Divisor.multiplicativeInverse();
5788 ExactShifts.push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
5789 ExactFactors.push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
5790 return true;
5791 };
5792
5793 if (MI.getFlag(MachineInstr::MIFlag::IsExact)) {
5794 // Collect all magic values from the build vector.
5795 bool Matched = matchUnaryPredicate(MRI, RHS, BuildExactSDIVPattern);
5796 (void)Matched;
5797 assert(Matched && "Expected unary predicate match to succeed");
5798
5799 Register Shift, Factor;
5800 if (Ty.isVector()) {
5801 Shift = MIB.buildBuildVector(ShiftAmtTy, ExactShifts).getReg(0);
5802 Factor = MIB.buildBuildVector(Ty, ExactFactors).getReg(0);
5803 } else {
5804 Shift = ExactShifts[0];
5805 Factor = ExactFactors[0];
5806 }
5807
5808 Register Res = LHS;
5809
5810 if (UseSRA)
5811 Res = MIB.buildAShr(Ty, Res, Shift, MachineInstr::IsExact).getReg(0);
5812
5813 return MIB.buildMul(Ty, Res, Factor);
5814 }
5815
5816 SmallVector<Register, 16> MagicFactors, Factors, Shifts, ShiftMasks;
5817
5818 auto BuildSDIVPattern = [&](const Constant *C) {
5819 auto *CI = cast<ConstantInt>(C);
5820 const APInt &Divisor = CI->getValue();
5821
5824 int NumeratorFactor = 0;
5825 int ShiftMask = -1;
5826
5827 if (Divisor.isOne() || Divisor.isAllOnes()) {
5828 // If d is +1/-1, we just multiply the numerator by +1/-1.
5829 NumeratorFactor = Divisor.getSExtValue();
5830 Magics.Magic = 0;
5831 Magics.ShiftAmount = 0;
5832 ShiftMask = 0;
5833 } else if (Divisor.isStrictlyPositive() && Magics.Magic.isNegative()) {
5834 // If d > 0 and m < 0, add the numerator.
5835 NumeratorFactor = 1;
5836 } else if (Divisor.isNegative() && Magics.Magic.isStrictlyPositive()) {
5837 // If d < 0 and m > 0, subtract the numerator.
5838 NumeratorFactor = -1;
5839 }
5840
5841 MagicFactors.push_back(MIB.buildConstant(ScalarTy, Magics.Magic).getReg(0));
5842 Factors.push_back(MIB.buildConstant(ScalarTy, NumeratorFactor).getReg(0));
5843 Shifts.push_back(
5844 MIB.buildConstant(ScalarShiftAmtTy, Magics.ShiftAmount).getReg(0));
5845 ShiftMasks.push_back(MIB.buildConstant(ScalarTy, ShiftMask).getReg(0));
5846
5847 return true;
5848 };
5849
5850 // Collect the shifts/magic values from each element.
5851 bool Matched = matchUnaryPredicate(MRI, RHS, BuildSDIVPattern);
5852 (void)Matched;
5853 assert(Matched && "Expected unary predicate match to succeed");
5854
5855 Register MagicFactor, Factor, Shift, ShiftMask;
5856 auto *RHSDef = getOpcodeDef<GBuildVector>(RHS, MRI);
5857 if (RHSDef) {
5858 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
5859 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
5860 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
5861 ShiftMask = MIB.buildBuildVector(Ty, ShiftMasks).getReg(0);
5862 } else {
5863 assert(MRI.getType(RHS).isScalar() &&
5864 "Non-build_vector operation should have been a scalar");
5865 MagicFactor = MagicFactors[0];
5866 Factor = Factors[0];
5867 Shift = Shifts[0];
5868 ShiftMask = ShiftMasks[0];
5869 }
5870
5871 Register Q = LHS;
5872 Q = MIB.buildSMulH(Ty, LHS, MagicFactor).getReg(0);
5873
5874 // (Optionally) Add/subtract the numerator using Factor.
5875 Factor = MIB.buildMul(Ty, LHS, Factor).getReg(0);
5876 Q = MIB.buildAdd(Ty, Q, Factor).getReg(0);
5877
5878 // Shift right algebraic by shift value.
5879 Q = MIB.buildAShr(Ty, Q, Shift).getReg(0);
5880
5881 // Extract the sign bit, mask it and add it to the quotient.
5882 auto SignShift = MIB.buildConstant(ShiftAmtTy, EltBits - 1);
5883 auto T = MIB.buildLShr(Ty, Q, SignShift);
5884 T = MIB.buildAnd(Ty, T, ShiftMask);
5885 auto ret = MIB.buildAdd(Ty, Q, T);
5886
5887 if (Opcode == TargetOpcode::G_SREM) {
5888 auto Prod = MIB.buildMul(Ty, ret, RHS);
5889 return MIB.buildSub(Ty, LHS, Prod);
5890 }
5891 return ret;
5892}
5893
5895 assert((MI.getOpcode() == TargetOpcode::G_SDIV ||
5896 MI.getOpcode() == TargetOpcode::G_UDIV) &&
5897 "Expected SDIV or UDIV");
5898 auto &Div = cast<GenericMachineInstr>(MI);
5899 Register RHS = Div.getReg(2);
5900 auto MatchPow2 = [&](const Constant *C) {
5901 auto *CI = dyn_cast<ConstantInt>(C);
5902 return CI && (CI->getValue().isPowerOf2() ||
5903 (IsSigned && CI->getValue().isNegatedPowerOf2()));
5904 };
5905 return matchUnaryPredicate(MRI, RHS, MatchPow2, /*AllowUndefs=*/false);
5906}
5907
5909 assert(MI.getOpcode() == TargetOpcode::G_SDIV && "Expected SDIV");
5910 auto &SDiv = cast<GenericMachineInstr>(MI);
5911 Register Dst = SDiv.getReg(0);
5912 Register LHS = SDiv.getReg(1);
5913 Register RHS = SDiv.getReg(2);
5914 LLT Ty = MRI.getType(Dst);
5916 LLT CCVT = Ty.isVector() ? LLT::vector(Ty.getElementCount(), LLT::integer(1))
5917 : LLT::integer(1);
5918
5919 // Effectively we want to lower G_SDIV %lhs, %rhs, where %rhs is a power of 2,
5920 // to the following version:
5921 //
5922 // %c1 = G_CTTZ %rhs
5923 // %inexact = G_SUB $bitwidth, %c1
5924 // %sign = %G_ASHR %lhs, $(bitwidth - 1)
5925 // %lshr = G_LSHR %sign, %inexact
5926 // %add = G_ADD %lhs, %lshr
5927 // %ashr = G_ASHR %add, %c1
5928 // %ashr = G_SELECT, %isoneorallones, %lhs, %ashr
5929 // %zero = G_CONSTANT $0
5930 // %neg = G_NEG %ashr
5931 // %isneg = G_ICMP SLT %rhs, %zero
5932 // %res = G_SELECT %isneg, %neg, %ashr
5933
5934 unsigned BitWidth = Ty.getScalarSizeInBits();
5935 auto Zero = Builder.buildConstant(Ty, 0);
5936
5937 auto Bits = Builder.buildConstant(ShiftAmtTy, BitWidth);
5938 auto C1 = Builder.buildCTTZ(ShiftAmtTy, RHS);
5939 auto Inexact = Builder.buildSub(ShiftAmtTy, Bits, C1);
5940 // Splat the sign bit into the register
5941 auto Sign = Builder.buildAShr(
5942 Ty, LHS, Builder.buildConstant(ShiftAmtTy, BitWidth - 1));
5943
5944 // Add (LHS < 0) ? abs2 - 1 : 0;
5945 auto LSrl = Builder.buildLShr(Ty, Sign, Inexact);
5946 auto Add = Builder.buildAdd(Ty, LHS, LSrl);
5947 auto AShr = Builder.buildAShr(Ty, Add, C1);
5948
5949 // Special case: (sdiv X, 1) -> X
5950 // Special Case: (sdiv X, -1) -> 0-X
5951 auto One = Builder.buildConstant(Ty, 1);
5952 auto MinusOne = Builder.buildConstant(Ty, -1);
5953 auto IsOne = Builder.buildICmp(CmpInst::Predicate::ICMP_EQ, CCVT, RHS, One);
5954 auto IsMinusOne =
5955 Builder.buildICmp(CmpInst::Predicate::ICMP_EQ, CCVT, RHS, MinusOne);
5956 auto IsOneOrMinusOne = Builder.buildOr(CCVT, IsOne, IsMinusOne);
5957 AShr = Builder.buildSelect(Ty, IsOneOrMinusOne, LHS, AShr);
5958
5959 // If divided by a positive value, we're done. Otherwise, the result must be
5960 // negated.
5961 auto Neg = Builder.buildNeg(Ty, AShr);
5962 auto IsNeg = Builder.buildICmp(CmpInst::Predicate::ICMP_SLT, CCVT, RHS, Zero);
5963 Builder.buildSelect(MI.getOperand(0).getReg(), IsNeg, Neg, AShr);
5964 MI.eraseFromParent();
5965}
5966
5968 assert(MI.getOpcode() == TargetOpcode::G_UDIV && "Expected UDIV");
5969 auto &UDiv = cast<GenericMachineInstr>(MI);
5970 Register Dst = UDiv.getReg(0);
5971 Register LHS = UDiv.getReg(1);
5972 Register RHS = UDiv.getReg(2);
5973 LLT Ty = MRI.getType(Dst);
5975
5976 auto C1 = Builder.buildCTTZ(ShiftAmtTy, RHS);
5977 Builder.buildLShr(MI.getOperand(0).getReg(), LHS, C1);
5978 MI.eraseFromParent();
5979}
5980
5982 BuildFnTy &MatchInfo) const {
5983 Register Dst = MI.getOperand(0).getReg();
5984 Register LHS = MI.getOperand(1).getReg();
5985 Register RHS = MI.getOperand(2).getReg();
5986 Register Base, Shift;
5987 if (!mi_match(RHS, MRI, m_GShl(m_Reg(Base), m_Reg(Shift))))
5988 return false;
5989
5990 if (!matchUnaryPredicate(MRI, Base, [](const Constant *C) {
5992 return CI && CI->getValue().isPowerOf2();
5993 }))
5994 return false;
5995
5996 LLT Ty = MRI.getType(Dst);
5997 LLT ShiftTy = MRI.getType(Shift);
5998 // The shift type must be able to represent every valid shift amount.
5999 if (ShiftTy.getScalarSizeInBits() < Log2_64_Ceil(Ty.getScalarSizeInBits()))
6000 return false;
6001 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_CTTZ, {ShiftTy, Ty}}) ||
6002 !isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {ShiftTy, ShiftTy}}) ||
6003 !isLegalOrBeforeLegalizer({TargetOpcode::G_LSHR, {Ty, ShiftTy}}))
6004 return false;
6005
6006 unsigned Flags =
6008 MatchInfo = [=](MachineIRBuilder &B) {
6009 auto Log2 = B.buildCTTZ(ShiftTy, Base);
6010 auto Amount = B.buildAdd(ShiftTy, Shift, Log2);
6011 B.buildLShr(Dst, LHS, Amount, Flags);
6012 };
6013 return true;
6014}
6015
6017 MachineInstr &MI, unsigned UnsignedOpcode) const {
6018 Register Dst = MI.getOperand(0).getReg();
6019 Register LHS = MI.getOperand(1).getReg();
6020 Register RHS = MI.getOperand(2).getReg();
6021 if (!VT || !VT->signBitIsZero(LHS) || !VT->signBitIsZero(RHS))
6022 return false;
6023
6024 LLT Ty = MRI.getType(Dst);
6025 return isLegalOrBeforeLegalizer({UnsignedOpcode, {Ty}});
6026}
6027
6029 assert(MI.getOpcode() == TargetOpcode::G_SREM && "Expected SREM");
6030 auto &SRem = cast<GBinOp>(MI);
6031 Register Dst = SRem.getReg(0);
6032 Register LHS = SRem.getLHSReg();
6033 Register RHS = SRem.getRHSReg();
6034 LLT Ty = MRI.getType(Dst);
6036
6037 // Effectively we want to lower G_SREM %lhs, %rhs, where %rhs is +/- a power
6038 // of 2, to the following branch-free bias-and-mask version:
6039 //
6040 // %abs = G_ABS %rhs
6041 // %mask = G_SUB %abs, 1
6042 // %sign = G_ASHR %lhs, $(bitwidth - 1)
6043 // %bias = G_AND %sign, %mask
6044 // %biased = G_ADD %lhs, %bias
6045 // %masked = G_AND %biased, %mask
6046 // %res = G_SUB %masked, %bias
6047 //
6048 // The bias adds (|%rhs| - 1) for negative %lhs, correcting rounding towards
6049 // zero (instead of towards -inf that a plain mask would give). Constant
6050 // divisors collapse %mask to a single G_CONSTANT via the CSEMIRBuilder folds
6051 // for G_ABS and G_SUB.
6052
6053 unsigned BitWidth = Ty.getScalarSizeInBits();
6054 auto AbsRHS = Builder.buildAbs(Ty, RHS);
6055 auto Mask = Builder.buildSub(Ty, AbsRHS, Builder.buildConstant(Ty, 1));
6056 auto BWMinusOne = Builder.buildConstant(ShiftAmtTy, BitWidth - 1);
6057 auto Sign = Builder.buildAShr(Ty, LHS, BWMinusOne);
6058 auto Bias = Builder.buildAnd(Ty, Sign, Mask);
6059 auto Biased = Builder.buildAdd(Ty, LHS, Bias);
6060 auto Masked = Builder.buildAnd(Ty, Biased, Mask);
6061 Builder.buildSub(Dst, Masked, Bias);
6062 MI.eraseFromParent();
6063}
6064
6066 assert(MI.getOpcode() == TargetOpcode::G_UMULH);
6067 Register RHS = MI.getOperand(2).getReg();
6068 Register Dst = MI.getOperand(0).getReg();
6069 LLT Ty = MRI.getType(Dst);
6070 LLT RHSTy = MRI.getType(RHS);
6072 auto MatchPow2ExceptOne = [&](const Constant *C) {
6073 if (auto *CI = dyn_cast<ConstantInt>(C))
6074 return CI->getValue().isPowerOf2() && !CI->getValue().isOne();
6075 return false;
6076 };
6077 if (!matchUnaryPredicate(MRI, RHS, MatchPow2ExceptOne, false))
6078 return false;
6079 // We need to check both G_LSHR and G_CTLZ because the combine uses G_CTLZ to
6080 // get log base 2, and it is not always legal for on a target.
6081 return isLegalOrBeforeLegalizer({TargetOpcode::G_LSHR, {Ty, ShiftAmtTy}}) &&
6082 isLegalOrBeforeLegalizer({TargetOpcode::G_CTLZ, {RHSTy, RHSTy}});
6083}
6084
6086 Register LHS = MI.getOperand(1).getReg();
6087 Register RHS = MI.getOperand(2).getReg();
6088 Register Dst = MI.getOperand(0).getReg();
6089 LLT Ty = MRI.getType(Dst);
6091 unsigned NumEltBits = Ty.getScalarSizeInBits();
6092
6093 auto LogBase2 = buildLogBase2(RHS, Builder);
6094 auto ShiftAmt =
6095 Builder.buildSub(Ty, Builder.buildConstant(Ty, NumEltBits), LogBase2);
6096 auto Trunc = Builder.buildZExtOrTrunc(ShiftAmtTy, ShiftAmt);
6097 Builder.buildLShr(Dst, LHS, Trunc);
6098 MI.eraseFromParent();
6099}
6100
6102 Register &MatchInfo) const {
6103 Register Dst = MI.getOperand(0).getReg();
6104 Register Src = MI.getOperand(1).getReg();
6105 LLT DstTy = MRI.getType(Dst);
6106 LLT SrcTy = MRI.getType(Src);
6107 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6108 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6109 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6110
6112 {TargetOpcode::G_TRUNC_SSAT_S, {DstTy, SrcTy}}))
6113 return false;
6114
6115 APInt SignedMax = APInt::getSignedMaxValue(NumDstBits).sext(NumSrcBits);
6116 APInt SignedMin = APInt::getSignedMinValue(NumDstBits).sext(NumSrcBits);
6117 if (mi_match(
6118 Src, MRI,
6119 m_GSMin(m_GSMax(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMin)),
6120 m_SpecificICstOrSplat(SignedMax))))
6121 return true;
6122 if (mi_match(
6123 Src, MRI,
6124 m_GSMax(m_GSMin(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMax)),
6125 m_SpecificICstOrSplat(SignedMin))))
6126 return true;
6127
6128 // CVP in the midend will often transform trunc(smin(smax(..)) into
6129 // trunc nsw(smin(..)) as the smax against INT_MIN never saturates.
6130 if (MI.getFlag(MachineInstr::MIFlag::NoSWrap) &&
6131 mi_match(Src, MRI,
6132 m_GSMin(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMax))))
6133 return true;
6134
6135 return false;
6136}
6137
6139 Register &MatchInfo) const {
6140 Register Dst = MI.getOperand(0).getReg();
6141 Builder.buildTruncSSatS(Dst, MatchInfo);
6142 MI.eraseFromParent();
6143}
6144
6146 Register &MatchInfo) const {
6147 Register Dst = MI.getOperand(0).getReg();
6148 Register Src = MI.getOperand(1).getReg();
6149 LLT DstTy = MRI.getType(Dst);
6150 LLT SrcTy = MRI.getType(Src);
6151 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6152 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6153 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6154
6156 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6157 return false;
6158 APInt UnsignedMax = APInt::getMaxValue(NumDstBits).zext(NumSrcBits);
6159 return mi_match(Src, MRI,
6161 m_SpecificICstOrSplat(UnsignedMax))) ||
6162 mi_match(Src, MRI,
6163 m_GSMax(m_GSMin(m_Reg(MatchInfo),
6164 m_SpecificICstOrSplat(UnsignedMax)),
6165 m_SpecificICstOrSplat(0))) ||
6166 mi_match(Src, MRI,
6168 m_SpecificICstOrSplat(UnsignedMax)));
6169}
6170
6172 Register &MatchInfo) const {
6173 Register Dst = MI.getOperand(0).getReg();
6174 Builder.buildTruncSSatU(Dst, MatchInfo);
6175 MI.eraseFromParent();
6176}
6177
6179 MachineInstr &MinMI) const {
6180 Register Min = MinMI.getOperand(2).getReg();
6181 Register Val = MinMI.getOperand(1).getReg();
6182 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6183 LLT SrcTy = MRI.getType(Val);
6184 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6185 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6186 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6187
6189 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6190 return false;
6191 APInt UnsignedMax = APInt::getMaxValue(NumDstBits).zext(NumSrcBits);
6192 return mi_match(Min, MRI, m_SpecificICstOrSplat(UnsignedMax)) &&
6193 !mi_match(Val, MRI, m_GSMax(m_Reg(), m_Reg()));
6194}
6195
6197 MachineInstr &SrcMI) const {
6198 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6199 LLT SrcTy = MRI.getType(SrcMI.getOperand(1).getReg());
6200
6201 return LI &&
6202 isLegalOrBeforeLegalizer({TargetOpcode::G_FPTOUI_SAT, {DstTy, SrcTy}});
6203}
6204
6206 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6207
6208 Register LHS = MI.getOperand(1).getReg();
6209 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
6210
6211 const auto LHSCst = Ty.isVector()
6212 ? getFConstantSplat(LHS, MRI, /* allowUndef */ true)
6214 if (!LHSCst)
6215 return false;
6216
6217 // Skip fsub_to_fneg when both LHS and RHS are scalar constants (vector FP
6218 // binop constant folding is not supported yet), so constant_fold_fp_binop
6219 // folds these cases.
6220 if (!Ty.isVector() && getConstantFPVRegVal(LHS, MRI) &&
6221 getConstantFPVRegVal(MI.getOperand(2).getReg(), MRI))
6222 return false;
6223
6224 // -0.0 is always allowed
6225 if (LHSCst->Value.isNegZero())
6226 return true;
6227
6228 // +0.0 is only allowed if nsz is set.
6229 if (LHSCst->Value.isPosZero())
6230 return MI.getFlag(MachineInstr::FmNsz);
6231
6232 return false;
6233}
6234
6235/// Checks if \p MI is TargetOpcode::G_FMUL and contractable either
6236/// due to global flags or MachineInstr flags.
6237static bool isContractableFMul(MachineInstr &MI, bool AllowFusionGlobally) {
6238 if (MI.getOpcode() != TargetOpcode::G_FMUL)
6239 return false;
6240 return AllowFusionGlobally || MI.getFlag(MachineInstr::MIFlag::FmContract);
6241}
6242
6243static bool hasMoreUses(const MachineInstr &MI0, const MachineInstr &MI1,
6244 const MachineRegisterInfo &MRI) {
6245 return std::distance(MRI.use_instr_nodbg_begin(MI0.getOperand(0).getReg()),
6246 MRI.use_instr_nodbg_end()) >
6247 std::distance(MRI.use_instr_nodbg_begin(MI1.getOperand(0).getReg()),
6248 MRI.use_instr_nodbg_end());
6249}
6250
6252 bool &AllowFusionGlobally,
6253 bool &HasFMAD, bool &Aggressive,
6254 bool CanReassociate) const {
6255
6256 auto *MF = MI.getMF();
6257 const auto &TLI = *MF->getSubtarget().getTargetLowering();
6258 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6259
6260 if (CanReassociate && !MI.getFlag(MachineInstr::MIFlag::FmReassoc))
6261 return false;
6262
6263 // Floating-point multiply-add with intermediate rounding.
6264 HasFMAD = (!isPreLegalize() && TLI.isFMADLegal(MI, DstType));
6265 // Floating-point multiply-add without intermediate rounding.
6266 bool HasFMA = TLI.isFMAFasterThanFMulAndFAdd(*MF, DstType) &&
6267 isLegalOrBeforeLegalizer({TargetOpcode::G_FMA, {DstType}});
6268 // No valid opcode, do not combine.
6269 if (!HasFMAD && !HasFMA)
6270 return false;
6271
6272 // FMAD (with intermediate rounding) is always safe to form; FMA requires the
6273 // contract fast-math flag.
6274 AllowFusionGlobally = HasFMAD;
6275 // If the addition is not contractable, do not combine.
6276 if (!AllowFusionGlobally && !MI.getFlag(MachineInstr::MIFlag::FmContract))
6277 return false;
6278
6279 Aggressive = TLI.enableAggressiveFMAFusion(DstType);
6280 return true;
6281}
6282
6285 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6286 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6287
6288 bool AllowFusionGlobally, HasFMAD, Aggressive;
6289 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6290 return false;
6291
6292 Register Op1 = MI.getOperand(1).getReg();
6293 Register Op2 = MI.getOperand(2).getReg();
6294 MachineInstr *Op1Def, *Op2Def;
6295 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6296 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6297 return false;
6298 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6299 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6300 unsigned PreferredFusedOpcode =
6301 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6302
6303 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6304 // prefer to fold the multiply with fewer uses.
6305 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6306 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6307 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6308 std::swap(LHS, RHS);
6309 }
6310
6311 // fold (fadd (fmul x, y), z) -> (fma x, y, z)
6312 if (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6313 (Aggressive || MRI.hasOneNonDBGUse(LHS.Reg))) {
6314 unsigned Flags = MI.getFlags() & LHS.MI->getFlags();
6315 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6316 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6317 {LHS.MI->getOperand(1).getReg(),
6318 LHS.MI->getOperand(2).getReg(), RHS.Reg},
6319 Flags);
6320 };
6321 return true;
6322 }
6323
6324 // fold (fadd x, (fmul y, z)) -> (fma y, z, x)
6325 if (isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6326 (Aggressive || MRI.hasOneNonDBGUse(RHS.Reg))) {
6327 unsigned Flags = MI.getFlags() & RHS.MI->getFlags();
6328 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6329 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6330 {RHS.MI->getOperand(1).getReg(),
6331 RHS.MI->getOperand(2).getReg(), LHS.Reg},
6332 Flags);
6333 };
6334 return true;
6335 }
6336
6337 return false;
6338}
6339
6342 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6343 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6344
6345 bool AllowFusionGlobally, HasFMAD, Aggressive;
6346 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6347 return false;
6348
6349 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6350 Register Op1 = MI.getOperand(1).getReg();
6351 Register Op2 = MI.getOperand(2).getReg();
6352 MachineInstr *Op1Def, *Op2Def;
6353 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6354 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6355 return false;
6356 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6357 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6358 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6359
6360 unsigned PreferredFusedOpcode =
6361 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6362
6363 MachineInstr *LHSFpExtSrc;
6364 bool LHSContractable =
6365 mi_match(LHS.Reg, MRI, m_GFPExt(m_MInstr(LHSFpExtSrc))) &&
6366 isContractableFMul(*LHSFpExtSrc, AllowFusionGlobally) &&
6367 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6368 MRI.getType(LHSFpExtSrc->getOperand(1).getReg()));
6369 MachineInstr *RHSFpExtSrc;
6370 bool RHSContractable =
6371 mi_match(RHS.Reg, MRI, m_GFPExt(m_MInstr(RHSFpExtSrc))) &&
6372 isContractableFMul(*RHSFpExtSrc, AllowFusionGlobally) &&
6373 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6374 MRI.getType(RHSFpExtSrc->getOperand(1).getReg()));
6375
6376 // fold (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z)
6377 if (LHSContractable || RHSContractable) {
6378 // Ensure that the contractable fmul with the fewest uses (if both are
6379 // contractable) is the LHS operand.
6380 if (!LHSContractable ||
6381 (RHSContractable && hasMoreUses(*LHSFpExtSrc, *RHSFpExtSrc, MRI))) {
6382 std::swap(LHS, RHS);
6383 LHSFpExtSrc = RHSFpExtSrc;
6384 }
6385
6386 unsigned Flags = MI.getFlags() & LHSFpExtSrc->getFlags();
6387 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6388 auto FpExtX = B.buildFPExt(DstType, LHSFpExtSrc->getOperand(1).getReg());
6389 auto FpExtY = B.buildFPExt(DstType, LHSFpExtSrc->getOperand(2).getReg());
6390 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6391 {FpExtX.getReg(0), FpExtY.getReg(0), RHS.Reg}, Flags);
6392 };
6393 return true;
6394 }
6395
6396 return false;
6397}
6398
6401 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6402 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6403
6404 bool AllowFusionGlobally, HasFMAD, Aggressive;
6405 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive, true))
6406 return false;
6407
6408 Register Op1 = MI.getOperand(1).getReg();
6409 Register Op2 = MI.getOperand(2).getReg();
6410 MachineInstr *Op1Def, *Op2Def;
6411 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6412 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6413 return false;
6414 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6415 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6416 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6417
6418 unsigned PreferredFusedOpcode =
6419 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6420
6421 MachineInstr *FMA = nullptr;
6422 Register Z;
6423 // fold (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z))
6424 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6425 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6426 m_GFMul(m_Reg(), m_Reg())) &&
6427 MRI.hasOneNonDBGUse(LHS.MI->getOperand(0).getReg()) &&
6428 MRI.hasOneNonDBGUse(LHS.MI->getOperand(3).getReg())) {
6429 FMA = LHS.MI;
6430 Z = RHS.Reg;
6431 }
6432 // fold (fadd z, (fma x, y, (fmul u, v))) -> (fma x, y, (fma u, v, z))
6433 else if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6434 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6435 m_GFMul(m_Reg(), m_Reg())) &&
6436 MRI.hasOneNonDBGUse(RHS.MI->getOperand(0).getReg()) &&
6437 MRI.hasOneNonDBGUse(RHS.MI->getOperand(3).getReg())) {
6438 Z = LHS.Reg;
6439 FMA = RHS.MI;
6440 }
6441
6442 if (FMA) {
6443 MachineInstr *FMulMI;
6444 if (!mi_match(FMA->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6445 return false;
6446 Register X = FMA->getOperand(1).getReg();
6447 Register Y = FMA->getOperand(2).getReg();
6448 Register U = FMulMI->getOperand(1).getReg();
6449 Register V = FMulMI->getOperand(2).getReg();
6450 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6451 unsigned OuterFlags = MI.getFlags() & FMA->getFlags();
6452
6453 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6454 Register InnerFMA = MRI.createGenericVirtualRegister(DstTy);
6455 B.buildInstr(PreferredFusedOpcode, {InnerFMA}, {U, V, Z}, InnerFlags);
6456 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6457 {X, Y, InnerFMA}, OuterFlags);
6458 };
6459 return true;
6460 }
6461
6462 return false;
6463}
6464
6467 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6468 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6469
6470 bool AllowFusionGlobally, HasFMAD, Aggressive;
6471 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6472 return false;
6473
6474 if (!Aggressive)
6475 return false;
6476
6477 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6478 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6479 Register Op1 = MI.getOperand(1).getReg();
6480 Register Op2 = MI.getOperand(2).getReg();
6481 MachineInstr *Op1Def, *Op2Def;
6482 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6483 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6484 return false;
6485 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6486 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6487
6488 unsigned PreferredFusedOpcode =
6489 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6490
6491 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6492 // prefer to fold the multiply with fewer uses.
6493 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6494 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6495 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6496 std::swap(LHS, RHS);
6497 }
6498
6499 // Builds: (fma x, y, (fma (fpext u), (fpext v), z))
6500 auto buildMatchInfo = [=, &MI](Register U, Register V, Register Z, Register X,
6501 Register Y, unsigned InnerFlags,
6502 unsigned OuterFlags, MachineIRBuilder &B) {
6503 Register FpExtU = B.buildFPExt(DstType, U).getReg(0);
6504 Register FpExtV = B.buildFPExt(DstType, V).getReg(0);
6505 Register InnerFMA = B.buildInstr(PreferredFusedOpcode, {DstType},
6506 {FpExtU, FpExtV, Z}, InnerFlags)
6507 .getReg(0);
6508 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6509 {X, Y, InnerFMA}, OuterFlags);
6510 };
6511
6512 MachineInstr *FMulMI, *FMAMI;
6513 // fold (fadd (fma x, y, (fpext (fmul u, v))), z)
6514 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6515 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6516 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6517 m_GFPExt(m_MInstr(FMulMI))) &&
6518 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6519 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6520 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6521 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6522 unsigned OuterFlags = MI.getFlags() & LHS.MI->getFlags();
6523 MatchInfo = [=](MachineIRBuilder &B) {
6524 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6525 FMulMI->getOperand(2).getReg(), RHS.Reg,
6526 LHS.MI->getOperand(1).getReg(),
6527 LHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6528 };
6529 return true;
6530 }
6531
6532 // fold (fadd (fpext (fma x, y, (fmul u, v))), z)
6533 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6534 // FIXME: This turns two single-precision and one double-precision
6535 // operation into two double-precision operations, which might not be
6536 // interesting for all targets, especially GPUs.
6537 if (mi_match(LHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6538 FMAMI->getOpcode() == PreferredFusedOpcode) {
6539 MachineInstr *FMulMI;
6540 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6541 return false;
6542 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6543 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6544 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6545 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6546 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6547 MatchInfo = [=](MachineIRBuilder &B) {
6548 Register X = FMAMI->getOperand(1).getReg();
6549 Register Y = FMAMI->getOperand(2).getReg();
6550 X = B.buildFPExt(DstType, X).getReg(0);
6551 Y = B.buildFPExt(DstType, Y).getReg(0);
6552 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6553 FMulMI->getOperand(2).getReg(), RHS.Reg, X, Y,
6554 InnerFlags, OuterFlags, B);
6555 };
6556
6557 return true;
6558 }
6559 }
6560
6561 // fold (fadd z, (fma x, y, (fpext (fmul u, v)))
6562 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6563 if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6564 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6565 m_GFPExt(m_MInstr(FMulMI))) &&
6566 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6567 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6568 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6569 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6570 unsigned OuterFlags = MI.getFlags() & RHS.MI->getFlags();
6571 MatchInfo = [=](MachineIRBuilder &B) {
6572 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6573 FMulMI->getOperand(2).getReg(), LHS.Reg,
6574 RHS.MI->getOperand(1).getReg(),
6575 RHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6576 };
6577 return true;
6578 }
6579
6580 // fold (fadd z, (fpext (fma x, y, (fmul u, v)))
6581 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6582 // FIXME: This turns two single-precision and one double-precision
6583 // operation into two double-precision operations, which might not be
6584 // interesting for all targets, especially GPUs.
6585 if (mi_match(RHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6586 FMAMI->getOpcode() == PreferredFusedOpcode) {
6587 MachineInstr *FMulMI;
6588 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6589 return false;
6590 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6591 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6592 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6593 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6594 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6595 MatchInfo = [=](MachineIRBuilder &B) {
6596 Register X = FMAMI->getOperand(1).getReg();
6597 Register Y = FMAMI->getOperand(2).getReg();
6598 X = B.buildFPExt(DstType, X).getReg(0);
6599 Y = B.buildFPExt(DstType, Y).getReg(0);
6600 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6601 FMulMI->getOperand(2).getReg(), LHS.Reg, X, Y,
6602 InnerFlags, OuterFlags, B);
6603 };
6604 return true;
6605 }
6606 }
6607
6608 return false;
6609}
6610
6613 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6614 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6615
6616 bool AllowFusionGlobally, HasFMAD, Aggressive;
6617 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6618 return false;
6619
6620 Register Op1 = MI.getOperand(1).getReg();
6621 Register Op2 = MI.getOperand(2).getReg();
6622 MachineInstr *Op1Def, *Op2Def;
6623 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6624 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6625 return false;
6626 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6627 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6628 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6629
6630 // If we have two choices trying to fold (fsub (fmul u, v), (fmul x, y)),
6631 // prefer to fold the multiply with fewer uses.
6632 int FirstMulHasFewerUses = true;
6633 if (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6634 isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6635 hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6636 FirstMulHasFewerUses = false;
6637
6638 unsigned PreferredFusedOpcode =
6639 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6640
6641 // fold (fsub (fmul x, y), z) -> (fma x, y, -z)
6642 if (FirstMulHasFewerUses &&
6643 (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6644 (Aggressive || MRI.hasOneNonDBGUse(LHS.Reg)))) {
6645 unsigned Flags = MI.getFlags() & LHS.MI->getFlags();
6646 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6647 Register NegZ = B.buildFNeg(DstTy, RHS.Reg).getReg(0);
6648 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6649 {LHS.MI->getOperand(1).getReg(),
6650 LHS.MI->getOperand(2).getReg(), NegZ},
6651 Flags);
6652 };
6653 return true;
6654 }
6655 // fold (fsub x, (fmul y, z)) -> (fma -y, z, x)
6656 else if ((isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6657 (Aggressive || MRI.hasOneNonDBGUse(RHS.Reg)))) {
6658 unsigned Flags = MI.getFlags() & RHS.MI->getFlags();
6659 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6660 Register NegY =
6661 B.buildFNeg(DstTy, RHS.MI->getOperand(1).getReg()).getReg(0);
6662 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6663 {NegY, RHS.MI->getOperand(2).getReg(), LHS.Reg}, Flags);
6664 };
6665 return true;
6666 }
6667
6668 return false;
6669}
6670
6673 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6674 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6675
6676 bool AllowFusionGlobally, HasFMAD, Aggressive;
6677 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6678 return false;
6679
6680 Register LHSReg = MI.getOperand(1).getReg();
6681 Register RHSReg = MI.getOperand(2).getReg();
6682 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6683
6684 unsigned PreferredFusedOpcode =
6685 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6686
6687 MachineInstr *FMulMI;
6688 // fold (fsub (fneg (fmul x, y)), z) -> (fma (fneg x), y, (fneg z))
6689 if (mi_match(LHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6690 (Aggressive || (MRI.hasOneNonDBGUse(LHSReg) &&
6691 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6692 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6693 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6694 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6695 Register NegX =
6696 B.buildFNeg(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6697 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6698 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6699 {NegX, FMulMI->getOperand(2).getReg(), NegZ}, Flags);
6700 };
6701 return true;
6702 }
6703
6704 // fold (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x)
6705 if (mi_match(RHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6706 (Aggressive || (MRI.hasOneNonDBGUse(RHSReg) &&
6707 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6708 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6709 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6710 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6711 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6712 {FMulMI->getOperand(1).getReg(),
6713 FMulMI->getOperand(2).getReg(), LHSReg},
6714 Flags);
6715 };
6716 return true;
6717 }
6718
6719 return false;
6720}
6721
6724 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6725 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6726
6727 bool AllowFusionGlobally, HasFMAD, Aggressive;
6728 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6729 return false;
6730
6731 Register LHSReg = MI.getOperand(1).getReg();
6732 Register RHSReg = MI.getOperand(2).getReg();
6733 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6734
6735 unsigned PreferredFusedOpcode =
6736 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6737
6738 MachineInstr *FMulMI;
6739 // fold (fsub (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), (fneg z))
6740 if (mi_match(LHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6741 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6742 (Aggressive || MRI.hasOneNonDBGUse(LHSReg))) {
6743 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6744 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6745 Register FpExtX =
6746 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6747 Register FpExtY =
6748 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6749 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6750 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6751 {FpExtX, FpExtY, NegZ}, Flags);
6752 };
6753 return true;
6754 }
6755
6756 // fold (fsub x, (fpext (fmul y, z))) -> (fma (fneg (fpext y)), (fpext z), x)
6757 if (mi_match(RHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6758 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6759 (Aggressive || MRI.hasOneNonDBGUse(RHSReg))) {
6760 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6761 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6762 Register FpExtY =
6763 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6764 Register NegY = B.buildFNeg(DstTy, FpExtY).getReg(0);
6765 Register FpExtZ =
6766 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6767 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6768 {NegY, FpExtZ, LHSReg}, Flags);
6769 };
6770 return true;
6771 }
6772
6773 return false;
6774}
6775
6778 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6779 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6780
6781 bool AllowFusionGlobally, HasFMAD, Aggressive;
6782 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6783 return false;
6784
6785 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6786 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6787 Register LHSReg = MI.getOperand(1).getReg();
6788 Register RHSReg = MI.getOperand(2).getReg();
6789
6790 unsigned PreferredFusedOpcode =
6791 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6792
6793 auto buildMatchInfo = [=](Register Dst, Register X, Register Y, Register Z,
6794 unsigned Flags, MachineIRBuilder &B) {
6795 Register FpExtX = B.buildFPExt(DstTy, X).getReg(0);
6796 Register FpExtY = B.buildFPExt(DstTy, Y).getReg(0);
6797 B.buildInstr(PreferredFusedOpcode, {Dst}, {FpExtX, FpExtY, Z}, Flags);
6798 };
6799
6800 MachineInstr *FMulMI;
6801 // fold (fsub (fpext (fneg (fmul x, y))), z) ->
6802 // (fneg (fma (fpext x), (fpext y), z))
6803 // fold (fsub (fneg (fpext (fmul x, y))), z) ->
6804 // (fneg (fma (fpext x), (fpext y), z))
6805 if ((mi_match(LHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
6806 mi_match(LHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
6807 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6808 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
6809 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6810 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6811 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6812 Register FMAReg = MRI.createGenericVirtualRegister(DstTy);
6813 buildMatchInfo(FMAReg, FMulMI->getOperand(1).getReg(),
6814 FMulMI->getOperand(2).getReg(), RHSReg, Flags, B);
6815 B.buildFNeg(MI.getOperand(0).getReg(), FMAReg);
6816 };
6817 return true;
6818 }
6819
6820 // fold (fsub x, (fpext (fneg (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
6821 // fold (fsub x, (fneg (fpext (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
6822 if ((mi_match(RHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
6823 mi_match(RHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
6824 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6825 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
6826 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6827 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6828 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6829 buildMatchInfo(MI.getOperand(0).getReg(), FMulMI->getOperand(1).getReg(),
6830 FMulMI->getOperand(2).getReg(), LHSReg, Flags, B);
6831 };
6832 return true;
6833 }
6834
6835 return false;
6836}
6837
6838// Combine multiple FDIVs with the same divisor into multiple FMULs by the
6839// reciprocal.
6840// E.g., (a / Y; b / Y;) -> (recip = 1.0 / Y; a * recip; b * recip)
6842 MachineInstr &MI, SmallVector<MachineInstr *> &MatchInfo) const {
6843 assert(MI.getOpcode() == TargetOpcode::G_FDIV);
6844
6845 Register X = MI.getOperand(1).getReg();
6846 Register Y = MI.getOperand(2).getReg();
6847
6848 if (!MI.getFlag(MachineInstr::MIFlag::FmArcp))
6849 return false;
6850
6851 auto IsOne = [this](Register X) {
6853 return N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne());
6854 };
6855
6856 // Skip if current node is a reciprocal/fneg-reciprocal.
6857 if (IsOne(X))
6858 return false;
6859
6860 // Exit early if the target does not want this transform or if there can't
6861 // possibly be enough uses of the divisor to make the transform worthwhile.
6862 unsigned MinUses = getTargetLowering().combineRepeatedFPDivisors();
6863 if (!MinUses)
6864 return false;
6865
6866 // Find all FDIV users of the same divisor. For the moment we limit all
6867 // instructions to a single BB and use the first Instr in MatchInfo as the
6868 // dominating position.
6869 MatchInfo.push_back(&MI);
6870 for (auto &U : MRI.use_nodbg_instructions(Y)) {
6871 if (&U == &MI || U.getParent() != MI.getParent())
6872 continue;
6873 if (U.getOpcode() == TargetOpcode::G_FDIV &&
6874 U.getOperand(2).getReg() == Y && U.getOperand(1).getReg() != Y &&
6875 !IsOne(U.getOperand(1).getReg())) {
6876 // This division is eligible for optimization only if global unsafe math
6877 // is enabled or if this division allows reciprocal formation.
6878 if (U.getFlag(MachineInstr::MIFlag::FmArcp)) {
6879 MatchInfo.push_back(&U);
6880 if (dominates(U, *MatchInfo[0]))
6881 std::swap(MatchInfo[0], MatchInfo.back());
6882 }
6883 }
6884 }
6885
6886 // Now that we have the actual number of divisor uses, make sure it meets
6887 // the minimum threshold specified by the target.
6888 return MatchInfo.size() >= MinUses;
6889}
6890
6892 SmallVector<MachineInstr *> &MatchInfo) const {
6893 // Generate the new div at the position of the first instruction, that we have
6894 // ensured will dominate all other instructions.
6895 Builder.setInsertPt(*MatchInfo[0]->getParent(), MatchInfo[0]);
6896 LLT Ty = MRI.getType(MatchInfo[0]->getOperand(0).getReg());
6897 auto Div = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0),
6898 MatchInfo[0]->getOperand(2).getReg(),
6899 MatchInfo[0]->getFlags());
6900
6901 // Replace all found div's with fmul instructions.
6902 for (MachineInstr *MI : MatchInfo) {
6903 Builder.setInsertPt(*MI->getParent(), MI);
6904 Builder.buildFMul(MI->getOperand(0).getReg(), MI->getOperand(1).getReg(),
6905 Div->getOperand(0).getReg(), MI->getFlags());
6906 MI->eraseFromParent();
6907 }
6908}
6909
6911 Register &MatchInfo) const {
6912 // This combine folds the following patterns:
6913 //
6914 // G_BUILD_VECTOR_TRUNC (G_BITCAST(x), G_LSHR(G_BITCAST(x), k))
6915 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), G_TRUNC(G_LSHR(G_BITCAST(x), k)))
6916 // into
6917 // x
6918 // if
6919 // k == sizeof(VecEltTy)/2
6920 // type(x) == type(dst)
6921 //
6922 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), undef)
6923 // into
6924 // x
6925 // if
6926 // type(x) == type(dst)
6927
6928 LLT DstVecTy = MRI.getType(MI.getOperand(0).getReg());
6929 LLT DstEltTy = DstVecTy.getElementType();
6930
6931 Register Lo, Hi;
6932
6933 if (mi_match(
6934 MI, MRI,
6936 MatchInfo = Lo;
6937 return MRI.getType(MatchInfo) == DstVecTy;
6938 }
6939
6940 std::optional<ValueAndVReg> ShiftAmount;
6941 const auto LoPattern = m_GBitcast(m_Reg(Lo));
6942 const auto HiPattern = m_GLShr(m_GBitcast(m_Reg(Hi)), m_GCst(ShiftAmount));
6943 if (mi_match(
6944 MI, MRI,
6945 m_any_of(m_GBuildVectorTrunc(LoPattern, HiPattern),
6946 m_GBuildVector(m_GTrunc(LoPattern), m_GTrunc(HiPattern))))) {
6947 if (Lo == Hi && ShiftAmount->Value == DstEltTy.getSizeInBits()) {
6948 MatchInfo = Lo;
6949 return MRI.getType(MatchInfo) == DstVecTy;
6950 }
6951 }
6952
6953 return false;
6954}
6955
6957 Register &MatchInfo) const {
6958 // Replace (G_TRUNC (G_BITCAST (G_BUILD_VECTOR x, y)) with just x
6959 // if type(x) == type(G_TRUNC)
6960 if (!mi_match(MI.getOperand(1).getReg(), MRI,
6961 m_GBitcast(m_GBuildVector(m_Reg(MatchInfo), m_Reg()))))
6962 return false;
6963
6964 return MRI.getType(MatchInfo) == MRI.getType(MI.getOperand(0).getReg());
6965}
6966
6968 Register &MatchInfo) const {
6969 // Replace (G_TRUNC (G_LSHR (G_BITCAST (G_BUILD_VECTOR x, y)), K)) with
6970 // y if K == size of vector element type
6971 std::optional<ValueAndVReg> ShiftAmt;
6972 if (!mi_match(MI.getOperand(1).getReg(), MRI,
6974 m_GCst(ShiftAmt))))
6975 return false;
6976
6977 LLT MatchTy = MRI.getType(MatchInfo);
6978 return ShiftAmt->Value.getZExtValue() == MatchTy.getSizeInBits() &&
6979 MatchTy == MRI.getType(MI.getOperand(0).getReg());
6980}
6981
6982unsigned CombinerHelper::getFPMinMaxOpcForSelect(
6983 CmpInst::Predicate Pred, LLT DstTy,
6984 SelectPatternNaNBehaviour VsNaNRetVal) const {
6985 assert(VsNaNRetVal != SelectPatternNaNBehaviour::NOT_APPLICABLE &&
6986 "Expected a NaN behaviour?");
6987 // Choose an opcode based off of legality or the behaviour when one of the
6988 // LHS/RHS may be NaN.
6989 switch (Pred) {
6990 default:
6991 return 0;
6992 case CmpInst::FCMP_UGT:
6993 case CmpInst::FCMP_UGE:
6994 case CmpInst::FCMP_OGT:
6995 case CmpInst::FCMP_OGE:
6996 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
6997 return TargetOpcode::G_FMAXNUM;
6998 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
6999 return TargetOpcode::G_FMAXIMUM;
7000 if (isLegal({TargetOpcode::G_FMAXNUM, {DstTy}}))
7001 return TargetOpcode::G_FMAXNUM;
7002 if (isLegal({TargetOpcode::G_FMAXIMUM, {DstTy}}))
7003 return TargetOpcode::G_FMAXIMUM;
7004 return 0;
7005 case CmpInst::FCMP_ULT:
7006 case CmpInst::FCMP_ULE:
7007 case CmpInst::FCMP_OLT:
7008 case CmpInst::FCMP_OLE:
7009 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7010 return TargetOpcode::G_FMINNUM;
7011 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7012 return TargetOpcode::G_FMINIMUM;
7013 if (isLegal({TargetOpcode::G_FMINNUM, {DstTy}}))
7014 return TargetOpcode::G_FMINNUM;
7015 if (!isLegal({TargetOpcode::G_FMINIMUM, {DstTy}}))
7016 return 0;
7017 return TargetOpcode::G_FMINIMUM;
7018 }
7019}
7020
7021CombinerHelper::SelectPatternNaNBehaviour
7022CombinerHelper::computeRetValAgainstNaN(Register LHS, Register RHS,
7023 bool IsOrderedComparison) const {
7024 bool LHSSafe = VT->isKnownNeverNaN(LHS);
7025 bool RHSSafe = VT->isKnownNeverNaN(RHS);
7026 // Completely unsafe.
7027 if (!LHSSafe && !RHSSafe)
7028 return SelectPatternNaNBehaviour::NOT_APPLICABLE;
7029 if (LHSSafe && RHSSafe)
7030 return SelectPatternNaNBehaviour::RETURNS_ANY;
7031 // An ordered comparison will return false when given a NaN, so it
7032 // returns the RHS.
7033 if (IsOrderedComparison)
7034 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_NAN
7035 : SelectPatternNaNBehaviour::RETURNS_OTHER;
7036 // An unordered comparison will return true when given a NaN, so it
7037 // returns the LHS.
7038 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_OTHER
7039 : SelectPatternNaNBehaviour::RETURNS_NAN;
7040}
7041
7042bool CombinerHelper::matchFPSelectToMinMax(Register Dst, Register Cond,
7043 Register TrueVal, Register FalseVal,
7044 BuildFnTy &MatchInfo) const {
7045 // Match: select (fcmp cond x, y) x, y
7046 // select (fcmp cond x, y) y, x
7047 // And turn it into fminnum/fmaxnum or fmin/fmax based off of the condition.
7048 LLT DstTy = MRI.getType(Dst);
7049 // Bail out early on pointers, since we'll never want to fold to a min/max.
7050 if (DstTy.isPointer())
7051 return false;
7052 // Match a floating point compare with a less-than/greater-than predicate.
7053 // TODO: Allow multiple users of the compare if they are all selects.
7055 Register CmpLHS, CmpRHS;
7056 if (!mi_match(
7057 Cond, MRI,
7058 m_OneUse(m_GFCmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS)))) ||
7060 return false;
7061 SelectPatternNaNBehaviour ResWithKnownNaNInfo =
7062 computeRetValAgainstNaN(CmpLHS, CmpRHS, CmpInst::isOrdered(Pred));
7063 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::NOT_APPLICABLE)
7064 return false;
7065 if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
7066 std::swap(CmpLHS, CmpRHS);
7068 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_NAN)
7069 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_OTHER;
7070 else if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_OTHER)
7071 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_NAN;
7072 }
7073 if (TrueVal != CmpLHS || FalseVal != CmpRHS)
7074 return false;
7075 // Decide what type of max/min this should be based off of the predicate.
7076 unsigned Opc = getFPMinMaxOpcForSelect(Pred, DstTy, ResWithKnownNaNInfo);
7077 if (!Opc || !isLegal({Opc, {DstTy}}))
7078 return false;
7079 // Comparisons between signed zero and zero may have different results...
7080 // unless we have fmaximum/fminimum. In that case, we know -0 < 0.
7081 if (Opc != TargetOpcode::G_FMAXIMUM && Opc != TargetOpcode::G_FMINIMUM) {
7082 // We don't know if a comparison between two 0s will give us a consistent
7083 // result. Be conservative and only proceed if at least one side is
7084 // non-zero.
7085 auto KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpLHS, MRI);
7086 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero()) {
7087 KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpRHS, MRI);
7088 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero())
7089 return false;
7090 }
7091 }
7092 MatchInfo = [=](MachineIRBuilder &B) {
7093 B.buildInstr(Opc, {Dst}, {CmpLHS, CmpRHS});
7094 };
7095 return true;
7096}
7097
7099 BuildFnTy &MatchInfo) const {
7100 // TODO: Handle integer cases.
7101 assert(MI.getOpcode() == TargetOpcode::G_SELECT);
7102 // Condition may be fed by a truncated compare.
7103 Register Cond = MI.getOperand(1).getReg();
7104 Register MaybeTrunc;
7105 if (mi_match(Cond, MRI, m_OneUse(m_GTrunc(m_Reg(MaybeTrunc)))))
7106 Cond = MaybeTrunc;
7107 Register Dst = MI.getOperand(0).getReg();
7108 Register TrueVal = MI.getOperand(2).getReg();
7109 Register FalseVal = MI.getOperand(3).getReg();
7110 return matchFPSelectToMinMax(Dst, Cond, TrueVal, FalseVal, MatchInfo);
7111}
7112
7114 BuildFnTy &MatchInfo) const {
7115 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
7116 // (X + Y) == X --> Y == 0
7117 // (X + Y) != X --> Y != 0
7118 // (X - Y) == X --> Y == 0
7119 // (X - Y) != X --> Y != 0
7120 // (X ^ Y) == X --> Y == 0
7121 // (X ^ Y) != X --> Y != 0
7122 Register Dst = MI.getOperand(0).getReg();
7123 CmpInst::Predicate Pred;
7124 Register X, Y, OpLHS, OpRHS;
7125 bool MatchedSub = mi_match(
7126 Dst, MRI,
7127 m_c_GICmp(m_Pred(Pred), m_Reg(X), m_GSub(m_Reg(OpLHS), m_Reg(Y))));
7128 if (MatchedSub && X != OpLHS)
7129 return false;
7130 if (!MatchedSub) {
7131 if (!mi_match(Dst, MRI,
7132 m_c_GICmp(m_Pred(Pred), m_Reg(X),
7133 m_any_of(m_GAdd(m_Reg(OpLHS), m_Reg(OpRHS)),
7134 m_GXor(m_Reg(OpLHS), m_Reg(OpRHS))))))
7135 return false;
7136 Y = X == OpLHS ? OpRHS : X == OpRHS ? OpLHS : Register();
7137 }
7138 MatchInfo = [=](MachineIRBuilder &B) {
7139 auto Zero = B.buildConstant(MRI.getType(Y), 0);
7140 B.buildICmp(Pred, Dst, Y, Zero);
7141 };
7142 return CmpInst::isEquality(Pred) && Y.isValid();
7143}
7144
7145/// Return the minimum useless shift amount that results in complete loss of the
7146/// source value. Return std::nullopt when it cannot determine a value.
7147static std::optional<unsigned>
7148getMinUselessShift(KnownBits ValueKB, unsigned Opcode,
7149 std::optional<int64_t> &Result) {
7150 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR ||
7151 Opcode == TargetOpcode::G_ASHR) &&
7152 "Expect G_SHL, G_LSHR or G_ASHR.");
7153 auto SignificantBits = 0;
7154 switch (Opcode) {
7155 case TargetOpcode::G_SHL:
7156 SignificantBits = ValueKB.countMinTrailingZeros();
7157 Result = 0;
7158 break;
7159 case TargetOpcode::G_LSHR:
7160 Result = 0;
7161 SignificantBits = ValueKB.countMinLeadingZeros();
7162 break;
7163 case TargetOpcode::G_ASHR:
7164 if (ValueKB.isNonNegative()) {
7165 SignificantBits = ValueKB.countMinLeadingZeros();
7166 Result = 0;
7167 } else if (ValueKB.isNegative()) {
7168 SignificantBits = ValueKB.countMinLeadingOnes();
7169 Result = -1;
7170 } else {
7171 // Cannot determine shift result.
7172 Result = std::nullopt;
7173 }
7174 break;
7175 default:
7176 break;
7177 }
7178 return ValueKB.getBitWidth() - SignificantBits;
7179}
7180
7182 BuildFnTy &MatchInfo) const {
7183 Register Dst = MI.getOperand(0).getReg();
7184 Register ShiftVal = MI.getOperand(1).getReg();
7185 Register ShiftReg = MI.getOperand(2).getReg();
7186 LLT ResTy = MRI.getType(Dst);
7187 std::optional<int64_t> Result;
7188 auto IsShiftTooBig = [&](const Constant *C) {
7189 auto *CI = dyn_cast<ConstantInt>(C);
7190 if (!CI)
7191 return false;
7192 if (CI->uge(ResTy.getScalarSizeInBits())) {
7193 Result = std::nullopt;
7194 return true;
7195 }
7196 auto OptMaxUsefulShift =
7197 getMinUselessShift(VT->getKnownBits(ShiftVal), MI.getOpcode(), Result);
7198 return OptMaxUsefulShift && CI->uge(*OptMaxUsefulShift);
7199 };
7200 if (!matchUnaryPredicate(MRI, ShiftReg, IsShiftTooBig))
7201 return false;
7202
7203 if (!Result) {
7204 MatchInfo = [Dst](MachineIRBuilder &B) { B.buildUndef(Dst); };
7205 return true;
7206 }
7207
7208 int64_t Val = *Result;
7209 MatchInfo = [Dst, Val](MachineIRBuilder &B) { B.buildConstant(Dst, Val); };
7210 return true;
7211}
7212
7214 unsigned LHSOpndIdx = 1;
7215 unsigned RHSOpndIdx = 2;
7216 switch (MI.getOpcode()) {
7217 case TargetOpcode::G_UADDO:
7218 case TargetOpcode::G_SADDO:
7219 case TargetOpcode::G_UMULO:
7220 case TargetOpcode::G_SMULO:
7221 LHSOpndIdx = 2;
7222 RHSOpndIdx = 3;
7223 break;
7224 default:
7225 break;
7226 }
7227 Register LHS = MI.getOperand(LHSOpndIdx).getReg();
7228 Register RHS = MI.getOperand(RHSOpndIdx).getReg();
7229 MachineInstr *LHSDef, *RHSDef;
7230 if (!mi_match(LHS, MRI, m_MInstr(LHSDef)) ||
7231 !mi_match(RHS, MRI, m_MInstr(RHSDef)))
7232 return false;
7233
7234 if (!getIConstantVRegVal(LHS, MRI)) {
7235 // Skip commuting if LHS is not a constant. But, LHS may be a
7236 // G_CONSTANT_FOLD_BARRIER. If so we commute as long as we don't already
7237 // have a constant on the RHS.
7238 if (LHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER)
7239 return false;
7240 }
7241 // Commute as long as RHS is not a constant or G_CONSTANT_FOLD_BARRIER.
7242 return RHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER &&
7243 !getIConstantVRegVal(RHS, MRI);
7244}
7245
7247 Register LHS = MI.getOperand(1).getReg();
7248 Register RHS = MI.getOperand(2).getReg();
7249 std::optional<FPValueAndVReg> ValAndVReg;
7250 if (!mi_match(LHS, MRI, m_GFCstOrSplat(ValAndVReg)))
7251 return false;
7252 return !mi_match(RHS, MRI, m_GFCstOrSplat(ValAndVReg));
7253}
7254
7255bool CombinerHelper::isOneOrOneSplat(Register Src, bool AllowUndefs) const {
7256 LLT SrcTy = MRI.getType(Src);
7257 if (SrcTy.isFixedVector())
7258 return isConstantSplatVector(Src, 1, AllowUndefs);
7259 if (SrcTy.isScalar()) {
7260 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7261 return true;
7262 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7263 return IConstant && IConstant->Value == 1;
7264 }
7265 return false; // scalable vector
7266}
7267
7268bool CombinerHelper::isZeroOrZeroSplat(Register Src, bool AllowUndefs) const {
7269 LLT SrcTy = MRI.getType(Src);
7270 if (SrcTy.isFixedVector())
7271 return isConstantSplatVector(Src, 0, AllowUndefs);
7272 if (SrcTy.isScalar()) {
7273 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7274 return true;
7275 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7276 return IConstant && IConstant->Value == 0;
7277 }
7278 return false; // scalable vector
7279}
7280
7281// Ignores COPYs during conformance checks.
7282// FIXME scalable vectors.
7283bool CombinerHelper::isConstantSplatVector(Register Src, int64_t SplatValue,
7284 bool AllowUndefs) const {
7285 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7286 if (!BuildVector)
7287 return false;
7288 unsigned NumSources = BuildVector->getNumSources();
7289
7290 for (unsigned I = 0; I < NumSources; ++I) {
7291 GImplicitDef *ImplicitDef =
7293 if (ImplicitDef && AllowUndefs)
7294 continue;
7295 if (ImplicitDef && !AllowUndefs)
7296 return false;
7297 std::optional<ValueAndVReg> IConstant =
7299 if (IConstant && IConstant->Value == SplatValue)
7300 continue;
7301 return false;
7302 }
7303 return true;
7304}
7305
7306// Ignores COPYs during lookups.
7307// FIXME scalable vectors
7308std::optional<APInt>
7309CombinerHelper::getConstantOrConstantSplatVector(Register Src) const {
7310 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7311 if (IConstant)
7312 return IConstant->Value;
7313
7314 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7315 if (!BuildVector)
7316 return std::nullopt;
7317 unsigned NumSources = BuildVector->getNumSources();
7318
7319 std::optional<APInt> Value = std::nullopt;
7320 for (unsigned I = 0; I < NumSources; ++I) {
7321 std::optional<ValueAndVReg> IConstant =
7323 if (!IConstant)
7324 return std::nullopt;
7325 if (!Value)
7326 Value = IConstant->Value;
7327 else if (*Value != IConstant->Value)
7328 return std::nullopt;
7329 }
7330 return Value;
7331}
7332
7333// FIXME G_SPLAT_VECTOR
7334bool CombinerHelper::isConstantOrConstantVectorI(Register Src) const {
7335 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7336 if (IConstant)
7337 return true;
7338
7339 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7340 if (!BuildVector)
7341 return false;
7342
7343 unsigned NumSources = BuildVector->getNumSources();
7344 for (unsigned I = 0; I < NumSources; ++I) {
7345 std::optional<ValueAndVReg> IConstant =
7347 if (!IConstant)
7348 return false;
7349 }
7350 return true;
7351}
7352
7353// TODO: use knownbits to determine zeros
7354bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
7355 BuildFnTy &MatchInfo) const {
7356 uint32_t Flags = Select->getFlags();
7357 Register Dest = Select->getReg(0);
7358 Register Cond = Select->getCondReg();
7359 Register True = Select->getTrueReg();
7360 Register False = Select->getFalseReg();
7361 LLT CondTy = MRI.getType(Select->getCondReg());
7362 LLT TrueTy = MRI.getType(Select->getTrueReg());
7363
7364 // We only do this combine for scalar boolean conditions.
7365 if (CondTy != LLT::scalar(1))
7366 return false;
7367
7368 if (TrueTy.isPointer())
7369 return false;
7370
7371 // Both are scalars.
7372 std::optional<ValueAndVReg> TrueOpt =
7374 std::optional<ValueAndVReg> FalseOpt =
7376
7377 if (!TrueOpt || !FalseOpt)
7378 return false;
7379
7380 APInt TrueValue = TrueOpt->Value;
7381 APInt FalseValue = FalseOpt->Value;
7382
7383 // select Cond, 1, 0 --> zext (Cond)
7384 if (TrueValue.isOne() && FalseValue.isZero()) {
7385 MatchInfo = [=](MachineIRBuilder &B) {
7386 B.setInstrAndDebugLoc(*Select);
7387 B.buildZExtOrTrunc(Dest, Cond);
7388 };
7389 return true;
7390 }
7391
7392 // select Cond, -1, 0 --> sext (Cond)
7393 if (TrueValue.isAllOnes() && FalseValue.isZero()) {
7394 MatchInfo = [=](MachineIRBuilder &B) {
7395 B.setInstrAndDebugLoc(*Select);
7396 B.buildSExtOrTrunc(Dest, Cond);
7397 };
7398 return true;
7399 }
7400
7401 // select Cond, 0, 1 --> zext (!Cond)
7402 if (TrueValue.isZero() && FalseValue.isOne()) {
7403 MatchInfo = [=](MachineIRBuilder &B) {
7404 B.setInstrAndDebugLoc(*Select);
7405 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7406 B.buildNot(Inner, Cond);
7407 B.buildZExtOrTrunc(Dest, Inner);
7408 };
7409 return true;
7410 }
7411
7412 // select Cond, 0, -1 --> sext (!Cond)
7413 if (TrueValue.isZero() && FalseValue.isAllOnes()) {
7414 MatchInfo = [=](MachineIRBuilder &B) {
7415 B.setInstrAndDebugLoc(*Select);
7416 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7417 B.buildNot(Inner, Cond);
7418 B.buildSExtOrTrunc(Dest, Inner);
7419 };
7420 return true;
7421 }
7422
7423 // select Cond, C1, C1-1 --> add (zext Cond), C1-1
7424 if (TrueValue - 1 == FalseValue) {
7425 MatchInfo = [=](MachineIRBuilder &B) {
7426 B.setInstrAndDebugLoc(*Select);
7427 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7428 B.buildZExtOrTrunc(Inner, Cond);
7429 B.buildAdd(Dest, Inner, False);
7430 };
7431 return true;
7432 }
7433
7434 // select Cond, C1, C1+1 --> add (sext Cond), C1+1
7435 if (TrueValue + 1 == FalseValue) {
7436 MatchInfo = [=](MachineIRBuilder &B) {
7437 B.setInstrAndDebugLoc(*Select);
7438 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7439 B.buildSExtOrTrunc(Inner, Cond);
7440 B.buildAdd(Dest, Inner, False);
7441 };
7442 return true;
7443 }
7444
7445 // select Cond, Pow2, 0 --> (zext Cond) << log2(Pow2)
7446 if (TrueValue.isPowerOf2() && FalseValue.isZero()) {
7447 MatchInfo = [=](MachineIRBuilder &B) {
7448 B.setInstrAndDebugLoc(*Select);
7449 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7450 B.buildZExtOrTrunc(Inner, Cond);
7451 // The shift amount must be scalar.
7452 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7453 auto ShAmtC = B.buildConstant(ShiftTy, TrueValue.exactLogBase2());
7454 B.buildShl(Dest, Inner, ShAmtC, Flags);
7455 };
7456 return true;
7457 }
7458
7459 // select Cond, 0, Pow2 --> (zext (!Cond)) << log2(Pow2)
7460 if (FalseValue.isPowerOf2() && TrueValue.isZero()) {
7461 MatchInfo = [=](MachineIRBuilder &B) {
7462 B.setInstrAndDebugLoc(*Select);
7463 Register Not = MRI.createGenericVirtualRegister(CondTy);
7464 B.buildNot(Not, Cond);
7465 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7466 B.buildZExtOrTrunc(Inner, Not);
7467 // The shift amount must be scalar.
7468 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7469 auto ShAmtC = B.buildConstant(ShiftTy, FalseValue.exactLogBase2());
7470 B.buildShl(Dest, Inner, ShAmtC, Flags);
7471 };
7472 return true;
7473 }
7474
7475 // select Cond, -1, C --> or (sext Cond), C
7476 if (TrueValue.isAllOnes()) {
7477 MatchInfo = [=](MachineIRBuilder &B) {
7478 B.setInstrAndDebugLoc(*Select);
7479 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7480 B.buildSExtOrTrunc(Inner, Cond);
7481 B.buildOr(Dest, Inner, False, Flags);
7482 };
7483 return true;
7484 }
7485
7486 // select Cond, C, -1 --> or (sext (not Cond)), C
7487 if (FalseValue.isAllOnes()) {
7488 MatchInfo = [=](MachineIRBuilder &B) {
7489 B.setInstrAndDebugLoc(*Select);
7490 Register Not = MRI.createGenericVirtualRegister(CondTy);
7491 B.buildNot(Not, Cond);
7492 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7493 B.buildSExtOrTrunc(Inner, Not);
7494 B.buildOr(Dest, Inner, True, Flags);
7495 };
7496 return true;
7497 }
7498
7499 return false;
7500}
7501
7502// TODO: use knownbits to determine zeros
7503bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
7504 BuildFnTy &MatchInfo) const {
7505 uint32_t Flags = Select->getFlags();
7506 Register DstReg = Select->getReg(0);
7507 Register Cond = Select->getCondReg();
7508 Register True = Select->getTrueReg();
7509 Register False = Select->getFalseReg();
7510 LLT CondTy = MRI.getType(Select->getCondReg());
7511 LLT TrueTy = MRI.getType(Select->getTrueReg());
7512
7513 // Boolean or fixed vector of booleans.
7514 if (CondTy.isScalableVector() ||
7515 (CondTy.isFixedVector() &&
7516 CondTy.getElementType().getScalarSizeInBits() != 1) ||
7517 CondTy.getScalarSizeInBits() != 1)
7518 return false;
7519
7520 if (CondTy != TrueTy)
7521 return false;
7522
7523 // select Cond, Cond, F --> or Cond, F
7524 // select Cond, 1, F --> or Cond, F
7525 if ((Cond == True) || isOneOrOneSplat(True, /* AllowUndefs */ true)) {
7526 MatchInfo = [=](MachineIRBuilder &B) {
7527 B.setInstrAndDebugLoc(*Select);
7528 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7529 B.buildZExtOrTrunc(Ext, Cond);
7530 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7531 B.buildOr(DstReg, Ext, FreezeFalse, Flags);
7532 };
7533 return true;
7534 }
7535
7536 // select Cond, T, Cond --> and Cond, T
7537 // select Cond, T, 0 --> and Cond, T
7538 if ((Cond == False) || isZeroOrZeroSplat(False, /* AllowUndefs */ true)) {
7539 MatchInfo = [=](MachineIRBuilder &B) {
7540 B.setInstrAndDebugLoc(*Select);
7541 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7542 B.buildZExtOrTrunc(Ext, Cond);
7543 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7544 B.buildAnd(DstReg, Ext, FreezeTrue);
7545 };
7546 return true;
7547 }
7548
7549 // select Cond, T, 1 --> or (not Cond), T
7550 if (isOneOrOneSplat(False, /* AllowUndefs */ true)) {
7551 MatchInfo = [=](MachineIRBuilder &B) {
7552 B.setInstrAndDebugLoc(*Select);
7553 // First the not.
7554 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7555 B.buildNot(Inner, Cond);
7556 // Then an ext to match the destination register.
7557 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7558 B.buildZExtOrTrunc(Ext, Inner);
7559 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7560 B.buildOr(DstReg, Ext, FreezeTrue, Flags);
7561 };
7562 return true;
7563 }
7564
7565 // select Cond, 0, F --> and (not Cond), F
7566 if (isZeroOrZeroSplat(True, /* AllowUndefs */ true)) {
7567 MatchInfo = [=](MachineIRBuilder &B) {
7568 B.setInstrAndDebugLoc(*Select);
7569 // First the not.
7570 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7571 B.buildNot(Inner, Cond);
7572 // Then an ext to match the destination register.
7573 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7574 B.buildZExtOrTrunc(Ext, Inner);
7575 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7576 B.buildAnd(DstReg, Ext, FreezeFalse);
7577 };
7578 return true;
7579 }
7580
7581 return false;
7582}
7583
7585 BuildFnTy &MatchInfo) const {
7586 Register DstReg = MO.getReg();
7587 Register CondReg, True, False;
7588 if (!mi_match(DstReg, MRI,
7589 m_GISelect(m_Reg(CondReg), m_Reg(True), m_Reg(False))))
7590 return false;
7591
7592 CmpInst::Predicate Pred;
7593 Register CmpLHS, CmpRHS;
7594 if (!mi_match(CondReg, MRI,
7595 m_GICmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS))))
7596 return false;
7597
7598 LLT DstTy = MRI.getType(DstReg);
7599 if (DstTy.isPointerOrPointerVector())
7600 return false;
7601
7602 // We want to fold the icmp and replace the select.
7603 if (!MRI.hasOneNonDBGUse(CondReg))
7604 return false;
7605
7606 // We need a larger or smaller predicate for
7607 // canonicalization.
7608 if (CmpInst::isEquality(Pred))
7609 return false;
7610
7611 // We can swap CmpLHS and CmpRHS for higher hitrate.
7612 if (True == CmpRHS && False == CmpLHS) {
7613 std::swap(CmpLHS, CmpRHS);
7614 Pred = CmpInst::getSwappedPredicate(Pred);
7615 }
7616
7617 // (icmp X, Y) ? X : Y -> integer minmax.
7618 // see matchSelectPattern in ValueTracking.
7619 // Legality between G_SELECT and integer minmax can differ.
7620 if (True != CmpLHS || False != CmpRHS)
7621 return false;
7622
7623 switch (Pred) {
7624 case ICmpInst::ICMP_UGT:
7625 case ICmpInst::ICMP_UGE: {
7626 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy}))
7627 return false;
7628 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMax(DstReg, True, False); };
7629 return true;
7630 }
7631 case ICmpInst::ICMP_SGT:
7632 case ICmpInst::ICMP_SGE: {
7633 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy}))
7634 return false;
7635 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMax(DstReg, True, False); };
7636 return true;
7637 }
7638 case ICmpInst::ICMP_ULT:
7639 case ICmpInst::ICMP_ULE: {
7640 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy}))
7641 return false;
7642 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMin(DstReg, True, False); };
7643 return true;
7644 }
7645 case ICmpInst::ICMP_SLT:
7646 case ICmpInst::ICMP_SLE: {
7647 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy}))
7648 return false;
7649 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(DstReg, True, False); };
7650 return true;
7651 }
7652 default:
7653 return false;
7654 }
7655}
7656
7657// (neg (min/max x, (neg x))) --> (max/min x, (neg x))
7659 BuildFnTy &MatchInfo) const {
7660 assert(MI.getOpcode() == TargetOpcode::G_SUB);
7661 Register DestReg = MI.getOperand(0).getReg();
7662 LLT DestTy = MRI.getType(DestReg);
7663
7664 Register X;
7665 Register Sub0;
7666 auto NegPattern = m_all_of(m_Neg(m_DeferredReg(X)), m_Reg(Sub0));
7667 if (mi_match(DestReg, MRI,
7668 m_Neg(m_OneUse(m_any_of(m_GSMin(m_Reg(X), NegPattern),
7669 m_GSMax(m_Reg(X), NegPattern),
7670 m_GUMin(m_Reg(X), NegPattern),
7671 m_GUMax(m_Reg(X), NegPattern)))))) {
7672 MachineInstr *MinMaxMI;
7673 if (!mi_match(MI.getOperand(2).getReg(), MRI, m_MInstr(MinMaxMI)))
7674 return false;
7675 unsigned NewOpc = getInverseGMinMaxOpcode(MinMaxMI->getOpcode());
7676 if (isLegal({NewOpc, {DestTy}})) {
7677 MatchInfo = [=](MachineIRBuilder &B) {
7678 B.buildInstr(NewOpc, {DestReg}, {X, Sub0});
7679 };
7680 return true;
7681 }
7682 }
7683
7684 return false;
7685}
7686
7689
7690 if (tryFoldSelectOfConstants(Select, MatchInfo))
7691 return true;
7692
7693 if (tryFoldBoolSelectToLogic(Select, MatchInfo))
7694 return true;
7695
7696 return false;
7697}
7698
7699/// Fold (icmp Pred1 V1, C1) && (icmp Pred2 V2, C2)
7700/// or (icmp Pred1 V1, C1) || (icmp Pred2 V2, C2)
7701/// into a single comparison using range-based reasoning.
7702/// see InstCombinerImpl::foldAndOrOfICmpsUsingRanges.
7703bool CombinerHelper::tryFoldAndOrOrICmpsUsingRanges(
7704 GLogicalBinOp *Logic, BuildFnTy &MatchInfo) const {
7705 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpected xor");
7706 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
7707 Register DstReg = Logic->getReg(0);
7708 Register LHS = Logic->getLHSReg();
7709 Register RHS = Logic->getRHSReg();
7710 unsigned Flags = Logic->getFlags();
7711
7712 // We need an G_ICMP on the LHS register.
7713 GICmp *Cmp1 = getOpcodeDef<GICmp>(LHS, MRI);
7714 if (!Cmp1)
7715 return false;
7716
7717 // We need an G_ICMP on the RHS register.
7718 GICmp *Cmp2 = getOpcodeDef<GICmp>(RHS, MRI);
7719 if (!Cmp2)
7720 return false;
7721
7722 // We want to fold the icmps.
7723 if (!MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
7724 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)))
7725 return false;
7726
7727 APInt C1;
7728 APInt C2;
7729 std::optional<ValueAndVReg> MaybeC1 =
7731 if (!MaybeC1)
7732 return false;
7733 C1 = MaybeC1->Value;
7734
7735 std::optional<ValueAndVReg> MaybeC2 =
7737 if (!MaybeC2)
7738 return false;
7739 C2 = MaybeC2->Value;
7740
7741 Register R1 = Cmp1->getLHSReg();
7742 Register R2 = Cmp2->getLHSReg();
7743 CmpInst::Predicate Pred1 = Cmp1->getCond();
7744 CmpInst::Predicate Pred2 = Cmp2->getCond();
7745 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
7746 LLT CmpOperandTy = MRI.getType(R1);
7747
7748 if (CmpOperandTy.isPointer())
7749 return false;
7750
7751 // We build ands, adds, and constants of type CmpOperandTy.
7752 // They must be legal to build.
7753 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_AND, CmpOperandTy}) ||
7754 !isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, CmpOperandTy}) ||
7755 !isConstantLegalOrBeforeLegalizer(CmpOperandTy))
7756 return false;
7757
7758 // Look through add of a constant offset on R1, R2, or both operands. This
7759 // allows us to interpret the R + C' < C'' range idiom into a proper range.
7760 std::optional<APInt> Offset1;
7761 std::optional<APInt> Offset2;
7762 if (R1 != R2) {
7763 if (GAdd *Add = getOpcodeDef<GAdd>(R1, MRI)) {
7764 std::optional<ValueAndVReg> MaybeOffset1 =
7766 if (MaybeOffset1) {
7767 R1 = Add->getLHSReg();
7768 Offset1 = MaybeOffset1->Value;
7769 }
7770 }
7771 if (GAdd *Add = getOpcodeDef<GAdd>(R2, MRI)) {
7772 std::optional<ValueAndVReg> MaybeOffset2 =
7774 if (MaybeOffset2) {
7775 R2 = Add->getLHSReg();
7776 Offset2 = MaybeOffset2->Value;
7777 }
7778 }
7779 }
7780
7781 if (R1 != R2)
7782 return false;
7783
7784 // We calculate the icmp ranges including maybe offsets.
7785 ConstantRange CR1 = ConstantRange::makeExactICmpRegion(
7786 IsAnd ? ICmpInst::getInversePredicate(Pred1) : Pred1, C1);
7787 if (Offset1)
7788 CR1 = CR1.subtract(*Offset1);
7789
7790 ConstantRange CR2 = ConstantRange::makeExactICmpRegion(
7791 IsAnd ? ICmpInst::getInversePredicate(Pred2) : Pred2, C2);
7792 if (Offset2)
7793 CR2 = CR2.subtract(*Offset2);
7794
7795 bool CreateMask = false;
7796 APInt LowerDiff;
7797 std::optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
7798 if (!CR) {
7799 // We need non-wrapping ranges.
7800 if (CR1.isWrappedSet() || CR2.isWrappedSet())
7801 return false;
7802
7803 // Check whether we have equal-size ranges that only differ by one bit.
7804 // In that case we can apply a mask to map one range onto the other.
7805 LowerDiff = CR1.getLower() ^ CR2.getLower();
7806 APInt UpperDiff = (CR1.getUpper() - 1) ^ (CR2.getUpper() - 1);
7807 APInt CR1Size = CR1.getUpper() - CR1.getLower();
7808 if (!LowerDiff.isPowerOf2() || LowerDiff != UpperDiff ||
7809 CR1Size != CR2.getUpper() - CR2.getLower())
7810 return false;
7811
7812 CR = CR1.getLower().ult(CR2.getLower()) ? CR1 : CR2;
7813 CreateMask = true;
7814 }
7815
7816 if (IsAnd)
7817 CR = CR->inverse();
7818
7819 CmpInst::Predicate NewPred;
7820 APInt NewC, Offset;
7821 CR->getEquivalentICmp(NewPred, NewC, Offset);
7822
7823 // We take the result type of one of the original icmps, CmpTy, for
7824 // the to be build icmp. The operand type, CmpOperandTy, is used for
7825 // the other instructions and constants to be build. The types of
7826 // the parameters and output are the same for add and and. CmpTy
7827 // and the type of DstReg might differ. That is why we zext or trunc
7828 // the icmp into the destination register.
7829
7830 MatchInfo = [=](MachineIRBuilder &B) {
7831 if (CreateMask && Offset != 0) {
7832 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
7833 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
7834 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
7835 auto Add = B.buildAdd(CmpOperandTy, And, OffsetC, Flags);
7836 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7837 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
7838 B.buildZExtOrTrunc(DstReg, ICmp);
7839 } else if (CreateMask && Offset == 0) {
7840 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
7841 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
7842 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7843 auto ICmp = B.buildICmp(NewPred, CmpTy, And, NewCon);
7844 B.buildZExtOrTrunc(DstReg, ICmp);
7845 } else if (!CreateMask && Offset != 0) {
7846 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
7847 auto Add = B.buildAdd(CmpOperandTy, R1, OffsetC, Flags);
7848 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7849 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
7850 B.buildZExtOrTrunc(DstReg, ICmp);
7851 } else if (!CreateMask && Offset == 0) {
7852 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7853 auto ICmp = B.buildICmp(NewPred, CmpTy, R1, NewCon);
7854 B.buildZExtOrTrunc(DstReg, ICmp);
7855 } else {
7856 llvm_unreachable("unexpected configuration of CreateMask and Offset");
7857 }
7858 };
7859 return true;
7860}
7861
7862bool CombinerHelper::tryFoldLogicOfFCmps(GLogicalBinOp *Logic,
7863 BuildFnTy &MatchInfo) const {
7864 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpecte xor");
7865 Register DestReg = Logic->getReg(0);
7866 Register LHS = Logic->getLHSReg();
7867 Register RHS = Logic->getRHSReg();
7868 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
7869
7870 // We need a compare on the LHS register.
7871 GFCmp *Cmp1 = getOpcodeDef<GFCmp>(LHS, MRI);
7872 if (!Cmp1)
7873 return false;
7874
7875 // We need a compare on the RHS register.
7876 GFCmp *Cmp2 = getOpcodeDef<GFCmp>(RHS, MRI);
7877 if (!Cmp2)
7878 return false;
7879
7880 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
7881 LLT CmpOperandTy = MRI.getType(Cmp1->getLHSReg());
7882
7883 // We build one fcmp, want to fold the fcmps, replace the logic op,
7884 // and the fcmps must have the same shape.
7886 {TargetOpcode::G_FCMP, {CmpTy, CmpOperandTy}}) ||
7887 !MRI.hasOneNonDBGUse(Logic->getReg(0)) ||
7888 !MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
7889 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)) ||
7890 MRI.getType(Cmp1->getLHSReg()) != MRI.getType(Cmp2->getLHSReg()))
7891 return false;
7892
7893 CmpInst::Predicate PredL = Cmp1->getCond();
7894 CmpInst::Predicate PredR = Cmp2->getCond();
7895 Register LHS0 = Cmp1->getLHSReg();
7896 Register LHS1 = Cmp1->getRHSReg();
7897 Register RHS0 = Cmp2->getLHSReg();
7898 Register RHS1 = Cmp2->getRHSReg();
7899
7900 if (LHS0 == RHS1 && LHS1 == RHS0) {
7901 // Swap RHS operands to match LHS.
7902 PredR = CmpInst::getSwappedPredicate(PredR);
7903 std::swap(RHS0, RHS1);
7904 }
7905
7906 if (LHS0 == RHS0 && LHS1 == RHS1) {
7907 // We determine the new predicate.
7908 unsigned CmpCodeL = getFCmpCode(PredL);
7909 unsigned CmpCodeR = getFCmpCode(PredR);
7910 unsigned NewPred = IsAnd ? CmpCodeL & CmpCodeR : CmpCodeL | CmpCodeR;
7911 unsigned Flags = Cmp1->getFlags() | Cmp2->getFlags();
7912 MatchInfo = [=](MachineIRBuilder &B) {
7913 // The fcmp predicates fill the lower part of the enum.
7914 FCmpInst::Predicate Pred = static_cast<FCmpInst::Predicate>(NewPred);
7915 if (Pred == FCmpInst::FCMP_FALSE &&
7917 auto False = B.buildConstant(CmpTy, 0);
7918 B.buildZExtOrTrunc(DestReg, False);
7919 } else if (Pred == FCmpInst::FCMP_TRUE &&
7921 auto True =
7922 B.buildConstant(CmpTy, getICmpTrueVal(getTargetLowering(),
7923 CmpTy.isVector() /*isVector*/,
7924 true /*isFP*/));
7925 B.buildZExtOrTrunc(DestReg, True);
7926 } else { // We take the predicate without predicate optimizations.
7927 auto Cmp = B.buildFCmp(Pred, CmpTy, LHS0, LHS1, Flags);
7928 B.buildZExtOrTrunc(DestReg, Cmp);
7929 }
7930 };
7931 return true;
7932 }
7933
7934 return false;
7935}
7936
7938 GAnd *And = cast<GAnd>(&MI);
7939
7940 if (tryFoldAndOrOrICmpsUsingRanges(And, MatchInfo))
7941 return true;
7942
7943 if (tryFoldLogicOfFCmps(And, MatchInfo))
7944 return true;
7945
7946 return false;
7947}
7948
7950 GOr *Or = cast<GOr>(&MI);
7951
7952 if (tryFoldAndOrOrICmpsUsingRanges(Or, MatchInfo))
7953 return true;
7954
7955 if (tryFoldLogicOfFCmps(Or, MatchInfo))
7956 return true;
7957
7958 return false;
7959}
7960
7962 BuildFnTy &MatchInfo) const {
7964
7965 // Addo has no flags
7966 Register Dst = Add->getReg(0);
7967 Register Carry = Add->getReg(1);
7968 Register LHS = Add->getLHSReg();
7969 Register RHS = Add->getRHSReg();
7970 bool IsSigned = Add->isSigned();
7971 LLT DstTy = MRI.getType(Dst);
7972 LLT CarryTy = MRI.getType(Carry);
7973
7974 // Canonicalize constant to RHS.
7975 if (isConstantOrConstantVectorI(LHS) && !isConstantOrConstantVectorI(RHS)) {
7976 if (IsSigned) {
7977 MatchInfo = [=](MachineIRBuilder &B) {
7978 B.buildSAddo(Dst, Carry, RHS, LHS);
7979 };
7980 return true;
7981 }
7982 // !IsSigned
7983 MatchInfo = [=](MachineIRBuilder &B) {
7984 B.buildUAddo(Dst, Carry, RHS, LHS);
7985 };
7986 return true;
7987 }
7988
7989 std::optional<APInt> MaybeLHS = getConstantOrConstantSplatVector(LHS);
7990 std::optional<APInt> MaybeRHS = getConstantOrConstantSplatVector(RHS);
7991
7992 // Fold addo(c1, c2) -> c3, carry.
7993 if (MaybeLHS && MaybeRHS && isConstantLegalOrBeforeLegalizer(DstTy) &&
7995 bool Overflow;
7996 APInt Result = IsSigned ? MaybeLHS->sadd_ov(*MaybeRHS, Overflow)
7997 : MaybeLHS->uadd_ov(*MaybeRHS, Overflow);
7998 MatchInfo = [=](MachineIRBuilder &B) {
7999 B.buildConstant(Dst, Result);
8000 B.buildConstant(Carry, Overflow);
8001 };
8002 return true;
8003 }
8004
8005 // Fold (addo x, 0) -> x, no carry
8006 if (MaybeRHS && *MaybeRHS == 0 && isConstantLegalOrBeforeLegalizer(CarryTy)) {
8007 MatchInfo = [=](MachineIRBuilder &B) {
8008 B.buildCopy(Dst, LHS);
8009 B.buildConstant(Carry, 0);
8010 };
8011 return true;
8012 }
8013
8014 // Given 2 constant operands whose sum does not overflow:
8015 // uaddo (X +nuw C0), C1 -> uaddo X, C0 + C1
8016 // saddo (X +nsw C0), C1 -> saddo X, C0 + C1
8017 GAdd *AddLHS = getOpcodeDef<GAdd>(LHS, MRI);
8018 if (MaybeRHS && AddLHS && MRI.hasOneNonDBGUse(Add->getReg(0)) &&
8019 ((IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoSWrap)) ||
8020 (!IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoUWrap)))) {
8021 std::optional<APInt> MaybeAddRHS =
8022 getConstantOrConstantSplatVector(AddLHS->getRHSReg());
8023 if (MaybeAddRHS) {
8024 bool Overflow;
8025 APInt NewC = IsSigned ? MaybeAddRHS->sadd_ov(*MaybeRHS, Overflow)
8026 : MaybeAddRHS->uadd_ov(*MaybeRHS, Overflow);
8027 if (!Overflow && isConstantLegalOrBeforeLegalizer(DstTy)) {
8028 if (IsSigned) {
8029 MatchInfo = [=](MachineIRBuilder &B) {
8030 auto ConstRHS = B.buildConstant(DstTy, NewC);
8031 B.buildSAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
8032 };
8033 return true;
8034 }
8035 // !IsSigned
8036 MatchInfo = [=](MachineIRBuilder &B) {
8037 auto ConstRHS = B.buildConstant(DstTy, NewC);
8038 B.buildUAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
8039 };
8040 return true;
8041 }
8042 }
8043 };
8044
8045 // We try to combine addo to non-overflowing add.
8046 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}}) ||
8048 return false;
8049
8050 // We try to combine uaddo to non-overflowing add.
8051 if (!IsSigned) {
8052 ConstantRange CRLHS =
8053 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/false);
8054 ConstantRange CRRHS =
8055 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/false);
8056
8057 switch (CRLHS.unsignedAddMayOverflow(CRRHS)) {
8059 return false;
8061 MatchInfo = [=](MachineIRBuilder &B) {
8062 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
8063 B.buildConstant(Carry, 0);
8064 };
8065 return true;
8066 }
8069 MatchInfo = [=](MachineIRBuilder &B) {
8070 B.buildAdd(Dst, LHS, RHS);
8071 B.buildConstant(Carry, 1);
8072 };
8073 return true;
8074 }
8075 }
8076 return false;
8077 }
8078
8079 // We try to combine saddo to non-overflowing add.
8080
8081 // If LHS and RHS each have at least two sign bits, then there is no signed
8082 // overflow.
8083 if (VT->computeNumSignBits(RHS) > 1 && VT->computeNumSignBits(LHS) > 1) {
8084 MatchInfo = [=](MachineIRBuilder &B) {
8085 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8086 B.buildConstant(Carry, 0);
8087 };
8088 return true;
8089 }
8090
8091 ConstantRange CRLHS =
8092 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/true);
8093 ConstantRange CRRHS =
8094 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/true);
8095
8096 switch (CRLHS.signedAddMayOverflow(CRRHS)) {
8098 return false;
8100 MatchInfo = [=](MachineIRBuilder &B) {
8101 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8102 B.buildConstant(Carry, 0);
8103 };
8104 return true;
8105 }
8108 MatchInfo = [=](MachineIRBuilder &B) {
8109 B.buildAdd(Dst, LHS, RHS);
8110 B.buildConstant(Carry, 1);
8111 };
8112 return true;
8113 }
8114 }
8115
8116 return false;
8117}
8118
8120 BuildFnTy &MatchInfo) const {
8122 MatchInfo(Builder);
8123 Root->eraseFromParent();
8124}
8125
8127 int64_t Exponent) const {
8128 bool OptForSize = MI.getMF()->getFunction().hasOptSize();
8130}
8131
8133 int64_t Exponent) const {
8134 auto [Dst, Base] = MI.getFirst2Regs();
8135 LLT Ty = MRI.getType(Dst);
8136 int64_t ExpVal = Exponent;
8137
8138 if (ExpVal == 0) {
8139 Builder.buildFConstant(Dst, 1.0);
8140 MI.removeFromParent();
8141 return;
8142 }
8143
8144 if (ExpVal < 0)
8145 ExpVal = -ExpVal;
8146
8147 // We use the simple binary decomposition method from SelectionDAG ExpandPowI
8148 // to generate the multiply sequence. There are more optimal ways to do this
8149 // (for example, powi(x,15) generates one more multiply than it should), but
8150 // this has the benefit of being both really simple and much better than a
8151 // libcall.
8152 std::optional<SrcOp> Res;
8153 SrcOp CurSquare = Base;
8154 while (ExpVal > 0) {
8155 if (ExpVal & 1) {
8156 if (!Res)
8157 Res = CurSquare;
8158 else
8159 Res = Builder.buildFMul(Ty, *Res, CurSquare);
8160 }
8161
8162 CurSquare = Builder.buildFMul(Ty, CurSquare, CurSquare);
8163 ExpVal >>= 1;
8164 }
8165
8166 // If the original exponent was negative, invert the result, producing
8167 // 1/(x*x*x).
8168 if (Exponent < 0)
8169 Res = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0), *Res,
8170 MI.getFlags());
8171
8172 Builder.buildCopy(Dst, *Res);
8173 MI.eraseFromParent();
8174}
8175
8177 BuildFnTy &MatchInfo) const {
8178 // fold (A+C1)-C2 -> A+(C1-C2)
8179 const GSub *Sub = cast<GSub>(&MI);
8180 Register A, C1Reg;
8181 if (!mi_match(Sub->getLHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8182 return false;
8183
8184 if (!MRI.hasOneNonDBGUse(Sub->getLHSReg()))
8185 return false;
8186
8187 APInt C2 = getIConstantFromReg(Sub->getRHSReg(), MRI);
8188 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8189
8190 Register Dst = Sub->getReg(0);
8191 LLT DstTy = MRI.getType(Dst);
8192
8193 MatchInfo = [=](MachineIRBuilder &B) {
8194 auto Const = B.buildConstant(DstTy, C1 - C2);
8195 B.buildAdd(Dst, A, Const);
8196 };
8197
8198 return true;
8199}
8200
8202 BuildFnTy &MatchInfo) const {
8203 // fold C2-(A+C1) -> (C2-C1)-A
8204 const GSub *Sub = cast<GSub>(&MI);
8205 Register A, C1Reg;
8206 if (!mi_match(Sub->getRHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8207 return false;
8208
8209 if (!MRI.hasOneNonDBGUse(Sub->getRHSReg()))
8210 return false;
8211
8212 APInt C2 = getIConstantFromReg(Sub->getLHSReg(), MRI);
8213 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8214
8215 Register Dst = Sub->getReg(0);
8216 LLT DstTy = MRI.getType(Dst);
8217
8218 MatchInfo = [=](MachineIRBuilder &B) {
8219 auto Const = B.buildConstant(DstTy, C2 - C1);
8220 B.buildSub(Dst, Const, A);
8221 };
8222
8223 return true;
8224}
8225
8227 BuildFnTy &MatchInfo) const {
8228 // fold (A-C1)-C2 -> A-(C1+C2)
8229 const GSub *Sub1 = cast<GSub>(&MI);
8230 Register A, C1Reg;
8231 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8232 return false;
8233
8234 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8235 return false;
8236
8237 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8238 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8239
8240 Register Dst = Sub1->getReg(0);
8241 LLT DstTy = MRI.getType(Dst);
8242
8243 MatchInfo = [=](MachineIRBuilder &B) {
8244 auto Const = B.buildConstant(DstTy, C1 + C2);
8245 B.buildSub(Dst, A, Const);
8246 };
8247
8248 return true;
8249}
8250
8252 BuildFnTy &MatchInfo) const {
8253 // fold (C1-A)-C2 -> (C1-C2)-A
8254 const GSub *Sub1 = cast<GSub>(&MI);
8255 Register C1Reg, A;
8256 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(C1Reg), m_Reg(A))))
8257 return false;
8258
8259 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8260 return false;
8261
8262 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8263 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8264
8265 Register Dst = Sub1->getReg(0);
8266 LLT DstTy = MRI.getType(Dst);
8267
8268 MatchInfo = [=](MachineIRBuilder &B) {
8269 auto Const = B.buildConstant(DstTy, C1 - C2);
8270 B.buildSub(Dst, Const, A);
8271 };
8272
8273 return true;
8274}
8275
8277 BuildFnTy &MatchInfo) const {
8278 // fold ((A-C1)+C2) -> (A+(C2-C1))
8279 const GAdd *Add = cast<GAdd>(&MI);
8280 Register A, C1Reg;
8281 if (!mi_match(Add->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8282 return false;
8283
8284 if (!MRI.hasOneNonDBGUse(Add->getLHSReg()))
8285 return false;
8286
8287 APInt C2 = getIConstantFromReg(Add->getRHSReg(), MRI);
8288 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8289
8290 Register Dst = Add->getReg(0);
8291 LLT DstTy = MRI.getType(Dst);
8292
8293 MatchInfo = [=](MachineIRBuilder &B) {
8294 auto Const = B.buildConstant(DstTy, C2 - C1);
8295 B.buildAdd(Dst, A, Const);
8296 };
8297
8298 return true;
8299}
8300
8302 const MachineInstr &MI, BuildFnTy &MatchInfo) const {
8303 const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
8304
8305 if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
8306 return false;
8307
8308 LLT DstTy = MRI.getType(Unmerge->getReg(0));
8309
8310 // $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
8311 // $any:_(<8 x s16>) = G_ANYEXT $bv
8312 // $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
8313 //
8314 // ->
8315 //
8316 // $any:_(s16) = G_ANYEXT $bv[0]
8317 // $any1:_(s16) = G_ANYEXT $bv[1]
8318 // $any2:_(s16) = G_ANYEXT $bv[2]
8319 // $any3:_(s16) = G_ANYEXT $bv[3]
8320 // $any4:_(s16) = G_ANYEXT $bv[4]
8321 // $any5:_(s16) = G_ANYEXT $bv[5]
8322 // $any6:_(s16) = G_ANYEXT $bv[6]
8323 // $any7:_(s16) = G_ANYEXT $bv[7]
8324 // $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
8325 // $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7
8326
8327 // We want to unmerge into vectors.
8328 if (!DstTy.isFixedVector())
8329 return false;
8330
8331 Register AnySrcReg;
8332 if (!mi_match(Unmerge->getSourceReg(), MRI, m_GAnyExt(m_Reg(AnySrcReg))))
8333 return false;
8334
8335 GBuildVector *BV;
8336 if (mi_match(AnySrcReg, MRI, m_GBuildVector(BV))) {
8337 // G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR
8338
8339 if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
8340 return false;
8341
8342 // FIXME: check element types?
8343 if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
8344 return false;
8345
8346 LLT BigBvTy = MRI.getType(BV->getReg(0));
8347 LLT SmallBvTy = DstTy;
8348 LLT SmallBvElemenTy = SmallBvTy.getElementType();
8349
8351 {TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
8352 return false;
8353
8354 // We check the legality of scalar anyext.
8356 {TargetOpcode::G_ANYEXT,
8357 {SmallBvElemenTy, BigBvTy.getElementType()}}))
8358 return false;
8359
8360 MatchInfo = [=](MachineIRBuilder &B) {
8361 // Build into each G_UNMERGE_VALUES def
8362 // a small build vector with anyext from the source build vector.
8363 for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
8365 for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
8366 Register SourceArray =
8367 BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
8368 auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
8369 Ops.push_back(AnyExt.getReg(0));
8370 }
8371 B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
8372 };
8373 };
8374 return true;
8375 };
8376
8377 return false;
8378}
8379
8381 BuildFnTy &MatchInfo) const {
8382
8383 bool Changed = false;
8384 auto &Shuffle = cast<GShuffleVector>(MI);
8385 ArrayRef<int> OrigMask = Shuffle.getMask();
8386 SmallVector<int, 16> NewMask;
8387 const LLT SrcTy = MRI.getType(Shuffle.getSrc1Reg());
8388 const unsigned NumSrcElems = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
8389 const unsigned NumDstElts = OrigMask.size();
8390 for (unsigned i = 0; i != NumDstElts; ++i) {
8391 int Idx = OrigMask[i];
8392 if (Idx >= (int)NumSrcElems) {
8393 Idx = -1;
8394 Changed = true;
8395 }
8396 NewMask.push_back(Idx);
8397 }
8398
8399 if (!Changed)
8400 return false;
8401
8402 MatchInfo = [&, NewMask = std::move(NewMask)](MachineIRBuilder &B) {
8403 B.buildShuffleVector(MI.getOperand(0), MI.getOperand(1), MI.getOperand(2),
8404 std::move(NewMask));
8405 };
8406
8407 return true;
8408}
8409
8410static void commuteMask(MutableArrayRef<int> Mask, const unsigned NumElems) {
8411 const unsigned MaskSize = Mask.size();
8412 for (unsigned I = 0; I < MaskSize; ++I) {
8413 int Idx = Mask[I];
8414 if (Idx < 0)
8415 continue;
8416
8417 if (Idx < (int)NumElems)
8418 Mask[I] = Idx + NumElems;
8419 else
8420 Mask[I] = Idx - NumElems;
8421 }
8422}
8423
8425 BuildFnTy &MatchInfo) const {
8426
8427 auto &Shuffle = cast<GShuffleVector>(MI);
8428 // If any of the two inputs is already undef, don't check the mask again to
8429 // prevent infinite loop
8430 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(), MRI))
8431 return false;
8432
8433 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI))
8434 return false;
8435
8436 const LLT DstTy = MRI.getType(Shuffle.getReg(0));
8437 const LLT Src1Ty = MRI.getType(Shuffle.getSrc1Reg());
8439 {TargetOpcode::G_SHUFFLE_VECTOR, {DstTy, Src1Ty}}))
8440 return false;
8441
8442 ArrayRef<int> Mask = Shuffle.getMask();
8443 const unsigned NumSrcElems = Src1Ty.getNumElements();
8444
8445 bool TouchesSrc1 = false;
8446 bool TouchesSrc2 = false;
8447 const unsigned NumElems = Mask.size();
8448 for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
8449 if (Mask[Idx] < 0)
8450 continue;
8451
8452 if (Mask[Idx] < (int)NumSrcElems)
8453 TouchesSrc1 = true;
8454 else
8455 TouchesSrc2 = true;
8456 }
8457
8458 if (TouchesSrc1 == TouchesSrc2)
8459 return false;
8460
8461 Register NewSrc1 = Shuffle.getSrc1Reg();
8462 SmallVector<int, 16> NewMask(Mask);
8463 if (TouchesSrc2) {
8464 NewSrc1 = Shuffle.getSrc2Reg();
8465 commuteMask(NewMask, NumSrcElems);
8466 }
8467
8468 MatchInfo = [=, &Shuffle](MachineIRBuilder &B) {
8469 auto Undef = B.buildUndef(Src1Ty);
8470 B.buildShuffleVector(Shuffle.getReg(0), NewSrc1, Undef, NewMask);
8471 };
8472
8473 return true;
8474}
8475
8477 BuildFnTy &MatchInfo) const {
8478 const GSubCarryOut *Subo = cast<GSubCarryOut>(&MI);
8479
8480 Register Dst = Subo->getReg(0);
8481 Register LHS = Subo->getLHSReg();
8482 Register RHS = Subo->getRHSReg();
8483 Register Carry = Subo->getCarryOutReg();
8484 LLT DstTy = MRI.getType(Dst);
8485 LLT CarryTy = MRI.getType(Carry);
8486
8487 // Check legality before known bits.
8488 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy}}) ||
8490 return false;
8491
8492 ConstantRange KBLHS =
8493 ConstantRange::fromKnownBits(VT->getKnownBits(LHS),
8494 /* IsSigned=*/Subo->isSigned());
8495 ConstantRange KBRHS =
8496 ConstantRange::fromKnownBits(VT->getKnownBits(RHS),
8497 /* IsSigned=*/Subo->isSigned());
8498
8499 if (Subo->isSigned()) {
8500 // G_SSUBO
8501 switch (KBLHS.signedSubMayOverflow(KBRHS)) {
8503 return false;
8505 MatchInfo = [=](MachineIRBuilder &B) {
8506 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8507 B.buildConstant(Carry, 0);
8508 };
8509 return true;
8510 }
8513 MatchInfo = [=](MachineIRBuilder &B) {
8514 B.buildSub(Dst, LHS, RHS);
8515 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8516 /*isVector=*/CarryTy.isVector(),
8517 /*isFP=*/false));
8518 };
8519 return true;
8520 }
8521 }
8522 return false;
8523 }
8524
8525 // G_USUBO
8526 switch (KBLHS.unsignedSubMayOverflow(KBRHS)) {
8528 return false;
8530 MatchInfo = [=](MachineIRBuilder &B) {
8531 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
8532 B.buildConstant(Carry, 0);
8533 };
8534 return true;
8535 }
8538 MatchInfo = [=](MachineIRBuilder &B) {
8539 B.buildSub(Dst, LHS, RHS);
8540 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8541 /*isVector=*/CarryTy.isVector(),
8542 /*isFP=*/false));
8543 };
8544 return true;
8545 }
8546 }
8547
8548 return false;
8549}
8550
8551// Fold (ctlz (xor x, (sra x, bitwidth-1))) -> (add (ctls x), 1).
8552// Fold (ctlz (or (shl (xor x, (sra x, bitwidth-1)), 1), 1) -> (ctls x)
8554 BuildFnTy &MatchInfo) const {
8555 assert((CtlzMI.getOpcode() == TargetOpcode::G_CTLZ ||
8556 CtlzMI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON) &&
8557 "Expected G_CTLZ variant");
8558
8559 const Register Dst = CtlzMI.getOperand(0).getReg();
8560 Register Src = CtlzMI.getOperand(1).getReg();
8561
8562 LLT Ty = MRI.getType(Dst);
8563 LLT SrcTy = MRI.getType(Src);
8564
8565 if (!(Ty.isValid() && Ty.isScalar()))
8566 return false;
8567
8568 if (!LI)
8569 return false;
8570
8571 SmallVector<LLT, 2> QueryTypes = {Ty, SrcTy};
8572 LegalityQuery Query(TargetOpcode::G_CTLS, QueryTypes);
8573
8574 switch (LI->getAction(Query).Action) {
8575 default:
8576 return false;
8580 break;
8581 }
8582
8583 // Src = or(shl(V, 1), 1) -> Src=V; NeedAdd = False
8584 Register V;
8585 bool NeedAdd = true;
8586 if (mi_match(Src, MRI,
8588 m_SpecificICst(1))))) {
8589 NeedAdd = false;
8590 Src = V;
8591 }
8592
8593 unsigned BitWidth = Ty.getScalarSizeInBits();
8594
8595 Register X;
8596 if (!mi_match(Src, MRI,
8599 m_SpecificICst(BitWidth - 1)))))))
8600 return false;
8601
8602 MatchInfo = [=](MachineIRBuilder &B) {
8603 if (!NeedAdd) {
8604 B.buildCTLS(Dst, X);
8605 return;
8606 }
8607
8608 auto Ctls = B.buildCTLS(Ty, X);
8609 auto One = B.buildConstant(Ty, 1);
8610
8611 B.buildAdd(Dst, Ctls, One);
8612 };
8613
8614 return true;
8615}
8616
8618 const ConstantFP *C = getConstantFPVRegVal(Reg, MRI);
8619 return C && C->getValueAPF().isNaN();
8620}
8621
8623 unsigned ZeroPoisonOpc) const {
8624 const bool IsCtlzPair = Opc == TargetOpcode::G_CTLZ &&
8625 ZeroPoisonOpc == TargetOpcode::G_CTLZ_ZERO_POISON;
8626 const bool IsCttzPair = Opc == TargetOpcode::G_CTTZ &&
8627 ZeroPoisonOpc == TargetOpcode::G_CTTZ_ZERO_POISON;
8628 if (MI.getOpcode() != Opc || (!IsCtlzPair && !IsCttzPair))
8629 return false;
8630 if (!VT)
8631 return false;
8632
8633 Register Src = MI.getOperand(1).getReg();
8634 if (!VT->isKnownNeverZero(Src))
8635 return false;
8636
8637 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
8638 LLT SrcTy = MRI.getType(Src);
8639 return isLegalOrBeforeLegalizer({ZeroPoisonOpc, {DstTy, SrcTy}});
8640}
8641
8642static APInt getDemandedBitsForLogicalOp(unsigned Opcode, const APInt &Demanded,
8643 const KnownBits &OtherKnown) {
8644 assert((Opcode == TargetOpcode::G_AND || Opcode == TargetOpcode::G_OR) &&
8645 "Expected G_AND or G_OR");
8646 return Demanded &
8647 ~(Opcode == TargetOpcode::G_AND ? OtherKnown.Zero : OtherKnown.One);
8648}
8649
8650static std::optional<unsigned>
8651getValidConstShiftAmt(const std::optional<APInt> &Amt, unsigned BW) {
8652 if (!Amt || Amt->uge(BW))
8653 return std::nullopt;
8654 return Amt->getZExtValue();
8655}
8656
8658 const APInt &DemandedBits,
8659 unsigned ShAmt) {
8660 assert(ShAmt < DemandedBits.getBitWidth() &&
8661 "shift amount must be less than the bit width");
8662 switch (Opcode) {
8663 case TargetOpcode::G_SHL:
8664 return DemandedBits.lshr(ShAmt);
8665 case TargetOpcode::G_LSHR:
8666 return DemandedBits.shl(ShAmt);
8667 case TargetOpcode::G_ASHR: {
8668 APInt Src = DemandedBits.shl(ShAmt);
8669 if (DemandedBits.countLeadingZeros() < ShAmt)
8670 Src.setSignBit();
8671 return Src;
8672 }
8673 default:
8674 llvm_unreachable("not a shift opcode");
8675 }
8676}
8677
8678Register CombinerHelper::simplifyMultipleUseDemandedBits(
8679 Register R, const APInt &DemandedBits, unsigned Depth) const {
8680 assert(R.isVirtual() && "Expected a virtual register");
8681 assert(!DemandedBits.isZero() && "Zero demand is handled by the caller");
8683 return Register();
8684
8685 [[maybe_unused]] LLT Ty = MRI.getType(R);
8686 assert(Ty.isValid() && "Expected a typed register");
8687 assert(DemandedBits.getBitWidth() == Ty.getScalarSizeInBits() &&
8688 "DemandedBits width must match the register scalar type");
8689
8690 MachineInstr *DefMI = MRI.getVRegDef(R);
8691 assert(DefMI && "Expected a definition in generic SSA MIR");
8692 if (!isa<GAnd>(DefMI) && !isa<GOr>(DefMI))
8693 return Register();
8694
8695 unsigned Opcode = DefMI->getOpcode();
8696 auto *Logic = cast<GLogicalBinOp>(DefMI);
8697 Register LHS = Logic->getLHSReg();
8698 Register RHS = Logic->getRHSReg();
8699 assert(MRI.getType(LHS) == Ty && MRI.getType(RHS) == Ty &&
8700 "Logical operands must match the result type");
8701
8702 auto LookThrough = [&](Register X, Register CReg) -> Register {
8703 std::optional<APInt> C = getConstantOrConstantSplatVector(CReg);
8704 if (!C || C->getBitWidth() != DemandedBits.getBitWidth())
8705 return Register();
8706 bool BypassToX = Opcode == TargetOpcode::G_AND
8707 ? DemandedBits.isSubsetOf(*C)
8708 : DemandedBits.isSubsetOf(~*C);
8709 if (BypassToX) {
8710 if (Register Deeper =
8711 simplifyMultipleUseDemandedBits(X, DemandedBits, Depth + 1))
8712 return Deeper;
8713 return X;
8714 }
8715 bool BypassToC = Opcode == TargetOpcode::G_AND
8716 ? DemandedBits.isSubsetOf(~*C)
8717 : DemandedBits.isSubsetOf(*C);
8718 if (BypassToC)
8719 return CReg;
8720 return Register();
8721 };
8722
8723 if (Register Repl = LookThrough(LHS, RHS))
8724 return Repl;
8725 return LookThrough(RHS, LHS);
8726}
8727
8728bool CombinerHelper::simplifyDemandedBitsImpl(MachineInstr &MI, unsigned OpNo,
8729 const APInt &DemandedBits,
8730 KnownBits &Known, unsigned Depth,
8731 bool DoRewrite) const {
8732 Known = KnownBits(DemandedBits.getBitWidth());
8733 assert(MI.getOperand(OpNo).isReg() && !MI.getOperand(OpNo).isDef() &&
8734 "Expected a register use");
8735 Register OpReg = MI.getOperand(OpNo).getReg();
8736 assert(OpReg.isVirtual() && "Expected a virtual register");
8737 LLT OpTy = MRI.getType(OpReg);
8738 assert(OpTy.isValid() && "Expected a typed register");
8739 assert(DemandedBits.getBitWidth() == OpTy.getScalarSizeInBits() &&
8740 "DemandedBits width must match the operand scalar type");
8741
8742 MachineInstr *DefMI = MRI.getVRegDef(OpReg);
8743 assert(DefMI && "Expected a definition in generic SSA MIR");
8744 // Undemanded bits can still affect poison-generating flags in the user.
8745 auto DropPoisonFlags = [&]() {
8746 if (!DoRewrite ||
8748 return;
8749 Observer.changingInstr(MI);
8751 Observer.changedInstr(MI);
8752 };
8753 // Debug users can observe bits that are not demanded by other users.
8754 auto InvalidateDebugUses = [&](const APInt &Demanded) {
8755 if (DoRewrite && !Demanded.isAllOnes())
8756 MRI.markUsesInDebugValueAsUndef(OpReg);
8757 };
8758 auto Rewrite = [&](Register Repl) {
8759 if (!DoRewrite || Repl == OpReg)
8760 return Repl != OpReg;
8761 DropPoisonFlags();
8762 if (DefMI->getNumExplicitDefs() == 1 && MRI.hasOneNonDBGUse(OpReg)) {
8763 InvalidateDebugUses(DemandedBits);
8764 replaceRegWith(MRI, OpReg, Repl);
8765 eraseInst(*DefMI);
8766 } else {
8767 replaceRegOpWith(MRI, MI.getOperand(OpNo), Repl);
8768 }
8769 return true;
8770 };
8771
8772 if (DemandedBits.isZero()) {
8773 if (DefMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
8774 return false;
8775 if (!DoRewrite)
8776 return true;
8777 MachineBasicBlock &SaveMBB = Builder.getMBB();
8778 MachineBasicBlock::iterator SavePt = Builder.getInsertPt();
8779 DebugLoc SaveDL = Builder.getDL();
8780 Builder.setInstrAndDebugLoc(MI);
8781 Register Undef = Builder.buildUndef(OpTy).getReg(0);
8782 Builder.setInsertPt(SaveMBB, SavePt);
8783 Builder.setDebugLoc(SaveDL);
8784 // The producer may have side effects; replace only this use.
8785 DropPoisonFlags();
8786 replaceRegOpWith(MRI, MI.getOperand(OpNo), Undef);
8787 return true;
8788 }
8789
8790 if (!VT)
8791 return false;
8792
8793 unsigned BW = DemandedBits.getBitWidth();
8794 auto GiveUp = [&]() {
8795 APInt DemandedElts = OpTy.isFixedVector()
8797 : APInt(1, 1);
8798 Known = VT->getKnownBits(OpReg, DemandedElts, Depth);
8799 return false;
8800 };
8801
8803 return GiveUp();
8804
8805 // Shared defs require full demand unless this use can be rerouted to an
8806 // existing value that agrees on its demanded bits.
8807 APInt Demanded = DemandedBits;
8808 if (!MRI.hasOneNonDBGUse(OpReg) && !Demanded.isAllOnes()) {
8809 if (Register Repl =
8810 simplifyMultipleUseDemandedBits(OpReg, Demanded, Depth)) {
8811 Known = VT->getKnownBits(Repl);
8812 if (Rewrite(Repl))
8813 return true;
8814 }
8815 Demanded = APInt::getAllOnes(BW);
8816 }
8817
8818 unsigned Opcode = DefMI->getOpcode();
8819 switch (Opcode) {
8820 case TargetOpcode::G_AND:
8821 case TargetOpcode::G_OR: {
8822 auto *Logic = cast<GLogicalBinOp>(DefMI);
8823 Register LHS = Logic->getLHSReg();
8824 Register RHS = Logic->getRHSReg();
8825 assert(MRI.getType(LHS) == OpTy && MRI.getType(RHS) == OpTy &&
8826 "Logical operands must match the result type");
8827 auto SimplifyWithConst = [&](Register X,
8828 Register CReg) -> std::optional<Register> {
8829 std::optional<APInt> C = getConstantOrConstantSplatVector(CReg);
8830 if (!C)
8831 return std::nullopt;
8832 assert(C->getBitWidth() == BW && "Constant width must match its type");
8833 // Check redundancy before rewriting X can change its known bits.
8834 if (Opcode == TargetOpcode::G_AND) {
8835 if (Demanded.isSubsetOf(*C | VT->getKnownBits(X).Zero))
8836 return X;
8837 if (Demanded.isSubsetOf(~*C))
8838 return CReg;
8839 return std::nullopt;
8840 }
8841 if (Demanded.isSubsetOf(~*C | VT->getKnownBits(X).One))
8842 return X;
8843 if (Demanded.isSubsetOf(*C))
8844 return CReg;
8845 return std::nullopt;
8846 };
8847
8848 // Compute known bits before a rewrite can erase the def.
8849 if (std::optional<Register> Repl = SimplifyWithConst(LHS, RHS)) {
8850 Known = VT->getKnownBits(*Repl);
8851 if (Rewrite(*Repl))
8852 return true;
8853 }
8854 if (std::optional<Register> Repl = SimplifyWithConst(RHS, LHS)) {
8855 Known = VT->getKnownBits(*Repl);
8856 if (Rewrite(*Repl))
8857 return true;
8858 }
8859
8860 KnownBits RHSKnown(BW);
8861 bool Changed = simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/2, Demanded,
8862 RHSKnown, Depth + 1, DoRewrite);
8863 APInt LHSDemand = getDemandedBitsForLogicalOp(Opcode, Demanded, RHSKnown);
8864 KnownBits LHSKnown(BW);
8865 Changed |= simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/1, LHSDemand, LHSKnown,
8866 Depth + 1, DoRewrite);
8867 if (!Changed && MRI.hasOneNonDBGUse(RHS) &&
8868 !getConstantOrConstantSplatVector(RHS)) {
8869 // Reduced-demand LHS facts cannot justify reducing the RHS demand.
8870 APInt RHSDemand =
8871 LHSDemand == Demanded
8872 ? getDemandedBitsForLogicalOp(Opcode, Demanded, LHSKnown)
8874 Opcode, Demanded,
8875 VT->getKnownBits(
8876 LHS,
8877 OpTy.isFixedVector()
8878 ? APInt::getAllOnes(OpTy.getNumElements())
8879 : APInt(1, 1),
8880 Depth + 1));
8881 if (RHSDemand != Demanded) {
8882 // Keep full-demand RHS facts if the reduced-demand retry fails.
8883 KnownBits RetryKnown(BW);
8884 Changed = simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/2, RHSDemand,
8885 RetryKnown, Depth + 1, DoRewrite);
8886 }
8887 }
8888 if (Changed) {
8889 DropPoisonFlags();
8890 InvalidateDebugUses(Demanded);
8891 }
8892 Known = Opcode == TargetOpcode::G_AND ? LHSKnown & RHSKnown
8893 : LHSKnown | RHSKnown;
8894 return Changed;
8895 }
8896 case TargetOpcode::G_SHL:
8897 case TargetOpcode::G_LSHR:
8898 case TargetOpcode::G_ASHR: {
8899 std::optional<unsigned> ShAmt = getValidConstShiftAmt(
8900 getConstantOrConstantSplatVector(DefMI->getOperand(2).getReg()), BW);
8901 if (!ShAmt)
8902 return GiveUp();
8903
8904 APInt SrcDemand = getDemandedSrcBitsForShiftConst(Opcode, Demanded, *ShAmt);
8905 KnownBits SrcKnown(BW);
8906 bool Changed = simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/1, SrcDemand,
8907 SrcKnown, Depth + 1, DoRewrite);
8908 if (Changed) {
8909 DropPoisonFlags();
8910 InvalidateDebugUses(Demanded);
8911 }
8912 KnownBits AmtKnown = KnownBits::makeConstant(APInt(BW, *ShAmt));
8913 switch (Opcode) {
8914 case TargetOpcode::G_SHL:
8915 Known = KnownBits::shl(SrcKnown, AmtKnown);
8916 break;
8917 case TargetOpcode::G_LSHR:
8918 Known = KnownBits::lshr(SrcKnown, AmtKnown);
8919 break;
8920 case TargetOpcode::G_ASHR: {
8921 // ASHR and LSHR agree outside sign fill or for nonnegative inputs.
8922 LLT AmtTy = MRI.getType(DefMI->getOperand(2).getReg());
8923 bool LShrLegal = isPreLegalize() || !LI ||
8924 isLegal({TargetOpcode::G_LSHR, {OpTy, AmtTy}});
8925 if ((Demanded.countLeadingZeros() >= *ShAmt ||
8926 SrcKnown.isNonNegative()) &&
8927 LShrLegal) {
8928 if (DoRewrite) {
8929 MachineBasicBlock &SaveMBB = Builder.getMBB();
8930 MachineBasicBlock::iterator SavePt = Builder.getInsertPt();
8931 DebugLoc SaveDL = Builder.getDL();
8932 Builder.setInstrAndDebugLoc(*DefMI);
8933 auto Lshr = Builder.buildLShr(OpTy, DefMI->getOperand(1).getReg(),
8934 DefMI->getOperand(2).getReg());
8935 Builder.setInsertPt(SaveMBB, SavePt);
8936 Builder.setDebugLoc(SaveDL);
8937 Rewrite(Lshr.getReg(0));
8938 Known = KnownBits::lshr(SrcKnown, AmtKnown);
8939 }
8940 return true;
8941 }
8942 Known = KnownBits::ashr(SrcKnown, AmtKnown);
8943 break;
8944 }
8945 }
8946 return Changed;
8947 }
8948 default:
8949 return GiveUp();
8950 }
8951}
8952
8954 const APInt &DemandedBits,
8956 unsigned Depth) const {
8957 return simplifyDemandedBitsImpl(MI, OpNo, DemandedBits, Known, Depth,
8958 /*DoRewrite=*/true);
8959}
8960
8962 BuildFnTy &MatchInfo) const {
8963 Register Dst = MI.getOperand(0).getReg();
8964 LLT Ty = MRI.getType(Dst);
8965 assert(Ty.isValid() && "Expected a typed generic result");
8966 if (!VT || Ty.isVector())
8967 return false;
8968
8969 APInt RootDemand = APInt::getAllOnes(Ty.getScalarSizeInBits());
8970 auto Probe = [&](unsigned OpNo, const APInt &OpDemand, KnownBits &Known) {
8971 if (!simplifyDemandedBitsImpl(MI, OpNo, OpDemand, Known, /*Depth=*/0,
8972 /*DoRewrite=*/false))
8973 return false;
8974
8975 MatchInfo = [this, &MI, OpNo, OpDemand](MachineIRBuilder &) {
8976 KnownBits K(OpDemand.getBitWidth());
8977 simplifyDemandedBits(MI, OpNo, OpDemand, K);
8978 };
8979 return true;
8980 };
8981
8982 unsigned Opcode = MI.getOpcode();
8983 switch (Opcode) {
8984 case TargetOpcode::G_SHL:
8985 case TargetOpcode::G_LSHR:
8986 case TargetOpcode::G_ASHR: {
8987 std::optional<unsigned> ShAmt = getValidConstShiftAmt(
8988 getConstantOrConstantSplatVector(MI.getOperand(2).getReg()),
8989 RootDemand.getBitWidth());
8990 if (!ShAmt)
8991 return false;
8992 APInt SrcDemand =
8993 getDemandedSrcBitsForShiftConst(Opcode, RootDemand, *ShAmt);
8994 KnownBits SrcKnown(RootDemand.getBitWidth());
8995 return Probe(/*OpNo=*/1, SrcDemand, SrcKnown);
8996 }
8997 default:
8998 return false;
8999 case TargetOpcode::G_AND:
9000 case TargetOpcode::G_OR: {
9001 // Let redundant_and/redundant_or fold the root before operand rewrites can
9002 // discard the known bits that make it redundant.
9003 KnownBits L = VT->getKnownBits(MI.getOperand(1).getReg());
9004 KnownBits R = VT->getKnownBits(MI.getOperand(2).getReg());
9005 bool RootRedundant = Opcode == TargetOpcode::G_AND
9006 ? RootDemand.isSubsetOf(L.Zero | R.One) ||
9007 RootDemand.isSubsetOf(R.Zero | L.One)
9008 : RootDemand.isSubsetOf(L.One | R.Zero) ||
9009 RootDemand.isSubsetOf(R.One | L.Zero);
9010 if (RootRedundant)
9011 return false;
9012
9013 KnownBits RHSKnown(RootDemand.getBitWidth());
9014 if (Probe(/*OpNo=*/2, RootDemand, RHSKnown))
9015 return true;
9016
9017 APInt LHSDemand = getDemandedBitsForLogicalOp(Opcode, RootDemand, RHSKnown);
9018
9019 KnownBits LHSKnown(RootDemand.getBitWidth());
9020 if (Probe(/*OpNo=*/1, LHSDemand, LHSKnown))
9021 return true;
9022
9023 Register RHS = MI.getOperand(2).getReg();
9024 if (!MRI.hasOneNonDBGUse(RHS) || getConstantOrConstantSplatVector(RHS))
9025 return false;
9026
9027 APInt RHSDemand =
9028 LHSDemand == RootDemand
9029 ? getDemandedBitsForLogicalOp(Opcode, RootDemand, LHSKnown)
9031 Opcode, RootDemand,
9032 VT->getKnownBits(MI.getOperand(1).getReg()));
9033 KnownBits RetryKnown(RootDemand.getBitWidth());
9034 return RHSDemand != RootDemand && Probe(/*OpNo=*/2, RHSDemand, RetryKnown);
9035 }
9036 }
9037}
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
const TargetLowering & TLI
SDValue Pred
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
uint64_t Imm
AMDGPU Register Bank Select
Rewrite undef for PHI
This file declares a class to represent arbitrary precision floating point values and provide a varie...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static APInt getDemandedBitsForLogicalOp(unsigned Opcode, const APInt &Demanded, const KnownBits &OtherKnown)
static bool hasMoreUses(const MachineInstr &MI0, const MachineInstr &MI1, const MachineRegisterInfo &MRI)
static bool isContractableFMul(MachineInstr &MI, bool AllowFusionGlobally)
Checks if MI is TargetOpcode::G_FMUL and contractable either due to global flags or MachineInstr flag...
static unsigned getIndexedOpc(unsigned LdStOpc)
static std::optional< unsigned > getValidConstShiftAmt(const std::optional< APInt > &Amt, unsigned BW)
static APInt getDemandedSrcBitsForShiftConst(unsigned Opcode, const APInt &DemandedBits, unsigned ShAmt)
static std::optional< std::pair< GZExtLoad *, int64_t > > matchLoadAndBytePosition(Register Reg, unsigned MemSizeInBits, const MachineRegisterInfo &MRI)
Helper function for findLoadOffsetsForLoadOrCombine.
static std::optional< unsigned > getMinUselessShift(KnownBits ValueKB, unsigned Opcode, std::optional< int64_t > &Result)
Return the minimum useless shift amount that results in complete loss of the source value.
static Register peekThroughBitcast(Register Reg, const MachineRegisterInfo &MRI)
static unsigned bigEndianByteAt(const unsigned ByteWidth, const unsigned I)
static cl::opt< bool > ForceLegalIndexing("force-legal-indexing", cl::Hidden, cl::init(false), cl::desc("Force all indexed operations to be " "legal for the GlobalISel combiner"))
static void commuteMask(MutableArrayRef< int > Mask, const unsigned NumElems)
static cl::opt< unsigned > PostIndexUseThreshold("post-index-use-threshold", cl::Hidden, cl::init(32), cl::desc("Number of uses of a base pointer to check before it is no longer " "considered for post-indexing."))
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
static bool vectorFPFoldUsesIEEEDenormals(const MachineFunction &MF, LLT Ty)
static unsigned getExtLoadOpcForExtend(unsigned ExtOpc)
static bool isConstValidTrue(const TargetLowering &TLI, unsigned ScalarSizeBits, int64_t Cst, bool IsVector, bool IsFP)
static LLT getMidVTForTruncRightShiftCombine(LLT ShiftTy, LLT TruncTy)
static bool canFoldInAddressingMode(GLoadStore *MI, const TargetLowering &TLI, MachineRegisterInfo &MRI)
Return true if 'MI' is a load or a store that may be fold it's address operand into the load / store ...
static unsigned littleEndianByteAt(const unsigned ByteWidth, const unsigned I)
static Register buildLogBase2(Register V, MachineIRBuilder &MIB)
Determines the LogBase2 value for a non-null input value using the transform: LogBase2(V) = (EltBits ...
This contains common combine transformations that may be used in a combine pass,or by the target else...
Utilities for dealing with flags related to floating point properties and mode controls.
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
#define _
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Interface for Targets to specify which operations they can successfully select and how the others sho...
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
Implement a low-level type suitable for MachineInstr level instruction selection.
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register Reg
#define R2(n)
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
SmallVector< MachineOperand, 4 > Cond
int64_t C1
MachineRegisterInfo & MRI
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
SI Fold Operands
This file contains some templates that are useful if you are working with the STL at all.
This file implements a set that has insertion order iteration characteristics.
This file implements the SmallBitVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
Value * RHS
Value * LHS
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend, roundingMode RM)
Definition APFloat.h:1339
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:230
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:970
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
Definition APInt.h:202
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:367
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:376
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
Definition APInt.cpp:1695
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1115
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
Definition APInt.h:205
bool isNegative() const
Determine sign of this APInt.
Definition APInt.h:325
int32_t exactLogBase2() const
Definition APInt.h:1803
void ashrInPlace(unsigned ShiftAmt)
Arithmetic right-shift this APInt by ShiftAmt in place.
Definition APInt.h:836
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition APInt.h:1659
unsigned countl_zero() const
The APInt version of std::countl_zero.
Definition APInt.h:1618
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
Definition APInt.h:215
unsigned countLeadingZeros() const
Definition APInt.h:1626
bool isStrictlyPositive() const
Determine if this APInt Value is positive.
Definition APInt.h:352
static bool isSameValue(const APInt &I1, const APInt &I2, bool SignedCompare=false)
Determine if two APInts have the same value, after zero-extending or sign-extending (if SignedCompare...
Definition APInt.h:550
LLVM_ABI APInt multiplicativeInverse() const
Definition APInt.cpp:1303
bool isMask(unsigned numBits) const
Definition APInt.h:484
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1030
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
Definition APInt.h:1261
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:436
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:302
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:196
bool isOne() const
Determine if this is a value of 1.
Definition APInt.h:385
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Definition APInt.h:235
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
Definition APInt.h:860
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Definition APInt.h:853
unsigned countr_one() const
Count the number of trailing one bits.
Definition APInt.h:1676
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool isEquality() const
Determine if this is an equals/not equals predicate.
Definition InstrTypes.h:978
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
Definition InstrTypes.h:757
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition InstrTypes.h:755
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition InstrTypes.h:754
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition InstrTypes.h:752
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition InstrTypes.h:753
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
Definition InstrTypes.h:742
static LLVM_ABI bool isEquality(Predicate pred)
Determine if this is an equals/not equals predicate.
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:852
static LLVM_ABI bool isOrdered(Predicate predicate)
Determine if the predicate is an ordered operation.
LLVM_ABI void applyCombineBuildVectorOfBitcast(MachineInstr &MI, SmallVector< Register > &Ops) const
LLVM_ABI void applyCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo) const
LLVM_ABI bool matchRepeatedFPDivisor(MachineInstr &MI, SmallVector< MachineInstr * > &MatchInfo) const
LLVM_ABI bool isFPConstantLegalOrBeforeLegalizer(const LLT Ty) const
LLVM_ABI bool matchFoldC2MinusAPlusC1(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchLoadOrCombine(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match expression trees of the form.
LLVM_ABI const RegisterBank * getRegBank(Register Reg) const
Get the register bank of Reg.
LLVM_ABI bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2) const
Return true if MOP1 and MOP2 are register operands are defined by equivalent instructions.
LLVM_ABI void applyUDivOrURemByConst(MachineInstr &MI) const
LLVM_ABI void applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) const
LLVM_ABI bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchFsubToFneg(MachineInstr &MI) const
LLVM_ABI bool matchCtls(MachineInstr &CtlzMI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchSelectSameVal(MachineInstr &MI) const
Optimize (cond ? x : x) -> x.
LLVM_ABI bool matchReassocConstantInnerRHS(GPtrAdd &MI, MachineInstr *RHS, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchBitfieldExtractFromShr(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: shr (shl x, n), k -> sbfx/ubfx x, pos, width.
LLVM_ABI bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchTruncSSatU(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI void applySimplifyURemByPow2(MachineInstr &MI) const
Combine G_UREM x, (known power of 2) to an add and bitmasking.
LLVM_ABI bool matchCombineUnmergeZExtToZExt(MachineInstr &MI) const
Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0.
LLVM_ABI bool matchSimplifyDemandedBits(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match demanded-bits simplification of a root's register use.
const TargetInstrInfo * TII
LLVM_ABI void applyCombineConcatVectors(MachineInstr &MI, SmallVector< Register > &Ops) const
Replace MI with a flattened build_vector with Ops or an implicit_def if Ops is empty.
LLVM_ABI void applyXorOfAndWithSameReg(MachineInstr &MI, std::pair< Register, Register > &MatchInfo) const
LLVM_ABI bool canCombineFMadOrFMA(MachineInstr &MI, bool &AllowFusionGlobally, bool &HasFMAD, bool &Aggressive, bool CanReassociate=false) const
LLVM_ABI bool matchFoldAPlusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const
LLVM_ABI void applyCombineUnmergeConstant(MachineInstr &MI, SmallVectorImpl< APInt > &Csts) const
LLVM_ABI bool matchCombineFAddFpExtFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) (fadd (fpext (fmul x,...
LLVM_ABI bool matchCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const
LLVM_ABI void applyCombineShuffleConcat(MachineInstr &MI, SmallVector< Register > &Ops) const
Replace MI with a flattened build_vector with Ops or an implicit_def if Ops is empty.
LLVM_ABI void replaceSingleDefInstWithReg(MachineInstr &MI, Register Replacement) const
Delete MI and replace all of its uses with Replacement.
LLVM_ABI void applyCombineShuffleToBuildVector(MachineInstr &MI) const
Replace shuffle MI with a build_vector.
LLVM_ABI bool matchCombineExtractedVectorLoad(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine a G_EXTRACT_VECTOR_ELT of a load into a narrowed load.
LLVM_ABI void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const
MachineRegisterInfo::replaceRegWith() and inform the observer of the changes.
LLVM_ABI void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, Register ToReg) const
Replace a single register operand with a new register and inform the observer of the changes.
LLVM_ABI void applyCombineMemCpyFamily(MachineInstr &MI, MemCpyFamilyLoweringInfo &MatchInfo) const
LLVM_ABI bool matchReassocCommBinOp(MachineInstr &MI, BuildFnTy &MatchInfo) const
Reassociate commutative binary operations like G_ADD.
LLVM_ABI void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
LLVM_ABI bool matchCommuteConstantToRHS(MachineInstr &MI) const
Match constant LHS ops that should be commuted.
LLVM_ABI bool matchSimplifyNegMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const
Tranform (neg (min/max x, (neg x))) into (max/min x, (neg x)).
LLVM_ABI bool matchCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const
Try to combine G_[SU]DIV and G_[SU]REM into a single G_[SU]DIVREM when their source operands are iden...
LLVM_ABI void applyUMulHToLShr(MachineInstr &MI) const
LLVM_ABI void applyNotCmp(MachineInstr &MI, SmallVectorImpl< Register > &RegsToNegate) const
LLVM_ABI bool isLegalOrHasFewerElements(const LegalityQuery &Query) const
LLVM_ABI bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const
Fold (shift (shift base, x), y) -> (shift base (x+y))
LLVM_ABI bool matchTruncLshrBuildVectorFold(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI bool matchAllExplicitUsesAreUndef(MachineInstr &MI) const
Return true if all register explicit use operands on MI are defined by a G_IMPLICIT_DEF.
LLVM_ABI bool isPredecessor(const MachineInstr &DefMI, const MachineInstr &UseMI) const
Returns true if DefMI precedes UseMI or they are the same instruction.
LLVM_ABI bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const
LLVM_ABI bool matchTruncSSatS(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI const TargetLowering & getTargetLowering() const
LLVM_ABI bool matchShuffleUndefRHS(MachineInstr &MI, BuildFnTy &MatchInfo) const
Remove references to rhs if it is undef.
LLVM_ABI void applyBuildInstructionSteps(MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const
Replace MI with a series of instructions described in MatchInfo.
LLVM_ABI void applySDivByPow2(MachineInstr &MI) const
LLVM_ABI bool matchConstantFoldFPBinOp(MachineInstr &MI, BuildFnTy &MatchInfo) const
Do constant FP folding when opportunities are exposed after MIR building.
LLVM_ABI void applyUDivByPow2(MachineInstr &MI) const
Given an G_UDIV MI expressing an unsigned divided by a pow2 constant, return expressions that impleme...
LLVM_ABI bool matchOr(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine ors.
LLVM_ABI bool matchLshrOfTruncOfLshr(MachineInstr &MI, LshrOfTruncOfLshr &MatchInfo, MachineInstr &ShiftMI) const
Fold (lshr (trunc (lshr x, C1)), C2) -> trunc (shift x, (C1 + C2))
LLVM_ABI void replaceInstWithConstant(MachineInstr &MI, int64_t C) const
Replace an instruction with a G_CONSTANT with value C.
LLVM_ABI bool matchCombineFSubFpExtFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), (fneg z)) (fsub (fpext (fmul x,...
LLVM_ABI bool matchConstantLargerBitWidth(MachineInstr &MI, unsigned ConstIdx) const
Checks if constant at ConstIdx is larger than MI 's bitwidth.
LLVM_ABI void applyCombineCopy(MachineInstr &MI) const
LLVM_ABI bool matchCombineShlOfExtend(MachineInstr &MI, RegisterImmPair &MatchData) const
LLVM_ABI bool matchCombineFSubFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fmul x, y), z) -> (fma x, y, -z) (fsub (fmul x, y), z) -> (fmad x,...
LLVM_ABI bool matchCombineFAddFMAFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z)) (fadd (fmad x,...
LLVM_ABI bool matchSextTruncSextLoad(MachineInstr &MI) const
LLVM_ABI bool matchCombineInsertVecElts(MachineInstr &MI, SmallVectorImpl< Register > &MatchInfo) const
LLVM_ABI bool matchCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI, Register &UnmergeSrc) const
LLVM_ABI bool matchDivByPow2(MachineInstr &MI, bool IsSigned) const
Given an G_SDIV MI expressing a signed divided by a pow2 constant, return expressions that implements...
LLVM_ABI bool matchNarrowBinopFeedingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchCombineLoadWithAndMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match (and (load x), mask) -> zextload x.
LLVM_ABI bool matchCombineFAddFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fmul x, y), z) -> (fma x, y, z) (fadd (fmul x, y), z) -> (fmad x,...
LLVM_ABI bool matchCombineCopy(MachineInstr &MI) const
LLVM_ABI bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const
LLVM_ABI void applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const
LLVM_ABI bool matchXorOfAndWithSameReg(MachineInstr &MI, std::pair< Register, Register > &MatchInfo) const
Fold (xor (and x, y), y) -> (and (not x), y) {.
LLVM_ABI bool matchCombineShuffleVector(MachineInstr &MI, SmallVectorImpl< Register > &Ops) const
Check if the G_SHUFFLE_VECTOR MI can be replaced by a concat_vectors.
LLVM_ABI void replaceInstWithFConstant(MachineInstr &MI, double C) const
Replace an instruction with a G_FCONSTANT with value C.
LLVM_ABI bool matchOrShiftToFunnelShift(MachineInstr &MI, bool AllowScalarConstants, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchRedundantSExtInReg(MachineInstr &MI) const
LLVM_ABI void replaceOpcodeWith(MachineInstr &FromMI, unsigned ToOpcode) const
Replace the opcode in instruction with a new opcode and inform the observer of the changes.
LLVM_ABI void applyFunnelShiftConstantModulo(MachineInstr &MI) const
Replaces the shift amount in MI with ShiftAmt % BW.
LLVM_ABI bool matchFoldC1Minus2MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applyCombineShlOfExtend(MachineInstr &MI, const RegisterImmPair &MatchData) const
LLVM_ABI void applyUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B, bool IsPreLegalize, GISelValueTracking *VT=nullptr, MachineDominatorTree *MDT=nullptr, const LegalizerInfo *LI=nullptr)
LLVM_ABI bool matchShuffleDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
Turn shuffle a, b, mask -> shuffle undef, b, mask iff mask does not reference a.
LLVM_ABI bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const
Transform a multiply by a power-of-2 value to a left shift.
LLVM_ABI void applyCombineShuffleVector(MachineInstr &MI, ArrayRef< Register > Ops) const
Replace MI with a concat_vectors with Ops.
LLVM_ABI bool matchCombineUnmergeUndef(MachineInstr &MI, std::function< void(MachineIRBuilder &)> &MatchInfo) const
Transform G_UNMERGE G_IMPLICIT_DEF -> G_IMPLICIT_DEF, G_IMPLICIT_DEF, ...
LLVM_ABI void applyFoldBinOpIntoSelect(MachineInstr &MI, const unsigned &SelectOpNo) const
SelectOperand is the operand in binary operator MI that is the select to fold.
LLVM_ABI bool matchFoldAMinusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applyCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const
LLVM_ABI bool matchCombineShuffleConcat(MachineInstr &MI, SmallVector< Register > &Ops) const
LLVM_ABI void applySextInRegOfLoad(MachineInstr &MI, std::tuple< Register, unsigned > &MatchInfo) const
LLVM_ABI bool matchTruncUSatU(MachineInstr &MI, MachineInstr &MinMI) const
LLVM_ABI bool matchICmpToLHSKnownBits(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchReassocPtrAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Reassociate pointer calculations with G_ADD involved, to allow better addressing mode usage.
LLVM_ABI bool isPreLegalize() const
LLVM_ABI bool matchUndefShuffleVectorMask(MachineInstr &MI) const
Return true if a G_SHUFFLE_VECTOR instruction MI has an undef mask.
LLVM_ABI bool matchCombineSubToAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchShiftOfShiftedLogic(MachineInstr &MI, ShiftOfShiftedLogic &MatchInfo) const
If we have a shift-by-constant of a bitwise logic op that itself has a shift-by-constant operand with...
LLVM_ABI bool matchCombineConcatVectors(MachineInstr &MI, SmallVector< Register > &Ops) const
If MI is G_CONCAT_VECTORS, try to combine it.
LLVM_ABI bool matchInsertExtractVecEltOutOfBounds(MachineInstr &MI) const
Return true if a G_{EXTRACT,INSERT}_VECTOR_ELT has an out of range index.
LLVM_ABI bool matchOperandIsKnownToBeAPowerOfTwo(const MachineOperand &MO, bool OrNegative=false, bool OrZero=false) const
Check if operand MO is known to be a power of 2.
LLVM_ABI bool matchExtractAllEltsFromBuildVector(MachineInstr &MI, SmallVectorImpl< std::pair< Register, MachineInstr * > > &MatchInfo) const
LLVM_ABI LLVMContext & getContext() const
LLVM_ABI void applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const
LLVM_ABI bool isConstantLegalOrBeforeLegalizer(const LLT Ty) const
LLVM_ABI bool matchNotCmp(MachineInstr &MI, SmallVectorImpl< Register > &RegsToNegate) const
Combine inverting a result of a compare into the opposite cond code.
LLVM_ABI bool matchSextInRegOfLoad(MachineInstr &MI, std::tuple< Register, unsigned > &MatchInfo) const
Match sext_inreg(load p), imm -> sextload p.
LLVM_ABI bool matchSelectIMinMax(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine select to integer min/max.
LLVM_ABI bool simplifyDemandedBits(MachineInstr &MI, unsigned OpNo, const APInt &DemandedBits, KnownBits &Known, unsigned Depth=0) const
Simplify a register use under DemandedBits and compute Known in the same walk.
LLVM_ABI bool matchConstantFoldUnaryIntOp(MachineInstr &MI, BuildFnTy &MatchInfo) const
Constant fold a unary integer op (G_CTLZ, G_CTTZ, G_CTPOP and their _ZERO_POISON variants,...
LLVM_ABI bool isLegal(const LegalityQuery &Query) const
LLVM_ABI bool matchShiftsTooBig(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match shifts greater or equal to the range (the bitwidth of the result datatype, or the effective bit...
LLVM_ABI void applyCombineShuffleOfBuildVector(MachineInstr &MI) const
Replace shuffle of build_vector with a build_vector.
LLVM_ABI bool matchICmpToTrueFalseKnownBits(MachineInstr &MI, int64_t &MatchInfo) const
LLVM_ABI bool tryReassocBinOp(unsigned Opc, Register DstReg, Register Op0, Register Op1, BuildFnTy &MatchInfo) const
Try to reassociate to reassociate operands of a commutative binop.
LLVM_ABI void eraseInst(MachineInstr &MI) const
Erase MI.
LLVM_ABI void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
LLVM_ABI bool matchUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI bool matchConstantFoldBinOp(MachineInstr &MI, BuildFnTy &MatchInfo) const
Do constant folding when opportunities are exposed after MIR building.
MachineRegisterInfo & MRI
LLVM_ABI void applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const
LLVM_ABI bool matchConstantFPOp(const MachineOperand &MOP, double C) const
Return true if MOP is defined by a G_FCONSTANT or splat with a value exactly equal to C.
LLVM_ABI MachineInstr * buildUDivOrURemUsingMul(MachineInstr &MI) const
Given an G_UDIV MI or G_UREM MI expressing a divide by constant, return an expression that implements...
LLVM_ABI void applyExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const
LLVM_ABI bool matchFoldBinOpIntoSelect(MachineInstr &MI, unsigned &SelectOpNo) const
Push a binary operator through a select on constants.
LLVM_ABI bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount) const
LLVM_ABI bool isConstantNaN(Register Reg) const
LLVM_ABI bool matchPtrAddZeroVector(MachineInstr &MI) const
}
LLVM_ABI bool tryCombineExtendingLoads(MachineInstr &MI) const
If MI is extend that consumes the result of a load, try to combine it.
LLVM_ABI bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const
LLVM_ABI bool matchBuildVectorIdentityFold(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI bool matchBitfieldExtractFromShrAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: shr (and x, n), k -> ubfx x, pos, width.
LLVM_ABI void applyTruncSSatS(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI void applyRotateOutOfRange(MachineInstr &MI) const
LLVM_ABI bool matchReassocFoldConstantsInSubTree(GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchHoistLogicOpWithSameOpcodeHands(MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const
Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
LLVM_ABI bool matchBitfieldExtractFromAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: and (lshr x, cst), mask -> ubfx x, cst, width.
LLVM_ABI bool matchBitfieldExtractFromSExtInReg(MachineInstr &MI, BuildFnTy &MatchInfo) const
Form a G_SBFX from a G_SEXT_INREG fed by a right shift.
LLVM_ABI bool matchAndOrDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void replaceInstWithUndef(MachineInstr &MI) const
Replace an instruction with a G_IMPLICIT_DEF.
LLVM_ABI bool isDesirableToCommuteWithShift(const MachineInstr &MI) const
LLVM_ABI bool matchRedundantBinOpInEquality(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform: (X + Y) == X -> Y == 0 (X - Y) == X -> Y == 0 (X ^ Y) == X -> Y == 0 (X + Y) !...
LLVM_ABI bool matchConstantFoldFPUnary(MachineInstr &MI, BuildFnTy &MatchInfo) const
Constant fold a unary FP operation when the source is constant.
LLVM_ABI bool matchOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond) const
If a brcond's true block is not the fallthrough, make it so by inverting the condition and swapping o...
LLVM_ABI bool matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine addos.
LLVM_ABI void applyAshShlToSextInreg(MachineInstr &MI, std::tuple< Register, int64_t > &MatchInfo) const
LLVM_ABI bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine selects.
LLVM_ABI bool matchCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo) const
LLVM_ABI bool matchConstantFoldCastOp(MachineInstr &MI, BuildFnTy &MatchInfo) const
Do constant folding when opportunities are exposed after MIR building.
LLVM_ABI bool matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) const
Transform X, Y<dead> = G_UNMERGE Z -> X = G_TRUNC Z.
LLVM_ABI bool matchRotateOutOfRange(MachineInstr &MI) const
LLVM_ABI void applyExpandFPowI(MachineInstr &MI, int64_t Exponent) const
Expands FPOWI into a series of multiplications and a division if the exponent is negative.
LLVM_ABI void setRegBank(Register Reg, const RegisterBank *RegBank) const
Set the register bank of Reg.
LLVM_ABI bool matchCommuteFPConstantToRHS(MachineInstr &MI) const
Match constant LHS FP ops that should be commuted.
LLVM_ABI void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const
LLVM_ABI bool matchRedundantOr(MachineInstr &MI, Register &Replacement) const
LLVM_ABI void applyTruncSSatU(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI void applySimplifySRemByPow2(MachineInstr &MI) const
Combine G_SREM x, (+/-2^k) to a bias-and-mask sequence.
LLVM_ABI bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fpext (fneg (fmul x, y))), z) -> (fneg (fma (fpext x), (fpext y),...
LLVM_ABI bool matchTruncBuildVectorFold(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI void applyCombineTruncOfShift(MachineInstr &MI, std::pair< MachineInstr *, LLT > &MatchInfo) const
LLVM_ABI bool matchConstantOp(const MachineOperand &MOP, int64_t C) const
Return true if MOP is defined by a G_CONSTANT or splat with a value equal to C.
const LegalizerInfo * LI
LLVM_ABI void applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const
LLVM_ABI void applyCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, Register &UnmergeSrc) const
LLVM_ABI bool matchUMulHToLShr(MachineInstr &MI) const
MachineDominatorTree * MDT
LLVM_ABI bool matchSimplifySelectToMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applyRepeatedFPDivisor(SmallVector< MachineInstr * > &MatchInfo) const
LLVM_ABI bool matchTruncUSatUToFPTOUISat(MachineInstr &MI, MachineInstr &SrcMI) const
const RegisterBankInfo * RBI
LLVM_ABI bool matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: (G_*MULO x, 0) -> 0 + no carry out.
GISelValueTracking * VT
LLVM_ABI bool matchBinopWithNeg(MachineInstr &MI, BuildFnTy &MatchInfo) const
Fold a bitwiseop (~b +/- c) -> a bitwiseop ~(b -/+ c)
LLVM_ABI bool matchCombineUnmergeConstant(MachineInstr &MI, SmallVectorImpl< APInt > &Csts) const
Transform G_UNMERGE Constant -> Constant1, Constant2, ...
LLVM_ABI bool matchCountZeroToZeroPoison(MachineInstr &MI, unsigned Opc, unsigned ZeroPoisonOpc) const
LLVM_ABI void applyShiftOfShiftedLogic(MachineInstr &MI, ShiftOfShiftedLogic &MatchInfo) const
const TargetRegisterInfo * TRI
LLVM_ABI bool matchRedundantAnd(MachineInstr &MI, Register &Replacement) const
LLVM_ABI bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI) const
Returns true if DefMI dominates UseMI.
GISelChangeObserver & Observer
LLVM_ABI void applyBuildFn(MachineInstr &MI, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
LLVM_ABI bool matchCombineTruncOfShift(MachineInstr &MI, std::pair< MachineInstr *, LLT > &MatchInfo) const
Transform trunc (shl x, K) to shl (trunc x), K if K < VT.getScalarSizeInBits().
LLVM_ABI bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize, unsigned &ShiftVal) const
Reduce a shift by a constant to an unmerge and a shift on a half sized type.
LLVM_ABI bool matchUDivOrURemByConst(MachineInstr &MI) const
Combine G_UDIV or G_UREM by constant into a multiply by magic constant.
LLVM_ABI bool matchAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine ands.
LLVM_ABI bool matchSuboCarryOut(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchCombineFSubFNegFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z)) (fsub (fneg (fmul,...
LLVM_ABI bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg) const
Transform zext(trunc(x)) to x.
LLVM_ABI bool matchUDivByShiftedPow2(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine unsigned division by a shifted power of two into a right shift.
LLVM_ABI bool matchSameRegOrICstOrSplat(Register A, Register B) const
True when A and B are the same register, including through copies, or different registers holding the...
LLVM_ABI void applyLshrOfTruncOfLshr(MachineInstr &MI, LshrOfTruncOfLshr &MatchInfo) const
LLVM_ABI bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0) const
Optimize memcpy intrinsics et al, e.g.
LLVM_ABI bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applySDivOrSRemByConst(MachineInstr &MI) const
LLVM_ABI bool matchCombineMemCpyFamily(MachineInstr &MI, MemCpyFamilyLoweringInfo &MatchInfo, unsigned MaxLen=0) const
LLVM_ABI MachineInstr * buildSDivOrSRemUsingMul(MachineInstr &MI) const
Given an G_SDIV MI or G_SREM MI expressing a signed divide by constant, return an expression that imp...
LLVM_ABI bool isLegalOrHasWidenScalar(const LegalityQuery &Query) const
LLVM_ABI bool matchSignedDivRemToUnsigned(MachineInstr &MI, unsigned UnsignedOpcode) const
Convert signed division or remainder of nonnegative operands to unsigned.
LLVM_ABI bool matchReassocConstantInnerLHS(GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchOverlappingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0.
LLVM_ABI bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg) const
Transform anyext(trunc(x)) to x.
LLVM_ABI void applyExtractAllEltsFromBuildVector(MachineInstr &MI, SmallVectorImpl< std::pair< Register, MachineInstr * > > &MatchInfo) const
MachineIRBuilder & Builder
LLVM_ABI void replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx) const
Delete MI and replace all of its uses with its OpIdx-th operand.
LLVM_ABI const MachineFunction & getMachineFunction() const
LLVM_ABI bool matchCombineBuildVectorOfBitcast(MachineInstr &MI, SmallVector< Register > &Ops) const
Combine G_BUILD_VECTOR(G_UNMERGE(G_BITCAST), Undef) to G_BITCAST(G_BUILD_VECTOR(.....
LLVM_ABI bool matchCombineFAddFpExtFMulToFMadOrFMAAggressive(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchConstantFoldFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Constant fold G_FMA/G_FMAD.
LLVM_ABI bool matchSDivOrSRemByConst(MachineInstr &MI) const
Combine G_SDIV or G_SREM by constant into a multiply by magic constant.
LLVM_ABI void applyOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond) const
LLVM_ABI void applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal) const
LLVM_ABI bool matchFPowIExpansion(MachineInstr &MI, int64_t Exponent) const
Match FPOWI if it's safe to extend it into a series of multiplications.
LLVM_ABI void applyCombineInsertVecElts(MachineInstr &MI, SmallVectorImpl< Register > &MatchInfo) const
LLVM_ABI bool matchCombineUnmergeMergeToPlainValues(MachineInstr &MI, SmallVectorImpl< Register > &Operands) const
Transform <ty,...> G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z.
LLVM_ABI void applyCombineUnmergeMergeToPlainValues(MachineInstr &MI, SmallVectorImpl< Register > &Operands) const
LLVM_ABI bool matchAshrShlToSextInreg(MachineInstr &MI, std::tuple< Register, int64_t > &MatchInfo) const
Match ashr (shl x, C), C -> sext_inreg (C)
LLVM_ABI void applyCombineUnmergeZExtToZExt(MachineInstr &MI) const
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
const APFloat & getValueAPF() const
Definition Constants.h:463
This class represents a range of values.
LLVM_ABI std::optional< ConstantRange > exactUnionWith(const ConstantRange &CR) const
Union the two ranges and return the result if it can be represented exactly, otherwise return std::nu...
LLVM_ABI ConstantRange subtract(const APInt &CI) const
Subtract the specified constant from the endpoints of this constant range.
static LLVM_ABI ConstantRange fromKnownBits(const KnownBits &Known, bool IsSigned)
Initialize a range based on a known bits constraint.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI OverflowResult unsignedSubMayOverflow(const ConstantRange &Other) const
Return whether unsigned sub of the two ranges always/never overflows.
LLVM_ABI OverflowResult unsignedAddMayOverflow(const ConstantRange &Other) const
Return whether unsigned add of the two ranges always/never overflows.
LLVM_ABI bool isWrappedSet() const
Return true if this set wraps around the unsigned domain.
const APInt & getUpper() const
Return the upper value for this range.
static LLVM_ABI ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, const APInt &Other)
Produce the exact range such that all values in the returned range satisfy the given predicate with a...
LLVM_ABI OverflowResult signedAddMayOverflow(const ConstantRange &Other) const
Return whether signed add of the two ranges always/never overflows.
@ AlwaysOverflowsHigh
Always overflows in the direction of signed/unsigned max value.
@ AlwaysOverflowsLow
Always overflows in the direction of signed/unsigned min value.
@ MayOverflow
May or may not overflow.
LLVM_ABI OverflowResult signedSubMayOverflow(const ConstantRange &Other) const
Return whether signed sub of the two ranges always/never overflows.
This is an important base class in LLVM.
Definition Constant.h:44
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
bool isBigEndian() const
Definition DataLayout.h:218
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
iterator end()
Definition DenseMap.h:686
unsigned size() const
Definition DenseMap.h:717
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:793
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
Represents overflowing add operations.
Represents an integer addition.
Represents a logical and.
CmpInst::Predicate getCond() const
Register getLHSReg() const
Register getRHSReg() const
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Register getCarryOutReg() const
Register getLHSReg() const
Register getRHSReg() const
Represents a G_BUILD_VECTOR.
Register getSrcReg() const
Represents a G_CONCAT_VECTORS.
Represent a G_ICMP.
Abstract class that contains various methods for clients to notify about changes.
Simple wrapper observer that takes several observers, and calls each one for each event.
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
Represents a G_LOAD.
Represents a logical binary operation.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
LocationSize getMemSizeInBits() const
Returns the size in bits of the memory access.
Register getSourceReg(unsigned I) const
Returns the I'th source register.
unsigned getNumSources() const
Returns the number of source registers.
Represents a logical or.
Represents a G_PTR_ADD.
Represents a G_SELECT.
Represents overflowing sub operations.
Represents an integer subtraction.
Represents a G_UNMERGE_VALUES.
unsigned getNumDefs() const
Returns the number of def registers.
Register getSourceReg() const
Get the unmerge source register.
Represents a G_ZEXTLOAD.
Represents a zext.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr bool isAnyScalar() const
constexpr ElementCount getElementCount() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
constexpr bool isFixedVector() const
Returns true if the LLT is a fixed vector.
static LLT integer(unsigned SizeInBits)
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, Register Dst, Register Src, uint64_t KnownLen, Align Alignment, bool DstAlignCanChange, ArrayRef< LLT > MemOps)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
TypeSize getValue() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
DenormalMode getDenormalMode(const fltSemantics &FPType) const
Returns the denormal handling type for the default rounding mode of the function.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Helper class to build MachineInstr.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildCTLZ(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTLZ Op0, Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
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.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI bool isDereferenceableInvariantLoad() const
Return true if this load instruction never traps and points to a memory location whose value doesn't ...
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
unsigned getNumOperands() const
Retuns the total number of operands.
static constexpr uint32_t getPoisonGeneratingFlags()
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
mop_range uses()
Returns all operands which may be register uses.
MachineOperand * findRegisterUseOperand(Register Reg, const TargetRegisterInfo *TRI, bool isKill=false)
Wrapper for findRegisterUseOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
LLT getMemoryType() const
Return the memory type of the memory reference.
unsigned getAddrSpace() const
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
const MachinePointerInfo & getPointerInfo() const
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setMBB(MachineBasicBlock *MBB)
void setPredicate(unsigned Predicate)
Register getReg() const
getReg - Returns the register number.
unsigned getPredicate() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
This class implements the register bank concept.
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
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
Definition SetVector.h:268
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallBitVector & set()
bool all() const
Returns true if all bits are set.
size_type size() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:346
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
virtual LLVM_READONLY LLT getPreferredShiftAmountTy(LLT ShiftValueTy) const
Return the preferred type to use for a shift opcode, given the shifted amount type is ShiftValueTy.
bool isBeneficialToExpandPowI(int64_t Exponent, bool OptForSize) const
Return true if it is beneficial to expand an @llvm.powi.
virtual bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AddrSpace, Instruction *I=nullptr) const
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual bool isIndexingLegal(MachineInstr &MI, Register Base, Register Offset, bool IsPre, MachineRegisterInfo &MRI) const
Returns true if the specified base+offset is a legal indexed addressing mode for this target.
virtual bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const
Return true if it is profitable to move this shift by a constant amount through its operand,...
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:181
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
self_iterator getIterator()
Definition ilist_node.h:123
#define INT64_MAX
Definition DataTypes.h:71
#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...
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Custom
The target wants to do something special with this combination of operand and type.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
GInstrBind< GBuildVector > m_GBuildVector(GBuildVector *&Inst)
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
LoadOp_match< GLoad, PtrP > m_GLoad(const PtrP &Ptr)
MIFlagsRef m_MIFlags(uint32_t &Flags)
operand_type_match m_Pred()
BinaryOp_match< LHS, RHS, TargetOpcode::G_UMIN, true > m_GUMin(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_XOR, true > m_GXor(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_FPEXT > m_GFPExt(const SrcTy &Src)
ConstantMatch< APInt > m_ICst(APInt &Cst)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ADD, true > m_GAdd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
ICstOrSplatMatch< APInt > m_ICstOrSplat(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
GInstrBind< GConcatVectors > m_GConcatVectors(GConcatVectors *&Inst)
GConstantBitsMatch m_GConstantOrFConstantBits(APInt &Bits)
CheckType m_SpecificType(LLT Ty)
deferred_ty< Register > m_DeferredReg(Register &R)
Similar to m_SpecificReg/Type, but the specific value to match originated from an earlier sub-pattern...
BinaryOp_match< LHS, RHS, TargetOpcode::G_UMAX, true > m_GUMax(const LHS &L, const RHS &R)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)
GInstrBind< GUnmerge > m_GUnmerge(GUnmerge *&Inst)
Instruction binders for ops with no operand-form matcher (constant-immediate or variadic-source ops).
MMORef m_MMO(const MachineMemOperand *&MMO)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ASHR, false > m_GAShr(const LHS &L, const RHS &R)
TernaryOp_match< Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT > m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
Or< Preds... > m_any_of(Preds &&... preds)
SpecificConstantOrSplatMatch m_SpecificICstOrSplat(const APInt &RequestedValue)
Matches a RequestedValue constant or a constant splat of RequestedValue.
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_BUILD_VECTOR_TRUNC, false > m_GBuildVectorTrunc(const LHS &L, const RHS &R)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
UnaryOp_match< SrcTy, TargetOpcode::G_FNEG > m_GFNeg(const SrcTy &Src)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP, true > m_c_GICmp(const Pred &P, const LHS &L, const RHS &R)
G_ICMP matcher that also matches commuted compares.
LoadOp_match< GAnyLoad, PtrP > m_GAnyLoad(const PtrP &Ptr)
TernaryOp_match< Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_INSERT_VECTOR_ELT > m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
And< Preds... > m_all_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SMIN, true > m_GSMin(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, TargetOpcode::G_FMUL, true > m_GFMul(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SMAX, true > m_GSMax(const LHS &L, const RHS &R)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP > m_GFCmp(const Pred &P, const LHS &L, const RHS &R)
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
Not(const Pred &P) -> Not< Pred >
initializer< Ty > init(const Ty &Val)
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:117
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a constant integer or a splat vector of constant integers.
Definition Utils.cpp:1677
@ Offset
Definition DWP.cpp:577
LLVM_ABI bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition Utils.cpp:1593
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
Definition Utils.cpp:2138
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
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:679
LLVM_ABI std::optional< APFloat > isConstantOrConstantSplatVectorFP(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a float constant integer or a splat vector of float constant integers.
Definition Utils.cpp:1689
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:487
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
Definition Utils.cpp:301
LLVM_ABI std::optional< APInt > getIConstantSplatVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:1553
LLVM_ABI bool isAllOnesOrAllOnesSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant -1 integer or a splatted vector of a constant -1 integer (with...
Definition Utils.cpp:1717
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
unsigned Log2_64_Ceil(uint64_t Value)
Return the ceil log base 2 of the specified value, 64 if the value is zero.
Definition MathExtras.h:345
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:315
std::function< void(MachineIRBuilder &)> BuildFnTy
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
LLVM_ABI std::optional< APFloat > ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
Definition Utils.cpp:754
@ Load
The value being inserted comes from a load (InsertElement only).
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, llvm::function_ref< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
Definition Utils.cpp:1732
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
Definition Utils.cpp:1699
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:520
LLVM_ABI bool isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector, bool IsFP)
Returns true if given the TargetLowering's boolean contents information, the value Val contains a tru...
Definition Utils.cpp:1765
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, bool OrZero=false, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return true if the given value is known to have exactly one bit set when defined.
LLVM_ABI std::optional< APInt > ConstantFoldBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
Definition Utils.cpp:685
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI const APInt & getIConstantFromReg(Register VReg, const MachineRegisterInfo &MRI)
VReg is defined by a G_CONSTANT, return the corresponding value.
Definition Utils.cpp:312
LLVM_ABI bool isConstantOrConstantVector(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowFP=true, bool AllowOpaqueConstants=true)
Return true if the specified instruction is known to be a constant, or a vector of constants.
Definition Utils.cpp:1657
constexpr unsigned MaxAnalysisRecursionDepth
SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > OperandBuildSteps
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
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:207
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
std::tuple< Register, Register, uint64_t, Align, bool, std::vector< LLT > > MemCpyFamilyLoweringInfo
Definition Utils.h:212
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition MathExtras.h:262
LLVM_ABI bool canCreateUndefOrPoison(const Operator *Op, bool ConsiderFlagsAndMetadata=true)
canCreateUndefOrPoison returns true if Op can create undef or poison from non-undef & non-poison oper...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI SmallVector< APInt > ConstantFoldVectorBinop(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
Tries to constant fold a vector binop with sources Op1 and Op2.
Definition Utils.cpp:832
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
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 std::optional< FPValueAndVReg > getFConstantSplat(Register VReg, const MachineRegisterInfo &MRI, bool AllowUndef=true)
Returns a floating point scalar constant of a build vector splat if it exists.
Definition Utils.cpp:1586
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI std::optional< APInt > ConstantFoldCastOp(unsigned Opcode, LLT DstTy, const Register Op0, const MachineRegisterInfo &MRI)
Definition Utils.cpp:946
@ Other
Any other memory.
Definition ModRef.h:68
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
Definition Utils.cpp:2305
LLVM_ABI SmallVector< APFloat > ConstantFoldUnaryFPOp(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI)
Tries to constant fold a unary floating-point operation on Src.
Definition Utils.cpp:1031
LLVM_ABI unsigned getInverseGMinMaxOpcode(unsigned MinMaxOpc)
Returns the inverse opcode of MinMaxOpc, which is a generic min/max opcode like G_SMIN.
Definition Utils.cpp:286
LLVM_ABI SmallVector< APFloat > ConstantFoldVectorFPBinop(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
Tries to constant fold a vector floating-point binop with sources Op1 and Op2.
Definition Utils.cpp:855
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
LLVM_ABI std::optional< FPValueAndVReg > getFConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_FCONSTANT returns it...
Definition Utils.cpp:454
constexpr unsigned BitWidth
LLVM_ABI int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP)
Returns an integer representing true, as defined by the TargetBooleanContents.
Definition Utils.cpp:1790
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< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:440
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
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:495
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:206
LLVM_ABI SmallVector< APInt > ConstantFoldUnaryIntOp(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI)
Tries to constant fold a unary integer operation (G_CTLZ, G_CTTZ, G_CTPOP and their _ZERO_POISON vari...
Definition Utils.cpp:983
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:202
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:527
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
unsigned getFCmpCode(CmpInst::Predicate CC)
Similar to getICmpCode but for FCmpInst.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Simple struct used to hold a Register value and the instruction which defines it.
Definition Utils.h:249
static constexpr DenormalMode getIEEE()
Extended Value Type.
Definition ValueTypes.h:35
SmallVector< InstructionBuildSteps, 2 > InstrsToBuild
Describes instructions to be built during a combine.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
Definition KnownBits.h:315
bool isNonNegative() const
Returns true if this value is known to be non-negative.
Definition KnownBits.h:106
unsigned countMinLeadingOnes() const
Returns the minimum number of leading one bits.
Definition KnownBits.h:265
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
Definition KnownBits.h:256
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
Definition KnownBits.h:64
unsigned getBitWidth() const
Get the bit width of this value.
Definition KnownBits.h:44
static LLVM_ABI KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for lshr(LHS, RHS).
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
Definition KnownBits.h:262
bool isNegative() const
Returns true if this value is known to be negative.
Definition KnownBits.h:103
static LLVM_ABI KnownBits shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW=false, bool NSW=false, bool ShAmtNonZero=false)
Compute known bits for shl(LHS, RHS).
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
Matching combinators.
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
MachinePointerInfo getWithOffset(int64_t O) const
const RegisterBank * Bank
Magic data for optimising signed division by a constant.
static LLVM_ABI SignedDivisionByConstantInfo get(const APInt &D)
Calculate the magic numbers required to implement a signed integer division by a constant as a sequen...
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
Magic data for optimising unsigned division by a constant.
static LLVM_ABI UnsignedDivisionByConstantInfo get(const APInt &D, unsigned LeadingZeros=0, bool AllowEvenDivisorOptimization=true, bool AllowWidenOptimization=false)
Calculate the magic numbers required to implement an unsigned integer division by a constant as a seq...