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