51#define GET_GICOMBINER_DEPS
52#include "AArch64GenPostLegalizeGILowering.inc"
53#undef GET_GICOMBINER_DEPS
55#define DEBUG_TYPE "aarch64-postlegalizer-lowering"
61#define GET_GICOMBINER_TYPES
62#include "AArch64GenPostLegalizeGILowering.inc"
63#undef GET_GICOMBINER_TYPES
70struct ShuffleVectorPseudo {
75 std::initializer_list<SrcOp> SrcOps)
76 :
Opc(
Opc), Dst(Dst), SrcOps(SrcOps){};
77 ShuffleVectorPseudo() =
default;
82std::optional<std::pair<bool, uint64_t>> getExtMask(
ArrayRef<int> M,
85 auto FirstRealElt =
find_if(M, [](
int Elt) {
return Elt >= 0; });
86 if (FirstRealElt == M.end())
91 APInt ExpectedElt =
APInt(MaskBits, *FirstRealElt + 1,
false,
true);
97 [&ExpectedElt](
int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
107 bool ReverseExt =
false;
119 return std::make_pair(ReverseExt,
Imm);
131 int NumInputElements) {
132 if (M.size() !=
static_cast<size_t>(NumInputElements))
134 int NumLHSMatch = 0, NumRHSMatch = 0;
135 int LastLHSMismatch = -1, LastRHSMismatch = -1;
136 for (
int Idx = 0; Idx < NumInputElements; ++Idx) {
142 M[Idx] == Idx ? ++NumLHSMatch : LastLHSMismatch = Idx;
143 M[Idx] == Idx + NumInputElements ? ++NumRHSMatch : LastRHSMismatch = Idx;
145 const int NumNeededToMatch = NumInputElements - 1;
146 if (NumLHSMatch == NumNeededToMatch)
147 return std::make_pair(
true, LastLHSMismatch);
148 if (NumRHSMatch == NumNeededToMatch)
149 return std::make_pair(
false, LastRHSMismatch);
156 ShuffleVectorPseudo &MatchInfo) {
157 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
168 unsigned NumElts = Ty.getNumElements();
171 for (
unsigned LaneSize : {64U, 32U, 16U}) {
172 if (
isREVMask(ShuffleMask, EltSize, NumElts, LaneSize)) {
175 Opcode = AArch64::G_REV64;
176 else if (LaneSize == 32U)
177 Opcode = AArch64::G_REV32;
179 Opcode = AArch64::G_BSWAP;
181 MatchInfo = ShuffleVectorPseudo(Opcode, Dst, {Src});
192 ShuffleVectorPseudo &MatchInfo) {
193 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
194 unsigned WhichResult;
195 unsigned OperandOrder = 0;
199 bool TRNMask =
isTRNMask(ShuffleMask, NumElts, WhichResult, OperandOrder);
202 unsigned Opc = (WhichResult == 0) ? AArch64::G_TRN1 : AArch64::G_TRN2;
203 Register V1 =
MI.getOperand(OperandOrder == 0 ? 1 : 2).getReg();
204 Register V2 =
MI.getOperand(OperandOrder == 0 && TRNMask ? 2 : 1).getReg();
205 MatchInfo = ShuffleVectorPseudo(
Opc, Dst, {
V1, V2});
215 ShuffleVectorPseudo &MatchInfo) {
216 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
217 unsigned WhichResult;
221 bool UZPMask =
isUZPMask(ShuffleMask, NumElts, WhichResult);
224 unsigned Opc = (WhichResult == 0) ? AArch64::G_UZP1 : AArch64::G_UZP2;
226 Register V2 =
MI.getOperand(UZPMask ? 2 : 1).getReg();
227 MatchInfo = ShuffleVectorPseudo(
Opc, Dst, {
V1, V2});
232 ShuffleVectorPseudo &MatchInfo) {
233 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
234 unsigned WhichResult;
235 unsigned OperandOrder = 0;
239 bool ZIPMask =
isZIPMask(ShuffleMask, NumElts, WhichResult, OperandOrder);
242 unsigned Opc = (WhichResult == 0) ? AArch64::G_ZIP1 : AArch64::G_ZIP2;
243 Register V1 =
MI.getOperand(OperandOrder == 0 ? 1 : 2).getReg();
244 Register V2 =
MI.getOperand(OperandOrder == 0 && ZIPMask ? 2 : 1).getReg();
245 MatchInfo = ShuffleVectorPseudo(
Opc, Dst, {
V1, V2});
252 ShuffleVectorPseudo &MatchInfo) {
271 auto *InsMI =
getOpcodeDef(TargetOpcode::G_INSERT_VECTOR_ELT,
272 MI.getOperand(1).getReg(), MRI);
276 if (!
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
284 MatchInfo = ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(),
285 {InsMI->getOperand(2).getReg()});
292 ShuffleVectorPseudo &MatchInfo) {
293 assert(Lane >= 0 &&
"Expected positive lane?");
299 MI.getOperand(Lane < NumElements ? 1 : 2).getReg(), MRI);
301 if (NumElements <= Lane)
306 Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
308 ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(), {Reg});
313 ShuffleVectorPseudo &MatchInfo) {
314 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
318 int Lane = *MaybeLane;
322 if (matchDupFromInsertVectorElt(Lane,
MI, MRI, MatchInfo))
324 if (matchDupFromBuildVector(Lane,
MI, MRI, MatchInfo))
332 unsigned NumElts = Ty.getNumElements();
341 unsigned ExpectedElt = M[0];
342 for (
unsigned I = 1;
I < NumElts; ++
I) {
346 if (ExpectedElt == NumElts)
351 if (ExpectedElt !=
static_cast<unsigned>(M[
I]))
359 ShuffleVectorPseudo &MatchInfo) {
360 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
365 auto Mask =
MI.getOperand(3).getShuffleMask();
372 !isSingletonExtMask(Mask, DstTy))
375 Imm = Mask[0] * ExtFactor;
376 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {
V1,
V1,
Imm});
380 std::tie(ReverseExt,
Imm) = *ExtInfo;
384 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {
V1, V2,
Imm});
391 ShuffleVectorPseudo &MatchInfo) {
393 if (MatchInfo.Opc == TargetOpcode::G_BSWAP) {
394 assert(MatchInfo.SrcOps.size() == 1);
402 auto BS1 = MIRBuilder.
buildInstr(TargetOpcode::G_BITCAST, {BSTy},
403 MatchInfo.SrcOps[0]);
404 auto BS2 = MIRBuilder.
buildInstr(MatchInfo.Opc, {BSTy}, {BS1});
405 MIRBuilder.
buildInstr(TargetOpcode::G_BITCAST, {MatchInfo.Dst}, {BS2});
407 MIRBuilder.
buildInstr(MatchInfo.Opc, {MatchInfo.Dst}, MatchInfo.SrcOps);
408 MI.eraseFromParent();
416 if (MatchInfo.SrcOps[2].getImm() == 0)
417 MIRBuilder.
buildCopy(MatchInfo.Dst, MatchInfo.SrcOps[0]);
421 MatchInfo.SrcOps[2].getImm());
422 MIRBuilder.
buildInstr(MatchInfo.Opc, {MatchInfo.Dst},
423 {MatchInfo.SrcOps[0], MatchInfo.SrcOps[1], Cst});
425 MI.eraseFromParent();
433 "Expected 128bit vector in applyFullRev");
436 auto Rev = MIRBuilder.
buildInstr(AArch64::G_REV64, {DstTy}, {Src});
437 MIRBuilder.
buildInstr(AArch64::G_EXT, {Dst}, {Rev, Rev, Cst});
438 MI.eraseFromParent();
442 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT);
452 Builder.setInstrAndDebugLoc(Insert);
456 LLT EltTy = MRI.
getType(Insert.getElementReg());
457 LLT IdxTy = MRI.
getType(Insert.getIndexReg());
470 auto StackTemp = Builder.buildFrameIndex(FramePtrTy, FrameIdx);
472 Builder.buildStore(Insert.getOperand(1), StackTemp, PtrInfo,
Align(8));
477 "Expected a power-2 vector size");
478 auto Mask = Builder.buildConstant(IdxTy, VecTy.
getNumElements() - 1);
480 auto EltSize = Builder.buildConstant(IdxTy, EltTy.
getSizeInBytes());
483 Builder.buildPtrAdd(MRI.
getType(StackTemp.getReg(0)), StackTemp,
Mul)
487 Builder.buildStore(Insert.getElementReg(), EltPtr, PtrInfo,
Align(1));
489 Builder.buildLoad(Insert.getReg(0), StackTemp, PtrInfo,
Align(8));
490 Insert.eraseFromParent();
505 std::tuple<Register, int, Register, int> &MatchInfo) {
506 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
510 auto DstIsLeftAndDstLane =
isINSMask(ShuffleMask, NumElts);
511 if (!DstIsLeftAndDstLane)
515 std::tie(DstIsLeft, DstLane) = *DstIsLeftAndDstLane;
521 int SrcLane = ShuffleMask[DstLane];
522 if (SrcLane >= NumElts) {
527 MatchInfo = std::make_tuple(DstVec, DstLane, SrcVec, SrcLane);
533 std::tuple<Register, int, Register, int> &MatchInfo) {
534 Builder.setInstrAndDebugLoc(
MI);
538 int DstLane, SrcLane;
539 std::tie(DstVec, DstLane, SrcVec, SrcLane) = MatchInfo;
540 auto SrcCst = Builder.buildConstant(
LLT::integer(64), SrcLane);
541 auto Extract = Builder.buildExtractVectorElement(ScalarTy, SrcVec, SrcCst);
542 auto DstCst = Builder.buildConstant(
LLT::integer(64), DstLane);
543 Builder.buildInsertVectorElement(Dst, DstVec, Extract, DstCst);
544 MI.eraseFromParent();
552 assert(Ty.isVector() &&
"vector shift count is not a vector type");
558 int64_t ElementBits = Ty.getScalarSizeInBits();
559 return Cnt >= 1 && Cnt <= ElementBits;
565 assert(
MI.getOpcode() == TargetOpcode::G_ASHR ||
566 MI.getOpcode() == TargetOpcode::G_LSHR);
575 unsigned Opc =
MI.getOpcode();
576 assert(
Opc == TargetOpcode::G_ASHR ||
Opc == TargetOpcode::G_LSHR);
578 Opc == TargetOpcode::G_ASHR ? AArch64::G_VASHR : AArch64::G_VLSHR;
581 MI.eraseFromParent();
638std::optional<std::pair<uint64_t, CmpInst::Predicate>>
644 assert((Ty.getSizeInBits() == 32 || Ty.getSizeInBits() == 64) &&
645 "Expected 32 or 64 bit compare only?");
652 APInt C = ValAndVReg->Value;
674 if (
C.isMinSignedValue())
687 assert(!
C.isZero() &&
"C should not be zero here!");
699 if (
C.isMaxSignedValue())
731 if (NumberOfInstrToLoadImm(OriginalC) > NumberOfInstrToLoadImm(NewC))
745bool matchAdjustICmpImmAndPred(
747 std::pair<uint64_t, CmpInst::Predicate> &MatchInfo) {
748 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
752 if (
auto MaybeNewImmAndPred = tryAdjustICmpImmAndPred(
LHS,
RHS, Pred, MRI)) {
753 MatchInfo = *MaybeNewImmAndPred;
759void applyAdjustICmpImmAndPred(
760 MachineInstr &
MI, std::pair<uint64_t, CmpInst::Predicate> &MatchInfo,
768 RHS.setReg(Cst->getOperand(0).getReg());
769 MI.getOperand(1).setPredicate(MatchInfo.second);
774 std::pair<unsigned, int> &MatchInfo) {
775 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
778 const LLT DstTy = MRI.
getType(
MI.getOperand(0).getReg());
785 if (*LaneIdx >= SrcTy.getNumElements())
795 switch (SrcTy.getNumElements()) {
797 if (ScalarSize == 64)
798 Opc = AArch64::G_DUPLANE64;
799 else if (ScalarSize == 32)
800 Opc = AArch64::G_DUPLANE32;
803 if (ScalarSize == 32)
804 Opc = AArch64::G_DUPLANE32;
805 else if (ScalarSize == 16)
806 Opc = AArch64::G_DUPLANE16;
810 Opc = AArch64::G_DUPLANE8;
811 else if (ScalarSize == 16)
812 Opc = AArch64::G_DUPLANE16;
816 Opc = AArch64::G_DUPLANE8;
824 MatchInfo.first =
Opc;
825 MatchInfo.second = *LaneIdx;
831 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
835 B.setInstrAndDebugLoc(
MI);
836 auto Lane =
B.buildConstant(
LLT::integer(64), MatchInfo.second);
841 if (SrcTy.getSizeInBits() == 64) {
842 auto Undef =
B.buildUndef(SrcTy);
843 DupSrc =
B.buildConcatVectors(SrcTy.multiplyElements(2),
844 {Src1Reg, Undef.getReg(0)})
847 B.buildInstr(MatchInfo.first, {MI.getOperand(0).getReg()}, {DupSrc, Lane});
848 MI.eraseFromParent();
853 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
855 if (SrcTy.getSizeInBits() != 128 && SrcTy.getSizeInBits() != 64)
857 return SrcTy.
isVector() && !SrcTy.isScalable() &&
858 (Unmerge.getNumOperands() == (
unsigned)SrcTy.getNumElements() + 1 ||
859 (Unmerge.getNumDefs() == 2 && SrcTy.getSizeInBits() == 128 &&
866 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
868 const LLT DstTy = MRI.
getType(Unmerge.getReg(0));
869 assert((SrcTy.isVector() && !SrcTy.isScalable()) &&
870 "Expected a fixed length vector");
873 assert(Unmerge.getNumDefs() == 2);
875 B.buildExtractSubvector(Unmerge.getReg(0), Src1Reg, 0);
877 B.buildExtractSubvector(Unmerge.getReg(1), Src1Reg,
878 SrcTy.getNumElements() / 2);
880 for (
int I = 0;
I < SrcTy.getNumElements(); ++
I)
882 B.buildExtractVectorElementConstant(Unmerge.getReg(
I), Src1Reg,
I);
884 MI.eraseFromParent();
889 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
901 unsigned NumNonUndef = 0;
908 else if (
Op.getReg() !=
Reg)
914 return Reg && NumNonUndef > 1;
919 B.setInstrAndDebugLoc(
MI);
920 B.buildInstr(AArch64::G_DUP, {
MI.getOperand(0).getReg()}, {Src});
921 MI.eraseFromParent();
930 if (
MI.getOpcode() == TargetOpcode::G_SEXT_INREG)
932 if (
MI.getOpcode() == TargetOpcode::G_AND) {
936 uint64_t Mask = ValAndVReg->Value.getZExtValue();
937 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
948 if (IsSupportedExtend(*Def))
951 unsigned Opc = Def->getOpcode();
952 if (
Opc == TargetOpcode::G_SHL ||
Opc == TargetOpcode::G_LSHR ||
953 Opc == TargetOpcode::G_ASHR) {
957 uint64_t ShiftAmt = MaybeShiftAmt->Value.getZExtValue();
960 if (IsSupportedExtend(*ShiftLHS))
961 return (ShiftAmt <= 4) ? 2 : 1;
962 LLT Ty = MRI.
getType(Def->getOperand(0).getReg());
966 if ((ShiftSize == 32 && ShiftAmt <= 31) ||
967 (ShiftSize == 64 && ShiftAmt <= 63))
978 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
999 return isCMN(Def, Pred, MRI) ? Def->getOperand(2).getReg() :
Reg;
1019 MI.getOperand(2).setReg(
RHS);
1020 MI.getOperand(3).setReg(
LHS);
1068 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
1073 if (!DstTy.
isVector() || !ST.hasNEON())
1077 if (EltSize == 16 && !ST.hasFullFP16())
1079 if (EltSize != 16 && EltSize != 32 && EltSize != 64)
1088 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
1099 bool Invert =
false;
1120 auto Cmp = getVectorFCMP(CC,
LHS,
RHS, NoNans, MRI);
1125 auto Cmp2 = getVectorFCMP(CC2,
LHS,
RHS, NoNans, MRI);
1126 auto Cmp2Dst = Cmp2(MIB);
1127 auto Cmp1Dst = Cmp(MIB);
1133 MI.eraseFromParent();
1141 for (
unsigned I = 0;
I < GBuildVec->getNumSources(); ++
I) {
1145 if (!ConstVal.has_value())
1155 LLT DstTy = MRI.
getType(GBuildVec->getReg(0));
1156 Register DstReg =
B.buildUndef(DstTy).getReg(0);
1158 for (
unsigned I = 0;
I < GBuildVec->getNumSources(); ++
I) {
1159 Register SrcReg = GBuildVec->getSourceReg(
I);
1164 B.buildInsertVectorElement(DstTy, DstReg, SrcReg, IdxReg).getReg(0);
1166 B.buildCopy(GBuildVec->getReg(0), DstReg);
1167 GBuildVec->eraseFromParent();
1172 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1188 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1190 MI.getOperand(0).setReg(SrcReg);
1198 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1206 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1207 B.setInstrAndDebugLoc(
MI);
1217 if (Unmerge.getNumDefs() != 2)
1234 if (!LowestVal || LowestVal->Value.getZExtValue() != DstTy.
getSizeInBytes())
1240 MatchInfo = ExtSrc1;
1250 MI.getOperand(0).setReg(
MI.getOperand(1).getReg());
1251 MI.getOperand(1).setReg(Dst1);
1252 MI.getOperand(2).setReg(SrcReg);
1269 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
1270 "Expected a G_MUL instruction");
1281class AArch64PostLegalizerLoweringImpl :
public Combiner {
1284 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig;
1288 AArch64PostLegalizerLoweringImpl(
1290 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1293 static const char *
getName() {
return "AArch6400PreLegalizerCombiner"; }
1298#define GET_GICOMBINER_CLASS_MEMBERS
1299#include "AArch64GenPostLegalizeGILowering.inc"
1300#undef GET_GICOMBINER_CLASS_MEMBERS
1303#define GET_GICOMBINER_IMPL
1304#include "AArch64GenPostLegalizeGILowering.inc"
1305#undef GET_GICOMBINER_IMPL
1307AArch64PostLegalizerLoweringImpl::AArch64PostLegalizerLoweringImpl(
1309 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1311 :
Combiner(MF, CInfo, nullptr, CSEInfo),
1312 Helper(Observer,
B,
true), RuleConfig(RuleConfig),
1315#include
"AArch64GenPostLegalizeGILowering.inc"
1320bool runPostLegalizerLowering(
1322 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig) {
1330 F.hasOptSize(),
F.hasMinSize());
1332 CInfo.MaxIterations = 1;
1335 CInfo.EnableFullDCE =
false;
1336 AArch64PostLegalizerLoweringImpl Impl(MF, CInfo,
nullptr,
1338 return Impl.combineMachineInstrs();
1345 AArch64PostLegalizerLoweringLegacy();
1347 StringRef getPassName()
const override {
1348 return "AArch64PostLegalizerLowering";
1352 void getAnalysisUsage(AnalysisUsage &AU)
const override;
1355 AArch64PostLegalizerLoweringImplRuleConfig RuleConfig;
1359void AArch64PostLegalizerLoweringLegacy::getAnalysisUsage(
1366AArch64PostLegalizerLoweringLegacy::AArch64PostLegalizerLoweringLegacy()
1367 : MachineFunctionPass(
ID) {
1368 if (!RuleConfig.parseCommandLineOption())
1372bool AArch64PostLegalizerLoweringLegacy::runOnMachineFunction(
1375 return runPostLegalizerLowering(MF, RuleConfig);
1378char AArch64PostLegalizerLoweringLegacy::ID = 0;
1380 "Lower AArch64 MachineInstrs after legalization",
false,
1383 "Lower AArch64 MachineInstrs after legalization",
false,
1388 std::make_unique<AArch64PostLegalizerLoweringImplRuleConfig>()) {
1389 if (!RuleConfig->parseCommandLineOption())
1402 const bool Changed = runPostLegalizerLowering(MF, *RuleConfig);
1414 return new AArch64PostLegalizerLoweringLegacy();
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isINSMask(ArrayRef< int > M, int NumInputElements, bool &DstIsLeft, int &Anomaly)
static unsigned getCmpOperandFoldingProfit(SDValue Op, bool AllowExtend)
Returns how profitable it is to fold a comparison's operand's shift and/or extension operations.
static bool shouldBeAdjustedToZero(SDValue LHS, const APInt &C, ISD::CondCode &CC)
This file declares the targeting of the Machinelegalizer class for AArch64.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define GET_GICOMBINER_CONSTRUCTOR_INITS
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This contains common combine transformations that may be used in a combine pass,or by the target else...
Option class for Targets to specify which operations are combined how and when.
This contains the base class for all Combiners generated by TableGen.
This contains common code to allow clients to notify changes to machine instr.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static StringRef getName(Value *V)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
~AArch64PostLegalizerLoweringPass()
AArch64PostLegalizerLoweringPass()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned logBase2() const
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents analyses that only rely on functions' control flow.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ ICMP_ULT
unsigned less than
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
FunctionPass class - This class is used to implement most global optimizations.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
constexpr unsigned getScalarSizeInBits() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
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.
static LLT integer(unsigned SizeInBits)
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
An RAII based helper class to modify MachineFunctionProperties when running pass.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Helper class to build MachineInstr.
MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0)
Build and insert a bitwise not, NegOne = G_CONSTANT -1 Res = G_OR Op0, NegOne.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
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.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
bool isCMN(const MachineInstr *MaybeSub, const CmpInst::Predicate &Pred, const MachineRegisterInfo &MRI)
std::optional< int64_t > getAArch64VectorSplatScalar(const MachineInstr &MI, const MachineRegisterInfo &MRI)
static bool isLegalCmpImmed(const APInt &C)
isLegalCmpImmed -
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
operand_type_match m_Reg()
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ImplicitDefMatch m_GImplicitDef()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
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.
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...
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> (WhichResultOut = 0,...
@ Undef
Value of the register doesn't matter.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createAArch64PostLegalizerLowering()
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
bool isUZP_v_undef_Mask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
isUZP_v_undef_Mask - Special case of isUZPMask for canonical form of "vector_shuffle v,...
LLVM_ABI std::optional< ValueAndVReg > getAnyConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true, bool LookThroughAnyExt=false)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT or G_FCONST...
LLVM_ABI bool isBuildVectorAllOnes(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...
LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
bool isZIP_v_undef_Mask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
isZIP_v_undef_Mask - Special case of isZIPMask for canonical form of "vector_shuffle v,...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool isTRN_v_undef_Mask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
isTRN_v_undef_Mask - Special case of isTRNMask for canonical form of "vector_shuffle v,...
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...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
LLVM_ABI int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
@ SinglePass
Enables Observer-based DCE and additional heuristics that retry combining defined and used instructio...
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.