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 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6642 // prefer to fold the multiply with fewer uses.
6643 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6644 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6645 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6646 std::swap(LHS, RHS);
6647 }
6648
6649 MachineInstr *FMA = nullptr;
6650 Register Z;
6651 // fold (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z))
6652 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6653 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6654 m_GFMul(m_Reg(), m_Reg())) &&
6655 MRI.hasOneNonDBGUse(LHS.MI->getOperand(0).getReg()) &&
6656 MRI.hasOneNonDBGUse(LHS.MI->getOperand(3).getReg())) {
6657 FMA = LHS.MI;
6658 Z = RHS.Reg;
6659 }
6660 // fold (fadd z, (fma x, y, (fmul u, v))) -> (fma x, y, (fma u, v, z))
6661 else if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6662 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6663 m_GFMul(m_Reg(), m_Reg())) &&
6664 MRI.hasOneNonDBGUse(RHS.MI->getOperand(0).getReg()) &&
6665 MRI.hasOneNonDBGUse(RHS.MI->getOperand(3).getReg())) {
6666 Z = LHS.Reg;
6667 FMA = RHS.MI;
6668 }
6669
6670 if (FMA) {
6671 MachineInstr *FMulMI;
6672 if (!mi_match(FMA->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6673 return false;
6674 Register X = FMA->getOperand(1).getReg();
6675 Register Y = FMA->getOperand(2).getReg();
6676 Register U = FMulMI->getOperand(1).getReg();
6677 Register V = FMulMI->getOperand(2).getReg();
6678 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6679 unsigned OuterFlags = MI.getFlags() & FMA->getFlags();
6680
6681 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6682 Register InnerFMA = MRI.createGenericVirtualRegister(DstTy);
6683 B.buildInstr(PreferredFusedOpcode, {InnerFMA}, {U, V, Z}, InnerFlags);
6684 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6685 {X, Y, InnerFMA}, OuterFlags);
6686 };
6687 return true;
6688 }
6689
6690 return false;
6691}
6692
6695 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6696 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6697
6698 bool AllowFusionGlobally, HasFMAD, Aggressive;
6699 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6700 return false;
6701
6702 if (!Aggressive)
6703 return false;
6704
6705 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6706 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6707 Register Op1 = MI.getOperand(1).getReg();
6708 Register Op2 = MI.getOperand(2).getReg();
6709 MachineInstr *Op1Def, *Op2Def;
6710 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6711 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6712 return false;
6713 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6714 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6715
6716 unsigned PreferredFusedOpcode =
6717 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6718
6719 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6720 // prefer to fold the multiply with fewer uses.
6721 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6722 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6723 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6724 std::swap(LHS, RHS);
6725 }
6726
6727 // Builds: (fma x, y, (fma (fpext u), (fpext v), z))
6728 auto buildMatchInfo = [=, &MI](Register U, Register V, Register Z, Register X,
6729 Register Y, unsigned InnerFlags,
6730 unsigned OuterFlags, MachineIRBuilder &B) {
6731 Register FpExtU = B.buildFPExt(DstType, U).getReg(0);
6732 Register FpExtV = B.buildFPExt(DstType, V).getReg(0);
6733 Register InnerFMA = B.buildInstr(PreferredFusedOpcode, {DstType},
6734 {FpExtU, FpExtV, Z}, InnerFlags)
6735 .getReg(0);
6736 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6737 {X, Y, InnerFMA}, OuterFlags);
6738 };
6739
6740 MachineInstr *FMulMI, *FMAMI;
6741 // fold (fadd (fma x, y, (fpext (fmul u, v))), z)
6742 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6743 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6744 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6745 m_GFPExt(m_MInstr(FMulMI))) &&
6746 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6747 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6748 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6749 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6750 unsigned OuterFlags = MI.getFlags() & LHS.MI->getFlags();
6751 MatchInfo = [=](MachineIRBuilder &B) {
6752 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6753 FMulMI->getOperand(2).getReg(), RHS.Reg,
6754 LHS.MI->getOperand(1).getReg(),
6755 LHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6756 };
6757 return true;
6758 }
6759
6760 // fold (fadd (fpext (fma x, y, (fmul u, v))), z)
6761 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6762 // FIXME: This turns two single-precision and one double-precision
6763 // operation into two double-precision operations, which might not be
6764 // interesting for all targets, especially GPUs.
6765 if (mi_match(LHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6766 FMAMI->getOpcode() == PreferredFusedOpcode) {
6767 MachineInstr *FMulMI;
6768 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6769 return false;
6770 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6771 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6772 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6773 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6774 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6775 MatchInfo = [=](MachineIRBuilder &B) {
6776 Register X = FMAMI->getOperand(1).getReg();
6777 Register Y = FMAMI->getOperand(2).getReg();
6778 X = B.buildFPExt(DstType, X).getReg(0);
6779 Y = B.buildFPExt(DstType, Y).getReg(0);
6780 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6781 FMulMI->getOperand(2).getReg(), RHS.Reg, X, Y,
6782 InnerFlags, OuterFlags, B);
6783 };
6784
6785 return true;
6786 }
6787 }
6788
6789 // fold (fadd z, (fma x, y, (fpext (fmul u, v)))
6790 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6791 if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6792 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6793 m_GFPExt(m_MInstr(FMulMI))) &&
6794 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6795 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6796 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6797 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6798 unsigned OuterFlags = MI.getFlags() & RHS.MI->getFlags();
6799 MatchInfo = [=](MachineIRBuilder &B) {
6800 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6801 FMulMI->getOperand(2).getReg(), LHS.Reg,
6802 RHS.MI->getOperand(1).getReg(),
6803 RHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6804 };
6805 return true;
6806 }
6807
6808 // fold (fadd z, (fpext (fma x, y, (fmul u, v)))
6809 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6810 // FIXME: This turns two single-precision and one double-precision
6811 // operation into two double-precision operations, which might not be
6812 // interesting for all targets, especially GPUs.
6813 if (mi_match(RHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6814 FMAMI->getOpcode() == PreferredFusedOpcode) {
6815 MachineInstr *FMulMI;
6816 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6817 return false;
6818 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6819 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6820 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6821 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6822 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6823 MatchInfo = [=](MachineIRBuilder &B) {
6824 Register X = FMAMI->getOperand(1).getReg();
6825 Register Y = FMAMI->getOperand(2).getReg();
6826 X = B.buildFPExt(DstType, X).getReg(0);
6827 Y = B.buildFPExt(DstType, Y).getReg(0);
6828 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6829 FMulMI->getOperand(2).getReg(), LHS.Reg, X, Y,
6830 InnerFlags, OuterFlags, B);
6831 };
6832 return true;
6833 }
6834 }
6835
6836 return false;
6837}
6838
6841 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6842 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6843
6844 bool AllowFusionGlobally, HasFMAD, Aggressive;
6845 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6846 return false;
6847
6848 Register Op1 = MI.getOperand(1).getReg();
6849 Register Op2 = MI.getOperand(2).getReg();
6850 MachineInstr *Op1Def, *Op2Def;
6851 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6852 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6853 return false;
6854 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6855 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6856 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6857
6858 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6859 // prefer to fold the multiply with fewer uses.
6860 int FirstMulHasFewerUses = true;
6861 if (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6862 isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6863 hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6864 FirstMulHasFewerUses = false;
6865
6866 unsigned PreferredFusedOpcode =
6867 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6868
6869 // fold (fsub (fmul x, y), z) -> (fma x, y, -z)
6870 if (FirstMulHasFewerUses &&
6871 (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6872 (Aggressive || MRI.hasOneNonDBGUse(LHS.Reg)))) {
6873 unsigned Flags = MI.getFlags() & LHS.MI->getFlags();
6874 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6875 Register NegZ = B.buildFNeg(DstTy, RHS.Reg).getReg(0);
6876 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6877 {LHS.MI->getOperand(1).getReg(),
6878 LHS.MI->getOperand(2).getReg(), NegZ},
6879 Flags);
6880 };
6881 return true;
6882 }
6883 // fold (fsub x, (fmul y, z)) -> (fma -y, z, x)
6884 else if ((isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6885 (Aggressive || MRI.hasOneNonDBGUse(RHS.Reg)))) {
6886 unsigned Flags = MI.getFlags() & RHS.MI->getFlags();
6887 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6888 Register NegY =
6889 B.buildFNeg(DstTy, RHS.MI->getOperand(1).getReg()).getReg(0);
6890 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6891 {NegY, RHS.MI->getOperand(2).getReg(), LHS.Reg}, Flags);
6892 };
6893 return true;
6894 }
6895
6896 return false;
6897}
6898
6901 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6902 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6903
6904 bool AllowFusionGlobally, HasFMAD, Aggressive;
6905 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6906 return false;
6907
6908 Register LHSReg = MI.getOperand(1).getReg();
6909 Register RHSReg = MI.getOperand(2).getReg();
6910 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6911
6912 unsigned PreferredFusedOpcode =
6913 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6914
6915 MachineInstr *FMulMI;
6916 // fold (fsub (fneg (fmul x, y)), z) -> (fma (fneg x), y, (fneg z))
6917 if (mi_match(LHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6918 (Aggressive || (MRI.hasOneNonDBGUse(LHSReg) &&
6919 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6920 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6921 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6922 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6923 Register NegX =
6924 B.buildFNeg(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6925 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6926 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6927 {NegX, FMulMI->getOperand(2).getReg(), NegZ}, Flags);
6928 };
6929 return true;
6930 }
6931
6932 // fold (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x)
6933 if (mi_match(RHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6934 (Aggressive || (MRI.hasOneNonDBGUse(RHSReg) &&
6935 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6936 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6937 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6938 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6939 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6940 {FMulMI->getOperand(1).getReg(),
6941 FMulMI->getOperand(2).getReg(), LHSReg},
6942 Flags);
6943 };
6944 return true;
6945 }
6946
6947 return false;
6948}
6949
6952 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6953 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6954
6955 bool AllowFusionGlobally, HasFMAD, Aggressive;
6956 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6957 return false;
6958
6959 Register LHSReg = MI.getOperand(1).getReg();
6960 Register RHSReg = MI.getOperand(2).getReg();
6961 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6962
6963 unsigned PreferredFusedOpcode =
6964 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6965
6966 MachineInstr *FMulMI;
6967 // fold (fsub (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), (fneg z))
6968 if (mi_match(LHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6969 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6970 (Aggressive || MRI.hasOneNonDBGUse(LHSReg))) {
6971 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6972 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6973 Register FpExtX =
6974 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6975 Register FpExtY =
6976 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6977 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6978 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6979 {FpExtX, FpExtY, NegZ}, Flags);
6980 };
6981 return true;
6982 }
6983
6984 // fold (fsub x, (fpext (fmul y, z))) -> (fma (fneg (fpext y)), (fpext z), x)
6985 if (mi_match(RHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6986 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6987 (Aggressive || MRI.hasOneNonDBGUse(RHSReg))) {
6988 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6989 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6990 Register FpExtY =
6991 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6992 Register NegY = B.buildFNeg(DstTy, FpExtY).getReg(0);
6993 Register FpExtZ =
6994 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6995 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6996 {NegY, FpExtZ, LHSReg}, Flags);
6997 };
6998 return true;
6999 }
7000
7001 return false;
7002}
7003
7006 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
7007 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
7008
7009 bool AllowFusionGlobally, HasFMAD, Aggressive;
7010 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
7011 return false;
7012
7013 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
7014 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
7015 Register LHSReg = MI.getOperand(1).getReg();
7016 Register RHSReg = MI.getOperand(2).getReg();
7017
7018 unsigned PreferredFusedOpcode =
7019 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
7020
7021 auto buildMatchInfo = [=](Register Dst, Register X, Register Y, Register Z,
7022 unsigned Flags, MachineIRBuilder &B) {
7023 Register FpExtX = B.buildFPExt(DstTy, X).getReg(0);
7024 Register FpExtY = B.buildFPExt(DstTy, Y).getReg(0);
7025 B.buildInstr(PreferredFusedOpcode, {Dst}, {FpExtX, FpExtY, Z}, Flags);
7026 };
7027
7028 MachineInstr *FMulMI;
7029 // fold (fsub (fpext (fneg (fmul x, y))), z) ->
7030 // (fneg (fma (fpext x), (fpext y), z))
7031 // fold (fsub (fneg (fpext (fmul x, y))), z) ->
7032 // (fneg (fma (fpext x), (fpext y), z))
7033 if ((mi_match(LHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
7034 mi_match(LHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
7035 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
7036 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
7037 MRI.getType(FMulMI->getOperand(0).getReg()))) {
7038 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
7039 MatchInfo = [=, &MI](MachineIRBuilder &B) {
7040 Register FMAReg = MRI.createGenericVirtualRegister(DstTy);
7041 buildMatchInfo(FMAReg, FMulMI->getOperand(1).getReg(),
7042 FMulMI->getOperand(2).getReg(), RHSReg, Flags, B);
7043 B.buildFNeg(MI.getOperand(0).getReg(), FMAReg);
7044 };
7045 return true;
7046 }
7047
7048 // fold (fsub x, (fpext (fneg (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
7049 // fold (fsub x, (fneg (fpext (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
7050 if ((mi_match(RHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
7051 mi_match(RHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
7052 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
7053 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
7054 MRI.getType(FMulMI->getOperand(0).getReg()))) {
7055 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
7056 MatchInfo = [=, &MI](MachineIRBuilder &B) {
7057 buildMatchInfo(MI.getOperand(0).getReg(), FMulMI->getOperand(1).getReg(),
7058 FMulMI->getOperand(2).getReg(), LHSReg, Flags, B);
7059 };
7060 return true;
7061 }
7062
7063 return false;
7064}
7065
7067 unsigned &IdxToPropagate) const {
7068 bool PropagateNaN;
7069 switch (MI.getOpcode()) {
7070 default:
7071 return false;
7072 case TargetOpcode::G_FMINNUM:
7073 case TargetOpcode::G_FMAXNUM:
7074 PropagateNaN = false;
7075 break;
7076 case TargetOpcode::G_FMINIMUM:
7077 case TargetOpcode::G_FMAXIMUM:
7078 PropagateNaN = true;
7079 break;
7080 }
7081
7082 auto MatchNaN = [&](unsigned Idx) {
7083 Register MaybeNaNReg = MI.getOperand(Idx).getReg();
7084 const ConstantFP *MaybeCst = getConstantFPVRegVal(MaybeNaNReg, MRI);
7085 if (!MaybeCst || !MaybeCst->getValueAPF().isNaN())
7086 return false;
7087 IdxToPropagate = PropagateNaN ? Idx : (Idx == 1 ? 2 : 1);
7088 return true;
7089 };
7090
7091 return MatchNaN(1) || MatchNaN(2);
7092}
7093
7094// Combine multiple FDIVs with the same divisor into multiple FMULs by the
7095// reciprocal.
7096// E.g., (a / Y; b / Y;) -> (recip = 1.0 / Y; a * recip; b * recip)
7098 MachineInstr &MI, SmallVector<MachineInstr *> &MatchInfo) const {
7099 assert(MI.getOpcode() == TargetOpcode::G_FDIV);
7100
7101 Register X = MI.getOperand(1).getReg();
7102 Register Y = MI.getOperand(2).getReg();
7103
7104 if (!MI.getFlag(MachineInstr::MIFlag::FmArcp))
7105 return false;
7106
7107 auto IsOne = [this](Register X) {
7109 return N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne());
7110 };
7111
7112 // Skip if current node is a reciprocal/fneg-reciprocal.
7113 if (IsOne(X))
7114 return false;
7115
7116 // Exit early if the target does not want this transform or if there can't
7117 // possibly be enough uses of the divisor to make the transform worthwhile.
7118 unsigned MinUses = getTargetLowering().combineRepeatedFPDivisors();
7119 if (!MinUses)
7120 return false;
7121
7122 // Find all FDIV users of the same divisor. For the moment we limit all
7123 // instructions to a single BB and use the first Instr in MatchInfo as the
7124 // dominating position.
7125 MatchInfo.push_back(&MI);
7126 for (auto &U : MRI.use_nodbg_instructions(Y)) {
7127 if (&U == &MI || U.getParent() != MI.getParent())
7128 continue;
7129 if (U.getOpcode() == TargetOpcode::G_FDIV &&
7130 U.getOperand(2).getReg() == Y && U.getOperand(1).getReg() != Y &&
7131 !IsOne(U.getOperand(1).getReg())) {
7132 // This division is eligible for optimization only if global unsafe math
7133 // is enabled or if this division allows reciprocal formation.
7134 if (U.getFlag(MachineInstr::MIFlag::FmArcp)) {
7135 MatchInfo.push_back(&U);
7136 if (dominates(U, *MatchInfo[0]))
7137 std::swap(MatchInfo[0], MatchInfo.back());
7138 }
7139 }
7140 }
7141
7142 // Now that we have the actual number of divisor uses, make sure it meets
7143 // the minimum threshold specified by the target.
7144 return MatchInfo.size() >= MinUses;
7145}
7146
7148 SmallVector<MachineInstr *> &MatchInfo) const {
7149 // Generate the new div at the position of the first instruction, that we have
7150 // ensured will dominate all other instructions.
7151 Builder.setInsertPt(*MatchInfo[0]->getParent(), MatchInfo[0]);
7152 LLT Ty = MRI.getType(MatchInfo[0]->getOperand(0).getReg());
7153 auto Div = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0),
7154 MatchInfo[0]->getOperand(2).getReg(),
7155 MatchInfo[0]->getFlags());
7156
7157 // Replace all found div's with fmul instructions.
7158 for (MachineInstr *MI : MatchInfo) {
7159 Builder.setInsertPt(*MI->getParent(), MI);
7160 Builder.buildFMul(MI->getOperand(0).getReg(), MI->getOperand(1).getReg(),
7161 Div->getOperand(0).getReg(), MI->getFlags());
7162 MI->eraseFromParent();
7163 }
7164}
7165
7167 assert(MI.getOpcode() == TargetOpcode::G_ADD && "Expected a G_ADD");
7168 Register LHS = MI.getOperand(1).getReg();
7169 Register RHS = MI.getOperand(2).getReg();
7170
7171 // Helper lambda to check for opportunities for
7172 // A + (B - A) -> B
7173 // (B - A) + A -> B
7174 auto CheckFold = [&](Register MaybeSub, Register MaybeSameReg) {
7175 Register Reg;
7176 return mi_match(MaybeSub, MRI, m_GSub(m_Reg(Src), m_Reg(Reg))) &&
7177 Reg == MaybeSameReg;
7178 };
7179 return CheckFold(LHS, RHS) || CheckFold(RHS, LHS);
7180}
7181
7183 Register &MatchInfo) const {
7184 // This combine folds the following patterns:
7185 //
7186 // G_BUILD_VECTOR_TRUNC (G_BITCAST(x), G_LSHR(G_BITCAST(x), k))
7187 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), G_TRUNC(G_LSHR(G_BITCAST(x), k)))
7188 // into
7189 // x
7190 // if
7191 // k == sizeof(VecEltTy)/2
7192 // type(x) == type(dst)
7193 //
7194 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), undef)
7195 // into
7196 // x
7197 // if
7198 // type(x) == type(dst)
7199
7200 LLT DstVecTy = MRI.getType(MI.getOperand(0).getReg());
7201 LLT DstEltTy = DstVecTy.getElementType();
7202
7203 Register Lo, Hi;
7204
7205 if (mi_match(
7206 MI, MRI,
7208 MatchInfo = Lo;
7209 return MRI.getType(MatchInfo) == DstVecTy;
7210 }
7211
7212 std::optional<ValueAndVReg> ShiftAmount;
7213 const auto LoPattern = m_GBitcast(m_Reg(Lo));
7214 const auto HiPattern = m_GLShr(m_GBitcast(m_Reg(Hi)), m_GCst(ShiftAmount));
7215 if (mi_match(
7216 MI, MRI,
7217 m_any_of(m_GBuildVectorTrunc(LoPattern, HiPattern),
7218 m_GBuildVector(m_GTrunc(LoPattern), m_GTrunc(HiPattern))))) {
7219 if (Lo == Hi && ShiftAmount->Value == DstEltTy.getSizeInBits()) {
7220 MatchInfo = Lo;
7221 return MRI.getType(MatchInfo) == DstVecTy;
7222 }
7223 }
7224
7225 return false;
7226}
7227
7229 Register &MatchInfo) const {
7230 // Replace (G_TRUNC (G_BITCAST (G_BUILD_VECTOR x, y)) with just x
7231 // if type(x) == type(G_TRUNC)
7232 if (!mi_match(MI.getOperand(1).getReg(), MRI,
7233 m_GBitcast(m_GBuildVector(m_Reg(MatchInfo), m_Reg()))))
7234 return false;
7235
7236 return MRI.getType(MatchInfo) == MRI.getType(MI.getOperand(0).getReg());
7237}
7238
7240 Register &MatchInfo) const {
7241 // Replace (G_TRUNC (G_LSHR (G_BITCAST (G_BUILD_VECTOR x, y)), K)) with
7242 // y if K == size of vector element type
7243 std::optional<ValueAndVReg> ShiftAmt;
7244 if (!mi_match(MI.getOperand(1).getReg(), MRI,
7246 m_GCst(ShiftAmt))))
7247 return false;
7248
7249 LLT MatchTy = MRI.getType(MatchInfo);
7250 return ShiftAmt->Value.getZExtValue() == MatchTy.getSizeInBits() &&
7251 MatchTy == MRI.getType(MI.getOperand(0).getReg());
7252}
7253
7254unsigned CombinerHelper::getFPMinMaxOpcForSelect(
7255 CmpInst::Predicate Pred, LLT DstTy,
7256 SelectPatternNaNBehaviour VsNaNRetVal) const {
7257 assert(VsNaNRetVal != SelectPatternNaNBehaviour::NOT_APPLICABLE &&
7258 "Expected a NaN behaviour?");
7259 // Choose an opcode based off of legality or the behaviour when one of the
7260 // LHS/RHS may be NaN.
7261 switch (Pred) {
7262 default:
7263 return 0;
7264 case CmpInst::FCMP_UGT:
7265 case CmpInst::FCMP_UGE:
7266 case CmpInst::FCMP_OGT:
7267 case CmpInst::FCMP_OGE:
7268 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7269 return TargetOpcode::G_FMAXNUM;
7270 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7271 return TargetOpcode::G_FMAXIMUM;
7272 if (isLegal({TargetOpcode::G_FMAXNUM, {DstTy}}))
7273 return TargetOpcode::G_FMAXNUM;
7274 if (isLegal({TargetOpcode::G_FMAXIMUM, {DstTy}}))
7275 return TargetOpcode::G_FMAXIMUM;
7276 return 0;
7277 case CmpInst::FCMP_ULT:
7278 case CmpInst::FCMP_ULE:
7279 case CmpInst::FCMP_OLT:
7280 case CmpInst::FCMP_OLE:
7281 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7282 return TargetOpcode::G_FMINNUM;
7283 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7284 return TargetOpcode::G_FMINIMUM;
7285 if (isLegal({TargetOpcode::G_FMINNUM, {DstTy}}))
7286 return TargetOpcode::G_FMINNUM;
7287 if (!isLegal({TargetOpcode::G_FMINIMUM, {DstTy}}))
7288 return 0;
7289 return TargetOpcode::G_FMINIMUM;
7290 }
7291}
7292
7293CombinerHelper::SelectPatternNaNBehaviour
7294CombinerHelper::computeRetValAgainstNaN(Register LHS, Register RHS,
7295 bool IsOrderedComparison) const {
7296 bool LHSSafe = VT->isKnownNeverNaN(LHS);
7297 bool RHSSafe = VT->isKnownNeverNaN(RHS);
7298 // Completely unsafe.
7299 if (!LHSSafe && !RHSSafe)
7300 return SelectPatternNaNBehaviour::NOT_APPLICABLE;
7301 if (LHSSafe && RHSSafe)
7302 return SelectPatternNaNBehaviour::RETURNS_ANY;
7303 // An ordered comparison will return false when given a NaN, so it
7304 // returns the RHS.
7305 if (IsOrderedComparison)
7306 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_NAN
7307 : SelectPatternNaNBehaviour::RETURNS_OTHER;
7308 // An unordered comparison will return true when given a NaN, so it
7309 // returns the LHS.
7310 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_OTHER
7311 : SelectPatternNaNBehaviour::RETURNS_NAN;
7312}
7313
7314bool CombinerHelper::matchFPSelectToMinMax(Register Dst, Register Cond,
7315 Register TrueVal, Register FalseVal,
7316 BuildFnTy &MatchInfo) const {
7317 // Match: select (fcmp cond x, y) x, y
7318 // select (fcmp cond x, y) y, x
7319 // And turn it into fminnum/fmaxnum or fmin/fmax based off of the condition.
7320 LLT DstTy = MRI.getType(Dst);
7321 // Bail out early on pointers, since we'll never want to fold to a min/max.
7322 if (DstTy.isPointer())
7323 return false;
7324 // Match a floating point compare with a less-than/greater-than predicate.
7325 // TODO: Allow multiple users of the compare if they are all selects.
7326 CmpInst::Predicate Pred;
7327 Register CmpLHS, CmpRHS;
7328 if (!mi_match(Cond, MRI,
7330 m_GFCmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS)))) ||
7331 CmpInst::isEquality(Pred))
7332 return false;
7333 SelectPatternNaNBehaviour ResWithKnownNaNInfo =
7334 computeRetValAgainstNaN(CmpLHS, CmpRHS, CmpInst::isOrdered(Pred));
7335 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::NOT_APPLICABLE)
7336 return false;
7337 if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
7338 std::swap(CmpLHS, CmpRHS);
7339 Pred = CmpInst::getSwappedPredicate(Pred);
7340 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_NAN)
7341 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_OTHER;
7342 else if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_OTHER)
7343 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_NAN;
7344 }
7345 if (TrueVal != CmpLHS || FalseVal != CmpRHS)
7346 return false;
7347 // Decide what type of max/min this should be based off of the predicate.
7348 unsigned Opc = getFPMinMaxOpcForSelect(Pred, DstTy, ResWithKnownNaNInfo);
7349 if (!Opc || !isLegal({Opc, {DstTy}}))
7350 return false;
7351 // Comparisons between signed zero and zero may have different results...
7352 // unless we have fmaximum/fminimum. In that case, we know -0 < 0.
7353 if (Opc != TargetOpcode::G_FMAXIMUM && Opc != TargetOpcode::G_FMINIMUM) {
7354 // We don't know if a comparison between two 0s will give us a consistent
7355 // result. Be conservative and only proceed if at least one side is
7356 // non-zero.
7357 auto KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpLHS, MRI);
7358 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero()) {
7359 KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpRHS, MRI);
7360 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero())
7361 return false;
7362 }
7363 }
7364 MatchInfo = [=](MachineIRBuilder &B) {
7365 B.buildInstr(Opc, {Dst}, {CmpLHS, CmpRHS});
7366 };
7367 return true;
7368}
7369
7371 BuildFnTy &MatchInfo) const {
7372 // TODO: Handle integer cases.
7373 assert(MI.getOpcode() == TargetOpcode::G_SELECT);
7374 // Condition may be fed by a truncated compare.
7375 Register Cond = MI.getOperand(1).getReg();
7376 Register MaybeTrunc;
7377 if (mi_match(Cond, MRI, m_OneNonDBGUse(m_GTrunc(m_Reg(MaybeTrunc)))))
7378 Cond = MaybeTrunc;
7379 Register Dst = MI.getOperand(0).getReg();
7380 Register TrueVal = MI.getOperand(2).getReg();
7381 Register FalseVal = MI.getOperand(3).getReg();
7382 return matchFPSelectToMinMax(Dst, Cond, TrueVal, FalseVal, MatchInfo);
7383}
7384
7386 BuildFnTy &MatchInfo) const {
7387 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
7388 // (X + Y) == X --> Y == 0
7389 // (X + Y) != X --> Y != 0
7390 // (X - Y) == X --> Y == 0
7391 // (X - Y) != X --> Y != 0
7392 // (X ^ Y) == X --> Y == 0
7393 // (X ^ Y) != X --> Y != 0
7394 Register Dst = MI.getOperand(0).getReg();
7395 CmpInst::Predicate Pred;
7396 Register X, Y, OpLHS, OpRHS;
7397 bool MatchedSub = mi_match(
7398 Dst, MRI,
7399 m_c_GICmp(m_Pred(Pred), m_Reg(X), m_GSub(m_Reg(OpLHS), m_Reg(Y))));
7400 if (MatchedSub && X != OpLHS)
7401 return false;
7402 if (!MatchedSub) {
7403 if (!mi_match(Dst, MRI,
7404 m_c_GICmp(m_Pred(Pred), m_Reg(X),
7405 m_any_of(m_GAdd(m_Reg(OpLHS), m_Reg(OpRHS)),
7406 m_GXor(m_Reg(OpLHS), m_Reg(OpRHS))))))
7407 return false;
7408 Y = X == OpLHS ? OpRHS : X == OpRHS ? OpLHS : Register();
7409 }
7410 MatchInfo = [=](MachineIRBuilder &B) {
7411 auto Zero = B.buildConstant(MRI.getType(Y), 0);
7412 B.buildICmp(Pred, Dst, Y, Zero);
7413 };
7414 return CmpInst::isEquality(Pred) && Y.isValid();
7415}
7416
7417/// Return the minimum useless shift amount that results in complete loss of the
7418/// source value. Return std::nullopt when it cannot determine a value.
7419static std::optional<unsigned>
7420getMinUselessShift(KnownBits ValueKB, unsigned Opcode,
7421 std::optional<int64_t> &Result) {
7422 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR ||
7423 Opcode == TargetOpcode::G_ASHR) &&
7424 "Expect G_SHL, G_LSHR or G_ASHR.");
7425 auto SignificantBits = 0;
7426 switch (Opcode) {
7427 case TargetOpcode::G_SHL:
7428 SignificantBits = ValueKB.countMinTrailingZeros();
7429 Result = 0;
7430 break;
7431 case TargetOpcode::G_LSHR:
7432 Result = 0;
7433 SignificantBits = ValueKB.countMinLeadingZeros();
7434 break;
7435 case TargetOpcode::G_ASHR:
7436 if (ValueKB.isNonNegative()) {
7437 SignificantBits = ValueKB.countMinLeadingZeros();
7438 Result = 0;
7439 } else if (ValueKB.isNegative()) {
7440 SignificantBits = ValueKB.countMinLeadingOnes();
7441 Result = -1;
7442 } else {
7443 // Cannot determine shift result.
7444 Result = std::nullopt;
7445 }
7446 break;
7447 default:
7448 break;
7449 }
7450 return ValueKB.getBitWidth() - SignificantBits;
7451}
7452
7454 MachineInstr &MI, std::optional<int64_t> &MatchInfo) const {
7455 Register ShiftVal = MI.getOperand(1).getReg();
7456 Register ShiftReg = MI.getOperand(2).getReg();
7457 LLT ResTy = MRI.getType(MI.getOperand(0).getReg());
7458 auto IsShiftTooBig = [&](const Constant *C) {
7459 auto *CI = dyn_cast<ConstantInt>(C);
7460 if (!CI)
7461 return false;
7462 if (CI->uge(ResTy.getScalarSizeInBits())) {
7463 MatchInfo = std::nullopt;
7464 return true;
7465 }
7466 auto OptMaxUsefulShift = getMinUselessShift(VT->getKnownBits(ShiftVal),
7467 MI.getOpcode(), MatchInfo);
7468 return OptMaxUsefulShift && CI->uge(*OptMaxUsefulShift);
7469 };
7470 return matchUnaryPredicate(MRI, ShiftReg, IsShiftTooBig);
7471}
7472
7474 unsigned LHSOpndIdx = 1;
7475 unsigned RHSOpndIdx = 2;
7476 switch (MI.getOpcode()) {
7477 case TargetOpcode::G_UADDO:
7478 case TargetOpcode::G_SADDO:
7479 case TargetOpcode::G_UMULO:
7480 case TargetOpcode::G_SMULO:
7481 LHSOpndIdx = 2;
7482 RHSOpndIdx = 3;
7483 break;
7484 default:
7485 break;
7486 }
7487 Register LHS = MI.getOperand(LHSOpndIdx).getReg();
7488 Register RHS = MI.getOperand(RHSOpndIdx).getReg();
7489 MachineInstr *LHSDef, *RHSDef;
7490 if (!mi_match(LHS, MRI, m_MInstr(LHSDef)) ||
7491 !mi_match(RHS, MRI, m_MInstr(RHSDef)))
7492 return false;
7493
7494 if (!getIConstantVRegVal(LHS, MRI)) {
7495 // Skip commuting if LHS is not a constant. But, LHS may be a
7496 // G_CONSTANT_FOLD_BARRIER. If so we commute as long as we don't already
7497 // have a constant on the RHS.
7498 if (LHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER)
7499 return false;
7500 }
7501 // Commute as long as RHS is not a constant or G_CONSTANT_FOLD_BARRIER.
7502 return RHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER &&
7503 !getIConstantVRegVal(RHS, MRI);
7504}
7505
7507 Register LHS = MI.getOperand(1).getReg();
7508 Register RHS = MI.getOperand(2).getReg();
7509 std::optional<FPValueAndVReg> ValAndVReg;
7510 if (!mi_match(LHS, MRI, m_GFCstOrSplat(ValAndVReg)))
7511 return false;
7512 return !mi_match(RHS, MRI, m_GFCstOrSplat(ValAndVReg));
7513}
7514
7516 Observer.changingInstr(MI);
7517 unsigned LHSOpndIdx = 1;
7518 unsigned RHSOpndIdx = 2;
7519 switch (MI.getOpcode()) {
7520 case TargetOpcode::G_UADDO:
7521 case TargetOpcode::G_SADDO:
7522 case TargetOpcode::G_UMULO:
7523 case TargetOpcode::G_SMULO:
7524 LHSOpndIdx = 2;
7525 RHSOpndIdx = 3;
7526 break;
7527 default:
7528 break;
7529 }
7530 Register LHSReg = MI.getOperand(LHSOpndIdx).getReg();
7531 Register RHSReg = MI.getOperand(RHSOpndIdx).getReg();
7532 MI.getOperand(LHSOpndIdx).setReg(RHSReg);
7533 MI.getOperand(RHSOpndIdx).setReg(LHSReg);
7534 Observer.changedInstr(MI);
7535}
7536
7537bool CombinerHelper::isOneOrOneSplat(Register Src, bool AllowUndefs) const {
7538 LLT SrcTy = MRI.getType(Src);
7539 if (SrcTy.isFixedVector())
7540 return isConstantSplatVector(Src, 1, AllowUndefs);
7541 if (SrcTy.isScalar()) {
7542 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7543 return true;
7544 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7545 return IConstant && IConstant->Value == 1;
7546 }
7547 return false; // scalable vector
7548}
7549
7550bool CombinerHelper::isZeroOrZeroSplat(Register Src, bool AllowUndefs) const {
7551 LLT SrcTy = MRI.getType(Src);
7552 if (SrcTy.isFixedVector())
7553 return isConstantSplatVector(Src, 0, AllowUndefs);
7554 if (SrcTy.isScalar()) {
7555 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7556 return true;
7557 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7558 return IConstant && IConstant->Value == 0;
7559 }
7560 return false; // scalable vector
7561}
7562
7563// Ignores COPYs during conformance checks.
7564// FIXME scalable vectors.
7565bool CombinerHelper::isConstantSplatVector(Register Src, int64_t SplatValue,
7566 bool AllowUndefs) const {
7567 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7568 if (!BuildVector)
7569 return false;
7570 unsigned NumSources = BuildVector->getNumSources();
7571
7572 for (unsigned I = 0; I < NumSources; ++I) {
7573 GImplicitDef *ImplicitDef =
7575 if (ImplicitDef && AllowUndefs)
7576 continue;
7577 if (ImplicitDef && !AllowUndefs)
7578 return false;
7579 std::optional<ValueAndVReg> IConstant =
7581 if (IConstant && IConstant->Value == SplatValue)
7582 continue;
7583 return false;
7584 }
7585 return true;
7586}
7587
7588// Ignores COPYs during lookups.
7589// FIXME scalable vectors
7590std::optional<APInt>
7591CombinerHelper::getConstantOrConstantSplatVector(Register Src) const {
7592 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7593 if (IConstant)
7594 return IConstant->Value;
7595
7596 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7597 if (!BuildVector)
7598 return std::nullopt;
7599 unsigned NumSources = BuildVector->getNumSources();
7600
7601 std::optional<APInt> Value = std::nullopt;
7602 for (unsigned I = 0; I < NumSources; ++I) {
7603 std::optional<ValueAndVReg> IConstant =
7605 if (!IConstant)
7606 return std::nullopt;
7607 if (!Value)
7608 Value = IConstant->Value;
7609 else if (*Value != IConstant->Value)
7610 return std::nullopt;
7611 }
7612 return Value;
7613}
7614
7615// FIXME G_SPLAT_VECTOR
7616bool CombinerHelper::isConstantOrConstantVectorI(Register Src) const {
7617 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7618 if (IConstant)
7619 return true;
7620
7621 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7622 if (!BuildVector)
7623 return false;
7624
7625 unsigned NumSources = BuildVector->getNumSources();
7626 for (unsigned I = 0; I < NumSources; ++I) {
7627 std::optional<ValueAndVReg> IConstant =
7629 if (!IConstant)
7630 return false;
7631 }
7632 return true;
7633}
7634
7635// TODO: use knownbits to determine zeros
7636bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
7637 BuildFnTy &MatchInfo) const {
7638 uint32_t Flags = Select->getFlags();
7639 Register Dest = Select->getReg(0);
7640 Register Cond = Select->getCondReg();
7641 Register True = Select->getTrueReg();
7642 Register False = Select->getFalseReg();
7643 LLT CondTy = MRI.getType(Select->getCondReg());
7644 LLT TrueTy = MRI.getType(Select->getTrueReg());
7645
7646 // We only do this combine for scalar boolean conditions.
7647 if (CondTy != LLT::scalar(1))
7648 return false;
7649
7650 if (TrueTy.isPointer())
7651 return false;
7652
7653 // Both are scalars.
7654 std::optional<ValueAndVReg> TrueOpt =
7656 std::optional<ValueAndVReg> FalseOpt =
7658
7659 if (!TrueOpt || !FalseOpt)
7660 return false;
7661
7662 APInt TrueValue = TrueOpt->Value;
7663 APInt FalseValue = FalseOpt->Value;
7664
7665 // select Cond, 1, 0 --> zext (Cond)
7666 if (TrueValue.isOne() && FalseValue.isZero()) {
7667 MatchInfo = [=](MachineIRBuilder &B) {
7668 B.setInstrAndDebugLoc(*Select);
7669 B.buildZExtOrTrunc(Dest, Cond);
7670 };
7671 return true;
7672 }
7673
7674 // select Cond, -1, 0 --> sext (Cond)
7675 if (TrueValue.isAllOnes() && FalseValue.isZero()) {
7676 MatchInfo = [=](MachineIRBuilder &B) {
7677 B.setInstrAndDebugLoc(*Select);
7678 B.buildSExtOrTrunc(Dest, Cond);
7679 };
7680 return true;
7681 }
7682
7683 // select Cond, 0, 1 --> zext (!Cond)
7684 if (TrueValue.isZero() && FalseValue.isOne()) {
7685 MatchInfo = [=](MachineIRBuilder &B) {
7686 B.setInstrAndDebugLoc(*Select);
7687 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7688 B.buildNot(Inner, Cond);
7689 B.buildZExtOrTrunc(Dest, Inner);
7690 };
7691 return true;
7692 }
7693
7694 // select Cond, 0, -1 --> sext (!Cond)
7695 if (TrueValue.isZero() && FalseValue.isAllOnes()) {
7696 MatchInfo = [=](MachineIRBuilder &B) {
7697 B.setInstrAndDebugLoc(*Select);
7698 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7699 B.buildNot(Inner, Cond);
7700 B.buildSExtOrTrunc(Dest, Inner);
7701 };
7702 return true;
7703 }
7704
7705 // select Cond, C1, C1-1 --> add (zext Cond), C1-1
7706 if (TrueValue - 1 == FalseValue) {
7707 MatchInfo = [=](MachineIRBuilder &B) {
7708 B.setInstrAndDebugLoc(*Select);
7709 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7710 B.buildZExtOrTrunc(Inner, Cond);
7711 B.buildAdd(Dest, Inner, False);
7712 };
7713 return true;
7714 }
7715
7716 // select Cond, C1, C1+1 --> add (sext Cond), C1+1
7717 if (TrueValue + 1 == FalseValue) {
7718 MatchInfo = [=](MachineIRBuilder &B) {
7719 B.setInstrAndDebugLoc(*Select);
7720 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7721 B.buildSExtOrTrunc(Inner, Cond);
7722 B.buildAdd(Dest, Inner, False);
7723 };
7724 return true;
7725 }
7726
7727 // select Cond, Pow2, 0 --> (zext Cond) << log2(Pow2)
7728 if (TrueValue.isPowerOf2() && FalseValue.isZero()) {
7729 MatchInfo = [=](MachineIRBuilder &B) {
7730 B.setInstrAndDebugLoc(*Select);
7731 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7732 B.buildZExtOrTrunc(Inner, Cond);
7733 // The shift amount must be scalar.
7734 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7735 auto ShAmtC = B.buildConstant(ShiftTy, TrueValue.exactLogBase2());
7736 B.buildShl(Dest, Inner, ShAmtC, Flags);
7737 };
7738 return true;
7739 }
7740
7741 // select Cond, 0, Pow2 --> (zext (!Cond)) << log2(Pow2)
7742 if (FalseValue.isPowerOf2() && TrueValue.isZero()) {
7743 MatchInfo = [=](MachineIRBuilder &B) {
7744 B.setInstrAndDebugLoc(*Select);
7745 Register Not = MRI.createGenericVirtualRegister(CondTy);
7746 B.buildNot(Not, Cond);
7747 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7748 B.buildZExtOrTrunc(Inner, Not);
7749 // The shift amount must be scalar.
7750 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7751 auto ShAmtC = B.buildConstant(ShiftTy, FalseValue.exactLogBase2());
7752 B.buildShl(Dest, Inner, ShAmtC, Flags);
7753 };
7754 return true;
7755 }
7756
7757 // select Cond, -1, C --> or (sext Cond), C
7758 if (TrueValue.isAllOnes()) {
7759 MatchInfo = [=](MachineIRBuilder &B) {
7760 B.setInstrAndDebugLoc(*Select);
7761 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7762 B.buildSExtOrTrunc(Inner, Cond);
7763 B.buildOr(Dest, Inner, False, Flags);
7764 };
7765 return true;
7766 }
7767
7768 // select Cond, C, -1 --> or (sext (not Cond)), C
7769 if (FalseValue.isAllOnes()) {
7770 MatchInfo = [=](MachineIRBuilder &B) {
7771 B.setInstrAndDebugLoc(*Select);
7772 Register Not = MRI.createGenericVirtualRegister(CondTy);
7773 B.buildNot(Not, Cond);
7774 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7775 B.buildSExtOrTrunc(Inner, Not);
7776 B.buildOr(Dest, Inner, True, Flags);
7777 };
7778 return true;
7779 }
7780
7781 return false;
7782}
7783
7784// TODO: use knownbits to determine zeros
7785bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
7786 BuildFnTy &MatchInfo) const {
7787 uint32_t Flags = Select->getFlags();
7788 Register DstReg = Select->getReg(0);
7789 Register Cond = Select->getCondReg();
7790 Register True = Select->getTrueReg();
7791 Register False = Select->getFalseReg();
7792 LLT CondTy = MRI.getType(Select->getCondReg());
7793 LLT TrueTy = MRI.getType(Select->getTrueReg());
7794
7795 // Boolean or fixed vector of booleans.
7796 if (CondTy.isScalableVector() ||
7797 (CondTy.isFixedVector() &&
7798 CondTy.getElementType().getScalarSizeInBits() != 1) ||
7799 CondTy.getScalarSizeInBits() != 1)
7800 return false;
7801
7802 if (CondTy != TrueTy)
7803 return false;
7804
7805 // select Cond, Cond, F --> or Cond, F
7806 // select Cond, 1, F --> or Cond, F
7807 if ((Cond == True) || isOneOrOneSplat(True, /* AllowUndefs */ true)) {
7808 MatchInfo = [=](MachineIRBuilder &B) {
7809 B.setInstrAndDebugLoc(*Select);
7810 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7811 B.buildZExtOrTrunc(Ext, Cond);
7812 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7813 B.buildOr(DstReg, Ext, FreezeFalse, Flags);
7814 };
7815 return true;
7816 }
7817
7818 // select Cond, T, Cond --> and Cond, T
7819 // select Cond, T, 0 --> and Cond, T
7820 if ((Cond == False) || isZeroOrZeroSplat(False, /* AllowUndefs */ true)) {
7821 MatchInfo = [=](MachineIRBuilder &B) {
7822 B.setInstrAndDebugLoc(*Select);
7823 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7824 B.buildZExtOrTrunc(Ext, Cond);
7825 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7826 B.buildAnd(DstReg, Ext, FreezeTrue);
7827 };
7828 return true;
7829 }
7830
7831 // select Cond, T, 1 --> or (not Cond), T
7832 if (isOneOrOneSplat(False, /* AllowUndefs */ true)) {
7833 MatchInfo = [=](MachineIRBuilder &B) {
7834 B.setInstrAndDebugLoc(*Select);
7835 // First the not.
7836 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7837 B.buildNot(Inner, Cond);
7838 // Then an ext to match the destination register.
7839 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7840 B.buildZExtOrTrunc(Ext, Inner);
7841 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7842 B.buildOr(DstReg, Ext, FreezeTrue, Flags);
7843 };
7844 return true;
7845 }
7846
7847 // select Cond, 0, F --> and (not Cond), F
7848 if (isZeroOrZeroSplat(True, /* AllowUndefs */ true)) {
7849 MatchInfo = [=](MachineIRBuilder &B) {
7850 B.setInstrAndDebugLoc(*Select);
7851 // First the not.
7852 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7853 B.buildNot(Inner, Cond);
7854 // Then an ext to match the destination register.
7855 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7856 B.buildZExtOrTrunc(Ext, Inner);
7857 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7858 B.buildAnd(DstReg, Ext, FreezeFalse);
7859 };
7860 return true;
7861 }
7862
7863 return false;
7864}
7865
7867 BuildFnTy &MatchInfo) const {
7868 Register DstReg = MO.getReg();
7869 Register CondReg, True, False;
7870 if (!mi_match(DstReg, MRI,
7871 m_GISelect(m_Reg(CondReg), m_Reg(True), m_Reg(False))))
7872 return false;
7873
7874 CmpInst::Predicate Pred;
7875 Register CmpLHS, CmpRHS;
7876 if (!mi_match(CondReg, MRI,
7877 m_GICmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS))))
7878 return false;
7879
7880 LLT DstTy = MRI.getType(DstReg);
7881 if (DstTy.isPointerOrPointerVector())
7882 return false;
7883
7884 // We want to fold the icmp and replace the select.
7885 if (!MRI.hasOneNonDBGUse(CondReg))
7886 return false;
7887
7888 // We need a larger or smaller predicate for
7889 // canonicalization.
7890 if (CmpInst::isEquality(Pred))
7891 return false;
7892
7893 // We can swap CmpLHS and CmpRHS for higher hitrate.
7894 if (True == CmpRHS && False == CmpLHS) {
7895 std::swap(CmpLHS, CmpRHS);
7896 Pred = CmpInst::getSwappedPredicate(Pred);
7897 }
7898
7899 // (icmp X, Y) ? X : Y -> integer minmax.
7900 // see matchSelectPattern in ValueTracking.
7901 // Legality between G_SELECT and integer minmax can differ.
7902 if (True != CmpLHS || False != CmpRHS)
7903 return false;
7904
7905 switch (Pred) {
7906 case ICmpInst::ICMP_UGT:
7907 case ICmpInst::ICMP_UGE: {
7908 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy}))
7909 return false;
7910 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMax(DstReg, True, False); };
7911 return true;
7912 }
7913 case ICmpInst::ICMP_SGT:
7914 case ICmpInst::ICMP_SGE: {
7915 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy}))
7916 return false;
7917 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMax(DstReg, True, False); };
7918 return true;
7919 }
7920 case ICmpInst::ICMP_ULT:
7921 case ICmpInst::ICMP_ULE: {
7922 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy}))
7923 return false;
7924 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMin(DstReg, True, False); };
7925 return true;
7926 }
7927 case ICmpInst::ICMP_SLT:
7928 case ICmpInst::ICMP_SLE: {
7929 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy}))
7930 return false;
7931 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(DstReg, True, False); };
7932 return true;
7933 }
7934 default:
7935 return false;
7936 }
7937}
7938
7939// (neg (min/max x, (neg x))) --> (max/min x, (neg x))
7941 BuildFnTy &MatchInfo) const {
7942 assert(MI.getOpcode() == TargetOpcode::G_SUB);
7943 Register DestReg = MI.getOperand(0).getReg();
7944 LLT DestTy = MRI.getType(DestReg);
7945
7946 Register X;
7947 Register Sub0;
7948 auto NegPattern = m_all_of(m_Neg(m_DeferredReg(X)), m_Reg(Sub0));
7949 if (mi_match(DestReg, MRI,
7950 m_Neg(m_OneUse(m_any_of(m_GSMin(m_Reg(X), NegPattern),
7951 m_GSMax(m_Reg(X), NegPattern),
7952 m_GUMin(m_Reg(X), NegPattern),
7953 m_GUMax(m_Reg(X), NegPattern)))))) {
7954 MachineInstr *MinMaxMI;
7955 if (!mi_match(MI.getOperand(2).getReg(), MRI, m_MInstr(MinMaxMI)))
7956 return false;
7957 unsigned NewOpc = getInverseGMinMaxOpcode(MinMaxMI->getOpcode());
7958 if (isLegal({NewOpc, {DestTy}})) {
7959 MatchInfo = [=](MachineIRBuilder &B) {
7960 B.buildInstr(NewOpc, {DestReg}, {X, Sub0});
7961 };
7962 return true;
7963 }
7964 }
7965
7966 return false;
7967}
7968
7971
7972 if (tryFoldSelectOfConstants(Select, MatchInfo))
7973 return true;
7974
7975 if (tryFoldBoolSelectToLogic(Select, MatchInfo))
7976 return true;
7977
7978 return false;
7979}
7980
7981/// Fold (icmp Pred1 V1, C1) && (icmp Pred2 V2, C2)
7982/// or (icmp Pred1 V1, C1) || (icmp Pred2 V2, C2)
7983/// into a single comparison using range-based reasoning.
7984/// see InstCombinerImpl::foldAndOrOfICmpsUsingRanges.
7985bool CombinerHelper::tryFoldAndOrOrICmpsUsingRanges(
7986 GLogicalBinOp *Logic, BuildFnTy &MatchInfo) const {
7987 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpected xor");
7988 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
7989 Register DstReg = Logic->getReg(0);
7990 Register LHS = Logic->getLHSReg();
7991 Register RHS = Logic->getRHSReg();
7992 unsigned Flags = Logic->getFlags();
7993
7994 // We need an G_ICMP on the LHS register.
7995 GICmp *Cmp1 = getOpcodeDef<GICmp>(LHS, MRI);
7996 if (!Cmp1)
7997 return false;
7998
7999 // We need an G_ICMP on the RHS register.
8000 GICmp *Cmp2 = getOpcodeDef<GICmp>(RHS, MRI);
8001 if (!Cmp2)
8002 return false;
8003
8004 // We want to fold the icmps.
8005 if (!MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
8006 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)))
8007 return false;
8008
8009 APInt C1;
8010 APInt C2;
8011 std::optional<ValueAndVReg> MaybeC1 =
8013 if (!MaybeC1)
8014 return false;
8015 C1 = MaybeC1->Value;
8016
8017 std::optional<ValueAndVReg> MaybeC2 =
8019 if (!MaybeC2)
8020 return false;
8021 C2 = MaybeC2->Value;
8022
8023 Register R1 = Cmp1->getLHSReg();
8024 Register R2 = Cmp2->getLHSReg();
8025 CmpInst::Predicate Pred1 = Cmp1->getCond();
8026 CmpInst::Predicate Pred2 = Cmp2->getCond();
8027 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
8028 LLT CmpOperandTy = MRI.getType(R1);
8029
8030 if (CmpOperandTy.isPointer())
8031 return false;
8032
8033 // We build ands, adds, and constants of type CmpOperandTy.
8034 // They must be legal to build.
8035 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_AND, CmpOperandTy}) ||
8036 !isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, CmpOperandTy}) ||
8037 !isConstantLegalOrBeforeLegalizer(CmpOperandTy))
8038 return false;
8039
8040 // Look through add of a constant offset on R1, R2, or both operands. This
8041 // allows us to interpret the R + C' < C'' range idiom into a proper range.
8042 std::optional<APInt> Offset1;
8043 std::optional<APInt> Offset2;
8044 if (R1 != R2) {
8045 if (GAdd *Add = getOpcodeDef<GAdd>(R1, MRI)) {
8046 std::optional<ValueAndVReg> MaybeOffset1 =
8048 if (MaybeOffset1) {
8049 R1 = Add->getLHSReg();
8050 Offset1 = MaybeOffset1->Value;
8051 }
8052 }
8053 if (GAdd *Add = getOpcodeDef<GAdd>(R2, MRI)) {
8054 std::optional<ValueAndVReg> MaybeOffset2 =
8056 if (MaybeOffset2) {
8057 R2 = Add->getLHSReg();
8058 Offset2 = MaybeOffset2->Value;
8059 }
8060 }
8061 }
8062
8063 if (R1 != R2)
8064 return false;
8065
8066 // We calculate the icmp ranges including maybe offsets.
8067 ConstantRange CR1 = ConstantRange::makeExactICmpRegion(
8068 IsAnd ? ICmpInst::getInversePredicate(Pred1) : Pred1, C1);
8069 if (Offset1)
8070 CR1 = CR1.subtract(*Offset1);
8071
8072 ConstantRange CR2 = ConstantRange::makeExactICmpRegion(
8073 IsAnd ? ICmpInst::getInversePredicate(Pred2) : Pred2, C2);
8074 if (Offset2)
8075 CR2 = CR2.subtract(*Offset2);
8076
8077 bool CreateMask = false;
8078 APInt LowerDiff;
8079 std::optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
8080 if (!CR) {
8081 // We need non-wrapping ranges.
8082 if (CR1.isWrappedSet() || CR2.isWrappedSet())
8083 return false;
8084
8085 // Check whether we have equal-size ranges that only differ by one bit.
8086 // In that case we can apply a mask to map one range onto the other.
8087 LowerDiff = CR1.getLower() ^ CR2.getLower();
8088 APInt UpperDiff = (CR1.getUpper() - 1) ^ (CR2.getUpper() - 1);
8089 APInt CR1Size = CR1.getUpper() - CR1.getLower();
8090 if (!LowerDiff.isPowerOf2() || LowerDiff != UpperDiff ||
8091 CR1Size != CR2.getUpper() - CR2.getLower())
8092 return false;
8093
8094 CR = CR1.getLower().ult(CR2.getLower()) ? CR1 : CR2;
8095 CreateMask = true;
8096 }
8097
8098 if (IsAnd)
8099 CR = CR->inverse();
8100
8101 CmpInst::Predicate NewPred;
8102 APInt NewC, Offset;
8103 CR->getEquivalentICmp(NewPred, NewC, Offset);
8104
8105 // We take the result type of one of the original icmps, CmpTy, for
8106 // the to be build icmp. The operand type, CmpOperandTy, is used for
8107 // the other instructions and constants to be build. The types of
8108 // the parameters and output are the same for add and and. CmpTy
8109 // and the type of DstReg might differ. That is why we zext or trunc
8110 // the icmp into the destination register.
8111
8112 MatchInfo = [=](MachineIRBuilder &B) {
8113 if (CreateMask && Offset != 0) {
8114 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
8115 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
8116 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
8117 auto Add = B.buildAdd(CmpOperandTy, And, OffsetC, Flags);
8118 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
8119 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
8120 B.buildZExtOrTrunc(DstReg, ICmp);
8121 } else if (CreateMask && Offset == 0) {
8122 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
8123 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
8124 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
8125 auto ICmp = B.buildICmp(NewPred, CmpTy, And, NewCon);
8126 B.buildZExtOrTrunc(DstReg, ICmp);
8127 } else if (!CreateMask && Offset != 0) {
8128 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
8129 auto Add = B.buildAdd(CmpOperandTy, R1, OffsetC, Flags);
8130 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
8131 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
8132 B.buildZExtOrTrunc(DstReg, ICmp);
8133 } else if (!CreateMask && Offset == 0) {
8134 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
8135 auto ICmp = B.buildICmp(NewPred, CmpTy, R1, NewCon);
8136 B.buildZExtOrTrunc(DstReg, ICmp);
8137 } else {
8138 llvm_unreachable("unexpected configuration of CreateMask and Offset");
8139 }
8140 };
8141 return true;
8142}
8143
8144bool CombinerHelper::tryFoldLogicOfFCmps(GLogicalBinOp *Logic,
8145 BuildFnTy &MatchInfo) const {
8146 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpecte xor");
8147 Register DestReg = Logic->getReg(0);
8148 Register LHS = Logic->getLHSReg();
8149 Register RHS = Logic->getRHSReg();
8150 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
8151
8152 // We need a compare on the LHS register.
8153 GFCmp *Cmp1 = getOpcodeDef<GFCmp>(LHS, MRI);
8154 if (!Cmp1)
8155 return false;
8156
8157 // We need a compare on the RHS register.
8158 GFCmp *Cmp2 = getOpcodeDef<GFCmp>(RHS, MRI);
8159 if (!Cmp2)
8160 return false;
8161
8162 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
8163 LLT CmpOperandTy = MRI.getType(Cmp1->getLHSReg());
8164
8165 // We build one fcmp, want to fold the fcmps, replace the logic op,
8166 // and the fcmps must have the same shape.
8168 {TargetOpcode::G_FCMP, {CmpTy, CmpOperandTy}}) ||
8169 !MRI.hasOneNonDBGUse(Logic->getReg(0)) ||
8170 !MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
8171 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)) ||
8172 MRI.getType(Cmp1->getLHSReg()) != MRI.getType(Cmp2->getLHSReg()))
8173 return false;
8174
8175 CmpInst::Predicate PredL = Cmp1->getCond();
8176 CmpInst::Predicate PredR = Cmp2->getCond();
8177 Register LHS0 = Cmp1->getLHSReg();
8178 Register LHS1 = Cmp1->getRHSReg();
8179 Register RHS0 = Cmp2->getLHSReg();
8180 Register RHS1 = Cmp2->getRHSReg();
8181
8182 if (LHS0 == RHS1 && LHS1 == RHS0) {
8183 // Swap RHS operands to match LHS.
8184 PredR = CmpInst::getSwappedPredicate(PredR);
8185 std::swap(RHS0, RHS1);
8186 }
8187
8188 if (LHS0 == RHS0 && LHS1 == RHS1) {
8189 // We determine the new predicate.
8190 unsigned CmpCodeL = getFCmpCode(PredL);
8191 unsigned CmpCodeR = getFCmpCode(PredR);
8192 unsigned NewPred = IsAnd ? CmpCodeL & CmpCodeR : CmpCodeL | CmpCodeR;
8193 unsigned Flags = Cmp1->getFlags() | Cmp2->getFlags();
8194 MatchInfo = [=](MachineIRBuilder &B) {
8195 // The fcmp predicates fill the lower part of the enum.
8196 FCmpInst::Predicate Pred = static_cast<FCmpInst::Predicate>(NewPred);
8197 if (Pred == FCmpInst::FCMP_FALSE &&
8199 auto False = B.buildConstant(CmpTy, 0);
8200 B.buildZExtOrTrunc(DestReg, False);
8201 } else if (Pred == FCmpInst::FCMP_TRUE &&
8203 auto True =
8204 B.buildConstant(CmpTy, getICmpTrueVal(getTargetLowering(),
8205 CmpTy.isVector() /*isVector*/,
8206 true /*isFP*/));
8207 B.buildZExtOrTrunc(DestReg, True);
8208 } else { // We take the predicate without predicate optimizations.
8209 auto Cmp = B.buildFCmp(Pred, CmpTy, LHS0, LHS1, Flags);
8210 B.buildZExtOrTrunc(DestReg, Cmp);
8211 }
8212 };
8213 return true;
8214 }
8215
8216 return false;
8217}
8218
8220 GAnd *And = cast<GAnd>(&MI);
8221
8222 if (tryFoldAndOrOrICmpsUsingRanges(And, MatchInfo))
8223 return true;
8224
8225 if (tryFoldLogicOfFCmps(And, MatchInfo))
8226 return true;
8227
8228 return false;
8229}
8230
8232 GOr *Or = cast<GOr>(&MI);
8233
8234 if (tryFoldAndOrOrICmpsUsingRanges(Or, MatchInfo))
8235 return true;
8236
8237 if (tryFoldLogicOfFCmps(Or, MatchInfo))
8238 return true;
8239
8240 return false;
8241}
8242
8244 BuildFnTy &MatchInfo) const {
8246
8247 // Addo has no flags
8248 Register Dst = Add->getReg(0);
8249 Register Carry = Add->getReg(1);
8250 Register LHS = Add->getLHSReg();
8251 Register RHS = Add->getRHSReg();
8252 bool IsSigned = Add->isSigned();
8253 LLT DstTy = MRI.getType(Dst);
8254 LLT CarryTy = MRI.getType(Carry);
8255
8256 // Fold addo, if the carry is dead -> add, undef.
8257 if (MRI.use_nodbg_empty(Carry) &&
8258 isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}})) {
8259 MatchInfo = [=](MachineIRBuilder &B) {
8260 B.buildAdd(Dst, LHS, RHS);
8261 B.buildUndef(Carry);
8262 };
8263 return true;
8264 }
8265
8266 // Canonicalize constant to RHS.
8267 if (isConstantOrConstantVectorI(LHS) && !isConstantOrConstantVectorI(RHS)) {
8268 if (IsSigned) {
8269 MatchInfo = [=](MachineIRBuilder &B) {
8270 B.buildSAddo(Dst, Carry, RHS, LHS);
8271 };
8272 return true;
8273 }
8274 // !IsSigned
8275 MatchInfo = [=](MachineIRBuilder &B) {
8276 B.buildUAddo(Dst, Carry, RHS, LHS);
8277 };
8278 return true;
8279 }
8280
8281 std::optional<APInt> MaybeLHS = getConstantOrConstantSplatVector(LHS);
8282 std::optional<APInt> MaybeRHS = getConstantOrConstantSplatVector(RHS);
8283
8284 // Fold addo(c1, c2) -> c3, carry.
8285 if (MaybeLHS && MaybeRHS && isConstantLegalOrBeforeLegalizer(DstTy) &&
8287 bool Overflow;
8288 APInt Result = IsSigned ? MaybeLHS->sadd_ov(*MaybeRHS, Overflow)
8289 : MaybeLHS->uadd_ov(*MaybeRHS, Overflow);
8290 MatchInfo = [=](MachineIRBuilder &B) {
8291 B.buildConstant(Dst, Result);
8292 B.buildConstant(Carry, Overflow);
8293 };
8294 return true;
8295 }
8296
8297 // Fold (addo x, 0) -> x, no carry
8298 if (MaybeRHS && *MaybeRHS == 0 && isConstantLegalOrBeforeLegalizer(CarryTy)) {
8299 MatchInfo = [=](MachineIRBuilder &B) {
8300 B.buildCopy(Dst, LHS);
8301 B.buildConstant(Carry, 0);
8302 };
8303 return true;
8304 }
8305
8306 // Given 2 constant operands whose sum does not overflow:
8307 // uaddo (X +nuw C0), C1 -> uaddo X, C0 + C1
8308 // saddo (X +nsw C0), C1 -> saddo X, C0 + C1
8309 GAdd *AddLHS = getOpcodeDef<GAdd>(LHS, MRI);
8310 if (MaybeRHS && AddLHS && MRI.hasOneNonDBGUse(Add->getReg(0)) &&
8311 ((IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoSWrap)) ||
8312 (!IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoUWrap)))) {
8313 std::optional<APInt> MaybeAddRHS =
8314 getConstantOrConstantSplatVector(AddLHS->getRHSReg());
8315 if (MaybeAddRHS) {
8316 bool Overflow;
8317 APInt NewC = IsSigned ? MaybeAddRHS->sadd_ov(*MaybeRHS, Overflow)
8318 : MaybeAddRHS->uadd_ov(*MaybeRHS, Overflow);
8319 if (!Overflow && isConstantLegalOrBeforeLegalizer(DstTy)) {
8320 if (IsSigned) {
8321 MatchInfo = [=](MachineIRBuilder &B) {
8322 auto ConstRHS = B.buildConstant(DstTy, NewC);
8323 B.buildSAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
8324 };
8325 return true;
8326 }
8327 // !IsSigned
8328 MatchInfo = [=](MachineIRBuilder &B) {
8329 auto ConstRHS = B.buildConstant(DstTy, NewC);
8330 B.buildUAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
8331 };
8332 return true;
8333 }
8334 }
8335 };
8336
8337 // We try to combine addo to non-overflowing add.
8338 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}}) ||
8340 return false;
8341
8342 // We try to combine uaddo to non-overflowing add.
8343 if (!IsSigned) {
8344 ConstantRange CRLHS =
8345 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/false);
8346 ConstantRange CRRHS =
8347 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/false);
8348
8349 switch (CRLHS.unsignedAddMayOverflow(CRRHS)) {
8351 return false;
8353 MatchInfo = [=](MachineIRBuilder &B) {
8354 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
8355 B.buildConstant(Carry, 0);
8356 };
8357 return true;
8358 }
8361 MatchInfo = [=](MachineIRBuilder &B) {
8362 B.buildAdd(Dst, LHS, RHS);
8363 B.buildConstant(Carry, 1);
8364 };
8365 return true;
8366 }
8367 }
8368 return false;
8369 }
8370
8371 // We try to combine saddo to non-overflowing add.
8372
8373 // If LHS and RHS each have at least two sign bits, then there is no signed
8374 // overflow.
8375 if (VT->computeNumSignBits(RHS) > 1 && VT->computeNumSignBits(LHS) > 1) {
8376 MatchInfo = [=](MachineIRBuilder &B) {
8377 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8378 B.buildConstant(Carry, 0);
8379 };
8380 return true;
8381 }
8382
8383 ConstantRange CRLHS =
8384 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/true);
8385 ConstantRange CRRHS =
8386 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/true);
8387
8388 switch (CRLHS.signedAddMayOverflow(CRRHS)) {
8390 return false;
8392 MatchInfo = [=](MachineIRBuilder &B) {
8393 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8394 B.buildConstant(Carry, 0);
8395 };
8396 return true;
8397 }
8400 MatchInfo = [=](MachineIRBuilder &B) {
8401 B.buildAdd(Dst, LHS, RHS);
8402 B.buildConstant(Carry, 1);
8403 };
8404 return true;
8405 }
8406 }
8407
8408 return false;
8409}
8410
8412 BuildFnTy &MatchInfo) const {
8414 MatchInfo(Builder);
8415 Root->eraseFromParent();
8416}
8417
8419 int64_t Exponent) const {
8420 bool OptForSize = MI.getMF()->getFunction().hasOptSize();
8422}
8423
8425 int64_t Exponent) const {
8426 auto [Dst, Base] = MI.getFirst2Regs();
8427 LLT Ty = MRI.getType(Dst);
8428 int64_t ExpVal = Exponent;
8429
8430 if (ExpVal == 0) {
8431 Builder.buildFConstant(Dst, 1.0);
8432 MI.removeFromParent();
8433 return;
8434 }
8435
8436 if (ExpVal < 0)
8437 ExpVal = -ExpVal;
8438
8439 // We use the simple binary decomposition method from SelectionDAG ExpandPowI
8440 // to generate the multiply sequence. There are more optimal ways to do this
8441 // (for example, powi(x,15) generates one more multiply than it should), but
8442 // this has the benefit of being both really simple and much better than a
8443 // libcall.
8444 std::optional<SrcOp> Res;
8445 SrcOp CurSquare = Base;
8446 while (ExpVal > 0) {
8447 if (ExpVal & 1) {
8448 if (!Res)
8449 Res = CurSquare;
8450 else
8451 Res = Builder.buildFMul(Ty, *Res, CurSquare);
8452 }
8453
8454 CurSquare = Builder.buildFMul(Ty, CurSquare, CurSquare);
8455 ExpVal >>= 1;
8456 }
8457
8458 // If the original exponent was negative, invert the result, producing
8459 // 1/(x*x*x).
8460 if (Exponent < 0)
8461 Res = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0), *Res,
8462 MI.getFlags());
8463
8464 Builder.buildCopy(Dst, *Res);
8465 MI.eraseFromParent();
8466}
8467
8469 BuildFnTy &MatchInfo) const {
8470 // fold (A+C1)-C2 -> A+(C1-C2)
8471 const GSub *Sub = cast<GSub>(&MI);
8472 Register A, C1Reg;
8473 if (!mi_match(Sub->getLHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8474 return false;
8475
8476 if (!MRI.hasOneNonDBGUse(Sub->getLHSReg()))
8477 return false;
8478
8479 APInt C2 = getIConstantFromReg(Sub->getRHSReg(), MRI);
8480 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8481
8482 Register Dst = Sub->getReg(0);
8483 LLT DstTy = MRI.getType(Dst);
8484
8485 MatchInfo = [=](MachineIRBuilder &B) {
8486 auto Const = B.buildConstant(DstTy, C1 - C2);
8487 B.buildAdd(Dst, A, Const);
8488 };
8489
8490 return true;
8491}
8492
8494 BuildFnTy &MatchInfo) const {
8495 // fold C2-(A+C1) -> (C2-C1)-A
8496 const GSub *Sub = cast<GSub>(&MI);
8497 Register A, C1Reg;
8498 if (!mi_match(Sub->getRHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8499 return false;
8500
8501 if (!MRI.hasOneNonDBGUse(Sub->getRHSReg()))
8502 return false;
8503
8504 APInt C2 = getIConstantFromReg(Sub->getLHSReg(), MRI);
8505 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8506
8507 Register Dst = Sub->getReg(0);
8508 LLT DstTy = MRI.getType(Dst);
8509
8510 MatchInfo = [=](MachineIRBuilder &B) {
8511 auto Const = B.buildConstant(DstTy, C2 - C1);
8512 B.buildSub(Dst, Const, A);
8513 };
8514
8515 return true;
8516}
8517
8519 BuildFnTy &MatchInfo) const {
8520 // fold (A-C1)-C2 -> A-(C1+C2)
8521 const GSub *Sub1 = cast<GSub>(&MI);
8522 Register A, C1Reg;
8523 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8524 return false;
8525
8526 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8527 return false;
8528
8529 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8530 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8531
8532 Register Dst = Sub1->getReg(0);
8533 LLT DstTy = MRI.getType(Dst);
8534
8535 MatchInfo = [=](MachineIRBuilder &B) {
8536 auto Const = B.buildConstant(DstTy, C1 + C2);
8537 B.buildSub(Dst, A, Const);
8538 };
8539
8540 return true;
8541}
8542
8544 BuildFnTy &MatchInfo) const {
8545 // fold (C1-A)-C2 -> (C1-C2)-A
8546 const GSub *Sub1 = cast<GSub>(&MI);
8547 Register C1Reg, A;
8548 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(C1Reg), m_Reg(A))))
8549 return false;
8550
8551 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8552 return false;
8553
8554 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8555 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8556
8557 Register Dst = Sub1->getReg(0);
8558 LLT DstTy = MRI.getType(Dst);
8559
8560 MatchInfo = [=](MachineIRBuilder &B) {
8561 auto Const = B.buildConstant(DstTy, C1 - C2);
8562 B.buildSub(Dst, Const, A);
8563 };
8564
8565 return true;
8566}
8567
8569 BuildFnTy &MatchInfo) const {
8570 // fold ((A-C1)+C2) -> (A+(C2-C1))
8571 const GAdd *Add = cast<GAdd>(&MI);
8572 Register A, C1Reg;
8573 if (!mi_match(Add->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8574 return false;
8575
8576 if (!MRI.hasOneNonDBGUse(Add->getLHSReg()))
8577 return false;
8578
8579 APInt C2 = getIConstantFromReg(Add->getRHSReg(), MRI);
8580 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8581
8582 Register Dst = Add->getReg(0);
8583 LLT DstTy = MRI.getType(Dst);
8584
8585 MatchInfo = [=](MachineIRBuilder &B) {
8586 auto Const = B.buildConstant(DstTy, C2 - C1);
8587 B.buildAdd(Dst, A, Const);
8588 };
8589
8590 return true;
8591}
8592
8594 const MachineInstr &MI, BuildFnTy &MatchInfo) const {
8595 const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
8596
8597 if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
8598 return false;
8599
8600 LLT DstTy = MRI.getType(Unmerge->getReg(0));
8601
8602 // $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
8603 // $any:_(<8 x s16>) = G_ANYEXT $bv
8604 // $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
8605 //
8606 // ->
8607 //
8608 // $any:_(s16) = G_ANYEXT $bv[0]
8609 // $any1:_(s16) = G_ANYEXT $bv[1]
8610 // $any2:_(s16) = G_ANYEXT $bv[2]
8611 // $any3:_(s16) = G_ANYEXT $bv[3]
8612 // $any4:_(s16) = G_ANYEXT $bv[4]
8613 // $any5:_(s16) = G_ANYEXT $bv[5]
8614 // $any6:_(s16) = G_ANYEXT $bv[6]
8615 // $any7:_(s16) = G_ANYEXT $bv[7]
8616 // $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
8617 // $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7
8618
8619 // We want to unmerge into vectors.
8620 if (!DstTy.isFixedVector())
8621 return false;
8622
8623 Register AnySrcReg;
8624 if (!mi_match(Unmerge->getSourceReg(), MRI, m_GAnyExt(m_Reg(AnySrcReg))))
8625 return false;
8626
8627 GBuildVector *BV;
8628 if (mi_match(AnySrcReg, MRI, m_GBuildVector(BV))) {
8629 // G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR
8630
8631 if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
8632 return false;
8633
8634 // FIXME: check element types?
8635 if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
8636 return false;
8637
8638 LLT BigBvTy = MRI.getType(BV->getReg(0));
8639 LLT SmallBvTy = DstTy;
8640 LLT SmallBvElemenTy = SmallBvTy.getElementType();
8641
8643 {TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
8644 return false;
8645
8646 // We check the legality of scalar anyext.
8648 {TargetOpcode::G_ANYEXT,
8649 {SmallBvElemenTy, BigBvTy.getElementType()}}))
8650 return false;
8651
8652 MatchInfo = [=](MachineIRBuilder &B) {
8653 // Build into each G_UNMERGE_VALUES def
8654 // a small build vector with anyext from the source build vector.
8655 for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
8657 for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
8658 Register SourceArray =
8659 BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
8660 auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
8661 Ops.push_back(AnyExt.getReg(0));
8662 }
8663 B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
8664 };
8665 };
8666 return true;
8667 };
8668
8669 return false;
8670}
8671
8673 BuildFnTy &MatchInfo) const {
8674
8675 bool Changed = false;
8676 auto &Shuffle = cast<GShuffleVector>(MI);
8677 ArrayRef<int> OrigMask = Shuffle.getMask();
8678 SmallVector<int, 16> NewMask;
8679 const LLT SrcTy = MRI.getType(Shuffle.getSrc1Reg());
8680 const unsigned NumSrcElems = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
8681 const unsigned NumDstElts = OrigMask.size();
8682 for (unsigned i = 0; i != NumDstElts; ++i) {
8683 int Idx = OrigMask[i];
8684 if (Idx >= (int)NumSrcElems) {
8685 Idx = -1;
8686 Changed = true;
8687 }
8688 NewMask.push_back(Idx);
8689 }
8690
8691 if (!Changed)
8692 return false;
8693
8694 MatchInfo = [&, NewMask = std::move(NewMask)](MachineIRBuilder &B) {
8695 B.buildShuffleVector(MI.getOperand(0), MI.getOperand(1), MI.getOperand(2),
8696 std::move(NewMask));
8697 };
8698
8699 return true;
8700}
8701
8702static void commuteMask(MutableArrayRef<int> Mask, const unsigned NumElems) {
8703 const unsigned MaskSize = Mask.size();
8704 for (unsigned I = 0; I < MaskSize; ++I) {
8705 int Idx = Mask[I];
8706 if (Idx < 0)
8707 continue;
8708
8709 if (Idx < (int)NumElems)
8710 Mask[I] = Idx + NumElems;
8711 else
8712 Mask[I] = Idx - NumElems;
8713 }
8714}
8715
8717 BuildFnTy &MatchInfo) const {
8718
8719 auto &Shuffle = cast<GShuffleVector>(MI);
8720 // If any of the two inputs is already undef, don't check the mask again to
8721 // prevent infinite loop
8722 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(), MRI))
8723 return false;
8724
8725 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI))
8726 return false;
8727
8728 const LLT DstTy = MRI.getType(Shuffle.getReg(0));
8729 const LLT Src1Ty = MRI.getType(Shuffle.getSrc1Reg());
8731 {TargetOpcode::G_SHUFFLE_VECTOR, {DstTy, Src1Ty}}))
8732 return false;
8733
8734 ArrayRef<int> Mask = Shuffle.getMask();
8735 const unsigned NumSrcElems = Src1Ty.getNumElements();
8736
8737 bool TouchesSrc1 = false;
8738 bool TouchesSrc2 = false;
8739 const unsigned NumElems = Mask.size();
8740 for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
8741 if (Mask[Idx] < 0)
8742 continue;
8743
8744 if (Mask[Idx] < (int)NumSrcElems)
8745 TouchesSrc1 = true;
8746 else
8747 TouchesSrc2 = true;
8748 }
8749
8750 if (TouchesSrc1 == TouchesSrc2)
8751 return false;
8752
8753 Register NewSrc1 = Shuffle.getSrc1Reg();
8754 SmallVector<int, 16> NewMask(Mask);
8755 if (TouchesSrc2) {
8756 NewSrc1 = Shuffle.getSrc2Reg();
8757 commuteMask(NewMask, NumSrcElems);
8758 }
8759
8760 MatchInfo = [=, &Shuffle](MachineIRBuilder &B) {
8761 auto Undef = B.buildUndef(Src1Ty);
8762 B.buildShuffleVector(Shuffle.getReg(0), NewSrc1, Undef, NewMask);
8763 };
8764
8765 return true;
8766}
8767
8769 BuildFnTy &MatchInfo) const {
8770 const GSubCarryOut *Subo = cast<GSubCarryOut>(&MI);
8771
8772 Register Dst = Subo->getReg(0);
8773 Register LHS = Subo->getLHSReg();
8774 Register RHS = Subo->getRHSReg();
8775 Register Carry = Subo->getCarryOutReg();
8776 LLT DstTy = MRI.getType(Dst);
8777 LLT CarryTy = MRI.getType(Carry);
8778
8779 // Check legality before known bits.
8780 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy}}) ||
8782 return false;
8783
8784 ConstantRange KBLHS =
8785 ConstantRange::fromKnownBits(VT->getKnownBits(LHS),
8786 /* IsSigned=*/Subo->isSigned());
8787 ConstantRange KBRHS =
8788 ConstantRange::fromKnownBits(VT->getKnownBits(RHS),
8789 /* IsSigned=*/Subo->isSigned());
8790
8791 if (Subo->isSigned()) {
8792 // G_SSUBO
8793 switch (KBLHS.signedSubMayOverflow(KBRHS)) {
8795 return false;
8797 MatchInfo = [=](MachineIRBuilder &B) {
8798 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8799 B.buildConstant(Carry, 0);
8800 };
8801 return true;
8802 }
8805 MatchInfo = [=](MachineIRBuilder &B) {
8806 B.buildSub(Dst, LHS, RHS);
8807 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8808 /*isVector=*/CarryTy.isVector(),
8809 /*isFP=*/false));
8810 };
8811 return true;
8812 }
8813 }
8814 return false;
8815 }
8816
8817 // G_USUBO
8818 switch (KBLHS.unsignedSubMayOverflow(KBRHS)) {
8820 return false;
8822 MatchInfo = [=](MachineIRBuilder &B) {
8823 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
8824 B.buildConstant(Carry, 0);
8825 };
8826 return true;
8827 }
8830 MatchInfo = [=](MachineIRBuilder &B) {
8831 B.buildSub(Dst, LHS, RHS);
8832 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8833 /*isVector=*/CarryTy.isVector(),
8834 /*isFP=*/false));
8835 };
8836 return true;
8837 }
8838 }
8839
8840 return false;
8841}
8842
8843// Fold (ctlz (xor x, (sra x, bitwidth-1))) -> (add (ctls x), 1).
8844// Fold (ctlz (or (shl (xor x, (sra x, bitwidth-1)), 1), 1) -> (ctls x)
8846 BuildFnTy &MatchInfo) const {
8847 assert((CtlzMI.getOpcode() == TargetOpcode::G_CTLZ ||
8848 CtlzMI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON) &&
8849 "Expected G_CTLZ variant");
8850
8851 const Register Dst = CtlzMI.getOperand(0).getReg();
8852 Register Src = CtlzMI.getOperand(1).getReg();
8853
8854 LLT Ty = MRI.getType(Dst);
8855 LLT SrcTy = MRI.getType(Src);
8856
8857 if (!(Ty.isValid() && Ty.isScalar()))
8858 return false;
8859
8860 if (!LI)
8861 return false;
8862
8863 SmallVector<LLT, 2> QueryTypes = {Ty, SrcTy};
8864 LegalityQuery Query(TargetOpcode::G_CTLS, QueryTypes);
8865
8866 switch (LI->getAction(Query).Action) {
8867 default:
8868 return false;
8872 break;
8873 }
8874
8875 // Src = or(shl(V, 1), 1) -> Src=V; NeedAdd = False
8876 Register V;
8877 bool NeedAdd = true;
8878 if (mi_match(Src, MRI,
8880 m_SpecificICst(1))))) {
8881 NeedAdd = false;
8882 Src = V;
8883 }
8884
8885 unsigned BitWidth = Ty.getScalarSizeInBits();
8886
8887 Register X;
8888 if (!mi_match(Src, MRI,
8891 m_SpecificICst(BitWidth - 1)))))))
8892 return false;
8893
8894 MatchInfo = [=](MachineIRBuilder &B) {
8895 if (!NeedAdd) {
8896 B.buildCTLS(Dst, X);
8897 return;
8898 }
8899
8900 auto Ctls = B.buildCTLS(Ty, X);
8901 auto One = B.buildConstant(Ty, 1);
8902
8903 B.buildAdd(Dst, Ctls, One);
8904 };
8905
8906 return true;
8907}
8908
8909// Fold shr ( add ( ext X, ext Y ), 1 ) -> avgfloor ( x, y )
8910// Fold shr ( add ( ext X, ext Y, 1 ), 1 ) -> avgceil ( x, y )
8913 unsigned TargetOpc) const {
8914 assert((MI.getOpcode() == TargetOpcode::G_LSHR ||
8915 MI.getOpcode() == TargetOpcode::G_ASHR) &&
8916 "Expected G_LSHR/G_ASHR");
8917
8918 LLT XTy = MRI.getType(X);
8919 return XTy == MRI.getType(Y) && isLegal({TargetOpc, {XTy}});
8920}
8921
8923 assert((MI.getOpcode() == TargetOpcode::G_CTLZ ||
8924 MI.getOpcode() == TargetOpcode::G_CTTZ) &&
8925 "Expected count-zero opcode");
8926 switch (MI.getOpcode()) {
8927 case TargetOpcode::G_CTLZ:
8928 return TargetOpcode::G_CTLZ_ZERO_POISON;
8929 case TargetOpcode::G_CTTZ:
8930 return TargetOpcode::G_CTTZ_ZERO_POISON;
8931 default:
8932 llvm_unreachable("Unexpected count-zero opcode");
8933 }
8934}
8935
8937 if (!VT)
8938 return false;
8939
8940 unsigned ZPOpc = getCountZeroPoisonOpcode(MI);
8941 Register Src = MI.getOperand(1).getReg();
8942 if (!VT->isKnownNeverZero(Src))
8943 return false;
8944
8945 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
8946 LLT SrcTy = MRI.getType(Src);
8947 return isLegalOrBeforeLegalizer({ZPOpc, {DstTy, SrcTy}});
8948}
8949
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...