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 BuildFnTy &MatchInfo) const {
5900 Register Dst = MI.getOperand(0).getReg();
5901 Register LHS = MI.getOperand(1).getReg();
5902 Register RHS = MI.getOperand(2).getReg();
5903 Register Base, Shift;
5904 if (!mi_match(RHS, MRI, m_GShl(m_Reg(Base), m_Reg(Shift))))
5905 return false;
5906
5907 if (!matchUnaryPredicate(MRI, Base, [](const Constant *C) {
5909 return CI && CI->getValue().isPowerOf2();
5910 }))
5911 return false;
5912
5913 LLT Ty = MRI.getType(Dst);
5914 LLT ShiftTy = MRI.getType(Shift);
5915 // The shift type must be able to represent every valid shift amount.
5916 if (ShiftTy.getScalarSizeInBits() < Log2_64_Ceil(Ty.getScalarSizeInBits()))
5917 return false;
5918 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_CTTZ, {ShiftTy, Ty}}) ||
5919 !isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {ShiftTy, ShiftTy}}) ||
5920 !isLegalOrBeforeLegalizer({TargetOpcode::G_LSHR, {Ty, ShiftTy}}))
5921 return false;
5922
5923 unsigned Flags =
5925 MatchInfo = [=](MachineIRBuilder &B) {
5926 auto Log2 = B.buildCTTZ(ShiftTy, Base);
5927 auto Amount = B.buildAdd(ShiftTy, Shift, Log2);
5928 B.buildLShr(Dst, LHS, Amount, Flags);
5929 };
5930 return true;
5931}
5932
5934 MachineInstr &MI, unsigned UnsignedOpcode) const {
5935 Register Dst = MI.getOperand(0).getReg();
5936 Register LHS = MI.getOperand(1).getReg();
5937 Register RHS = MI.getOperand(2).getReg();
5938 if (!VT || !VT->signBitIsZero(LHS) || !VT->signBitIsZero(RHS))
5939 return false;
5940
5941 LLT Ty = MRI.getType(Dst);
5942 return isLegalOrBeforeLegalizer({UnsignedOpcode, {Ty}});
5943}
5944
5946 assert(MI.getOpcode() == TargetOpcode::G_SREM && "Expected SREM");
5947 auto &SRem = cast<GBinOp>(MI);
5948 Register Dst = SRem.getReg(0);
5949 Register LHS = SRem.getLHSReg();
5950 Register RHS = SRem.getRHSReg();
5951 LLT Ty = MRI.getType(Dst);
5953
5954 // Effectively we want to lower G_SREM %lhs, %rhs, where %rhs is +/- a power
5955 // of 2, to the following branch-free bias-and-mask version:
5956 //
5957 // %abs = G_ABS %rhs
5958 // %mask = G_SUB %abs, 1
5959 // %sign = G_ASHR %lhs, $(bitwidth - 1)
5960 // %bias = G_AND %sign, %mask
5961 // %biased = G_ADD %lhs, %bias
5962 // %masked = G_AND %biased, %mask
5963 // %res = G_SUB %masked, %bias
5964 //
5965 // The bias adds (|%rhs| - 1) for negative %lhs, correcting rounding towards
5966 // zero (instead of towards -inf that a plain mask would give). Constant
5967 // divisors collapse %mask to a single G_CONSTANT via the CSEMIRBuilder folds
5968 // for G_ABS and G_SUB.
5969
5970 unsigned BitWidth = Ty.getScalarSizeInBits();
5971 auto AbsRHS = Builder.buildAbs(Ty, RHS);
5972 auto Mask = Builder.buildSub(Ty, AbsRHS, Builder.buildConstant(Ty, 1));
5973 auto BWMinusOne = Builder.buildConstant(ShiftAmtTy, BitWidth - 1);
5974 auto Sign = Builder.buildAShr(Ty, LHS, BWMinusOne);
5975 auto Bias = Builder.buildAnd(Ty, Sign, Mask);
5976 auto Biased = Builder.buildAdd(Ty, LHS, Bias);
5977 auto Masked = Builder.buildAnd(Ty, Biased, Mask);
5978 Builder.buildSub(Dst, Masked, Bias);
5979 MI.eraseFromParent();
5980}
5981
5983 assert(MI.getOpcode() == TargetOpcode::G_UMULH);
5984 Register RHS = MI.getOperand(2).getReg();
5985 Register Dst = MI.getOperand(0).getReg();
5986 LLT Ty = MRI.getType(Dst);
5987 LLT RHSTy = MRI.getType(RHS);
5989 auto MatchPow2ExceptOne = [&](const Constant *C) {
5990 if (auto *CI = dyn_cast<ConstantInt>(C))
5991 return CI->getValue().isPowerOf2() && !CI->getValue().isOne();
5992 return false;
5993 };
5994 if (!matchUnaryPredicate(MRI, RHS, MatchPow2ExceptOne, false))
5995 return false;
5996 // We need to check both G_LSHR and G_CTLZ because the combine uses G_CTLZ to
5997 // get log base 2, and it is not always legal for on a target.
5998 return isLegalOrBeforeLegalizer({TargetOpcode::G_LSHR, {Ty, ShiftAmtTy}}) &&
5999 isLegalOrBeforeLegalizer({TargetOpcode::G_CTLZ, {RHSTy, RHSTy}});
6000}
6001
6003 Register LHS = MI.getOperand(1).getReg();
6004 Register RHS = MI.getOperand(2).getReg();
6005 Register Dst = MI.getOperand(0).getReg();
6006 LLT Ty = MRI.getType(Dst);
6008 unsigned NumEltBits = Ty.getScalarSizeInBits();
6009
6010 auto LogBase2 = buildLogBase2(RHS, Builder);
6011 auto ShiftAmt =
6012 Builder.buildSub(Ty, Builder.buildConstant(Ty, NumEltBits), LogBase2);
6013 auto Trunc = Builder.buildZExtOrTrunc(ShiftAmtTy, ShiftAmt);
6014 Builder.buildLShr(Dst, LHS, Trunc);
6015 MI.eraseFromParent();
6016}
6017
6019 Register &MatchInfo) const {
6020 Register Dst = MI.getOperand(0).getReg();
6021 Register Src = MI.getOperand(1).getReg();
6022 LLT DstTy = MRI.getType(Dst);
6023 LLT SrcTy = MRI.getType(Src);
6024 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6025 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6026 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6027
6029 {TargetOpcode::G_TRUNC_SSAT_S, {DstTy, SrcTy}}))
6030 return false;
6031
6032 APInt SignedMax = APInt::getSignedMaxValue(NumDstBits).sext(NumSrcBits);
6033 APInt SignedMin = APInt::getSignedMinValue(NumDstBits).sext(NumSrcBits);
6034 if (mi_match(
6035 Src, MRI,
6036 m_GSMin(m_GSMax(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMin)),
6037 m_SpecificICstOrSplat(SignedMax))))
6038 return true;
6039 if (mi_match(
6040 Src, MRI,
6041 m_GSMax(m_GSMin(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMax)),
6042 m_SpecificICstOrSplat(SignedMin))))
6043 return true;
6044
6045 // CVP in the midend will often transform trunc(smin(smax(..)) into
6046 // trunc nsw(smin(..)) as the smax against INT_MIN never saturates.
6047 if (MI.getFlag(MachineInstr::MIFlag::NoSWrap) &&
6048 mi_match(Src, MRI,
6049 m_GSMin(m_Reg(MatchInfo), m_SpecificICstOrSplat(SignedMax))))
6050 return true;
6051
6052 return false;
6053}
6054
6056 Register &MatchInfo) const {
6057 Register Dst = MI.getOperand(0).getReg();
6058 Builder.buildTruncSSatS(Dst, MatchInfo);
6059 MI.eraseFromParent();
6060}
6061
6063 Register &MatchInfo) const {
6064 Register Dst = MI.getOperand(0).getReg();
6065 Register Src = MI.getOperand(1).getReg();
6066 LLT DstTy = MRI.getType(Dst);
6067 LLT SrcTy = MRI.getType(Src);
6068 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6069 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6070 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6071
6073 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6074 return false;
6075 APInt UnsignedMax = APInt::getMaxValue(NumDstBits).zext(NumSrcBits);
6076 return mi_match(Src, MRI,
6078 m_SpecificICstOrSplat(UnsignedMax))) ||
6079 mi_match(Src, MRI,
6080 m_GSMax(m_GSMin(m_Reg(MatchInfo),
6081 m_SpecificICstOrSplat(UnsignedMax)),
6082 m_SpecificICstOrSplat(0))) ||
6083 mi_match(Src, MRI,
6085 m_SpecificICstOrSplat(UnsignedMax)));
6086}
6087
6089 Register &MatchInfo) const {
6090 Register Dst = MI.getOperand(0).getReg();
6091 Builder.buildTruncSSatU(Dst, MatchInfo);
6092 MI.eraseFromParent();
6093}
6094
6096 MachineInstr &MinMI) const {
6097 Register Min = MinMI.getOperand(2).getReg();
6098 Register Val = MinMI.getOperand(1).getReg();
6099 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6100 LLT SrcTy = MRI.getType(Val);
6101 unsigned NumDstBits = DstTy.getScalarSizeInBits();
6102 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6103 assert(NumSrcBits > NumDstBits && "Unexpected types for truncate operation");
6104
6106 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6107 return false;
6108 APInt UnsignedMax = APInt::getMaxValue(NumDstBits).zext(NumSrcBits);
6109 return mi_match(Min, MRI, m_SpecificICstOrSplat(UnsignedMax)) &&
6110 !mi_match(Val, MRI, m_GSMax(m_Reg(), m_Reg()));
6111}
6112
6114 MachineInstr &SrcMI) const {
6115 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6116 LLT SrcTy = MRI.getType(SrcMI.getOperand(1).getReg());
6117
6118 return LI &&
6119 isLegalOrBeforeLegalizer({TargetOpcode::G_FPTOUI_SAT, {DstTy, SrcTy}});
6120}
6121
6123 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6124
6125 Register LHS = MI.getOperand(1).getReg();
6126 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
6127
6128 const auto LHSCst = Ty.isVector()
6129 ? getFConstantSplat(LHS, MRI, /* allowUndef */ true)
6131 if (!LHSCst)
6132 return false;
6133
6134 // Skip fsub_to_fneg when both LHS and RHS are scalar constants (vector FP
6135 // binop constant folding is not supported yet), so constant_fold_fp_binop
6136 // folds these cases.
6137 if (!Ty.isVector() && getConstantFPVRegVal(LHS, MRI) &&
6138 getConstantFPVRegVal(MI.getOperand(2).getReg(), MRI))
6139 return false;
6140
6141 // -0.0 is always allowed
6142 if (LHSCst->Value.isNegZero())
6143 return true;
6144
6145 // +0.0 is only allowed if nsz is set.
6146 if (LHSCst->Value.isPosZero())
6147 return MI.getFlag(MachineInstr::FmNsz);
6148
6149 return false;
6150}
6151
6152/// Checks if \p MI is TargetOpcode::G_FMUL and contractable either
6153/// due to global flags or MachineInstr flags.
6154static bool isContractableFMul(MachineInstr &MI, bool AllowFusionGlobally) {
6155 if (MI.getOpcode() != TargetOpcode::G_FMUL)
6156 return false;
6157 return AllowFusionGlobally || MI.getFlag(MachineInstr::MIFlag::FmContract);
6158}
6159
6160static bool hasMoreUses(const MachineInstr &MI0, const MachineInstr &MI1,
6161 const MachineRegisterInfo &MRI) {
6162 return std::distance(MRI.use_instr_nodbg_begin(MI0.getOperand(0).getReg()),
6163 MRI.use_instr_nodbg_end()) >
6164 std::distance(MRI.use_instr_nodbg_begin(MI1.getOperand(0).getReg()),
6165 MRI.use_instr_nodbg_end());
6166}
6167
6169 bool &AllowFusionGlobally,
6170 bool &HasFMAD, bool &Aggressive,
6171 bool CanReassociate) const {
6172
6173 auto *MF = MI.getMF();
6174 const auto &TLI = *MF->getSubtarget().getTargetLowering();
6175 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6176
6177 if (CanReassociate && !MI.getFlag(MachineInstr::MIFlag::FmReassoc))
6178 return false;
6179
6180 // Floating-point multiply-add with intermediate rounding.
6181 HasFMAD = (!isPreLegalize() && TLI.isFMADLegal(MI, DstType));
6182 // Floating-point multiply-add without intermediate rounding.
6183 bool HasFMA = TLI.isFMAFasterThanFMulAndFAdd(*MF, DstType) &&
6184 isLegalOrBeforeLegalizer({TargetOpcode::G_FMA, {DstType}});
6185 // No valid opcode, do not combine.
6186 if (!HasFMAD && !HasFMA)
6187 return false;
6188
6189 // FMAD (with intermediate rounding) is always safe to form; FMA requires the
6190 // contract fast-math flag.
6191 AllowFusionGlobally = HasFMAD;
6192 // If the addition is not contractable, do not combine.
6193 if (!AllowFusionGlobally && !MI.getFlag(MachineInstr::MIFlag::FmContract))
6194 return false;
6195
6196 Aggressive = TLI.enableAggressiveFMAFusion(DstType);
6197 return true;
6198}
6199
6202 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6203 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6204
6205 bool AllowFusionGlobally, HasFMAD, Aggressive;
6206 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6207 return false;
6208
6209 Register Op1 = MI.getOperand(1).getReg();
6210 Register Op2 = MI.getOperand(2).getReg();
6211 MachineInstr *Op1Def, *Op2Def;
6212 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6213 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6214 return false;
6215 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6216 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6217 unsigned PreferredFusedOpcode =
6218 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6219
6220 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6221 // prefer to fold the multiply with fewer uses.
6222 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6223 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6224 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6225 std::swap(LHS, RHS);
6226 }
6227
6228 // fold (fadd (fmul x, y), z) -> (fma x, y, z)
6229 if (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6230 (Aggressive || MRI.hasOneNonDBGUse(LHS.Reg))) {
6231 unsigned Flags = MI.getFlags() & LHS.MI->getFlags();
6232 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6233 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6234 {LHS.MI->getOperand(1).getReg(),
6235 LHS.MI->getOperand(2).getReg(), RHS.Reg},
6236 Flags);
6237 };
6238 return true;
6239 }
6240
6241 // fold (fadd x, (fmul y, z)) -> (fma y, z, x)
6242 if (isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6243 (Aggressive || MRI.hasOneNonDBGUse(RHS.Reg))) {
6244 unsigned Flags = MI.getFlags() & RHS.MI->getFlags();
6245 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6246 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6247 {RHS.MI->getOperand(1).getReg(),
6248 RHS.MI->getOperand(2).getReg(), LHS.Reg},
6249 Flags);
6250 };
6251 return true;
6252 }
6253
6254 return false;
6255}
6256
6259 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6260 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6261
6262 bool AllowFusionGlobally, HasFMAD, Aggressive;
6263 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6264 return false;
6265
6266 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6267 Register Op1 = MI.getOperand(1).getReg();
6268 Register Op2 = MI.getOperand(2).getReg();
6269 MachineInstr *Op1Def, *Op2Def;
6270 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6271 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6272 return false;
6273 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6274 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6275 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6276
6277 unsigned PreferredFusedOpcode =
6278 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6279
6280 MachineInstr *LHSFpExtSrc;
6281 bool LHSContractable =
6282 mi_match(LHS.Reg, MRI, m_GFPExt(m_MInstr(LHSFpExtSrc))) &&
6283 isContractableFMul(*LHSFpExtSrc, AllowFusionGlobally) &&
6284 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6285 MRI.getType(LHSFpExtSrc->getOperand(1).getReg()));
6286 MachineInstr *RHSFpExtSrc;
6287 bool RHSContractable =
6288 mi_match(RHS.Reg, MRI, m_GFPExt(m_MInstr(RHSFpExtSrc))) &&
6289 isContractableFMul(*RHSFpExtSrc, AllowFusionGlobally) &&
6290 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6291 MRI.getType(RHSFpExtSrc->getOperand(1).getReg()));
6292
6293 // fold (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z)
6294 if (LHSContractable || RHSContractable) {
6295 // Ensure that the contractable fmul with the fewest uses (if both are
6296 // contractable) is the LHS operand.
6297 if (!LHSContractable ||
6298 (RHSContractable && hasMoreUses(*LHSFpExtSrc, *RHSFpExtSrc, MRI))) {
6299 std::swap(LHS, RHS);
6300 LHSFpExtSrc = RHSFpExtSrc;
6301 }
6302
6303 unsigned Flags = MI.getFlags() & LHSFpExtSrc->getFlags();
6304 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6305 auto FpExtX = B.buildFPExt(DstType, LHSFpExtSrc->getOperand(1).getReg());
6306 auto FpExtY = B.buildFPExt(DstType, LHSFpExtSrc->getOperand(2).getReg());
6307 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6308 {FpExtX.getReg(0), FpExtY.getReg(0), RHS.Reg}, Flags);
6309 };
6310 return true;
6311 }
6312
6313 return false;
6314}
6315
6318 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6319 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6320
6321 bool AllowFusionGlobally, HasFMAD, Aggressive;
6322 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive, true))
6323 return false;
6324
6325 Register Op1 = MI.getOperand(1).getReg();
6326 Register Op2 = MI.getOperand(2).getReg();
6327 MachineInstr *Op1Def, *Op2Def;
6328 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6329 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6330 return false;
6331 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6332 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6333 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6334
6335 unsigned PreferredFusedOpcode =
6336 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6337
6338 MachineInstr *FMA = nullptr;
6339 Register Z;
6340 // fold (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z))
6341 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6342 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6343 m_GFMul(m_Reg(), m_Reg())) &&
6344 MRI.hasOneNonDBGUse(LHS.MI->getOperand(0).getReg()) &&
6345 MRI.hasOneNonDBGUse(LHS.MI->getOperand(3).getReg())) {
6346 FMA = LHS.MI;
6347 Z = RHS.Reg;
6348 }
6349 // fold (fadd z, (fma x, y, (fmul u, v))) -> (fma x, y, (fma u, v, z))
6350 else if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6351 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6352 m_GFMul(m_Reg(), m_Reg())) &&
6353 MRI.hasOneNonDBGUse(RHS.MI->getOperand(0).getReg()) &&
6354 MRI.hasOneNonDBGUse(RHS.MI->getOperand(3).getReg())) {
6355 Z = LHS.Reg;
6356 FMA = RHS.MI;
6357 }
6358
6359 if (FMA) {
6360 MachineInstr *FMulMI;
6361 if (!mi_match(FMA->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6362 return false;
6363 Register X = FMA->getOperand(1).getReg();
6364 Register Y = FMA->getOperand(2).getReg();
6365 Register U = FMulMI->getOperand(1).getReg();
6366 Register V = FMulMI->getOperand(2).getReg();
6367 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6368 unsigned OuterFlags = MI.getFlags() & FMA->getFlags();
6369
6370 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6371 Register InnerFMA = MRI.createGenericVirtualRegister(DstTy);
6372 B.buildInstr(PreferredFusedOpcode, {InnerFMA}, {U, V, Z}, InnerFlags);
6373 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6374 {X, Y, InnerFMA}, OuterFlags);
6375 };
6376 return true;
6377 }
6378
6379 return false;
6380}
6381
6384 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6385 assert(MI.getOpcode() == TargetOpcode::G_FADD);
6386
6387 bool AllowFusionGlobally, HasFMAD, Aggressive;
6388 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6389 return false;
6390
6391 if (!Aggressive)
6392 return false;
6393
6394 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6395 LLT DstType = MRI.getType(MI.getOperand(0).getReg());
6396 Register Op1 = MI.getOperand(1).getReg();
6397 Register Op2 = MI.getOperand(2).getReg();
6398 MachineInstr *Op1Def, *Op2Def;
6399 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6400 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6401 return false;
6402 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6403 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6404
6405 unsigned PreferredFusedOpcode =
6406 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6407
6408 // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)),
6409 // prefer to fold the multiply with fewer uses.
6410 if (Aggressive && isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6411 isContractableFMul(*RHS.MI, AllowFusionGlobally)) {
6412 if (hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6413 std::swap(LHS, RHS);
6414 }
6415
6416 // Builds: (fma x, y, (fma (fpext u), (fpext v), z))
6417 auto buildMatchInfo = [=, &MI](Register U, Register V, Register Z, Register X,
6418 Register Y, unsigned InnerFlags,
6419 unsigned OuterFlags, MachineIRBuilder &B) {
6420 Register FpExtU = B.buildFPExt(DstType, U).getReg(0);
6421 Register FpExtV = B.buildFPExt(DstType, V).getReg(0);
6422 Register InnerFMA = B.buildInstr(PreferredFusedOpcode, {DstType},
6423 {FpExtU, FpExtV, Z}, InnerFlags)
6424 .getReg(0);
6425 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6426 {X, Y, InnerFMA}, OuterFlags);
6427 };
6428
6429 MachineInstr *FMulMI, *FMAMI;
6430 // fold (fadd (fma x, y, (fpext (fmul u, v))), z)
6431 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6432 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6433 mi_match(LHS.MI->getOperand(3).getReg(), MRI,
6434 m_GFPExt(m_MInstr(FMulMI))) &&
6435 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6436 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6437 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6438 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6439 unsigned OuterFlags = MI.getFlags() & LHS.MI->getFlags();
6440 MatchInfo = [=](MachineIRBuilder &B) {
6441 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6442 FMulMI->getOperand(2).getReg(), RHS.Reg,
6443 LHS.MI->getOperand(1).getReg(),
6444 LHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6445 };
6446 return true;
6447 }
6448
6449 // fold (fadd (fpext (fma x, y, (fmul u, v))), z)
6450 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6451 // FIXME: This turns two single-precision and one double-precision
6452 // operation into two double-precision operations, which might not be
6453 // interesting for all targets, especially GPUs.
6454 if (mi_match(LHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6455 FMAMI->getOpcode() == PreferredFusedOpcode) {
6456 MachineInstr *FMulMI;
6457 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6458 return false;
6459 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6460 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6461 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6462 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6463 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6464 MatchInfo = [=](MachineIRBuilder &B) {
6465 Register X = FMAMI->getOperand(1).getReg();
6466 Register Y = FMAMI->getOperand(2).getReg();
6467 X = B.buildFPExt(DstType, X).getReg(0);
6468 Y = B.buildFPExt(DstType, Y).getReg(0);
6469 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6470 FMulMI->getOperand(2).getReg(), RHS.Reg, X, Y,
6471 InnerFlags, OuterFlags, B);
6472 };
6473
6474 return true;
6475 }
6476 }
6477
6478 // fold (fadd z, (fma x, y, (fpext (fmul u, v)))
6479 // -> (fma x, y, (fma (fpext u), (fpext v), z))
6480 if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6481 mi_match(RHS.MI->getOperand(3).getReg(), MRI,
6482 m_GFPExt(m_MInstr(FMulMI))) &&
6483 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6484 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6485 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6486 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6487 unsigned OuterFlags = MI.getFlags() & RHS.MI->getFlags();
6488 MatchInfo = [=](MachineIRBuilder &B) {
6489 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6490 FMulMI->getOperand(2).getReg(), LHS.Reg,
6491 RHS.MI->getOperand(1).getReg(),
6492 RHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags, B);
6493 };
6494 return true;
6495 }
6496
6497 // fold (fadd z, (fpext (fma x, y, (fmul u, v)))
6498 // -> (fma (fpext x), (fpext y), (fma (fpext u), (fpext v), z))
6499 // FIXME: This turns two single-precision and one double-precision
6500 // operation into two double-precision operations, which might not be
6501 // interesting for all targets, especially GPUs.
6502 if (mi_match(RHS.Reg, MRI, m_GFPExt(m_MInstr(FMAMI))) &&
6503 FMAMI->getOpcode() == PreferredFusedOpcode) {
6504 MachineInstr *FMulMI;
6505 if (!mi_match(FMAMI->getOperand(3).getReg(), MRI, m_MInstr(FMulMI)))
6506 return false;
6507 if (isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6508 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstType,
6509 MRI.getType(FMAMI->getOperand(0).getReg()))) {
6510 unsigned InnerFlags = MI.getFlags() & FMulMI->getFlags();
6511 unsigned OuterFlags = MI.getFlags() & FMAMI->getFlags();
6512 MatchInfo = [=](MachineIRBuilder &B) {
6513 Register X = FMAMI->getOperand(1).getReg();
6514 Register Y = FMAMI->getOperand(2).getReg();
6515 X = B.buildFPExt(DstType, X).getReg(0);
6516 Y = B.buildFPExt(DstType, Y).getReg(0);
6517 buildMatchInfo(FMulMI->getOperand(1).getReg(),
6518 FMulMI->getOperand(2).getReg(), LHS.Reg, X, Y,
6519 InnerFlags, OuterFlags, B);
6520 };
6521 return true;
6522 }
6523 }
6524
6525 return false;
6526}
6527
6530 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6531 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6532
6533 bool AllowFusionGlobally, HasFMAD, Aggressive;
6534 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6535 return false;
6536
6537 Register Op1 = MI.getOperand(1).getReg();
6538 Register Op2 = MI.getOperand(2).getReg();
6539 MachineInstr *Op1Def, *Op2Def;
6540 if (!mi_match(Op1, MRI, m_MInstr(Op1Def)) ||
6541 !mi_match(Op2, MRI, m_MInstr(Op2Def)))
6542 return false;
6543 DefinitionAndSourceRegister LHS = {Op1Def, Op1};
6544 DefinitionAndSourceRegister RHS = {Op2Def, Op2};
6545 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6546
6547 // If we have two choices trying to fold (fsub (fmul u, v), (fmul x, y)),
6548 // prefer to fold the multiply with fewer uses.
6549 int FirstMulHasFewerUses = true;
6550 if (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6551 isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6552 hasMoreUses(*LHS.MI, *RHS.MI, MRI))
6553 FirstMulHasFewerUses = false;
6554
6555 unsigned PreferredFusedOpcode =
6556 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6557
6558 // fold (fsub (fmul x, y), z) -> (fma x, y, -z)
6559 if (FirstMulHasFewerUses &&
6560 (isContractableFMul(*LHS.MI, AllowFusionGlobally) &&
6561 (Aggressive || MRI.hasOneNonDBGUse(LHS.Reg)))) {
6562 unsigned Flags = MI.getFlags() & LHS.MI->getFlags();
6563 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6564 Register NegZ = B.buildFNeg(DstTy, RHS.Reg).getReg(0);
6565 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6566 {LHS.MI->getOperand(1).getReg(),
6567 LHS.MI->getOperand(2).getReg(), NegZ},
6568 Flags);
6569 };
6570 return true;
6571 }
6572 // fold (fsub x, (fmul y, z)) -> (fma -y, z, x)
6573 else if ((isContractableFMul(*RHS.MI, AllowFusionGlobally) &&
6574 (Aggressive || MRI.hasOneNonDBGUse(RHS.Reg)))) {
6575 unsigned Flags = MI.getFlags() & RHS.MI->getFlags();
6576 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6577 Register NegY =
6578 B.buildFNeg(DstTy, RHS.MI->getOperand(1).getReg()).getReg(0);
6579 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6580 {NegY, RHS.MI->getOperand(2).getReg(), LHS.Reg}, Flags);
6581 };
6582 return true;
6583 }
6584
6585 return false;
6586}
6587
6590 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6591 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6592
6593 bool AllowFusionGlobally, HasFMAD, Aggressive;
6594 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6595 return false;
6596
6597 Register LHSReg = MI.getOperand(1).getReg();
6598 Register RHSReg = MI.getOperand(2).getReg();
6599 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6600
6601 unsigned PreferredFusedOpcode =
6602 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6603
6604 MachineInstr *FMulMI;
6605 // fold (fsub (fneg (fmul x, y)), z) -> (fma (fneg x), y, (fneg z))
6606 if (mi_match(LHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6607 (Aggressive || (MRI.hasOneNonDBGUse(LHSReg) &&
6608 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6609 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6610 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6611 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6612 Register NegX =
6613 B.buildFNeg(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6614 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6615 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6616 {NegX, FMulMI->getOperand(2).getReg(), NegZ}, Flags);
6617 };
6618 return true;
6619 }
6620
6621 // fold (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x)
6622 if (mi_match(RHSReg, MRI, m_GFNeg(m_MInstr(FMulMI))) &&
6623 (Aggressive || (MRI.hasOneNonDBGUse(RHSReg) &&
6624 MRI.hasOneNonDBGUse(FMulMI->getOperand(0).getReg()))) &&
6625 isContractableFMul(*FMulMI, AllowFusionGlobally)) {
6626 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6627 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6628 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6629 {FMulMI->getOperand(1).getReg(),
6630 FMulMI->getOperand(2).getReg(), LHSReg},
6631 Flags);
6632 };
6633 return true;
6634 }
6635
6636 return false;
6637}
6638
6641 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6642 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6643
6644 bool AllowFusionGlobally, HasFMAD, Aggressive;
6645 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6646 return false;
6647
6648 Register LHSReg = MI.getOperand(1).getReg();
6649 Register RHSReg = MI.getOperand(2).getReg();
6650 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6651
6652 unsigned PreferredFusedOpcode =
6653 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6654
6655 MachineInstr *FMulMI;
6656 // fold (fsub (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), (fneg z))
6657 if (mi_match(LHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6658 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6659 (Aggressive || MRI.hasOneNonDBGUse(LHSReg))) {
6660 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6661 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6662 Register FpExtX =
6663 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6664 Register FpExtY =
6665 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6666 Register NegZ = B.buildFNeg(DstTy, RHSReg).getReg(0);
6667 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6668 {FpExtX, FpExtY, NegZ}, Flags);
6669 };
6670 return true;
6671 }
6672
6673 // fold (fsub x, (fpext (fmul y, z))) -> (fma (fneg (fpext y)), (fpext z), x)
6674 if (mi_match(RHSReg, MRI, m_GFPExt(m_MInstr(FMulMI))) &&
6675 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6676 (Aggressive || MRI.hasOneNonDBGUse(RHSReg))) {
6677 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6678 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6679 Register FpExtY =
6680 B.buildFPExt(DstTy, FMulMI->getOperand(1).getReg()).getReg(0);
6681 Register NegY = B.buildFNeg(DstTy, FpExtY).getReg(0);
6682 Register FpExtZ =
6683 B.buildFPExt(DstTy, FMulMI->getOperand(2).getReg()).getReg(0);
6684 B.buildInstr(PreferredFusedOpcode, {MI.getOperand(0).getReg()},
6685 {NegY, FpExtZ, LHSReg}, Flags);
6686 };
6687 return true;
6688 }
6689
6690 return false;
6691}
6692
6695 std::function<void(MachineIRBuilder &)> &MatchInfo) const {
6696 assert(MI.getOpcode() == TargetOpcode::G_FSUB);
6697
6698 bool AllowFusionGlobally, HasFMAD, Aggressive;
6699 if (!canCombineFMadOrFMA(MI, AllowFusionGlobally, HasFMAD, Aggressive))
6700 return false;
6701
6702 const auto &TLI = *MI.getMF()->getSubtarget().getTargetLowering();
6703 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
6704 Register LHSReg = MI.getOperand(1).getReg();
6705 Register RHSReg = MI.getOperand(2).getReg();
6706
6707 unsigned PreferredFusedOpcode =
6708 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6709
6710 auto buildMatchInfo = [=](Register Dst, Register X, Register Y, Register Z,
6711 unsigned Flags, MachineIRBuilder &B) {
6712 Register FpExtX = B.buildFPExt(DstTy, X).getReg(0);
6713 Register FpExtY = B.buildFPExt(DstTy, Y).getReg(0);
6714 B.buildInstr(PreferredFusedOpcode, {Dst}, {FpExtX, FpExtY, Z}, Flags);
6715 };
6716
6717 MachineInstr *FMulMI;
6718 // fold (fsub (fpext (fneg (fmul x, y))), z) ->
6719 // (fneg (fma (fpext x), (fpext y), z))
6720 // fold (fsub (fneg (fpext (fmul x, y))), z) ->
6721 // (fneg (fma (fpext x), (fpext y), z))
6722 if ((mi_match(LHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
6723 mi_match(LHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
6724 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6725 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
6726 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6727 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6728 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6729 Register FMAReg = MRI.createGenericVirtualRegister(DstTy);
6730 buildMatchInfo(FMAReg, FMulMI->getOperand(1).getReg(),
6731 FMulMI->getOperand(2).getReg(), RHSReg, Flags, B);
6732 B.buildFNeg(MI.getOperand(0).getReg(), FMAReg);
6733 };
6734 return true;
6735 }
6736
6737 // fold (fsub x, (fpext (fneg (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
6738 // fold (fsub x, (fneg (fpext (fmul y, z)))) -> (fma (fpext y), (fpext z), x)
6739 if ((mi_match(RHSReg, MRI, m_GFPExt(m_GFNeg(m_MInstr(FMulMI)))) ||
6740 mi_match(RHSReg, MRI, m_GFNeg(m_GFPExt(m_MInstr(FMulMI))))) &&
6741 isContractableFMul(*FMulMI, AllowFusionGlobally) &&
6742 TLI.isFPExtFoldable(MI, PreferredFusedOpcode, DstTy,
6743 MRI.getType(FMulMI->getOperand(0).getReg()))) {
6744 unsigned Flags = MI.getFlags() & FMulMI->getFlags();
6745 MatchInfo = [=, &MI](MachineIRBuilder &B) {
6746 buildMatchInfo(MI.getOperand(0).getReg(), FMulMI->getOperand(1).getReg(),
6747 FMulMI->getOperand(2).getReg(), LHSReg, Flags, B);
6748 };
6749 return true;
6750 }
6751
6752 return false;
6753}
6754
6755// Combine multiple FDIVs with the same divisor into multiple FMULs by the
6756// reciprocal.
6757// E.g., (a / Y; b / Y;) -> (recip = 1.0 / Y; a * recip; b * recip)
6759 MachineInstr &MI, SmallVector<MachineInstr *> &MatchInfo) const {
6760 assert(MI.getOpcode() == TargetOpcode::G_FDIV);
6761
6762 Register X = MI.getOperand(1).getReg();
6763 Register Y = MI.getOperand(2).getReg();
6764
6765 if (!MI.getFlag(MachineInstr::MIFlag::FmArcp))
6766 return false;
6767
6768 auto IsOne = [this](Register X) {
6770 return N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne());
6771 };
6772
6773 // Skip if current node is a reciprocal/fneg-reciprocal.
6774 if (IsOne(X))
6775 return false;
6776
6777 // Exit early if the target does not want this transform or if there can't
6778 // possibly be enough uses of the divisor to make the transform worthwhile.
6779 unsigned MinUses = getTargetLowering().combineRepeatedFPDivisors();
6780 if (!MinUses)
6781 return false;
6782
6783 // Find all FDIV users of the same divisor. For the moment we limit all
6784 // instructions to a single BB and use the first Instr in MatchInfo as the
6785 // dominating position.
6786 MatchInfo.push_back(&MI);
6787 for (auto &U : MRI.use_nodbg_instructions(Y)) {
6788 if (&U == &MI || U.getParent() != MI.getParent())
6789 continue;
6790 if (U.getOpcode() == TargetOpcode::G_FDIV &&
6791 U.getOperand(2).getReg() == Y && U.getOperand(1).getReg() != Y &&
6792 !IsOne(U.getOperand(1).getReg())) {
6793 // This division is eligible for optimization only if global unsafe math
6794 // is enabled or if this division allows reciprocal formation.
6795 if (U.getFlag(MachineInstr::MIFlag::FmArcp)) {
6796 MatchInfo.push_back(&U);
6797 if (dominates(U, *MatchInfo[0]))
6798 std::swap(MatchInfo[0], MatchInfo.back());
6799 }
6800 }
6801 }
6802
6803 // Now that we have the actual number of divisor uses, make sure it meets
6804 // the minimum threshold specified by the target.
6805 return MatchInfo.size() >= MinUses;
6806}
6807
6809 SmallVector<MachineInstr *> &MatchInfo) const {
6810 // Generate the new div at the position of the first instruction, that we have
6811 // ensured will dominate all other instructions.
6812 Builder.setInsertPt(*MatchInfo[0]->getParent(), MatchInfo[0]);
6813 LLT Ty = MRI.getType(MatchInfo[0]->getOperand(0).getReg());
6814 auto Div = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0),
6815 MatchInfo[0]->getOperand(2).getReg(),
6816 MatchInfo[0]->getFlags());
6817
6818 // Replace all found div's with fmul instructions.
6819 for (MachineInstr *MI : MatchInfo) {
6820 Builder.setInsertPt(*MI->getParent(), MI);
6821 Builder.buildFMul(MI->getOperand(0).getReg(), MI->getOperand(1).getReg(),
6822 Div->getOperand(0).getReg(), MI->getFlags());
6823 MI->eraseFromParent();
6824 }
6825}
6826
6828 Register &MatchInfo) const {
6829 // This combine folds the following patterns:
6830 //
6831 // G_BUILD_VECTOR_TRUNC (G_BITCAST(x), G_LSHR(G_BITCAST(x), k))
6832 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), G_TRUNC(G_LSHR(G_BITCAST(x), k)))
6833 // into
6834 // x
6835 // if
6836 // k == sizeof(VecEltTy)/2
6837 // type(x) == type(dst)
6838 //
6839 // G_BUILD_VECTOR(G_TRUNC(G_BITCAST(x)), undef)
6840 // into
6841 // x
6842 // if
6843 // type(x) == type(dst)
6844
6845 LLT DstVecTy = MRI.getType(MI.getOperand(0).getReg());
6846 LLT DstEltTy = DstVecTy.getElementType();
6847
6848 Register Lo, Hi;
6849
6850 if (mi_match(
6851 MI, MRI,
6853 MatchInfo = Lo;
6854 return MRI.getType(MatchInfo) == DstVecTy;
6855 }
6856
6857 std::optional<ValueAndVReg> ShiftAmount;
6858 const auto LoPattern = m_GBitcast(m_Reg(Lo));
6859 const auto HiPattern = m_GLShr(m_GBitcast(m_Reg(Hi)), m_GCst(ShiftAmount));
6860 if (mi_match(
6861 MI, MRI,
6862 m_any_of(m_GBuildVectorTrunc(LoPattern, HiPattern),
6863 m_GBuildVector(m_GTrunc(LoPattern), m_GTrunc(HiPattern))))) {
6864 if (Lo == Hi && ShiftAmount->Value == DstEltTy.getSizeInBits()) {
6865 MatchInfo = Lo;
6866 return MRI.getType(MatchInfo) == DstVecTy;
6867 }
6868 }
6869
6870 return false;
6871}
6872
6874 Register &MatchInfo) const {
6875 // Replace (G_TRUNC (G_BITCAST (G_BUILD_VECTOR x, y)) with just x
6876 // if type(x) == type(G_TRUNC)
6877 if (!mi_match(MI.getOperand(1).getReg(), MRI,
6878 m_GBitcast(m_GBuildVector(m_Reg(MatchInfo), m_Reg()))))
6879 return false;
6880
6881 return MRI.getType(MatchInfo) == MRI.getType(MI.getOperand(0).getReg());
6882}
6883
6885 Register &MatchInfo) const {
6886 // Replace (G_TRUNC (G_LSHR (G_BITCAST (G_BUILD_VECTOR x, y)), K)) with
6887 // y if K == size of vector element type
6888 std::optional<ValueAndVReg> ShiftAmt;
6889 if (!mi_match(MI.getOperand(1).getReg(), MRI,
6891 m_GCst(ShiftAmt))))
6892 return false;
6893
6894 LLT MatchTy = MRI.getType(MatchInfo);
6895 return ShiftAmt->Value.getZExtValue() == MatchTy.getSizeInBits() &&
6896 MatchTy == MRI.getType(MI.getOperand(0).getReg());
6897}
6898
6899unsigned CombinerHelper::getFPMinMaxOpcForSelect(
6900 CmpInst::Predicate Pred, LLT DstTy,
6901 SelectPatternNaNBehaviour VsNaNRetVal) const {
6902 assert(VsNaNRetVal != SelectPatternNaNBehaviour::NOT_APPLICABLE &&
6903 "Expected a NaN behaviour?");
6904 // Choose an opcode based off of legality or the behaviour when one of the
6905 // LHS/RHS may be NaN.
6906 switch (Pred) {
6907 default:
6908 return 0;
6909 case CmpInst::FCMP_UGT:
6910 case CmpInst::FCMP_UGE:
6911 case CmpInst::FCMP_OGT:
6912 case CmpInst::FCMP_OGE:
6913 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
6914 return TargetOpcode::G_FMAXNUM;
6915 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
6916 return TargetOpcode::G_FMAXIMUM;
6917 if (isLegal({TargetOpcode::G_FMAXNUM, {DstTy}}))
6918 return TargetOpcode::G_FMAXNUM;
6919 if (isLegal({TargetOpcode::G_FMAXIMUM, {DstTy}}))
6920 return TargetOpcode::G_FMAXIMUM;
6921 return 0;
6922 case CmpInst::FCMP_ULT:
6923 case CmpInst::FCMP_ULE:
6924 case CmpInst::FCMP_OLT:
6925 case CmpInst::FCMP_OLE:
6926 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
6927 return TargetOpcode::G_FMINNUM;
6928 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
6929 return TargetOpcode::G_FMINIMUM;
6930 if (isLegal({TargetOpcode::G_FMINNUM, {DstTy}}))
6931 return TargetOpcode::G_FMINNUM;
6932 if (!isLegal({TargetOpcode::G_FMINIMUM, {DstTy}}))
6933 return 0;
6934 return TargetOpcode::G_FMINIMUM;
6935 }
6936}
6937
6938CombinerHelper::SelectPatternNaNBehaviour
6939CombinerHelper::computeRetValAgainstNaN(Register LHS, Register RHS,
6940 bool IsOrderedComparison) const {
6941 bool LHSSafe = VT->isKnownNeverNaN(LHS);
6942 bool RHSSafe = VT->isKnownNeverNaN(RHS);
6943 // Completely unsafe.
6944 if (!LHSSafe && !RHSSafe)
6945 return SelectPatternNaNBehaviour::NOT_APPLICABLE;
6946 if (LHSSafe && RHSSafe)
6947 return SelectPatternNaNBehaviour::RETURNS_ANY;
6948 // An ordered comparison will return false when given a NaN, so it
6949 // returns the RHS.
6950 if (IsOrderedComparison)
6951 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_NAN
6952 : SelectPatternNaNBehaviour::RETURNS_OTHER;
6953 // An unordered comparison will return true when given a NaN, so it
6954 // returns the LHS.
6955 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_OTHER
6956 : SelectPatternNaNBehaviour::RETURNS_NAN;
6957}
6958
6959bool CombinerHelper::matchFPSelectToMinMax(Register Dst, Register Cond,
6960 Register TrueVal, Register FalseVal,
6961 BuildFnTy &MatchInfo) const {
6962 // Match: select (fcmp cond x, y) x, y
6963 // select (fcmp cond x, y) y, x
6964 // And turn it into fminnum/fmaxnum or fmin/fmax based off of the condition.
6965 LLT DstTy = MRI.getType(Dst);
6966 // Bail out early on pointers, since we'll never want to fold to a min/max.
6967 if (DstTy.isPointer())
6968 return false;
6969 // Match a floating point compare with a less-than/greater-than predicate.
6970 // TODO: Allow multiple users of the compare if they are all selects.
6971 CmpInst::Predicate Pred;
6972 Register CmpLHS, CmpRHS;
6973 if (!mi_match(Cond, MRI,
6975 m_GFCmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS)))) ||
6976 CmpInst::isEquality(Pred))
6977 return false;
6978 SelectPatternNaNBehaviour ResWithKnownNaNInfo =
6979 computeRetValAgainstNaN(CmpLHS, CmpRHS, CmpInst::isOrdered(Pred));
6980 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::NOT_APPLICABLE)
6981 return false;
6982 if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
6983 std::swap(CmpLHS, CmpRHS);
6984 Pred = CmpInst::getSwappedPredicate(Pred);
6985 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_NAN)
6986 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_OTHER;
6987 else if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_OTHER)
6988 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_NAN;
6989 }
6990 if (TrueVal != CmpLHS || FalseVal != CmpRHS)
6991 return false;
6992 // Decide what type of max/min this should be based off of the predicate.
6993 unsigned Opc = getFPMinMaxOpcForSelect(Pred, DstTy, ResWithKnownNaNInfo);
6994 if (!Opc || !isLegal({Opc, {DstTy}}))
6995 return false;
6996 // Comparisons between signed zero and zero may have different results...
6997 // unless we have fmaximum/fminimum. In that case, we know -0 < 0.
6998 if (Opc != TargetOpcode::G_FMAXIMUM && Opc != TargetOpcode::G_FMINIMUM) {
6999 // We don't know if a comparison between two 0s will give us a consistent
7000 // result. Be conservative and only proceed if at least one side is
7001 // non-zero.
7002 auto KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpLHS, MRI);
7003 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero()) {
7004 KnownNonZeroSide = getFConstantVRegValWithLookThrough(CmpRHS, MRI);
7005 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero())
7006 return false;
7007 }
7008 }
7009 MatchInfo = [=](MachineIRBuilder &B) {
7010 B.buildInstr(Opc, {Dst}, {CmpLHS, CmpRHS});
7011 };
7012 return true;
7013}
7014
7016 BuildFnTy &MatchInfo) const {
7017 // TODO: Handle integer cases.
7018 assert(MI.getOpcode() == TargetOpcode::G_SELECT);
7019 // Condition may be fed by a truncated compare.
7020 Register Cond = MI.getOperand(1).getReg();
7021 Register MaybeTrunc;
7022 if (mi_match(Cond, MRI, m_OneNonDBGUse(m_GTrunc(m_Reg(MaybeTrunc)))))
7023 Cond = MaybeTrunc;
7024 Register Dst = MI.getOperand(0).getReg();
7025 Register TrueVal = MI.getOperand(2).getReg();
7026 Register FalseVal = MI.getOperand(3).getReg();
7027 return matchFPSelectToMinMax(Dst, Cond, TrueVal, FalseVal, MatchInfo);
7028}
7029
7031 BuildFnTy &MatchInfo) const {
7032 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
7033 // (X + Y) == X --> Y == 0
7034 // (X + Y) != X --> Y != 0
7035 // (X - Y) == X --> Y == 0
7036 // (X - Y) != X --> Y != 0
7037 // (X ^ Y) == X --> Y == 0
7038 // (X ^ Y) != X --> Y != 0
7039 Register Dst = MI.getOperand(0).getReg();
7040 CmpInst::Predicate Pred;
7041 Register X, Y, OpLHS, OpRHS;
7042 bool MatchedSub = mi_match(
7043 Dst, MRI,
7044 m_c_GICmp(m_Pred(Pred), m_Reg(X), m_GSub(m_Reg(OpLHS), m_Reg(Y))));
7045 if (MatchedSub && X != OpLHS)
7046 return false;
7047 if (!MatchedSub) {
7048 if (!mi_match(Dst, MRI,
7049 m_c_GICmp(m_Pred(Pred), m_Reg(X),
7050 m_any_of(m_GAdd(m_Reg(OpLHS), m_Reg(OpRHS)),
7051 m_GXor(m_Reg(OpLHS), m_Reg(OpRHS))))))
7052 return false;
7053 Y = X == OpLHS ? OpRHS : X == OpRHS ? OpLHS : Register();
7054 }
7055 MatchInfo = [=](MachineIRBuilder &B) {
7056 auto Zero = B.buildConstant(MRI.getType(Y), 0);
7057 B.buildICmp(Pred, Dst, Y, Zero);
7058 };
7059 return CmpInst::isEquality(Pred) && Y.isValid();
7060}
7061
7062/// Return the minimum useless shift amount that results in complete loss of the
7063/// source value. Return std::nullopt when it cannot determine a value.
7064static std::optional<unsigned>
7065getMinUselessShift(KnownBits ValueKB, unsigned Opcode,
7066 std::optional<int64_t> &Result) {
7067 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR ||
7068 Opcode == TargetOpcode::G_ASHR) &&
7069 "Expect G_SHL, G_LSHR or G_ASHR.");
7070 auto SignificantBits = 0;
7071 switch (Opcode) {
7072 case TargetOpcode::G_SHL:
7073 SignificantBits = ValueKB.countMinTrailingZeros();
7074 Result = 0;
7075 break;
7076 case TargetOpcode::G_LSHR:
7077 Result = 0;
7078 SignificantBits = ValueKB.countMinLeadingZeros();
7079 break;
7080 case TargetOpcode::G_ASHR:
7081 if (ValueKB.isNonNegative()) {
7082 SignificantBits = ValueKB.countMinLeadingZeros();
7083 Result = 0;
7084 } else if (ValueKB.isNegative()) {
7085 SignificantBits = ValueKB.countMinLeadingOnes();
7086 Result = -1;
7087 } else {
7088 // Cannot determine shift result.
7089 Result = std::nullopt;
7090 }
7091 break;
7092 default:
7093 break;
7094 }
7095 return ValueKB.getBitWidth() - SignificantBits;
7096}
7097
7099 MachineInstr &MI, std::optional<int64_t> &MatchInfo) const {
7100 Register ShiftVal = MI.getOperand(1).getReg();
7101 Register ShiftReg = MI.getOperand(2).getReg();
7102 LLT ResTy = MRI.getType(MI.getOperand(0).getReg());
7103 auto IsShiftTooBig = [&](const Constant *C) {
7104 auto *CI = dyn_cast<ConstantInt>(C);
7105 if (!CI)
7106 return false;
7107 if (CI->uge(ResTy.getScalarSizeInBits())) {
7108 MatchInfo = std::nullopt;
7109 return true;
7110 }
7111 auto OptMaxUsefulShift = getMinUselessShift(VT->getKnownBits(ShiftVal),
7112 MI.getOpcode(), MatchInfo);
7113 return OptMaxUsefulShift && CI->uge(*OptMaxUsefulShift);
7114 };
7115 return matchUnaryPredicate(MRI, ShiftReg, IsShiftTooBig);
7116}
7117
7119 unsigned LHSOpndIdx = 1;
7120 unsigned RHSOpndIdx = 2;
7121 switch (MI.getOpcode()) {
7122 case TargetOpcode::G_UADDO:
7123 case TargetOpcode::G_SADDO:
7124 case TargetOpcode::G_UMULO:
7125 case TargetOpcode::G_SMULO:
7126 LHSOpndIdx = 2;
7127 RHSOpndIdx = 3;
7128 break;
7129 default:
7130 break;
7131 }
7132 Register LHS = MI.getOperand(LHSOpndIdx).getReg();
7133 Register RHS = MI.getOperand(RHSOpndIdx).getReg();
7134 MachineInstr *LHSDef, *RHSDef;
7135 if (!mi_match(LHS, MRI, m_MInstr(LHSDef)) ||
7136 !mi_match(RHS, MRI, m_MInstr(RHSDef)))
7137 return false;
7138
7139 if (!getIConstantVRegVal(LHS, MRI)) {
7140 // Skip commuting if LHS is not a constant. But, LHS may be a
7141 // G_CONSTANT_FOLD_BARRIER. If so we commute as long as we don't already
7142 // have a constant on the RHS.
7143 if (LHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER)
7144 return false;
7145 }
7146 // Commute as long as RHS is not a constant or G_CONSTANT_FOLD_BARRIER.
7147 return RHSDef->getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER &&
7148 !getIConstantVRegVal(RHS, MRI);
7149}
7150
7152 Register LHS = MI.getOperand(1).getReg();
7153 Register RHS = MI.getOperand(2).getReg();
7154 std::optional<FPValueAndVReg> ValAndVReg;
7155 if (!mi_match(LHS, MRI, m_GFCstOrSplat(ValAndVReg)))
7156 return false;
7157 return !mi_match(RHS, MRI, m_GFCstOrSplat(ValAndVReg));
7158}
7159
7160bool CombinerHelper::isOneOrOneSplat(Register Src, bool AllowUndefs) const {
7161 LLT SrcTy = MRI.getType(Src);
7162 if (SrcTy.isFixedVector())
7163 return isConstantSplatVector(Src, 1, AllowUndefs);
7164 if (SrcTy.isScalar()) {
7165 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7166 return true;
7167 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7168 return IConstant && IConstant->Value == 1;
7169 }
7170 return false; // scalable vector
7171}
7172
7173bool CombinerHelper::isZeroOrZeroSplat(Register Src, bool AllowUndefs) const {
7174 LLT SrcTy = MRI.getType(Src);
7175 if (SrcTy.isFixedVector())
7176 return isConstantSplatVector(Src, 0, AllowUndefs);
7177 if (SrcTy.isScalar()) {
7178 if (AllowUndefs && getOpcodeDef<GImplicitDef>(Src, MRI) != nullptr)
7179 return true;
7180 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7181 return IConstant && IConstant->Value == 0;
7182 }
7183 return false; // scalable vector
7184}
7185
7186// Ignores COPYs during conformance checks.
7187// FIXME scalable vectors.
7188bool CombinerHelper::isConstantSplatVector(Register Src, int64_t SplatValue,
7189 bool AllowUndefs) const {
7190 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7191 if (!BuildVector)
7192 return false;
7193 unsigned NumSources = BuildVector->getNumSources();
7194
7195 for (unsigned I = 0; I < NumSources; ++I) {
7196 GImplicitDef *ImplicitDef =
7198 if (ImplicitDef && AllowUndefs)
7199 continue;
7200 if (ImplicitDef && !AllowUndefs)
7201 return false;
7202 std::optional<ValueAndVReg> IConstant =
7204 if (IConstant && IConstant->Value == SplatValue)
7205 continue;
7206 return false;
7207 }
7208 return true;
7209}
7210
7211// Ignores COPYs during lookups.
7212// FIXME scalable vectors
7213std::optional<APInt>
7214CombinerHelper::getConstantOrConstantSplatVector(Register Src) const {
7215 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7216 if (IConstant)
7217 return IConstant->Value;
7218
7219 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7220 if (!BuildVector)
7221 return std::nullopt;
7222 unsigned NumSources = BuildVector->getNumSources();
7223
7224 std::optional<APInt> Value = std::nullopt;
7225 for (unsigned I = 0; I < NumSources; ++I) {
7226 std::optional<ValueAndVReg> IConstant =
7228 if (!IConstant)
7229 return std::nullopt;
7230 if (!Value)
7231 Value = IConstant->Value;
7232 else if (*Value != IConstant->Value)
7233 return std::nullopt;
7234 }
7235 return Value;
7236}
7237
7238// FIXME G_SPLAT_VECTOR
7239bool CombinerHelper::isConstantOrConstantVectorI(Register Src) const {
7240 auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI);
7241 if (IConstant)
7242 return true;
7243
7244 GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI);
7245 if (!BuildVector)
7246 return false;
7247
7248 unsigned NumSources = BuildVector->getNumSources();
7249 for (unsigned I = 0; I < NumSources; ++I) {
7250 std::optional<ValueAndVReg> IConstant =
7252 if (!IConstant)
7253 return false;
7254 }
7255 return true;
7256}
7257
7258// TODO: use knownbits to determine zeros
7259bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select,
7260 BuildFnTy &MatchInfo) const {
7261 uint32_t Flags = Select->getFlags();
7262 Register Dest = Select->getReg(0);
7263 Register Cond = Select->getCondReg();
7264 Register True = Select->getTrueReg();
7265 Register False = Select->getFalseReg();
7266 LLT CondTy = MRI.getType(Select->getCondReg());
7267 LLT TrueTy = MRI.getType(Select->getTrueReg());
7268
7269 // We only do this combine for scalar boolean conditions.
7270 if (CondTy != LLT::scalar(1))
7271 return false;
7272
7273 if (TrueTy.isPointer())
7274 return false;
7275
7276 // Both are scalars.
7277 std::optional<ValueAndVReg> TrueOpt =
7279 std::optional<ValueAndVReg> FalseOpt =
7281
7282 if (!TrueOpt || !FalseOpt)
7283 return false;
7284
7285 APInt TrueValue = TrueOpt->Value;
7286 APInt FalseValue = FalseOpt->Value;
7287
7288 // select Cond, 1, 0 --> zext (Cond)
7289 if (TrueValue.isOne() && FalseValue.isZero()) {
7290 MatchInfo = [=](MachineIRBuilder &B) {
7291 B.setInstrAndDebugLoc(*Select);
7292 B.buildZExtOrTrunc(Dest, Cond);
7293 };
7294 return true;
7295 }
7296
7297 // select Cond, -1, 0 --> sext (Cond)
7298 if (TrueValue.isAllOnes() && FalseValue.isZero()) {
7299 MatchInfo = [=](MachineIRBuilder &B) {
7300 B.setInstrAndDebugLoc(*Select);
7301 B.buildSExtOrTrunc(Dest, Cond);
7302 };
7303 return true;
7304 }
7305
7306 // select Cond, 0, 1 --> zext (!Cond)
7307 if (TrueValue.isZero() && FalseValue.isOne()) {
7308 MatchInfo = [=](MachineIRBuilder &B) {
7309 B.setInstrAndDebugLoc(*Select);
7310 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7311 B.buildNot(Inner, Cond);
7312 B.buildZExtOrTrunc(Dest, Inner);
7313 };
7314 return true;
7315 }
7316
7317 // select Cond, 0, -1 --> sext (!Cond)
7318 if (TrueValue.isZero() && FalseValue.isAllOnes()) {
7319 MatchInfo = [=](MachineIRBuilder &B) {
7320 B.setInstrAndDebugLoc(*Select);
7321 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7322 B.buildNot(Inner, Cond);
7323 B.buildSExtOrTrunc(Dest, Inner);
7324 };
7325 return true;
7326 }
7327
7328 // select Cond, C1, C1-1 --> add (zext Cond), C1-1
7329 if (TrueValue - 1 == FalseValue) {
7330 MatchInfo = [=](MachineIRBuilder &B) {
7331 B.setInstrAndDebugLoc(*Select);
7332 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7333 B.buildZExtOrTrunc(Inner, Cond);
7334 B.buildAdd(Dest, Inner, False);
7335 };
7336 return true;
7337 }
7338
7339 // select Cond, C1, C1+1 --> add (sext Cond), C1+1
7340 if (TrueValue + 1 == FalseValue) {
7341 MatchInfo = [=](MachineIRBuilder &B) {
7342 B.setInstrAndDebugLoc(*Select);
7343 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7344 B.buildSExtOrTrunc(Inner, Cond);
7345 B.buildAdd(Dest, Inner, False);
7346 };
7347 return true;
7348 }
7349
7350 // select Cond, Pow2, 0 --> (zext Cond) << log2(Pow2)
7351 if (TrueValue.isPowerOf2() && FalseValue.isZero()) {
7352 MatchInfo = [=](MachineIRBuilder &B) {
7353 B.setInstrAndDebugLoc(*Select);
7354 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7355 B.buildZExtOrTrunc(Inner, Cond);
7356 // The shift amount must be scalar.
7357 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7358 auto ShAmtC = B.buildConstant(ShiftTy, TrueValue.exactLogBase2());
7359 B.buildShl(Dest, Inner, ShAmtC, Flags);
7360 };
7361 return true;
7362 }
7363
7364 // select Cond, 0, Pow2 --> (zext (!Cond)) << log2(Pow2)
7365 if (FalseValue.isPowerOf2() && TrueValue.isZero()) {
7366 MatchInfo = [=](MachineIRBuilder &B) {
7367 B.setInstrAndDebugLoc(*Select);
7368 Register Not = MRI.createGenericVirtualRegister(CondTy);
7369 B.buildNot(Not, Cond);
7370 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7371 B.buildZExtOrTrunc(Inner, Not);
7372 // The shift amount must be scalar.
7373 LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy;
7374 auto ShAmtC = B.buildConstant(ShiftTy, FalseValue.exactLogBase2());
7375 B.buildShl(Dest, Inner, ShAmtC, Flags);
7376 };
7377 return true;
7378 }
7379
7380 // select Cond, -1, C --> or (sext Cond), C
7381 if (TrueValue.isAllOnes()) {
7382 MatchInfo = [=](MachineIRBuilder &B) {
7383 B.setInstrAndDebugLoc(*Select);
7384 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7385 B.buildSExtOrTrunc(Inner, Cond);
7386 B.buildOr(Dest, Inner, False, Flags);
7387 };
7388 return true;
7389 }
7390
7391 // select Cond, C, -1 --> or (sext (not Cond)), C
7392 if (FalseValue.isAllOnes()) {
7393 MatchInfo = [=](MachineIRBuilder &B) {
7394 B.setInstrAndDebugLoc(*Select);
7395 Register Not = MRI.createGenericVirtualRegister(CondTy);
7396 B.buildNot(Not, Cond);
7397 Register Inner = MRI.createGenericVirtualRegister(TrueTy);
7398 B.buildSExtOrTrunc(Inner, Not);
7399 B.buildOr(Dest, Inner, True, Flags);
7400 };
7401 return true;
7402 }
7403
7404 return false;
7405}
7406
7407// TODO: use knownbits to determine zeros
7408bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
7409 BuildFnTy &MatchInfo) const {
7410 uint32_t Flags = Select->getFlags();
7411 Register DstReg = Select->getReg(0);
7412 Register Cond = Select->getCondReg();
7413 Register True = Select->getTrueReg();
7414 Register False = Select->getFalseReg();
7415 LLT CondTy = MRI.getType(Select->getCondReg());
7416 LLT TrueTy = MRI.getType(Select->getTrueReg());
7417
7418 // Boolean or fixed vector of booleans.
7419 if (CondTy.isScalableVector() ||
7420 (CondTy.isFixedVector() &&
7421 CondTy.getElementType().getScalarSizeInBits() != 1) ||
7422 CondTy.getScalarSizeInBits() != 1)
7423 return false;
7424
7425 if (CondTy != TrueTy)
7426 return false;
7427
7428 // select Cond, Cond, F --> or Cond, F
7429 // select Cond, 1, F --> or Cond, F
7430 if ((Cond == True) || isOneOrOneSplat(True, /* AllowUndefs */ true)) {
7431 MatchInfo = [=](MachineIRBuilder &B) {
7432 B.setInstrAndDebugLoc(*Select);
7433 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7434 B.buildZExtOrTrunc(Ext, Cond);
7435 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7436 B.buildOr(DstReg, Ext, FreezeFalse, Flags);
7437 };
7438 return true;
7439 }
7440
7441 // select Cond, T, Cond --> and Cond, T
7442 // select Cond, T, 0 --> and Cond, T
7443 if ((Cond == False) || isZeroOrZeroSplat(False, /* AllowUndefs */ true)) {
7444 MatchInfo = [=](MachineIRBuilder &B) {
7445 B.setInstrAndDebugLoc(*Select);
7446 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7447 B.buildZExtOrTrunc(Ext, Cond);
7448 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7449 B.buildAnd(DstReg, Ext, FreezeTrue);
7450 };
7451 return true;
7452 }
7453
7454 // select Cond, T, 1 --> or (not Cond), T
7455 if (isOneOrOneSplat(False, /* AllowUndefs */ true)) {
7456 MatchInfo = [=](MachineIRBuilder &B) {
7457 B.setInstrAndDebugLoc(*Select);
7458 // First the not.
7459 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7460 B.buildNot(Inner, Cond);
7461 // Then an ext to match the destination register.
7462 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7463 B.buildZExtOrTrunc(Ext, Inner);
7464 auto FreezeTrue = B.buildFreeze(TrueTy, True);
7465 B.buildOr(DstReg, Ext, FreezeTrue, Flags);
7466 };
7467 return true;
7468 }
7469
7470 // select Cond, 0, F --> and (not Cond), F
7471 if (isZeroOrZeroSplat(True, /* AllowUndefs */ true)) {
7472 MatchInfo = [=](MachineIRBuilder &B) {
7473 B.setInstrAndDebugLoc(*Select);
7474 // First the not.
7475 Register Inner = MRI.createGenericVirtualRegister(CondTy);
7476 B.buildNot(Inner, Cond);
7477 // Then an ext to match the destination register.
7478 Register Ext = MRI.createGenericVirtualRegister(TrueTy);
7479 B.buildZExtOrTrunc(Ext, Inner);
7480 auto FreezeFalse = B.buildFreeze(TrueTy, False);
7481 B.buildAnd(DstReg, Ext, FreezeFalse);
7482 };
7483 return true;
7484 }
7485
7486 return false;
7487}
7488
7490 BuildFnTy &MatchInfo) const {
7491 Register DstReg = MO.getReg();
7492 Register CondReg, True, False;
7493 if (!mi_match(DstReg, MRI,
7494 m_GISelect(m_Reg(CondReg), m_Reg(True), m_Reg(False))))
7495 return false;
7496
7497 CmpInst::Predicate Pred;
7498 Register CmpLHS, CmpRHS;
7499 if (!mi_match(CondReg, MRI,
7500 m_GICmp(m_Pred(Pred), m_Reg(CmpLHS), m_Reg(CmpRHS))))
7501 return false;
7502
7503 LLT DstTy = MRI.getType(DstReg);
7504 if (DstTy.isPointerOrPointerVector())
7505 return false;
7506
7507 // We want to fold the icmp and replace the select.
7508 if (!MRI.hasOneNonDBGUse(CondReg))
7509 return false;
7510
7511 // We need a larger or smaller predicate for
7512 // canonicalization.
7513 if (CmpInst::isEquality(Pred))
7514 return false;
7515
7516 // We can swap CmpLHS and CmpRHS for higher hitrate.
7517 if (True == CmpRHS && False == CmpLHS) {
7518 std::swap(CmpLHS, CmpRHS);
7519 Pred = CmpInst::getSwappedPredicate(Pred);
7520 }
7521
7522 // (icmp X, Y) ? X : Y -> integer minmax.
7523 // see matchSelectPattern in ValueTracking.
7524 // Legality between G_SELECT and integer minmax can differ.
7525 if (True != CmpLHS || False != CmpRHS)
7526 return false;
7527
7528 switch (Pred) {
7529 case ICmpInst::ICMP_UGT:
7530 case ICmpInst::ICMP_UGE: {
7531 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy}))
7532 return false;
7533 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMax(DstReg, True, False); };
7534 return true;
7535 }
7536 case ICmpInst::ICMP_SGT:
7537 case ICmpInst::ICMP_SGE: {
7538 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy}))
7539 return false;
7540 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMax(DstReg, True, False); };
7541 return true;
7542 }
7543 case ICmpInst::ICMP_ULT:
7544 case ICmpInst::ICMP_ULE: {
7545 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy}))
7546 return false;
7547 MatchInfo = [=](MachineIRBuilder &B) { B.buildUMin(DstReg, True, False); };
7548 return true;
7549 }
7550 case ICmpInst::ICMP_SLT:
7551 case ICmpInst::ICMP_SLE: {
7552 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy}))
7553 return false;
7554 MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(DstReg, True, False); };
7555 return true;
7556 }
7557 default:
7558 return false;
7559 }
7560}
7561
7562// (neg (min/max x, (neg x))) --> (max/min x, (neg x))
7564 BuildFnTy &MatchInfo) const {
7565 assert(MI.getOpcode() == TargetOpcode::G_SUB);
7566 Register DestReg = MI.getOperand(0).getReg();
7567 LLT DestTy = MRI.getType(DestReg);
7568
7569 Register X;
7570 Register Sub0;
7571 auto NegPattern = m_all_of(m_Neg(m_DeferredReg(X)), m_Reg(Sub0));
7572 if (mi_match(DestReg, MRI,
7573 m_Neg(m_OneUse(m_any_of(m_GSMin(m_Reg(X), NegPattern),
7574 m_GSMax(m_Reg(X), NegPattern),
7575 m_GUMin(m_Reg(X), NegPattern),
7576 m_GUMax(m_Reg(X), NegPattern)))))) {
7577 MachineInstr *MinMaxMI;
7578 if (!mi_match(MI.getOperand(2).getReg(), MRI, m_MInstr(MinMaxMI)))
7579 return false;
7580 unsigned NewOpc = getInverseGMinMaxOpcode(MinMaxMI->getOpcode());
7581 if (isLegal({NewOpc, {DestTy}})) {
7582 MatchInfo = [=](MachineIRBuilder &B) {
7583 B.buildInstr(NewOpc, {DestReg}, {X, Sub0});
7584 };
7585 return true;
7586 }
7587 }
7588
7589 return false;
7590}
7591
7594
7595 if (tryFoldSelectOfConstants(Select, MatchInfo))
7596 return true;
7597
7598 if (tryFoldBoolSelectToLogic(Select, MatchInfo))
7599 return true;
7600
7601 return false;
7602}
7603
7604/// Fold (icmp Pred1 V1, C1) && (icmp Pred2 V2, C2)
7605/// or (icmp Pred1 V1, C1) || (icmp Pred2 V2, C2)
7606/// into a single comparison using range-based reasoning.
7607/// see InstCombinerImpl::foldAndOrOfICmpsUsingRanges.
7608bool CombinerHelper::tryFoldAndOrOrICmpsUsingRanges(
7609 GLogicalBinOp *Logic, BuildFnTy &MatchInfo) const {
7610 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpected xor");
7611 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
7612 Register DstReg = Logic->getReg(0);
7613 Register LHS = Logic->getLHSReg();
7614 Register RHS = Logic->getRHSReg();
7615 unsigned Flags = Logic->getFlags();
7616
7617 // We need an G_ICMP on the LHS register.
7618 GICmp *Cmp1 = getOpcodeDef<GICmp>(LHS, MRI);
7619 if (!Cmp1)
7620 return false;
7621
7622 // We need an G_ICMP on the RHS register.
7623 GICmp *Cmp2 = getOpcodeDef<GICmp>(RHS, MRI);
7624 if (!Cmp2)
7625 return false;
7626
7627 // We want to fold the icmps.
7628 if (!MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
7629 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)))
7630 return false;
7631
7632 APInt C1;
7633 APInt C2;
7634 std::optional<ValueAndVReg> MaybeC1 =
7636 if (!MaybeC1)
7637 return false;
7638 C1 = MaybeC1->Value;
7639
7640 std::optional<ValueAndVReg> MaybeC2 =
7642 if (!MaybeC2)
7643 return false;
7644 C2 = MaybeC2->Value;
7645
7646 Register R1 = Cmp1->getLHSReg();
7647 Register R2 = Cmp2->getLHSReg();
7648 CmpInst::Predicate Pred1 = Cmp1->getCond();
7649 CmpInst::Predicate Pred2 = Cmp2->getCond();
7650 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
7651 LLT CmpOperandTy = MRI.getType(R1);
7652
7653 if (CmpOperandTy.isPointer())
7654 return false;
7655
7656 // We build ands, adds, and constants of type CmpOperandTy.
7657 // They must be legal to build.
7658 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_AND, CmpOperandTy}) ||
7659 !isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, CmpOperandTy}) ||
7660 !isConstantLegalOrBeforeLegalizer(CmpOperandTy))
7661 return false;
7662
7663 // Look through add of a constant offset on R1, R2, or both operands. This
7664 // allows us to interpret the R + C' < C'' range idiom into a proper range.
7665 std::optional<APInt> Offset1;
7666 std::optional<APInt> Offset2;
7667 if (R1 != R2) {
7668 if (GAdd *Add = getOpcodeDef<GAdd>(R1, MRI)) {
7669 std::optional<ValueAndVReg> MaybeOffset1 =
7671 if (MaybeOffset1) {
7672 R1 = Add->getLHSReg();
7673 Offset1 = MaybeOffset1->Value;
7674 }
7675 }
7676 if (GAdd *Add = getOpcodeDef<GAdd>(R2, MRI)) {
7677 std::optional<ValueAndVReg> MaybeOffset2 =
7679 if (MaybeOffset2) {
7680 R2 = Add->getLHSReg();
7681 Offset2 = MaybeOffset2->Value;
7682 }
7683 }
7684 }
7685
7686 if (R1 != R2)
7687 return false;
7688
7689 // We calculate the icmp ranges including maybe offsets.
7690 ConstantRange CR1 = ConstantRange::makeExactICmpRegion(
7691 IsAnd ? ICmpInst::getInversePredicate(Pred1) : Pred1, C1);
7692 if (Offset1)
7693 CR1 = CR1.subtract(*Offset1);
7694
7695 ConstantRange CR2 = ConstantRange::makeExactICmpRegion(
7696 IsAnd ? ICmpInst::getInversePredicate(Pred2) : Pred2, C2);
7697 if (Offset2)
7698 CR2 = CR2.subtract(*Offset2);
7699
7700 bool CreateMask = false;
7701 APInt LowerDiff;
7702 std::optional<ConstantRange> CR = CR1.exactUnionWith(CR2);
7703 if (!CR) {
7704 // We need non-wrapping ranges.
7705 if (CR1.isWrappedSet() || CR2.isWrappedSet())
7706 return false;
7707
7708 // Check whether we have equal-size ranges that only differ by one bit.
7709 // In that case we can apply a mask to map one range onto the other.
7710 LowerDiff = CR1.getLower() ^ CR2.getLower();
7711 APInt UpperDiff = (CR1.getUpper() - 1) ^ (CR2.getUpper() - 1);
7712 APInt CR1Size = CR1.getUpper() - CR1.getLower();
7713 if (!LowerDiff.isPowerOf2() || LowerDiff != UpperDiff ||
7714 CR1Size != CR2.getUpper() - CR2.getLower())
7715 return false;
7716
7717 CR = CR1.getLower().ult(CR2.getLower()) ? CR1 : CR2;
7718 CreateMask = true;
7719 }
7720
7721 if (IsAnd)
7722 CR = CR->inverse();
7723
7724 CmpInst::Predicate NewPred;
7725 APInt NewC, Offset;
7726 CR->getEquivalentICmp(NewPred, NewC, Offset);
7727
7728 // We take the result type of one of the original icmps, CmpTy, for
7729 // the to be build icmp. The operand type, CmpOperandTy, is used for
7730 // the other instructions and constants to be build. The types of
7731 // the parameters and output are the same for add and and. CmpTy
7732 // and the type of DstReg might differ. That is why we zext or trunc
7733 // the icmp into the destination register.
7734
7735 MatchInfo = [=](MachineIRBuilder &B) {
7736 if (CreateMask && Offset != 0) {
7737 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
7738 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
7739 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
7740 auto Add = B.buildAdd(CmpOperandTy, And, OffsetC, Flags);
7741 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7742 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
7743 B.buildZExtOrTrunc(DstReg, ICmp);
7744 } else if (CreateMask && Offset == 0) {
7745 auto TildeLowerDiff = B.buildConstant(CmpOperandTy, ~LowerDiff);
7746 auto And = B.buildAnd(CmpOperandTy, R1, TildeLowerDiff); // the mask.
7747 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7748 auto ICmp = B.buildICmp(NewPred, CmpTy, And, NewCon);
7749 B.buildZExtOrTrunc(DstReg, ICmp);
7750 } else if (!CreateMask && Offset != 0) {
7751 auto OffsetC = B.buildConstant(CmpOperandTy, Offset);
7752 auto Add = B.buildAdd(CmpOperandTy, R1, OffsetC, Flags);
7753 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7754 auto ICmp = B.buildICmp(NewPred, CmpTy, Add, NewCon);
7755 B.buildZExtOrTrunc(DstReg, ICmp);
7756 } else if (!CreateMask && Offset == 0) {
7757 auto NewCon = B.buildConstant(CmpOperandTy, NewC);
7758 auto ICmp = B.buildICmp(NewPred, CmpTy, R1, NewCon);
7759 B.buildZExtOrTrunc(DstReg, ICmp);
7760 } else {
7761 llvm_unreachable("unexpected configuration of CreateMask and Offset");
7762 }
7763 };
7764 return true;
7765}
7766
7767bool CombinerHelper::tryFoldLogicOfFCmps(GLogicalBinOp *Logic,
7768 BuildFnTy &MatchInfo) const {
7769 assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpecte xor");
7770 Register DestReg = Logic->getReg(0);
7771 Register LHS = Logic->getLHSReg();
7772 Register RHS = Logic->getRHSReg();
7773 bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
7774
7775 // We need a compare on the LHS register.
7776 GFCmp *Cmp1 = getOpcodeDef<GFCmp>(LHS, MRI);
7777 if (!Cmp1)
7778 return false;
7779
7780 // We need a compare on the RHS register.
7781 GFCmp *Cmp2 = getOpcodeDef<GFCmp>(RHS, MRI);
7782 if (!Cmp2)
7783 return false;
7784
7785 LLT CmpTy = MRI.getType(Cmp1->getReg(0));
7786 LLT CmpOperandTy = MRI.getType(Cmp1->getLHSReg());
7787
7788 // We build one fcmp, want to fold the fcmps, replace the logic op,
7789 // and the fcmps must have the same shape.
7791 {TargetOpcode::G_FCMP, {CmpTy, CmpOperandTy}}) ||
7792 !MRI.hasOneNonDBGUse(Logic->getReg(0)) ||
7793 !MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
7794 !MRI.hasOneNonDBGUse(Cmp2->getReg(0)) ||
7795 MRI.getType(Cmp1->getLHSReg()) != MRI.getType(Cmp2->getLHSReg()))
7796 return false;
7797
7798 CmpInst::Predicate PredL = Cmp1->getCond();
7799 CmpInst::Predicate PredR = Cmp2->getCond();
7800 Register LHS0 = Cmp1->getLHSReg();
7801 Register LHS1 = Cmp1->getRHSReg();
7802 Register RHS0 = Cmp2->getLHSReg();
7803 Register RHS1 = Cmp2->getRHSReg();
7804
7805 if (LHS0 == RHS1 && LHS1 == RHS0) {
7806 // Swap RHS operands to match LHS.
7807 PredR = CmpInst::getSwappedPredicate(PredR);
7808 std::swap(RHS0, RHS1);
7809 }
7810
7811 if (LHS0 == RHS0 && LHS1 == RHS1) {
7812 // We determine the new predicate.
7813 unsigned CmpCodeL = getFCmpCode(PredL);
7814 unsigned CmpCodeR = getFCmpCode(PredR);
7815 unsigned NewPred = IsAnd ? CmpCodeL & CmpCodeR : CmpCodeL | CmpCodeR;
7816 unsigned Flags = Cmp1->getFlags() | Cmp2->getFlags();
7817 MatchInfo = [=](MachineIRBuilder &B) {
7818 // The fcmp predicates fill the lower part of the enum.
7819 FCmpInst::Predicate Pred = static_cast<FCmpInst::Predicate>(NewPred);
7820 if (Pred == FCmpInst::FCMP_FALSE &&
7822 auto False = B.buildConstant(CmpTy, 0);
7823 B.buildZExtOrTrunc(DestReg, False);
7824 } else if (Pred == FCmpInst::FCMP_TRUE &&
7826 auto True =
7827 B.buildConstant(CmpTy, getICmpTrueVal(getTargetLowering(),
7828 CmpTy.isVector() /*isVector*/,
7829 true /*isFP*/));
7830 B.buildZExtOrTrunc(DestReg, True);
7831 } else { // We take the predicate without predicate optimizations.
7832 auto Cmp = B.buildFCmp(Pred, CmpTy, LHS0, LHS1, Flags);
7833 B.buildZExtOrTrunc(DestReg, Cmp);
7834 }
7835 };
7836 return true;
7837 }
7838
7839 return false;
7840}
7841
7843 GAnd *And = cast<GAnd>(&MI);
7844
7845 if (tryFoldAndOrOrICmpsUsingRanges(And, MatchInfo))
7846 return true;
7847
7848 if (tryFoldLogicOfFCmps(And, MatchInfo))
7849 return true;
7850
7851 return false;
7852}
7853
7855 GOr *Or = cast<GOr>(&MI);
7856
7857 if (tryFoldAndOrOrICmpsUsingRanges(Or, MatchInfo))
7858 return true;
7859
7860 if (tryFoldLogicOfFCmps(Or, MatchInfo))
7861 return true;
7862
7863 return false;
7864}
7865
7867 BuildFnTy &MatchInfo) const {
7869
7870 // Addo has no flags
7871 Register Dst = Add->getReg(0);
7872 Register Carry = Add->getReg(1);
7873 Register LHS = Add->getLHSReg();
7874 Register RHS = Add->getRHSReg();
7875 bool IsSigned = Add->isSigned();
7876 LLT DstTy = MRI.getType(Dst);
7877 LLT CarryTy = MRI.getType(Carry);
7878
7879 // Canonicalize constant to RHS.
7880 if (isConstantOrConstantVectorI(LHS) && !isConstantOrConstantVectorI(RHS)) {
7881 if (IsSigned) {
7882 MatchInfo = [=](MachineIRBuilder &B) {
7883 B.buildSAddo(Dst, Carry, RHS, LHS);
7884 };
7885 return true;
7886 }
7887 // !IsSigned
7888 MatchInfo = [=](MachineIRBuilder &B) {
7889 B.buildUAddo(Dst, Carry, RHS, LHS);
7890 };
7891 return true;
7892 }
7893
7894 std::optional<APInt> MaybeLHS = getConstantOrConstantSplatVector(LHS);
7895 std::optional<APInt> MaybeRHS = getConstantOrConstantSplatVector(RHS);
7896
7897 // Fold addo(c1, c2) -> c3, carry.
7898 if (MaybeLHS && MaybeRHS && isConstantLegalOrBeforeLegalizer(DstTy) &&
7900 bool Overflow;
7901 APInt Result = IsSigned ? MaybeLHS->sadd_ov(*MaybeRHS, Overflow)
7902 : MaybeLHS->uadd_ov(*MaybeRHS, Overflow);
7903 MatchInfo = [=](MachineIRBuilder &B) {
7904 B.buildConstant(Dst, Result);
7905 B.buildConstant(Carry, Overflow);
7906 };
7907 return true;
7908 }
7909
7910 // Fold (addo x, 0) -> x, no carry
7911 if (MaybeRHS && *MaybeRHS == 0 && isConstantLegalOrBeforeLegalizer(CarryTy)) {
7912 MatchInfo = [=](MachineIRBuilder &B) {
7913 B.buildCopy(Dst, LHS);
7914 B.buildConstant(Carry, 0);
7915 };
7916 return true;
7917 }
7918
7919 // Given 2 constant operands whose sum does not overflow:
7920 // uaddo (X +nuw C0), C1 -> uaddo X, C0 + C1
7921 // saddo (X +nsw C0), C1 -> saddo X, C0 + C1
7922 GAdd *AddLHS = getOpcodeDef<GAdd>(LHS, MRI);
7923 if (MaybeRHS && AddLHS && MRI.hasOneNonDBGUse(Add->getReg(0)) &&
7924 ((IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoSWrap)) ||
7925 (!IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoUWrap)))) {
7926 std::optional<APInt> MaybeAddRHS =
7927 getConstantOrConstantSplatVector(AddLHS->getRHSReg());
7928 if (MaybeAddRHS) {
7929 bool Overflow;
7930 APInt NewC = IsSigned ? MaybeAddRHS->sadd_ov(*MaybeRHS, Overflow)
7931 : MaybeAddRHS->uadd_ov(*MaybeRHS, Overflow);
7932 if (!Overflow && isConstantLegalOrBeforeLegalizer(DstTy)) {
7933 if (IsSigned) {
7934 MatchInfo = [=](MachineIRBuilder &B) {
7935 auto ConstRHS = B.buildConstant(DstTy, NewC);
7936 B.buildSAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
7937 };
7938 return true;
7939 }
7940 // !IsSigned
7941 MatchInfo = [=](MachineIRBuilder &B) {
7942 auto ConstRHS = B.buildConstant(DstTy, NewC);
7943 B.buildUAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS);
7944 };
7945 return true;
7946 }
7947 }
7948 };
7949
7950 // We try to combine addo to non-overflowing add.
7951 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}}) ||
7953 return false;
7954
7955 // We try to combine uaddo to non-overflowing add.
7956 if (!IsSigned) {
7957 ConstantRange CRLHS =
7958 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/false);
7959 ConstantRange CRRHS =
7960 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/false);
7961
7962 switch (CRLHS.unsignedAddMayOverflow(CRRHS)) {
7964 return false;
7966 MatchInfo = [=](MachineIRBuilder &B) {
7967 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
7968 B.buildConstant(Carry, 0);
7969 };
7970 return true;
7971 }
7974 MatchInfo = [=](MachineIRBuilder &B) {
7975 B.buildAdd(Dst, LHS, RHS);
7976 B.buildConstant(Carry, 1);
7977 };
7978 return true;
7979 }
7980 }
7981 return false;
7982 }
7983
7984 // We try to combine saddo to non-overflowing add.
7985
7986 // If LHS and RHS each have at least two sign bits, then there is no signed
7987 // overflow.
7988 if (VT->computeNumSignBits(RHS) > 1 && VT->computeNumSignBits(LHS) > 1) {
7989 MatchInfo = [=](MachineIRBuilder &B) {
7990 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
7991 B.buildConstant(Carry, 0);
7992 };
7993 return true;
7994 }
7995
7996 ConstantRange CRLHS =
7997 ConstantRange::fromKnownBits(VT->getKnownBits(LHS), /*IsSigned=*/true);
7998 ConstantRange CRRHS =
7999 ConstantRange::fromKnownBits(VT->getKnownBits(RHS), /*IsSigned=*/true);
8000
8001 switch (CRLHS.signedAddMayOverflow(CRRHS)) {
8003 return false;
8005 MatchInfo = [=](MachineIRBuilder &B) {
8006 B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8007 B.buildConstant(Carry, 0);
8008 };
8009 return true;
8010 }
8013 MatchInfo = [=](MachineIRBuilder &B) {
8014 B.buildAdd(Dst, LHS, RHS);
8015 B.buildConstant(Carry, 1);
8016 };
8017 return true;
8018 }
8019 }
8020
8021 return false;
8022}
8023
8025 BuildFnTy &MatchInfo) const {
8027 MatchInfo(Builder);
8028 Root->eraseFromParent();
8029}
8030
8032 int64_t Exponent) const {
8033 bool OptForSize = MI.getMF()->getFunction().hasOptSize();
8035}
8036
8038 int64_t Exponent) const {
8039 auto [Dst, Base] = MI.getFirst2Regs();
8040 LLT Ty = MRI.getType(Dst);
8041 int64_t ExpVal = Exponent;
8042
8043 if (ExpVal == 0) {
8044 Builder.buildFConstant(Dst, 1.0);
8045 MI.removeFromParent();
8046 return;
8047 }
8048
8049 if (ExpVal < 0)
8050 ExpVal = -ExpVal;
8051
8052 // We use the simple binary decomposition method from SelectionDAG ExpandPowI
8053 // to generate the multiply sequence. There are more optimal ways to do this
8054 // (for example, powi(x,15) generates one more multiply than it should), but
8055 // this has the benefit of being both really simple and much better than a
8056 // libcall.
8057 std::optional<SrcOp> Res;
8058 SrcOp CurSquare = Base;
8059 while (ExpVal > 0) {
8060 if (ExpVal & 1) {
8061 if (!Res)
8062 Res = CurSquare;
8063 else
8064 Res = Builder.buildFMul(Ty, *Res, CurSquare);
8065 }
8066
8067 CurSquare = Builder.buildFMul(Ty, CurSquare, CurSquare);
8068 ExpVal >>= 1;
8069 }
8070
8071 // If the original exponent was negative, invert the result, producing
8072 // 1/(x*x*x).
8073 if (Exponent < 0)
8074 Res = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0), *Res,
8075 MI.getFlags());
8076
8077 Builder.buildCopy(Dst, *Res);
8078 MI.eraseFromParent();
8079}
8080
8082 BuildFnTy &MatchInfo) const {
8083 // fold (A+C1)-C2 -> A+(C1-C2)
8084 const GSub *Sub = cast<GSub>(&MI);
8085 Register A, C1Reg;
8086 if (!mi_match(Sub->getLHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8087 return false;
8088
8089 if (!MRI.hasOneNonDBGUse(Sub->getLHSReg()))
8090 return false;
8091
8092 APInt C2 = getIConstantFromReg(Sub->getRHSReg(), MRI);
8093 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8094
8095 Register Dst = Sub->getReg(0);
8096 LLT DstTy = MRI.getType(Dst);
8097
8098 MatchInfo = [=](MachineIRBuilder &B) {
8099 auto Const = B.buildConstant(DstTy, C1 - C2);
8100 B.buildAdd(Dst, A, Const);
8101 };
8102
8103 return true;
8104}
8105
8107 BuildFnTy &MatchInfo) const {
8108 // fold C2-(A+C1) -> (C2-C1)-A
8109 const GSub *Sub = cast<GSub>(&MI);
8110 Register A, C1Reg;
8111 if (!mi_match(Sub->getRHSReg(), MRI, m_GAdd(m_Reg(A), m_Reg(C1Reg))))
8112 return false;
8113
8114 if (!MRI.hasOneNonDBGUse(Sub->getRHSReg()))
8115 return false;
8116
8117 APInt C2 = getIConstantFromReg(Sub->getLHSReg(), MRI);
8118 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8119
8120 Register Dst = Sub->getReg(0);
8121 LLT DstTy = MRI.getType(Dst);
8122
8123 MatchInfo = [=](MachineIRBuilder &B) {
8124 auto Const = B.buildConstant(DstTy, C2 - C1);
8125 B.buildSub(Dst, Const, A);
8126 };
8127
8128 return true;
8129}
8130
8132 BuildFnTy &MatchInfo) const {
8133 // fold (A-C1)-C2 -> A-(C1+C2)
8134 const GSub *Sub1 = cast<GSub>(&MI);
8135 Register A, C1Reg;
8136 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8137 return false;
8138
8139 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8140 return false;
8141
8142 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8143 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8144
8145 Register Dst = Sub1->getReg(0);
8146 LLT DstTy = MRI.getType(Dst);
8147
8148 MatchInfo = [=](MachineIRBuilder &B) {
8149 auto Const = B.buildConstant(DstTy, C1 + C2);
8150 B.buildSub(Dst, A, Const);
8151 };
8152
8153 return true;
8154}
8155
8157 BuildFnTy &MatchInfo) const {
8158 // fold (C1-A)-C2 -> (C1-C2)-A
8159 const GSub *Sub1 = cast<GSub>(&MI);
8160 Register C1Reg, A;
8161 if (!mi_match(Sub1->getLHSReg(), MRI, m_GSub(m_Reg(C1Reg), m_Reg(A))))
8162 return false;
8163
8164 if (!MRI.hasOneNonDBGUse(Sub1->getLHSReg()))
8165 return false;
8166
8167 APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
8168 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8169
8170 Register Dst = Sub1->getReg(0);
8171 LLT DstTy = MRI.getType(Dst);
8172
8173 MatchInfo = [=](MachineIRBuilder &B) {
8174 auto Const = B.buildConstant(DstTy, C1 - C2);
8175 B.buildSub(Dst, Const, A);
8176 };
8177
8178 return true;
8179}
8180
8182 BuildFnTy &MatchInfo) const {
8183 // fold ((A-C1)+C2) -> (A+(C2-C1))
8184 const GAdd *Add = cast<GAdd>(&MI);
8185 Register A, C1Reg;
8186 if (!mi_match(Add->getLHSReg(), MRI, m_GSub(m_Reg(A), m_Reg(C1Reg))))
8187 return false;
8188
8189 if (!MRI.hasOneNonDBGUse(Add->getLHSReg()))
8190 return false;
8191
8192 APInt C2 = getIConstantFromReg(Add->getRHSReg(), MRI);
8193 APInt C1 = getIConstantFromReg(C1Reg, MRI);
8194
8195 Register Dst = Add->getReg(0);
8196 LLT DstTy = MRI.getType(Dst);
8197
8198 MatchInfo = [=](MachineIRBuilder &B) {
8199 auto Const = B.buildConstant(DstTy, C2 - C1);
8200 B.buildAdd(Dst, A, Const);
8201 };
8202
8203 return true;
8204}
8205
8207 const MachineInstr &MI, BuildFnTy &MatchInfo) const {
8208 const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
8209
8210 if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
8211 return false;
8212
8213 LLT DstTy = MRI.getType(Unmerge->getReg(0));
8214
8215 // $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
8216 // $any:_(<8 x s16>) = G_ANYEXT $bv
8217 // $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
8218 //
8219 // ->
8220 //
8221 // $any:_(s16) = G_ANYEXT $bv[0]
8222 // $any1:_(s16) = G_ANYEXT $bv[1]
8223 // $any2:_(s16) = G_ANYEXT $bv[2]
8224 // $any3:_(s16) = G_ANYEXT $bv[3]
8225 // $any4:_(s16) = G_ANYEXT $bv[4]
8226 // $any5:_(s16) = G_ANYEXT $bv[5]
8227 // $any6:_(s16) = G_ANYEXT $bv[6]
8228 // $any7:_(s16) = G_ANYEXT $bv[7]
8229 // $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
8230 // $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7
8231
8232 // We want to unmerge into vectors.
8233 if (!DstTy.isFixedVector())
8234 return false;
8235
8236 Register AnySrcReg;
8237 if (!mi_match(Unmerge->getSourceReg(), MRI, m_GAnyExt(m_Reg(AnySrcReg))))
8238 return false;
8239
8240 GBuildVector *BV;
8241 if (mi_match(AnySrcReg, MRI, m_GBuildVector(BV))) {
8242 // G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR
8243
8244 if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
8245 return false;
8246
8247 // FIXME: check element types?
8248 if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
8249 return false;
8250
8251 LLT BigBvTy = MRI.getType(BV->getReg(0));
8252 LLT SmallBvTy = DstTy;
8253 LLT SmallBvElemenTy = SmallBvTy.getElementType();
8254
8256 {TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
8257 return false;
8258
8259 // We check the legality of scalar anyext.
8261 {TargetOpcode::G_ANYEXT,
8262 {SmallBvElemenTy, BigBvTy.getElementType()}}))
8263 return false;
8264
8265 MatchInfo = [=](MachineIRBuilder &B) {
8266 // Build into each G_UNMERGE_VALUES def
8267 // a small build vector with anyext from the source build vector.
8268 for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
8270 for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
8271 Register SourceArray =
8272 BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
8273 auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
8274 Ops.push_back(AnyExt.getReg(0));
8275 }
8276 B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
8277 };
8278 };
8279 return true;
8280 };
8281
8282 return false;
8283}
8284
8286 BuildFnTy &MatchInfo) const {
8287
8288 bool Changed = false;
8289 auto &Shuffle = cast<GShuffleVector>(MI);
8290 ArrayRef<int> OrigMask = Shuffle.getMask();
8291 SmallVector<int, 16> NewMask;
8292 const LLT SrcTy = MRI.getType(Shuffle.getSrc1Reg());
8293 const unsigned NumSrcElems = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
8294 const unsigned NumDstElts = OrigMask.size();
8295 for (unsigned i = 0; i != NumDstElts; ++i) {
8296 int Idx = OrigMask[i];
8297 if (Idx >= (int)NumSrcElems) {
8298 Idx = -1;
8299 Changed = true;
8300 }
8301 NewMask.push_back(Idx);
8302 }
8303
8304 if (!Changed)
8305 return false;
8306
8307 MatchInfo = [&, NewMask = std::move(NewMask)](MachineIRBuilder &B) {
8308 B.buildShuffleVector(MI.getOperand(0), MI.getOperand(1), MI.getOperand(2),
8309 std::move(NewMask));
8310 };
8311
8312 return true;
8313}
8314
8315static void commuteMask(MutableArrayRef<int> Mask, const unsigned NumElems) {
8316 const unsigned MaskSize = Mask.size();
8317 for (unsigned I = 0; I < MaskSize; ++I) {
8318 int Idx = Mask[I];
8319 if (Idx < 0)
8320 continue;
8321
8322 if (Idx < (int)NumElems)
8323 Mask[I] = Idx + NumElems;
8324 else
8325 Mask[I] = Idx - NumElems;
8326 }
8327}
8328
8330 BuildFnTy &MatchInfo) const {
8331
8332 auto &Shuffle = cast<GShuffleVector>(MI);
8333 // If any of the two inputs is already undef, don't check the mask again to
8334 // prevent infinite loop
8335 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(), MRI))
8336 return false;
8337
8338 if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(), MRI))
8339 return false;
8340
8341 const LLT DstTy = MRI.getType(Shuffle.getReg(0));
8342 const LLT Src1Ty = MRI.getType(Shuffle.getSrc1Reg());
8344 {TargetOpcode::G_SHUFFLE_VECTOR, {DstTy, Src1Ty}}))
8345 return false;
8346
8347 ArrayRef<int> Mask = Shuffle.getMask();
8348 const unsigned NumSrcElems = Src1Ty.getNumElements();
8349
8350 bool TouchesSrc1 = false;
8351 bool TouchesSrc2 = false;
8352 const unsigned NumElems = Mask.size();
8353 for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
8354 if (Mask[Idx] < 0)
8355 continue;
8356
8357 if (Mask[Idx] < (int)NumSrcElems)
8358 TouchesSrc1 = true;
8359 else
8360 TouchesSrc2 = true;
8361 }
8362
8363 if (TouchesSrc1 == TouchesSrc2)
8364 return false;
8365
8366 Register NewSrc1 = Shuffle.getSrc1Reg();
8367 SmallVector<int, 16> NewMask(Mask);
8368 if (TouchesSrc2) {
8369 NewSrc1 = Shuffle.getSrc2Reg();
8370 commuteMask(NewMask, NumSrcElems);
8371 }
8372
8373 MatchInfo = [=, &Shuffle](MachineIRBuilder &B) {
8374 auto Undef = B.buildUndef(Src1Ty);
8375 B.buildShuffleVector(Shuffle.getReg(0), NewSrc1, Undef, NewMask);
8376 };
8377
8378 return true;
8379}
8380
8382 BuildFnTy &MatchInfo) const {
8383 const GSubCarryOut *Subo = cast<GSubCarryOut>(&MI);
8384
8385 Register Dst = Subo->getReg(0);
8386 Register LHS = Subo->getLHSReg();
8387 Register RHS = Subo->getRHSReg();
8388 Register Carry = Subo->getCarryOutReg();
8389 LLT DstTy = MRI.getType(Dst);
8390 LLT CarryTy = MRI.getType(Carry);
8391
8392 // Check legality before known bits.
8393 if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SUB, {DstTy}}) ||
8395 return false;
8396
8397 ConstantRange KBLHS =
8398 ConstantRange::fromKnownBits(VT->getKnownBits(LHS),
8399 /* IsSigned=*/Subo->isSigned());
8400 ConstantRange KBRHS =
8401 ConstantRange::fromKnownBits(VT->getKnownBits(RHS),
8402 /* IsSigned=*/Subo->isSigned());
8403
8404 if (Subo->isSigned()) {
8405 // G_SSUBO
8406 switch (KBLHS.signedSubMayOverflow(KBRHS)) {
8408 return false;
8410 MatchInfo = [=](MachineIRBuilder &B) {
8411 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap);
8412 B.buildConstant(Carry, 0);
8413 };
8414 return true;
8415 }
8418 MatchInfo = [=](MachineIRBuilder &B) {
8419 B.buildSub(Dst, LHS, RHS);
8420 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8421 /*isVector=*/CarryTy.isVector(),
8422 /*isFP=*/false));
8423 };
8424 return true;
8425 }
8426 }
8427 return false;
8428 }
8429
8430 // G_USUBO
8431 switch (KBLHS.unsignedSubMayOverflow(KBRHS)) {
8433 return false;
8435 MatchInfo = [=](MachineIRBuilder &B) {
8436 B.buildSub(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap);
8437 B.buildConstant(Carry, 0);
8438 };
8439 return true;
8440 }
8443 MatchInfo = [=](MachineIRBuilder &B) {
8444 B.buildSub(Dst, LHS, RHS);
8445 B.buildConstant(Carry, getICmpTrueVal(getTargetLowering(),
8446 /*isVector=*/CarryTy.isVector(),
8447 /*isFP=*/false));
8448 };
8449 return true;
8450 }
8451 }
8452
8453 return false;
8454}
8455
8456// Fold (ctlz (xor x, (sra x, bitwidth-1))) -> (add (ctls x), 1).
8457// Fold (ctlz (or (shl (xor x, (sra x, bitwidth-1)), 1), 1) -> (ctls x)
8459 BuildFnTy &MatchInfo) const {
8460 assert((CtlzMI.getOpcode() == TargetOpcode::G_CTLZ ||
8461 CtlzMI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON) &&
8462 "Expected G_CTLZ variant");
8463
8464 const Register Dst = CtlzMI.getOperand(0).getReg();
8465 Register Src = CtlzMI.getOperand(1).getReg();
8466
8467 LLT Ty = MRI.getType(Dst);
8468 LLT SrcTy = MRI.getType(Src);
8469
8470 if (!(Ty.isValid() && Ty.isScalar()))
8471 return false;
8472
8473 if (!LI)
8474 return false;
8475
8476 SmallVector<LLT, 2> QueryTypes = {Ty, SrcTy};
8477 LegalityQuery Query(TargetOpcode::G_CTLS, QueryTypes);
8478
8479 switch (LI->getAction(Query).Action) {
8480 default:
8481 return false;
8485 break;
8486 }
8487
8488 // Src = or(shl(V, 1), 1) -> Src=V; NeedAdd = False
8489 Register V;
8490 bool NeedAdd = true;
8491 if (mi_match(Src, MRI,
8493 m_SpecificICst(1))))) {
8494 NeedAdd = false;
8495 Src = V;
8496 }
8497
8498 unsigned BitWidth = Ty.getScalarSizeInBits();
8499
8500 Register X;
8501 if (!mi_match(Src, MRI,
8504 m_SpecificICst(BitWidth - 1)))))))
8505 return false;
8506
8507 MatchInfo = [=](MachineIRBuilder &B) {
8508 if (!NeedAdd) {
8509 B.buildCTLS(Dst, X);
8510 return;
8511 }
8512
8513 auto Ctls = B.buildCTLS(Ty, X);
8514 auto One = B.buildConstant(Ty, 1);
8515
8516 B.buildAdd(Dst, Ctls, One);
8517 };
8518
8519 return true;
8520}
8521
8523 const ConstantFP *C = getConstantFPVRegVal(Reg, MRI);
8524 return C && C->getValueAPF().isNaN();
8525}
8526
8528 unsigned ZeroPoisonOpc) const {
8529 const bool IsCtlzPair = Opc == TargetOpcode::G_CTLZ &&
8530 ZeroPoisonOpc == TargetOpcode::G_CTLZ_ZERO_POISON;
8531 const bool IsCttzPair = Opc == TargetOpcode::G_CTTZ &&
8532 ZeroPoisonOpc == TargetOpcode::G_CTTZ_ZERO_POISON;
8533 if (MI.getOpcode() != Opc || (!IsCtlzPair && !IsCttzPair))
8534 return false;
8535 if (!VT)
8536 return false;
8537
8538 Register Src = MI.getOperand(1).getReg();
8539 if (!VT->isKnownNeverZero(Src))
8540 return false;
8541
8542 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
8543 LLT SrcTy = MRI.getType(Src);
8544 return isLegalOrBeforeLegalizer({ZeroPoisonOpc, {DstTy, SrcTy}});
8545}
8546
8547static APInt getDemandedBitsForLogicalOp(unsigned Opcode, const APInt &Demanded,
8548 const KnownBits &OtherKnown) {
8549 assert((Opcode == TargetOpcode::G_AND || Opcode == TargetOpcode::G_OR) &&
8550 "Expected G_AND or G_OR");
8551 return Demanded &
8552 ~(Opcode == TargetOpcode::G_AND ? OtherKnown.Zero : OtherKnown.One);
8553}
8554
8555static std::optional<unsigned>
8556getValidConstShiftAmt(const std::optional<APInt> &Amt, unsigned BW) {
8557 if (!Amt || Amt->uge(BW))
8558 return std::nullopt;
8559 return Amt->getZExtValue();
8560}
8561
8563 const APInt &DemandedBits,
8564 unsigned ShAmt) {
8565 assert(ShAmt < DemandedBits.getBitWidth() &&
8566 "shift amount must be less than the bit width");
8567 switch (Opcode) {
8568 case TargetOpcode::G_SHL:
8569 return DemandedBits.lshr(ShAmt);
8570 case TargetOpcode::G_LSHR:
8571 return DemandedBits.shl(ShAmt);
8572 case TargetOpcode::G_ASHR: {
8573 APInt Src = DemandedBits.shl(ShAmt);
8574 if (DemandedBits.countLeadingZeros() < ShAmt)
8575 Src.setSignBit();
8576 return Src;
8577 }
8578 default:
8579 llvm_unreachable("not a shift opcode");
8580 }
8581}
8582
8583Register CombinerHelper::simplifyMultipleUseDemandedBits(
8584 Register R, const APInt &DemandedBits, unsigned Depth) const {
8585 assert(R.isVirtual() && "Expected a virtual register");
8586 assert(!DemandedBits.isZero() && "Zero demand is handled by the caller");
8588 return Register();
8589
8590 [[maybe_unused]] LLT Ty = MRI.getType(R);
8591 assert(Ty.isValid() && "Expected a typed register");
8592 assert(DemandedBits.getBitWidth() == Ty.getScalarSizeInBits() &&
8593 "DemandedBits width must match the register scalar type");
8594
8595 MachineInstr *DefMI = MRI.getVRegDef(R);
8596 assert(DefMI && "Expected a definition in generic SSA MIR");
8597 if (!isa<GAnd>(DefMI) && !isa<GOr>(DefMI))
8598 return Register();
8599
8600 unsigned Opcode = DefMI->getOpcode();
8601 auto *Logic = cast<GLogicalBinOp>(DefMI);
8602 Register LHS = Logic->getLHSReg();
8603 Register RHS = Logic->getRHSReg();
8604 assert(MRI.getType(LHS) == Ty && MRI.getType(RHS) == Ty &&
8605 "Logical operands must match the result type");
8606
8607 auto LookThrough = [&](Register X, Register CReg) -> Register {
8608 std::optional<APInt> C = getConstantOrConstantSplatVector(CReg);
8609 if (!C || C->getBitWidth() != DemandedBits.getBitWidth())
8610 return Register();
8611 bool BypassToX = Opcode == TargetOpcode::G_AND
8612 ? DemandedBits.isSubsetOf(*C)
8613 : DemandedBits.isSubsetOf(~*C);
8614 if (BypassToX) {
8615 if (Register Deeper =
8616 simplifyMultipleUseDemandedBits(X, DemandedBits, Depth + 1))
8617 return Deeper;
8618 return X;
8619 }
8620 bool BypassToC = Opcode == TargetOpcode::G_AND
8621 ? DemandedBits.isSubsetOf(~*C)
8622 : DemandedBits.isSubsetOf(*C);
8623 if (BypassToC)
8624 return CReg;
8625 return Register();
8626 };
8627
8628 if (Register Repl = LookThrough(LHS, RHS))
8629 return Repl;
8630 return LookThrough(RHS, LHS);
8631}
8632
8633bool CombinerHelper::simplifyDemandedBitsImpl(MachineInstr &MI, unsigned OpNo,
8634 const APInt &DemandedBits,
8635 KnownBits &Known, unsigned Depth,
8636 bool DoRewrite) const {
8637 Known = KnownBits(DemandedBits.getBitWidth());
8638 assert(MI.getOperand(OpNo).isReg() && !MI.getOperand(OpNo).isDef() &&
8639 "Expected a register use");
8640 Register OpReg = MI.getOperand(OpNo).getReg();
8641 assert(OpReg.isVirtual() && "Expected a virtual register");
8642 LLT OpTy = MRI.getType(OpReg);
8643 assert(OpTy.isValid() && "Expected a typed register");
8644 assert(DemandedBits.getBitWidth() == OpTy.getScalarSizeInBits() &&
8645 "DemandedBits width must match the operand scalar type");
8646
8647 MachineInstr *DefMI = MRI.getVRegDef(OpReg);
8648 assert(DefMI && "Expected a definition in generic SSA MIR");
8649 // Undemanded bits can still affect poison-generating flags in the user.
8650 auto DropPoisonFlags = [&]() {
8651 if (!DoRewrite ||
8653 return;
8654 Observer.changingInstr(MI);
8656 Observer.changedInstr(MI);
8657 };
8658 // Debug users can observe bits that are not demanded by other users.
8659 auto InvalidateDebugUses = [&](const APInt &Demanded) {
8660 if (DoRewrite && !Demanded.isAllOnes())
8661 MRI.markUsesInDebugValueAsUndef(OpReg);
8662 };
8663 auto Rewrite = [&](Register Repl) {
8664 if (!DoRewrite || Repl == OpReg)
8665 return Repl != OpReg;
8666 DropPoisonFlags();
8667 if (DefMI->getNumExplicitDefs() == 1 && MRI.hasOneNonDBGUse(OpReg)) {
8668 InvalidateDebugUses(DemandedBits);
8669 replaceRegWith(MRI, OpReg, Repl);
8670 eraseInst(*DefMI);
8671 } else {
8672 replaceRegOpWith(MRI, MI.getOperand(OpNo), Repl);
8673 }
8674 return true;
8675 };
8676
8677 if (DemandedBits.isZero()) {
8678 if (DefMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
8679 return false;
8680 if (!DoRewrite)
8681 return true;
8682 MachineBasicBlock &SaveMBB = Builder.getMBB();
8683 MachineBasicBlock::iterator SavePt = Builder.getInsertPt();
8684 DebugLoc SaveDL = Builder.getDL();
8685 Builder.setInstrAndDebugLoc(MI);
8686 Register Undef = Builder.buildUndef(OpTy).getReg(0);
8687 Builder.setInsertPt(SaveMBB, SavePt);
8688 Builder.setDebugLoc(SaveDL);
8689 // The producer may have side effects; replace only this use.
8690 DropPoisonFlags();
8691 replaceRegOpWith(MRI, MI.getOperand(OpNo), Undef);
8692 return true;
8693 }
8694
8695 if (!VT)
8696 return false;
8697
8698 unsigned BW = DemandedBits.getBitWidth();
8699 auto GiveUp = [&]() {
8700 APInt DemandedElts = OpTy.isFixedVector()
8702 : APInt(1, 1);
8703 Known = VT->getKnownBits(OpReg, DemandedElts, Depth);
8704 return false;
8705 };
8706
8708 return GiveUp();
8709
8710 // Shared defs require full demand unless this use can be rerouted to an
8711 // existing value that agrees on its demanded bits.
8712 APInt Demanded = DemandedBits;
8713 if (!MRI.hasOneNonDBGUse(OpReg) && !Demanded.isAllOnes()) {
8714 if (Register Repl =
8715 simplifyMultipleUseDemandedBits(OpReg, Demanded, Depth)) {
8716 Known = VT->getKnownBits(Repl);
8717 if (Rewrite(Repl))
8718 return true;
8719 }
8720 Demanded = APInt::getAllOnes(BW);
8721 }
8722
8723 unsigned Opcode = DefMI->getOpcode();
8724 switch (Opcode) {
8725 case TargetOpcode::G_AND:
8726 case TargetOpcode::G_OR: {
8727 auto *Logic = cast<GLogicalBinOp>(DefMI);
8728 Register LHS = Logic->getLHSReg();
8729 Register RHS = Logic->getRHSReg();
8730 assert(MRI.getType(LHS) == OpTy && MRI.getType(RHS) == OpTy &&
8731 "Logical operands must match the result type");
8732 auto SimplifyWithConst = [&](Register X,
8733 Register CReg) -> std::optional<Register> {
8734 std::optional<APInt> C = getConstantOrConstantSplatVector(CReg);
8735 if (!C)
8736 return std::nullopt;
8737 assert(C->getBitWidth() == BW && "Constant width must match its type");
8738 // Check redundancy before rewriting X can change its known bits.
8739 if (Opcode == TargetOpcode::G_AND) {
8740 if (Demanded.isSubsetOf(*C | VT->getKnownBits(X).Zero))
8741 return X;
8742 if (Demanded.isSubsetOf(~*C))
8743 return CReg;
8744 return std::nullopt;
8745 }
8746 if (Demanded.isSubsetOf(~*C | VT->getKnownBits(X).One))
8747 return X;
8748 if (Demanded.isSubsetOf(*C))
8749 return CReg;
8750 return std::nullopt;
8751 };
8752
8753 // Compute known bits before a rewrite can erase the def.
8754 if (std::optional<Register> Repl = SimplifyWithConst(LHS, RHS)) {
8755 Known = VT->getKnownBits(*Repl);
8756 if (Rewrite(*Repl))
8757 return true;
8758 }
8759 if (std::optional<Register> Repl = SimplifyWithConst(RHS, LHS)) {
8760 Known = VT->getKnownBits(*Repl);
8761 if (Rewrite(*Repl))
8762 return true;
8763 }
8764
8765 KnownBits RHSKnown(BW);
8766 bool Changed = simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/2, Demanded,
8767 RHSKnown, Depth + 1, DoRewrite);
8768 APInt LHSDemand = getDemandedBitsForLogicalOp(Opcode, Demanded, RHSKnown);
8769 KnownBits LHSKnown(BW);
8770 Changed |= simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/1, LHSDemand, LHSKnown,
8771 Depth + 1, DoRewrite);
8772 if (!Changed && MRI.hasOneNonDBGUse(RHS) &&
8773 !getConstantOrConstantSplatVector(RHS)) {
8774 // Reduced-demand LHS facts cannot justify reducing the RHS demand.
8775 APInt RHSDemand =
8776 LHSDemand == Demanded
8777 ? getDemandedBitsForLogicalOp(Opcode, Demanded, LHSKnown)
8779 Opcode, Demanded,
8780 VT->getKnownBits(
8781 LHS,
8782 OpTy.isFixedVector()
8783 ? APInt::getAllOnes(OpTy.getNumElements())
8784 : APInt(1, 1),
8785 Depth + 1));
8786 if (RHSDemand != Demanded) {
8787 // Keep full-demand RHS facts if the reduced-demand retry fails.
8788 KnownBits RetryKnown(BW);
8789 Changed = simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/2, RHSDemand,
8790 RetryKnown, Depth + 1, DoRewrite);
8791 }
8792 }
8793 if (Changed) {
8794 DropPoisonFlags();
8795 InvalidateDebugUses(Demanded);
8796 }
8797 Known = Opcode == TargetOpcode::G_AND ? LHSKnown & RHSKnown
8798 : LHSKnown | RHSKnown;
8799 return Changed;
8800 }
8801 case TargetOpcode::G_SHL:
8802 case TargetOpcode::G_LSHR:
8803 case TargetOpcode::G_ASHR: {
8804 std::optional<unsigned> ShAmt = getValidConstShiftAmt(
8805 getConstantOrConstantSplatVector(DefMI->getOperand(2).getReg()), BW);
8806 if (!ShAmt)
8807 return GiveUp();
8808
8809 APInt SrcDemand = getDemandedSrcBitsForShiftConst(Opcode, Demanded, *ShAmt);
8810 KnownBits SrcKnown(BW);
8811 bool Changed = simplifyDemandedBitsImpl(*DefMI, /*OpNo=*/1, SrcDemand,
8812 SrcKnown, Depth + 1, DoRewrite);
8813 if (Changed) {
8814 DropPoisonFlags();
8815 InvalidateDebugUses(Demanded);
8816 }
8817 KnownBits AmtKnown = KnownBits::makeConstant(APInt(BW, *ShAmt));
8818 switch (Opcode) {
8819 case TargetOpcode::G_SHL:
8820 Known = KnownBits::shl(SrcKnown, AmtKnown);
8821 break;
8822 case TargetOpcode::G_LSHR:
8823 Known = KnownBits::lshr(SrcKnown, AmtKnown);
8824 break;
8825 case TargetOpcode::G_ASHR: {
8826 // ASHR and LSHR agree outside sign fill or for nonnegative inputs.
8827 LLT AmtTy = MRI.getType(DefMI->getOperand(2).getReg());
8828 bool LShrLegal = isPreLegalize() || !LI ||
8829 isLegal({TargetOpcode::G_LSHR, {OpTy, AmtTy}});
8830 if ((Demanded.countLeadingZeros() >= *ShAmt ||
8831 SrcKnown.isNonNegative()) &&
8832 LShrLegal) {
8833 if (DoRewrite) {
8834 MachineBasicBlock &SaveMBB = Builder.getMBB();
8835 MachineBasicBlock::iterator SavePt = Builder.getInsertPt();
8836 DebugLoc SaveDL = Builder.getDL();
8837 Builder.setInstrAndDebugLoc(*DefMI);
8838 auto Lshr = Builder.buildLShr(OpTy, DefMI->getOperand(1).getReg(),
8839 DefMI->getOperand(2).getReg());
8840 Builder.setInsertPt(SaveMBB, SavePt);
8841 Builder.setDebugLoc(SaveDL);
8842 Rewrite(Lshr.getReg(0));
8843 Known = KnownBits::lshr(SrcKnown, AmtKnown);
8844 }
8845 return true;
8846 }
8847 Known = KnownBits::ashr(SrcKnown, AmtKnown);
8848 break;
8849 }
8850 }
8851 return Changed;
8852 }
8853 default:
8854 return GiveUp();
8855 }
8856}
8857
8859 const APInt &DemandedBits,
8861 unsigned Depth) const {
8862 return simplifyDemandedBitsImpl(MI, OpNo, DemandedBits, Known, Depth,
8863 /*DoRewrite=*/true);
8864}
8865
8867 BuildFnTy &MatchInfo) const {
8868 Register Dst = MI.getOperand(0).getReg();
8869 LLT Ty = MRI.getType(Dst);
8870 assert(Ty.isValid() && "Expected a typed generic result");
8871 if (!VT || Ty.isVector())
8872 return false;
8873
8874 APInt RootDemand = APInt::getAllOnes(Ty.getScalarSizeInBits());
8875 auto Probe = [&](unsigned OpNo, const APInt &OpDemand, KnownBits &Known) {
8876 if (!simplifyDemandedBitsImpl(MI, OpNo, OpDemand, Known, /*Depth=*/0,
8877 /*DoRewrite=*/false))
8878 return false;
8879
8880 MatchInfo = [this, &MI, OpNo, OpDemand](MachineIRBuilder &) {
8881 KnownBits K(OpDemand.getBitWidth());
8882 simplifyDemandedBits(MI, OpNo, OpDemand, K);
8883 };
8884 return true;
8885 };
8886
8887 unsigned Opcode = MI.getOpcode();
8888 switch (Opcode) {
8889 case TargetOpcode::G_SHL:
8890 case TargetOpcode::G_LSHR:
8891 case TargetOpcode::G_ASHR: {
8892 std::optional<unsigned> ShAmt = getValidConstShiftAmt(
8893 getConstantOrConstantSplatVector(MI.getOperand(2).getReg()),
8894 RootDemand.getBitWidth());
8895 if (!ShAmt)
8896 return false;
8897 APInt SrcDemand =
8898 getDemandedSrcBitsForShiftConst(Opcode, RootDemand, *ShAmt);
8899 KnownBits SrcKnown(RootDemand.getBitWidth());
8900 return Probe(/*OpNo=*/1, SrcDemand, SrcKnown);
8901 }
8902 default:
8903 return false;
8904 case TargetOpcode::G_AND:
8905 case TargetOpcode::G_OR: {
8906 // Let redundant_and/redundant_or fold the root before operand rewrites can
8907 // discard the known bits that make it redundant.
8908 KnownBits L = VT->getKnownBits(MI.getOperand(1).getReg());
8909 KnownBits R = VT->getKnownBits(MI.getOperand(2).getReg());
8910 bool RootRedundant = Opcode == TargetOpcode::G_AND
8911 ? RootDemand.isSubsetOf(L.Zero | R.One) ||
8912 RootDemand.isSubsetOf(R.Zero | L.One)
8913 : RootDemand.isSubsetOf(L.One | R.Zero) ||
8914 RootDemand.isSubsetOf(R.One | L.Zero);
8915 if (RootRedundant)
8916 return false;
8917
8918 KnownBits RHSKnown(RootDemand.getBitWidth());
8919 if (Probe(/*OpNo=*/2, RootDemand, RHSKnown))
8920 return true;
8921
8922 APInt LHSDemand = getDemandedBitsForLogicalOp(Opcode, RootDemand, RHSKnown);
8923
8924 KnownBits LHSKnown(RootDemand.getBitWidth());
8925 if (Probe(/*OpNo=*/1, LHSDemand, LHSKnown))
8926 return true;
8927
8928 Register RHS = MI.getOperand(2).getReg();
8929 if (!MRI.hasOneNonDBGUse(RHS) || getConstantOrConstantSplatVector(RHS))
8930 return false;
8931
8932 APInt RHSDemand =
8933 LHSDemand == RootDemand
8934 ? getDemandedBitsForLogicalOp(Opcode, RootDemand, LHSKnown)
8936 Opcode, RootDemand,
8937 VT->getKnownBits(MI.getOperand(1).getReg()));
8938 KnownBits RetryKnown(RootDemand.getBitWidth());
8939 return RHSDemand != RootDemand && Probe(/*OpNo=*/2, RHSDemand, RetryKnown);
8940 }
8941 }
8942}
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 matchUDivByShiftedPow2(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine unsigned division by a shifted power of two into a right shift.
LLVM_ABI bool matchSameRegOrICstOrSplat(Register A, Register B) const
True when A and B are the same register, including through copies, or different registers holding the...
LLVM_ABI void applyLshrOfTruncOfLshr(MachineInstr &MI, LshrOfTruncOfLshr &MatchInfo) const
LLVM_ABI bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0) const
Optimize memcpy intrinsics et al, e.g.
LLVM_ABI bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI void applySDivOrSRemByConst(MachineInstr &MI) const
LLVM_ABI bool matchCombineMemCpyFamily(MachineInstr &MI, MemCpyFamilyLoweringInfo &MatchInfo, unsigned MaxLen=0) const
LLVM_ABI MachineInstr * buildSDivOrSRemUsingMul(MachineInstr &MI) const
Given an G_SDIV MI or G_SREM MI expressing a signed divide by constant, return an expression that imp...
LLVM_ABI bool isLegalOrHasWidenScalar(const LegalityQuery &Query) const
LLVM_ABI bool matchSignedDivRemToUnsigned(MachineInstr &MI, unsigned UnsignedOpcode) const
Convert signed division or remainder of nonnegative operands to unsigned.
LLVM_ABI bool matchReassocConstantInnerLHS(GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS, BuildFnTy &MatchInfo) const
LLVM_ABI bool matchOverlappingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0.
LLVM_ABI bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg) const
Transform anyext(trunc(x)) to x.
LLVM_ABI void applyExtractAllEltsFromBuildVector(MachineInstr &MI, SmallVectorImpl< std::pair< Register, MachineInstr * > > &MatchInfo) const
MachineIRBuilder & Builder
LLVM_ABI void replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx) const
Delete MI and replace all of its uses with its OpIdx-th operand.
LLVM_ABI const MachineFunction & getMachineFunction() const
LLVM_ABI bool matchCombineBuildVectorOfBitcast(MachineInstr &MI, SmallVector< Register > &Ops) const
Combine G_BUILD_VECTOR(G_UNMERGE(G_BITCAST), Undef) to G_BITCAST(G_BUILD_VECTOR(.....
LLVM_ABI bool matchCombineFAddFpExtFMulToFMadOrFMAAggressive(MachineInstr &MI, BuildFnTy &MatchInfo) const
LLVM_ABI bool 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:1537
@ 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:1453
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
Definition Utils.cpp:1998
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:675
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:1549
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:483
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:1413
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:1577
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
unsigned Log2_64_Ceil(uint64_t Value)
Return the ceil log base 2 of the specified value, 64 if the value is zero.
Definition MathExtras.h:345
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:315
std::function< void(MachineIRBuilder &)> BuildFnTy
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
LLVM_ABI std::optional< APFloat > ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
Definition Utils.cpp:750
@ 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:1592
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
Definition Utils.cpp:1559
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:516
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:1625
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:681
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:1517
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:1446
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:917
@ 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:2165
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:1650
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:491
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:954
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:202
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:523
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:249
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...