Go to the documentation of this file.
45 #define DEBUG_TYPE "aarch64-postlegalizer-lowering"
48 using namespace MIPatternMatch;
49 using namespace AArch64GISelUtils;
59 std::initializer_list<SrcOp> SrcOps)
60 : Opc(Opc), Dst(Dst), SrcOps(SrcOps){};
69 "Only possible block sizes for REV are: 16, 32, 64");
70 assert(EltSize != 64 &&
"EltSize cannot be 64 for REV mask.");
72 unsigned BlockElts =
M[0] + 1;
81 for (
unsigned i = 0;
i < NumElts; ++
i) {
85 if (
static_cast<unsigned>(
M[
i]) !=
86 (
i -
i % BlockElts) + (BlockElts - 1 -
i % BlockElts))
96 unsigned &WhichResult) {
99 WhichResult = (
M[0] == 0 ? 0 : 1);
100 for (
unsigned i = 0;
i < NumElts;
i += 2) {
101 if ((
M[
i] >= 0 &&
static_cast<unsigned>(
M[
i]) !=
i + WhichResult) ||
103 static_cast<unsigned>(
M[
i + 1]) !=
i + NumElts + WhichResult))
114 auto FirstRealElt =
find_if(
M, [](
int Elt) {
return Elt >= 0; });
115 if (FirstRealElt ==
M.end())
120 APInt ExpectedElt =
APInt(MaskBits, *FirstRealElt + 1);
126 [&ExpectedElt](
int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
136 bool ReverseExt =
false;
148 return std::make_pair(ReverseExt,
Imm);
154 unsigned &WhichResult) {
155 WhichResult = (
M[0] == 0 ? 0 : 1);
156 for (
unsigned i = 0;
i != NumElts; ++
i) {
160 if (
static_cast<unsigned>(
M[
i]) != 2 *
i + WhichResult)
169 unsigned &WhichResult) {
170 if (NumElts % 2 != 0)
174 WhichResult = (
M[0] == 0 ? 0 : 1);
175 unsigned Idx = WhichResult * NumElts / 2;
176 for (
unsigned i = 0;
i != NumElts;
i += 2) {
177 if ((
M[
i] >= 0 &&
static_cast<unsigned>(
M[
i]) != Idx) ||
178 (
M[
i + 1] >= 0 &&
static_cast<unsigned>(
M[
i + 1]) != Idx + NumElts))
194 int NumInputElements) {
195 if (
M.size() !=
static_cast<size_t>(NumInputElements))
197 int NumLHSMatch = 0, NumRHSMatch = 0;
198 int LastLHSMismatch = -1, LastRHSMismatch = -1;
199 for (
int Idx = 0; Idx < NumInputElements; ++Idx) {
205 M[Idx] == Idx ? ++NumLHSMatch : LastLHSMismatch = Idx;
206 M[Idx] == Idx + NumInputElements ? ++NumRHSMatch : LastRHSMismatch = Idx;
208 const int NumNeededToMatch = NumInputElements - 1;
209 if (NumLHSMatch == NumNeededToMatch)
210 return std::make_pair(
true, LastLHSMismatch);
211 if (NumRHSMatch == NumNeededToMatch)
212 return std::make_pair(
false, LastRHSMismatch);
220 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
234 if (
isREVMask(ShuffleMask, EltSize, NumElts, 64)) {
249 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
250 unsigned WhichResult;
254 if (!
isTRNMask(ShuffleMask, NumElts, WhichResult))
256 unsigned Opc = (WhichResult == 0) ? AArch64::G_TRN1 : AArch64::G_TRN2;
270 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
271 unsigned WhichResult;
275 if (!
isUZPMask(ShuffleMask, NumElts, WhichResult))
277 unsigned Opc = (WhichResult == 0) ? AArch64::G_UZP1 : AArch64::G_UZP2;
286 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
287 unsigned WhichResult;
291 if (!
isZipMask(ShuffleMask, NumElts, WhichResult))
293 unsigned Opc = (WhichResult == 0) ? AArch64::G_ZIP1 : AArch64::G_ZIP2;
321 auto *InsMI =
getOpcodeDef(TargetOpcode::G_INSERT_VECTOR_ELT,
322 MI.getOperand(1).getReg(),
MRI);
326 if (!
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
335 {InsMI->getOperand(2).getReg()});
343 assert(Lane >= 0 &&
"Expected positive lane?");
346 auto *BuildVecMI =
getOpcodeDef(TargetOpcode::G_BUILD_VECTOR,
347 MI.getOperand(1).getReg(),
MRI);
350 Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
358 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
362 int Lane = *MaybeLane;
375 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
377 auto ExtInfo =
getExtMask(
MI.getOperand(3).getShuffleMask(),
383 std::tie(ReverseExt,
Imm) = *ExtInfo;
400 MI.eraseFromParent();
413 {MatchInfo.SrcOps[0], MatchInfo.SrcOps[1], Cst});
414 MI.eraseFromParent();
430 std::tuple<Register, int, Register, int> &MatchInfo) {
431 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
435 auto DstIsLeftAndDstLane =
isINSMask(ShuffleMask, NumElts);
436 if (!DstIsLeftAndDstLane)
440 std::tie(DstIsLeft, DstLane) = *DstIsLeftAndDstLane;
446 int SrcLane = ShuffleMask[DstLane];
447 if (SrcLane >= NumElts) {
452 MatchInfo = std::make_tuple(DstVec, DstLane, SrcVec, SrcLane);
458 std::tuple<Register, int, Register, int> &MatchInfo) {
463 int DstLane, SrcLane;
464 std::tie(DstVec, DstLane, SrcVec, SrcLane) = MatchInfo;
466 auto Extract =
Builder.buildExtractVectorElement(ScalarTy, SrcVec, SrcCst);
468 Builder.buildInsertVectorElement(Dst, DstVec, Extract, DstCst);
469 MI.eraseFromParent();
478 assert(Ty.
isVector() &&
"vector shift count is not a vector type");
485 return Cnt >= 1 && Cnt <= ElementBits;
491 assert(
MI.getOpcode() == TargetOpcode::G_ASHR ||
492 MI.getOpcode() == TargetOpcode::G_LSHR);
501 unsigned Opc =
MI.getOpcode();
502 assert(Opc == TargetOpcode::G_ASHR || Opc == TargetOpcode::G_LSHR);
504 Opc == TargetOpcode::G_ASHR ? AArch64::G_VASHR : AArch64::G_VLSHR;
507 MIB.
buildInstr(NewOpc, {
MI.getOperand(0)}, {
MI.getOperand(1), ImmDef});
508 MI.eraseFromParent();
525 unsigned Size = Ty.getSizeInBits();
526 assert((Size == 32 || Size == 64) &&
"Expected 32 or 64 bit compare only?");
533 uint64_t C = ValAndVReg->Value.getZExtValue();
550 if ((Size == 64 &&
static_cast<int64_t
>(
C) ==
INT64_MIN) ||
551 (Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MIN))
577 if ((Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MAX) ||
578 (Size == 64 &&
static_cast<int64_t
>(
C) ==
INT64_MAX))
591 if ((Size == 32 &&
static_cast<uint32_t>(
C) == UINT32_MAX) ||
618 std::pair<uint64_t, CmpInst::Predicate> &MatchInfo) {
619 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
623 MatchInfo = *MaybeNewImmAndPred;
630 MachineInstr &
MI, std::pair<uint64_t, CmpInst::Predicate> &MatchInfo,
638 RHS.setReg(Cst->getOperand(0).getReg());
639 MI.getOperand(1).setPredicate(MatchInfo.second);
645 std::pair<unsigned, int> &MatchInfo) {
646 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
668 if (ScalarSize == 64)
669 Opc = AArch64::G_DUPLANE64;
670 else if (ScalarSize == 32)
671 Opc = AArch64::G_DUPLANE32;
674 if (ScalarSize == 32)
675 Opc = AArch64::G_DUPLANE32;
678 if (ScalarSize == 16)
679 Opc = AArch64::G_DUPLANE16;
683 Opc = AArch64::G_DUPLANE8;
691 MatchInfo.first = Opc;
692 MatchInfo.second = *LaneIdx;
698 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
702 B.setInstrAndDebugLoc(
MI);
703 auto Lane =
B.buildConstant(
LLT::scalar(64), MatchInfo.second);
710 "Unexpected dest elements");
711 auto Undef =
B.buildUndef(SrcTy);
712 DupSrc =
B.buildConcatVectors(
714 {Src1Reg, Undef.getReg(0)})
717 B.buildInstr(MatchInfo.first, {MI.getOperand(0).getReg()}, {DupSrc, Lane});
718 MI.eraseFromParent();
723 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
732 int64_t Cst = Splat->getCst();
733 return (Cst != 0 && Cst != -1);
738 B.setInstrAndDebugLoc(
MI);
739 B.buildInstr(AArch64::G_DUP, {
MI.getOperand(0).
getReg()},
741 MI.eraseFromParent();
755 if (
MI.getOpcode() == TargetOpcode::G_SEXT_INREG)
757 if (
MI.getOpcode() != TargetOpcode::G_AND)
764 return (
Mask == 0xFF ||
Mask == 0xFFFF ||
Mask == 0xFFFFFFFF);
768 if (IsSupportedExtend(*
Def))
771 unsigned Opc =
Def->getOpcode();
772 if (Opc != TargetOpcode::G_SHL && Opc != TargetOpcode::G_ASHR &&
773 Opc != TargetOpcode::G_LSHR)
780 uint64_t ShiftAmt = MaybeShiftAmt->Value.getZExtValue();
787 if (IsSupportedExtend(*ShiftLHS))
788 return (ShiftAmt <= 4) ? 2 : 1;
794 if ((ShiftSize == 32 && ShiftAmt <= 31) ||
795 (ShiftSize == 64 && ShiftAmt <= 63))
804 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
846 MI.getOperand(2).setReg(
RHS);
847 MI.getOperand(3).setReg(
LHS);
868 ? MIB.buildInstr(AArch64::G_FCMEQZ, {DstTy}, {
LHS})
869 : MIB.buildInstr(AArch64::G_FCMEQ, {DstTy}, {
LHS,
RHS});
870 return MIB.buildNot(DstTy, FCmp).getReg(0);
875 ? MIB.buildInstr(AArch64::G_FCMEQZ, {DstTy}, {
LHS}).
getReg(0)
876 : MIB.buildInstr(AArch64::G_FCMEQ, {DstTy}, {
LHS,
RHS})
882 ? MIB.buildInstr(AArch64::G_FCMGEZ, {DstTy}, {
LHS}).
getReg(0)
883 : MIB.buildInstr(AArch64::G_FCMGE, {DstTy}, {
LHS,
RHS})
889 ? MIB.buildInstr(AArch64::G_FCMGTZ, {DstTy}, {
LHS}).
getReg(0)
890 : MIB.buildInstr(AArch64::G_FCMGT, {DstTy}, {
LHS,
RHS})
896 ? MIB.buildInstr(AArch64::G_FCMLEZ, {DstTy}, {
LHS}).
getReg(0)
897 : MIB.buildInstr(AArch64::G_FCMGE, {DstTy}, {
RHS,
LHS})
903 ? MIB.buildInstr(AArch64::G_FCMLTZ, {DstTy}, {
LHS}).
getReg(0)
904 : MIB.buildInstr(AArch64::G_FCMGT, {DstTy}, {
RHS,
LHS})
913 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
924 if (EltSize != 32 && EltSize != 64)
930 bool IsZero = Splat && Splat->isCst() && Splat->getCst() == 0;
934 bool NoNans =
ST.getTargetLowering()->getTargetMachine().Options.NoNaNsFPMath;
944 auto Cmp2Dst = Cmp2(MIB);
945 auto Cmp1Dst = Cmp(MIB);
951 MI.eraseFromParent();
957 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
972 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
974 MI.getOperand(0).setReg(SrcReg);
979 #define AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_DEPS
980 #include "AArch64GenPostLegalizeGILowering.inc"
981 #undef AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_DEPS
984 #define AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_H
985 #include "AArch64GenPostLegalizeGILowering.inc"
986 #undef AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_H
988 class AArch64PostLegalizerLoweringInfo :
public CombinerInfo {
990 AArch64GenPostLegalizerLoweringHelperRuleConfig GeneratedRuleCfg;
992 AArch64PostLegalizerLoweringInfo(
bool OptSize,
bool MinSize)
994 nullptr,
true, OptSize,
996 if (!GeneratedRuleCfg.parseCommandLineOption())
1008 AArch64GenPostLegalizerLoweringHelper Generated(GeneratedRuleCfg);
1009 return Generated.tryCombineAll(Observer,
MI,
B, Helper);
1012 #define AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_CPP
1013 #include "AArch64GenPostLegalizeGILowering.inc"
1014 #undef AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_CPP
1020 AArch64PostLegalizerLowering();
1022 StringRef getPassName()
const override {
1023 return "AArch64PostLegalizerLowering";
1031 void AArch64PostLegalizerLowering::getAnalysisUsage(
AnalysisUsage &AU)
const {
1038 AArch64PostLegalizerLowering::AArch64PostLegalizerLowering()
1043 bool AArch64PostLegalizerLowering::runOnMachineFunction(
MachineFunction &MF) {
1045 MachineFunctionProperties::Property::FailedISel))
1048 MachineFunctionProperties::Property::Legalized) &&
1049 "Expected a legalized function?");
1050 auto *TPC = &getAnalysis<TargetPassConfig>();
1052 AArch64PostLegalizerLoweringInfo PCInfo(
F.hasOptSize(),
F.hasMinSize());
1054 return C.combineMachineInstrs(MF,
nullptr);
1059 "Lower AArch64 MachineInstrs after legalization",
false,
1068 return new AArch64PostLegalizerLowering();
static bool applyShuffleVectorPseudo(MachineInstr &MI, ShuffleVectorPseudo &MatchInfo)
Replace a G_SHUFFLE_VECTOR instruction with a pseudo.
bool applyDupLane(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, std::pair< unsigned, int > &MatchInfo)
bool hasProperty(Property P) const
void changeVectorFCMPPredToAArch64CC(const CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2, bool &Invert)
Find the AArch64 condition codes necessary to represent P for a vector floating point comparison.
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
This is an optimization pass for GlobalISel generic memory operations.
static const int BlockSize
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, Optional< unsigned > Flags=None)
Build and insert Res = G_OR Op0, Op1.
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getScalarSizeInBits() const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
operand_type_match m_Reg()
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static bool matchDupFromInsertVectorElt(int Lane, MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
Helper function for matchDup.
Optional< RegOrConstant > getAArch64VectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
MachineRegisterInfo * getMRI()
Getter for MRI.
Reg
All possible values of the reg field in the ModR/M byte.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
static bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
Determines if M is a shuffle vector mask for a UZP of NumElts.
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
bool applyAdjustICmpImmAndPred(MachineInstr &MI, std::pair< uint64_t, CmpInst::Predicate > &MatchInfo, MachineIRBuilder &MIB, GISelChangeObserver &Observer)
@ ICMP_SGT
signed greater than
bool matchDupLane(MachineInstr &MI, MachineRegisterInfo &MRI, std::pair< unsigned, int > &MatchInfo)
INITIALIZE_PASS_BEGIN(AArch64PostLegalizerLowering, DEBUG_TYPE, "Lower AArch64 MachineInstrs after legalization", false, false) INITIALIZE_PASS_END(AArch64PostLegalizerLowering
static bool matchZip(MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
@ ICMP_SLE
signed less or equal
static bool matchREV(MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
static unsigned getCmpOperandFoldingProfit(Register CmpOp, const MachineRegisterInfo &MRI)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
static LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
FunctionPass * createAArch64PostLegalizerLowering()
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
(vector float) vec_cmpeq(*A, *B) C
static bool applyBuildVectorToDup(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B)
@ ICMP_ULE
unsigned less or equal
TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
ShuffleVectorPseudo(unsigned Opc, Register Dst, std::initializer_list< SrcOp > SrcOps)
Represent the analysis usage information of a pass.
const MachineFunctionProperties & getProperties() const
Get the function properties.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
MachineOperand class - Representation of each machine instruction operand.
SpecificConstantMatch m_ZeroInt()
{ Convenience matchers for specific integer values.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
uint64_t getZExtValue() const
Get zero extended value.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
static ElementCount getFixed(ScalarTy MinVal)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Register getReg(unsigned Idx) const
Get the register for the operand index.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
static bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
SmallVector< SrcOp, 2 > SrcOps
Source registers.
static bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
Determines if M is a shuffle vector mask for a TRN of NumElts.
static bool lowerVectorFCMP(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIB)
Try to lower a vector G_FCMP MI into an AArch64-specific pseudo.
Target-Independent Code Generator Pass Configuration Options.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
static bool isVShiftRImm(Register Reg, MachineRegisterInfo &MRI, LLT Ty, int64_t &Cnt)
isVShiftRImm - Check if this is a valid vector for the immediate operand of a vector shift right oper...
Helper class to build MachineInstr.
Representation of each machine instruction.
unsigned Opc
Opcode for the instruction. (E.g. G_ZIP1)
static bool isZipMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
static bool applySwapICmpOperands(MachineInstr &MI, GISelChangeObserver &Observer)
static bool isCMN(SDValue Op, ISD::CondCode CC)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
unsigned logBase2() const
void initializeAArch64PostLegalizerLoweringPass(PassRegistry &)
static bool matchDupFromBuildVector(int Lane, MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
Helper function for matchDup.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
Register Dst
Destination register.
uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
Represents a pseudo instruction which replaces a G_SHUFFLE_VECTOR.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
@ ICMP_UGE
unsigned greater or equal
static bool matchUZP(MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
static bool matchBuildVectorToDup(MachineInstr &MI, MachineRegisterInfo &MRI)
print Print MemDeps of function
static bool applyFormTruncstore(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer, Register &SrcReg)
bool matchAdjustICmpImmAndPred(MachineInstr &MI, const MachineRegisterInfo &MRI, std::pair< uint64_t, CmpInst::Predicate > &MatchInfo)
Determine whether or not it is possible to update the RHS and predicate of a G_ICMP instruction such ...
Class for arbitrary precision integers.
@ ICMP_SLT
signed less than
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
Optional< std::pair< uint64_t, CmpInst::Predicate > > tryAdjustICmpImmAndPred(Register RHS, CmpInst::Predicate P, const MachineRegisterInfo &MRI)
Determine if it is possible to modify the RHS and predicate P of a G_ICMP instruction such that the r...
static bool matchDup(MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
static bool matchEXT(MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
Lower AArch64 MachineInstrs after legalization
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
StringRef - Represent a constant reference to a string, i.e.
bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
@ ICMP_ULT
unsigned less than
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static Optional< std::pair< bool, int > > isINSMask(ArrayRef< int > M, int NumInputElements)
Helper function for matchINS.
Abstract class that contains various methods for clients to notify about changes.
MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0)
Build and insert a bitwise not, NegOne = G_CONSTANT -1 Res = G_OR Op0, NegOne.
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
static bool applyVAshrLshrImm(MachineInstr &MI, MachineRegisterInfo &MRI, int64_t &Imm)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Function & getFunction()
Return the LLVM function that this machine code represents.
static bool applyINS(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &Builder, std::tuple< Register, int, Register, int > &MatchInfo)
static bool matchVAshrLshrImm(MachineInstr &MI, MachineRegisterInfo &MRI, int64_t &Imm)
Match a vector G_ASHR or G_LSHR with a valid immediate shift.
static bool matchINS(MachineInstr &MI, MachineRegisterInfo &MRI, std::tuple< Register, int, Register, int > &MatchInfo)
Match a G_SHUFFLE_VECTOR with a mask which corresponds to a G_INSERT_VECTOR_ELT and G_EXTRACT_VECTOR_...
static bool trySwapICmpOperands(MachineInstr &MI, const MachineRegisterInfo &MRI)
@ ICMP_SGE
signed greater or equal
static bool applyEXT(MachineInstr &MI, ShuffleVectorPseudo &MatchInfo)
Replace a G_SHUFFLE_VECTOR instruction with G_EXT.
static bool matchFormTruncstore(MachineInstr &MI, MachineRegisterInfo &MRI, Register &SrcReg)
int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
@ ICMP_UGT
unsigned greater than
static Optional< std::pair< bool, uint64_t > > getExtMask(ArrayRef< int > M, unsigned NumElts)
Check if a G_EXT instruction can handle a shuffle mask M when the vector sources of the shuffle are d...
FunctionPass class - This class is used to implement most global optimizations.
static bool matchTRN(MachineInstr &MI, MachineRegisterInfo &MRI, ShuffleVectorPseudo &MatchInfo)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
AnalysisUsage & addRequired()
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Optional< int64_t > getAArch64VectorSplatScalar(const MachineInstr &MI, const MachineRegisterInfo &MRI)
static std::function< Register(MachineIRBuilder &)> getVectorFCMP(AArch64CC::CondCode CC, Register LHS, Register RHS, bool IsZero, bool NoNans, MachineRegisterInfo &MRI)
static bool isLegalArithImmed(uint64_t C)
@ Undef
Value of the register doesn't matter.