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