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_PTRTOINT && "Expected a G_PTRTOINT");
2591 Register DstReg = MI.getOperand(0).getReg();
2592 Builder.buildZExtOrTrunc(DstReg, Reg);
2593 MI.eraseFromParent();
2594}
2595
2597 Register &Reg) const {
2598 assert(MI.getOpcode() == TargetOpcode::G_ANYEXT && "Expected a G_ANYEXT");
2599 Register DstReg = MI.getOperand(0).getReg();
2600 Register SrcReg = MI.getOperand(1).getReg();
2601 Register OriginalSrcReg = getSrcRegIgnoringCopies(SrcReg, MRI);
2602 if (OriginalSrcReg.isValid())
2603 SrcReg = OriginalSrcReg;
2604 LLT DstTy = MRI.getType(DstReg);
2605 return mi_match(SrcReg, MRI,
2606 m_GTrunc(m_all_of(m_Reg(Reg), m_SpecificType(DstTy)))) &&
2607 canReplaceReg(DstReg, Reg, MRI);
2608}
2609
2611 Register &Reg) const {
2612 assert(MI.getOpcode() == TargetOpcode::G_ZEXT && "Expected a G_ZEXT");
2613 Register DstReg = MI.getOperand(0).getReg();
2614 Register SrcReg = MI.getOperand(1).getReg();
2615 LLT DstTy = MRI.getType(DstReg);
2616 if (mi_match(SrcReg, MRI,
2617 m_GTrunc(m_all_of(m_Reg(Reg), m_SpecificType(DstTy)))) &&
2618 canReplaceReg(DstReg, Reg, MRI)) {
2619 unsigned DstSize = DstTy.getScalarSizeInBits();
2620 unsigned SrcSize = MRI.getType(SrcReg).getScalarSizeInBits();
2621 return VT->getKnownBits(Reg).countMinLeadingZeros() >= DstSize - SrcSize;
2622 }
2623 return false;
2624}
2625
2627 const unsigned ShiftSize = ShiftTy.getScalarSizeInBits();
2628 const unsigned TruncSize = TruncTy.getScalarSizeInBits();
2629
2630 // ShiftTy > 32 > TruncTy -> 32
2631 if (ShiftSize > 32 && TruncSize < 32)
2632 return ShiftTy.changeElementSize(32);
2633
2634 // TODO: We could also reduce to 16 bits, but that's more target-dependent.
2635 // Some targets like it, some don't, some only like it under certain
2636 // conditions/processor versions, etc.
2637 // A TL hook might be needed for this.
2638
2639 // Don't combine
2640 return ShiftTy;
2641}
2642
2644 MachineInstr &MI, std::pair<MachineInstr *, LLT> &MatchInfo) const {
2645 assert(MI.getOpcode() == TargetOpcode::G_TRUNC && "Expected a G_TRUNC");
2646 Register DstReg = MI.getOperand(0).getReg();
2647 Register SrcReg = MI.getOperand(1).getReg();
2648
2649 if (!MRI.hasOneNonDBGUse(SrcReg))
2650 return false;
2651
2652 LLT SrcTy = MRI.getType(SrcReg);
2653 LLT DstTy = MRI.getType(DstReg);
2654
2655 MachineInstr *SrcMI = getDefIgnoringCopies(SrcReg, MRI);
2656 const auto &TL = getTargetLowering();
2657
2658 LLT NewShiftTy;
2659 switch (SrcMI->getOpcode()) {
2660 default:
2661 return false;
2662 case TargetOpcode::G_SHL: {
2663 NewShiftTy = DstTy;
2664
2665 // Make sure new shift amount is legal.
2666 KnownBits Known = VT->getKnownBits(SrcMI->getOperand(2).getReg());
2667 if (Known.getMaxValue().uge(NewShiftTy.getScalarSizeInBits()))
2668 return false;
2669 break;
2670 }
2671 case TargetOpcode::G_LSHR:
2672 case TargetOpcode::G_ASHR: {
2673 // For right shifts, we conservatively do not do the transform if the TRUNC
2674 // has any STORE users. The reason is that if we change the type of the
2675 // shift, we may break the truncstore combine.
2676 //
2677 // TODO: Fix truncstore combine to handle (trunc(lshr (trunc x), k)).
2678 for (auto &User : MRI.use_instructions(DstReg))
2679 if (User.getOpcode() == TargetOpcode::G_STORE)
2680 return false;
2681
2682 NewShiftTy = getMidVTForTruncRightShiftCombine(SrcTy, DstTy);
2683 if (NewShiftTy == SrcTy)
2684 return false;
2685
2686 // Make sure we won't lose information by truncating the high bits.
2687 KnownBits Known = VT->getKnownBits(SrcMI->getOperand(2).getReg());
2688 if (Known.getMaxValue().ugt(NewShiftTy.getScalarSizeInBits() -
2689 DstTy.getScalarSizeInBits()))
2690 return false;
2691 break;
2692 }
2693 }
2694
2696 {SrcMI->getOpcode(),
2697 {NewShiftTy, TL.getPreferredShiftAmountTy(NewShiftTy)}}))
2698 return false;
2699
2700 MatchInfo = std::make_pair(SrcMI, NewShiftTy);
2701 return true;
2702}
2703
2705 MachineInstr &MI, std::pair<MachineInstr *, LLT> &MatchInfo) const {
2706 MachineInstr *ShiftMI = MatchInfo.first;
2707 LLT NewShiftTy = MatchInfo.second;
2708
2709 Register Dst = MI.getOperand(0).getReg();
2710 LLT DstTy = MRI.getType(Dst);
2711
2712 Register ShiftAmt = ShiftMI->getOperand(2).getReg();
2713 Register ShiftSrc = ShiftMI->getOperand(1).getReg();
2714 ShiftSrc = Builder.buildTrunc(NewShiftTy, ShiftSrc).getReg(0);
2715
2716 const auto &TL = getTargetLowering();
2717 LLT PrefShiftTy = TL.getPreferredShiftAmountTy(NewShiftTy);
2718 if (MRI.getType(ShiftAmt) != PrefShiftTy)
2719 ShiftAmt = Builder.buildZExtOrTrunc(PrefShiftTy, ShiftAmt).getReg(0);
2720
2721 Register NewShift =
2722 Builder
2723 .buildInstr(ShiftMI->getOpcode(), {NewShiftTy}, {ShiftSrc, ShiftAmt})
2724 .getReg(0);
2725
2726 if (NewShiftTy == DstTy)
2727 replaceRegWith(MRI, Dst, NewShift);
2728 else
2729 Builder.buildTrunc(Dst, NewShift);
2730
2731 eraseInst(MI);
2732}
2733
2735 return all_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
2736 return !MO.isReg() ||
2737 getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
2738 });
2739}
2740
2742 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
2743 ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
2744 return all_of(Mask, [](int Elt) { return Elt < 0; });
2745}
2746
2748 assert(MI.getOpcode() == TargetOpcode::G_STORE);
2749 return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(0).getReg(),
2750 MRI);
2751}
2752
2754 MachineInstr &MI) const {
2755 assert((MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT ||
2756 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT) &&
2757 "Expected an insert/extract element op");
2758 LLT VecTy = MRI.getType(MI.getOperand(1).getReg());
2759 if (VecTy.isScalableVector())
2760 return false;
2761
2762 unsigned IdxIdx =
2763 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
2764 auto Idx = getIConstantVRegVal(MI.getOperand(IdxIdx).getReg(), MRI);
2765 if (!Idx)
2766 return false;
2767 return Idx->getZExtValue() >= VecTy.getNumElements();
2768}
2769
2771 unsigned &OpIdx) const {
2772 GSelect &SelMI = cast<GSelect>(MI);
2773 auto Cst = isConstantOrConstantSplatVector(SelMI.getCondReg(), MRI);
2774 if (!Cst)
2775 return false;
2776 OpIdx = Cst->isZero() ? 3 : 2;
2777 return true;
2778}
2779
2780void CombinerHelper::eraseInst(MachineInstr &MI) const { MI.eraseFromParent(); }
2781
2783 const MachineOperand &MOP2) const {
2784 if (!MOP1.isReg() || !MOP2.isReg())
2785 return false;
2786 auto InstAndDef1 = getDefSrcRegIgnoringCopies(MOP1.getReg(), MRI);
2787 if (!InstAndDef1)
2788 return false;
2789 auto InstAndDef2 = getDefSrcRegIgnoringCopies(MOP2.getReg(), MRI);
2790 if (!InstAndDef2)
2791 return false;
2792 MachineInstr *I1 = InstAndDef1->MI;
2793 MachineInstr *I2 = InstAndDef2->MI;
2794
2795 // Handle a case like this:
2796 //
2797 // %0:_(s64), %1:_(s64) = G_UNMERGE_VALUES %2:_(<2 x s64>)
2798 //
2799 // Even though %0 and %1 are produced by the same instruction they are not
2800 // the same values.
2801 if (I1 == I2)
2802 return MOP1.getReg() == MOP2.getReg();
2803
2804 // If we have an instruction which loads or stores, we can't guarantee that
2805 // it is identical.
2806 //
2807 // For example, we may have
2808 //
2809 // %x1 = G_LOAD %addr (load N from @somewhere)
2810 // ...
2811 // call @foo
2812 // ...
2813 // %x2 = G_LOAD %addr (load N from @somewhere)
2814 // ...
2815 // %or = G_OR %x1, %x2
2816 //
2817 // It's possible that @foo will modify whatever lives at the address we're
2818 // loading from. To be safe, let's just assume that all loads and stores
2819 // are different (unless we have something which is guaranteed to not
2820 // change.)
2821 if (I1->mayLoadOrStore() && !I1->isDereferenceableInvariantLoad())
2822 return false;
2823
2824 // If both instructions are loads or stores, they are equal only if both
2825 // are dereferenceable invariant loads with the same number of bits.
2826 if (I1->mayLoadOrStore() && I2->mayLoadOrStore()) {
2829 if (!LS1 || !LS2)
2830 return false;
2831
2832 if (!I2->isDereferenceableInvariantLoad() ||
2833 (LS1->getMemSizeInBits() != LS2->getMemSizeInBits()))
2834 return false;
2835 }
2836
2837 // Check for physical registers on the instructions first to avoid cases
2838 // like this:
2839 //
2840 // %a = COPY $physreg
2841 // ...
2842 // SOMETHING implicit-def $physreg
2843 // ...
2844 // %b = COPY $physreg
2845 //
2846 // These copies are not equivalent.
2847 if (any_of(I1->uses(), [](const MachineOperand &MO) {
2848 return MO.isReg() && MO.getReg().isPhysical();
2849 })) {
2850 // Check if we have a case like this:
2851 //
2852 // %a = COPY $physreg
2853 // %b = COPY %a
2854 //
2855 // In this case, I1 and I2 will both be equal to %a = COPY $physreg.
2856 // From that, we know that they must have the same value, since they must
2857 // have come from the same COPY.
2858 return I1->isIdenticalTo(*I2);
2859 }
2860
2861 // We don't have any physical registers, so we don't necessarily need the
2862 // same vreg defs.
2863 //
2864 // On the off-chance that there's some target instruction feeding into the
2865 // instruction, let's use produceSameValue instead of isIdenticalTo.
2866 if (Builder.getTII().produceSameValue(*I1, *I2, &MRI)) {
2867 // Handle instructions with multiple defs that produce same values. Values
2868 // are same for operands with same index.
2869 // %0:_(s8), %1:_(s8), %2:_(s8), %3:_(s8) = G_UNMERGE_VALUES %4:_(<4 x s8>)
2870 // %5:_(s8), %6:_(s8), %7:_(s8), %8:_(s8) = G_UNMERGE_VALUES %4:_(<4 x s8>)
2871 // I1 and I2 are different instructions but produce same values,
2872 // %1 and %6 are same, %1 and %7 are not the same value.
2873 return I1->findRegisterDefOperandIdx(InstAndDef1->Reg, /*TRI=*/nullptr) ==
2874 I2->findRegisterDefOperandIdx(InstAndDef2->Reg, /*TRI=*/nullptr);
2875 }
2876 return false;
2877}
2878
2880 double C) const {
2881 if (!MOP.isReg())
2882 return false;
2883 std::optional<FPValueAndVReg> MaybeCst;
2884 if (!mi_match(MOP.getReg(), MRI, m_GFCstOrSplat(MaybeCst)))
2885 return false;
2886
2887 return MaybeCst->Value.isExactlyValue(C);
2888}
2889
2891 unsigned OpIdx) const {
2892 assert(MI.getNumExplicitDefs() == 1 && "Expected one explicit def?");
2893 Register OldReg = MI.getOperand(0).getReg();
2894 Register Replacement = MI.getOperand(OpIdx).getReg();
2895 assert(canReplaceReg(OldReg, Replacement, MRI) && "Cannot replace register?");
2896 replaceRegWith(MRI, OldReg, Replacement);
2897 MI.eraseFromParent();
2898}
2899
2901 Register Replacement) const {
2902 assert(MI.getNumExplicitDefs() == 1 && "Expected one explicit def?");
2903 Register OldReg = MI.getOperand(0).getReg();
2904 assert(canReplaceReg(OldReg, Replacement, MRI) && "Cannot replace register?");
2905 replaceRegWith(MRI, OldReg, Replacement);
2906 MI.eraseFromParent();
2907}
2908
2910 unsigned ConstIdx) const {
2911 Register ConstReg = MI.getOperand(ConstIdx).getReg();
2912 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
2913
2914 // Get the shift amount
2915 auto VRegAndVal = getIConstantVRegValWithLookThrough(ConstReg, MRI);
2916 if (!VRegAndVal)
2917 return false;
2918
2919 // Return true of shift amount >= Bitwidth
2920 return (VRegAndVal->Value.uge(DstTy.getSizeInBits()));
2921}
2922
2924 assert((MI.getOpcode() == TargetOpcode::G_FSHL ||
2925 MI.getOpcode() == TargetOpcode::G_FSHR) &&
2926 "This is not a funnel shift operation");
2927
2928 Register ConstReg = MI.getOperand(3).getReg();
2929 LLT ConstTy = MRI.getType(ConstReg);
2930 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
2931
2932 auto VRegAndVal = getIConstantVRegValWithLookThrough(ConstReg, MRI);
2933 assert((VRegAndVal) && "Value is not a constant");
2934
2935 // Calculate the new Shift Amount = Old Shift Amount % BitWidth
2936 APInt NewConst = VRegAndVal->Value.urem(
2937 APInt(ConstTy.getSizeInBits(), DstTy.getScalarSizeInBits()));
2938
2939 auto NewConstInstr = Builder.buildConstant(ConstTy, NewConst.getZExtValue());
2940 Builder.buildInstr(
2941 MI.getOpcode(), {MI.getOperand(0)},
2942 {MI.getOperand(1), MI.getOperand(2), NewConstInstr.getReg(0)});
2943
2944 MI.eraseFromParent();
2945}
2946
2948 assert(MI.getOpcode() == TargetOpcode::G_SELECT);
2949 // Match (cond ? x : x)
2950 return matchEqualDefs(MI.getOperand(2), MI.getOperand(3)) &&
2951 canReplaceReg(MI.getOperand(0).getReg(), MI.getOperand(2).getReg(),
2952 MRI);
2953}
2954
2956 const MachineOperand &MO, bool OrNegative) const {
2957 return isKnownToBeAPowerOfTwo(MO.getReg(), MRI, VT, OrNegative);
2958}
2959
2961 double C) const {
2962 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2963 Builder.buildFConstant(MI.getOperand(0), C);
2964 MI.eraseFromParent();
2965}
2966
2968 int64_t C) const {
2969 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2970 Builder.buildConstant(MI.getOperand(0), C);
2971 MI.eraseFromParent();
2972}
2973
2975 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2976 Builder.buildConstant(MI.getOperand(0), C);
2977 MI.eraseFromParent();
2978}
2979
2981 ConstantFP *CFP) const {
2982 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2983 Builder.buildFConstant(MI.getOperand(0), CFP->getValueAPF());
2984 MI.eraseFromParent();
2985}
2986
2988 assert(MI.getNumDefs() == 1 && "Expected only one def?");
2989 Builder.buildUndef(MI.getOperand(0));
2990 MI.eraseFromParent();
2991}
2992
2994 MachineInstr &MI, SmallVectorImpl<Register> &MatchInfo) const {
2995 assert(MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT &&
2996 "Invalid opcode");
2997 Register DstReg = MI.getOperand(0).getReg();
2998 LLT DstTy = MRI.getType(DstReg);
2999 assert(DstTy.isVector() && "Invalid G_INSERT_VECTOR_ELT?");
3000
3001 if (DstTy.isScalableVector())
3002 return false;
3003
3004 unsigned NumElts = DstTy.getNumElements();
3005 // If this MI is part of a sequence of insert_vec_elts, then
3006 // don't do the combine in the middle of the sequence.
3007 if (MRI.hasOneUse(DstReg) && MRI.use_instr_begin(DstReg)->getOpcode() ==
3008 TargetOpcode::G_INSERT_VECTOR_ELT)
3009 return false;
3010 MachineInstr *CurrInst = &MI;
3011 MachineInstr *TmpInst;
3012 int64_t IntImm;
3013 Register TmpReg;
3014 MatchInfo.resize(NumElts);
3015 while (mi_match(
3016 *CurrInst, MRI,
3017 m_GInsertVecElt(m_MInstr(TmpInst), m_Reg(TmpReg), m_ICst(IntImm)))) {
3018 if (IntImm >= NumElts || IntImm < 0)
3019 return false;
3020 if (!MatchInfo[IntImm])
3021 MatchInfo[IntImm] = TmpReg;
3022 CurrInst = TmpInst;
3023 }
3024 // Variable index.
3025 if (CurrInst->getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
3026 return false;
3027 if (TmpInst->getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
3028 for (unsigned I = 1; I < TmpInst->getNumOperands(); ++I) {
3029 if (!MatchInfo[I - 1].isValid())
3030 MatchInfo[I - 1] = TmpInst->getOperand(I).getReg();
3031 }
3032 return true;
3033 }
3034 // If we didn't end in a G_IMPLICIT_DEF and the source is not fully
3035 // overwritten, bail out.
3036 return TmpInst->getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
3037 all_of(MatchInfo, [](Register Reg) { return !!Reg; });
3038}
3039
3041 MachineInstr &MI, SmallVectorImpl<Register> &MatchInfo) const {
3042 Register UndefReg;
3043 auto GetUndef = [&]() {
3044 if (UndefReg)
3045 return UndefReg;
3046 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
3047 UndefReg = Builder.buildUndef(DstTy.getScalarType()).getReg(0);
3048 return UndefReg;
3049 };
3050 for (Register &Reg : MatchInfo) {
3051 if (!Reg)
3052 Reg = GetUndef();
3053 }
3054 Builder.buildBuildVector(MI.getOperand(0).getReg(), MatchInfo);
3055 MI.eraseFromParent();
3056}
3057
3058bool CombinerHelper::matchBinopWithNegInner(Register MInner, Register Other,
3059 unsigned RootOpc, Register Dst,
3060 LLT Ty,
3061 BuildFnTy &MatchInfo) const {
3062 /// Helper function for matchBinopWithNeg: tries to match one commuted form
3063 /// of `a bitwiseop (~b +/- c)` -> `a bitwiseop ~(b -/+ c)`.
3064 MachineInstr *InnerDef;
3065 if (!mi_match(MInner, MRI, m_MInstr(InnerDef)))
3066 return false;
3067
3068 unsigned InnerOpc = InnerDef->getOpcode();
3069 if (InnerOpc != TargetOpcode::G_ADD && InnerOpc != TargetOpcode::G_SUB)
3070 return false;
3071
3072 if (!MRI.hasOneNonDBGUse(MInner))
3073 return false;
3074
3075 Register InnerLHS = InnerDef->getOperand(1).getReg();
3076 Register InnerRHS = InnerDef->getOperand(2).getReg();
3077 Register NotSrc;
3078 Register B, C;
3079
3080 // Check if either operand is ~b
3081 auto TryMatch = [&](Register MaybeNot, Register Other) {
3082 if (mi_match(MaybeNot, MRI, m_Not(m_Reg(NotSrc)))) {
3083 if (!MRI.hasOneNonDBGUse(MaybeNot))
3084 return false;
3085 B = NotSrc;
3086 C = Other;
3087 return true;
3088 }
3089 return false;
3090 };
3091
3092 // For SUB, the not must be the LHS. For ADD, it can be either operand.
3093 if (!TryMatch(InnerLHS, InnerRHS) &&
3094 !(InnerOpc == TargetOpcode::G_ADD && TryMatch(InnerRHS, InnerLHS)))
3095 return false;
3096
3097 // Flip add/sub
3098 unsigned FlippedOpc = (InnerOpc == TargetOpcode::G_ADD) ? TargetOpcode::G_SUB
3099 : TargetOpcode::G_ADD;
3100
3101 Register A = Other;
3102 MatchInfo = [=](MachineIRBuilder &Builder) {
3103 auto NewInner = Builder.buildInstr(FlippedOpc, {Ty}, {B, C});
3104 auto NewNot = Builder.buildNot(Ty, NewInner);
3105 Builder.buildInstr(RootOpc, {Dst}, {A, NewNot});
3106 };
3107 return true;
3108}
3109
3111 BuildFnTy &MatchInfo) const {
3112 // Fold `a bitwiseop (~b +/- c)` -> `a bitwiseop ~(b -/+ c)`
3113 // Root MI is one of G_AND, G_OR, G_XOR.
3114 // We also look for commuted forms of operations. Pattern shouldn't apply
3115 // if there are multiple reasons of inner operations.
3116
3117 unsigned RootOpc = MI.getOpcode();
3118 Register Dst = MI.getOperand(0).getReg();
3119 LLT Ty = MRI.getType(Dst);
3120
3121 Register LHS = MI.getOperand(1).getReg();
3122 Register RHS = MI.getOperand(2).getReg();
3123 // Check the commuted and uncommuted forms of the operation.
3124 return matchBinopWithNegInner(LHS, RHS, RootOpc, Dst, Ty, MatchInfo) ||
3125 matchBinopWithNegInner(RHS, LHS, RootOpc, Dst, Ty, MatchInfo);
3126}
3127
3129 MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const {
3130 // Matches: logic (hand x, ...), (hand y, ...) -> hand (logic x, y), ...
3131 //
3132 // Creates the new hand + logic instruction (but does not insert them.)
3133 //
3134 // On success, MatchInfo is populated with the new instructions. These are
3135 // inserted in applyHoistLogicOpWithSameOpcodeHands.
3136 unsigned LogicOpcode = MI.getOpcode();
3137 assert(LogicOpcode == TargetOpcode::G_AND ||
3138 LogicOpcode == TargetOpcode::G_OR ||
3139 LogicOpcode == TargetOpcode::G_XOR);
3140 MachineIRBuilder MIB(MI);
3141 Register Dst = MI.getOperand(0).getReg();
3142 Register LHSReg = MI.getOperand(1).getReg();
3143 Register RHSReg = MI.getOperand(2).getReg();
3144
3145 // Don't recompute anything.
3146 if (!MRI.hasOneNonDBGUse(LHSReg) || !MRI.hasOneNonDBGUse(RHSReg))
3147 return false;
3148
3149 // Make sure we have (hand x, ...), (hand y, ...)
3150 MachineInstr *LeftHandInst = getDefIgnoringCopies(LHSReg, MRI);
3151 MachineInstr *RightHandInst = getDefIgnoringCopies(RHSReg, MRI);
3152 if (!LeftHandInst || !RightHandInst)
3153 return false;
3154 unsigned HandOpcode = LeftHandInst->getOpcode();
3155 if (HandOpcode != RightHandInst->getOpcode())
3156 return false;
3157 if (LeftHandInst->getNumOperands() < 2 ||
3158 !LeftHandInst->getOperand(1).isReg() ||
3159 RightHandInst->getNumOperands() < 2 ||
3160 !RightHandInst->getOperand(1).isReg())
3161 return false;
3162
3163 // Make sure the types match up, and if we're doing this post-legalization,
3164 // we end up with legal types.
3165 Register X = LeftHandInst->getOperand(1).getReg();
3166 Register Y = RightHandInst->getOperand(1).getReg();
3167 LLT XTy = MRI.getType(X);
3168 LLT YTy = MRI.getType(Y);
3169 if (!XTy.isValid() || XTy != YTy)
3170 return false;
3171
3172 // Optional extra source register.
3173 Register ExtraHandOpSrcReg;
3174 switch (HandOpcode) {
3175 default:
3176 return false;
3177 case TargetOpcode::G_ANYEXT:
3178 case TargetOpcode::G_SEXT:
3179 case TargetOpcode::G_ZEXT: {
3180 // Match: logic (ext X), (ext Y) --> ext (logic X, Y)
3181 break;
3182 }
3183 case TargetOpcode::G_TRUNC: {
3184 // Match: logic (trunc X), (trunc Y) -> trunc (logic X, Y)
3185 const MachineFunction *MF = MI.getMF();
3186 LLVMContext &Ctx = MF->getFunction().getContext();
3187
3188 LLT DstTy = MRI.getType(Dst);
3189 const TargetLowering &TLI = getTargetLowering();
3190
3191 // Be extra careful sinking truncate. If it's free, there's no benefit in
3192 // widening a binop.
3193 if (TLI.isZExtFree(DstTy, XTy, Ctx) && TLI.isTruncateFree(XTy, DstTy, Ctx))
3194 return false;
3195 break;
3196 }
3197 case TargetOpcode::G_AND:
3198 case TargetOpcode::G_ASHR:
3199 case TargetOpcode::G_LSHR:
3200 case TargetOpcode::G_SHL: {
3201 // Match: logic (binop x, z), (binop y, z) -> binop (logic x, y), z
3202 MachineOperand &ZOp = LeftHandInst->getOperand(2);
3203 if (!matchEqualDefs(ZOp, RightHandInst->getOperand(2)))
3204 return false;
3205 ExtraHandOpSrcReg = ZOp.getReg();
3206 break;
3207 }
3208 }
3209
3210 if (!isLegalOrBeforeLegalizer({LogicOpcode, {XTy, YTy}}))
3211 return false;
3212
3213 // Record the steps to build the new instructions.
3214 //
3215 // Steps to build (logic x, y)
3216 auto NewLogicDst = MRI.createGenericVirtualRegister(XTy);
3217 OperandBuildSteps LogicBuildSteps = {
3218 [=](MachineInstrBuilder &MIB) { MIB.addDef(NewLogicDst); },
3219 [=](MachineInstrBuilder &MIB) { MIB.addReg(X); },
3220 [=](MachineInstrBuilder &MIB) { MIB.addReg(Y); }};
3221 InstructionBuildSteps LogicSteps(LogicOpcode, LogicBuildSteps);
3222
3223 // Steps to build hand (logic x, y), ...z
3224 OperandBuildSteps HandBuildSteps = {
3225 [=](MachineInstrBuilder &MIB) { MIB.addDef(Dst); },
3226 [=](MachineInstrBuilder &MIB) { MIB.addReg(NewLogicDst); }};
3227 if (ExtraHandOpSrcReg.isValid())
3228 HandBuildSteps.push_back(
3229 [=](MachineInstrBuilder &MIB) { MIB.addReg(ExtraHandOpSrcReg); });
3230 InstructionBuildSteps HandSteps(HandOpcode, HandBuildSteps);
3231
3232 MatchInfo = InstructionStepsMatchInfo({LogicSteps, HandSteps});
3233 return true;
3234}
3235
3237 MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const {
3238 assert(MatchInfo.InstrsToBuild.size() &&
3239 "Expected at least one instr to build?");
3240 for (auto &InstrToBuild : MatchInfo.InstrsToBuild) {
3241 assert(InstrToBuild.Opcode && "Expected a valid opcode?");
3242 assert(InstrToBuild.OperandFns.size() && "Expected at least one operand?");
3243 MachineInstrBuilder Instr = Builder.buildInstr(InstrToBuild.Opcode);
3244 for (auto &OperandFn : InstrToBuild.OperandFns)
3245 OperandFn(Instr);
3246 }
3247 MI.eraseFromParent();
3248}
3249
3251 MachineInstr &MI, std::tuple<Register, int64_t> &MatchInfo) const {
3252 assert(MI.getOpcode() == TargetOpcode::G_ASHR);
3253 int64_t ShlCst, AshrCst;
3254 Register Src;
3255 if (!mi_match(MI.getOperand(0).getReg(), MRI,
3256 m_GAShr(m_GShl(m_Reg(Src), m_ICstOrSplat(ShlCst)),
3257 m_ICstOrSplat(AshrCst))))
3258 return false;
3259 if (ShlCst != AshrCst)
3260 return false;
3262 {TargetOpcode::G_SEXT_INREG,
3263 {MRI.getType(Src)},
3264 {},
3265 {MRI.getType(Src).getScalarSizeInBits() - ShlCst}}))
3266 return false;
3267 MatchInfo = std::make_tuple(Src, ShlCst);
3268 return true;
3269}
3270
3272 MachineInstr &MI, std::tuple<Register, int64_t> &MatchInfo) const {
3273 assert(MI.getOpcode() == TargetOpcode::G_ASHR);
3274 Register Src;
3275 int64_t ShiftAmt;
3276 std::tie(Src, ShiftAmt) = MatchInfo;
3277 unsigned Size = MRI.getType(Src).getScalarSizeInBits();
3278 Builder.buildSExtInReg(MI.getOperand(0).getReg(), Src, Size - ShiftAmt);
3279 MI.eraseFromParent();
3280}
3281
3282/// and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0
3285 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
3286 assert(MI.getOpcode() == TargetOpcode::G_AND);
3287
3288 Register Dst = MI.getOperand(0).getReg();
3289 LLT Ty = MRI.getType(Dst);
3290
3291 Register R;
3292 int64_t C1;
3293 int64_t C2;
3294 if (!mi_match(
3295 Dst, MRI,
3296 m_GAnd(m_GAnd(m_Reg(R), m_ICst(C1)), m_ICst(C2))))
3297 return false;
3298
3299 MatchInfo = [=](MachineIRBuilder &B) {
3300 if (C1 & C2) {
3301 B.buildAnd(Dst, R, B.buildConstant(Ty, C1 & C2));
3302 return;
3303 }
3304 auto Zero = B.buildConstant(Ty, 0);
3305 replaceRegWith(MRI, Dst, Zero->getOperand(0).getReg());
3306 };
3307 return true;
3308}
3309
3311 Register &Replacement) const {
3312 // Given
3313 //
3314 // %y:_(sN) = G_SOMETHING
3315 // %x:_(sN) = G_SOMETHING
3316 // %res:_(sN) = G_AND %x, %y
3317 //
3318 // Eliminate the G_AND when it is known that x & y == x or x & y == y.
3319 //
3320 // Patterns like this can appear as a result of legalization. E.g.
3321 //
3322 // %cmp:_(s32) = G_ICMP intpred(pred), %x(s32), %y
3323 // %one:_(s32) = G_CONSTANT i32 1
3324 // %and:_(s32) = G_AND %cmp, %one
3325 //
3326 // In this case, G_ICMP only produces a single bit, so x & 1 == x.
3327 assert(MI.getOpcode() == TargetOpcode::G_AND);
3328 if (!VT)
3329 return false;
3330
3331 Register AndDst = MI.getOperand(0).getReg();
3332 Register LHS = MI.getOperand(1).getReg();
3333 Register RHS = MI.getOperand(2).getReg();
3334
3335 // Check the RHS (maybe a constant) first, and if we have no KnownBits there,
3336 // we can't do anything. If we do, then it depends on whether we have
3337 // KnownBits on the LHS.
3338 KnownBits RHSBits = VT->getKnownBits(RHS);
3339 if (RHSBits.isUnknown())
3340 return false;
3341
3342 KnownBits LHSBits = VT->getKnownBits(LHS);
3343
3344 // Check that x & Mask == x.
3345 // x & 1 == x, always
3346 // x & 0 == x, only if x is also 0
3347 // Meaning Mask has no effect if every bit is either one in Mask or zero in x.
3348 //
3349 // Check if we can replace AndDst with the LHS of the G_AND
3350 if (canReplaceReg(AndDst, LHS, MRI) &&
3351 (LHSBits.Zero | RHSBits.One).isAllOnes()) {
3352 Replacement = LHS;
3353 return true;
3354 }
3355
3356 // Check if we can replace AndDst with the RHS of the G_AND
3357 if (canReplaceReg(AndDst, RHS, MRI) &&
3358 (LHSBits.One | RHSBits.Zero).isAllOnes()) {
3359 Replacement = RHS;
3360 return true;
3361 }
3362
3363 return false;
3364}
3365
3367 Register &Replacement) const {
3368 // Given
3369 //
3370 // %y:_(sN) = G_SOMETHING
3371 // %x:_(sN) = G_SOMETHING
3372 // %res:_(sN) = G_OR %x, %y
3373 //
3374 // Eliminate the G_OR when it is known that x | y == x or x | y == y.
3375 assert(MI.getOpcode() == TargetOpcode::G_OR);
3376 if (!VT)
3377 return false;
3378
3379 Register OrDst = MI.getOperand(0).getReg();
3380 Register LHS = MI.getOperand(1).getReg();
3381 Register RHS = MI.getOperand(2).getReg();
3382
3383 KnownBits LHSBits = VT->getKnownBits(LHS);
3384 KnownBits RHSBits = VT->getKnownBits(RHS);
3385
3386 // Check that x | Mask == x.
3387 // x | 0 == x, always
3388 // x | 1 == x, only if x is also 1
3389 // Meaning Mask has no effect if every bit is either zero in Mask or one in x.
3390 //
3391 // Check if we can replace OrDst with the LHS of the G_OR
3392 if (canReplaceReg(OrDst, LHS, MRI) &&
3393 (LHSBits.One | RHSBits.Zero).isAllOnes()) {
3394 Replacement = LHS;
3395 return true;
3396 }
3397
3398 // Check if we can replace OrDst with the RHS of the G_OR
3399 if (canReplaceReg(OrDst, RHS, MRI) &&
3400 (LHSBits.Zero | RHSBits.One).isAllOnes()) {
3401 Replacement = RHS;
3402 return true;
3403 }
3404
3405 return false;
3406}
3407
3409 // If the input is already sign extended, just drop the extension.
3410 Register Src = MI.getOperand(1).getReg();
3411 unsigned ExtBits = MI.getOperand(2).getImm();
3412 unsigned TypeSize = MRI.getType(Src).getScalarSizeInBits();
3413 return VT->computeNumSignBits(Src) >= (TypeSize - ExtBits + 1);
3414}
3415
3416static bool isConstValidTrue(const TargetLowering &TLI, unsigned ScalarSizeBits,
3417 int64_t Cst, bool IsVector, bool IsFP) {
3418 // For i1, Cst will always be -1 regardless of boolean contents.
3419 return (ScalarSizeBits == 1 && Cst == -1) ||
3420 isConstTrueVal(TLI, Cst, IsVector, IsFP);
3421}
3422
3423// This pattern aims to match the following shape to avoid extra mov
3424// instructions
3425// G_BUILD_VECTOR(
3426// G_UNMERGE_VALUES(src, 0)
3427// G_UNMERGE_VALUES(src, 1)
3428// G_IMPLICIT_DEF
3429// G_IMPLICIT_DEF
3430// )
3431// ->
3432// G_CONCAT_VECTORS(
3433// src,
3434// undef
3435// )
3438 Register &UnmergeSrc) const {
3439 auto &BV = cast<GBuildVector>(MI);
3440
3441 unsigned BuildUseCount = BV.getNumSources();
3442 if (BuildUseCount % 2 != 0)
3443 return false;
3444
3445 unsigned NumUnmerge = BuildUseCount / 2;
3446
3447 auto *Unmerge = getOpcodeDef<GUnmerge>(BV.getSourceReg(0), MRI);
3448
3449 // Check the first operand is an unmerge and has the correct number of
3450 // operands
3451 if (!Unmerge || Unmerge->getNumDefs() != NumUnmerge)
3452 return false;
3453
3454 UnmergeSrc = Unmerge->getSourceReg();
3455
3456 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
3457 LLT UnmergeSrcTy = MRI.getType(UnmergeSrc);
3458
3459 if (!UnmergeSrcTy.isVector())
3460 return false;
3461
3462 // Ensure we only generate legal instructions post-legalizer
3463 if (!IsPreLegalize &&
3464 !isLegal({TargetOpcode::G_CONCAT_VECTORS, {DstTy, UnmergeSrcTy}}))
3465 return false;
3466
3467 // Check that all of the operands before the midpoint come from the same
3468 // unmerge and are in the same order as they are used in the build_vector
3469 for (unsigned I = 0; I < NumUnmerge; ++I) {
3470 auto MaybeUnmergeReg = BV.getSourceReg(I);
3471 auto *LoopUnmerge = getOpcodeDef<GUnmerge>(MaybeUnmergeReg, MRI);
3472
3473 if (!LoopUnmerge || LoopUnmerge != Unmerge)
3474 return false;
3475
3476 if (LoopUnmerge->getOperand(I).getReg() != MaybeUnmergeReg)
3477 return false;
3478 }
3479
3480 // Check that all of the unmerged values are used
3481 if (Unmerge->getNumDefs() != NumUnmerge)
3482 return false;
3483
3484 // Check that all of the operands after the mid point are undefs.
3485 for (unsigned I = NumUnmerge; I < BuildUseCount; ++I) {
3486 auto *Undef = getDefIgnoringCopies(BV.getSourceReg(I), MRI);
3487
3488 if (Undef->getOpcode() != TargetOpcode::G_IMPLICIT_DEF)
3489 return false;
3490 }
3491
3492 return true;
3493}
3494
3498 Register &UnmergeSrc) const {
3499 assert(UnmergeSrc && "Expected there to be one matching G_UNMERGE_VALUES");
3500 B.setInstrAndDebugLoc(MI);
3501
3502 Register UndefVec = B.buildUndef(MRI.getType(UnmergeSrc)).getReg(0);
3503 B.buildConcatVectors(MI.getOperand(0), {UnmergeSrc, UndefVec});
3504
3505 MI.eraseFromParent();
3506}
3507
3508// This combine tries to reduce the number of scalarised G_TRUNC instructions by
3509// using vector truncates instead
3510//
3511// EXAMPLE:
3512// %a(i32), %b(i32) = G_UNMERGE_VALUES %src(<2 x i32>)
3513// %T_a(i16) = G_TRUNC %a(i32)
3514// %T_b(i16) = G_TRUNC %b(i32)
3515// %Undef(i16) = G_IMPLICIT_DEF(i16)
3516// %dst(v4i16) = G_BUILD_VECTORS %T_a(i16), %T_b(i16), %Undef(i16), %Undef(i16)
3517//
3518// ===>
3519// %Undef(<2 x i32>) = G_IMPLICIT_DEF(<2 x i32>)
3520// %Mid(<4 x s32>) = G_CONCAT_VECTORS %src(<2 x i32>), %Undef(<2 x i32>)
3521// %dst(<4 x s16>) = G_TRUNC %Mid(<4 x s32>)
3522//
3523// Only matches sources made up of G_TRUNCs followed by G_IMPLICIT_DEFs
3525 Register &MatchInfo) const {
3526 auto BuildMI = cast<GBuildVector>(&MI);
3527 unsigned NumOperands = BuildMI->getNumSources();
3528 LLT DstTy = MRI.getType(BuildMI->getReg(0));
3529
3530 // Check the G_BUILD_VECTOR sources
3531 unsigned I;
3532 GUnmerge *UnmergeMI = nullptr;
3533
3534 // Check all source TRUNCs come from the same UNMERGE instruction
3535 // and that the element order matches (BUILD_VECTOR position I
3536 // corresponds to UNMERGE result I)
3537 for (I = 0; I < NumOperands; ++I) {
3538 // Check if the G_TRUNC instructions all come from the same MI
3539 Register TruncSrcReg;
3540 if (!mi_match(BuildMI->getSourceReg(I), MRI, m_GTrunc(m_Reg(TruncSrcReg))))
3541 break;
3542
3543 if (!UnmergeMI) {
3544 if (!mi_match(TruncSrcReg, MRI, m_GUnmerge(UnmergeMI)))
3545 return false;
3546 } else {
3547 MachineInstr *UnmergeSrcMI;
3548 if (!mi_match(TruncSrcReg, MRI, m_MInstr(UnmergeSrcMI)) ||
3549 UnmergeMI != UnmergeSrcMI)
3550 return false;
3551 }
3552 // Element order must match: position I must use UNMERGE result I.
3553 if (UnmergeMI->getOperand(I).getReg() != TruncSrcReg)
3554 return false;
3555 }
3556 if (I < 2)
3557 return false;
3558
3559 // Check the remaining source elements are only G_IMPLICIT_DEF
3560 for (; I < NumOperands; ++I) {
3561 if (!mi_match(BuildMI->getSourceReg(I), MRI, m_GImplicitDef()))
3562 return false;
3563 }
3564
3565 // Check the size of unmerge source
3566 MatchInfo = UnmergeMI->getSourceReg();
3567 LLT UnmergeSrcTy = MRI.getType(MatchInfo);
3568 if (!DstTy.getElementCount().isKnownMultipleOf(UnmergeSrcTy.getNumElements()))
3569 return false;
3570
3571 // Check the unmerge source and destination element types match
3572 LLT UnmergeSrcEltTy = UnmergeSrcTy.getElementType();
3573 Register UnmergeDstReg = UnmergeMI->getOperand(0).getReg();
3574 LLT UnmergeDstEltTy = MRI.getType(UnmergeDstReg);
3575 if (UnmergeSrcEltTy != UnmergeDstEltTy)
3576 return false;
3577
3578 // Only generate legal instructions post-legalizer
3579 if (!IsPreLegalize) {
3580 LLT MidTy = DstTy.changeElementType(UnmergeSrcTy.getScalarType());
3581
3582 if (DstTy.getElementCount() != UnmergeSrcTy.getElementCount() &&
3583 !isLegal({TargetOpcode::G_CONCAT_VECTORS, {MidTy, UnmergeSrcTy}}))
3584 return false;
3585
3586 if (!isLegal({TargetOpcode::G_TRUNC, {DstTy, MidTy}}))
3587 return false;
3588 }
3589
3590 return true;
3591}
3592
3594 Register &MatchInfo) const {
3595 Register MidReg;
3596 auto BuildMI = cast<GBuildVector>(&MI);
3597 Register DstReg = BuildMI->getReg(0);
3598 LLT DstTy = MRI.getType(DstReg);
3599 LLT UnmergeSrcTy = MRI.getType(MatchInfo);
3600 unsigned DstTyNumElt = DstTy.getNumElements();
3601 unsigned UnmergeSrcTyNumElt = UnmergeSrcTy.getNumElements();
3602
3603 // No need to pad vector if only G_TRUNC is needed
3604 if (DstTyNumElt / UnmergeSrcTyNumElt == 1) {
3605 MidReg = MatchInfo;
3606 } else {
3607 Register UndefReg = Builder.buildUndef(UnmergeSrcTy).getReg(0);
3608 SmallVector<Register> ConcatRegs = {MatchInfo};
3609 for (unsigned I = 1; I < DstTyNumElt / UnmergeSrcTyNumElt; ++I)
3610 ConcatRegs.push_back(UndefReg);
3611
3612 auto MidTy = DstTy.changeElementType(UnmergeSrcTy.getScalarType());
3613 MidReg = Builder.buildConcatVectors(MidTy, ConcatRegs).getReg(0);
3614 }
3615
3616 Builder.buildTrunc(DstReg, MidReg);
3617 MI.eraseFromParent();
3618}
3619
3621 MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate) const {
3622 assert(MI.getOpcode() == TargetOpcode::G_XOR);
3623 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3624 const auto &TLI = *Builder.getMF().getSubtarget().getTargetLowering();
3625 Register XorSrc;
3626 Register CstReg;
3627 // We match xor(src, true) here.
3628 if (!mi_match(MI.getOperand(0).getReg(), MRI,
3629 m_GXor(m_Reg(XorSrc), m_Reg(CstReg))))
3630 return false;
3631
3632 if (!MRI.hasOneNonDBGUse(XorSrc))
3633 return false;
3634
3635 // Check that XorSrc is the root of a tree of comparisons combined with ANDs
3636 // and ORs. The suffix of RegsToNegate starting from index I is used a work
3637 // list of tree nodes to visit.
3638 RegsToNegate.push_back(XorSrc);
3639 // Remember whether the comparisons are all integer or all floating point.
3640 bool IsInt = false;
3641 bool IsFP = false;
3642 for (unsigned I = 0; I < RegsToNegate.size(); ++I) {
3643 Register Reg = RegsToNegate[I];
3644 if (!MRI.hasOneNonDBGUse(Reg))
3645 return false;
3646 MachineInstr *Def;
3647 if (!mi_match(Reg, MRI, m_MInstr(Def)))
3648 return false;
3649 switch (Def->getOpcode()) {
3650 default:
3651 // Don't match if the tree contains anything other than ANDs, ORs and
3652 // comparisons.
3653 return false;
3654 case TargetOpcode::G_ICMP:
3655 if (IsFP)
3656 return false;
3657 IsInt = true;
3658 // When we apply the combine we will invert the predicate.
3659 break;
3660 case TargetOpcode::G_FCMP:
3661 if (IsInt)
3662 return false;
3663 IsFP = true;
3664 // When we apply the combine we will invert the predicate.
3665 break;
3666 case TargetOpcode::G_AND:
3667 case TargetOpcode::G_OR:
3668 // Implement De Morgan's laws:
3669 // ~(x & y) -> ~x | ~y
3670 // ~(x | y) -> ~x & ~y
3671 // When we apply the combine we will change the opcode and recursively
3672 // negate the operands.
3673 RegsToNegate.push_back(Def->getOperand(1).getReg());
3674 RegsToNegate.push_back(Def->getOperand(2).getReg());
3675 break;
3676 }
3677 }
3678
3679 // Now we know whether the comparisons are integer or floating point, check
3680 // the constant in the xor.
3681 int64_t Cst;
3682 if (Ty.isVector()) {
3683 int64_t SplatCst;
3684 if (!mi_match(CstReg, MRI, m_ICstOrSplat(SplatCst)))
3685 return false;
3686 if (!isConstValidTrue(TLI, Ty.getScalarSizeInBits(), SplatCst, true, IsFP))
3687 return false;
3688 } else {
3689 if (!mi_match(CstReg, MRI, m_ICst(Cst)))
3690 return false;
3691 if (!isConstValidTrue(TLI, Ty.getSizeInBits(), Cst, false, IsFP))
3692 return false;
3693 }
3694
3695 return true;
3696}
3697
3699 MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate) const {
3700 for (Register Reg : RegsToNegate) {
3701 MachineInstr *Def = MRI.getVRegDef(Reg);
3702 Observer.changingInstr(*Def);
3703 // For each comparison, invert the opcode. For each AND and OR, change the
3704 // opcode.
3705 switch (Def->getOpcode()) {
3706 default:
3707 llvm_unreachable("Unexpected opcode");
3708 case TargetOpcode::G_ICMP:
3709 case TargetOpcode::G_FCMP: {
3710 MachineOperand &PredOp = Def->getOperand(1);
3713 PredOp.setPredicate(NewP);
3714 break;
3715 }
3716 case TargetOpcode::G_AND:
3717 Def->setDesc(Builder.getTII().get(TargetOpcode::G_OR));
3718 break;
3719 case TargetOpcode::G_OR:
3720 Def->setDesc(Builder.getTII().get(TargetOpcode::G_AND));
3721 break;
3722 }
3723 Observer.changedInstr(*Def);
3724 }
3725
3726 replaceRegWith(MRI, MI.getOperand(0).getReg(), MI.getOperand(1).getReg());
3727 MI.eraseFromParent();
3728}
3729
3731 MachineInstr &MI, std::pair<Register, Register> &MatchInfo) const {
3732 // Match (xor (and x, y), y) (or any of its commuted cases)
3733 assert(MI.getOpcode() == TargetOpcode::G_XOR);
3734 Register &X = MatchInfo.first;
3735 Register &Y = MatchInfo.second;
3736 Register AndReg = MI.getOperand(1).getReg();
3737 Register SharedReg = MI.getOperand(2).getReg();
3738
3739 // Find a G_AND on either side of the G_XOR.
3740 // Look for one of
3741 //
3742 // (xor (and x, y), SharedReg)
3743 // (xor SharedReg, (and x, y))
3744 if (!mi_match(AndReg, MRI, m_GAnd(m_Reg(X), m_Reg(Y)))) {
3745 std::swap(AndReg, SharedReg);
3746 if (!mi_match(AndReg, MRI, m_GAnd(m_Reg(X), m_Reg(Y))))
3747 return false;
3748 }
3749
3750 // Only do this if we'll eliminate the G_AND.
3751 if (!MRI.hasOneNonDBGUse(AndReg))
3752 return false;
3753
3754 // We can combine if SharedReg is the same as either the LHS or RHS of the
3755 // G_AND.
3756 if (Y != SharedReg)
3757 std::swap(X, Y);
3758 return Y == SharedReg;
3759}
3760
3762 MachineInstr &MI, std::pair<Register, Register> &MatchInfo) const {
3763 // Fold (xor (and x, y), y) -> (and (not x), y)
3764 Register X, Y;
3765 std::tie(X, Y) = MatchInfo;
3766 auto Not = Builder.buildNot(MRI.getType(X), X);
3767 Observer.changingInstr(MI);
3768 MI.setDesc(Builder.getTII().get(TargetOpcode::G_AND));
3769 MI.getOperand(1).setReg(Not->getOperand(0).getReg());
3770 MI.getOperand(2).setReg(Y);
3771 Observer.changedInstr(MI);
3772}
3773
3775 auto &PtrAdd = cast<GPtrAdd>(MI);
3776 Register DstReg = PtrAdd.getReg(0);
3777 LLT Ty = MRI.getType(DstReg);
3778 const DataLayout &DL = Builder.getMF().getDataLayout();
3779
3780 if (DL.isNonIntegralAddressSpace(Ty.getScalarType().getAddressSpace()))
3781 return false;
3782
3783 if (Ty.isPointer()) {
3784 auto ConstVal = getIConstantVRegVal(PtrAdd.getBaseReg(), MRI);
3785 return ConstVal && *ConstVal == 0;
3786 }
3787
3788 assert(Ty.isVector() && "Expecting a vector type");
3789 const MachineInstr *VecMI;
3790 if (!mi_match(PtrAdd.getBaseReg(), MRI, m_MInstr(VecMI)))
3791 return false;
3792 return isBuildVectorAllZeros(*VecMI, MRI);
3793}
3794
3795/// The second source operand is known to be a power of 2.
3797 Register DstReg = MI.getOperand(0).getReg();
3798 Register Src0 = MI.getOperand(1).getReg();
3799 Register Pow2Src1 = MI.getOperand(2).getReg();
3800 LLT Ty = MRI.getType(DstReg);
3801
3802 // Fold (urem x, pow2) -> (and x, pow2-1)
3803 auto NegOne = Builder.buildConstant(Ty, -1);
3804 auto Add = Builder.buildAdd(Ty, Pow2Src1, NegOne);
3805 Builder.buildAnd(DstReg, Src0, Add);
3806 MI.eraseFromParent();
3807}
3808
3810 unsigned &SelectOpNo) const {
3811 Register LHS = MI.getOperand(1).getReg();
3812 Register RHS = MI.getOperand(2).getReg();
3813
3814 Register OtherOperandReg = RHS;
3815 SelectOpNo = 1;
3816 Register SelectTrue, SelectFalse;
3817
3818 // Don't do this unless the old select is going away. We want to eliminate the
3819 // binary operator, not replace a binop with a select.
3820 if (!mi_match(LHS, MRI,
3821 m_GISelect(m_Reg(), m_Reg(SelectTrue), m_Reg(SelectFalse))) ||
3822 !MRI.hasOneNonDBGUse(LHS)) {
3823 OtherOperandReg = LHS;
3824 SelectOpNo = 2;
3825 if (!mi_match(RHS, MRI,
3826 m_GISelect(m_Reg(), m_Reg(SelectTrue), m_Reg(SelectFalse))) ||
3827 !MRI.hasOneNonDBGUse(RHS))
3828 return false;
3829 }
3830
3831 MachineInstr *SelectLHS, *SelectRHS;
3832 if (!mi_match(SelectTrue, MRI, m_MInstr(SelectLHS)) ||
3833 !mi_match(SelectFalse, MRI, m_MInstr(SelectRHS)))
3834 return false;
3835
3836 if (!isConstantOrConstantVector(*SelectLHS, MRI,
3837 /*AllowFP*/ true,
3838 /*AllowOpaqueConstants*/ false))
3839 return false;
3840 if (!isConstantOrConstantVector(*SelectRHS, MRI,
3841 /*AllowFP*/ true,
3842 /*AllowOpaqueConstants*/ false))
3843 return false;
3844
3845 unsigned BinOpcode = MI.getOpcode();
3846
3847 // We know that one of the operands is a select of constants. Now verify that
3848 // the other binary operator operand is either a constant, or we can handle a
3849 // variable.
3850 bool CanFoldNonConst =
3851 (BinOpcode == TargetOpcode::G_AND || BinOpcode == TargetOpcode::G_OR) &&
3852 (isNullOrNullSplat(*SelectLHS, MRI) ||
3853 isAllOnesOrAllOnesSplat(*SelectLHS, MRI)) &&
3854 (isNullOrNullSplat(*SelectRHS, MRI) ||
3855 isAllOnesOrAllOnesSplat(*SelectRHS, MRI));
3856 if (CanFoldNonConst)
3857 return true;
3858
3859 MachineInstr *OtherOperandDef;
3860 if (!mi_match(OtherOperandReg, MRI, m_MInstr(OtherOperandDef)))
3861 return false;
3862 return isConstantOrConstantVector(*OtherOperandDef, MRI,
3863 /*AllowFP*/ true,
3864 /*AllowOpaqueConstants*/ false);
3865}
3866
3867/// \p SelectOperand is the operand in binary operator \p MI that is the select
3868/// to fold.
3870 MachineInstr &MI, const unsigned &SelectOperand) const {
3871 Register Dst = MI.getOperand(0).getReg();
3872 Register LHS = MI.getOperand(1).getReg();
3873 Register RHS = MI.getOperand(2).getReg();
3874 GSelect *Select =
3875 cast<GSelect>(MRI.getVRegDef(MI.getOperand(SelectOperand).getReg()));
3876
3877 Register SelectCond = Select->getCondReg();
3878 Register SelectTrue = Select->getTrueReg();
3879 Register SelectFalse = Select->getFalseReg();
3880
3881 LLT Ty = MRI.getType(Dst);
3882 unsigned BinOpcode = MI.getOpcode();
3883
3884 Register FoldTrue, FoldFalse;
3885
3886 // We have a select-of-constants followed by a binary operator with a
3887 // constant. Eliminate the binop by pulling the constant math into the select.
3888 // Example: add (select Cond, CT, CF), CBO --> select Cond, CT + CBO, CF + CBO
3889 if (SelectOperand == 1) {
3890 // TODO: SelectionDAG verifies this actually constant folds before
3891 // committing to the combine.
3892
3893 FoldTrue = Builder.buildInstr(BinOpcode, {Ty}, {SelectTrue, RHS}).getReg(0);
3894 FoldFalse =
3895 Builder.buildInstr(BinOpcode, {Ty}, {SelectFalse, RHS}).getReg(0);
3896 } else {
3897 FoldTrue = Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectTrue}).getReg(0);
3898 FoldFalse =
3899 Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectFalse}).getReg(0);
3900 }
3901
3902 Builder.buildSelect(Dst, SelectCond, FoldTrue, FoldFalse, MI.getFlags());
3903 MI.eraseFromParent();
3904}
3905
3906std::optional<SmallVector<Register, 8>>
3907CombinerHelper::findCandidatesForLoadOrCombine(const MachineInstr *Root) const {
3908 assert(Root->getOpcode() == TargetOpcode::G_OR && "Expected G_OR only!");
3909 // We want to detect if Root is part of a tree which represents a bunch
3910 // of loads being merged into a larger load. We'll try to recognize patterns
3911 // like, for example:
3912 //
3913 // Reg Reg
3914 // \ /
3915 // OR_1 Reg
3916 // \ /
3917 // OR_2
3918 // \ Reg
3919 // .. /
3920 // Root
3921 //
3922 // Reg Reg Reg Reg
3923 // \ / \ /
3924 // OR_1 OR_2
3925 // \ /
3926 // \ /
3927 // ...
3928 // Root
3929 //
3930 // Each "Reg" may have been produced by a load + some arithmetic. This
3931 // function will save each of them.
3932 SmallVector<Register, 8> RegsToVisit;
3934
3935 // In the "worst" case, we're dealing with a load for each byte. So, there
3936 // are at most #bytes - 1 ORs.
3937 const unsigned MaxIter =
3938 MRI.getType(Root->getOperand(0).getReg()).getSizeInBytes() - 1;
3939 for (unsigned Iter = 0; Iter < MaxIter; ++Iter) {
3940 if (Ors.empty())
3941 break;
3942 const MachineInstr *Curr = Ors.pop_back_val();
3943 Register OrLHS = Curr->getOperand(1).getReg();
3944 Register OrRHS = Curr->getOperand(2).getReg();
3945
3946 // In the combine, we want to elimate the entire tree.
3947 if (!MRI.hasOneNonDBGUse(OrLHS) || !MRI.hasOneNonDBGUse(OrRHS))
3948 return std::nullopt;
3949
3950 // If it's a G_OR, save it and continue to walk. If it's not, then it's
3951 // something that may be a load + arithmetic.
3952 if (const MachineInstr *Or = getOpcodeDef(TargetOpcode::G_OR, OrLHS, MRI))
3953 Ors.push_back(Or);
3954 else
3955 RegsToVisit.push_back(OrLHS);
3956 if (const MachineInstr *Or = getOpcodeDef(TargetOpcode::G_OR, OrRHS, MRI))
3957 Ors.push_back(Or);
3958 else
3959 RegsToVisit.push_back(OrRHS);
3960 }
3961
3962 // We're going to try and merge each register into a wider power-of-2 type,
3963 // so we ought to have an even number of registers.
3964 if (RegsToVisit.empty() || RegsToVisit.size() % 2 != 0)
3965 return std::nullopt;
3966 return RegsToVisit;
3967}
3968
3969/// Helper function for findLoadOffsetsForLoadOrCombine.
3970///
3971/// Check if \p Reg is the result of loading a \p MemSizeInBits wide value,
3972/// and then moving that value into a specific byte offset.
3973///
3974/// e.g. x[i] << 24
3975///
3976/// \returns The load instruction and the byte offset it is moved into.
3977static std::optional<std::pair<GZExtLoad *, int64_t>>
3978matchLoadAndBytePosition(Register Reg, unsigned MemSizeInBits,
3979 const MachineRegisterInfo &MRI) {
3980 assert(MRI.hasOneNonDBGUse(Reg) &&
3981 "Expected Reg to only have one non-debug use?");
3982 Register MaybeLoad;
3983 int64_t Shift;
3984 if (!mi_match(Reg, MRI,
3985 m_OneNonDBGUse(m_GShl(m_Reg(MaybeLoad), m_ICst(Shift))))) {
3986 Shift = 0;
3987 MaybeLoad = Reg;
3988 }
3989
3990 if (Shift % MemSizeInBits != 0)
3991 return std::nullopt;
3992
3993 // TODO: Handle other types of loads.
3994 auto *Load = getOpcodeDef<GZExtLoad>(MaybeLoad, MRI);
3995 if (!Load)
3996 return std::nullopt;
3997
3998 if (!Load->isUnordered() || Load->getMemSizeInBits() != MemSizeInBits)
3999 return std::nullopt;
4000
4001 return std::make_pair(Load, Shift / MemSizeInBits);
4002}
4003
4004std::optional<std::tuple<GZExtLoad *, int64_t, GZExtLoad *>>
4005CombinerHelper::findLoadOffsetsForLoadOrCombine(
4007 const SmallVector<Register, 8> &RegsToVisit,
4008 const unsigned MemSizeInBits) const {
4009
4010 // Each load found for the pattern. There should be one for each RegsToVisit.
4011 SmallSetVector<const MachineInstr *, 8> Loads;
4012
4013 // The lowest index used in any load. (The lowest "i" for each x[i].)
4014 int64_t LowestIdx = INT64_MAX;
4015
4016 // The load which uses the lowest index.
4017 GZExtLoad *LowestIdxLoad = nullptr;
4018
4019 // Keeps track of the load indices we see. We shouldn't see any indices twice.
4020 SmallSet<int64_t, 8> SeenIdx;
4021
4022 // Ensure each load is in the same MBB.
4023 // TODO: Support multiple MachineBasicBlocks.
4024 MachineBasicBlock *MBB = nullptr;
4025 const MachineMemOperand *MMO = nullptr;
4026
4027 // Earliest instruction-order load in the pattern.
4028 GZExtLoad *EarliestLoad = nullptr;
4029
4030 // Latest instruction-order load in the pattern.
4031 GZExtLoad *LatestLoad = nullptr;
4032
4033 // Base pointer which every load should share.
4035
4036 // We want to find a load for each register. Each load should have some
4037 // appropriate bit twiddling arithmetic. During this loop, we will also keep
4038 // track of the load which uses the lowest index. Later, we will check if we
4039 // can use its pointer in the final, combined load.
4040 for (auto Reg : RegsToVisit) {
4041 // Find the load, and find the position that it will end up in (e.g. a
4042 // shifted) value.
4043 auto LoadAndPos = matchLoadAndBytePosition(Reg, MemSizeInBits, MRI);
4044 if (!LoadAndPos)
4045 return std::nullopt;
4046 GZExtLoad *Load;
4047 int64_t DstPos;
4048 std::tie(Load, DstPos) = *LoadAndPos;
4049
4050 // TODO: Handle multiple MachineBasicBlocks. Currently not handled because
4051 // it is difficult to check for stores/calls/etc between loads.
4052 MachineBasicBlock *LoadMBB = Load->getParent();
4053 if (!MBB)
4054 MBB = LoadMBB;
4055 if (LoadMBB != MBB)
4056 return std::nullopt;
4057
4058 // Make sure that the MachineMemOperands of every seen load are compatible.
4059 auto &LoadMMO = Load->getMMO();
4060 if (!MMO)
4061 MMO = &LoadMMO;
4062 if (MMO->getAddrSpace() != LoadMMO.getAddrSpace())
4063 return std::nullopt;
4064
4065 // Find out what the base pointer and index for the load is.
4066 Register LoadPtr;
4067 int64_t Idx;
4068 if (!mi_match(Load->getOperand(1).getReg(), MRI,
4069 m_GPtrAdd(m_Reg(LoadPtr), m_ICst(Idx)))) {
4070 LoadPtr = Load->getOperand(1).getReg();
4071 Idx = 0;
4072 }
4073
4074 // Don't combine things like a[i], a[i] -> a bigger load.
4075 if (!SeenIdx.insert(Idx).second)
4076 return std::nullopt;
4077
4078 // Every load must share the same base pointer; don't combine things like:
4079 //
4080 // a[i], b[i + 1] -> a bigger load.
4081 if (!BasePtr.isValid())
4082 BasePtr = LoadPtr;
4083 if (BasePtr != LoadPtr)
4084 return std::nullopt;
4085
4086 if (Idx < LowestIdx) {
4087 LowestIdx = Idx;
4088 LowestIdxLoad = Load;
4089 }
4090
4091 // Keep track of the byte offset that this load ends up at. If we have seen
4092 // the byte offset, then stop here. We do not want to combine:
4093 //
4094 // a[i] << 16, a[i + k] << 16 -> a bigger load.
4095 if (!MemOffset2Idx.try_emplace(DstPos, Idx).second)
4096 return std::nullopt;
4097 Loads.insert(Load);
4098
4099 // Keep track of the position of the earliest/latest loads in the pattern.
4100 // We will check that there are no load fold barriers between them later
4101 // on.
4102 //
4103 // FIXME: Is there a better way to check for load fold barriers?
4104 if (!EarliestLoad || dominates(*Load, *EarliestLoad))
4105 EarliestLoad = Load;
4106 if (!LatestLoad || dominates(*LatestLoad, *Load))
4107 LatestLoad = Load;
4108 }
4109
4110 // We found a load for each register. Let's check if each load satisfies the
4111 // pattern.
4112 assert(Loads.size() == RegsToVisit.size() &&
4113 "Expected to find a load for each register?");
4114 assert(EarliestLoad != LatestLoad && EarliestLoad &&
4115 LatestLoad && "Expected at least two loads?");
4116
4117 // Check if there are any stores, calls, etc. between any of the loads. If
4118 // there are, then we can't safely perform the combine.
4119 //
4120 // MaxIter is chosen based off the (worst case) number of iterations it
4121 // typically takes to succeed in the LLVM test suite plus some padding.
4122 //
4123 // FIXME: Is there a better way to check for load fold barriers?
4124 const unsigned MaxIter = 20;
4125 unsigned Iter = 0;
4126 for (const auto &MI : instructionsWithoutDebug(EarliestLoad->getIterator(),
4127 LatestLoad->getIterator())) {
4128 if (Loads.count(&MI))
4129 continue;
4130 if (MI.isLoadFoldBarrier())
4131 return std::nullopt;
4132 if (Iter++ == MaxIter)
4133 return std::nullopt;
4134 }
4135
4136 return std::make_tuple(LowestIdxLoad, LowestIdx, LatestLoad);
4137}
4138
4141 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4142 assert(MI.getOpcode() == TargetOpcode::G_OR);
4143 MachineFunction &MF = *MI.getMF();
4144 // Assuming a little-endian target, transform:
4145 // s8 *a = ...
4146 // s32 val = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24)
4147 // =>
4148 // s32 val = *((i32)a)
4149 //
4150 // s8 *a = ...
4151 // s32 val = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]
4152 // =>
4153 // s32 val = BSWAP(*((s32)a))
4154 Register Dst = MI.getOperand(0).getReg();
4155 LLT Ty = MRI.getType(Dst);
4156 if (Ty.isVector())
4157 return false;
4158
4159 // We need to combine at least two loads into this type. Since the smallest
4160 // possible load is into a byte, we need at least a 16-bit wide type.
4161 const unsigned WideMemSizeInBits = Ty.getSizeInBits();
4162 if (WideMemSizeInBits < 16 || WideMemSizeInBits % 8 != 0)
4163 return false;
4164
4165 // Match a collection of non-OR instructions in the pattern.
4166 auto RegsToVisit = findCandidatesForLoadOrCombine(&MI);
4167 if (!RegsToVisit)
4168 return false;
4169
4170 // We have a collection of non-OR instructions. Figure out how wide each of
4171 // the small loads should be based off of the number of potential loads we
4172 // found.
4173 const unsigned NarrowMemSizeInBits = WideMemSizeInBits / RegsToVisit->size();
4174 if (NarrowMemSizeInBits % 8 != 0)
4175 return false;
4176
4177 // Check if each register feeding into each OR is a load from the same
4178 // base pointer + some arithmetic.
4179 //
4180 // e.g. a[0], a[1] << 8, a[2] << 16, etc.
4181 //
4182 // Also verify that each of these ends up putting a[i] into the same memory
4183 // offset as a load into a wide type would.
4185 GZExtLoad *LowestIdxLoad, *LatestLoad;
4186 int64_t LowestIdx;
4187 auto MaybeLoadInfo = findLoadOffsetsForLoadOrCombine(
4188 MemOffset2Idx, *RegsToVisit, NarrowMemSizeInBits);
4189 if (!MaybeLoadInfo)
4190 return false;
4191 std::tie(LowestIdxLoad, LowestIdx, LatestLoad) = *MaybeLoadInfo;
4192
4193 // We have a bunch of loads being OR'd together. Using the addresses + offsets
4194 // we found before, check if this corresponds to a big or little endian byte
4195 // pattern. If it does, then we can represent it using a load + possibly a
4196 // BSWAP.
4197 bool IsBigEndianTarget = MF.getDataLayout().isBigEndian();
4198 std::optional<bool> IsBigEndian = isBigEndian(MemOffset2Idx, LowestIdx);
4199 if (!IsBigEndian)
4200 return false;
4201 bool NeedsBSwap = IsBigEndianTarget != *IsBigEndian;
4202 if (NeedsBSwap && !isLegalOrBeforeLegalizer({TargetOpcode::G_BSWAP, {Ty}}))
4203 return false;
4204
4205 // Make sure that the load from the lowest index produces offset 0 in the
4206 // final value.
4207 //
4208 // This ensures that we won't combine something like this:
4209 //
4210 // load x[i] -> byte 2
4211 // load x[i+1] -> byte 0 ---> wide_load x[i]
4212 // load x[i+2] -> byte 1
4213 const unsigned NumLoadsInTy = WideMemSizeInBits / NarrowMemSizeInBits;
4214 const unsigned ZeroByteOffset =
4215 *IsBigEndian
4216 ? bigEndianByteAt(NumLoadsInTy, 0)
4217 : littleEndianByteAt(NumLoadsInTy, 0);
4218 auto ZeroOffsetIdx = MemOffset2Idx.find(ZeroByteOffset);
4219 if (ZeroOffsetIdx == MemOffset2Idx.end() ||
4220 ZeroOffsetIdx->second != LowestIdx)
4221 return false;
4222
4223 // We wil reuse the pointer from the load which ends up at byte offset 0. It
4224 // may not use index 0.
4225 Register Ptr = LowestIdxLoad->getPointerReg();
4226 const MachineMemOperand &MMO = LowestIdxLoad->getMMO();
4227 LegalityQuery::MemDesc MMDesc(MMO);
4228 MMDesc.MemoryTy = Ty;
4230 {TargetOpcode::G_LOAD, {Ty, MRI.getType(Ptr)}, {MMDesc}}))
4231 return false;
4232 auto PtrInfo = MMO.getPointerInfo();
4233 auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, WideMemSizeInBits / 8);
4234
4235 // Load must be allowed and fast on the target.
4237 auto &DL = MF.getDataLayout();
4238 unsigned Fast = 0;
4239 if (!getTargetLowering().allowsMemoryAccess(C, DL, Ty, *NewMMO, &Fast) ||
4240 !Fast)
4241 return false;
4242
4243 MatchInfo = [=](MachineIRBuilder &MIB) {
4244 MIB.setInstrAndDebugLoc(*LatestLoad);
4245 Register LoadDst = NeedsBSwap ? MRI.cloneVirtualRegister(Dst) : Dst;
4246 MIB.buildLoad(LoadDst, Ptr, *NewMMO);
4247 if (NeedsBSwap)
4248 MIB.buildBSwap(Dst, LoadDst);
4249 };
4250 return true;
4251}
4252
4254 MachineInstr *&ExtMI) const {
4255 auto &PHI = cast<GPhi>(MI);
4256 Register DstReg = PHI.getReg(0);
4257
4258 // TODO: Extending a vector may be expensive, don't do this until heuristics
4259 // are better.
4260 if (MRI.getType(DstReg).isVector())
4261 return false;
4262
4263 // Try to match a phi, whose only use is an extend.
4264 if (!MRI.hasOneNonDBGUse(DstReg))
4265 return false;
4266 ExtMI = &*MRI.use_instr_nodbg_begin(DstReg);
4267 switch (ExtMI->getOpcode()) {
4268 case TargetOpcode::G_ANYEXT:
4269 return true; // G_ANYEXT is usually free.
4270 case TargetOpcode::G_ZEXT:
4271 case TargetOpcode::G_SEXT:
4272 break;
4273 default:
4274 return false;
4275 }
4276
4277 // If the target is likely to fold this extend away, don't propagate.
4278 if (Builder.getTII().isExtendLikelyToBeFolded(*ExtMI, MRI))
4279 return false;
4280
4281 // We don't want to propagate the extends unless there's a good chance that
4282 // they'll be optimized in some way.
4283 // Collect the unique incoming values.
4285 for (unsigned I = 0; I < PHI.getNumIncomingValues(); ++I) {
4286 auto *DefMI = getDefIgnoringCopies(PHI.getIncomingValue(I), MRI);
4287 switch (DefMI->getOpcode()) {
4288 case TargetOpcode::G_LOAD:
4289 case TargetOpcode::G_TRUNC:
4290 case TargetOpcode::G_SEXT:
4291 case TargetOpcode::G_ZEXT:
4292 case TargetOpcode::G_ANYEXT:
4293 case TargetOpcode::G_CONSTANT:
4294 InSrcs.insert(DefMI);
4295 // Don't try to propagate if there are too many places to create new
4296 // extends, chances are it'll increase code size.
4297 if (InSrcs.size() > 2)
4298 return false;
4299 break;
4300 default:
4301 return false;
4302 }
4303 }
4304 return true;
4305}
4306
4308 MachineInstr *&ExtMI) const {
4309 auto &PHI = cast<GPhi>(MI);
4310 Register DstReg = ExtMI->getOperand(0).getReg();
4311 LLT ExtTy = MRI.getType(DstReg);
4312
4313 // Propagate the extension into the block of each incoming reg's block.
4314 // Use a SetVector here because PHIs can have duplicate edges, and we want
4315 // deterministic iteration order.
4318 for (unsigned I = 0; I < PHI.getNumIncomingValues(); ++I) {
4319 auto SrcReg = PHI.getIncomingValue(I);
4320 MachineInstr *SrcMI;
4321 if (!mi_match(SrcReg, MRI, m_MInstr(SrcMI)))
4322 continue;
4323 if (!SrcMIs.insert(SrcMI))
4324 continue;
4325
4326 // Build an extend after each src inst.
4327 auto *MBB = SrcMI->getParent();
4328 MachineBasicBlock::iterator InsertPt = ++SrcMI->getIterator();
4329 if (InsertPt != MBB->end() && InsertPt->isPHI())
4330 InsertPt = MBB->getFirstNonPHI();
4331
4332 Builder.setInsertPt(*SrcMI->getParent(), InsertPt);
4333 Builder.setDebugLoc(MI.getDebugLoc());
4334 auto NewExt = Builder.buildExtOrTrunc(ExtMI->getOpcode(), ExtTy, SrcReg);
4335 OldToNewSrcMap[SrcMI] = NewExt;
4336 }
4337
4338 // Create a new phi with the extended inputs.
4339 Builder.setInstrAndDebugLoc(MI);
4340 auto NewPhi = Builder.buildInstrNoInsert(TargetOpcode::G_PHI);
4341 NewPhi.addDef(DstReg);
4342 for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) {
4343 if (!MO.isReg()) {
4344 NewPhi.addMBB(MO.getMBB());
4345 continue;
4346 }
4347 auto *NewSrc = OldToNewSrcMap[MRI.getVRegDef(MO.getReg())];
4348 NewPhi.addUse(NewSrc->getOperand(0).getReg());
4349 }
4350 Builder.insertInstr(NewPhi);
4351 ExtMI->eraseFromParent();
4352}
4353
4355 Register &Reg) const {
4356 assert(MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT);
4357 // If we have a constant index, look for a G_BUILD_VECTOR source
4358 // and find the source register that the index maps to.
4359 Register SrcVec = MI.getOperand(1).getReg();
4360 LLT SrcTy = MRI.getType(SrcVec);
4361 if (SrcTy.isScalableVector())
4362 return false;
4363
4364 auto Cst = getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
4365 if (!Cst || Cst->Value.getZExtValue() >= SrcTy.getNumElements())
4366 return false;
4367
4368 unsigned VecIdx = Cst->Value.getZExtValue();
4369
4370 // Check if we have a build_vector or build_vector_trunc with an optional
4371 // trunc in front.
4372 MachineInstr *SrcVecMI;
4373 Register TruncSrc;
4374 if (mi_match(SrcVec, MRI, m_GTrunc(m_Reg(TruncSrc)))) {
4375 if (!mi_match(TruncSrc, MRI, m_MInstr(SrcVecMI)))
4376 return false;
4377 } else if (!mi_match(SrcVec, MRI, m_MInstr(SrcVecMI)))
4378 return false;
4379
4380 if (SrcVecMI->getOpcode() != TargetOpcode::G_BUILD_VECTOR &&
4381 SrcVecMI->getOpcode() != TargetOpcode::G_BUILD_VECTOR_TRUNC)
4382 return false;
4383
4384 EVT Ty(getMVTForLLT(SrcTy));
4385 if (!MRI.hasOneNonDBGUse(SrcVec) &&
4386 !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty))
4387 return false;
4388
4389 Reg = SrcVecMI->getOperand(VecIdx + 1).getReg();
4390 return true;
4391}
4392
4394 Register &Reg) const {
4395 // Check the type of the register, since it may have come from a
4396 // G_BUILD_VECTOR_TRUNC.
4397 LLT ScalarTy = MRI.getType(Reg);
4398 Register DstReg = MI.getOperand(0).getReg();
4399 LLT DstTy = MRI.getType(DstReg);
4400
4401 if (ScalarTy != DstTy) {
4402 assert(ScalarTy.getSizeInBits() > DstTy.getSizeInBits());
4403 Builder.buildTrunc(DstReg, Reg);
4404 MI.eraseFromParent();
4405 return;
4406 }
4408}
4409
4412 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs) const {
4413 assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4414 // This combine tries to find build_vector's which have every source element
4415 // extracted using G_EXTRACT_VECTOR_ELT. This can happen when transforms like
4416 // the masked load scalarization is run late in the pipeline. There's already
4417 // a combine for a similar pattern starting from the extract, but that
4418 // doesn't attempt to do it if there are multiple uses of the build_vector,
4419 // which in this case is true. Starting the combine from the build_vector
4420 // feels more natural than trying to find sibling nodes of extracts.
4421 // E.g.
4422 // %vec(<4 x s32>) = G_BUILD_VECTOR %s1(s32), %s2, %s3, %s4
4423 // %ext1 = G_EXTRACT_VECTOR_ELT %vec, 0
4424 // %ext2 = G_EXTRACT_VECTOR_ELT %vec, 1
4425 // %ext3 = G_EXTRACT_VECTOR_ELT %vec, 2
4426 // %ext4 = G_EXTRACT_VECTOR_ELT %vec, 3
4427 // ==>
4428 // replace ext{1,2,3,4} with %s{1,2,3,4}
4429
4430 Register DstReg = MI.getOperand(0).getReg();
4431 LLT DstTy = MRI.getType(DstReg);
4432 unsigned NumElts = DstTy.getNumElements();
4433
4434 SmallBitVector ExtractedElts(NumElts);
4435 for (MachineInstr &II : MRI.use_nodbg_instructions(DstReg)) {
4436 if (II.getOpcode() != TargetOpcode::G_EXTRACT_VECTOR_ELT)
4437 return false;
4438 auto Cst = getIConstantVRegVal(II.getOperand(2).getReg(), MRI);
4439 if (!Cst)
4440 return false;
4441 unsigned Idx = Cst->getZExtValue();
4442 if (Idx >= NumElts)
4443 return false; // Out of range.
4444 ExtractedElts.set(Idx);
4445 SrcDstPairs.emplace_back(
4446 std::make_pair(MI.getOperand(Idx + 1).getReg(), &II));
4447 }
4448 // Match if every element was extracted.
4449 return ExtractedElts.all();
4450}
4451
4454 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs) const {
4455 assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4456 for (auto &Pair : SrcDstPairs) {
4457 auto *ExtMI = Pair.second;
4458 replaceRegWith(MRI, ExtMI->getOperand(0).getReg(), Pair.first);
4459 ExtMI->eraseFromParent();
4460 }
4461 MI.eraseFromParent();
4462}
4463
4466 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4467 applyBuildFnNoErase(MI, MatchInfo);
4468 MI.eraseFromParent();
4469}
4470
4473 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4474 MatchInfo(Builder);
4475}
4476
4478 bool AllowScalarConstants,
4479 BuildFnTy &MatchInfo) const {
4480 assert(MI.getOpcode() == TargetOpcode::G_OR);
4481
4482 Register Dst = MI.getOperand(0).getReg();
4483 LLT Ty = MRI.getType(Dst);
4484 unsigned BitWidth = Ty.getScalarSizeInBits();
4485
4486 Register ShlSrc, ShlAmt, LShrSrc, LShrAmt, Amt;
4487 unsigned FshOpc = 0;
4488
4489 // Match (or (shl ...), (lshr ...)).
4490 if (!mi_match(Dst, MRI,
4491 // m_GOr() handles the commuted version as well.
4492 m_GOr(m_GShl(m_Reg(ShlSrc), m_Reg(ShlAmt)),
4493 m_GLShr(m_Reg(LShrSrc), m_Reg(LShrAmt)))))
4494 return false;
4495
4496 // Given constants C0 and C1 such that C0 + C1 is bit-width:
4497 // (or (shl x, C0), (lshr y, C1)) -> (fshl x, y, C0) or (fshr x, y, C1)
4498 int64_t CstShlAmt = 0, CstLShrAmt;
4499 if (mi_match(ShlAmt, MRI, m_ICstOrSplat(CstShlAmt)) &&
4500 mi_match(LShrAmt, MRI, m_ICstOrSplat(CstLShrAmt)) &&
4501 CstShlAmt + CstLShrAmt == BitWidth) {
4502 FshOpc = TargetOpcode::G_FSHR;
4503 Amt = LShrAmt;
4504 } else if (mi_match(LShrAmt, MRI,
4506 ShlAmt == Amt) {
4507 // (or (shl x, amt), (lshr y, (sub bw, amt))) -> (fshl x, y, amt)
4508 FshOpc = TargetOpcode::G_FSHL;
4509 } else if (mi_match(ShlAmt, MRI,
4511 LShrAmt == Amt) {
4512 // (or (shl x, (sub bw, amt)), (lshr y, amt)) -> (fshr x, y, amt)
4513 FshOpc = TargetOpcode::G_FSHR;
4514 } else {
4515 return false;
4516 }
4517
4518 LLT AmtTy = MRI.getType(Amt);
4519 if (!isLegalOrBeforeLegalizer({FshOpc, {Ty, AmtTy}}) &&
4520 (!AllowScalarConstants || CstShlAmt == 0 || !Ty.isScalar()))
4521 return false;
4522
4523 MatchInfo = [=](MachineIRBuilder &B) {
4524 B.buildInstr(FshOpc, {Dst}, {ShlSrc, LShrSrc, Amt});
4525 };
4526 return true;
4527}
4528
4529/// Match an FSHL or FSHR that can be combined to a ROTR or ROTL rotate.
4531 unsigned Opc = MI.getOpcode();
4532 assert(Opc == TargetOpcode::G_FSHL || Opc == TargetOpcode::G_FSHR);
4533 Register X = MI.getOperand(1).getReg();
4534 Register Y = MI.getOperand(2).getReg();
4535 if (X != Y)
4536 return false;
4537 unsigned RotateOpc =
4538 Opc == TargetOpcode::G_FSHL ? TargetOpcode::G_ROTL : TargetOpcode::G_ROTR;
4539 return isLegalOrBeforeLegalizer({RotateOpc, {MRI.getType(X), MRI.getType(Y)}});
4540}
4541
4543 unsigned Opc = MI.getOpcode();
4544 assert(Opc == TargetOpcode::G_FSHL || Opc == TargetOpcode::G_FSHR);
4545 bool IsFSHL = Opc == TargetOpcode::G_FSHL;
4546 Observer.changingInstr(MI);
4547 MI.setDesc(Builder.getTII().get(IsFSHL ? TargetOpcode::G_ROTL
4548 : TargetOpcode::G_ROTR));
4549 MI.removeOperand(2);
4550 Observer.changedInstr(MI);
4551}
4552
4553// Fold (rot x, c) -> (rot x, c % BitSize)
4555 assert(MI.getOpcode() == TargetOpcode::G_ROTL ||
4556 MI.getOpcode() == TargetOpcode::G_ROTR);
4557 unsigned Bitsize =
4558 MRI.getType(MI.getOperand(0).getReg()).getScalarSizeInBits();
4559 Register AmtReg = MI.getOperand(2).getReg();
4560 bool OutOfRange = false;
4561 auto MatchOutOfRange = [Bitsize, &OutOfRange](const Constant *C) {
4562 if (auto *CI = dyn_cast<ConstantInt>(C))
4563 OutOfRange |= CI->getValue().uge(Bitsize);
4564 return true;
4565 };
4566 return matchUnaryPredicate(MRI, AmtReg, MatchOutOfRange) && OutOfRange;
4567}
4568
4570 assert(MI.getOpcode() == TargetOpcode::G_ROTL ||
4571 MI.getOpcode() == TargetOpcode::G_ROTR);
4572 unsigned Bitsize =
4573 MRI.getType(MI.getOperand(0).getReg()).getScalarSizeInBits();
4574 Register Amt = MI.getOperand(2).getReg();
4575 LLT AmtTy = MRI.getType(Amt);
4576 auto Bits = Builder.buildConstant(AmtTy, Bitsize);
4577 Amt = Builder.buildURem(AmtTy, MI.getOperand(2).getReg(), Bits).getReg(0);
4578 Observer.changingInstr(MI);
4579 MI.getOperand(2).setReg(Amt);
4580 Observer.changedInstr(MI);
4581}
4582
4584 int64_t &MatchInfo) const {
4585 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
4586 auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
4587
4588 // We want to avoid calling KnownBits on the LHS if possible, as this combine
4589 // has no filter and runs on every G_ICMP instruction. We can avoid calling
4590 // KnownBits on the LHS in two cases:
4591 //
4592 // - The RHS is unknown: Constants are always on RHS. If the RHS is unknown
4593 // we cannot do any transforms so we can safely bail out early.
4594 // - The RHS is zero: we don't need to know the LHS to do unsigned <0 and
4595 // >=0.
4596 auto KnownRHS = VT->getKnownBits(MI.getOperand(3).getReg());
4597 if (KnownRHS.isUnknown())
4598 return false;
4599
4600 std::optional<bool> KnownVal;
4601 if (KnownRHS.isZero()) {
4602 // ? uge 0 -> always true
4603 // ? ult 0 -> always false
4604 if (Pred == CmpInst::ICMP_UGE)
4605 KnownVal = true;
4606 else if (Pred == CmpInst::ICMP_ULT)
4607 KnownVal = false;
4608 }
4609
4610 if (!KnownVal) {
4611 auto KnownLHS = VT->getKnownBits(MI.getOperand(2).getReg());
4612 KnownVal = ICmpInst::compare(KnownLHS, KnownRHS, Pred);
4613 }
4614
4615 if (!KnownVal)
4616 return false;
4617 MatchInfo =
4618 *KnownVal
4620 /*IsVector = */
4621 MRI.getType(MI.getOperand(0).getReg()).isVector(),
4622 /* IsFP = */ false)
4623 : 0;
4624 return true;
4625}
4626
4629 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4630 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
4631 // Given:
4632 //
4633 // %x = G_WHATEVER (... x is known to be 0 or 1 ...)
4634 // %cmp = G_ICMP ne %x, 0
4635 //
4636 // Or:
4637 //
4638 // %x = G_WHATEVER (... x is known to be 0 or 1 ...)
4639 // %cmp = G_ICMP eq %x, 1
4640 //
4641 // We can replace %cmp with %x assuming true is 1 on the target.
4642 auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
4643 if (!CmpInst::isEquality(Pred))
4644 return false;
4645 Register Dst = MI.getOperand(0).getReg();
4646 LLT DstTy = MRI.getType(Dst);
4648 /* IsFP = */ false) != 1)
4649 return false;
4650 int64_t OneOrZero = Pred == CmpInst::ICMP_EQ;
4651 if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICst(OneOrZero)))
4652 return false;
4653 Register LHS = MI.getOperand(2).getReg();
4654 auto KnownLHS = VT->getKnownBits(LHS);
4655 if (KnownLHS.getMinValue() != 0 || KnownLHS.getMaxValue() != 1)
4656 return false;
4657 // Make sure replacing Dst with the LHS is a legal operation.
4658 LLT LHSTy = MRI.getType(LHS);
4659 unsigned LHSSize = LHSTy.getSizeInBits();
4660 unsigned DstSize = DstTy.getSizeInBits();
4661 unsigned Op = TargetOpcode::COPY;
4662 if (DstSize != LHSSize)
4663 Op = DstSize < LHSSize ? TargetOpcode::G_TRUNC : TargetOpcode::G_ZEXT;
4664 if (!isLegalOrBeforeLegalizer({Op, {DstTy, LHSTy}}))
4665 return false;
4666 MatchInfo = [=](MachineIRBuilder &B) { B.buildInstr(Op, {Dst}, {LHS}); };
4667 return true;
4668}
4669
4670// Replace (and (or x, c1), c2) with (and x, c2) iff c1 & c2 == 0
4673 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4674 assert(MI.getOpcode() == TargetOpcode::G_AND);
4675
4676 // Ignore vector types to simplify matching the two constants.
4677 // TODO: do this for vectors and scalars via a demanded bits analysis.
4678 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4679 if (Ty.isVector())
4680 return false;
4681
4682 Register Src;
4683 Register AndMaskReg;
4684 int64_t AndMaskBits;
4685 int64_t OrMaskBits;
4686 if (!mi_match(MI, MRI,
4687 m_GAnd(m_GOr(m_Reg(Src), m_ICst(OrMaskBits)),
4688 m_all_of(m_ICst(AndMaskBits), m_Reg(AndMaskReg)))))
4689 return false;
4690
4691 // Check if OrMask could turn on any bits in Src.
4692 if (AndMaskBits & OrMaskBits)
4693 return false;
4694
4695 MatchInfo = [=, &MI](MachineIRBuilder &B) {
4696 Observer.changingInstr(MI);
4697 // Canonicalize the result to have the constant on the RHS.
4698 if (MI.getOperand(1).getReg() == AndMaskReg)
4699 MI.getOperand(2).setReg(AndMaskReg);
4700 MI.getOperand(1).setReg(Src);
4701 Observer.changedInstr(MI);
4702 };
4703 return true;
4704}
4705
4706/// Form a G_SBFX from a G_SEXT_INREG fed by a right shift.
4709 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4710 assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
4711 Register Dst = MI.getOperand(0).getReg();
4712 Register Src = MI.getOperand(1).getReg();
4713 LLT Ty = MRI.getType(Src);
4715 if (!LI || !LI->isLegalOrCustom({TargetOpcode::G_SBFX, {Ty, ExtractTy}}))
4716 return false;
4717 int64_t Width = MI.getOperand(2).getImm();
4718 Register ShiftSrc;
4719 int64_t ShiftImm;
4720 if (!mi_match(
4721 Src, MRI,
4722 m_OneNonDBGUse(m_any_of(m_GAShr(m_Reg(ShiftSrc), m_ICst(ShiftImm)),
4723 m_GLShr(m_Reg(ShiftSrc), m_ICst(ShiftImm))))))
4724 return false;
4725 if (ShiftImm < 0 || ShiftImm + Width > Ty.getScalarSizeInBits())
4726 return false;
4727
4728 MatchInfo = [=](MachineIRBuilder &B) {
4729 auto Cst1 = B.buildConstant(ExtractTy, ShiftImm);
4730 auto Cst2 = B.buildConstant(ExtractTy, Width);
4731 B.buildSbfx(Dst, ShiftSrc, Cst1, Cst2);
4732 };
4733 return true;
4734}
4735
4736/// Form a G_UBFX from "(a srl b) & mask", where b and mask are constants.
4738 BuildFnTy &MatchInfo) const {
4739 GAnd *And = cast<GAnd>(&MI);
4740 Register Dst = And->getReg(0);
4741 LLT Ty = MRI.getType(Dst);
4743 // Note that isLegalOrBeforeLegalizer is stricter and does not take custom
4744 // into account.
4745 if (LI && !LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
4746 return false;
4747
4748 int64_t AndImm, LSBImm;
4749 Register ShiftSrc;
4750 const unsigned Size = Ty.getScalarSizeInBits();
4751 if (!mi_match(And->getReg(0), MRI,
4752 m_GAnd(m_OneNonDBGUse(m_GLShr(m_Reg(ShiftSrc), m_ICst(LSBImm))),
4753 m_ICst(AndImm))))
4754 return false;
4755
4756 // AndImm is sign-extended to 64 bits by m_ICst; restrict it to the operand
4757 // width so an all-ones mask (a redundant AND) is not misread as a wider mask.
4758 uint64_t MaybeMask = static_cast<uint64_t>(AndImm);
4759 if (Size < 64)
4760 MaybeMask &= maskTrailingOnes<uint64_t>(Size);
4761
4762 // The mask is a mask of the low bits iff imm & (imm+1) == 0.
4763 if (MaybeMask & (MaybeMask + 1))
4764 return false;
4765
4766 // LSB must fit within the register.
4767 if (static_cast<uint64_t>(LSBImm) >= Size)
4768 return false;
4769
4770 uint64_t Width = APInt(Size, MaybeMask).countr_one();
4771 // The extracted field [LSB, LSB+Width) must fit within the register.
4772 // Otherwise this is a redundant AND (e.g. an all-ones mask combined with a
4773 // non-zero shift) that is better handled by other combines, and would form
4774 // an out-of-range bitfield extract.
4775 if (static_cast<uint64_t>(LSBImm) + Width > Size)
4776 return false;
4777
4778 MatchInfo = [=](MachineIRBuilder &B) {
4779 auto WidthCst = B.buildConstant(ExtractTy, Width);
4780 auto LSBCst = B.buildConstant(ExtractTy, LSBImm);
4781 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {ShiftSrc, LSBCst, WidthCst});
4782 };
4783 return true;
4784}
4785
4788 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4789 const unsigned Opcode = MI.getOpcode();
4790 assert(Opcode == TargetOpcode::G_ASHR || Opcode == TargetOpcode::G_LSHR);
4791
4792 const Register Dst = MI.getOperand(0).getReg();
4793
4794 const unsigned ExtrOpcode = Opcode == TargetOpcode::G_ASHR
4795 ? TargetOpcode::G_SBFX
4796 : TargetOpcode::G_UBFX;
4797
4798 // Check if the type we would use for the extract is legal
4799 LLT Ty = MRI.getType(Dst);
4801 if (!LI || !LI->isLegalOrCustom({ExtrOpcode, {Ty, ExtractTy}}))
4802 return false;
4803
4804 Register ShlSrc;
4805 int64_t ShrAmt;
4806 int64_t ShlAmt;
4807 const unsigned Size = Ty.getScalarSizeInBits();
4808
4809 // Try to match shr (shl x, c1), c2
4810 if (!mi_match(Dst, MRI,
4811 m_BinOp(Opcode,
4812 m_OneNonDBGUse(m_GShl(m_Reg(ShlSrc), m_ICst(ShlAmt))),
4813 m_ICst(ShrAmt))))
4814 return false;
4815
4816 // Make sure that the shift sizes can fit a bitfield extract
4817 if (ShlAmt < 0 || ShlAmt > ShrAmt || ShrAmt >= Size)
4818 return false;
4819
4820 // Skip this combine if the G_SEXT_INREG combine could handle it
4821 if (Opcode == TargetOpcode::G_ASHR && ShlAmt == ShrAmt)
4822 return false;
4823
4824 // Calculate start position and width of the extract
4825 const int64_t Pos = ShrAmt - ShlAmt;
4826 const int64_t Width = Size - ShrAmt;
4827
4828 MatchInfo = [=](MachineIRBuilder &B) {
4829 auto WidthCst = B.buildConstant(ExtractTy, Width);
4830 auto PosCst = B.buildConstant(ExtractTy, Pos);
4831 B.buildInstr(ExtrOpcode, {Dst}, {ShlSrc, PosCst, WidthCst});
4832 };
4833 return true;
4834}
4835
4838 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
4839 const unsigned Opcode = MI.getOpcode();
4840 assert(Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_ASHR);
4841
4842 const Register Dst = MI.getOperand(0).getReg();
4843 LLT Ty = MRI.getType(Dst);
4845 if (LI && !LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
4846 return false;
4847
4848 // Try to match shr (and x, c1), c2
4849 Register AndSrc;
4850 int64_t ShrAmt;
4851 int64_t SMask;
4852 if (!mi_match(Dst, MRI,
4853 m_BinOp(Opcode,
4854 m_OneNonDBGUse(m_GAnd(m_Reg(AndSrc), m_ICst(SMask))),
4855 m_ICst(ShrAmt))))
4856 return false;
4857
4858 const unsigned Size = Ty.getScalarSizeInBits();
4859 if (ShrAmt < 0 || ShrAmt >= Size)
4860 return false;
4861
4862 // If the shift subsumes the mask, emit the 0 directly.
4863 if (0 == (SMask >> ShrAmt)) {
4864 MatchInfo = [=](MachineIRBuilder &B) {
4865 B.buildConstant(Dst, 0);
4866 };
4867 return true;
4868 }
4869
4870 // Check that ubfx can do the extraction, with no holes in the mask.
4871 uint64_t UMask = SMask;
4872 UMask |= maskTrailingOnes<uint64_t>(ShrAmt);
4874 if (!isMask_64(UMask))
4875 return false;
4876
4877 // Calculate start position and width of the extract.
4878 const int64_t Pos = ShrAmt;
4879 const int64_t Width = llvm::countr_one(UMask) - ShrAmt;
4880
4881 // It's preferable to keep the shift, rather than form G_SBFX.
4882 // TODO: remove the G_AND via demanded bits analysis.
4883 if (Opcode == TargetOpcode::G_ASHR && Width + ShrAmt == Size)
4884 return false;
4885
4886 MatchInfo = [=](MachineIRBuilder &B) {
4887 auto WidthCst = B.buildConstant(ExtractTy, Width);
4888 auto PosCst = B.buildConstant(ExtractTy, Pos);
4889 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {AndSrc, PosCst, WidthCst});
4890 };
4891 return true;
4892}
4893
4894bool CombinerHelper::reassociationCanBreakAddressingModePattern(
4895 MachineInstr &MI) const {
4896 auto &PtrAdd = cast<GPtrAdd>(MI);
4897
4898 Register Src1Reg = PtrAdd.getBaseReg();
4899 auto *Src1Def = getOpcodeDef<GPtrAdd>(Src1Reg, MRI);
4900 if (!Src1Def)
4901 return false;
4902
4903 Register Src2Reg = PtrAdd.getOffsetReg();
4904
4905 if (MRI.hasOneNonDBGUse(Src1Reg))
4906 return false;
4907
4908 auto C1 = getIConstantVRegVal(Src1Def->getOffsetReg(), MRI);
4909 if (!C1)
4910 return false;
4911 auto C2 = getIConstantVRegVal(Src2Reg, MRI);
4912 if (!C2)
4913 return false;
4914
4915 const APInt &C1APIntVal = *C1;
4916 const APInt &C2APIntVal = *C2;
4917 const int64_t CombinedValue = (C1APIntVal + C2APIntVal).getSExtValue();
4918
4919 for (auto &UseMI : MRI.use_nodbg_instructions(PtrAdd.getReg(0))) {
4920 // This combine may end up running before ptrtoint/inttoptr combines
4921 // manage to eliminate redundant conversions, so try to look through them.
4922 MachineInstr *ConvUseMI = &UseMI;
4923 unsigned ConvUseOpc = ConvUseMI->getOpcode();
4924 while (ConvUseOpc == TargetOpcode::G_INTTOPTR ||
4925 ConvUseOpc == TargetOpcode::G_PTRTOINT) {
4926 Register DefReg = ConvUseMI->getOperand(0).getReg();
4927 if (!MRI.hasOneNonDBGUse(DefReg))
4928 break;
4929 ConvUseMI = &*MRI.use_instr_nodbg_begin(DefReg);
4930 ConvUseOpc = ConvUseMI->getOpcode();
4931 }
4932 auto *LdStMI = dyn_cast<GLoadStore>(ConvUseMI);
4933 if (!LdStMI)
4934 continue;
4935 // Is x[offset2] already not a legal addressing mode? If so then
4936 // reassociating the constants breaks nothing (we test offset2 because
4937 // that's the one we hope to fold into the load or store).
4938 TargetLoweringBase::AddrMode AM;
4939 AM.HasBaseReg = true;
4940 AM.BaseOffs = C2APIntVal.getSExtValue();
4941 unsigned AS = MRI.getType(LdStMI->getPointerReg()).getAddressSpace();
4942 Type *AccessTy = getTypeForLLT(LdStMI->getMMO().getMemoryType(),
4943 PtrAdd.getMF()->getFunction().getContext());
4944 const auto &TLI = *PtrAdd.getMF()->getSubtarget().getTargetLowering();
4945 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
4946 AccessTy, AS))
4947 continue;
4948
4949 // Would x[offset1+offset2] still be a legal addressing mode?
4950 AM.BaseOffs = CombinedValue;
4951 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
4952 AccessTy, AS))
4953 return true;
4954 }
4955
4956 return false;
4957}
4958
4960 MachineInstr *RHS,
4961 BuildFnTy &MatchInfo) const {
4962 // G_PTR_ADD(BASE, G_ADD(X, C)) -> G_PTR_ADD(G_PTR_ADD(BASE, X), C)
4963 Register Src1Reg = MI.getOperand(1).getReg();
4964 if (RHS->getOpcode() != TargetOpcode::G_ADD)
4965 return false;
4966 auto C2 = getIConstantVRegVal(RHS->getOperand(2).getReg(), MRI);
4967 if (!C2)
4968 return false;
4969
4970 // If both additions are nuw, the reassociated additions are also nuw.
4971 // If the original G_PTR_ADD is additionally nusw, X and C are both not
4972 // negative, so BASE+X is between BASE and BASE+(X+C). The new G_PTR_ADDs are
4973 // therefore also nusw.
4974 // If the original G_PTR_ADD is additionally inbounds (which implies nusw),
4975 // the new G_PTR_ADDs are then also inbounds.
4976 unsigned PtrAddFlags = MI.getFlags();
4977 unsigned AddFlags = RHS->getFlags();
4978 bool IsNoUWrap = PtrAddFlags & AddFlags & MachineInstr::MIFlag::NoUWrap;
4979 bool IsNoUSWrap = IsNoUWrap && (PtrAddFlags & MachineInstr::MIFlag::NoUSWrap);
4980 bool IsInBounds = IsNoUWrap && (PtrAddFlags & MachineInstr::MIFlag::InBounds);
4981 unsigned Flags = 0;
4982 if (IsNoUWrap)
4984 if (IsNoUSWrap)
4986 if (IsInBounds)
4988
4989 MatchInfo = [=, &MI](MachineIRBuilder &B) {
4990 LLT PtrTy = MRI.getType(MI.getOperand(0).getReg());
4991
4992 auto NewBase =
4993 Builder.buildPtrAdd(PtrTy, Src1Reg, RHS->getOperand(1).getReg(), Flags);
4994 Observer.changingInstr(MI);
4995 MI.getOperand(1).setReg(NewBase.getReg(0));
4996 MI.getOperand(2).setReg(RHS->getOperand(2).getReg());
4997 MI.setFlags(Flags);
4998 Observer.changedInstr(MI);
4999 };
5000 return !reassociationCanBreakAddressingModePattern(MI);
5001}
5002
5004 MachineInstr *LHS,
5005 MachineInstr *RHS,
5006 BuildFnTy &MatchInfo) const {
5007 // G_PTR_ADD (G_PTR_ADD X, C), Y) -> (G_PTR_ADD (G_PTR_ADD(X, Y), C)
5008 // if and only if (G_PTR_ADD X, C) has one use.
5009 Register LHSBase;
5010 std::optional<ValueAndVReg> LHSCstOff;
5011 if (!mi_match(MI.getBaseReg(), MRI,
5012 m_OneNonDBGUse(m_GPtrAdd(m_Reg(LHSBase), m_GCst(LHSCstOff)))))
5013 return false;
5014
5015 auto *LHSPtrAdd = cast<GPtrAdd>(LHS);
5016
5017 // Reassociating nuw additions preserves nuw. If both original G_PTR_ADDs are
5018 // nuw and inbounds (which implies nusw), the offsets are both non-negative,
5019 // so the new G_PTR_ADDs are also inbounds.
5020 unsigned PtrAddFlags = MI.getFlags();
5021 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
5022 bool IsNoUWrap = PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::NoUWrap;
5023 bool IsNoUSWrap = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
5025 bool IsInBounds = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
5027 unsigned Flags = 0;
5028 if (IsNoUWrap)
5030 if (IsNoUSWrap)
5032 if (IsInBounds)
5034
5035 MatchInfo = [=, &MI](MachineIRBuilder &B) {
5036 // When we change LHSPtrAdd's offset register we might cause it to use a reg
5037 // before its def. Sink the instruction so the outer PTR_ADD to ensure this
5038 // doesn't happen.
5039 LHSPtrAdd->moveBefore(&MI);
5040 Register RHSReg = MI.getOffsetReg();
5041 // set VReg will cause type mismatch if it comes from extend/trunc
5042 auto NewCst = B.buildConstant(MRI.getType(RHSReg), LHSCstOff->Value);
5043 Observer.changingInstr(MI);
5044 MI.getOperand(2).setReg(NewCst.getReg(0));
5045 MI.setFlags(Flags);
5046 Observer.changedInstr(MI);
5047 Observer.changingInstr(*LHSPtrAdd);
5048 LHSPtrAdd->getOperand(2).setReg(RHSReg);
5049 LHSPtrAdd->setFlags(Flags);
5050 Observer.changedInstr(*LHSPtrAdd);
5051 };
5052 return !reassociationCanBreakAddressingModePattern(MI);
5053}
5054
5056 GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS,
5057 BuildFnTy &MatchInfo) const {
5058 // G_PTR_ADD(G_PTR_ADD(BASE, C1), C2) -> G_PTR_ADD(BASE, C1+C2)
5059 auto *LHSPtrAdd = dyn_cast<GPtrAdd>(LHS);
5060 if (!LHSPtrAdd)
5061 return false;
5062
5063 Register Src2Reg = MI.getOperand(2).getReg();
5064 Register LHSSrc1 = LHSPtrAdd->getBaseReg();
5065 Register LHSSrc2 = LHSPtrAdd->getOffsetReg();
5066 auto C1 = getIConstantVRegVal(LHSSrc2, MRI);
5067 if (!C1)
5068 return false;
5069 auto C2 = getIConstantVRegVal(Src2Reg, MRI);
5070 if (!C2)
5071 return false;
5072
5073 // Reassociating nuw additions preserves nuw. If both original G_PTR_ADDs are
5074 // inbounds, reaching the same result in one G_PTR_ADD is also inbounds.
5075 // The nusw constraints are satisfied because imm1+imm2 cannot exceed the
5076 // largest signed integer that fits into the index type, which is the maximum
5077 // size of allocated objects according to the IR Language Reference.
5078 unsigned PtrAddFlags = MI.getFlags();
5079 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
5080 bool IsNoUWrap = PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::NoUWrap;
5081 bool IsInBounds =
5082 PtrAddFlags & LHSPtrAddFlags & MachineInstr::MIFlag::InBounds;
5083 unsigned Flags = 0;
5084 if (IsNoUWrap)
5086 if (IsInBounds) {
5089 }
5090
5091 MatchInfo = [=, &MI](MachineIRBuilder &B) {
5092 auto NewCst = B.buildConstant(MRI.getType(Src2Reg), *C1 + *C2);
5093 Observer.changingInstr(MI);
5094 MI.getOperand(1).setReg(LHSSrc1);
5095 MI.getOperand(2).setReg(NewCst.getReg(0));
5096 MI.setFlags(Flags);
5097 Observer.changedInstr(MI);
5098 };
5099 return !reassociationCanBreakAddressingModePattern(MI);
5100}
5101
5103 BuildFnTy &MatchInfo) const {
5104 auto &PtrAdd = cast<GPtrAdd>(MI);
5105 // We're trying to match a few pointer computation patterns here for
5106 // re-association opportunities.
5107 // 1) Isolating a constant operand to be on the RHS, e.g.:
5108 // G_PTR_ADD(BASE, G_ADD(X, C)) -> G_PTR_ADD(G_PTR_ADD(BASE, X), C)
5109 //
5110 // 2) Folding two constants in each sub-tree as long as such folding
5111 // doesn't break a legal addressing mode.
5112 // G_PTR_ADD(G_PTR_ADD(BASE, C1), C2) -> G_PTR_ADD(BASE, C1+C2)
5113 //
5114 // 3) Move a constant from the LHS of an inner op to the RHS of the outer.
5115 // G_PTR_ADD (G_PTR_ADD X, C), Y) -> G_PTR_ADD (G_PTR_ADD(X, Y), C)
5116 // iif (G_PTR_ADD X, C) has one use.
5117 MachineInstr *LHS, *RHS;
5118 if (!mi_match(PtrAdd.getBaseReg(), MRI, m_MInstr(LHS)) ||
5119 !mi_match(PtrAdd.getOffsetReg(), MRI, m_MInstr(RHS)))
5120 return false;
5121
5122 // Try to match example 2.
5123 if (matchReassocFoldConstantsInSubTree(PtrAdd, LHS, RHS, MatchInfo))
5124 return true;
5125
5126 // Try to match example 3.
5127 if (matchReassocConstantInnerLHS(PtrAdd, LHS, RHS, MatchInfo))
5128 return true;
5129
5130 // Try to match example 1.
5131 if (matchReassocConstantInnerRHS(PtrAdd, RHS, MatchInfo))
5132 return true;
5133
5134 return false;
5135}
5137 Register OpLHS, Register OpRHS,
5138 BuildFnTy &MatchInfo) const {
5139 LLT OpRHSTy = MRI.getType(OpRHS);
5140 MachineInstr *OpLHSDef;
5141 if (!mi_match(OpLHS, MRI, m_MInstr(OpLHSDef)) || OpLHSDef->getOpcode() != Opc)
5142 return false;
5143
5144 Register OpLHSLHS = OpLHSDef->getOperand(1).getReg();
5145 Register OpLHSRHS = OpLHSDef->getOperand(2).getReg();
5146
5147 // If the inner op is (X op C), pull the constant out so it can be folded with
5148 // other constants in the expression tree. Folding is not guaranteed so we
5149 // might have (C1 op C2). In that case do not pull a constant out because it
5150 // won't help and can lead to infinite loops.
5151 if (isConstantOrConstantSplatVector(OpLHSRHS, MRI) &&
5154 // (Opc (Opc X, C1), C2) -> (Opc X, (Opc C1, C2))
5155 MatchInfo = [=](MachineIRBuilder &B) {
5156 auto NewCst = B.buildInstr(Opc, {OpRHSTy}, {OpLHSRHS, OpRHS});
5157 B.buildInstr(Opc, {DstReg}, {OpLHSLHS, NewCst});
5158 };
5159 return true;
5160 }
5161 if (getTargetLowering().isReassocProfitable(MRI, OpLHS, OpRHS)) {
5162 // Reassociate: (op (op x, c1), y) -> (op (op x, y), c1)
5163 // iff (op x, c1) has one use
5164 MatchInfo = [=](MachineIRBuilder &B) {
5165 auto NewLHSLHS = B.buildInstr(Opc, {OpRHSTy}, {OpLHSLHS, OpRHS});
5166 B.buildInstr(Opc, {DstReg}, {NewLHSLHS, OpLHSRHS});
5167 };
5168 return true;
5169 }
5170 }
5171
5172 return false;
5173}
5174
5176 BuildFnTy &MatchInfo) const {
5177 // We don't check if the reassociation will break a legal addressing mode
5178 // here since pointer arithmetic is handled by G_PTR_ADD.
5179 unsigned Opc = MI.getOpcode();
5180 Register DstReg = MI.getOperand(0).getReg();
5181 Register LHSReg = MI.getOperand(1).getReg();
5182 Register RHSReg = MI.getOperand(2).getReg();
5183
5184 if (tryReassocBinOp(Opc, DstReg, LHSReg, RHSReg, MatchInfo))
5185 return true;
5186 if (tryReassocBinOp(Opc, DstReg, RHSReg, LHSReg, MatchInfo))
5187 return true;
5188 return false;
5189}
5190
5192 APInt &MatchInfo) const {
5193 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
5194 Register SrcOp = MI.getOperand(1).getReg();
5195
5196 if (auto MaybeCst = ConstantFoldCastOp(MI.getOpcode(), DstTy, SrcOp, MRI)) {
5197 MatchInfo = *MaybeCst;
5198 return true;
5199 }
5200
5201 return false;
5202}
5203
5205 BuildFnTy &MatchInfo) const {
5206 Register Dst = MI.getOperand(0).getReg();
5207 auto Csts = ConstantFoldUnaryIntOp(MI.getOpcode(), MRI.getType(Dst),
5208 MI.getOperand(1).getReg(), MRI);
5209 if (Csts.empty())
5210 return false;
5211
5212 MatchInfo = [Dst, Csts = std::move(Csts)](MachineIRBuilder &B) {
5213 if (Csts.size() == 1)
5214 B.buildConstant(Dst, Csts[0]);
5215 else
5216 B.buildBuildVectorConstant(Dst, Csts);
5217 };
5218 return true;
5219}
5220
5222 APInt &MatchInfo) const {
5223 Register Op1 = MI.getOperand(1).getReg();
5224 Register Op2 = MI.getOperand(2).getReg();
5225 auto MaybeCst = ConstantFoldBinOp(MI.getOpcode(), Op1, Op2, MRI);
5226 if (!MaybeCst)
5227 return false;
5228 MatchInfo = *MaybeCst;
5229 return true;
5230}
5231
5233 ConstantFP *&MatchInfo) const {
5234 Register Op1 = MI.getOperand(1).getReg();
5235 Register Op2 = MI.getOperand(2).getReg();
5236 auto MaybeCst = ConstantFoldFPBinOp(MI.getOpcode(), Op1, Op2, MRI);
5237 if (!MaybeCst)
5238 return false;
5239 MatchInfo =
5240 ConstantFP::get(MI.getMF()->getFunction().getContext(), *MaybeCst);
5241 return true;
5242}
5243
5245 ConstantFP *&MatchInfo) const {
5246 assert(MI.getOpcode() == TargetOpcode::G_FMA ||
5247 MI.getOpcode() == TargetOpcode::G_FMAD);
5248 auto [_, Op1, Op2, Op3] = MI.getFirst4Regs();
5249
5250 const ConstantFP *Op3Cst = getConstantFPVRegVal(Op3, MRI);
5251 if (!Op3Cst)
5252 return false;
5253
5254 const ConstantFP *Op2Cst = getConstantFPVRegVal(Op2, MRI);
5255 if (!Op2Cst)
5256 return false;
5257
5258 const ConstantFP *Op1Cst = getConstantFPVRegVal(Op1, MRI);
5259 if (!Op1Cst)
5260 return false;
5261
5262 APFloat Op1F = Op1Cst->getValueAPF();
5263 Op1F.fusedMultiplyAdd(Op2Cst->getValueAPF(), Op3Cst->getValueAPF(),
5265 MatchInfo = ConstantFP::get(MI.getMF()->getFunction().getContext(), Op1F);
5266 return true;
5267}
5268
5271 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
5272 // Look for a binop feeding into an AND with a mask:
5273 //
5274 // %add = G_ADD %lhs, %rhs
5275 // %and = G_AND %add, 000...11111111
5276 //
5277 // Check if it's possible to perform the binop at a narrower width and zext
5278 // back to the original width like so:
5279 //
5280 // %narrow_lhs = G_TRUNC %lhs
5281 // %narrow_rhs = G_TRUNC %rhs
5282 // %narrow_add = G_ADD %narrow_lhs, %narrow_rhs
5283 // %new_add = G_ZEXT %narrow_add
5284 // %and = G_AND %new_add, 000...11111111
5285 //
5286 // This can allow later combines to eliminate the G_AND if it turns out
5287 // that the mask is irrelevant.
5288 assert(MI.getOpcode() == TargetOpcode::G_AND);
5289 Register Dst = MI.getOperand(0).getReg();
5290 Register AndLHS = MI.getOperand(1).getReg();
5291 Register AndRHS = MI.getOperand(2).getReg();
5292 LLT WideTy = MRI.getType(Dst);
5293
5294 // If the potential binop has more than one use, then it's possible that one
5295 // of those uses will need its full width.
5296 if (!WideTy.isScalar() || !MRI.hasOneNonDBGUse(AndLHS))
5297 return false;
5298
5299 // Check if the LHS feeding the AND is impacted by the high bits that we're
5300 // masking out.
5301 //
5302 // e.g. for 64-bit x, y:
5303 //
5304 // add_64(x, y) & 65535 == zext(add_16(trunc(x), trunc(y))) & 65535
5305 MachineInstr *LHSInst = getDefIgnoringCopies(AndLHS, MRI);
5306 if (!LHSInst)
5307 return false;
5308 unsigned LHSOpc = LHSInst->getOpcode();
5309 switch (LHSOpc) {
5310 default:
5311 return false;
5312 case TargetOpcode::G_ADD:
5313 case TargetOpcode::G_SUB:
5314 case TargetOpcode::G_MUL:
5315 case TargetOpcode::G_AND:
5316 case TargetOpcode::G_OR:
5317 case TargetOpcode::G_XOR:
5318 break;
5319 }
5320
5321 // Find the mask on the RHS.
5322 auto Cst = getIConstantVRegValWithLookThrough(AndRHS, MRI);
5323 if (!Cst)
5324 return false;
5325 auto Mask = Cst->Value;
5326 if (!Mask.isMask())
5327 return false;
5328
5329 // No point in combining if there's nothing to truncate.
5330 unsigned NarrowWidth = Mask.countr_one();
5331 if (NarrowWidth == WideTy.getSizeInBits())
5332 return false;
5333 LLT NarrowTy = LLT::integer(NarrowWidth);
5334
5335 // Check if adding the zext + truncates could be harmful.
5336 auto &MF = *MI.getMF();
5337 const auto &TLI = getTargetLowering();
5338 LLVMContext &Ctx = MF.getFunction().getContext();
5339 if (!TLI.isTruncateFree(WideTy, NarrowTy, Ctx) ||
5340 !TLI.isZExtFree(NarrowTy, WideTy, Ctx))
5341 return false;
5342 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {NarrowTy, WideTy}}) ||
5343 !isLegalOrBeforeLegalizer({TargetOpcode::G_ZEXT, {WideTy, NarrowTy}}))
5344 return false;
5345 Register BinOpLHS = LHSInst->getOperand(1).getReg();
5346 Register BinOpRHS = LHSInst->getOperand(2).getReg();
5347 MatchInfo = [=, &MI](MachineIRBuilder &B) {
5348 auto NarrowLHS = Builder.buildTrunc(NarrowTy, BinOpLHS);
5349 auto NarrowRHS = Builder.buildTrunc(NarrowTy, BinOpRHS);
5350 auto NarrowBinOp =
5351 Builder.buildInstr(LHSOpc, {NarrowTy}, {NarrowLHS, NarrowRHS});
5352 auto Ext = Builder.buildZExt(WideTy, NarrowBinOp);
5353 Observer.changingInstr(MI);
5354 MI.getOperand(1).setReg(Ext.getReg(0));
5355 Observer.changedInstr(MI);
5356 };
5357 return true;
5358}
5359
5361 BuildFnTy &MatchInfo) const {
5362 unsigned Opc = MI.getOpcode();
5363 assert(Opc == TargetOpcode::G_UMULO || Opc == TargetOpcode::G_SMULO);
5364
5365 if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICstOrSplat(2)))
5366 return false;
5367
5368 MatchInfo = [=, &MI](MachineIRBuilder &B) {
5369 Observer.changingInstr(MI);
5370 unsigned NewOpc = Opc == TargetOpcode::G_UMULO ? TargetOpcode::G_UADDO
5371 : TargetOpcode::G_SADDO;
5372 MI.setDesc(Builder.getTII().get(NewOpc));
5373 MI.getOperand(3).setReg(MI.getOperand(2).getReg());
5374 Observer.changedInstr(MI);
5375 };
5376 return true;
5377}
5378
5380 BuildFnTy &MatchInfo) const {
5381 // (G_*MULO x, 0) -> 0 + no carry out
5382 assert(MI.getOpcode() == TargetOpcode::G_UMULO ||
5383 MI.getOpcode() == TargetOpcode::G_SMULO);
5384 if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICstOrSplat(0)))
5385 return false;
5386 Register Dst = MI.getOperand(0).getReg();
5387 Register Carry = MI.getOperand(1).getReg();
5388 if (!isConstantLegalOrBeforeLegalizer(MRI.getType(Dst)) ||
5389 !isConstantLegalOrBeforeLegalizer(MRI.getType(Carry)))
5390 return false;
5391 MatchInfo = [=](MachineIRBuilder &B) {
5392 B.buildConstant(Dst, 0);
5393 B.buildConstant(Carry, 0);
5394 };
5395 return true;
5396}
5397
5399 BuildFnTy &MatchInfo) const {
5400 // (G_*ADDE x, y, 0) -> (G_*ADDO x, y)
5401 // (G_*SUBE x, y, 0) -> (G_*SUBO x, y)
5402 assert(MI.getOpcode() == TargetOpcode::G_UADDE ||
5403 MI.getOpcode() == TargetOpcode::G_SADDE ||
5404 MI.getOpcode() == TargetOpcode::G_USUBE ||
5405 MI.getOpcode() == TargetOpcode::G_SSUBE);
5406 if (!mi_match(MI.getOperand(4).getReg(), MRI, m_SpecificICstOrSplat(0)))
5407 return false;
5408 MatchInfo = [&](MachineIRBuilder &B) {
5409 unsigned NewOpcode;
5410 switch (MI.getOpcode()) {
5411 case TargetOpcode::G_UADDE:
5412 NewOpcode = TargetOpcode::G_UADDO;
5413 break;
5414 case TargetOpcode::G_SADDE:
5415 NewOpcode = TargetOpcode::G_SADDO;
5416 break;
5417 case TargetOpcode::G_USUBE:
5418 NewOpcode = TargetOpcode::G_USUBO;
5419 break;
5420 case TargetOpcode::G_SSUBE:
5421 NewOpcode = TargetOpcode::G_SSUBO;
5422 break;
5423 }
5424 Observer.changingInstr(MI);
5425 MI.setDesc(B.getTII().get(NewOpcode));
5426 MI.removeOperand(4);
5427 Observer.changedInstr(MI);
5428 };
5429 return true;
5430}
5431
5433 BuildFnTy &MatchInfo) const {
5434 assert(MI.getOpcode() == TargetOpcode::G_SUB);
5435 Register Dst = MI.getOperand(0).getReg();
5436 // (x + y) - z -> x (if y == z)
5437 // (x + y) - z -> y (if x == z)
5438 Register X, Y, Z;
5439 if (mi_match(Dst, MRI, m_GSub(m_GAdd(m_Reg(X), m_Reg(Y)), m_Reg(Z)))) {
5440 Register ReplaceReg;
5441 int64_t CstX, CstY;
5442 if (Y == Z || (mi_match(Y, MRI, m_ICstOrSplat(CstY)) &&
5444 ReplaceReg = X;
5445 else if (X == Z || (mi_match(X, MRI, m_ICstOrSplat(CstX)) &&
5447 ReplaceReg = Y;
5448 if (ReplaceReg) {
5449 MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, ReplaceReg); };
5450 return true;
5451 }
5452 }
5453
5454 // x - (y + z) -> 0 - y (if x == z)
5455 // x - (y + z) -> 0 - z (if x == y)
5456 if (mi_match(Dst, MRI, m_GSub(m_Reg(X), m_GAdd(m_Reg(Y), m_Reg(Z))))) {
5457 Register ReplaceReg;
5458 int64_t CstX;
5459 if (X == Z || (mi_match(X, MRI, m_ICstOrSplat(CstX)) &&
5461 ReplaceReg = Y;
5462 else if (X == Y || (mi_match(X, MRI, m_ICstOrSplat(CstX)) &&
5464 ReplaceReg = Z;
5465 if (ReplaceReg) {
5466 MatchInfo = [=](MachineIRBuilder &B) {
5467 auto Zero = B.buildConstant(MRI.getType(Dst), 0);
5468 B.buildSub(Dst, Zero, ReplaceReg);
5469 };
5470 return true;
5471 }
5472 }
5473 return false;
5474}
5475
5477 unsigned Opcode = MI.getOpcode();
5478 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5479 auto &UDivorRem = cast<GenericMachineInstr>(MI);
5480 Register Dst = UDivorRem.getReg(0);
5481 Register LHS = UDivorRem.getReg(1);
5482 Register RHS = UDivorRem.getReg(2);
5483 LLT Ty = MRI.getType(Dst);
5484 LLT ScalarTy = Ty.getScalarType();
5485 const unsigned EltBits = ScalarTy.getScalarSizeInBits();
5487 LLT ScalarShiftAmtTy = ShiftAmtTy.getScalarType();
5488
5489 auto &MIB = Builder;
5490
5491 bool UseSRL = false;
5492 SmallVector<Register, 16> Shifts, Factors;
5493 auto *RHSDefInstr = cast<GenericMachineInstr>(getDefIgnoringCopies(RHS, MRI));
5494 bool IsSplat = getIConstantSplatVal(*RHSDefInstr, MRI).has_value();
5495
5496 auto BuildExactUDIVPattern = [&](const Constant *C) {
5497 // Don't recompute inverses for each splat element.
5498 if (IsSplat && !Factors.empty()) {
5499 Shifts.push_back(Shifts[0]);
5500 Factors.push_back(Factors[0]);
5501 return true;
5502 }
5503
5504 auto *CI = cast<ConstantInt>(C);
5505 APInt Divisor = CI->getValue();
5506 unsigned Shift = Divisor.countr_zero();
5507 if (Shift) {
5508 Divisor.lshrInPlace(Shift);
5509 UseSRL = true;
5510 }
5511
5512 // Calculate the multiplicative inverse modulo BW.
5513 APInt Factor = Divisor.multiplicativeInverse();
5514 Shifts.push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
5515 Factors.push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
5516 return true;
5517 };
5518
5519 if (MI.getFlag(MachineInstr::MIFlag::IsExact)) {
5520 // Collect all magic values from the build vector.
5521 if (!matchUnaryPredicate(MRI, RHS, BuildExactUDIVPattern))
5522 llvm_unreachable("Expected unary predicate match to succeed");
5523
5524 Register Shift, Factor;
5525 if (Ty.isVector()) {
5526 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
5527 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
5528 } else {
5529 Shift = Shifts[0];
5530 Factor = Factors[0];
5531 }
5532
5533 Register Res = LHS;
5534
5535 if (UseSRL)
5536 Res = MIB.buildLShr(Ty, Res, Shift, MachineInstr::IsExact).getReg(0);
5537
5538 return MIB.buildMul(Ty, Res, Factor);
5539 }
5540
5541 unsigned KnownLeadingZeros =
5542 VT ? VT->getKnownBits(LHS).countMinLeadingZeros() : 0;
5543
5544 bool UseNPQ = false;
5545 SmallVector<Register, 16> PreShifts, PostShifts, MagicFactors, NPQFactors;
5546 auto BuildUDIVPattern = [&](const Constant *C) {
5547 auto *CI = cast<ConstantInt>(C);
5548 const APInt &Divisor = CI->getValue();
5549
5550 bool SelNPQ = false;
5551 APInt Magic(Divisor.getBitWidth(), 0);
5552 unsigned PreShift = 0, PostShift = 0;
5553
5554 // Magic algorithm doesn't work for division by 1. We need to emit a select
5555 // at the end.
5556 // TODO: Use undef values for divisor of 1.
5557 if (!Divisor.isOne()) {
5558
5559 // UnsignedDivisionByConstantInfo doesn't work correctly if leading zeros
5560 // in the dividend exceeds the leading zeros for the divisor.
5563 Divisor, std::min(KnownLeadingZeros, Divisor.countl_zero()));
5564
5565 Magic = std::move(magics.Magic);
5566
5567 assert(magics.PreShift < Divisor.getBitWidth() &&
5568 "We shouldn't generate an undefined shift!");
5569 assert(magics.PostShift < Divisor.getBitWidth() &&
5570 "We shouldn't generate an undefined shift!");
5571 assert((!magics.IsAdd || magics.PreShift == 0) && "Unexpected pre-shift");
5572 PreShift = magics.PreShift;
5573 PostShift = magics.PostShift;
5574 SelNPQ = magics.IsAdd;
5575 }
5576
5577 PreShifts.push_back(
5578 MIB.buildConstant(ScalarShiftAmtTy, PreShift).getReg(0));
5579 MagicFactors.push_back(MIB.buildConstant(ScalarTy, Magic).getReg(0));
5580 NPQFactors.push_back(
5581 MIB.buildConstant(ScalarTy,
5582 SelNPQ ? APInt::getOneBitSet(EltBits, EltBits - 1)
5583 : APInt::getZero(EltBits))
5584 .getReg(0));
5585 PostShifts.push_back(
5586 MIB.buildConstant(ScalarShiftAmtTy, PostShift).getReg(0));
5587 UseNPQ |= SelNPQ;
5588 return true;
5589 };
5590
5591 // Collect the shifts/magic values from each element.
5592 bool Matched = matchUnaryPredicate(MRI, RHS, BuildUDIVPattern);
5593 (void)Matched;
5594 assert(Matched && "Expected unary predicate match to succeed");
5595
5596 Register PreShift, PostShift, MagicFactor, NPQFactor;
5597 auto *RHSDef = getOpcodeDef<GBuildVector>(RHS, MRI);
5598 if (RHSDef) {
5599 PreShift = MIB.buildBuildVector(ShiftAmtTy, PreShifts).getReg(0);
5600 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
5601 NPQFactor = MIB.buildBuildVector(Ty, NPQFactors).getReg(0);
5602 PostShift = MIB.buildBuildVector(ShiftAmtTy, PostShifts).getReg(0);
5603 } else {
5604 assert(MRI.getType(RHS).isScalar() &&
5605 "Non-build_vector operation should have been a scalar");
5606 PreShift = PreShifts[0];
5607 MagicFactor = MagicFactors[0];
5608 PostShift = PostShifts[0];
5609 }
5610
5611 Register Q = LHS;
5612 Q = MIB.buildLShr(Ty, Q, PreShift).getReg(0);
5613
5614 // Multiply the numerator (operand 0) by the magic value.
5615 Q = MIB.buildUMulH(Ty, Q, MagicFactor).getReg(0);
5616
5617 if (UseNPQ) {
5618 Register NPQ = MIB.buildSub(Ty, LHS, Q).getReg(0);
5619
5620 // For vectors we might have a mix of non-NPQ/NPQ paths, so use
5621 // G_UMULH to act as a SRL-by-1 for NPQ, else multiply by zero.
5622 if (Ty.isVector())
5623 NPQ = MIB.buildUMulH(Ty, NPQ, NPQFactor).getReg(0);
5624 else
5625 NPQ = MIB.buildLShr(Ty, NPQ, MIB.buildConstant(ShiftAmtTy, 1)).getReg(0);
5626
5627 Q = MIB.buildAdd(Ty, NPQ, Q).getReg(0);
5628 }
5629
5630 Q = MIB.buildLShr(Ty, Q, PostShift).getReg(0);
5631 auto One = MIB.buildConstant(Ty, 1);
5632 auto IsOne = MIB.buildICmp(
5634 Ty.isScalar() ? LLT::integer(1) : Ty.changeElementType(LLT::integer(1)),
5635 RHS, One);
5636 auto ret = MIB.buildSelect(Ty, IsOne, LHS, Q);
5637
5638 if (Opcode == TargetOpcode::G_UREM) {
5639 auto Prod = MIB.buildMul(Ty, ret, RHS);
5640 return MIB.buildSub(Ty, LHS, Prod);
5641 }
5642 return ret;
5643}
5644
5646 unsigned Opcode = MI.getOpcode();
5647 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5648 Register Dst = MI.getOperand(0).getReg();
5649 Register RHS = MI.getOperand(2).getReg();
5650 LLT DstTy = MRI.getType(Dst);
5651
5652 auto &MF = *MI.getMF();
5653 AttributeList Attr = MF.getFunction().getAttributes();
5654 const auto &TLI = getTargetLowering();
5655 LLVMContext &Ctx = MF.getFunction().getContext();
5656 if (DstTy.getScalarSizeInBits() == 1 ||
5657 TLI.isIntDivCheap(getApproximateEVTForLLT(DstTy, Ctx), Attr))
5658 return false;
5659
5660 // Don't do this for minsize because the instruction sequence is usually
5661 // larger.
5662 if (MF.getFunction().hasMinSize())
5663 return false;
5664
5665 if (Opcode == TargetOpcode::G_UDIV &&
5667 return matchUnaryPredicate(
5668 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5669 }
5670
5671 MachineInstr *RHSDef;
5672 if (!mi_match(RHS, MRI, m_MInstr(RHSDef)) ||
5674 return false;
5675
5676 // Don't do this if the types are not going to be legal.
5677 if (LI) {
5678 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_MUL, {DstTy, DstTy}}))
5679 return false;
5680 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMULH, {DstTy}}))
5681 return false;
5683 {TargetOpcode::G_ICMP,
5684 {DstTy.isVector() ? DstTy.changeElementSize(1) : LLT::scalar(1),
5685 DstTy}}))
5686 return false;
5687 if (Opcode == TargetOpcode::G_UREM &&
5688 !isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy, DstTy}}))
5689 return false;
5690 }
5691
5692 return matchUnaryPredicate(
5693 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5694}
5695
5697 auto *NewMI = buildUDivOrURemUsingMul(MI);
5698 replaceSingleDefInstWithReg(MI, NewMI->getOperand(0).getReg());
5699}
5700
5702 unsigned Opcode = MI.getOpcode();
5703 assert(Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_SREM);
5704 Register Dst = MI.getOperand(0).getReg();
5705 Register RHS = MI.getOperand(2).getReg();
5706 LLT DstTy = MRI.getType(Dst);
5707 auto SizeInBits = DstTy.getScalarSizeInBits();
5708 LLT WideTy = DstTy.changeElementSize(SizeInBits * 2);
5709
5710 auto &MF = *MI.getMF();
5711 AttributeList Attr = MF.getFunction().getAttributes();
5712 const auto &TLI = getTargetLowering();
5713 LLVMContext &Ctx = MF.getFunction().getContext();
5714 if (DstTy.getScalarSizeInBits() < 3 ||
5715 TLI.isIntDivCheap(getApproximateEVTForLLT(DstTy, Ctx), Attr))
5716 return false;
5717
5718 // Don't do this for minsize because the instruction sequence is usually
5719 // larger.
5720 if (MF.getFunction().hasMinSize())
5721 return false;
5722
5723 // If the sdiv has an 'exact' flag we can use a simpler lowering.
5724 if (Opcode == TargetOpcode::G_SDIV &&
5726 return matchUnaryPredicate(
5727 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5728 }
5729
5730 MachineInstr *RHSDef;
5731 if (!mi_match(RHS, MRI, m_MInstr(RHSDef)) ||
5733 return false;
5734
5735 // Don't do this if the types are not going to be legal.
5736 if (LI) {
5737 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_MUL, {DstTy, DstTy}}))
5738 return false;
5739 if (!isLegal({TargetOpcode::G_SMULH, {DstTy}}) &&
5740 !isLegalOrHasWidenScalar({TargetOpcode::G_MUL, {WideTy, WideTy}}))
5741 return false;
5742 if (Opcode == TargetOpcode::G_SREM &&
5743 !isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy, DstTy}}))
5744 return false;
5745 }
5746
5747 return matchUnaryPredicate(
5748 MRI, RHS, [](const Constant *C) { return C && !C->isNullValue(); });
5749}
5750
5752 auto *NewMI = buildSDivOrSRemUsingMul(MI);
5753 replaceSingleDefInstWithReg(MI, NewMI->getOperand(0).getReg());
5754}
5755
5757 unsigned Opcode = MI.getOpcode();
5758 assert(MI.getOpcode() == TargetOpcode::G_SDIV ||
5759 Opcode == TargetOpcode::G_SREM);
5760 auto &SDivorRem = cast<GenericMachineInstr>(MI);
5761 Register Dst = SDivorRem.getReg(0);
5762 Register LHS = SDivorRem.getReg(1);
5763 Register RHS = SDivorRem.getReg(2);
5764 LLT Ty = MRI.getType(Dst);
5765 LLT ScalarTy = Ty.getScalarType();
5766 const unsigned EltBits = ScalarTy.getScalarSizeInBits();
5768 LLT ScalarShiftAmtTy = ShiftAmtTy.getScalarType();
5769 auto &MIB = Builder;
5770
5771 bool UseSRA = false;
5772 SmallVector<Register, 16> ExactShifts, ExactFactors;
5773
5774 auto *RHSDefInstr = cast<GenericMachineInstr>(getDefIgnoringCopies(RHS, MRI));
5775 bool IsSplat = getIConstantSplatVal(*RHSDefInstr, MRI).has_value();
5776
5777 auto BuildExactSDIVPattern = [&](const Constant *C) {
5778 // Don't recompute inverses for each splat element.
5779 if (IsSplat && !ExactFactors.empty()) {
5780 ExactShifts.push_back(ExactShifts[0]);
5781 ExactFactors.push_back(ExactFactors[0]);
5782 return true;
5783 }
5784
5785 auto *CI = cast<ConstantInt>(C);
5786 APInt Divisor = CI->getValue();
5787 unsigned Shift = Divisor.countr_zero();
5788 if (Shift) {
5789 Divisor.ashrInPlace(Shift);
5790 UseSRA = true;
5791 }
5792
5793 // Calculate the multiplicative inverse modulo BW.
5794 // 2^W requires W + 1 bits, so we have to extend and then truncate.
5795 APInt Factor = Divisor.multiplicativeInverse();
5796 ExactShifts.push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
5797 ExactFactors.push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
5798 return true;
5799 };
5800
5801 if (MI.getFlag(MachineInstr::MIFlag::IsExact)) {
5802 // Collect all magic values from the build vector.
5803 bool Matched = matchUnaryPredicate(MRI, RHS, BuildExactSDIVPattern);
5804 (void)Matched;
5805 assert(Matched && "Expected unary predicate match to succeed");
5806
5807 Register Shift, Factor;
5808 if (Ty.isVector()) {
5809 Shift = MIB.buildBuildVector(ShiftAmtTy, ExactShifts).getReg(0);
5810 Factor = MIB.buildBuildVector(Ty, ExactFactors).getReg(0);
5811 } else {
5812 Shift = ExactShifts[0];
5813 Factor = ExactFactors[0];
5814 }
5815
5816 Register Res = LHS;
5817
5818 if (UseSRA)
5819 Res = MIB.buildAShr(Ty, Res, Shift, MachineInstr::IsExact).getReg(0);
5820
5821 return MIB.buildMul(Ty, Res, Factor);
5822 }
5823
5824 SmallVector<Register, 16> MagicFactors, Factors, Shifts, ShiftMasks;
5825
5826 auto BuildSDIVPattern = [&](const Constant *C) {
5827 auto *CI = cast<ConstantInt>(C);
5828 const APInt &Divisor = CI->getValue();
5829
5832 int NumeratorFactor = 0;
5833 int ShiftMask = -1;
5834
5835 if (Divisor.isOne() || Divisor.isAllOnes()) {
5836 // If d is +1/-1, we just multiply the numerator by +1/-1.
5837 NumeratorFactor = Divisor.getSExtValue();
5838 Magics.Magic = 0;
5839 Magics.ShiftAmount = 0;
5840 ShiftMask = 0;
5841 } else if (Divisor.isStrictlyPositive() && Magics.Magic.isNegative()) {
5842 // If d > 0 and m < 0, add the numerator.
5843 NumeratorFactor = 1;
5844 } else if (Divisor.isNegative() && Magics.Magic.isStrictlyPositive()) {
5845 // If d < 0 and m > 0, subtract the numerator.
5846 NumeratorFactor = -1;
5847 }
5848
5849 MagicFactors.push_back(MIB.buildConstant(ScalarTy, Magics.Magic).getReg(0));
5850 Factors.push_back(MIB.buildConstant(ScalarTy, NumeratorFactor).getReg(0));
5851 Shifts.push_back(
5852 MIB.buildConstant(ScalarShiftAmtTy, Magics.ShiftAmount).getReg(0));
5853 ShiftMasks.push_back(MIB.buildConstant(ScalarTy, ShiftMask).getReg(0));
5854
5855 return true;
5856 };
5857
5858 // Collect the shifts/magic values from each element.
5859 bool Matched = matchUnaryPredicate(MRI, RHS, BuildSDIVPattern);
5860 (void)Matched;
5861 assert(Matched && "Expected unary predicate match to succeed");
5862
5863 Register MagicFactor, Factor, Shift, ShiftMask;
5864 auto *RHSDef = getOpcodeDef<GBuildVector>(RHS, MRI);
5865 if (RHSDef) {
5866 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
5867 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
5868 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
5869 ShiftMask = MIB.buildBuildVector(Ty, ShiftMasks).getReg(0);
5870 } else {
5871 assert(MRI.getType(RHS).isScalar() &&
5872 "Non-build_vector operation should have been a scalar");
5873 MagicFactor = MagicFactors[0];
5874 Factor = Factors[0];
5875 Shift = Shifts[0];
5876 ShiftMask = ShiftMasks[0];
5877 }
5878
5879 Register Q = LHS;
5880 Q = MIB.buildSMulH(Ty, LHS, MagicFactor).getReg(0);
5881
5882 // (Optionally) Add/subtract the numerator using Factor.
5883 Factor = MIB.buildMul(Ty, LHS, Factor).getReg(0);
5884 Q = MIB.buildAdd(Ty, Q, Factor).getReg(0);
5885
5886 // Shift right algebraic by shift value.
5887 Q = MIB.buildAShr(Ty, Q, Shift).getReg(0);
5888
5889 // Extract the sign bit, mask it and add it to the quotient.
5890 auto SignShift = MIB.buildConstant(ShiftAmtTy, EltBits - 1);
5891 auto T = MIB.buildLShr(Ty, Q, SignShift);
5892 T = MIB.buildAnd(Ty, T, ShiftMask);
5893 auto ret = MIB.buildAdd(Ty, Q, T);
5894
5895 if (Opcode == TargetOpcode::G_SREM) {
5896 auto Prod = MIB.buildMul(Ty, ret, RHS);
5897 return MIB.buildSub(Ty, LHS, Prod);
5898 }
5899 return ret;
5900}
5901
5903 assert((MI.getOpcode() == TargetOpcode::G_SDIV ||
5904 MI.getOpcode() == TargetOpcode::G_UDIV) &&
5905 "Expected SDIV or UDIV");
5906 auto &Div = cast<GenericMachineInstr>(MI);
5907 Register RHS = Div.getReg(2);
5908 auto MatchPow2 = [&](const Constant *C) {
5909 auto *CI = dyn_cast<ConstantInt>(C);
5910 return CI && (CI->getValue().isPowerOf2() ||
5911 (IsSigned && CI->getValue().isNegatedPowerOf2()));
5912 };
5913 return matchUnaryPredicate(MRI, RHS, MatchPow2, /*AllowUndefs=*/false);
5914}
5915
5917 assert(MI.getOpcode() == TargetOpcode::G_SDIV && "Expected SDIV");
5918 auto &SDiv = cast<GenericMachineInstr>(MI);
5919 Register Dst = SDiv.getReg(0);
5920 Register LHS = SDiv.getReg(1);
5921 Register RHS = SDiv.getReg(2);
5922 LLT Ty = MRI.getType(Dst);
5924 LLT CCVT = Ty.isVector() ? LLT::vector(Ty.getElementCount(), LLT::integer(1))
5925 : LLT::integer(1);
5926
5927 // Effectively we want to lower G_SDIV %lhs, %rhs, where %rhs is a power of 2,
5928 // to the following version:
5929 //
5930 // %c1 = G_CTTZ %rhs
5931 // %inexact = G_SUB $bitwidth, %c1
5932 // %sign = %G_ASHR %lhs, $(bitwidth - 1)
5933 // %lshr = G_LSHR %sign, %inexact
5934 // %add = G_ADD %lhs, %lshr
5935 // %ashr = G_ASHR %add, %c1
5936 // %ashr = G_SELECT, %isoneorallones, %lhs, %ashr
5937 // %zero = G_CONSTANT $0
5938 // %neg = G_NEG %ashr
5939 // %isneg = G_ICMP SLT %rhs, %zero
5940 // %res = G_SELECT %isneg, %neg, %ashr
5941
5942 unsigned BitWidth = Ty.getScalarSizeInBits();
5943 auto Zero = Builder.buildConstant(Ty, 0);
5944
5945 auto Bits = Builder.buildConstant(ShiftAmtTy, BitWidth);
5946 auto C1 = Builder.buildCTTZ(ShiftAmtTy, RHS);
5947 auto Inexact = Builder.buildSub(ShiftAmtTy, Bits, C1);
5948 // Splat the sign bit into the register
5949 auto Sign = Builder.buildAShr(
5950 Ty, LHS, Builder.buildConstant(ShiftAmtTy, BitWidth - 1));
5951
5952 // Add (LHS < 0) ? abs2 - 1 : 0;
5953 auto LSrl = Builder.buildLShr(Ty, Sign, Inexact);
5954 auto Add = Builder.buildAdd(Ty, LHS, LSrl);
5955 auto AShr = Builder.buildAShr(Ty, Add, C1);
5956
5957 // Special case: (sdiv X, 1) -> X
5958 // Special Case: (sdiv X, -1) -> 0-X
5959 auto One = Builder.buildConstant(Ty, 1);
5960 auto MinusOne = Builder.buildConstant(Ty, -1);
5961 auto IsOne = Builder.buildICmp(CmpInst::Predicate::ICMP_EQ, CCVT, RHS, One);
5962 auto IsMinusOne =
5963 Builder.buildICmp(CmpInst::Predicate::ICMP_EQ, CCVT, RHS, MinusOne);
5964 auto IsOneOrMinusOne = Builder.buildOr(CCVT, IsOne, IsMinusOne);
5965 AShr = Builder.buildSelect(Ty, IsOneOrMinusOne, LHS, AShr);
5966
5967 // If divided by a positive value, we're done. Otherwise, the result must be
5968 // negated.
5969 auto Neg = Builder.buildNeg(Ty, AShr);
5970 auto IsNeg = Builder.buildICmp(CmpInst::Predicate::ICMP_SLT, CCVT, RHS, Zero);
5971 Builder.buildSelect(MI.getOperand(0).getReg(), IsNeg, Neg, AShr);
5972 MI.eraseFromParent();
5973}
5974
5976 assert(MI.getOpcode() == TargetOpcode::G_UDIV && "Expected UDIV");
5977 auto &UDiv = cast<GenericMachineInstr>(MI);
5978 Register Dst = UDiv.getReg(0);
5979 Register LHS = UDiv.getReg(1);
5980 Register RHS = UDiv.getReg(2);
5981 LLT Ty = MRI.getType(Dst);
5983
5984 auto C1 = Builder.buildCTTZ(ShiftAmtTy, RHS);
5985 Builder.buildLShr(MI.getOperand(0).getReg(), LHS, C1);
5986 MI.eraseFromParent();
5987}
5988
5990 assert(MI.getOpcode() == TargetOpcode::G_SREM && "Expected SREM");
5991 auto &SRem = cast<GBinOp>(MI);
5992 Register Dst = SRem.getReg(0);
5993 Register LHS = SRem.getLHSReg();
5994 Register RHS = SRem.getRHSReg();
5995 LLT Ty = MRI.getType(Dst);
5997
5998 // Effectively we want to lower G_SREM %lhs, %rhs, where %rhs is +/- a power
5999 // of 2, to the following branch-free bias-and-mask version:
6000 //
6001 // %abs = G_ABS %rhs
6002 // %mask = G_SUB %abs, 1
6003 // %sign = G_ASHR %lhs, $(bitwidth - 1)
6004 // %bias = G_AND %sign, %mask
6005 // %biased = G_ADD %lhs, %bias
6006 // %masked = G_AND %biased, %mask
6007 // %res = G_SUB %masked, %bias
6008 //
6009 // The bias adds (|%rhs| - 1) for negative %lhs, correcting rounding towards
6010 // zero (instead of towards -inf that a plain mask would give). Constant
6011 // divisors collapse %mask to a single G_CONSTANT via the CSEMIRBuilder folds
6012 // for G_ABS and G_SUB.
6013
6014 unsigned BitWidth = Ty.getScalarSizeInBits();
6015 auto AbsRHS = Builder.buildAbs(Ty, RHS);
6016 auto Mask = Builder.buildSub(Ty, AbsRHS, Builder.buildConstant(Ty, 1));
6017 auto BWMinusOne = Builder.buildConstant(ShiftAmtTy, BitWidth - 1);
6018 auto Sign = Builder.buildAShr(Ty, LHS, BWMinusOne);
6019 auto Bias = Builder.buildAnd(Ty, Sign, Mask);
6020 auto Biased = Builder.buildAdd(Ty, LHS, Bias);
6021 auto Masked = Builder.buildAnd(Ty, Biased, Mask);
6022 Builder.buildSub(Dst, Masked, Bias);
6023 MI.eraseFromParent();
6024}
6025
6027 assert(MI.getOpcode() == TargetOpcode::G_UMULH);
6028 Register RHS = MI.getOperand(2).getReg();
6029 Register Dst = MI.getOperand(0).getReg();
6030 LLT Ty = MRI.getType(Dst);
6031 LLT RHSTy = MRI.getType(RHS);
6033 auto MatchPow2ExceptOne = [&](const Constant *C) {
6034 if (auto *CI = dyn_cast<ConstantInt>(C))
6035 return CI->getValue().isPowerOf2() && !CI->getValue().isOne();
6036 return false;
6037 };
6038 if (!matchUnaryPredicate(MRI, RHS, MatchPow2ExceptOne, false))
6039 return false;
6040 // We need to check both G_LSHR and G_CTLZ because the combine uses G_CTLZ to
6041 // get log base 2, and it is not always legal for on a target.
6042 return isLegalOrBeforeLegalizer({TargetOpcode::G_LSHR, {Ty, ShiftAmtTy}}) &&
6043 isLegalOrBeforeLegalizer({TargetOpcode::G_CTLZ, {RHSTy, RHSTy}});
6044}
6045
6047 Register LHS = MI.getOperand(1).getReg();
6048 Register RHS = MI.getOperand(2).getReg();
6049 Register Dst = MI.getOperand(0).getReg();
6050 LLT Ty = MRI.getType(Dst);
6052 unsigned NumEltBits = Ty.getScalarSizeInBits();
6053
6054 auto LogBase2 = buildLogBase2(RHS, Builder);
6055 auto ShiftAmt =
6056 Builder.buildSub(Ty, Builder.buildConstant(Ty, NumEltBits), LogBase2);
6057 auto Trunc = Builder.buildZExtOrTrunc(ShiftAmtTy, ShiftAmt);
6058 Builder.buildLShr(Dst, LHS, Trunc);
6059 MI.eraseFromParent();
6060}
6061
6063 Register &MatchInfo) const {
6064 Register Dst = MI.getOperand(0).getReg();
6065 Register Src = MI.getOperand(1).getReg();
6066 LLT DstTy = MRI.getType(Dst);
6067 LLT SrcTy = MRI.getType(Src);
6068 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6069 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6070 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6071
6073 {TargetOpcode::G_TRUNC_SSAT_S, {DstTy, SrcTy}}))
6074 return false;
6075
6076 APInt SignedMax = APInt::getSignedMaxValue(NumDstBits).sext(NumSrcBits);
6077 APInt SignedMin = APInt::getSignedMinValue(NumDstBits).sext(NumSrcBits);
6078 if (mi_match(
6079 Src, MRI,
6080 m_GSMin(m_GSMax(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMin)),
6081 m_SpecificICstOrSplat(SignedMax))))
6082 return true;
6083 if (mi_match(
6084 Src, MRI,
6085 m_GSMax(m_GSMin(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMax)),
6086 m_SpecificICstOrSplat(SignedMin))))
6087 return true;
6088
6089 // CVP in the midend will often transform trunc(smin(smax(..)) into
6090 // trunc nsw(smin(..)) as the smax against INT_MIN never saturates.
6091 if (MI.getFlag(MachineInstr::MIFlag::NoSWrap) &&
6092 mi_match(Src, MRI,
6093 m_GSMin(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMax))))
6094 return true;
6095
6096 return false;
6097}
6098
6100 Register &MatchInfo) const {
6101 Register Dst = MI.getOperand(0).getReg();
6102 Builder.buildTruncSSatS(Dst, MatchInfo);
6103 MI.eraseFromParent();
6104}
6105
6107 Register &MatchInfo) const {
6108 Register Dst = MI.getOperand(0).getReg();
6109 Register Src = MI.getOperand(1).getReg();
6110 LLT DstTy = MRI.getType(Dst);
6111 LLT SrcTy = MRI.getType(Src);
6112 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6113 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6114 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6115
6117 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6118 return false;
6119 APInt UnsignedMax = APInt::getMaxValue(NumDstBits).zext(NumSrcBits);
6120 return mi_match(Src, MRI,
6122 m_SpecificICstOrSplat(UnsignedMax))) ||
6123 mi_match(Src, MRI,
6124 m_GSMax(m_GSMin(m_Reg(MatchInfo),
6125 m_SpecificICstOrSplat(UnsignedMax)),
6126 m_SpecificICstOrSplat(0))) ||
6127 mi_match(Src, MRI,
6129 m_SpecificICstOrSplat(UnsignedMax)));
6130}
6131
6133 Register &MatchInfo) const {
6134 Register Dst = MI.getOperand(0).getReg();
6135 Builder.buildTruncSSatU(Dst, MatchInfo);
6136 MI.eraseFromParent();
6137}
6138
6140 MachineInstr &MinMI) const {
6141 Register Min = MinMI.getOperand(2).getReg();
6142 Register Val = MinMI.getOperand(1).getReg();
6143 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6144 LLT SrcTy = MRI.getType(Val);
6145 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6146 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6147 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6148
6150 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6151 return false;
6152 APInt UnsignedMax = APInt::getMaxValue(NumDstBits).zext(NumSrcBits);
6153 return mi_match(Min, MRI, m_SpecificICstOrSplat(UnsignedMax)) &&
6154 !mi_match(Val, MRI, m_GSMax(m_Reg(), m_Reg()));
6155}
6156
6158 MachineInstr &SrcMI) const {
6159 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6160 LLT SrcTy = MRI.getType(SrcMI.getOperand(1).getReg());
6161
6162 return LI &&
6163 isLegalOrBeforeLegalizer({TargetOpcode::G_FPTOUI_SAT, {DstTy, SrcTy}});
6164}
6165
6167 BuildFnTy &MatchInfo) const {
6168 unsigned Opc = MI.getOpcode();
6169 assert(Opc == TargetOpcode::G_FADD || Opc == TargetOpcode::G_FSUB);
6170
6171 Register Dst = MI.getOperand(0).getReg();
6172 Register X = MI.getOperand(1).getReg();
6173 Register Y = MI.getOperand(2).getReg();
6174 LLT Type = MRI.getType(Dst);
6175
6176 // fold (fadd x, fneg(y)) -> (fsub x, y)
6177 // fold (fadd fneg(y), x) -> (fsub x, y)
6178 // G_ADD is commutative so both cases are checked by m_GFAdd
6179 if (mi_match(Dst, MRI, m_GFAdd(m_Reg(X), m_GFNeg(m_Reg(Y)))) &&
6180 isLegalOrBeforeLegalizer({TargetOpcode::G_FSUB, {Type}})) {
6181 Opc = TargetOpcode::G_FSUB;
6182 }
6183 /// fold (fsub x, fneg(y)) -> (fadd x, y)
6184 else if (mi_match(Dst, MRI, m_GFSub(m_Reg(X), m_GFNeg(m_Reg(Y)))) &&
6185 isLegalOrBeforeLegalizer({TargetOpcode::G_FADD, {Type}})) {
6186 Opc = TargetOpcode::G_FADD;
6187 } else
6188 return false;
6189
6190 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6191 Observer.changingInstr(MI);
6192 MI.setDesc(B.getTII().get(Opc));
6193 MI.getOperand(1).setReg(X);
6194 MI.getOperand(2).setReg(Y);
6195 Observer.changedInstr(MI);
6196 };
6197 return true;
6198}
6199
6201 Register &MatchInfo) const {
6202 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6203
6204 Register LHS = MI.getOperand(1).getReg();
6205 MatchInfo = MI.getOperand(2).getReg();
6206 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
6207
6208 const auto LHSCst = Ty.isVector()
6209 ? getFConstantSplat(LHS, MRI, /* allowUndef */ true)
6211 if (!LHSCst)
6212 return false;
6213
6214 // -0.0 is always allowed
6215 if (LHSCst->Value.isNegZero())
6216 return true;
6217
6218 // +0.0 is only allowed if nsz is set.
6219 if (LHSCst->Value.isPosZero())
6220 return MI.getFlag(MachineInstr::FmNsz);
6221
6222 return false;
6223}
6224
6226 Register &MatchInfo) const {
6227 Register Dst = MI.getOperand(0).getReg();
6228 Builder.buildFNeg(
6229 Dst, Builder.buildFCanonicalize(MRI.getType(Dst), MatchInfo).getReg(0));
6230 eraseInst(MI);
6231}
6232
6233/// Checks if \p MI is TargetOpcode::G_FMUL and contractable either
6234/// due to global flags or MachineInstr flags.
6235static bool isContractableFMul(MachineInstr &MI, bool AllowFusionGlobally) {
6236 if (MI.getOpcode() != TargetOpcode::G_FMUL)
6237 return false;
6238 return AllowFusionGlobally || MI.getFlag(MachineInstr::MIFlag::FmContract);
6239}
6240
6241static bool hasMoreUses(const MachineInstr &MI0, const MachineInstr &MI1,
6242 const MachineRegisterInfo &MRI) {
6243 return std::distance(MRI.use_instr_nodbg_begin(MI0.getOperand(0).getReg()),
6244 MRI.use_instr_nodbg_end()) >
6245 std::distance(MRI.use_instr_nodbg_begin(MI1.getOperand(0).getReg()),
6246 MRI.use_instr_nodbg_end());
6247}
6248
6250 bool &AllowFusionGlobally,
6251 bool &HasFMAD, bool &Aggressive,
6252 bool CanReassociate) const {
6253
6254 auto *MF = MI.getMF();
6255 const auto &TLI = *MF->getSubtarget().getTargetLowering();
6256 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6257
6258 if (CanReassociate && !MI.getFlag(MachineInstr::MIFlag::FmReassoc))
6259 return false;
6260
6261 // Floating-point multiply-add with intermediate rounding.
6262 HasFMAD = (!isPreLegalize() && TLI.isFMADLegal(MI, DstType));
6263 // Floating-point multiply-add without intermediate rounding.
6264 bool HasFMA = TLI.isFMAFasterThanFMulAndFAdd(*MF, DstType) &&
6265 isLegalOrBeforeLegalizer({TargetOpcode::G_FMA, {DstType}});
6266 // No valid opcode, do not combine.
6267 if (!HasFMAD && !HasFMA)
6268 return false;
6269
6270 // FMAD (with intermediate rounding) is always safe to form; FMA requires the
6271 // contract fast-math flag.
6272 AllowFusionGlobally = HasFMAD;
6273 // If the addition is not contractable, do not combine.
6274 if (!AllowFusionGlobally && !MI.getFlag(MachineInstr::MIFlag::FmContract))
6275 return false;
6276
6277 Aggressive = TLI.enableAggressiveFMAFusion(DstType);
6278 return true;
6279}
6280
6283 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6284 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6285
6286 bool AllowFusionGlobally, HasFMAD, Aggressive;
6287 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6288 return false;
6289
6290 Register Op1 = MI.getOperand(1).getReg();
6291 Register Op2 = MI.getOperand(2).getReg();
6292 MachineInstr *Op1Def, *Op2Def;
6293 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6294 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6295 return false;
6296 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6297 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6298 unsigned PreferredFusedOpcode =
6299 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6300
6301 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6302 // prefer to fold the multiply with fewer uses.
6303 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6304 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6305 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6306 std::swap(LHS, RHS);
6307 }
6308
6309 // fold (fadd (fmul x, y), z) -> (fma x, y, z)
6310 if (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6311 (Aggressive || MRI.hasOneNonDBGUse(LHS.Reg))) {
6312 unsigned Flags = MI.getFlags() & LHS.MI->getFlags();
6313 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6314 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6315 {LHS.MI->getOperand(1).getReg(),
6316 LHS.MI->getOperand(2).getReg(), RHS.Reg},
6317 Flags);
6318 };
6319 return true;
6320 }
6321
6322 // fold (fadd x, (fmul y, z)) -> (fma y, z, x)
6323 if (isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6324 (Aggressive || MRI.hasOneNonDBGUse(RHS.Reg))) {
6325 unsigned Flags = MI.getFlags() & RHS.MI->getFlags();
6326 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6327 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6328 {RHS.MI->getOperand(1).getReg(),
6329 RHS.MI->getOperand(2).getReg(), LHS.Reg},
6330 Flags);
6331 };
6332 return true;
6333 }
6334
6335 return false;
6336}
6337
6340 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6341 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6342
6343 bool AllowFusionGlobally, HasFMAD, Aggressive;
6344 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6345 return false;
6346
6347 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6348 Register Op1 = MI.getOperand(1).getReg();
6349 Register Op2 = MI.getOperand(2).getReg();
6350 MachineInstr *Op1Def, *Op2Def;
6351 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6352 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6353 return false;
6354 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6355 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6356 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6357
6358 unsigned PreferredFusedOpcode =
6359 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6360
6361 MachineInstr *LHSFpExtSrc;
6362 bool LHSContractable =
6363 mi_match(LHS.Reg, MRI, m_GFPExt(m_MInstr(LHSFpExtSrc))) &&
6364 isContractableFMul(*LHSFpExtSrc, AllowFusionGlobally) &&
6365 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6366 MRI.getType(LHSFpExtSrc->getOperand(1).getReg()));
6367 MachineInstr *RHSFpExtSrc;
6368 bool RHSContractable =
6369 mi_match(RHS.Reg, MRI, m_GFPExt(m_MInstr(RHSFpExtSrc))) &&
6370 isContractableFMul(*RHSFpExtSrc, AllowFusionGlobally) &&
6371 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6372 MRI.getType(RHSFpExtSrc->getOperand(1).getReg()));
6373
6374 // fold (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z)
6375 if (LHSContractable || RHSContractable) {
6376 // Ensure that the contractable fmul with the fewest uses (if both are
6377 // contractable) is the LHS operand.
6378 if (!LHSContractable ||
6379 (RHSContractable && hasMoreUses(*LHSFpExtSrc, *RHSFpExtSrc, MRI))) {
6380 std::swap(LHS, RHS);
6381 LHSFpExtSrc = RHSFpExtSrc;
6382 }
6383
6384 unsigned Flags = MI.getFlags() & LHSFpExtSrc->getFlags();
6385 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6386 auto FpExtX = B.buildFPExt(DstType, LHSFpExtSrc->getOperand(1).getReg());
6387 auto FpExtY = B.buildFPExt(DstType, LHSFpExtSrc->getOperand(2).getReg());
6388 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6389 {FpExtX.getReg(0), FpExtY.getReg(0), RHS.Reg}, Flags);
6390 };
6391 return true;
6392 }
6393
6394 return false;
6395}
6396
6399 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6400 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6401
6402 bool AllowFusionGlobally, HasFMAD, Aggressive;
6403 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive, true))
6404 return false;
6405
6406 Register Op1 = MI.getOperand(1).getReg();
6407 Register Op2 = MI.getOperand(2).getReg();
6408 MachineInstr *Op1Def, *Op2Def;
6409 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6410 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6411 return false;
6412 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6413 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6414 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6415
6416 unsigned PreferredFusedOpcode =
6417 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6418
6419 MachineInstr *FMA = nullptr;
6420 Register Z;
6421 // fold (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z))
6422 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6423 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6424 m_GFMul(m_Reg(), m_Reg())) &&
6425 MRI.hasOneNonDBGUse(LHS.MI->getOperand(0).getReg()) &&
6426 MRI.hasOneNonDBGUse(LHS.MI->getOperand(3).getReg())) {
6427 FMA = LHS.MI;
6428 Z = RHS.Reg;
6429 }
6430 // fold (fadd z, (fma x, y, (fmul u, v))) -> (fma x, y, (fma u, v, z))
6431 else if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6432 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6433 m_GFMul(m_Reg(), m_Reg())) &&
6434 MRI.hasOneNonDBGUse(RHS.MI->getOperand(0).getReg()) &&
6435 MRI.hasOneNonDBGUse(RHS.MI->getOperand(3).getReg())) {
6436 Z = LHS.Reg;
6437 FMA = RHS.MI;
6438 }
6439
6440 if (FMA) {
6441 MachineInstr *FMulMI;
6442 if (!mi_match(FMA->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6443 return false;
6444 Register X = FMA->getOperand(1).getReg();
6445 Register Y = FMA->getOperand(2).getReg();
6446 Register U = FMulMI->getOperand(1).getReg();
6447 Register V = FMulMI->getOperand(2).getReg();
6448 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6449 unsigned OuterFlags = MI.getFlags() & FMA->getFlags();
6450
6451 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6452 Register InnerFMA = MRI.createGenericVirtualRegister(DstTy);
6453 B.buildInstr(PreferredFusedOpcode, {InnerFMA}, {U, V, Z}, InnerFlags);
6454 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6455 {X, Y, InnerFMA}, OuterFlags);
6456 };
6457 return true;
6458 }
6459
6460 return false;
6461}
6462
6465 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6466 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6467
6468 bool AllowFusionGlobally, HasFMAD, Aggressive;
6469 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6470 return false;
6471
6472 if (!Aggressive)
6473 return false;
6474
6475 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6476 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6477 Register Op1 = MI.getOperand(1).getReg();
6478 Register Op2 = MI.getOperand(2).getReg();
6479 MachineInstr *Op1Def, *Op2Def;
6480 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6481 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6482 return false;
6483 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6484 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6485
6486 unsigned PreferredFusedOpcode =
6487 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6488
6489 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6490 // prefer to fold the multiply with fewer uses.
6491 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6492 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6493 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6494 std::swap(LHS, RHS);
6495 }
6496
6497 // Builds: (fma x, y, (fma (fpext u), (fpext v), z))
6498 auto buildMatchInfo = [=, &MI](Register U, Register V, Register Z, Register X,
6499 Register Y, unsigned InnerFlags,
6500 unsigned OuterFlags, MachineIRBuilder &B) {
6501 Register FpExtU = B.buildFPExt(DstType, U).getReg(0);
6502 Register FpExtV = B.buildFPExt(DstType, V).getReg(0);
6503 Register InnerFMA = B.buildInstr(PreferredFusedOpcode, {DstType},
6504 {FpExtU, FpExtV, Z}, InnerFlags)
6505 .getReg(0);
6506 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6507 {X, Y, InnerFMA}, OuterFlags);
6508 };
6509
6510 MachineInstr *FMulMI, *FMAMI;
6511 // fold (fadd (fma x, y, (fpext (fmul u, v))), z)
6512 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6513 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6514 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6515 m_GFPExt(m_MInstr(FMulMI))) &&
6516 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6517 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6518 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6519 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6520 unsigned OuterFlags = MI.getFlags() & LHS.MI->getFlags();
6521 MatchInfo = [=](MachineIRBuilder &B) {
6522 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6523 FMulMI->getOperand(2).getReg(), RHS.Reg,
6524 LHS.MI->getOperand(1).getReg(),
6525 LHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6526 };
6527 return true;
6528 }
6529
6530 // fold (fadd (fpext (fma x, y, (fmul u, v))), z)
6531 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6532 // FIXME: This turns two single-precision and one double-precision
6533 // operation into two double-precision operations, which might not be
6534 // interesting for all targets, especially GPUs.
6535 if (mi_match(LHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6536 FMAMI->getOpcode() == PreferredFusedOpcode) {
6537 MachineInstr *FMulMI;
6538 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6539 return false;
6540 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6541 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6542 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6543 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6544 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6545 MatchInfo = [=](MachineIRBuilder &B) {
6546 Register X = FMAMI->getOperand(1).getReg();
6547 Register Y = FMAMI->getOperand(2).getReg();
6548 X = B.buildFPExt(DstType, X).getReg(0);
6549 Y = B.buildFPExt(DstType, Y).getReg(0);
6550 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6551 FMulMI->getOperand(2).getReg(), RHS.Reg, X, Y,
6552 InnerFlags, OuterFlags, B);
6553 };
6554
6555 return true;
6556 }
6557 }
6558
6559 // fold (fadd z, (fma x, y, (fpext (fmul u, v)))
6560 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6561 if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6562 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6563 m_GFPExt(m_MInstr(FMulMI))) &&
6564 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6565 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6566 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6567 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6568 unsigned OuterFlags = MI.getFlags() & RHS.MI->getFlags();
6569 MatchInfo = [=](MachineIRBuilder &B) {
6570 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6571 FMulMI->getOperand(2).getReg(), LHS.Reg,
6572 RHS.MI->getOperand(1).getReg(),
6573 RHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6574 };
6575 return true;
6576 }
6577
6578 // fold (fadd z, (fpext (fma x, y, (fmul u, v)))
6579 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6580 // FIXME: This turns two single-precision and one double-precision
6581 // operation into two double-precision operations, which might not be
6582 // interesting for all targets, especially GPUs.
6583 if (mi_match(RHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6584 FMAMI->getOpcode() == PreferredFusedOpcode) {
6585 MachineInstr *FMulMI;
6586 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6587 return false;
6588 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6589 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6590 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6591 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6592 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6593 MatchInfo = [=](MachineIRBuilder &B) {
6594 Register X = FMAMI->getOperand(1).getReg();
6595 Register Y = FMAMI->getOperand(2).getReg();
6596 X = B.buildFPExt(DstType, X).getReg(0);
6597 Y = B.buildFPExt(DstType, Y).getReg(0);
6598 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6599 FMulMI->getOperand(2).getReg(), LHS.Reg, X, Y,
6600 InnerFlags, OuterFlags, B);
6601 };
6602 return true;
6603 }
6604 }
6605
6606 return false;
6607}
6608
6611 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6612 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6613
6614 bool AllowFusionGlobally, HasFMAD, Aggressive;
6615 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6616 return false;
6617
6618 Register Op1 = MI.getOperand(1).getReg();
6619 Register Op2 = MI.getOperand(2).getReg();
6620 MachineInstr *Op1Def, *Op2Def;
6621 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6622 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6623 return false;
6624 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6625 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6626 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6627
6628 // If we have two choices trying to fold (fsub (fmul u, v), (fmul x, y)),
6629 // prefer to fold the multiply with fewer uses.
6630 int FirstMulHasFewerUses = true;
6631 if (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6632 isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6633 hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6634 FirstMulHasFewerUses = false;
6635
6636 unsigned PreferredFusedOpcode =
6637 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6638
6639 // fold (fsub (fmul x, y), z) -> (fma x, y, -z)
6640 if (FirstMulHasFewerUses &&
6641 (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6642 (Aggressive || MRI.hasOneNonDBGUse(LHS.Reg)))) {
6643 unsigned Flags = MI.getFlags() & LHS.MI->getFlags();
6644 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6645 Register NegZ = B.buildFNeg(DstTy, RHS.Reg).getReg(0);
6646 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6647 {LHS.MI->getOperand(1).getReg(),
6648 LHS.MI->getOperand(2).getReg(), NegZ},
6649 Flags);
6650 };
6651 return true;
6652 }
6653 // fold (fsub x, (fmul y, z)) -> (fma -y, z, x)
6654 else if ((isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6655 (Aggressive || MRI.hasOneNonDBGUse(RHS.Reg)))) {
6656 unsigned Flags = MI.getFlags() & RHS.MI->getFlags();
6657 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6658 Register NegY =
6659 B.buildFNeg(DstTy, RHS.MI->getOperand(1).getReg()).getReg(0);
6660 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6661 {NegY, RHS.MI->getOperand(2).getReg(), LHS.Reg}, Flags);
6662 };
6663 return true;
6664 }
6665
6666 return false;
6667}
6668
6671 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6672 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6673
6674 bool AllowFusionGlobally, HasFMAD, Aggressive;
6675 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6676 return false;
6677
6678 Register LHSReg = MI.getOperand(1).getReg();
6679 Register RHSReg = MI.getOperand(2).getReg();
6680 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6681
6682 unsigned PreferredFusedOpcode =
6683 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6684
6685 MachineInstr *FMulMI;
6686 // fold (fsub (fneg (fmul x, y)), z) -> (fma (fneg x), y, (fneg z))
6687 if (mi_match(LHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6688 (Aggressive || (MRI.hasOneNonDBGUse(LHSReg) &&
6689 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6690 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6691 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6692 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6693 Register NegX =
6694 B.buildFNeg(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6695 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6696 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6697 {NegX, FMulMI->getOperand(2).getReg(), NegZ}, Flags);
6698 };
6699 return true;
6700 }
6701
6702 // fold (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x)
6703 if (mi_match(RHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6704 (Aggressive || (MRI.hasOneNonDBGUse(RHSReg) &&
6705 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6706 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6707 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6708 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6709 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6710 {FMulMI->getOperand(1).getReg(),
6711 FMulMI->getOperand(2).getReg(), LHSReg},
6712 Flags);
6713 };
6714 return true;
6715 }
6716
6717 return false;
6718}
6719
6722 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6723 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6724
6725 bool AllowFusionGlobally, HasFMAD, Aggressive;
6726 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6727 return false;
6728
6729 Register LHSReg = MI.getOperand(1).getReg();
6730 Register RHSReg = MI.getOperand(2).getReg();
6731 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6732
6733 unsigned PreferredFusedOpcode =
6734 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6735
6736 MachineInstr *FMulMI;
6737 // fold (fsub (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), (fneg z))
6738 if (mi_match(LHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6739 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6740 (Aggressive || MRI.hasOneNonDBGUse(LHSReg))) {
6741 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6742 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6743 Register FpExtX =
6744 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6745 Register FpExtY =
6746 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6747 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6748 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6749 {FpExtX, FpExtY, NegZ}, Flags);
6750 };
6751 return true;
6752 }
6753
6754 // fold (fsub x, (fpext (fmul y, z))) -> (fma (fneg (fpext y)), (fpext z), x)
6755 if (mi_match(RHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6756 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6757 (Aggressive || MRI.hasOneNonDBGUse(RHSReg))) {
6758 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6759 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6760 Register FpExtY =
6761 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6762 Register NegY = B.buildFNeg(DstTy, FpExtY).getReg(0);
6763 Register FpExtZ =
6764 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6765 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6766 {NegY, FpExtZ, LHSReg}, Flags);
6767 };
6768 return true;
6769 }
6770
6771 return false;
6772}
6773
6776 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6777 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6778
6779 bool AllowFusionGlobally, HasFMAD, Aggressive;
6780 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6781 return false;
6782
6783 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6784 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6785 Register LHSReg = MI.getOperand(1).getReg();
6786 Register RHSReg = MI.getOperand(2).getReg();
6787
6788 unsigned PreferredFusedOpcode =
6789 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6790
6791 auto buildMatchInfo = [=](Register Dst, Register X, Register Y, Register Z,
6792 unsigned Flags, MachineIRBuilder &B) {
6793 Register FpExtX = B.buildFPExt(DstTy, X).getReg(0);
6794 Register FpExtY = B.buildFPExt(DstTy, Y).getReg(0);
6795 B.buildInstr(PreferredFusedOpcode, {Dst}, {FpExtX, FpExtY, Z}, Flags);
6796 };
6797
6798 MachineInstr *FMulMI;
6799 // fold (fsub (fpext (fneg (fmul x, y))), z) ->
6800 // (fneg (fma (fpext x), (fpext y), z))
6801 // fold (fsub (fneg (fpext (fmul x, y))), z) ->
6802 // (fneg (fma (fpext x), (fpext y), z))
6803 if ((mi_match(LHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
6804 mi_match(LHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
6805 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6806 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
6807 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6808 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6809 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6810 Register FMAReg = MRI.createGenericVirtualRegister(DstTy);
6811 buildMatchInfo(FMAReg, FMulMI->getOperand(1).getReg(),
6812 FMulMI->getOperand(2).getReg(), RHSReg, Flags, B);
6813 B.buildFNeg(MI.getOperand(0).getReg(), FMAReg);
6814 };
6815 return true;
6816 }
6817
6818 // fold (fsub x, (fpext (fneg (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
6819 // fold (fsub x, (fneg (fpext (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
6820 if ((mi_match(RHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
6821 mi_match(RHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
6822 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6823 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
6824 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6825 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6826 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6827 buildMatchInfo(MI.getOperand(0).getReg(), FMulMI->getOperand(1).getReg(),
6828 FMulMI->getOperand(2).getReg(), LHSReg, Flags, B);
6829 };
6830 return true;
6831 }
6832
6833 return false;
6834}
6835
6837 unsigned &IdxToPropagate) const {
6838 bool PropagateNaN;
6839 switch (MI.getOpcode()) {
6840 default:
6841 return false;
6842 case TargetOpcode::G_FMINNUM:
6843 case TargetOpcode::G_FMAXNUM:
6844 PropagateNaN = false;
6845 break;
6846 case TargetOpcode::G_FMINIMUM:
6847 case TargetOpcode::G_FMAXIMUM:
6848 PropagateNaN = true;
6849 break;
6850 }
6851
6852 auto MatchNaN = [&](unsigned Idx) {
6853 Register MaybeNaNReg = MI.getOperand(Idx).getReg();
6854 const ConstantFP *MaybeCst = getConstantFPVRegVal(MaybeNaNReg, MRI);
6855 if (!MaybeCst || !MaybeCst->getValueAPF().isNaN())
6856 return false;
6857 IdxToPropagate = PropagateNaN ? Idx : (Idx == 1 ? 2 : 1);
6858 return true;
6859 };
6860
6861 return MatchNaN(1) || MatchNaN(2);
6862}
6863
6864// Combine multiple FDIVs with the same divisor into multiple FMULs by the
6865// reciprocal.
6866// E.g., (a / Y; b / Y;) -> (recip = 1.0 / Y; a * recip; b * recip)
6868 MachineInstr &MI, SmallVector<MachineInstr *> &MatchInfo) const {
6869 assert(MI.getOpcode() == TargetOpcode::G_FDIV);
6870
6871 Register X = MI.getOperand(1).getReg();
6872 Register Y = MI.getOperand(2).getReg();
6873
6874 if (!MI.getFlag(MachineInstr::MIFlag::FmArcp))
6875 return false;
6876
6877 auto IsOne = [this](Register X) {
6879 return N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne());
6880 };
6881
6882 // Skip if current node is a reciprocal/fneg-reciprocal.
6883 if (IsOne(X))
6884 return false;
6885
6886 // Exit early if the target does not want this transform or if there can't
6887 // possibly be enough uses of the divisor to make the transform worthwhile.
6888 unsigned MinUses = getTargetLowering().combineRepeatedFPDivisors();
6889 if (!MinUses)
6890 return false;
6891
6892 // Find all FDIV users of the same divisor. For the moment we limit all
6893 // instructions to a single BB and use the first Instr in MatchInfo as the
6894 // dominating position.
6895 MatchInfo.push_back(&MI);
6896 for (auto &U : MRI.use_nodbg_instructions(Y)) {
6897 if (&U == &MI || U.getParent() != MI.getParent())
6898 continue;
6899 if (U.getOpcode() == TargetOpcode::G_FDIV &&
6900 U.getOperand(2).getReg() == Y && U.getOperand(1).getReg() != Y &&
6901 !IsOne(U.getOperand(1).getReg())) {
6902 // This division is eligible for optimization only if global unsafe math
6903 // is enabled or if this division allows reciprocal formation.
6904 if (U.getFlag(MachineInstr::MIFlag::FmArcp)) {
6905 MatchInfo.push_back(&U);
6906 if (dominates(U, *MatchInfo[0]))
6907 std::swap(MatchInfo[0], MatchInfo.back());
6908 }
6909 }
6910 }
6911
6912 // Now that we have the actual number of divisor uses, make sure it meets
6913 // the minimum threshold specified by the target.
6914 return MatchInfo.size() >= MinUses;
6915}
6916
6918 SmallVector<MachineInstr *> &MatchInfo) const {
6919 // Generate the new div at the position of the first instruction, that we have
6920 // ensured will dominate all other instructions.
6921 Builder.setInsertPt(*MatchInfo[0]->getParent(), MatchInfo[0]);
6922 LLT Ty = MRI.getType(MatchInfo[0]->getOperand(0).getReg());
6923 auto Div = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0),
6924 MatchInfo[0]->getOperand(2).getReg(),
6925 MatchInfo[0]->getFlags());
6926
6927 // Replace all found div's with fmul instructions.
6928 for (MachineInstr *MI : MatchInfo) {
6929 Builder.setInsertPt(*MI->getParent(), MI);
6930 Builder.buildFMul(MI->getOperand(0).getReg(), MI->getOperand(1).getReg(),
6931 Div->getOperand(0).getReg(), MI->getFlags());
6932 MI->eraseFromParent();
6933 }
6934}
6935
6937 Register &MatchInfo) const {
6938 // This combine folds the following patterns:
6939 //
6940 // G_BUILD_VECTOR_TRUNC (G_BITCAST(x), G_LSHR(G_BITCAST(x), k))
6941 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), G_TRUNC(G_LSHR(G_BITCAST(x), k)))
6942 // into
6943 // x
6944 // if
6945 // k == sizeof(VecEltTy)/2
6946 // type(x) == type(dst)
6947 //
6948 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), undef)
6949 // into
6950 // x
6951 // if
6952 // type(x) == type(dst)
6953
6954 LLT DstVecTy = MRI.getType(MI.getOperand(0).getReg());
6955 LLT DstEltTy = DstVecTy.getElementType();
6956
6957 Register Lo, Hi;
6958
6959 if (mi_match(
6960 MI, MRI,
6962 MatchInfo = Lo;
6963 return MRI.getType(MatchInfo) == DstVecTy;
6964 }
6965
6966 std::optional<ValueAndVReg> ShiftAmount;
6967 const auto LoPattern = m_GBitcast(m_Reg(Lo));
6968 const auto HiPattern = m_GLShr(m_GBitcast(m_Reg(Hi)), m_GCst(ShiftAmount));
6969 if (mi_match(
6970 MI, MRI,
6971 m_any_of(m_GBuildVectorTrunc(LoPattern, HiPattern),
6972 m_GBuildVector(m_GTrunc(LoPattern), m_GTrunc(HiPattern))))) {
6973 if (Lo == Hi && ShiftAmount->Value == DstEltTy.getSizeInBits()) {
6974 MatchInfo = Lo;
6975 return MRI.getType(MatchInfo) == DstVecTy;
6976 }
6977 }
6978
6979 return false;
6980}
6981
6983 Register &MatchInfo) const {
6984 // Replace (G_TRUNC (G_BITCAST (G_BUILD_VECTOR x, y)) with just x
6985 // if type(x) == type(G_TRUNC)
6986 if (!mi_match(MI.getOperand(1).getReg(), MRI,
6987 m_GBitcast(m_GBuildVector(m_Reg(MatchInfo), m_Reg()))))
6988 return false;
6989
6990 return MRI.getType(MatchInfo) == MRI.getType(MI.getOperand(0).getReg());
6991}
6992
6994 Register &MatchInfo) const {
6995 // Replace (G_TRUNC (G_LSHR (G_BITCAST (G_BUILD_VECTOR x, y)), K)) with
6996 // y if K == size of vector element type
6997 std::optional<ValueAndVReg> ShiftAmt;
6998 if (!mi_match(MI.getOperand(1).getReg(), MRI,
7000 m_GCst(ShiftAmt))))
7001 return false;
7002
7003 LLT MatchTy = MRI.getType(MatchInfo);
7004 return ShiftAmt->Value.getZExtValue() == MatchTy.getSizeInBits() &&
7005 MatchTy == MRI.getType(MI.getOperand(0).getReg());
7006}
7007
7008unsigned CombinerHelper::getFPMinMaxOpcForSelect(
7009 CmpInst::Predicate Pred, LLT DstTy,
7010 SelectPatternNaNBehaviour VsNaNRetVal) const {
7011 assert(VsNaNRetVal != SelectPatternNaNBehaviour::NOT_APPLICABLE &&
7012 "Expected a NaN behaviour?");
7013 // Choose an opcode based off of legality or the behaviour when one of the
7014 // LHS/RHS may be NaN.
7015 switch (Pred) {
7016 default:
7017 return 0;
7018 case CmpInst::FCMP_UGT:
7019 case CmpInst::FCMP_UGE:
7020 case CmpInst::FCMP_OGT:
7021 case CmpInst::FCMP_OGE:
7022 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7023 return TargetOpcode::G_FMAXNUM;
7024 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7025 return TargetOpcode::G_FMAXIMUM;
7026 if (isLegal({TargetOpcode::G_FMAXNUM, {DstTy}}))
7027 return TargetOpcode::G_FMAXNUM;
7028 if (isLegal({TargetOpcode::G_FMAXIMUM, {DstTy}}))
7029 return TargetOpcode::G_FMAXIMUM;
7030 return 0;
7031 case CmpInst::FCMP_ULT:
7032 case CmpInst::FCMP_ULE:
7033 case CmpInst::FCMP_OLT:
7034 case CmpInst::FCMP_OLE:
7035 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7036 return TargetOpcode::G_FMINNUM;
7037 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7038 return TargetOpcode::G_FMINIMUM;
7039 if (isLegal({TargetOpcode::G_FMINNUM, {DstTy}}))
7040 return TargetOpcode::G_FMINNUM;
7041 if (!isLegal({TargetOpcode::G_FMINIMUM, {DstTy}}))
7042 return 0;
7043 return TargetOpcode::G_FMINIMUM;
7044 }
7045}
7046
7047CombinerHelper::SelectPatternNaNBehaviour
7048CombinerHelper::computeRetValAgainstNaN(Register LHS, Register RHS,
7049 bool IsOrderedComparison) const {
7050 bool LHSSafe = VT->isKnownNeverNaN(LHS);
7051 bool RHSSafe = VT->isKnownNeverNaN(RHS);
7052 // Completely unsafe.
7053 if (!LHSSafe && !RHSSafe)
7054 return SelectPatternNaNBehaviour::NOT_APPLICABLE;
7055 if (LHSSafe && RHSSafe)
7056 return SelectPatternNaNBehaviour::RETURNS_ANY;
7057 // An ordered comparison will return false when given a NaN, so it
7058 // returns the RHS.
7059 if (IsOrderedComparison)
7060 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_NAN
7061 : SelectPatternNaNBehaviour::RETURNS_OTHER;
7062 // An unordered comparison will return true when given a NaN, so it
7063 // returns the LHS.
7064 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_OTHER
7065 : SelectPatternNaNBehaviour::RETURNS_NAN;
7066}
7067
7068bool CombinerHelper::matchFPSelectToMinMax(Register Dst, Register Cond,
7069 Register TrueVal, Register FalseVal,
7070 BuildFnTy &MatchInfo) const {
7071 // Match: select (fcmp cond x, y) x, y
7072 // select (fcmp cond x, y) y, x
7073 // And turn it into fminnum/fmaxnum or fmin/fmax based off of the condition.
7074 LLT DstTy = MRI.getType(Dst);
7075 // Bail out early on pointers, since we'll never want to fold to a min/max.
7076 if (DstTy.isPointer())
7077 return false;
7078 // Match a floating point compare with a less-than/greater-than predicate.
7079 // TODO: Allow multiple users of the compare if they are all selects.
7080 CmpInst::Predicate Pred;
7081 Register CmpLHS, CmpRHS;
7082 if (!mi_match(Cond, MRI,
7084 m_GFCmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS)))) ||
7085 CmpInst::isEquality(Pred))
7086 return false;
7087 SelectPatternNaNBehaviour ResWithKnownNaNInfo =
7088 computeRetValAgainstNaN(CmpLHS, CmpRHS, CmpInst::isOrdered(Pred));
7089 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::NOT_APPLICABLE)
7090 return false;
7091 if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
7092 std::swap(CmpLHS, CmpRHS);
7093 Pred = CmpInst::getSwappedPredicate(Pred);
7094 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_NAN)
7095 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_OTHER;
7096 else if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_OTHER)
7097 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_NAN;
7098 }
7099 if (TrueVal != CmpLHS || FalseVal != CmpRHS)
7100 return false;
7101 // Decide what type of max/min this should be based off of the predicate.
7102 unsigned Opc = getFPMinMaxOpcForSelect(Pred, DstTy, ResWithKnownNaNInfo);
7103 if (!Opc || !isLegal({Opc, {DstTy}}))
7104 return false;
7105 // Comparisons between signed zero and zero may have different results...
7106 // unless we have fmaximum/fminimum. In that case, we know -0 < 0.
7107 if (Opc != TargetOpcode::G_FMAXIMUM && Opc != TargetOpcode::G_FMINIMUM) {
7108 // We don't know if a comparison between two 0s will give us a consistent
7109 // result. Be conservative and only proceed if at least one side is
7110 // non-zero.
7111 auto KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpLHS, MRI);
7112 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero()) {
7113 KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpRHS, MRI);
7114 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero())
7115 return false;
7116 }
7117 }
7118 MatchInfo = [=](MachineIRBuilder &B) {
7119 B.buildInstr(Opc, {Dst}, {CmpLHS, CmpRHS});
7120 };
7121 return true;
7122}
7123
7125 BuildFnTy &MatchInfo) const {
7126 // TODO: Handle integer cases.
7127 assert(MI.getOpcode() == TargetOpcode::G_SELECT);
7128 // Condition may be fed by a truncated compare.
7129 Register Cond = MI.getOperand(1).getReg();
7130 Register MaybeTrunc;
7131 if (mi_match(Cond, MRI, m_OneNonDBGUse(m_GTrunc(m_Reg(MaybeTrunc)))))
7132 Cond = MaybeTrunc;
7133 Register Dst = MI.getOperand(0).getReg();
7134 Register TrueVal = MI.getOperand(2).getReg();
7135 Register FalseVal = MI.getOperand(3).getReg();
7136 return matchFPSelectToMinMax(Dst, Cond, TrueVal, FalseVal, MatchInfo);
7137}
7138
7140 BuildFnTy &MatchInfo) const {
7141 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
7142 // (X + Y) == X --> Y == 0
7143 // (X + Y) != X --> Y != 0
7144 // (X - Y) == X --> Y == 0
7145 // (X - Y) != X --> Y != 0
7146 // (X ^ Y) == X --> Y == 0
7147 // (X ^ Y) != X --> Y != 0
7148 Register Dst = MI.getOperand(0).getReg();
7149 CmpInst::Predicate Pred;
7150 Register X, Y, OpLHS, OpRHS;
7151 bool MatchedSub = mi_match(
7152 Dst, MRI,
7153 m_c_GICmp(m_Pred(Pred), m_Reg(X), m_GSub(m_Reg(OpLHS), m_Reg(Y))));
7154 if (MatchedSub && X != OpLHS)
7155 return false;
7156 if (!MatchedSub) {
7157 if (!mi_match(Dst, MRI,
7158 m_c_GICmp(m_Pred(Pred), m_Reg(X),
7159 m_any_of(m_GAdd(m_Reg(OpLHS), m_Reg(OpRHS)),
7160 m_GXor(m_Reg(OpLHS), m_Reg(OpRHS))))))
7161 return false;
7162 Y = X == OpLHS ? OpRHS : X == OpRHS ? OpLHS : Register();
7163 }
7164 MatchInfo = [=](MachineIRBuilder &B) {
7165 auto Zero = B.buildConstant(MRI.getType(Y), 0);
7166 B.buildICmp(Pred, Dst, Y, Zero);
7167 };
7168 return CmpInst::isEquality(Pred) && Y.isValid();
7169}
7170
7171/// Return the minimum useless shift amount that results in complete loss of the
7172/// source value. Return std::nullopt when it cannot determine a value.
7173static std::optional<unsigned>
7174getMinUselessShift(KnownBits ValueKB, unsigned Opcode,
7175 std::optional<int64_t> &Result) {
7176 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR ||
7177 Opcode == TargetOpcode::G_ASHR) &&
7178 "Expect G_SHL, G_LSHR or G_ASHR.");
7179 auto SignificantBits = 0;
7180 switch (Opcode) {
7181 case TargetOpcode::G_SHL:
7182 SignificantBits = ValueKB.countMinTrailingZeros();
7183 Result = 0;
7184 break;
7185 case TargetOpcode::G_LSHR:
7186 Result = 0;
7187 SignificantBits = ValueKB.countMinLeadingZeros();
7188 break;
7189 case TargetOpcode::G_ASHR:
7190 if (ValueKB.isNonNegative()) {
7191 SignificantBits = ValueKB.countMinLeadingZeros();
7192 Result = 0;
7193 } else if (ValueKB.isNegative()) {
7194 SignificantBits = ValueKB.countMinLeadingOnes();
7195 Result = -1;
7196 } else {
7197 // Cannot determine shift result.
7198 Result = std::nullopt;
7199 }
7200 break;
7201 default:
7202 break;
7203 }
7204 return ValueKB.getBitWidth() - SignificantBits;
7205}
7206
7208 MachineInstr &MI, std::optional<int64_t> &MatchInfo) const {
7209 Register ShiftVal = MI.getOperand(1).getReg();
7210 Register ShiftReg = MI.getOperand(2).getReg();
7211 LLT ResTy = MRI.getType(MI.getOperand(0).getReg());
7212 auto IsShiftTooBig = [&](const Constant *C) {
7213 auto *CI = dyn_cast<ConstantInt>(C);
7214 if (!CI)
7215 return false;
7216 if (CI->uge(ResTy.getScalarSizeInBits())) {
7217 MatchInfo = std::nullopt;
7218 return true;
7219 }
7220 auto OptMaxUsefulShift = getMinUselessShift(VT->getKnownBits(ShiftVal),
7221 MI.getOpcode(), MatchInfo);
7222 return OptMaxUsefulShift && CI->uge(*OptMaxUsefulShift);
7223 };
7224 return matchUnaryPredicate(MRI, ShiftReg, IsShiftTooBig);
7225}
7226
7228 unsigned LHSOpndIdx = 1;
7229 unsigned RHSOpndIdx = 2;
7230 switch (MI.getOpcode()) {
7231 case TargetOpcode::G_UADDO:
7232 case TargetOpcode::G_SADDO:
7233 case TargetOpcode::G_UMULO:
7234 case TargetOpcode::G_SMULO:
7235 LHSOpndIdx = 2;
7236 RHSOpndIdx = 3;
7237 break;
7238 default:
7239 break;
7240 }
7241 Register LHS = MI.getOperand(LHSOpndIdx).getReg();
7242 Register RHS = MI.getOperand(RHSOpndIdx).getReg();
7243 MachineInstr *LHSDef, *RHSDef;
7244 if (!mi_match(LHS, MRI, m_MInstr(LHSDef)) ||
7245 !mi_match(RHS, MRI, m_MInstr(RHSDef)))
7246 return false;
7247
7248 if (!getIConstantVRegVal(LHS, MRI)) {
7249 // Skip commuting if LHS is not a constant. But, LHS may be a
7250 // G_CONSTANT_FOLD_BARRIER. If so we commute as long as we don't already
7251 // have a constant on the RHS.
7252 if (LHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER)
7253 return false;
7254 }
7255 // Commute as long as RHS is not a constant or G_CONSTANT_FOLD_BARRIER.
7256 return RHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER &&
7257 !getIConstantVRegVal(RHS, MRI);
7258}
7259
7261 Register LHS = MI.getOperand(1).getReg();
7262 Register RHS = MI.getOperand(2).getReg();
7263 std::optional<FPValueAndVReg> ValAndVReg;
7264 if (!mi_match(LHS, MRI, m_GFCstOrSplat(ValAndVReg)))
7265 return false;
7266 return !mi_match(RHS, MRI, m_GFCstOrSplat(ValAndVReg));
7267}
7268
7270 Observer.changingInstr(MI);
7271 unsigned LHSOpndIdx = 1;
7272 unsigned RHSOpndIdx = 2;
7273 switch (MI.getOpcode()) {
7274 case TargetOpcode::G_UADDO:
7275 case TargetOpcode::G_SADDO:
7276 case TargetOpcode::G_UMULO:
7277 case TargetOpcode::G_SMULO:
7278 LHSOpndIdx = 2;
7279 RHSOpndIdx = 3;
7280 break;
7281 default:
7282 break;
7283 }
7284 Register LHSReg = MI.getOperand(LHSOpndIdx).getReg();
7285 Register RHSReg = MI.getOperand(RHSOpndIdx).getReg();
7286 MI.getOperand(LHSOpndIdx).setReg(RHSReg);
7287 MI.getOperand(RHSOpndIdx).setReg(LHSReg);
7288 Observer.changedInstr(MI);
7289}
7290
7291bool CombinerHelper::isOneOrOneSplat(Register Src, bool AllowUndefs) const {
7292 LLT SrcTy = MRI.getType(Src);
7293 if (SrcTy.isFixedVector())
7294 return isConstantSplatVector(Src, 1, AllowUndefs);
7295 if (SrcTy.isScalar()) {
7296 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7297 return true;
7298 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7299 return IConstant && IConstant->Value == 1;
7300 }
7301 return false; // scalable vector
7302}
7303
7304bool CombinerHelper::isZeroOrZeroSplat(Register Src, bool AllowUndefs) const {
7305 LLT SrcTy = MRI.getType(Src);
7306 if (SrcTy.isFixedVector())
7307 return isConstantSplatVector(Src, 0, AllowUndefs);
7308 if (SrcTy.isScalar()) {
7309 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7310 return true;
7311 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7312 return IConstant && IConstant->Value == 0;
7313 }
7314 return false; // scalable vector
7315}
7316
7317// Ignores COPYs during conformance checks.
7318// FIXME scalable vectors.
7319bool CombinerHelper::isConstantSplatVector(Register Src, int64_t SplatValue,
7320 bool AllowUndefs) const {
7321 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7322 if (!BuildVector)
7323 return false;
7324 unsigned NumSources = BuildVector->getNumSources();
7325
7326 for (unsigned I = 0; I < NumSources; ++I) {
7327 GImplicitDef *ImplicitDef =
7329 if (ImplicitDef && AllowUndefs)
7330 continue;
7331 if (ImplicitDef && !AllowUndefs)
7332 return false;
7333 std::optional<ValueAndVReg> IConstant =
7335 if (IConstant && IConstant->Value == SplatValue)
7336 continue;
7337 return false;
7338 }
7339 return true;
7340}
7341
7342// Ignores COPYs during lookups.
7343// FIXME scalable vectors
7344std::optional<APInt>
7345CombinerHelper::getConstantOrConstantSplatVector(Register Src) const {
7346 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7347 if (IConstant)
7348 return IConstant->Value;
7349
7350 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7351 if (!BuildVector)
7352 return std::nullopt;
7353 unsigned NumSources = BuildVector->getNumSources();
7354
7355 std::optional<APInt> Value = std::nullopt;
7356 for (unsigned I = 0; I < NumSources; ++I) {
7357 std::optional<ValueAndVReg> IConstant =
7359 if (!IConstant)
7360 return std::nullopt;
7361 if (!Value)
7362 Value = IConstant->Value;
7363 else if (*Value != IConstant->Value)
7364 return std::nullopt;
7365 }
7366 return Value;
7367}
7368
7369// FIXME G_SPLAT_VECTOR
7370bool CombinerHelper::isConstantOrConstantVectorI(Register Src) const {
7371 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7372 if (IConstant)
7373 return true;
7374
7375 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7376 if (!BuildVector)
7377 return false;
7378
7379 unsigned NumSources = BuildVector->getNumSources();
7380 for (unsigned I = 0; I < NumSources; ++I) {
7381 std::optional<ValueAndVReg> IConstant =
7383 if (!IConstant)
7384 return false;
7385 }
7386 return true;
7387}
7388
7389// TODO: use knownbits to determine zeros
7390bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
7391 BuildFnTy &MatchInfo) const {
7392 uint32_t Flags = Select->getFlags();
7393 Register Dest = Select->getReg(0);
7394 Register Cond = Select->getCondReg();
7395 Register True = Select->getTrueReg();
7396 Register False = Select->getFalseReg();
7397 LLT CondTy = MRI.getType(Select->getCondReg());
7398 LLT TrueTy = MRI.getType(Select->getTrueReg());
7399
7400 // We only do this combine for scalar boolean conditions.
7401 if (CondTy != LLT::scalar(1))
7402 return false;
7403
7404 if (TrueTy.isPointer())
7405 return false;
7406
7407 // Both are scalars.
7408 std::optional<ValueAndVReg> TrueOpt =
7410 std::optional<ValueAndVReg> FalseOpt =
7412
7413 if (!TrueOpt || !FalseOpt)
7414 return false;
7415
7416 APInt TrueValue = TrueOpt->Value;
7417 APInt FalseValue = FalseOpt->Value;
7418
7419 // select Cond, 1, 0 --> zext (Cond)
7420 if (TrueValue.isOne() && FalseValue.isZero()) {
7421 MatchInfo = [=](MachineIRBuilder &B) {
7422 B.setInstrAndDebugLoc(*Select);
7423 B.buildZExtOrTrunc(Dest, Cond);
7424 };
7425 return true;
7426 }
7427
7428 // select Cond, -1, 0 --> sext (Cond)
7429 if (TrueValue.isAllOnes() && FalseValue.isZero()) {
7430 MatchInfo = [=](MachineIRBuilder &B) {
7431 B.setInstrAndDebugLoc(*Select);
7432 B.buildSExtOrTrunc(Dest, Cond);
7433 };
7434 return true;
7435 }
7436
7437 // select Cond, 0, 1 --> zext (!Cond)
7438 if (TrueValue.isZero() && FalseValue.isOne()) {
7439 MatchInfo = [=](MachineIRBuilder &B) {
7440 B.setInstrAndDebugLoc(*Select);
7441 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7442 B.buildNot(Inner, Cond);
7443 B.buildZExtOrTrunc(Dest, Inner);
7444 };
7445 return true;
7446 }
7447
7448 // select Cond, 0, -1 --> sext (!Cond)
7449 if (TrueValue.isZero() && FalseValue.isAllOnes()) {
7450 MatchInfo = [=](MachineIRBuilder &B) {
7451 B.setInstrAndDebugLoc(*Select);
7452 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7453 B.buildNot(Inner, Cond);
7454 B.buildSExtOrTrunc(Dest, Inner);
7455 };
7456 return true;
7457 }
7458
7459 // select Cond, C1, C1-1 --> add (zext Cond), C1-1
7460 if (TrueValue - 1 == FalseValue) {
7461 MatchInfo = [=](MachineIRBuilder &B) {
7462 B.setInstrAndDebugLoc(*Select);
7463 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7464 B.buildZExtOrTrunc(Inner, Cond);
7465 B.buildAdd(Dest, Inner, False);
7466 };
7467 return true;
7468 }
7469
7470 // select Cond, C1, C1+1 --> add (sext Cond), C1+1
7471 if (TrueValue + 1 == FalseValue) {
7472 MatchInfo = [=](MachineIRBuilder &B) {
7473 B.setInstrAndDebugLoc(*Select);
7474 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7475 B.buildSExtOrTrunc(Inner, Cond);
7476 B.buildAdd(Dest, Inner, False);
7477 };
7478 return true;
7479 }
7480
7481 // select Cond, Pow2, 0 --> (zext Cond) << log2(Pow2)
7482 if (TrueValue.isPowerOf2() && FalseValue.isZero()) {
7483 MatchInfo = [=](MachineIRBuilder &B) {
7484 B.setInstrAndDebugLoc(*Select);
7485 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7486 B.buildZExtOrTrunc(Inner, Cond);
7487 // The shift amount must be scalar.
7488 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7489 auto ShAmtC = B.buildConstant(ShiftTy, TrueValue.exactLogBase2());
7490 B.buildShl(Dest, Inner, ShAmtC, Flags);
7491 };
7492 return true;
7493 }
7494
7495 // select Cond, 0, Pow2 --> (zext (!Cond)) << log2(Pow2)
7496 if (FalseValue.isPowerOf2() && TrueValue.isZero()) {
7497 MatchInfo = [=](MachineIRBuilder &B) {
7498 B.setInstrAndDebugLoc(*Select);
7499 Register Not = MRI.createGenericVirtualRegister(CondTy);
7500 B.buildNot(Not, Cond);
7501 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7502 B.buildZExtOrTrunc(Inner, Not);
7503 // The shift amount must be scalar.
7504 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7505 auto ShAmtC = B.buildConstant(ShiftTy, FalseValue.exactLogBase2());
7506 B.buildShl(Dest, Inner, ShAmtC, Flags);
7507 };
7508 return true;
7509 }
7510
7511 // select Cond, -1, C --> or (sext Cond), C
7512 if (TrueValue.isAllOnes()) {
7513 MatchInfo = [=](MachineIRBuilder &B) {
7514 B.setInstrAndDebugLoc(*Select);
7515 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7516 B.buildSExtOrTrunc(Inner, Cond);
7517 B.buildOr(Dest, Inner, False, Flags);
7518 };
7519 return true;
7520 }
7521
7522 // select Cond, C, -1 --> or (sext (not Cond)), C
7523 if (FalseValue.isAllOnes()) {
7524 MatchInfo = [=](MachineIRBuilder &B) {
7525 B.setInstrAndDebugLoc(*Select);
7526 Register Not = MRI.createGenericVirtualRegister(CondTy);
7527 B.buildNot(Not, Cond);
7528 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7529 B.buildSExtOrTrunc(Inner, Not);
7530 B.buildOr(Dest, Inner, True, Flags);
7531 };
7532 return true;
7533 }
7534
7535 return false;
7536}
7537
7538// TODO: use knownbits to determine zeros
7539bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
7540 BuildFnTy &MatchInfo) const {
7541 uint32_t Flags = Select->getFlags();
7542 Register DstReg = Select->getReg(0);
7543 Register Cond = Select->getCondReg();
7544 Register True = Select->getTrueReg();
7545 Register False = Select->getFalseReg();
7546 LLT CondTy = MRI.getType(Select->getCondReg());
7547 LLT TrueTy = MRI.getType(Select->getTrueReg());
7548
7549 // Boolean or fixed vector of booleans.
7550 if (CondTy.isScalableVector() ||
7551 (CondTy.isFixedVector() &&
7552 CondTy.getElementType().getScalarSizeInBits() != 1) ||
7553 CondTy.getScalarSizeInBits() != 1)
7554 return false;
7555
7556 if (CondTy != TrueTy)
7557 return false;
7558
7559 // select Cond, Cond, F --> or Cond, F
7560 // select Cond, 1, F --> or Cond, F
7561 if ((Cond == True) || isOneOrOneSplat(True, /* AllowUndefs */ true)) {
7562 MatchInfo = [=](MachineIRBuilder &B) {
7563 B.setInstrAndDebugLoc(*Select);
7564 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7565 B.buildZExtOrTrunc(Ext, Cond);
7566 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7567 B.buildOr(DstReg, Ext, FreezeFalse, Flags);
7568 };
7569 return true;
7570 }
7571
7572 // select Cond, T, Cond --> and Cond, T
7573 // select Cond, T, 0 --> and Cond, T
7574 if ((Cond == False) || isZeroOrZeroSplat(False, /* AllowUndefs */ true)) {
7575 MatchInfo = [=](MachineIRBuilder &B) {
7576 B.setInstrAndDebugLoc(*Select);
7577 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7578 B.buildZExtOrTrunc(Ext, Cond);
7579 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7580 B.buildAnd(DstReg, Ext, FreezeTrue);
7581 };
7582 return true;
7583 }
7584
7585 // select Cond, T, 1 --> or (not Cond), T
7586 if (isOneOrOneSplat(False, /* AllowUndefs */ true)) {
7587 MatchInfo = [=](MachineIRBuilder &B) {
7588 B.setInstrAndDebugLoc(*Select);
7589 // First the not.
7590 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7591 B.buildNot(Inner, Cond);
7592 // Then an ext to match the destination register.
7593 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7594 B.buildZExtOrTrunc(Ext, Inner);
7595 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7596 B.buildOr(DstReg, Ext, FreezeTrue, Flags);
7597 };
7598 return true;
7599 }
7600
7601 // select Cond, 0, F --> and (not Cond), F
7602 if (isZeroOrZeroSplat(True, /* AllowUndefs */ true)) {
7603 MatchInfo = [=](MachineIRBuilder &B) {
7604 B.setInstrAndDebugLoc(*Select);
7605 // First the not.
7606 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7607 B.buildNot(Inner, Cond);
7608 // Then an ext to match the destination register.
7609 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7610 B.buildZExtOrTrunc(Ext, Inner);
7611 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7612 B.buildAnd(DstReg, Ext, FreezeFalse);
7613 };
7614 return true;
7615 }
7616
7617 return false;
7618}
7619
7621 BuildFnTy &MatchInfo) const {
7622 Register DstReg = MO.getReg();
7623 Register CondReg, True, False;
7624 if (!mi_match(DstReg, MRI,
7625 m_GISelect(m_Reg(CondReg), m_Reg(True), m_Reg(False))))
7626 return false;
7627
7628 CmpInst::Predicate Pred;
7629 Register CmpLHS, CmpRHS;
7630 if (!mi_match(CondReg, MRI,
7631 m_GICmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS))))
7632 return false;
7633
7634 LLT DstTy = MRI.getType(DstReg);
7635 if (DstTy.isPointerOrPointerVector())
7636 return false;
7637
7638 // We want to fold the icmp and replace the select.
7639 if (!MRI.hasOneNonDBGUse(CondReg))
7640 return false;
7641
7642 // We need a larger or smaller predicate for
7643 // canonicalization.
7644 if (CmpInst::isEquality(Pred))
7645 return false;
7646
7647 // We can swap CmpLHS and CmpRHS for higher hitrate.
7648 if (True == CmpRHS && False == CmpLHS) {
7649 std::swap(CmpLHS, CmpRHS);
7650 Pred = CmpInst::getSwappedPredicate(Pred);
7651 }
7652
7653 // (icmp X, Y) ? X : Y -> integer minmax.
7654 // see matchSelectPattern in ValueTracking.
7655 // Legality between G_SELECT and integer minmax can differ.
7656 if (True != CmpLHS || False != CmpRHS)
7657 return false;
7658
7659 switch (Pred) {
7660 case ICmpInst::ICMP_UGT:
7661 case ICmpInst::ICMP_UGE: {
7662 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy}))
7663 return false;
7664 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMax(DstReg, True, False); };
7665 return true;
7666 }
7667 case ICmpInst::ICMP_SGT:
7668 case ICmpInst::ICMP_SGE: {
7669 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy}))
7670 return false;
7671 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMax(DstReg, True, False); };
7672 return true;
7673 }
7674 case ICmpInst::ICMP_ULT:
7675 case ICmpInst::ICMP_ULE: {
7676 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy}))
7677 return false;
7678 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMin(DstReg, True, False); };
7679 return true;
7680 }
7681 case ICmpInst::ICMP_SLT:
7682 case ICmpInst::ICMP_SLE: {
7683 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy}))
7684 return false;
7685 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(DstReg, True, False); };
7686 return true;
7687 }
7688 default:
7689 return false;
7690 }
7691}
7692
7693// (neg (min/max x, (neg x))) --> (max/min x, (neg x))
7695 BuildFnTy &MatchInfo) const {
7696 assert(MI.getOpcode() == TargetOpcode::G_SUB);
7697 Register DestReg = MI.getOperand(0).getReg();
7698 LLT DestTy = MRI.getType(DestReg);
7699
7700 Register X;
7701 Register Sub0;
7702 auto NegPattern = m_all_of(m_Neg(m_DeferredReg(X)), m_Reg(Sub0));
7703 if (mi_match(DestReg, MRI,
7704 m_Neg(m_OneUse(m_any_of(m_GSMin(m_Reg(X), NegPattern),
7705 m_GSMax(m_Reg(X), NegPattern),
7706 m_GUMin(m_Reg(X), NegPattern),
7707 m_GUMax(m_Reg(X), NegPattern)))))) {
7708 MachineInstr *MinMaxMI;
7709 if (!mi_match(MI.getOperand(2).getReg(), MRI, m_MInstr(MinMaxMI)))
7710 return false;
7711 unsigned NewOpc = getInverseGMinMaxOpcode(MinMaxMI->getOpcode());
7712 if (isLegal({NewOpc, {DestTy}})) {
7713 MatchInfo = [=](MachineIRBuilder &B) {
7714 B.buildInstr(NewOpc, {DestReg}, {X, Sub0});
7715 };
7716 return true;
7717 }
7718 }
7719
7720 return false;
7721}
7722
7725
7726 if (tryFoldSelectOfConstants(Select, MatchInfo))
7727 return true;
7728
7729 if (tryFoldBoolSelectToLogic(Select, MatchInfo))
7730 return true;
7731
7732 return false;
7733}
7734
7735/// Fold (icmp Pred1 V1, C1) && (icmp Pred2 V2, C2)
7736/// or (icmp Pred1 V1, C1) || (icmp Pred2 V2, C2)
7737/// into a single comparison using range-based reasoning.
7738/// see InstCombinerImpl::foldAndOrOfICmpsUsingRanges.
7739bool CombinerHelper::tryFoldAndOrOrICmpsUsingRanges(
7740 GLogicalBinOp *Logic, BuildFnTy &MatchInfo) const {
7741 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpected xor");
7742 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
7743 Register DstReg = Logic->getReg(0);
7744 Register LHS = Logic->getLHSReg();
7745 Register RHS = Logic->getRHSReg();
7746 unsigned Flags = Logic->getFlags();
7747
7748 // We need an G_ICMP on the LHS register.
7749 GICmp *Cmp1 = getOpcodeDef<GICmp>(LHS, MRI);
7750 if (!Cmp1)
7751 return false;
7752
7753 // We need an G_ICMP on the RHS register.
7754 GICmp *Cmp2 = getOpcodeDef<GICmp>(RHS, MRI);
7755 if (!Cmp2)
7756 return false;
7757
7758 // We want to fold the icmps.
7759 if (!MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
7760 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)))
7761 return false;
7762
7763 APInt C1;
7764 APInt C2;
7765 std::optional<ValueAndVReg> MaybeC1 =
7767 if (!MaybeC1)
7768 return false;
7769 C1 = MaybeC1->Value;
7770
7771 std::optional<ValueAndVReg> MaybeC2 =
7773 if (!MaybeC2)
7774 return false;
7775 C2 = MaybeC2->Value;
7776
7777 Register R1 = Cmp1->getLHSReg();
7778 Register R2 = Cmp2->getLHSReg();
7779 CmpInst::Predicate Pred1 = Cmp1->getCond();
7780 CmpInst::Predicate Pred2 = Cmp2->getCond();
7781 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
7782 LLT CmpOperandTy = MRI.getType(R1);
7783
7784 if (CmpOperandTy.isPointer())
7785 return false;
7786
7787 // We build ands, adds, and constants of type CmpOperandTy.
7788 // They must be legal to build.
7789 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_AND, CmpOperandTy}) ||
7790 !isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, CmpOperandTy}) ||
7791 !isConstantLegalOrBeforeLegalizer(CmpOperandTy))
7792 return false;
7793
7794 // Look through add of a constant offset on R1, R2, or both operands. This
7795 // allows us to interpret the R + C' < C'' range idiom into a proper range.
7796 std::optional<APInt> Offset1;
7797 std::optional<APInt> Offset2;
7798 if (R1 != R2) {
7799 if (GAdd *Add = getOpcodeDef<GAdd>(R1, MRI)) {
7800 std::optional<ValueAndVReg> MaybeOffset1 =
7802 if (MaybeOffset1) {
7803 R1 = Add->getLHSReg();
7804 Offset1 = MaybeOffset1->Value;
7805 }
7806 }
7807 if (GAdd *Add = getOpcodeDef<GAdd>(R2, MRI)) {
7808 std::optional<ValueAndVReg> MaybeOffset2 =
7810 if (MaybeOffset2) {
7811 R2 = Add->getLHSReg();
7812 Offset2 = MaybeOffset2->Value;
7813 }
7814 }
7815 }
7816
7817 if (R1 != R2)
7818 return false;
7819
7820 // We calculate the icmp ranges including maybe offsets.
7821 ConstantRange CR1 = ConstantRange::makeExactICmpRegion(
7822 IsAnd ? ICmpInst::getInversePredicate(Pred1) : Pred1, C1);
7823 if (Offset1)
7824 CR1 = CR1.subtract(*Offset1);
7825
7826 ConstantRange CR2 = ConstantRange::makeExactICmpRegion(
7827 IsAnd ? ICmpInst::getInversePredicate(Pred2) : Pred2, C2);
7828 if (Offset2)
7829 CR2 = CR2.subtract(*Offset2);
7830
7831 bool CreateMask = false;
7832 APInt LowerDiff;
7833 std::optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
7834 if (!CR) {
7835 // We need non-wrapping ranges.
7836 if (CR1.isWrappedSet() || CR2.isWrappedSet())
7837 return false;
7838
7839 // Check whether we have equal-size ranges that only differ by one bit.
7840 // In that case we can apply a mask to map one range onto the other.
7841 LowerDiff = CR1.getLower() ^ CR2.getLower();
7842 APInt UpperDiff = (CR1.getUpper() - 1) ^ (CR2.getUpper() - 1);
7843 APInt CR1Size = CR1.getUpper() - CR1.getLower();
7844 if (!LowerDiff.isPowerOf2() || LowerDiff != UpperDiff ||
7845 CR1Size != CR2.getUpper() - CR2.getLower())
7846 return false;
7847
7848 CR = CR1.getLower().ult(CR2.getLower()) ? CR1 : CR2;
7849 CreateMask = true;
7850 }
7851
7852 if (IsAnd)
7853 CR = CR->inverse();
7854
7855 CmpInst::Predicate NewPred;
7856 APInt NewC, Offset;
7857 CR->getEquivalentICmp(NewPred, NewC, Offset);
7858
7859 // We take the result type of one of the original icmps, CmpTy, for
7860 // the to be build icmp. The operand type, CmpOperandTy, is used for
7861 // the other instructions and constants to be build. The types of
7862 // the parameters and output are the same for add and and. CmpTy
7863 // and the type of DstReg might differ. That is why we zext or trunc
7864 // the icmp into the destination register.
7865
7866 MatchInfo = [=](MachineIRBuilder &B) {
7867 if (CreateMask && Offset != 0) {
7868 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
7869 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
7870 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
7871 auto Add = B.buildAdd(CmpOperandTy, And, OffsetC, Flags);
7872 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7873 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
7874 B.buildZExtOrTrunc(DstReg, ICmp);
7875 } else if (CreateMask && Offset == 0) {
7876 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
7877 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
7878 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7879 auto ICmp = B.buildICmp(NewPred, CmpTy, And, NewCon);
7880 B.buildZExtOrTrunc(DstReg, ICmp);
7881 } else if (!CreateMask && Offset != 0) {
7882 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
7883 auto Add = B.buildAdd(CmpOperandTy, R1, OffsetC, Flags);
7884 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7885 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
7886 B.buildZExtOrTrunc(DstReg, ICmp);
7887 } else if (!CreateMask && Offset == 0) {
7888 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7889 auto ICmp = B.buildICmp(NewPred, CmpTy, R1, NewCon);
7890 B.buildZExtOrTrunc(DstReg, ICmp);
7891 } else {
7892 llvm_unreachable("unexpected configuration of CreateMask and Offset");
7893 }
7894 };
7895 return true;
7896}
7897
7898bool CombinerHelper::tryFoldLogicOfFCmps(GLogicalBinOp *Logic,
7899 BuildFnTy &MatchInfo) const {
7900 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpecte xor");
7901 Register DestReg = Logic->getReg(0);
7902 Register LHS = Logic->getLHSReg();
7903 Register RHS = Logic->getRHSReg();
7904 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
7905
7906 // We need a compare on the LHS register.
7907 GFCmp *Cmp1 = getOpcodeDef<GFCmp>(LHS, MRI);
7908 if (!Cmp1)
7909 return false;
7910
7911 // We need a compare on the RHS register.
7912 GFCmp *Cmp2 = getOpcodeDef<GFCmp>(RHS, MRI);
7913 if (!Cmp2)
7914 return false;
7915
7916 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
7917 LLT CmpOperandTy = MRI.getType(Cmp1->getLHSReg());
7918
7919 // We build one fcmp, want to fold the fcmps, replace the logic op,
7920 // and the fcmps must have the same shape.
7922 {TargetOpcode::G_FCMP, {CmpTy, CmpOperandTy}}) ||
7923 !MRI.hasOneNonDBGUse(Logic->getReg(0)) ||
7924 !MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
7925 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)) ||
7926 MRI.getType(Cmp1->getLHSReg()) != MRI.getType(Cmp2->getLHSReg()))
7927 return false;
7928
7929 CmpInst::Predicate PredL = Cmp1->getCond();
7930 CmpInst::Predicate PredR = Cmp2->getCond();
7931 Register LHS0 = Cmp1->getLHSReg();
7932 Register LHS1 = Cmp1->getRHSReg();
7933 Register RHS0 = Cmp2->getLHSReg();
7934 Register RHS1 = Cmp2->getRHSReg();
7935
7936 if (LHS0 == RHS1 && LHS1 == RHS0) {
7937 // Swap RHS operands to match LHS.
7938 PredR = CmpInst::getSwappedPredicate(PredR);
7939 std::swap(RHS0, RHS1);
7940 }
7941
7942 if (LHS0 == RHS0 && LHS1 == RHS1) {
7943 // We determine the new predicate.
7944 unsigned CmpCodeL = getFCmpCode(PredL);
7945 unsigned CmpCodeR = getFCmpCode(PredR);
7946 unsigned NewPred = IsAnd ? CmpCodeL & CmpCodeR : CmpCodeL | CmpCodeR;
7947 unsigned Flags = Cmp1->getFlags() | Cmp2->getFlags();
7948 MatchInfo = [=](MachineIRBuilder &B) {
7949 // The fcmp predicates fill the lower part of the enum.
7950 FCmpInst::Predicate Pred = static_cast<FCmpInst::Predicate>(NewPred);
7951 if (Pred == FCmpInst::FCMP_FALSE &&
7953 auto False = B.buildConstant(CmpTy, 0);
7954 B.buildZExtOrTrunc(DestReg, False);
7955 } else if (Pred == FCmpInst::FCMP_TRUE &&
7957 auto True =
7958 B.buildConstant(CmpTy, getICmpTrueVal(getTargetLowering(),
7959 CmpTy.isVector() /*isVector*/,
7960 true /*isFP*/));
7961 B.buildZExtOrTrunc(DestReg, True);
7962 } else { // We take the predicate without predicate optimizations.
7963 auto Cmp = B.buildFCmp(Pred, CmpTy, LHS0, LHS1, Flags);
7964 B.buildZExtOrTrunc(DestReg, Cmp);
7965 }
7966 };
7967 return true;
7968 }
7969
7970 return false;
7971}
7972
7974 GAnd *And = cast<GAnd>(&MI);
7975
7976 if (tryFoldAndOrOrICmpsUsingRanges(And, MatchInfo))
7977 return true;
7978
7979 if (tryFoldLogicOfFCmps(And, MatchInfo))
7980 return true;
7981
7982 return false;
7983}
7984
7986 GOr *Or = cast<GOr>(&MI);
7987
7988 if (tryFoldAndOrOrICmpsUsingRanges(Or, MatchInfo))
7989 return true;
7990
7991 if (tryFoldLogicOfFCmps(Or, MatchInfo))
7992 return true;
7993
7994 return false;
7995}
7996
7998 BuildFnTy &MatchInfo) const {
8000
8001 // Addo has no flags
8002 Register Dst = Add->getReg(0);
8003 Register Carry = Add->getReg(1);
8004 Register LHS = Add->getLHSReg();
8005 Register RHS = Add->getRHSReg();
8006 bool IsSigned = Add->isSigned();
8007 LLT DstTy = MRI.getType(Dst);
8008 LLT CarryTy = MRI.getType(Carry);
8009
8010 // Fold addo, if the carry is dead -> add, undef.
8011 if (MRI.use_nodbg_empty(Carry) &&
8012 isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}})) {
8013 MatchInfo = [=](MachineIRBuilder &B) {
8014 B.buildAdd(Dst, LHS, RHS);
8015 B.buildUndef(Carry);
8016 };
8017 return true;
8018 }
8019
8020 // Canonicalize constant to RHS.
8021 if (isConstantOrConstantVectorI(LHS) && !isConstantOrConstantVectorI(RHS)) {
8022 if (IsSigned) {
8023 MatchInfo = [=](MachineIRBuilder &B) {
8024 B.buildSAddo(Dst, Carry, RHS, LHS);
8025 };
8026 return true;
8027 }
8028 // !IsSigned
8029 MatchInfo = [=](MachineIRBuilder &B) {
8030 B.buildUAddo(Dst, Carry, RHS, LHS);
8031 };
8032 return true;
8033 }
8034
8035 std::optional<APInt> MaybeLHS = getConstantOrConstantSplatVector(LHS);
8036 std::optional<APInt> MaybeRHS = getConstantOrConstantSplatVector(RHS);
8037
8038 // Fold addo(c1, c2) -> c3, carry.
8039 if (MaybeLHS && MaybeRHS && isConstantLegalOrBeforeLegalizer(DstTy) &&
8041 bool Overflow;
8042 APInt Result = IsSigned ? MaybeLHS->sadd_ov(*MaybeRHS, Overflow)
8043 : MaybeLHS->uadd_ov(*MaybeRHS, Overflow);
8044 MatchInfo = [=](MachineIRBuilder &B) {
8045 B.buildConstant(Dst, Result);
8046 B.buildConstant(Carry, Overflow);
8047 };
8048 return true;
8049 }
8050
8051 // Fold (addo x, 0) -> x, no carry
8052 if (MaybeRHS && *MaybeRHS == 0 && isConstantLegalOrBeforeLegalizer(CarryTy)) {
8053 MatchInfo = [=](MachineIRBuilder &B) {
8054 B.buildCopy(Dst, LHS);
8055 B.buildConstant(Carry, 0);
8056 };
8057 return true;
8058 }
8059
8060 // Given 2 constant operands whose sum does not overflow:
8061 // uaddo (X +nuw C0), C1 -> uaddo X, C0 + C1
8062 // saddo (X +nsw C0), C1 -> saddo X, C0 + C1
8063 GAdd *AddLHS = getOpcodeDef<GAdd>(LHS, MRI);
8064 if (MaybeRHS && AddLHS && MRI.hasOneNonDBGUse(Add->getReg(0)) &&
8065 ((IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoSWrap)) ||
8066 (!IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoUWrap)))) {
8067 std::optional<APInt> MaybeAddRHS =
8068 getConstantOrConstantSplatVector(AddLHS->getRHSReg());
8069 if (MaybeAddRHS) {
8070 bool Overflow;
8071 APInt NewC = IsSigned ? MaybeAddRHS->sadd_ov(*MaybeRHS, Overflow)
8072 : MaybeAddRHS->uadd_ov(*MaybeRHS, Overflow);
8073 if (!Overflow && isConstantLegalOrBeforeLegalizer(DstTy)) {
8074 if (IsSigned) {
8075 MatchInfo = [=](MachineIRBuilder &B) {
8076 auto ConstRHS = B.buildConstant(DstTy, NewC);
8077 B.buildSAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
8078 };
8079 return true;
8080 }
8081 // !IsSigned
8082 MatchInfo = [=](MachineIRBuilder &B) {
8083 auto ConstRHS = B.buildConstant(DstTy, NewC);
8084 B.buildUAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
8085 };
8086 return true;
8087 }
8088 }
8089 };
8090
8091 // We try to combine addo to non-overflowing add.
8092 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}}) ||
8094 return false;
8095
8096 // We try to combine uaddo to non-overflowing add.
8097 if (!IsSigned) {
8098 ConstantRange CRLHS =
8099 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/false);
8100 ConstantRange CRRHS =
8101 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/false);
8102
8103 switch (CRLHS.unsignedAddMayOverflow(CRRHS)) {
8105 return false;
8107 MatchInfo = [=](MachineIRBuilder &B) {
8108 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
8109 B.buildConstant(Carry, 0);
8110 };
8111 return true;
8112 }
8115 MatchInfo = [=](MachineIRBuilder &B) {
8116 B.buildAdd(Dst, LHS, RHS);
8117 B.buildConstant(Carry, 1);
8118 };
8119 return true;
8120 }
8121 }
8122 return false;
8123 }
8124
8125 // We try to combine saddo to non-overflowing add.
8126
8127 // If LHS and RHS each have at least two sign bits, then there is no signed
8128 // overflow.
8129 if (VT->computeNumSignBits(RHS) > 1 && VT->computeNumSignBits(LHS) > 1) {
8130 MatchInfo = [=](MachineIRBuilder &B) {
8131 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8132 B.buildConstant(Carry, 0);
8133 };
8134 return true;
8135 }
8136
8137 ConstantRange CRLHS =
8138 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/true);
8139 ConstantRange CRRHS =
8140 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/true);
8141
8142 switch (CRLHS.signedAddMayOverflow(CRRHS)) {
8144 return false;
8146 MatchInfo = [=](MachineIRBuilder &B) {
8147 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8148 B.buildConstant(Carry, 0);
8149 };
8150 return true;
8151 }
8154 MatchInfo = [=](MachineIRBuilder &B) {
8155 B.buildAdd(Dst, LHS, RHS);
8156 B.buildConstant(Carry, 1);
8157 };
8158 return true;
8159 }
8160 }
8161
8162 return false;
8163}
8164
8166 BuildFnTy &MatchInfo) const {
8168 MatchInfo(Builder);
8169 Root->eraseFromParent();
8170}
8171
8173 int64_t Exponent) const {
8174 bool OptForSize = MI.getMF()->getFunction().hasOptSize();
8176}
8177
8179 int64_t Exponent) const {
8180 auto [Dst, Base] = MI.getFirst2Regs();
8181 LLT Ty = MRI.getType(Dst);
8182 int64_t ExpVal = Exponent;
8183
8184 if (ExpVal == 0) {
8185 Builder.buildFConstant(Dst, 1.0);
8186 MI.removeFromParent();
8187 return;
8188 }
8189
8190 if (ExpVal < 0)
8191 ExpVal = -ExpVal;
8192
8193 // We use the simple binary decomposition method from SelectionDAG ExpandPowI
8194 // to generate the multiply sequence. There are more optimal ways to do this
8195 // (for example, powi(x,15) generates one more multiply than it should), but
8196 // this has the benefit of being both really simple and much better than a
8197 // libcall.
8198 std::optional<SrcOp> Res;
8199 SrcOp CurSquare = Base;
8200 while (ExpVal > 0) {
8201 if (ExpVal & 1) {
8202 if (!Res)
8203 Res = CurSquare;
8204 else
8205 Res = Builder.buildFMul(Ty, *Res, CurSquare);
8206 }
8207
8208 CurSquare = Builder.buildFMul(Ty, CurSquare, CurSquare);
8209 ExpVal >>= 1;
8210 }
8211
8212 // If the original exponent was negative, invert the result, producing
8213 // 1/(x*x*x).
8214 if (Exponent < 0)
8215 Res = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0), *Res,
8216 MI.getFlags());
8217
8218 Builder.buildCopy(Dst, *Res);
8219 MI.eraseFromParent();
8220}
8221
8223 BuildFnTy &MatchInfo) const {
8224 // fold (A+C1)-C2 -> A+(C1-C2)
8225 const GSub *Sub = cast<GSub>(&MI);
8226 Register A, C1Reg;
8227 if (!mi_match(Sub->getLHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8228 return false;
8229
8230 if (!MRI.hasOneNonDBGUse(Sub->getLHSReg()))
8231 return false;
8232
8233 APInt C2 = getIConstantFromReg(Sub->getRHSReg(), MRI);
8234 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8235
8236 Register Dst = Sub->getReg(0);
8237 LLT DstTy = MRI.getType(Dst);
8238
8239 MatchInfo = [=](MachineIRBuilder &B) {
8240 auto Const = B.buildConstant(DstTy, C1 - C2);
8241 B.buildAdd(Dst, A, Const);
8242 };
8243
8244 return true;
8245}
8246
8248 BuildFnTy &MatchInfo) const {
8249 // fold C2-(A+C1) -> (C2-C1)-A
8250 const GSub *Sub = cast<GSub>(&MI);
8251 Register A, C1Reg;
8252 if (!mi_match(Sub->getRHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8253 return false;
8254
8255 if (!MRI.hasOneNonDBGUse(Sub->getRHSReg()))
8256 return false;
8257
8258 APInt C2 = getIConstantFromReg(Sub->getLHSReg(), MRI);
8259 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8260
8261 Register Dst = Sub->getReg(0);
8262 LLT DstTy = MRI.getType(Dst);
8263
8264 MatchInfo = [=](MachineIRBuilder &B) {
8265 auto Const = B.buildConstant(DstTy, C2 - C1);
8266 B.buildSub(Dst, Const, A);
8267 };
8268
8269 return true;
8270}
8271
8273 BuildFnTy &MatchInfo) const {
8274 // fold (A-C1)-C2 -> A-(C1+C2)
8275 const GSub *Sub1 = cast<GSub>(&MI);
8276 Register A, C1Reg;
8277 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8278 return false;
8279
8280 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8281 return false;
8282
8283 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8284 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8285
8286 Register Dst = Sub1->getReg(0);
8287 LLT DstTy = MRI.getType(Dst);
8288
8289 MatchInfo = [=](MachineIRBuilder &B) {
8290 auto Const = B.buildConstant(DstTy, C1 + C2);
8291 B.buildSub(Dst, A, Const);
8292 };
8293
8294 return true;
8295}
8296
8298 BuildFnTy &MatchInfo) const {
8299 // fold (C1-A)-C2 -> (C1-C2)-A
8300 const GSub *Sub1 = cast<GSub>(&MI);
8301 Register C1Reg, A;
8302 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(C1Reg), m_Reg(A))))
8303 return false;
8304
8305 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8306 return false;
8307
8308 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8309 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8310
8311 Register Dst = Sub1->getReg(0);
8312 LLT DstTy = MRI.getType(Dst);
8313
8314 MatchInfo = [=](MachineIRBuilder &B) {
8315 auto Const = B.buildConstant(DstTy, C1 - C2);
8316 B.buildSub(Dst, Const, A);
8317 };
8318
8319 return true;
8320}
8321
8323 BuildFnTy &MatchInfo) const {
8324 // fold ((A-C1)+C2) -> (A+(C2-C1))
8325 const GAdd *Add = cast<GAdd>(&MI);
8326 Register A, C1Reg;
8327 if (!mi_match(Add->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8328 return false;
8329
8330 if (!MRI.hasOneNonDBGUse(Add->getLHSReg()))
8331 return false;
8332
8333 APInt C2 = getIConstantFromReg(Add->getRHSReg(), MRI);
8334 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8335
8336 Register Dst = Add->getReg(0);
8337 LLT DstTy = MRI.getType(Dst);
8338
8339 MatchInfo = [=](MachineIRBuilder &B) {
8340 auto Const = B.buildConstant(DstTy, C2 - C1);
8341 B.buildAdd(Dst, A, Const);
8342 };
8343
8344 return true;
8345}
8346
8348 const MachineInstr &MI, BuildFnTy &MatchInfo) const {
8349 const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
8350
8351 if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
8352 return false;
8353
8354 LLT DstTy = MRI.getType(Unmerge->getReg(0));
8355
8356 // $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
8357 // $any:_(<8 x s16>) = G_ANYEXT $bv
8358 // $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
8359 //
8360 // ->
8361 //
8362 // $any:_(s16) = G_ANYEXT $bv[0]
8363 // $any1:_(s16) = G_ANYEXT $bv[1]
8364 // $any2:_(s16) = G_ANYEXT $bv[2]
8365 // $any3:_(s16) = G_ANYEXT $bv[3]
8366 // $any4:_(s16) = G_ANYEXT $bv[4]
8367 // $any5:_(s16) = G_ANYEXT $bv[5]
8368 // $any6:_(s16) = G_ANYEXT $bv[6]
8369 // $any7:_(s16) = G_ANYEXT $bv[7]
8370 // $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
8371 // $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7
8372
8373 // We want to unmerge into vectors.
8374 if (!DstTy.isFixedVector())
8375 return false;
8376
8377 Register AnySrcReg;
8378 if (!mi_match(Unmerge->getSourceReg(), MRI, m_GAnyExt(m_Reg(AnySrcReg))))
8379 return false;
8380
8381 GBuildVector *BV;
8382 if (mi_match(AnySrcReg, MRI, m_GBuildVector(BV))) {
8383 // G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR
8384
8385 if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
8386 return false;
8387
8388 // FIXME: check element types?
8389 if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
8390 return false;
8391
8392 LLT BigBvTy = MRI.getType(BV->getReg(0));
8393 LLT SmallBvTy = DstTy;
8394 LLT SmallBvElemenTy = SmallBvTy.getElementType();
8395
8397 {TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
8398 return false;
8399
8400 // We check the legality of scalar anyext.
8402 {TargetOpcode::G_ANYEXT,
8403 {SmallBvElemenTy, BigBvTy.getElementType()}}))
8404 return false;
8405
8406 MatchInfo = [=](MachineIRBuilder &B) {
8407 // Build into each G_UNMERGE_VALUES def
8408 // a small build vector with anyext from the source build vector.
8409 for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
8411 for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
8412 Register SourceArray =
8413 BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
8414 auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
8415 Ops.push_back(AnyExt.getReg(0));
8416 }
8417 B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
8418 };
8419 };
8420 return true;
8421 };
8422
8423 return false;
8424}
8425
8427 BuildFnTy &MatchInfo) const {
8428
8429 bool Changed = false;
8430 auto &Shuffle = cast<GShuffleVector>(MI);
8431 ArrayRef<int> OrigMask = Shuffle.getMask();
8432 SmallVector<int, 16> NewMask;
8433 const LLT SrcTy = MRI.getType(Shuffle.getSrc1Reg());
8434 const unsigned NumSrcElems = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
8435 const unsigned NumDstElts = OrigMask.size();
8436 for (unsigned i = 0; i != NumDstElts; ++i) {
8437 int Idx = OrigMask[i];
8438 if (Idx >= (int)NumSrcElems) {
8439 Idx = -1;
8440 Changed = true;
8441 }
8442 NewMask.push_back(Idx);
8443 }
8444
8445 if (!Changed)
8446 return false;
8447
8448 MatchInfo = [&, NewMask = std::move(NewMask)](MachineIRBuilder &B) {
8449 B.buildShuffleVector(MI.getOperand(0), MI.getOperand(1), MI.getOperand(2),
8450 std::move(NewMask));
8451 };
8452
8453 return true;
8454}
8455
8456static void commuteMask(MutableArrayRef<int> Mask, const unsigned NumElems) {
8457 const unsigned MaskSize = Mask.size();
8458 for (unsigned I = 0; I < MaskSize; ++I) {
8459 int Idx = Mask[I];
8460 if (Idx < 0)
8461 continue;
8462
8463 if (Idx < (int)NumElems)
8464 Mask[I] = Idx + NumElems;
8465 else
8466 Mask[I] = Idx - NumElems;
8467 }
8468}
8469
8471 BuildFnTy &MatchInfo) const {
8472
8473 auto &Shuffle = cast<GShuffleVector>(MI);
8474 // If any of the two inputs is already undef, don't check the mask again to
8475 // prevent infinite loop
8476 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(), MRI))
8477 return false;
8478
8479 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI))
8480 return false;
8481
8482 const LLT DstTy = MRI.getType(Shuffle.getReg(0));
8483 const LLT Src1Ty = MRI.getType(Shuffle.getSrc1Reg());
8485 {TargetOpcode::G_SHUFFLE_VECTOR, {DstTy, Src1Ty}}))
8486 return false;
8487
8488 ArrayRef<int> Mask = Shuffle.getMask();
8489 const unsigned NumSrcElems = Src1Ty.getNumElements();
8490
8491 bool TouchesSrc1 = false;
8492 bool TouchesSrc2 = false;
8493 const unsigned NumElems = Mask.size();
8494 for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
8495 if (Mask[Idx] < 0)
8496 continue;
8497
8498 if (Mask[Idx] < (int)NumSrcElems)
8499 TouchesSrc1 = true;
8500 else
8501 TouchesSrc2 = true;
8502 }
8503
8504 if (TouchesSrc1 == TouchesSrc2)
8505 return false;
8506
8507 Register NewSrc1 = Shuffle.getSrc1Reg();
8508 SmallVector<int, 16> NewMask(Mask);
8509 if (TouchesSrc2) {
8510 NewSrc1 = Shuffle.getSrc2Reg();
8511 commuteMask(NewMask, NumSrcElems);
8512 }
8513
8514 MatchInfo = [=, &Shuffle](MachineIRBuilder &B) {
8515 auto Undef = B.buildUndef(Src1Ty);
8516 B.buildShuffleVector(Shuffle.getReg(0), NewSrc1, Undef, NewMask);
8517 };
8518
8519 return true;
8520}
8521
8523 BuildFnTy &MatchInfo) const {
8524 const GSubCarryOut *Subo = cast<GSubCarryOut>(&MI);
8525
8526 Register Dst = Subo->getReg(0);
8527 Register LHS = Subo->getLHSReg();
8528 Register RHS = Subo->getRHSReg();
8529 Register Carry = Subo->getCarryOutReg();
8530 LLT DstTy = MRI.getType(Dst);
8531 LLT CarryTy = MRI.getType(Carry);
8532
8533 // Check legality before known bits.
8534 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy}}) ||
8536 return false;
8537
8538 ConstantRange KBLHS =
8539 ConstantRange::fromKnownBits(VT->getKnownBits(LHS),
8540 /* IsSigned=*/Subo->isSigned());
8541 ConstantRange KBRHS =
8542 ConstantRange::fromKnownBits(VT->getKnownBits(RHS),
8543 /* IsSigned=*/Subo->isSigned());
8544
8545 if (Subo->isSigned()) {
8546 // G_SSUBO
8547 switch (KBLHS.signedSubMayOverflow(KBRHS)) {
8549 return false;
8551 MatchInfo = [=](MachineIRBuilder &B) {
8552 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8553 B.buildConstant(Carry, 0);
8554 };
8555 return true;
8556 }
8559 MatchInfo = [=](MachineIRBuilder &B) {
8560 B.buildSub(Dst, LHS, RHS);
8561 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8562 /*isVector=*/CarryTy.isVector(),
8563 /*isFP=*/false));
8564 };
8565 return true;
8566 }
8567 }
8568 return false;
8569 }
8570
8571 // G_USUBO
8572 switch (KBLHS.unsignedSubMayOverflow(KBRHS)) {
8574 return false;
8576 MatchInfo = [=](MachineIRBuilder &B) {
8577 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
8578 B.buildConstant(Carry, 0);
8579 };
8580 return true;
8581 }
8584 MatchInfo = [=](MachineIRBuilder &B) {
8585 B.buildSub(Dst, LHS, RHS);
8586 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8587 /*isVector=*/CarryTy.isVector(),
8588 /*isFP=*/false));
8589 };
8590 return true;
8591 }
8592 }
8593
8594 return false;
8595}
8596
8597// Fold (ctlz (xor x, (sra x, bitwidth-1))) -> (add (ctls x), 1).
8598// Fold (ctlz (or (shl (xor x, (sra x, bitwidth-1)), 1), 1) -> (ctls x)
8600 BuildFnTy &MatchInfo) const {
8601 assert((CtlzMI.getOpcode() == TargetOpcode::G_CTLZ ||
8602 CtlzMI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON) &&
8603 "Expected G_CTLZ variant");
8604
8605 const Register Dst = CtlzMI.getOperand(0).getReg();
8606 Register Src = CtlzMI.getOperand(1).getReg();
8607
8608 LLT Ty = MRI.getType(Dst);
8609 LLT SrcTy = MRI.getType(Src);
8610
8611 if (!(Ty.isValid() && Ty.isScalar()))
8612 return false;
8613
8614 if (!LI)
8615 return false;
8616
8617 SmallVector<LLT, 2> QueryTypes = {Ty, SrcTy};
8618 LegalityQuery Query(TargetOpcode::G_CTLS, QueryTypes);
8619
8620 switch (LI->getAction(Query).Action) {
8621 default:
8622 return false;
8626 break;
8627 }
8628
8629 // Src = or(shl(V, 1), 1) -> Src=V; NeedAdd = False
8630 Register V;
8631 bool NeedAdd = true;
8632 if (mi_match(Src, MRI,
8634 m_SpecificICst(1))))) {
8635 NeedAdd = false;
8636 Src = V;
8637 }
8638
8639 unsigned BitWidth = Ty.getScalarSizeInBits();
8640
8641 Register X;
8642 if (!mi_match(Src, MRI,
8645 m_SpecificICst(BitWidth - 1)))))))
8646 return false;
8647
8648 MatchInfo = [=](MachineIRBuilder &B) {
8649 if (!NeedAdd) {
8650 B.buildCTLS(Dst, X);
8651 return;
8652 }
8653
8654 auto Ctls = B.buildCTLS(Ty, X);
8655 auto One = B.buildConstant(Ty, 1);
8656
8657 B.buildAdd(Dst, Ctls, One);
8658 };
8659
8660 return true;
8661}
8662
8663// Fold shr ( add ( ext X, ext Y ), 1 ) -> avgfloor ( x, y )
8664// Fold shr ( add ( ext X, ext Y, 1 ), 1 ) -> avgceil ( x, y )
8667 unsigned TargetOpc) const {
8668 assert((MI.getOpcode() == TargetOpcode::G_LSHR ||
8669 MI.getOpcode() == TargetOpcode::G_ASHR) &&
8670 "Expected G_LSHR/G_ASHR");
8671
8672 LLT XTy = MRI.getType(X);
8673 return XTy == MRI.getType(Y) && isLegal({TargetOpc, {XTy}});
8674}
8675
8677 assert((MI.getOpcode() == TargetOpcode::G_CTLZ ||
8678 MI.getOpcode() == TargetOpcode::G_CTTZ) &&
8679 "Expected count-zero opcode");
8680 switch (MI.getOpcode()) {
8681 case TargetOpcode::G_CTLZ:
8682 return TargetOpcode::G_CTLZ_ZERO_POISON;
8683 case TargetOpcode::G_CTTZ:
8684 return TargetOpcode::G_CTTZ_ZERO_POISON;
8685 default:
8686 llvm_unreachable("Unexpected count-zero opcode");
8687 }
8688}
8689
8691 if (!VT)
8692 return false;
8693
8694 unsigned ZPOpc = getCountZeroPoisonOpcode(MI);
8695 Register Src = MI.getOperand(1).getReg();
8696 if (!VT->isKnownNeverZero(Src))
8697 return false;
8698
8699 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
8700 LLT SrcTy = MRI.getType(Src);
8701 return isLegalOrBeforeLegalizer({ZPOpc, {DstTy, SrcTy}});
8702}
8703
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 unsigned getCountZeroPoisonOpcode(const MachineInstr &MI)
static LLT getMidVTForTruncRightShiftCombine(LLT ShiftTy, LLT TruncTy)
static bool canFoldInAddressingMode(GLoadStore *MI, const TargetLowering &TLI, MachineRegisterInfo &MRI)
Return true if 'MI' is a load or a store that may be fold it's address operand into the load / store ...
static unsigned littleEndianByteAt(const unsigned ByteWidth, const unsigned I)
static Register buildLogBase2(Register V, MachineIRBuilder &MIB)
Determines the LogBase2 value for a non-null input value using the transform: LogBase2(V) = (EltBits ...
This contains common combine transformations that may be used in a combine pass,or by the target else...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
#define _
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
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
bool isNaN() const
Definition APFloat.h:1581
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
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 matchCountZeroToZeroPoison(MachineInstr &MI) const
LLVM_ABI bool matchFoldC2MinusAPlusC1(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchLoadOrCombine(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match expression trees of the form.
LLVM_ABI const RegisterBank * getRegBank(Register Reg) const
Get the register bank of Reg.
LLVM_ABI bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2) const
Return true if MOP1 and MOP2 are register operands are defined by equivalent instructions.
LLVM_ABI void applyUDivOrURemByConst(MachineInstr &MI) const
LLVM_ABI bool matchConstantFoldBinOp(MachineInstr &MI, APInt &MatchInfo) const
Do constant folding when opportunities are exposed after MIR building.
LLVM_ABI void applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) const
LLVM_ABI bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchCtls(MachineInstr &CtlzMI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchSelectSameVal(MachineInstr &MI) const
Optimize (cond ? x : x) -> x.
LLVM_ABI bool matchAddEToAddO(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: (G_*ADDE x, y, 0) -> (G_*ADDO x, y) (G_*SUBE x, y, 0) -> (G_*SUBO x, y)
LLVM_ABI bool matchReassocConstantInnerRHS(GPtrAdd &MI, MachineInstr *RHS, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchAVG(MachineInstr &MI, MachineRegisterInfo &MRI, Register X, Register Y, unsigned TargetOpc) const
LLVM_ABI bool matchBitfieldExtractFromShr(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: shr (shl x, n), k -> sbfx/ubfx x, pos, width.
LLVM_ABI bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchTruncSSatU(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI void applySimplifyURemByPow2(MachineInstr &MI) const
Combine G_UREM x, (known power of 2) to an add and bitmasking.
LLVM_ABI bool matchCombineUnmergeZExtToZExt(MachineInstr &MI) const
Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0.
LLVM_ABI bool matchPtrAddZero(MachineInstr &MI) const
}
const TargetInstrInfo * TII
LLVM_ABI void applyCombineConcatVectors(MachineInstr &MI, SmallVector< Register > &Ops) const
Replace MI with a flattened build_vector with Ops or an implicit_def if Ops is empty.
LLVM_ABI void applyXorOfAndWithSameReg(MachineInstr &MI, std::pair< Register, Register > &MatchInfo) const
LLVM_ABI bool canCombineFMadOrFMA(MachineInstr &MI, bool &AllowFusionGlobally, bool &HasFMAD, bool &Aggressive, bool CanReassociate=false) const
LLVM_ABI bool matchFoldAPlusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const
LLVM_ABI void applyCombineUnmergeConstant(MachineInstr &MI, SmallVectorImpl< APInt > &Csts) const
LLVM_ABI bool matchShiftsTooBig(MachineInstr &MI, std::optional< int64_t > &MatchInfo) const
Match shifts greater or equal to the range (the bitwidth of the result datatype, or the effective bit...
LLVM_ABI bool matchCombineFAddFpExtFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) (fadd (fpext (fmul x,...
LLVM_ABI bool matchCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const
LLVM_ABI void applyCombineShuffleConcat(MachineInstr &MI, SmallVector< Register > &Ops) const
Replace MI with a flattened build_vector with Ops or an implicit_def if Ops is empty.
LLVM_ABI void replaceSingleDefInstWithReg(MachineInstr &MI, Register Replacement) const
Delete MI and replace all of its uses with Replacement.
LLVM_ABI void applyCombineShuffleToBuildVector(MachineInstr &MI) const
Replace MI with a build_vector.
LLVM_ABI bool matchCombineExtractedVectorLoad(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine a G_EXTRACT_VECTOR_ELT of a load into a narrowed load.
LLVM_ABI void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const
MachineRegisterInfo::replaceRegWith() and inform the observer of the changes.
LLVM_ABI void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, Register ToReg) const
Replace a single register operand with a new register and inform the observer of the changes.
LLVM_ABI void applyCombineMemCpyFamily(MachineInstr &MI, MemCpyFamilyLoweringInfo &MatchInfo) const
LLVM_ABI bool matchReassocCommBinOp(MachineInstr &MI, BuildFnTy &MatchInfo) const
Reassociate commutative binary operations like G_ADD.
LLVM_ABI void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
LLVM_ABI bool matchCommuteConstantToRHS(MachineInstr &MI) const
Match constant LHS ops that should be commuted.
LLVM_ABI 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 void applyFsubToFneg(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI bool matchConstantLargerBitWidth(MachineInstr &MI, unsigned ConstIdx) const
Checks if constant at ConstIdx is larger than MI 's bitwidth.
LLVM_ABI void applyCombineCopy(MachineInstr &MI) const
LLVM_ABI bool 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 matchRedundantNegOperands(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd x, fneg(y)) -> (fsub x, y) (fadd fneg(x), y) -> (fsub y, x) (fsub x,...
LLVM_ABI bool matchCombineLoadWithAndMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match (and (load x), mask) -> zextload x.
LLVM_ABI bool matchCombineFAddFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fmul x, y), z) -> (fma x, y, z) (fadd (fmul x, y), z) -> (fmad x,...
LLVM_ABI bool matchCombineCopy(MachineInstr &MI) const
LLVM_ABI bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const
LLVM_ABI void applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const
LLVM_ABI bool matchXorOfAndWithSameReg(MachineInstr &MI, std::pair< Register, Register > &MatchInfo) const
Fold (xor (and x, y), y) -> (and (not x), y) {.
LLVM_ABI bool matchCombineShuffleVector(MachineInstr &MI, SmallVectorImpl< Register > &Ops) const
Check if the G_SHUFFLE_VECTOR MI can be replaced by a concat_vectors.
LLVM_ABI void replaceInstWithFConstant(MachineInstr &MI, double C) const
Replace an instruction with a G_FCONSTANT with value C.
LLVM_ABI bool matchFunnelShiftToRotate(MachineInstr &MI) const
Match an FSHL or FSHR that can be combined to a ROTR or ROTL rotate.
LLVM_ABI bool matchOrShiftToFunnelShift(MachineInstr &MI, bool AllowScalarConstants, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchRedundantSExtInReg(MachineInstr &MI) const
LLVM_ABI void replaceOpcodeWith(MachineInstr &FromMI, unsigned ToOpcode) const
Replace the opcode in instruction with a new opcode and inform the observer of the changes.
LLVM_ABI void applyFunnelShiftConstantModulo(MachineInstr &MI) const
Replaces the shift amount in MI with ShiftAmt % BW.
LLVM_ABI bool matchFoldC1Minus2MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applyCombineShlOfExtend(MachineInstr &MI, const RegisterImmPair &MatchData) const
LLVM_ABI void applyUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B, bool IsPreLegalize, GISelValueTracking *VT=nullptr, MachineDominatorTree *MDT=nullptr, const LegalizerInfo *LI=nullptr)
LLVM_ABI bool matchShuffleDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
Turn shuffle a, b, mask -> shuffle undef, b, mask iff mask does not reference a.
LLVM_ABI bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const
Transform a multiply by a power-of-2 value to a left shift.
LLVM_ABI void applyCombineShuffleVector(MachineInstr &MI, ArrayRef< Register > Ops) const
Replace MI with a concat_vectors with Ops.
LLVM_ABI bool matchCombineUnmergeUndef(MachineInstr &MI, std::function< void(MachineIRBuilder &)> &MatchInfo) const
Transform G_UNMERGE G_IMPLICIT_DEF -> G_IMPLICIT_DEF, G_IMPLICIT_DEF, ...
LLVM_ABI void applyFoldBinOpIntoSelect(MachineInstr &MI, const unsigned &SelectOpNo) const
SelectOperand is the operand in binary operator MI that is the select to fold.
LLVM_ABI bool matchFoldAMinusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applyCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const
LLVM_ABI bool matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: (G_UMULO x, 2) -> (G_UADDO x, x) (G_SMULO x, 2) -> (G_SADDO x, x)
LLVM_ABI bool matchCombineShuffleConcat(MachineInstr &MI, SmallVector< Register > &Ops) const
LLVM_ABI void applySextInRegOfLoad(MachineInstr &MI, std::tuple< Register, unsigned > &MatchInfo) const
LLVM_ABI bool 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
LLVM_ABI bool matchUndefStore(MachineInstr &MI) const
Return true if a G_STORE instruction MI is storing an undef value.
MachineRegisterInfo & MRI
LLVM_ABI void applyCombineP2IToI2P(MachineInstr &MI, Register &Reg) const
Transform PtrToInt(IntToPtr(x)) to x.
LLVM_ABI void applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const
LLVM_ABI bool matchConstantFPOp(const MachineOperand &MOP, double C) const
Return true if MOP is defined by a G_FCONSTANT or splat with a value exactly equal to C.
LLVM_ABI MachineInstr * buildUDivOrURemUsingMul(MachineInstr &MI) const
Given an G_UDIV MI or G_UREM MI expressing a divide by constant, return an expression that implements...
LLVM_ABI void applyExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const
LLVM_ABI bool matchFoldBinOpIntoSelect(MachineInstr &MI, unsigned &SelectOpNo) const
Push a binary operator through a select on constants.
LLVM_ABI bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount) const
LLVM_ABI bool tryCombineExtendingLoads(MachineInstr &MI) const
If MI is extend that consumes the result of a load, try to combine it.
LLVM_ABI bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const
LLVM_ABI bool matchBuildVectorIdentityFold(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI bool matchBitfieldExtractFromShrAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: shr (and x, n), k -> ubfx x, pos, width.
LLVM_ABI void applyTruncSSatS(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI bool matchConstantFoldCastOp(MachineInstr &MI, APInt &MatchInfo) const
Do constant folding when opportunities are exposed after MIR building.
LLVM_ABI void applyRotateOutOfRange(MachineInstr &MI) const
LLVM_ABI bool matchReassocFoldConstantsInSubTree(GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchHoistLogicOpWithSameOpcodeHands(MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const
Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
LLVM_ABI bool matchBitfieldExtractFromAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: and (lshr x, cst), mask -> ubfx x, cst, width.
LLVM_ABI bool matchBitfieldExtractFromSExtInReg(MachineInstr &MI, BuildFnTy &MatchInfo) const
Form a G_SBFX from a G_SEXT_INREG fed by a right shift.
LLVM_ABI bool 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 matchFsubToFneg(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI bool matchRotateOutOfRange(MachineInstr &MI) const
LLVM_ABI void applyExpandFPowI(MachineInstr &MI, int64_t Exponent) const
Expands FPOWI into a series of multiplications and a division if the exponent is negative.
LLVM_ABI void setRegBank(Register Reg, const RegisterBank *RegBank) const
Set the register bank of Reg.
LLVM_ABI bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx) const
Return true if a G_SELECT instruction MI has a constant comparison.
LLVM_ABI bool matchCommuteFPConstantToRHS(MachineInstr &MI) const
Match constant LHS FP ops that should be commuted.
LLVM_ABI void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const
LLVM_ABI bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info) const
LLVM_ABI bool matchRedundantOr(MachineInstr &MI, Register &Replacement) const
LLVM_ABI void applyTruncSSatU(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI void applySimplifySRemByPow2(MachineInstr &MI) const
Combine G_SREM x, (+/-2^k) to a bias-and-mask sequence.
LLVM_ABI bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fpext (fneg (fmul x, y))), z) -> (fneg (fma (fpext x), (fpext y),...
LLVM_ABI bool matchTruncBuildVectorFold(MachineInstr &MI, Register &MatchInfo) const
LLVM_ABI void applyCombineTruncOfShift(MachineInstr &MI, std::pair< MachineInstr *, LLT > &MatchInfo) const
const LegalizerInfo * LI
LLVM_ABI void applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const
LLVM_ABI void applyCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, Register &UnmergeSrc) const
LLVM_ABI bool matchUMulHToLShr(MachineInstr &MI) const
MachineDominatorTree * MDT
LLVM_ABI void applyFunnelShiftToRotate(MachineInstr &MI) const
LLVM_ABI bool matchSimplifySelectToMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applyRepeatedFPDivisor(SmallVector< MachineInstr * > &MatchInfo) const
LLVM_ABI bool matchTruncUSatUToFPTOUISat(MachineInstr &MI, MachineInstr &SrcMI) const
const RegisterBankInfo * RBI
LLVM_ABI bool matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: (G_*MULO x, 0) -> 0 + no carry out.
GISelValueTracking * VT
LLVM_ABI bool matchBinopWithNeg(MachineInstr &MI, BuildFnTy &MatchInfo) const
Fold a bitwiseop (~b +/- c) -> a bitwiseop ~(b -/+ c)
LLVM_ABI bool matchCombineUnmergeConstant(MachineInstr &MI, SmallVectorImpl< APInt > &Csts) const
Transform G_UNMERGE Constant -> Constant1, Constant2, ...
LLVM_ABI void applyShiftOfShiftedLogic(MachineInstr &MI, ShiftOfShiftedLogic &MatchInfo) const
const TargetRegisterInfo * TRI
LLVM_ABI bool matchRedundantAnd(MachineInstr &MI, Register &Replacement) const
LLVM_ABI bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI) const
Returns true if DefMI dominates UseMI.
GISelChangeObserver & Observer
LLVM_ABI void applyBuildFn(MachineInstr &MI, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
LLVM_ABI bool matchCombineTruncOfShift(MachineInstr &MI, std::pair< MachineInstr *, LLT > &MatchInfo) const
Transform trunc (shl x, K) to shl (trunc x), K if K < VT.getScalarSizeInBits().
LLVM_ABI bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize, unsigned &ShiftVal) const
Reduce a shift by a constant to an unmerge and a shift on a half sized type.
LLVM_ABI bool matchUDivOrURemByConst(MachineInstr &MI) const
Combine G_UDIV or G_UREM by constant into a multiply by magic constant.
LLVM_ABI bool matchAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine ands.
LLVM_ABI bool matchSuboCarryOut(const MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchConstantFoldFMA(MachineInstr &MI, ConstantFP *&MatchInfo) const
Constant fold G_FMA/G_FMAD.
LLVM_ABI bool matchCombineFSubFNegFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z)) (fsub (fneg (fmul,...
LLVM_ABI bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg) const
Transform zext(trunc(x)) to x.
LLVM_ABI void applyCountZeroToZeroPoison(MachineInstr &MI) const
LLVM_ABI void applyLshrOfTruncOfLshr(MachineInstr &MI, LshrOfTruncOfLshr &MatchInfo) const
LLVM_ABI bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0) const
Optimize memcpy intrinsics et al, e.g.
LLVM_ABI bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applySDivOrSRemByConst(MachineInstr &MI) const
LLVM_ABI bool matchCombineMemCpyFamily(MachineInstr &MI, MemCpyFamilyLoweringInfo &MatchInfo, unsigned MaxLen=0) const
LLVM_ABI MachineInstr * buildSDivOrSRemUsingMul(MachineInstr &MI) const
Given an G_SDIV MI or G_SREM MI expressing a signed divide by constant, return an expression that imp...
LLVM_ABI bool isLegalOrHasWidenScalar(const LegalityQuery &Query) const
LLVM_ABI bool matchSubAddSameReg(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform: (x + y) - y -> x (x + y) - x -> y x - (y + x) -> 0 - y x - (x + z) -> 0 - z.
LLVM_ABI bool matchReassocConstantInnerLHS(GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchOverlappingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0.
LLVM_ABI bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg) const
Transform anyext(trunc(x)) to x.
LLVM_ABI void applyExtractAllEltsFromBuildVector(MachineInstr &MI, SmallVectorImpl< std::pair< Register, MachineInstr * > > &MatchInfo) const
MachineIRBuilder & Builder
LLVM_ABI void applyCommuteBinOpOperands(MachineInstr &MI) const
LLVM_ABI void replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx) const
Delete MI and replace all of its uses with its OpIdx-th operand.
LLVM_ABI const MachineFunction & getMachineFunction() const
LLVM_ABI bool matchCombineBuildVectorOfBitcast(MachineInstr &MI, SmallVector< Register > &Ops) const
Combine G_BUILD_VECTOR(G_UNMERGE(G_BITCAST), Undef) to G_BITCAST(G_BUILD_VECTOR(.....
LLVM_ABI bool matchCombineFAddFpExtFMulToFMadOrFMAAggressive(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchSDivOrSRemByConst(MachineInstr &MI) const
Combine G_SDIV or G_SREM by constant into a multiply by magic constant.
LLVM_ABI void applyOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond) const
LLVM_ABI void applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal) const
LLVM_ABI bool matchFPowIExpansion(MachineInstr &MI, int64_t Exponent) const
Match FPOWI if it's safe to extend it into a series of multiplications.
LLVM_ABI void applyCombineInsertVecElts(MachineInstr &MI, SmallVectorImpl< Register > &MatchInfo) const
LLVM_ABI bool matchCombineUnmergeMergeToPlainValues(MachineInstr &MI, SmallVectorImpl< Register > &Operands) const
Transform <ty,...> G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z.
LLVM_ABI void applyCombineUnmergeMergeToPlainValues(MachineInstr &MI, SmallVectorImpl< Register > &Operands) const
LLVM_ABI bool matchAshrShlToSextInreg(MachineInstr &MI, std::tuple< Register, int64_t > &MatchInfo) const
Match ashr (shl x, C), C -> sext_inreg (C)
LLVM_ABI void applyCombineUnmergeZExtToZExt(MachineInstr &MI) const
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
const APFloat & getValue() const
Definition Constants.h:464
const APFloat & getValueAPF() const
Definition Constants.h:463
This class represents a range of values.
LLVM_ABI std::optional< ConstantRange > exactUnionWith(const ConstantRange &CR) const
Union the two ranges and return the result if it can be represented exactly, otherwise return std::nu...
LLVM_ABI ConstantRange subtract(const APInt &CI) const
Subtract the specified constant from the endpoints of this constant range.
static LLVM_ABI ConstantRange fromKnownBits(const KnownBits &Known, bool IsSigned)
Initialize a range based on a known bits constraint.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI OverflowResult unsignedSubMayOverflow(const ConstantRange &Other) const
Return whether unsigned sub of the two ranges always/never overflows.
LLVM_ABI OverflowResult unsignedAddMayOverflow(const ConstantRange &Other) const
Return whether unsigned add of the two ranges always/never overflows.
LLVM_ABI bool isWrappedSet() const
Return true if this set wraps around the unsigned domain.
const APInt & getUpper() const
Return the upper value for this range.
static LLVM_ABI ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, const APInt &Other)
Produce the exact range such that all values in the returned range satisfy the given predicate with a...
LLVM_ABI OverflowResult signedAddMayOverflow(const ConstantRange &Other) const
Return whether signed add of the two ranges always/never overflows.
@ AlwaysOverflowsHigh
Always overflows in the direction of signed/unsigned max value.
@ AlwaysOverflowsLow
Always overflows in the direction of signed/unsigned min value.
@ MayOverflow
May or may not overflow.
LLVM_ABI OverflowResult signedSubMayOverflow(const ConstantRange &Other) const
Return whether signed sub of the two ranges always/never overflows.
This is an important base class in LLVM.
Definition Constant.h:43
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
bool isBigEndian() const
Definition DataLayout.h:218
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:285
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:258
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:348
unsigned size() const
Definition DenseMap.h:207
iterator end()
Definition DenseMap.h:176
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.
Register getCondReg() const
Represents overflowing sub operations.
Represents an integer subtraction.
Represents a G_UNMERGE_VALUES.
unsigned getNumDefs() const
Returns the number of def registers.
Register getSourceReg() const
Get the unmerge source register.
Represents a G_ZEXTLOAD.
Represents a zext.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr ElementCount getElementCount() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
constexpr bool isFixedVector() const
Returns true if the LLT is a fixed vector.
static LLT integer(unsigned SizeInBits)
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, Register Dst, Register Src, uint64_t KnownLen, Align Alignment, bool DstAlignCanChange, ArrayRef< LLT > MemOps)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
TypeSize getValue() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Helper class to build MachineInstr.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildCTLZ(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTLZ Op0, Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI bool isDereferenceableInvariantLoad() const
Return true if this load instruction never traps and points to a memory location whose value doesn't ...
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
mop_range uses()
Returns all operands which may be register uses.
MachineOperand * findRegisterUseOperand(Register Reg, const TargetRegisterInfo *TRI, bool isKill=false)
Wrapper for findRegisterUseOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
LLT getMemoryType() const
Return the memory type of the memory reference.
unsigned getAddrSpace() const
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
const MachinePointerInfo & getPointerInfo() const
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setMBB(MachineBasicBlock *MBB)
void setPredicate(unsigned Predicate)
Register getReg() const
getReg - Returns the register number.
unsigned getPredicate() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
static use_instr_nodbg_iterator use_instr_nodbg_end()
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
This class implements the register bank concept.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
Definition SetVector.h:268
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallBitVector & set()
bool all() const
Returns true if all bits are set.
size_type size() const
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)
BinaryOp_match< LHS, RHS, TargetOpcode::G_FADD, true > m_GFAdd(const LHS &L, const RHS &R)
GInstrBind< GUnmerge > m_GUnmerge(GUnmerge *&Inst)
Instruction binders for ops with no operand-form matcher (constant-immediate or variadic-source ops).
MMORef m_MMO(const MachineMemOperand *&MMO)
BinaryOp_match< LHS, RHS, TargetOpcode::G_FSUB, false > m_GFSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ASHR, false > m_GAShr(const LHS &L, const RHS &R)
TernaryOp_match< Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT > m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
Or< Preds... > m_any_of(Preds &&... preds)
SpecificConstantOrSplatMatch m_SpecificICstOrSplat(const APInt &RequestedValue)
Matches a RequestedValue constant or a constant splat of RequestedValue.
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_BUILD_VECTOR_TRUNC, false > m_GBuildVectorTrunc(const LHS &L, const RHS &R)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
UnaryOp_match< SrcTy, TargetOpcode::G_FNEG > m_GFNeg(const SrcTy &Src)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP, true > m_c_GICmp(const Pred &P, const LHS &L, const RHS &R)
G_ICMP matcher that also matches commuted compares.
LoadOp_match< GAnyLoad, PtrP > m_GAnyLoad(const PtrP &Ptr)
TernaryOp_match< Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_INSERT_VECTOR_ELT > m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
And< Preds... > m_all_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SMIN, true > m_GSMin(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, TargetOpcode::G_FMUL, true > m_GFMul(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SMAX, true > m_GSMax(const LHS &L, const RHS &R)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP > m_GFCmp(const Pred &P, const LHS &L, const RHS &R)
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
Not(const Pred &P) -> Not< Pred >
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h: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:1972
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h: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 MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
Definition Utils.cpp:1539
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:497
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
Definition Utils.cpp:1572
LLVM_ABI bool isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector, bool IsFP)
Returns true if given the TargetLowering's boolean contents information, the value Val contains a tru...
Definition Utils.cpp:1604
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI std::optional< APInt > ConstantFoldBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
Definition Utils.cpp:662
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h: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:2139
LLVM_ABI unsigned getInverseGMinMaxOpcode(unsigned MinMaxOpc)
Returns the inverse opcode of MinMaxOpc, which is a generic min/max opcode like G_SMIN.
Definition Utils.cpp:282
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
LLVM_ABI std::optional< FPValueAndVReg > getFConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_FCONSTANT returns it...
Definition Utils.cpp:450
constexpr unsigned BitWidth
LLVM_ABI int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP)
Returns an integer representing true, as defined by the TargetBooleanContents.
Definition Utils.cpp:1629
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h: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:201
LLVM_ABI SmallVector< APInt > ConstantFoldUnaryIntOp(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI)
Tries to constant fold a unary integer operation (G_CTLZ, G_CTTZ, G_CTPOP and their _ZERO_POISON vari...
Definition Utils.cpp:935
LLVM_ABI bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, bool OrZero=false, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return true if the given value is known to have exactly one bit set when defined.
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:504
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
unsigned getFCmpCode(CmpInst::Predicate CC)
Similar to getICmpCode but for FCmpInst.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Simple struct used to hold a Register value and the instruction which defines it.
Definition Utils.h: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...