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