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