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