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