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