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