50#define GET_GICOMBINER_DEPS
51#include "AArch64GenPostLegalizeGILowering.inc"
52#undef GET_GICOMBINER_DEPS
54#define DEBUG_TYPE "aarch64-postlegalizer-lowering"
57using namespace MIPatternMatch;
58using namespace AArch64GISelUtils;
62#define GET_GICOMBINER_TYPES
63#include "AArch64GenPostLegalizeGILowering.inc"
64#undef GET_GICOMBINER_TYPES
69struct ShuffleVectorPseudo {
73 ShuffleVectorPseudo(
unsigned Opc,
Register Dst,
74 std::initializer_list<SrcOp> SrcOps)
75 : Opc(Opc), Dst(Dst), SrcOps(SrcOps){};
76 ShuffleVectorPseudo() =
default;
81std::optional<std::pair<bool, uint64_t>> getExtMask(
ArrayRef<int> M,
84 auto FirstRealElt =
find_if(M, [](
int Elt) {
return Elt >= 0; });
85 if (FirstRealElt ==
M.end())
90 APInt ExpectedElt =
APInt(MaskBits, *FirstRealElt + 1,
false,
true);
96 [&ExpectedElt](
int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
106 bool ReverseExt =
false;
118 return std::make_pair(ReverseExt, Imm);
130 int NumInputElements) {
131 if (
M.size() !=
static_cast<size_t>(NumInputElements))
133 int NumLHSMatch = 0, NumRHSMatch = 0;
134 int LastLHSMismatch = -1, LastRHSMismatch = -1;
135 for (
int Idx = 0;
Idx < NumInputElements; ++
Idx) {
141 M[
Idx] ==
Idx ? ++NumLHSMatch : LastLHSMismatch =
Idx;
142 M[
Idx] ==
Idx + NumInputElements ? ++NumRHSMatch : LastRHSMismatch =
Idx;
144 const int NumNeededToMatch = NumInputElements - 1;
145 if (NumLHSMatch == NumNeededToMatch)
146 return std::make_pair(
true, LastLHSMismatch);
147 if (NumRHSMatch == NumNeededToMatch)
148 return std::make_pair(
false, LastRHSMismatch);
155 ShuffleVectorPseudo &MatchInfo) {
156 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
160 LLT Ty =
MRI.getType(Dst);
170 for (
unsigned LaneSize : {64U, 32U, 16U}) {
171 if (
isREVMask(ShuffleMask, EltSize, NumElts, LaneSize)) {
174 Opcode = AArch64::G_REV64;
175 else if (LaneSize == 32U)
176 Opcode = AArch64::G_REV32;
178 Opcode = AArch64::G_REV16;
180 MatchInfo = ShuffleVectorPseudo(Opcode, Dst, {Src});
191 ShuffleVectorPseudo &MatchInfo) {
192 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
193 unsigned WhichResult;
196 unsigned NumElts =
MRI.getType(Dst).getNumElements();
197 if (!
isTRNMask(ShuffleMask, NumElts, WhichResult))
199 unsigned Opc = (WhichResult == 0) ? AArch64::G_TRN1 : AArch64::G_TRN2;
202 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1,
V2});
212 ShuffleVectorPseudo &MatchInfo) {
213 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
214 unsigned WhichResult;
217 unsigned NumElts =
MRI.getType(Dst).getNumElements();
218 if (!
isUZPMask(ShuffleMask, NumElts, WhichResult))
220 unsigned Opc = (WhichResult == 0) ? AArch64::G_UZP1 : AArch64::G_UZP2;
223 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1,
V2});
228 ShuffleVectorPseudo &MatchInfo) {
229 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
230 unsigned WhichResult;
233 unsigned NumElts =
MRI.getType(Dst).getNumElements();
234 if (!
isZIPMask(ShuffleMask, NumElts, WhichResult))
236 unsigned Opc = (WhichResult == 0) ? AArch64::G_ZIP1 : AArch64::G_ZIP2;
239 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1,
V2});
246 ShuffleVectorPseudo &MatchInfo) {
265 auto *InsMI =
getOpcodeDef(TargetOpcode::G_INSERT_VECTOR_ELT,
266 MI.getOperand(1).getReg(),
MRI);
270 if (!
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
278 MatchInfo = ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(),
279 {InsMI->getOperand(2).getReg()});
286 ShuffleVectorPseudo &MatchInfo) {
287 assert(Lane >= 0 &&
"Expected positive lane?");
288 int NumElements =
MRI.getType(
MI.getOperand(1).getReg()).getNumElements();
293 MI.getOperand(Lane < NumElements ? 1 : 2).getReg(),
MRI);
295 if (NumElements <= Lane)
300 Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
302 ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(), {Reg});
307 ShuffleVectorPseudo &MatchInfo) {
308 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
312 int Lane = *MaybeLane;
316 if (matchDupFromInsertVectorElt(Lane,
MI,
MRI, MatchInfo))
318 if (matchDupFromBuildVector(Lane,
MI,
MRI, MatchInfo))
335 unsigned ExpectedElt =
M[0];
336 for (
unsigned I = 1;
I < NumElts; ++
I) {
340 if (ExpectedElt == NumElts)
345 if (ExpectedElt !=
static_cast<unsigned>(M[
I]))
353 ShuffleVectorPseudo &MatchInfo) {
354 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
356 LLT DstTy =
MRI.getType(Dst);
359 auto Mask =
MI.getOperand(3).getShuffleMask();
362 uint64_t ExtFactor =
MRI.getType(V1).getScalarSizeInBits() / 8;
365 if (!getOpcodeDef<GImplicitDef>(V2,
MRI) ||
366 !isSingletonExtMask(Mask, DstTy))
370 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1, V1,
Imm});
374 std::tie(ReverseExt, Imm) = *ExtInfo;
378 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1,
V2,
Imm});
385 ShuffleVectorPseudo &MatchInfo) {
387 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst}, MatchInfo.SrcOps);
388 MI.eraseFromParent();
396 if (MatchInfo.SrcOps[2].getImm() == 0)
397 MIRBuilder.buildCopy(MatchInfo.Dst, MatchInfo.SrcOps[0]);
401 MIRBuilder.buildConstant(
LLT::scalar(32), MatchInfo.SrcOps[2].getImm());
402 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst},
403 {MatchInfo.SrcOps[0], MatchInfo.SrcOps[1], Cst});
405 MI.eraseFromParent();
411 LLT DstTy =
MRI.getType(Dst);
413 "Expected 128bit vector in applyFullRev");
415 auto Cst = MIRBuilder.buildConstant(
LLT::scalar(32), 8);
416 auto Rev = MIRBuilder.buildInstr(AArch64::G_REV64, {DstTy}, {Src});
417 MIRBuilder.buildInstr(AArch64::G_EXT, {Dst}, {Rev, Rev, Cst});
418 MI.eraseFromParent();
422 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT);
431 auto &
Insert = cast<GInsertVectorElement>(
MI);
457 "Expected a power-2 vector size");
485 std::tuple<Register, int, Register, int> &MatchInfo) {
486 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
489 int NumElts =
MRI.getType(Dst).getNumElements();
490 auto DstIsLeftAndDstLane =
isINSMask(ShuffleMask, NumElts);
491 if (!DstIsLeftAndDstLane)
495 std::tie(DstIsLeft, DstLane) = *DstIsLeftAndDstLane;
501 int SrcLane = ShuffleMask[DstLane];
502 if (SrcLane >= NumElts) {
507 MatchInfo = std::make_tuple(DstVec, DstLane, SrcVec, SrcLane);
513 std::tuple<Register, int, Register, int> &MatchInfo) {
516 auto ScalarTy =
MRI.getType(Dst).getElementType();
518 int DstLane, SrcLane;
519 std::tie(DstVec, DstLane, SrcVec, SrcLane) = MatchInfo;
524 MI.eraseFromParent();
532 assert(Ty.
isVector() &&
"vector shift count is not a vector type");
539 return Cnt >= 1 && Cnt <= ElementBits;
545 assert(
MI.getOpcode() == TargetOpcode::G_ASHR ||
546 MI.getOpcode() == TargetOpcode::G_LSHR);
547 LLT Ty =
MRI.getType(
MI.getOperand(1).getReg());
555 unsigned Opc =
MI.getOpcode();
556 assert(Opc == TargetOpcode::G_ASHR || Opc == TargetOpcode::G_LSHR);
558 Opc == TargetOpcode::G_ASHR ? AArch64::G_VASHR : AArch64::G_VLSHR;
560 auto ImmDef = MIB.buildConstant(
LLT::scalar(32), Imm);
561 MIB.buildInstr(NewOpc, {
MI.getOperand(0)}, {
MI.getOperand(1), ImmDef});
562 MI.eraseFromParent();
572std::optional<std::pair<uint64_t, CmpInst::Predicate>>
575 const auto &Ty =
MRI.getType(RHS);
579 assert((
Size == 32 ||
Size == 64) &&
"Expected 32 or 64 bit compare only?");
586 uint64_t OriginalC = ValAndVReg->Value.getZExtValue();
605 (
Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MIN))
631 if ((
Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MAX) ||
645 if ((
Size == 32 &&
static_cast<uint32_t>(
C) == UINT32_MAX) ||
660 auto IsMaterializableInSingleInstruction = [=](
uint64_t Imm) {
663 return Insn.size() == 1;
666 if (!IsMaterializableInSingleInstruction(OriginalC) &&
667 IsMaterializableInSingleInstruction(
C))
681bool matchAdjustICmpImmAndPred(
683 std::pair<uint64_t, CmpInst::Predicate> &MatchInfo) {
684 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
687 if (
auto MaybeNewImmAndPred = tryAdjustICmpImmAndPred(RHS, Pred,
MRI)) {
688 MatchInfo = *MaybeNewImmAndPred;
694void applyAdjustICmpImmAndPred(
695 MachineInstr &
MI, std::pair<uint64_t, CmpInst::Predicate> &MatchInfo,
703 RHS.setReg(Cst->getOperand(0).getReg());
704 MI.getOperand(1).setPredicate(MatchInfo.second);
709 std::pair<unsigned, int> &MatchInfo) {
710 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
712 const LLT SrcTy =
MRI.getType(Src1Reg);
713 const LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
732 if (ScalarSize == 64)
733 Opc = AArch64::G_DUPLANE64;
734 else if (ScalarSize == 32)
735 Opc = AArch64::G_DUPLANE32;
738 if (ScalarSize == 32)
739 Opc = AArch64::G_DUPLANE32;
740 else if (ScalarSize == 16)
741 Opc = AArch64::G_DUPLANE16;
745 Opc = AArch64::G_DUPLANE8;
746 else if (ScalarSize == 16)
747 Opc = AArch64::G_DUPLANE16;
751 Opc = AArch64::G_DUPLANE8;
759 MatchInfo.first = Opc;
760 MatchInfo.second = *LaneIdx;
766 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
768 const LLT SrcTy =
MRI.getType(Src1Reg);
770 B.setInstrAndDebugLoc(
MI);
771 auto Lane =
B.buildConstant(
LLT::scalar(64), MatchInfo.second);
777 auto Undef =
B.buildUndef(SrcTy);
779 {Src1Reg, Undef.getReg(0)})
782 B.buildInstr(MatchInfo.first, {MI.getOperand(0).getReg()}, {DupSrc, Lane});
783 MI.eraseFromParent();
787 auto &Unmerge = cast<GUnmerge>(
MI);
788 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
789 const LLT SrcTy =
MRI.getType(Src1Reg);
798 auto &Unmerge = cast<GUnmerge>(
MI);
799 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
800 const LLT SrcTy =
MRI.getType(Src1Reg);
802 "Expected a fixed length vector");
805 B.buildExtractVectorElementConstant(Unmerge.getReg(
I), Src1Reg,
I);
806 MI.eraseFromParent();
810 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
819 int64_t Cst =
Splat->getCst();
820 return (Cst != 0 && Cst != -1);
825 B.setInstrAndDebugLoc(
MI);
826 B.buildInstr(AArch64::G_DUP, {
MI.getOperand(0).
getReg()},
828 MI.eraseFromParent();
835 if (!
MRI.hasOneNonDBGUse(CmpOp))
840 if (
MI.getOpcode() == TargetOpcode::G_SEXT_INREG)
842 if (
MI.getOpcode() != TargetOpcode::G_AND)
849 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
853 if (IsSupportedExtend(*Def))
856 unsigned Opc =
Def->getOpcode();
857 if (Opc != TargetOpcode::G_SHL && Opc != TargetOpcode::G_ASHR &&
858 Opc != TargetOpcode::G_LSHR)
865 uint64_t ShiftAmt = MaybeShiftAmt->Value.getZExtValue();
872 if (IsSupportedExtend(*ShiftLHS))
873 return (ShiftAmt <= 4) ? 2 : 1;
875 LLT Ty =
MRI.getType(
Def->getOperand(0).getReg());
879 if ((ShiftSize == 32 && ShiftAmt <= 31) ||
880 (ShiftSize == 64 && ShiftAmt <= 63))
888 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
914 Register TheLHS = GetRegForProfit(LHS);
915 Register TheRHS = GetRegForProfit(RHS);
929 MI.getOperand(2).setReg(RHS);
930 MI.getOperand(3).setReg(LHS);
941 LLT DstTy =
MRI.getType(LHS);
943 assert(DstTy ==
MRI.getType(RHS) &&
"Src and Dst types must match!");
995 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
999 LLT DstTy =
MRI.getType(Dst);
1003 unsigned EltSize =
MRI.getType(LHS).getScalarSizeInBits();
1004 if (EltSize == 16 && !
ST.hasFullFP16())
1006 if (EltSize != 16 && EltSize != 32 && EltSize != 64)
1015 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
1018 const auto &CmpMI = cast<GFCmp>(
MI);
1025 LLT DstTy =
MRI.getType(Dst);
1032 bool Invert =
false;
1034 if ((Pred == CmpInst::Predicate::FCMP_ORD ||
1035 Pred == CmpInst::Predicate::FCMP_UNO) &&
1052 ST.getTargetLowering()->getTargetMachine().Options.NoNaNsFPMath;
1054 auto Cmp = getVectorFCMP(
CC, LHS, RHS, IsZero, NoNans,
MRI);
1059 auto Cmp2 = getVectorFCMP(CC2, LHS, RHS, IsZero, NoNans,
MRI);
1060 auto Cmp2Dst = Cmp2(MIB);
1061 auto Cmp1Dst =
Cmp(MIB);
1066 MRI.replaceRegWith(Dst, CmpRes);
1067 MI.eraseFromParent();
1072 auto *GBuildVec = cast<GBuildVector>(&
MI);
1075 for (
unsigned I = 0;
I < GBuildVec->getNumSources(); ++
I) {
1079 if (!ConstVal.has_value())
1088 auto *GBuildVec = cast<GBuildVector>(&
MI);
1089 LLT DstTy =
MRI.getType(GBuildVec->getReg(0));
1090 Register DstReg =
B.buildUndef(DstTy).getReg(0);
1092 for (
unsigned I = 0;
I < GBuildVec->getNumSources(); ++
I) {
1093 Register SrcReg = GBuildVec->getSourceReg(
I);
1098 B.buildInsertVectorElement(DstTy, DstReg, SrcReg, IdxReg).getReg(0);
1100 B.buildCopy(GBuildVec->getReg(0), DstReg);
1101 GBuildVec->eraseFromParent();
1106 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1108 if (
MRI.getType(DstReg).isVector())
1114 return MRI.getType(SrcReg).getSizeInBits() <= 64;
1120 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1122 MI.getOperand(0).setReg(SrcReg);
1130 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1132 LLT DstTy =
MRI.getType(DstReg);
1138 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1139 B.setInstrAndDebugLoc(
MI);
1141 Helper.lower(
MI, 0,
LLT());
1148 auto &Unmerge = cast<GUnmerge>(
MI);
1149 if (Unmerge.getNumDefs() != 2)
1151 if (!
MRI.use_nodbg_empty(Unmerge.getReg(1)))
1154 LLT DstTy =
MRI.getType(Unmerge.getReg(0));
1166 if (!LowestVal || LowestVal->Value.getZExtValue() != DstTy.
getSizeInBytes())
1169 if (!getOpcodeDef<GImplicitDef>(ExtSrc2,
MRI))
1172 MatchInfo = ExtSrc1;
1182 MI.getOperand(0).setReg(
MI.getOperand(1).getReg());
1183 MI.getOperand(1).setReg(Dst1);
1184 MI.getOperand(2).setReg(SrcReg);
1195 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
1201 unsigned I1Opc =
I1->getOpcode();
1203 if (((I1Opc == TargetOpcode::G_ZEXT && I2Opc == TargetOpcode::G_ZEXT) ||
1204 (I1Opc == TargetOpcode::G_SEXT && I2Opc == TargetOpcode::G_SEXT)) &&
1205 (
MRI.getType(
I1->getOperand(0).getReg()).getScalarSizeInBits() ==
1206 MRI.getType(
I1->getOperand(1).getReg()).getScalarSizeInBits() * 2) &&
1221 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
1222 "Expected a G_MUL instruction");
1225 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
1230 unsigned I1Opc =
I1->getOpcode();
1232 if (((I1Opc == TargetOpcode::G_ZEXT && I2Opc == TargetOpcode::G_ZEXT) ||
1233 (I1Opc == TargetOpcode::G_SEXT && I2Opc == TargetOpcode::G_SEXT)) &&
1234 (
MRI.getType(
I1->getOperand(0).getReg()).getScalarSizeInBits() ==
1235 MRI.getType(
I1->getOperand(1).getReg()).getScalarSizeInBits() * 2) &&
1239 B.setInstrAndDebugLoc(
MI);
1240 B.buildInstr(
I1->getOpcode() == TargetOpcode::G_ZEXT ? AArch64::G_UMULL
1242 {MI.getOperand(0).getReg()},
1243 {I1->getOperand(1).getReg(), I2->getOperand(1).getReg()});
1244 MI.eraseFromParent();
1249 B.setInstrAndDebugLoc(
MI);
1250 Helper.fewerElementsVector(
1257class AArch64PostLegalizerLoweringImpl :
public Combiner {
1260 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig;
1264 AArch64PostLegalizerLoweringImpl(
1267 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1270 static const char *
getName() {
return "AArch6400PreLegalizerCombiner"; }
1275#define GET_GICOMBINER_CLASS_MEMBERS
1276#include "AArch64GenPostLegalizeGILowering.inc"
1277#undef GET_GICOMBINER_CLASS_MEMBERS
1280#define GET_GICOMBINER_IMPL
1281#include "AArch64GenPostLegalizeGILowering.inc"
1282#undef GET_GICOMBINER_IMPL
1284AArch64PostLegalizerLoweringImpl::AArch64PostLegalizerLoweringImpl(
1287 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1289 :
Combiner(MF, CInfo, TPC, nullptr, CSEInfo),
1290 Helper(Observer,
B,
true), RuleConfig(RuleConfig),
1293#include
"AArch64GenPostLegalizeGILowering.inc"
1302 AArch64PostLegalizerLowering();
1305 return "AArch64PostLegalizerLowering";
1312 AArch64PostLegalizerLoweringImplRuleConfig RuleConfig;
1316void AArch64PostLegalizerLowering::getAnalysisUsage(
AnalysisUsage &AU)
const {
1323AArch64PostLegalizerLowering::AArch64PostLegalizerLowering()
1327 if (!RuleConfig.parseCommandLineOption())
1331bool AArch64PostLegalizerLowering::runOnMachineFunction(
MachineFunction &MF) {
1333 MachineFunctionProperties::Property::FailedISel))
1336 MachineFunctionProperties::Property::Legalized) &&
1337 "Expected a legalized function?");
1338 auto *TPC = &getAnalysis<TargetPassConfig>();
1344 F.hasOptSize(),
F.hasMinSize());
1346 CInfo.MaxIterations = 1;
1347 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
1349 CInfo.EnableFullDCE =
false;
1350 AArch64PostLegalizerLoweringImpl Impl(MF, CInfo, TPC,
nullptr,
1352 return Impl.combineMachineInstrs();
1355char AArch64PostLegalizerLowering::ID = 0;
1357 "Lower AArch64 MachineInstrs after legalization",
false,
1366 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 isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
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.
This file declares the targeting of the Machinelegalizer class for AArch64.
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
#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 bool isScalableVector() const
Returns true if the LLT is a scalable vector.
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)
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...
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.
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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)
@ 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.
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...
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.