49#define GET_GICOMBINER_DEPS
50#include "AArch64GenPostLegalizeGILowering.inc"
51#undef GET_GICOMBINER_DEPS
53#define DEBUG_TYPE "aarch64-postlegalizer-lowering"
61#define GET_GICOMBINER_TYPES
62#include "AArch64GenPostLegalizeGILowering.inc"
63#undef GET_GICOMBINER_TYPES
68struct ShuffleVectorPseudo {
73 std::initializer_list<SrcOp> SrcOps)
74 :
Opc(
Opc), Dst(Dst), SrcOps(SrcOps){};
75 ShuffleVectorPseudo() =
default;
81 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT);
83 const unsigned DstSize =
MRI.getType(DstReg).getSizeInBits();
84 if (DstSize != 16 && DstSize != 32 && DstSize != 64)
90 return all_of(
MRI.use_nodbg_instructions(DstReg),
96 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT);
98 const APFloat &ImmValAPF =
MI.getOperand(1).getFPImm()->getValueAPF();
100 MI.eraseFromParent();
105std::optional<std::pair<bool, uint64_t>> getExtMask(
ArrayRef<int> M,
108 auto FirstRealElt =
find_if(M, [](
int Elt) {
return Elt >= 0; });
109 if (FirstRealElt == M.end())
114 APInt ExpectedElt =
APInt(MaskBits, *FirstRealElt + 1,
false,
true);
120 [&ExpectedElt](
int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
130 bool ReverseExt =
false;
142 return std::make_pair(ReverseExt, Imm);
154 int NumInputElements) {
155 if (M.size() !=
static_cast<size_t>(NumInputElements))
157 int NumLHSMatch = 0, NumRHSMatch = 0;
158 int LastLHSMismatch = -1, LastRHSMismatch = -1;
159 for (
int Idx = 0; Idx < NumInputElements; ++Idx) {
165 M[Idx] == Idx ? ++NumLHSMatch : LastLHSMismatch = Idx;
166 M[Idx] == Idx + NumInputElements ? ++NumRHSMatch : LastRHSMismatch = Idx;
168 const int NumNeededToMatch = NumInputElements - 1;
169 if (NumLHSMatch == NumNeededToMatch)
170 return std::make_pair(
true, LastLHSMismatch);
171 if (NumRHSMatch == NumNeededToMatch)
172 return std::make_pair(
false, LastRHSMismatch);
179 ShuffleVectorPseudo &MatchInfo) {
180 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
184 LLT Ty =
MRI.getType(Dst);
185 unsigned EltSize = Ty.getScalarSizeInBits();
191 unsigned NumElts = Ty.getNumElements();
194 for (
unsigned LaneSize : {64U, 32U, 16U}) {
195 if (
isREVMask(ShuffleMask, EltSize, NumElts, LaneSize)) {
198 Opcode = AArch64::G_REV64;
199 else if (LaneSize == 32U)
200 Opcode = AArch64::G_REV32;
202 Opcode = AArch64::G_REV16;
204 MatchInfo = ShuffleVectorPseudo(Opcode, Dst, {Src});
215 ShuffleVectorPseudo &MatchInfo) {
216 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
217 unsigned WhichResult;
218 unsigned OperandOrder;
221 unsigned NumElts =
MRI.getType(Dst).getNumElements();
222 if (!
isTRNMask(ShuffleMask, NumElts, WhichResult, OperandOrder))
224 unsigned Opc = (WhichResult == 0) ? AArch64::G_TRN1 :
AArch64::G_TRN2;
225 Register V1 =
MI.getOperand(OperandOrder == 0 ? 1 : 2).getReg();
226 Register V2 =
MI.getOperand(OperandOrder == 0 ? 2 : 1).getReg();
227 MatchInfo = ShuffleVectorPseudo(
Opc, Dst, {V1, V2});
237 ShuffleVectorPseudo &MatchInfo) {
238 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
239 unsigned WhichResult;
242 unsigned NumElts =
MRI.getType(Dst).getNumElements();
243 if (!
isUZPMask(ShuffleMask, NumElts, WhichResult))
245 unsigned Opc = (WhichResult == 0) ? AArch64::G_UZP1 :
AArch64::G_UZP2;
248 MatchInfo = ShuffleVectorPseudo(
Opc, Dst, {V1, V2});
253 ShuffleVectorPseudo &MatchInfo) {
254 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
255 unsigned WhichResult;
256 unsigned OperandOrder;
259 unsigned NumElts =
MRI.getType(Dst).getNumElements();
260 if (!
isZIPMask(ShuffleMask, NumElts, WhichResult, OperandOrder))
262 unsigned Opc = (WhichResult == 0) ? AArch64::G_ZIP1 :
AArch64::G_ZIP2;
263 Register V1 =
MI.getOperand(OperandOrder == 0 ? 1 : 2).getReg();
264 Register V2 =
MI.getOperand(OperandOrder == 0 ? 2 : 1).getReg();
265 MatchInfo = ShuffleVectorPseudo(
Opc, Dst, {V1, V2});
272 ShuffleVectorPseudo &MatchInfo) {
291 auto *InsMI =
getOpcodeDef(TargetOpcode::G_INSERT_VECTOR_ELT,
292 MI.getOperand(1).getReg(),
MRI);
296 if (!
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
304 MatchInfo = ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(),
305 {InsMI->getOperand(2).getReg()});
312 ShuffleVectorPseudo &MatchInfo) {
313 assert(Lane >= 0 &&
"Expected positive lane?");
314 int NumElements =
MRI.getType(
MI.getOperand(1).getReg()).getNumElements();
319 MI.getOperand(Lane < NumElements ? 1 : 2).getReg(),
MRI);
321 if (NumElements <= Lane)
326 Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
328 ShuffleVectorPseudo(AArch64::G_DUP,
MI.getOperand(0).getReg(), {Reg});
333 ShuffleVectorPseudo &MatchInfo) {
334 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
338 int Lane = *MaybeLane;
342 if (matchDupFromInsertVectorElt(Lane,
MI,
MRI, MatchInfo))
344 if (matchDupFromBuildVector(Lane,
MI,
MRI, MatchInfo))
352 unsigned NumElts = Ty.getNumElements();
361 unsigned ExpectedElt = M[0];
362 for (
unsigned I = 1;
I < NumElts; ++
I) {
366 if (ExpectedElt == NumElts)
371 if (ExpectedElt !=
static_cast<unsigned>(M[
I]))
379 ShuffleVectorPseudo &MatchInfo) {
380 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
382 LLT DstTy =
MRI.getType(Dst);
385 auto Mask =
MI.getOperand(3).getShuffleMask();
388 uint64_t ExtFactor =
MRI.getType(V1).getScalarSizeInBits() / 8;
392 !isSingletonExtMask(Mask, DstTy))
396 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1, V1,
Imm});
400 std::tie(ReverseExt, Imm) = *ExtInfo;
404 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1, V2,
Imm});
411 ShuffleVectorPseudo &MatchInfo) {
413 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst}, MatchInfo.SrcOps);
414 MI.eraseFromParent();
422 if (MatchInfo.SrcOps[2].getImm() == 0)
423 MIRBuilder.buildCopy(MatchInfo.Dst, MatchInfo.SrcOps[0]);
427 MIRBuilder.buildConstant(
LLT::scalar(32), MatchInfo.SrcOps[2].getImm());
428 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst},
429 {MatchInfo.SrcOps[0], MatchInfo.SrcOps[1], Cst});
431 MI.eraseFromParent();
437 LLT DstTy =
MRI.getType(Dst);
439 "Expected 128bit vector in applyFullRev");
441 auto Cst = MIRBuilder.buildConstant(
LLT::scalar(32), 8);
442 auto Rev = MIRBuilder.buildInstr(AArch64::G_REV64, {DstTy}, {Src});
443 MIRBuilder.buildInstr(AArch64::G_EXT, {Dst}, {Rev, Rev, Cst});
444 MI.eraseFromParent();
448 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT);
458 Builder.setInstrAndDebugLoc(Insert);
476 auto StackTemp = Builder.buildFrameIndex(FramePtrTy, FrameIdx);
478 Builder.buildStore(
Insert.getOperand(1), StackTemp, PtrInfo,
Align(8));
483 "Expected a power-2 vector size");
486 auto EltSize = Builder.buildConstant(IdxTy, EltTy.
getSizeInBytes());
489 Builder.buildPtrAdd(
MRI.getType(StackTemp.getReg(0)), StackTemp,
Mul)
493 Builder.buildStore(
Insert.getElementReg(), EltPtr, PtrInfo,
Align(1));
495 Builder.buildLoad(
Insert.getReg(0), StackTemp, PtrInfo,
Align(8));
511 std::tuple<Register, int, Register, int> &MatchInfo) {
512 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
515 int NumElts =
MRI.getType(Dst).getNumElements();
516 auto DstIsLeftAndDstLane =
isINSMask(ShuffleMask, NumElts);
517 if (!DstIsLeftAndDstLane)
521 std::tie(DstIsLeft, DstLane) = *DstIsLeftAndDstLane;
527 int SrcLane = ShuffleMask[DstLane];
528 if (SrcLane >= NumElts) {
533 MatchInfo = std::make_tuple(DstVec, DstLane, SrcVec, SrcLane);
539 std::tuple<Register, int, Register, int> &MatchInfo) {
540 Builder.setInstrAndDebugLoc(
MI);
542 auto ScalarTy =
MRI.getType(Dst).getElementType();
544 int DstLane, SrcLane;
545 std::tie(DstVec, DstLane, SrcVec, SrcLane) = MatchInfo;
546 auto SrcCst = Builder.buildConstant(
LLT::scalar(64), SrcLane);
547 auto Extract = Builder.buildExtractVectorElement(ScalarTy, SrcVec, SrcCst);
548 auto DstCst = Builder.buildConstant(
LLT::scalar(64), DstLane);
549 Builder.buildInsertVectorElement(Dst, DstVec, Extract, DstCst);
550 MI.eraseFromParent();
558 assert(Ty.isVector() &&
"vector shift count is not a vector type");
564 int64_t ElementBits = Ty.getScalarSizeInBits();
565 return Cnt >= 1 && Cnt <= ElementBits;
571 assert(
MI.getOpcode() == TargetOpcode::G_ASHR ||
572 MI.getOpcode() == TargetOpcode::G_LSHR);
573 LLT Ty =
MRI.getType(
MI.getOperand(1).getReg());
581 unsigned Opc =
MI.getOpcode();
582 assert(
Opc == TargetOpcode::G_ASHR ||
Opc == TargetOpcode::G_LSHR);
584 Opc == TargetOpcode::G_ASHR ? AArch64::G_VASHR : AArch64::G_VLSHR;
586 MIB.buildInstr(NewOpc, {
MI.getOperand(0)}, {
MI.getOperand(1)}).addImm(Imm);
587 MI.eraseFromParent();
597std::optional<std::pair<uint64_t, CmpInst::Predicate>>
600 const auto &Ty =
MRI.getType(
RHS);
603 unsigned Size = Ty.getSizeInBits();
604 assert((
Size == 32 ||
Size == 64) &&
"Expected 32 or 64 bit compare only?");
611 uint64_t OriginalC = ValAndVReg->Value.getZExtValue();
630 (
Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MIN))
643 assert(
C != 0 &&
"C should not be zero here!");
655 if ((
Size == 32 &&
static_cast<int32_t
>(
C) == INT32_MAX) ||
669 if ((
Size == 32 &&
static_cast<uint32_t>(
C) == UINT32_MAX) ||
690 if (NumberOfInstrToLoadImm(OriginalC) > NumberOfInstrToLoadImm(
C))
704bool matchAdjustICmpImmAndPred(
706 std::pair<uint64_t, CmpInst::Predicate> &MatchInfo) {
707 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
710 if (
auto MaybeNewImmAndPred = tryAdjustICmpImmAndPred(
RHS, Pred,
MRI)) {
711 MatchInfo = *MaybeNewImmAndPred;
717void applyAdjustICmpImmAndPred(
718 MachineInstr &
MI, std::pair<uint64_t, CmpInst::Predicate> &MatchInfo,
726 RHS.setReg(Cst->getOperand(0).getReg());
727 MI.getOperand(1).setPredicate(MatchInfo.second);
732 std::pair<unsigned, int> &MatchInfo) {
733 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
735 const LLT SrcTy =
MRI.getType(Src1Reg);
736 const LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
743 if (*LaneIdx >= SrcTy.getNumElements())
753 switch (SrcTy.getNumElements()) {
755 if (ScalarSize == 64)
756 Opc = AArch64::G_DUPLANE64;
757 else if (ScalarSize == 32)
758 Opc = AArch64::G_DUPLANE32;
761 if (ScalarSize == 32)
762 Opc = AArch64::G_DUPLANE32;
763 else if (ScalarSize == 16)
764 Opc = AArch64::G_DUPLANE16;
768 Opc = AArch64::G_DUPLANE8;
769 else if (ScalarSize == 16)
770 Opc = AArch64::G_DUPLANE16;
774 Opc = AArch64::G_DUPLANE8;
782 MatchInfo.first =
Opc;
783 MatchInfo.second = *LaneIdx;
789 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
791 const LLT SrcTy =
MRI.getType(Src1Reg);
793 B.setInstrAndDebugLoc(
MI);
794 auto Lane =
B.buildConstant(
LLT::scalar(64), MatchInfo.second);
799 if (SrcTy.getSizeInBits() == 64) {
800 auto Undef =
B.buildUndef(SrcTy);
801 DupSrc =
B.buildConcatVectors(SrcTy.multiplyElements(2),
802 {Src1Reg, Undef.getReg(0)})
805 B.buildInstr(MatchInfo.first, {MI.getOperand(0).getReg()}, {DupSrc, Lane});
806 MI.eraseFromParent();
811 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
812 const LLT SrcTy =
MRI.getType(Src1Reg);
813 if (SrcTy.getSizeInBits() != 128 && SrcTy.getSizeInBits() != 64)
815 return SrcTy.isVector() && !SrcTy.isScalable() &&
816 Unmerge.getNumOperands() == (
unsigned)SrcTy.getNumElements() + 1;
822 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
823 const LLT SrcTy =
MRI.getType(Src1Reg);
824 assert((SrcTy.isVector() && !SrcTy.isScalable()) &&
825 "Expected a fixed length vector");
827 for (
int I = 0;
I < SrcTy.getNumElements(); ++
I)
828 B.buildExtractVectorElementConstant(Unmerge.getReg(
I), Src1Reg,
I);
829 MI.eraseFromParent();
833 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
846 B.setInstrAndDebugLoc(
MI);
847 B.buildInstr(AArch64::G_DUP, {
MI.getOperand(0).getReg()},
848 {
MI.getOperand(1).getReg()});
849 MI.eraseFromParent();
856 if (!
MRI.hasOneNonDBGUse(CmpOp))
861 if (
MI.getOpcode() == TargetOpcode::G_SEXT_INREG)
863 if (
MI.getOpcode() != TargetOpcode::G_AND)
870 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
874 if (IsSupportedExtend(*Def))
877 unsigned Opc =
Def->getOpcode();
878 if (
Opc != TargetOpcode::G_SHL &&
Opc != TargetOpcode::G_ASHR &&
879 Opc != TargetOpcode::G_LSHR)
886 uint64_t ShiftAmt = MaybeShiftAmt->Value.getZExtValue();
893 if (IsSupportedExtend(*ShiftLHS))
894 return (ShiftAmt <= 4) ? 2 : 1;
896 LLT Ty =
MRI.getType(
Def->getOperand(0).getReg());
899 unsigned ShiftSize = Ty.getSizeInBits();
900 if ((ShiftSize == 32 && ShiftAmt <= 31) ||
901 (ShiftSize == 64 && ShiftAmt <= 63))
909 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
950 MI.getOperand(2).setReg(
RHS);
951 MI.getOperand(3).setReg(
LHS);
963 assert(DstTy ==
MRI.getType(
RHS) &&
"Src and Dst types must match!");
998 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
1002 LLT DstTy =
MRI.getType(Dst);
1006 unsigned EltSize =
MRI.getType(
LHS).getScalarSizeInBits();
1007 if (EltSize == 16 && !
ST.hasFullFP16())
1009 if (EltSize != 16 && EltSize != 32 && EltSize != 64)
1018 assert(
MI.getOpcode() == TargetOpcode::G_FCMP);
1028 LLT DstTy =
MRI.getType(Dst);
1030 bool Invert =
false;
1049 ST.getTargetLowering()->getTargetMachine().Options.NoNaNsFPMath;
1056 auto Cmp2 = getVectorFCMP(CC2,
LHS,
RHS, NoNans,
MRI);
1057 auto Cmp2Dst = Cmp2(MIB);
1058 auto Cmp1Dst =
Cmp(MIB);
1063 MRI.replaceRegWith(Dst, CmpRes);
1064 MI.eraseFromParent();
1072 for (
unsigned I = 0;
I < GBuildVec->getNumSources(); ++
I) {
1076 if (!ConstVal.has_value())
1086 LLT DstTy =
MRI.getType(GBuildVec->getReg(0));
1087 Register DstReg =
B.buildUndef(DstTy).getReg(0);
1089 for (
unsigned I = 0;
I < GBuildVec->getNumSources(); ++
I) {
1090 Register SrcReg = GBuildVec->getSourceReg(
I);
1095 B.buildInsertVectorElement(DstTy, DstReg, SrcReg, IdxReg).getReg(0);
1097 B.buildCopy(GBuildVec->getReg(0), DstReg);
1098 GBuildVec->eraseFromParent();
1103 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1105 if (
MRI.getType(DstReg).isVector())
1111 return MRI.getType(SrcReg).getSizeInBits() <= 64;
1117 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
1119 MI.getOperand(0).setReg(SrcReg);
1127 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1129 LLT DstTy =
MRI.getType(DstReg);
1135 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1136 B.setInstrAndDebugLoc(
MI);
1138 Helper.lower(
MI, 0,
LLT());
1146 if (Unmerge.getNumDefs() != 2)
1148 if (!
MRI.use_nodbg_empty(Unmerge.getReg(1)))
1151 LLT DstTy =
MRI.getType(Unmerge.getReg(0));
1163 if (!LowestVal || LowestVal->Value.getZExtValue() != DstTy.
getSizeInBytes())
1169 MatchInfo = ExtSrc1;
1179 MI.getOperand(0).setReg(
MI.getOperand(1).getReg());
1180 MI.getOperand(1).setReg(Dst1);
1181 MI.getOperand(2).setReg(SrcReg);
1192 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
1198 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
1199 "Expected a G_MUL instruction");
1202 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
1205 Helper.fewerElementsVector(
1210class AArch64PostLegalizerLoweringImpl :
public Combiner {
1212 const CombinerHelper Helper;
1213 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig;
1214 const AArch64Subtarget &STI;
1217 AArch64PostLegalizerLoweringImpl(
1218 MachineFunction &MF, CombinerInfo &CInfo,
const TargetPassConfig *TPC,
1219 GISelCSEInfo *CSEInfo,
1220 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1221 const AArch64Subtarget &STI);
1223 static const char *
getName() {
return "AArch6400PreLegalizerCombiner"; }
1225 bool tryCombineAll(MachineInstr &
I)
const override;
1228#define GET_GICOMBINER_CLASS_MEMBERS
1229#include "AArch64GenPostLegalizeGILowering.inc"
1230#undef GET_GICOMBINER_CLASS_MEMBERS
1233#define GET_GICOMBINER_IMPL
1234#include "AArch64GenPostLegalizeGILowering.inc"
1235#undef GET_GICOMBINER_IMPL
1237AArch64PostLegalizerLoweringImpl::AArch64PostLegalizerLoweringImpl(
1240 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1242 :
Combiner(MF, CInfo, TPC, nullptr, CSEInfo),
1243 Helper(Observer,
B,
true), RuleConfig(RuleConfig),
1246#include
"AArch64GenPostLegalizeGILowering.inc"
1255 AArch64PostLegalizerLowering();
1258 return "AArch64PostLegalizerLowering";
1265 AArch64PostLegalizerLoweringImplRuleConfig RuleConfig;
1269void AArch64PostLegalizerLowering::getAnalysisUsage(
AnalysisUsage &AU)
const {
1276AArch64PostLegalizerLowering::AArch64PostLegalizerLowering()
1278 if (!RuleConfig.parseCommandLineOption())
1282bool AArch64PostLegalizerLowering::runOnMachineFunction(
MachineFunction &MF) {
1286 auto *TPC = &getAnalysis<TargetPassConfig>();
1292 F.hasOptSize(),
F.hasMinSize());
1294 CInfo.MaxIterations = 1;
1297 CInfo.EnableFullDCE =
false;
1298 AArch64PostLegalizerLoweringImpl Impl(MF, CInfo, TPC,
nullptr,
1300 return Impl.combineMachineInstrs();
1303char AArch64PostLegalizerLowering::ID = 0;
1305 "Lower AArch64 MachineInstrs after legalization",
false,
1309 "Lower AArch64 MachineInstrs after legalization",
false,
1314 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 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.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define GET_GICOMBINER_CONSTRUCTOR_INITS
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_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)
Target-Independent Code Generator Pass Configuration Options pass.
APInt bitcastToAPInt() const
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()
LLVM_ABI 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),...
This class is the base class for the comparison instructions.
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.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
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 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.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
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,...
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.
Target-Independent Code Generator Pass Configuration Options.
A Use represents the edge between a Value definition and its users.
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)
constexpr bool isLegalArithImmed(const uint64_t C)
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)
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.
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.
ImplicitDefMatch m_GImplicitDef()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
@ Undef
Value of the register doesn't matter.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
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...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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,...
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.)
LLVM_ABI 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.
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.
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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.
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.