52#define GET_GICOMBINER_DEPS
53#include "AArch64GenPostLegalizeGILowering.inc"
54#undef GET_GICOMBINER_DEPS
56#define DEBUG_TYPE "aarch64-postlegalizer-lowering"
59using namespace MIPatternMatch;
60using namespace AArch64GISelUtils;
64#define GET_GICOMBINER_TYPES
65#include "AArch64GenPostLegalizeGILowering.inc"
66#undef GET_GICOMBINER_TYPES
71struct ShuffleVectorPseudo {
75 ShuffleVectorPseudo(
unsigned Opc,
Register Dst,
76 std::initializer_list<SrcOp> SrcOps)
77 : Opc(Opc), Dst(Dst), SrcOps(SrcOps){};
78 ShuffleVectorPseudo() =
default;
83std::optional<std::pair<bool, uint64_t>> getExtMask(
ArrayRef<int> M,
86 auto FirstRealElt =
find_if(M, [](
int Elt) {
return Elt >= 0; });
87 if (FirstRealElt ==
M.end())
92 APInt ExpectedElt =
APInt(MaskBits, *FirstRealElt + 1);
98 [&ExpectedElt](
int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
108 bool ReverseExt =
false;
120 return std::make_pair(ReverseExt, Imm);
132 int NumInputElements) {
133 if (
M.size() !=
static_cast<size_t>(NumInputElements))
135 int NumLHSMatch = 0, NumRHSMatch = 0;
136 int LastLHSMismatch = -1, LastRHSMismatch = -1;
137 for (
int Idx = 0;
Idx < NumInputElements; ++
Idx) {
143 M[
Idx] ==
Idx ? ++NumLHSMatch : LastLHSMismatch =
Idx;
144 M[
Idx] ==
Idx + NumInputElements ? ++NumRHSMatch : LastRHSMismatch =
Idx;
146 const int NumNeededToMatch = NumInputElements - 1;
147 if (NumLHSMatch == NumNeededToMatch)
148 return std::make_pair(
true, LastLHSMismatch);
149 if (NumRHSMatch == NumNeededToMatch)
150 return std::make_pair(
false, LastRHSMismatch);
157 ShuffleVectorPseudo &MatchInfo) {
158 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
162 LLT Ty =
MRI.getType(Dst);
172 for (
unsigned LaneSize : {64U, 32U, 16U}) {
173 if (
isREVMask(ShuffleMask, EltSize, NumElts, LaneSize)) {
176 Opcode = AArch64::G_REV64;
177 else if (LaneSize == 32U)
178 Opcode = AArch64::G_REV32;
180 Opcode = AArch64::G_REV16;
182 MatchInfo = ShuffleVectorPseudo(Opcode, Dst, {Src});
193 ShuffleVectorPseudo &MatchInfo) {
194 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
195 unsigned WhichResult;
198 unsigned NumElts =
MRI.getType(Dst).getNumElements();
199 if (!
isTRNMask(ShuffleMask, NumElts, WhichResult))
201 unsigned Opc = (WhichResult == 0) ? AArch64::G_TRN1 : AArch64::G_TRN2;
204 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1,
V2});
214 ShuffleVectorPseudo &MatchInfo) {
215 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
216 unsigned WhichResult;
219 unsigned NumElts =
MRI.getType(Dst).getNumElements();
220 if (!
isUZPMask(ShuffleMask, NumElts, WhichResult))
222 unsigned Opc = (WhichResult == 0) ? AArch64::G_UZP1 : AArch64::G_UZP2;
225 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1,
V2});
230 ShuffleVectorPseudo &MatchInfo) {
231 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
232 unsigned WhichResult;
235 unsigned NumElts =
MRI.getType(Dst).getNumElements();
236 if (!
isZIPMask(ShuffleMask, NumElts, WhichResult))
238 unsigned Opc = (WhichResult == 0) ? AArch64::G_ZIP1 : AArch64::G_ZIP2;
241 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1,
V2});
248 ShuffleVectorPseudo &MatchInfo) {
267 auto *InsMI =
getOpcodeDef(TargetOpcode::G_INSERT_VECTOR_ELT,
268 MI.getOperand(1).getReg(),
MRI);
272 if (!
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
280 MatchInfo = ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(),
281 {InsMI->getOperand(2).getReg()});
288 ShuffleVectorPseudo &MatchInfo) {
289 assert(Lane >= 0 &&
"Expected positive lane?");
292 auto *BuildVecMI =
getOpcodeDef(TargetOpcode::G_BUILD_VECTOR,
293 MI.getOperand(1).getReg(),
MRI);
296 Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
298 ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(), {Reg});
303 ShuffleVectorPseudo &MatchInfo) {
304 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
308 int Lane = *MaybeLane;
312 if (matchDupFromInsertVectorElt(Lane,
MI,
MRI, MatchInfo))
314 if (matchDupFromBuildVector(Lane,
MI,
MRI, MatchInfo))
331 unsigned ExpectedElt =
M[0];
332 for (
unsigned I = 1;
I < NumElts; ++
I) {
336 if (ExpectedElt == NumElts)
341 if (ExpectedElt !=
static_cast<unsigned>(M[
I]))
349 ShuffleVectorPseudo &MatchInfo) {
350 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
352 LLT DstTy =
MRI.getType(Dst);
355 auto Mask =
MI.getOperand(3).getShuffleMask();
358 uint64_t ExtFactor =
MRI.getType(V1).getScalarSizeInBits() / 8;
361 if (!getOpcodeDef<GImplicitDef>(V2,
MRI) ||
362 !isSingletonExtMask(Mask, DstTy))
366 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1, V1,
Imm});
370 std::tie(ReverseExt, Imm) = *ExtInfo;
374 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1,
V2,
Imm});
381 ShuffleVectorPseudo &MatchInfo) {
383 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst}, MatchInfo.SrcOps);
384 MI.eraseFromParent();
392 if (MatchInfo.SrcOps[2].getImm() == 0)
393 MIRBuilder.buildCopy(MatchInfo.Dst, MatchInfo.SrcOps[0]);
397 MIRBuilder.buildConstant(
LLT::scalar(32), MatchInfo.SrcOps[2].getImm());
398 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst},
399 {MatchInfo.SrcOps[0], MatchInfo.SrcOps[1], Cst});
401 MI.eraseFromParent();
405 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT);
414 auto &
Insert = cast<GInsertVectorElement>(
MI);
437 "Expected a power-2 vector size");
465 std::tuple<Register, int, Register, int> &MatchInfo) {
466 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
469 int NumElts =
MRI.getType(Dst).getNumElements();
470 auto DstIsLeftAndDstLane =
isINSMask(ShuffleMask, NumElts);
471 if (!DstIsLeftAndDstLane)
475 std::tie(DstIsLeft, DstLane) = *DstIsLeftAndDstLane;
481 int SrcLane = ShuffleMask[DstLane];
482 if (SrcLane >= NumElts) {
487 MatchInfo = std::make_tuple(DstVec, DstLane, SrcVec, SrcLane);
493 std::tuple<Register, int, Register, int> &MatchInfo) {
496 auto ScalarTy =
MRI.getType(Dst).getElementType();
498 int DstLane, SrcLane;
499 std::tie(DstVec, DstLane, SrcVec, SrcLane) = MatchInfo;
504 MI.eraseFromParent();
512 assert(Ty.
isVector() &&
"vector shift count is not a vector type");
519 return Cnt >= 1 && Cnt <= ElementBits;
525 assert(
MI.getOpcode() == TargetOpcode::G_ASHR ||
526 MI.getOpcode() == TargetOpcode::G_LSHR);
527 LLT Ty =
MRI.getType(
MI.getOperand(1).getReg());
535 unsigned Opc =
MI.getOpcode();
536 assert(Opc == TargetOpcode::G_ASHR || Opc == TargetOpcode::G_LSHR);
538 Opc == TargetOpcode::G_ASHR ? AArch64::G_VASHR : AArch64::G_VLSHR;
540 auto ImmDef = MIB.buildConstant(
LLT::scalar(32), Imm);
541 MIB.buildInstr(NewOpc, {
MI.getOperand(0)}, {
MI.getOperand(1), ImmDef});
542 MI.eraseFromParent();
552std::optional<std::pair<uint64_t, CmpInst::Predicate>>
555 const auto &Ty =
MRI.getType(RHS);
559 assert((
Size == 32 ||
Size == 64) &&
"Expected 32 or 64 bit compare only?");
566 uint64_t C = ValAndVReg->Value.getZExtValue();
584 (
Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MIN))
610 if ((
Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MAX) ||
624 if ((
Size == 32 &&
static_cast<uint32_t>(
C) == UINT32_MAX) ||
649bool matchAdjustICmpImmAndPred(
651 std::pair<uint64_t, CmpInst::Predicate> &MatchInfo) {
652 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
655 if (
auto MaybeNewImmAndPred = tryAdjustICmpImmAndPred(RHS, Pred,
MRI)) {
656 MatchInfo = *MaybeNewImmAndPred;
662void applyAdjustICmpImmAndPred(
663 MachineInstr &
MI, std::pair<uint64_t, CmpInst::Predicate> &MatchInfo,
671 RHS.setReg(Cst->getOperand(0).getReg());
672 MI.getOperand(1).setPredicate(MatchInfo.second);
677 std::pair<unsigned, int> &MatchInfo) {
678 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
680 const LLT SrcTy =
MRI.getType(Src1Reg);
681 const LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
700 if (ScalarSize == 64)
701 Opc = AArch64::G_DUPLANE64;
702 else if (ScalarSize == 32)
703 Opc = AArch64::G_DUPLANE32;
706 if (ScalarSize == 32)
707 Opc = AArch64::G_DUPLANE32;
708 else if (ScalarSize == 16)
709 Opc = AArch64::G_DUPLANE16;
713 Opc = AArch64::G_DUPLANE8;
714 else if (ScalarSize == 16)
715 Opc = AArch64::G_DUPLANE16;
719 Opc = AArch64::G_DUPLANE8;
727 MatchInfo.first = Opc;
728 MatchInfo.second = *LaneIdx;
734 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
736 const LLT SrcTy =
MRI.getType(Src1Reg);
738 B.setInstrAndDebugLoc(
MI);
739 auto Lane =
B.buildConstant(
LLT::scalar(64), MatchInfo.second);
745 auto Undef =
B.buildUndef(SrcTy);
747 {Src1Reg, Undef.getReg(0)})
750 B.buildInstr(MatchInfo.first, {MI.getOperand(0).getReg()}, {DupSrc, Lane});
751 MI.eraseFromParent();
755 auto &Unmerge = cast<GUnmerge>(
MI);
756 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
757 const LLT SrcTy =
MRI.getType(Src1Reg);
766 auto &Unmerge = cast<GUnmerge>(
MI);
767 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
768 const LLT SrcTy =
MRI.getType(Src1Reg);
770 "Expected a fixed length vector");
773 B.buildExtractVectorElementConstant(Unmerge.getReg(
I), Src1Reg,
I);
774 MI.eraseFromParent();
778 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
787 int64_t Cst =
Splat->getCst();
788 return (Cst != 0 && Cst != -1);
793 B.setInstrAndDebugLoc(
MI);
794 B.buildInstr(AArch64::G_DUP, {
MI.getOperand(0).
getReg()},
796 MI.eraseFromParent();
803 if (!
MRI.hasOneNonDBGUse(CmpOp))
808 if (
MI.getOpcode() == TargetOpcode::G_SEXT_INREG)
810 if (
MI.getOpcode() != TargetOpcode::G_AND)
817 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
821 if (IsSupportedExtend(*Def))
824 unsigned Opc =
Def->getOpcode();
825 if (Opc != TargetOpcode::G_SHL && Opc != TargetOpcode::G_ASHR &&
826 Opc != TargetOpcode::G_LSHR)
833 uint64_t ShiftAmt = MaybeShiftAmt->Value.getZExtValue();
840 if (IsSupportedExtend(*ShiftLHS))
841 return (ShiftAmt <= 4) ? 2 : 1;
843 LLT Ty =
MRI.getType(
Def->getOperand(0).getReg());
847 if ((ShiftSize == 32 && ShiftAmt <= 31) ||
848 (ShiftSize == 64 && ShiftAmt <= 63))
856 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
882 Register TheLHS = GetRegForProfit(LHS);
883 Register TheRHS = GetRegForProfit(RHS);
897 MI.getOperand(2).setReg(RHS);
898 MI.getOperand(3).setReg(LHS);
909 LLT DstTy =
MRI.getType(LHS);
911 assert(DstTy ==
MRI.getType(RHS) &&
"Src and Dst types must match!");
963 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
967 LLT DstTy =
MRI.getType(Dst);
971 unsigned EltSize =
MRI.getType(LHS).getScalarSizeInBits();
972 if (EltSize == 16 && !
ST.hasFullFP16())
974 if (EltSize != 16 && EltSize != 32 && EltSize != 64)
983 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
986 const auto &CmpMI = cast<GFCmp>(
MI);
993 LLT DstTy =
MRI.getType(Dst);
1000 bool Invert =
false;
1002 if ((Pred == CmpInst::Predicate::FCMP_ORD ||
1003 Pred == CmpInst::Predicate::FCMP_UNO) &&
1020 ST.getTargetLowering()->getTargetMachine().Options.NoNaNsFPMath;
1022 auto Cmp = getVectorFCMP(
CC, LHS, RHS, IsZero, NoNans,
MRI);
1027 auto Cmp2 = getVectorFCMP(CC2, LHS, RHS, IsZero, NoNans,
MRI);
1028 auto Cmp2Dst = Cmp2(MIB);
1029 auto Cmp1Dst =
Cmp(MIB);
1034 MRI.replaceRegWith(Dst, CmpRes);
1035 MI.eraseFromParent();
1040 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1042 if (
MRI.getType(DstReg).isVector())
1048 return MRI.getType(SrcReg).getSizeInBits() <= 64;
1054 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1056 MI.getOperand(0).setReg(SrcReg);
1064 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1066 LLT DstTy =
MRI.getType(DstReg);
1072 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1073 B.setInstrAndDebugLoc(
MI);
1075 Helper.lower(
MI, 0,
LLT());
1082 auto &Unmerge = cast<GUnmerge>(
MI);
1083 if (Unmerge.getNumDefs() != 2)
1085 if (!
MRI.use_nodbg_empty(Unmerge.getReg(1)))
1088 LLT DstTy =
MRI.getType(Unmerge.getReg(0));
1100 if (!LowestVal || LowestVal->Value.getZExtValue() != DstTy.
getSizeInBytes())
1103 if (!getOpcodeDef<GImplicitDef>(ExtSrc2,
MRI))
1106 MatchInfo = ExtSrc1;
1116 MI.getOperand(0).setReg(
MI.getOperand(1).getReg());
1117 MI.getOperand(1).setReg(Dst1);
1118 MI.getOperand(2).setReg(SrcReg);
1129 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
1135 unsigned I1Opc =
I1->getOpcode();
1137 if (((I1Opc == TargetOpcode::G_ZEXT && I2Opc == TargetOpcode::G_ZEXT) ||
1138 (I1Opc == TargetOpcode::G_SEXT && I2Opc == TargetOpcode::G_SEXT)) &&
1139 (
MRI.getType(
I1->getOperand(0).getReg()).getScalarSizeInBits() ==
1140 MRI.getType(
I1->getOperand(1).getReg()).getScalarSizeInBits() * 2) &&
1155 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
1156 "Expected a G_MUL instruction");
1159 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
1164 unsigned I1Opc =
I1->getOpcode();
1166 if (((I1Opc == TargetOpcode::G_ZEXT && I2Opc == TargetOpcode::G_ZEXT) ||
1167 (I1Opc == TargetOpcode::G_SEXT && I2Opc == TargetOpcode::G_SEXT)) &&
1168 (
MRI.getType(
I1->getOperand(0).getReg()).getScalarSizeInBits() ==
1169 MRI.getType(
I1->getOperand(1).getReg()).getScalarSizeInBits() * 2) &&
1173 B.setInstrAndDebugLoc(
MI);
1174 B.buildInstr(
I1->getOpcode() == TargetOpcode::G_ZEXT ? AArch64::G_UMULL
1176 {MI.getOperand(0).getReg()},
1177 {I1->getOperand(1).getReg(), I2->getOperand(1).getReg()});
1178 MI.eraseFromParent();
1183 B.setInstrAndDebugLoc(
MI);
1184 Helper.fewerElementsVector(
1191class AArch64PostLegalizerLoweringImpl :
public Combiner {
1195 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig;
1199 AArch64PostLegalizerLoweringImpl(
1202 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1205 static const char *
getName() {
return "AArch6400PreLegalizerCombiner"; }
1210#define GET_GICOMBINER_CLASS_MEMBERS
1211#include "AArch64GenPostLegalizeGILowering.inc"
1212#undef GET_GICOMBINER_CLASS_MEMBERS
1215#define GET_GICOMBINER_IMPL
1216#include "AArch64GenPostLegalizeGILowering.inc"
1217#undef GET_GICOMBINER_IMPL
1219AArch64PostLegalizerLoweringImpl::AArch64PostLegalizerLoweringImpl(
1222 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1224 :
Combiner(MF, CInfo, TPC, nullptr, CSEInfo),
1225 Helper(Observer,
B,
true), RuleConfig(RuleConfig),
1228#include
"AArch64GenPostLegalizeGILowering.inc"
1237 AArch64PostLegalizerLowering();
1240 return "AArch64PostLegalizerLowering";
1247 AArch64PostLegalizerLoweringImplRuleConfig RuleConfig;
1251void AArch64PostLegalizerLowering::getAnalysisUsage(
AnalysisUsage &AU)
const {
1258AArch64PostLegalizerLowering::AArch64PostLegalizerLowering()
1262 if (!RuleConfig.parseCommandLineOption())
1266bool AArch64PostLegalizerLowering::runOnMachineFunction(
MachineFunction &MF) {
1268 MachineFunctionProperties::Property::FailedISel))
1271 MachineFunctionProperties::Property::Legalized) &&
1272 "Expected a legalized function?");
1273 auto *TPC = &getAnalysis<TargetPassConfig>();
1279 F.hasOptSize(),
F.hasMinSize());
1280 AArch64PostLegalizerLoweringImpl Impl(MF, CInfo, TPC,
nullptr,
1282 return Impl.combineMachineInstrs();
1285char AArch64PostLegalizerLowering::ID = 0;
1287 "Lower AArch64 MachineInstrs after legalization",
false,
1296 return new AArch64PostLegalizerLowering();
unsigned const MachineRegisterInfo * MRI
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 isLegalArithImmed(uint64_t C)
static bool isINSMask(ArrayRef< int > M, int NumInputElements, bool &DstIsLeft, int &Anomaly)
static unsigned getCmpOperandFoldingProfit(SDValue Op)
Returns how profitable it is to fold a comparison's operand's shift and/or extension operations.
static bool isCMN(SDValue Op, ISD::CondCode CC)
This file declares the targeting of the Machinelegalizer class for AArch64.
#define GET_GICOMBINER_CONSTRUCTOR_INITS
Lower AArch64 MachineInstrs after legalization
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.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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.
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Target-Independent Code Generator Pass Configuration Options pass.
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
unsigned logBase2() const
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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
@ ICMP_SGE
signed greater or equal
@ ICMP_ULE
unsigned less or equal
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
virtual bool tryCombineAll(MachineInstr &I) const =0
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.
constexpr unsigned getScalarSizeInBits() const
constexpr LLT multiplyElements(int Factor) const
Produce a vector type that is Factor times bigger, preserving the element type.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
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 bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector 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.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
bool hasProperty(Property P) const
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 buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildExtractVectorElement(const DstOp &Res, const SrcOp &Val, const SrcOp &Idx)
Build and insert Res = G_EXTRACT_VECTOR_ELT Val, Idx.
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_PTR_ADD Op0, Op1.
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx)
Build and insert Res = G_FRAME_INDEX Idx.
MachineFunction & getMF()
Getter for the function we currently build.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
MachineInstrBuilder buildInsertVectorElement(const DstOp &Res, const SrcOp &Val, const SrcOp &Elt, const SrcOp &Idx)
Build and insert Res = G_INSERT_VECTOR_ELT Val, Elt, Idx.
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.
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.
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,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
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.
StringRef - Represent a constant reference to a string, i.e.
Target-Independent Code Generator Pass Configuration Options.
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.
std::optional< RegOrConstant > getAArch64VectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
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.
std::optional< int64_t > getAArch64VectorSplatScalar(const MachineInstr &MI, const MachineRegisterInfo &MRI)
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
operand_type_match m_Reg()
SpecificConstantMatch m_ZeroInt()
{ Convenience matchers for specific integer values.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
@ Undef
Value of the register doesn't matter.
Reg
All possible values of the reg field in the ModR/M byte.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
void initializeAArch64PostLegalizerLoweringPass(PassRegistry &)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResult)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> or <1,...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
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.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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.
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> or <4, 12,...
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.
int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
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.
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.