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