24#include "llvm/IR/IntrinsicsAArch64.h"
36#define DEBUG_TYPE "aarch64tti"
39class TailFoldingOption {
54 bool NeedsDefault =
true;
58 void setNeedsDefault(
bool V) { NeedsDefault = V; }
74 "Initial bits should only include one of "
75 "(disabled|all|simple|default)");
76 Bits = NeedsDefault ? DefaultBits : InitialBits;
84 errs() <<
"invalid argument '" << Opt
85 <<
"' to -sve-tail-folding=; the option should be of the form\n"
86 " (disabled|all|default|simple)[+(reductions|recurrences"
87 "|reverse|noreductions|norecurrences|noreverse)]\n";
93 void operator=(
const std::string &Val) {
102 setNeedsDefault(
false);
107 unsigned StartIdx = 1;
108 if (TailFoldTypes[0] ==
"disabled")
110 else if (TailFoldTypes[0] ==
"all")
112 else if (TailFoldTypes[0] ==
"default")
113 setNeedsDefault(
true);
114 else if (TailFoldTypes[0] ==
"simple")
121 for (
unsigned I = StartIdx;
I < TailFoldTypes.
size();
I++) {
122 if (TailFoldTypes[
I] ==
"reductions")
124 else if (TailFoldTypes[
I] ==
"recurrences")
126 else if (TailFoldTypes[
I] ==
"reverse")
128 else if (TailFoldTypes[
I] ==
"noreductions")
130 else if (TailFoldTypes[
I] ==
"norecurrences")
132 else if (TailFoldTypes[
I] ==
"noreverse")
144 return (
getBits(DefaultBits) & Required) == Required;
154 "Control the use of vectorisation using tail-folding for SVE where the"
155 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
156 "\ndisabled (Initial) No loop types will vectorize using "
158 "\ndefault (Initial) Uses the default tail-folding settings for "
160 "\nall (Initial) All legal loop types will vectorize using "
162 "\nsimple (Initial) Use tail-folding for simple loops (not "
163 "reductions or recurrences)"
164 "\nreductions Use tail-folding for loops containing reductions"
165 "\nnoreductions Inverse of above"
166 "\nrecurrences Use tail-folding for loops containing fixed order "
168 "\nnorecurrences Inverse of above"
169 "\nreverse Use tail-folding for loops requiring reversed "
171 "\nnoreverse Inverse of above"),
180 bool ConsiderSM)
const {
181 if (!ConsiderZA && !ConsiderZT && !ConsiderSM)
184 bool IsAlwaysInline =
F->hasFnAttribute(Attribute::AlwaysInline);
191 bool AssumeVScaleIsEquivalent =
192 F->getReturnType()->isScalableTy() ||
193 any_of(
F->getFunctionType()->params(),
194 [](
const Type *
T) { return T->isScalableTy(); });
202 if (CB->isInlineAsm())
205 if (
CallAttrs.callee().isSMEABIRoutine())
214 if (ConsiderSM &&
CallAttrs.callee().hasStreamingCompatibleInterface())
226 return isa<FixedVectorType>(V->getType());
231 unsigned IID =
II->getIntrinsicID();
239 case Intrinsic::masked_gather:
240 case Intrinsic::masked_scatter:
241 case Intrinsic::masked_compressstore:
242 case Intrinsic::experimental_vector_histogram_add:
246 if (
I.getOperand(0)->getType()->isScalableTy())
249 case Intrinsic::vscale:
250 if (!AssumeVScaleIsEquivalent)
258 if (!AssumeVScaleIsEquivalent &&
259 (
I.getType()->isScalableTy() ||
262 [](
const Value *V) { return V->getType()->isScalableTy(); }) ||
264 .getSourceElementType()
277 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
278 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
279 FeatureStr.
split(Features,
",");
295 return F.hasFnAttribute(
"fmv-features");
347 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
348 CallAttrs.callee().hasStreamingInterfaceOrBody())
356 if (
CallAttrs.callee().hasStreamingBody()) {
361 bool ConsiderZA =
CallAttrs.requiresZASave();
362 bool ConsiderZT =
CallAttrs.requiresPreservingZT0() ||
363 CallAttrs.requiresPreservingAllZAState();
364 bool ConsiderSM =
CallAttrs.requiresSMChange();
369 if (ConsiderSM && (Caller->isStrictFP() || Callee->isStrictFP()))
393 auto FVTy = dyn_cast<FixedVectorType>(Ty);
395 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
404 unsigned DefaultCallPenalty)
const {
429 if (
F ==
Call.getCaller())
430 return ST->getCLOpts().call_penalty_sm_change * DefaultCallPenalty;
432 return ST->getCLOpts().inline_call_penalty_sm_change * DefaultCallPenalty;
435 return DefaultCallPenalty;
446 ST->isSVEorStreamingSVEAvailable() &&
447 !ST->disableMaximizeScalableBandwidth();
471 assert(Ty->isIntegerTy());
473 unsigned BitSize = Ty->getPrimitiveSizeInBits();
480 ImmVal =
Imm.sext((BitSize + 63) & ~0x3fU);
485 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
491 return std::max<InstructionCost>(1,
Cost);
498 assert(Ty->isIntegerTy());
500 unsigned BitSize = Ty->getPrimitiveSizeInBits();
506 unsigned ImmIdx = ~0U;
510 case Instruction::GetElementPtr:
515 case Instruction::Store:
518 case Instruction::Add:
519 case Instruction::Sub:
520 case Instruction::Mul:
521 case Instruction::UDiv:
522 case Instruction::SDiv:
523 case Instruction::URem:
524 case Instruction::SRem:
525 case Instruction::And:
526 case Instruction::Or:
527 case Instruction::Xor:
528 case Instruction::ICmp:
532 case Instruction::Shl:
533 case Instruction::LShr:
534 case Instruction::AShr:
538 case Instruction::Trunc:
539 case Instruction::ZExt:
540 case Instruction::SExt:
541 case Instruction::IntToPtr:
542 case Instruction::PtrToInt:
543 case Instruction::BitCast:
544 case Instruction::PHI:
545 case Instruction::Call:
546 case Instruction::Select:
547 case Instruction::Ret:
548 case Instruction::Load:
553 int NumConstants = (BitSize + 63) / 64;
566 assert(Ty->isIntegerTy());
568 unsigned BitSize = Ty->getPrimitiveSizeInBits();
577 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
583 case Intrinsic::sadd_with_overflow:
584 case Intrinsic::uadd_with_overflow:
585 case Intrinsic::ssub_with_overflow:
586 case Intrinsic::usub_with_overflow:
587 case Intrinsic::smul_with_overflow:
588 case Intrinsic::umul_with_overflow:
590 int NumConstants = (BitSize + 63) / 64;
597 case Intrinsic::experimental_stackmap:
598 if ((Idx < 2) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
601 case Intrinsic::experimental_patchpoint_void:
602 case Intrinsic::experimental_patchpoint:
603 if ((Idx < 4) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
606 case Intrinsic::experimental_gc_statepoint:
607 if ((Idx < 5) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
617 if (TyWidth == 32 || TyWidth == 64)
626 return ST->getMispredictionPenalty();
647 unsigned TotalHistCnts = 1;
657 unsigned EC = VTy->getElementCount().getKnownMinValue();
662 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
664 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
668 TotalHistCnts = EC / NaturalVectorWidth;
670 return InstructionCost(ST->getCLOpts().base_histcnt_cost * TotalHistCnts);
687 !
is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
691 switch (ICA.
getID()) {
692 case Intrinsic::experimental_vector_histogram_add: {
699 case Intrinsic::experimental_vector_histogram_uadd_sat:
700 case Intrinsic::experimental_vector_histogram_umax:
701 case Intrinsic::experimental_vector_histogram_umin:
704 case Intrinsic::clmul: {
709 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
713 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
718 -1,
nullptr,
nullptr) *
721 -1,
nullptr,
nullptr);
725 if (LT.second.SimpleTy == MVT::nxv2i64)
726 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
729 if (ST->hasSVE2() || ST->hasSME()) {
730 switch (LT.second.SimpleTy) {
745 if (LT.second.SimpleTy == MVT::nxv2i64)
749 switch (LT.second.SimpleTy) {
759 -1,
nullptr,
nullptr) *
762 -1,
nullptr,
nullptr));
771 return LT.first * 11;
773 return LT.first * 14;
780 case Intrinsic::smulh:
781 case Intrinsic::umulh: {
787 if (RetTy->getScalarSizeInBits() > 64)
801 return MulCost + ExtraCost;
806 return LT.first + ExtraCost;
822 return LT.first * Entry->Cost + ExtraCost;
826 case Intrinsic::umin:
827 case Intrinsic::umax:
828 case Intrinsic::smin:
829 case Intrinsic::smax: {
830 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
831 MVT::v8i16, MVT::v2i32, MVT::v4i32,
832 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
839 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
840 EVT VT = TLI->getValueType(
DL, RetTy,
true);
841 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
842 return LT.first * (IsSigned ? 5 : 3);
844 if (LT.second == MVT::v2i64)
850 case Intrinsic::scmp:
851 case Intrinsic::ucmp: {
853 {Intrinsic::scmp, MVT::i32, 3},
854 {Intrinsic::scmp, MVT::i64, 3},
855 {Intrinsic::scmp, MVT::v8i8, 3},
856 {Intrinsic::scmp, MVT::v16i8, 3},
857 {Intrinsic::scmp, MVT::v4i16, 3},
858 {Intrinsic::scmp, MVT::v8i16, 3},
859 {Intrinsic::scmp, MVT::v2i32, 3},
860 {Intrinsic::scmp, MVT::v4i32, 3},
861 {Intrinsic::scmp, MVT::v1i64, 3},
862 {Intrinsic::scmp, MVT::v2i64, 3},
868 return Entry->Cost * LT.first;
871 case Intrinsic::sadd_sat:
872 case Intrinsic::ssub_sat:
873 case Intrinsic::uadd_sat:
874 case Intrinsic::usub_sat: {
875 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
876 MVT::v8i16, MVT::v2i32, MVT::v4i32,
882 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
884 return LT.first * Instrs;
889 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
890 return LT.first * Instrs;
894 case Intrinsic::abs: {
895 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
896 MVT::v8i16, MVT::v2i32, MVT::v4i32,
897 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
898 MVT::nxv4i32, MVT::nxv2i64};
904 case Intrinsic::bswap: {
905 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
906 MVT::v4i32, MVT::v2i64};
909 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
914 case Intrinsic::fmuladd: {
919 (EltTy->
isHalfTy() && ST->hasFullFP16()))
923 case Intrinsic::stepvector: {
932 Cost += AddCost * (LT.first - 1);
936 case Intrinsic::vector_extract:
937 case Intrinsic::vector_insert: {
950 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
951 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
959 getTLI()->getTypeConversion(
C, SubVecVT);
961 getTLI()->getTypeConversion(
C, VecVT);
969 case Intrinsic::bitreverse: {
971 {Intrinsic::bitreverse, MVT::i32, 1},
972 {Intrinsic::bitreverse, MVT::i64, 1},
973 {Intrinsic::bitreverse, MVT::v8i8, 1},
974 {Intrinsic::bitreverse, MVT::v16i8, 1},
975 {Intrinsic::bitreverse, MVT::v4i16, 2},
976 {Intrinsic::bitreverse, MVT::v8i16, 2},
977 {Intrinsic::bitreverse, MVT::v2i32, 2},
978 {Intrinsic::bitreverse, MVT::v4i32, 2},
979 {Intrinsic::bitreverse, MVT::v1i64, 2},
980 {Intrinsic::bitreverse, MVT::v2i64, 2},
988 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
989 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
990 return LegalisationCost.first * Entry->Cost + 1;
992 return LegalisationCost.first * Entry->Cost;
996 case Intrinsic::ctpop: {
1000 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
1003 return LT.first + ExtraCost;
1005 if (!ST->hasNEON()) {
1035 RetTy->getScalarSizeInBits()
1038 return LT.first * Entry->Cost + ExtraCost;
1042 case Intrinsic::sadd_with_overflow:
1043 case Intrinsic::uadd_with_overflow:
1044 case Intrinsic::ssub_with_overflow:
1045 case Intrinsic::usub_with_overflow:
1046 case Intrinsic::smul_with_overflow:
1047 case Intrinsic::umul_with_overflow: {
1049 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
1050 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
1051 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
1052 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
1053 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
1054 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
1055 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
1056 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
1057 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
1058 {Intrinsic::usub_with_overflow, MVT::i8, 3},
1059 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
1060 {Intrinsic::usub_with_overflow, MVT::i16, 3},
1061 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
1062 {Intrinsic::usub_with_overflow, MVT::i32, 1},
1063 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
1064 {Intrinsic::usub_with_overflow, MVT::i64, 1},
1065 {Intrinsic::smul_with_overflow, MVT::i8, 5},
1066 {Intrinsic::umul_with_overflow, MVT::i8, 4},
1067 {Intrinsic::smul_with_overflow, MVT::i16, 5},
1068 {Intrinsic::umul_with_overflow, MVT::i16, 4},
1069 {Intrinsic::smul_with_overflow, MVT::i32, 2},
1070 {Intrinsic::umul_with_overflow, MVT::i32, 2},
1071 {Intrinsic::smul_with_overflow, MVT::i64, 3},
1072 {Intrinsic::umul_with_overflow, MVT::i64, 3},
1074 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
1081 case Intrinsic::fptosi_sat:
1082 case Intrinsic::fptoui_sat: {
1085 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
1087 EVT MTy = TLI->getValueType(
DL, RetTy);
1090 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
1091 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
1092 LT.second == MVT::v2f64)) {
1094 (LT.second == MVT::f64 && MTy == MVT::i32) ||
1095 (LT.second == MVT::f32 && MTy == MVT::i64)))
1104 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
1111 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
1112 (LT.second == MVT::f16 && MTy == MVT::i64) ||
1113 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1127 if ((LT.second.getScalarType() == MVT::f32 ||
1128 LT.second.getScalarType() == MVT::f64 ||
1129 LT.second.getScalarType() == MVT::f16) &&
1132 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1133 if (LT.second.isVector())
1134 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1138 LegalTy, {LegalTy, LegalTy});
1142 LegalTy, {LegalTy, LegalTy});
1144 return LT.first *
Cost +
1145 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1151 RetTy = RetTy->getScalarType();
1152 if (LT.second.isVector()) {
1170 return LT.first *
Cost;
1172 case Intrinsic::fshl:
1173 case Intrinsic::fshr: {
1182 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1183 (RetTy->getPrimitiveSizeInBits() == 32 ||
1184 RetTy->getPrimitiveSizeInBits() == 64)) {
1197 {Intrinsic::fshl, MVT::v4i32, 2},
1198 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1199 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1200 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1206 return LegalisationCost.first * Entry->Cost;
1210 if (!RetTy->isIntegerTy())
1215 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1216 RetTy->getScalarSizeInBits() < 64) ||
1217 (RetTy->getScalarSizeInBits() % 64 != 0);
1218 unsigned ExtraCost = HigherCost ? 1 : 0;
1219 if (RetTy->getScalarSizeInBits() == 32 ||
1220 RetTy->getScalarSizeInBits() == 64)
1223 else if (HigherCost)
1227 return TyL.first + ExtraCost;
1229 case Intrinsic::get_active_lane_mask: {
1231 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1233 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1236 if (RetTy->isScalableTy()) {
1237 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1247 if (ST->hasSVE2p1() || ST->hasSME2()) {
1259 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1262 return Cost + (SplitCost * (
Cost - 1));
1277 case Intrinsic::experimental_vector_match: {
1278 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1284 unsigned SearchSize = NeedleTy->getNumElements();
1285 if (SearchSize <= 2)
1290 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1294 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1300 unsigned MatchesRequiredForNeedle =
1312 return Cost * LegalParts * MatchesRequiredForNeedle;
1314 case Intrinsic::cttz: {
1316 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1317 return LT.first * 2;
1318 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1319 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1320 return LT.first * 3;
1323 case Intrinsic::experimental_cttz_elts: {
1333 case Intrinsic::loop_dependence_raw_mask:
1334 case Intrinsic::loop_dependence_war_mask: {
1336 if (ST->hasSVE2() || ST->hasSME()) {
1337 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1338 unsigned EltSizeInBytes =
1348 case Intrinsic::experimental_vector_extract_last_active:
1349 if (ST->isSVEorStreamingSVEAvailable()) {
1355 case Intrinsic::pow: {
1358 EVT VT = getTLI()->getValueType(
DL, RetTy);
1359 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1361 getTLI()->getLibcallLoweringInfo().getVectorLibcallImplOrMasked(LC) !=
1377 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1378 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1388 return (Sqrt * 2) +
FMul;
1399 case Intrinsic::sqrt:
1400 case Intrinsic::fabs:
1401 case Intrinsic::ceil:
1402 case Intrinsic::floor:
1403 case Intrinsic::nearbyint:
1404 case Intrinsic::round:
1405 case Intrinsic::rint:
1406 case Intrinsic::roundeven:
1407 case Intrinsic::trunc:
1408 case Intrinsic::minnum:
1409 case Intrinsic::maxnum:
1410 case Intrinsic::minimum:
1411 case Intrinsic::maximum: {
1429 auto RequiredType =
II.getType();
1432 assert(PN &&
"Expected Phi Node!");
1435 if (!PN->hasOneUse())
1436 return std::nullopt;
1438 for (
Value *IncValPhi : PN->incoming_values()) {
1441 Reinterpret->getIntrinsicID() !=
1442 Intrinsic::aarch64_sve_convert_to_svbool ||
1443 RequiredType != Reinterpret->getArgOperand(0)->getType())
1444 return std::nullopt;
1452 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1454 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1527 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1532 return GoverningPredicateIdx;
1537 GoverningPredicateIdx = Index;
1559 return UndefIntrinsic;
1564 UndefIntrinsic = IID;
1591 return CmpPredicate;
1596 CmpPredicate = Pred;
1612 return ResultLanes == InactiveLanesTakenFromOperand;
1617 return OperandIdxForInactiveLanes;
1621 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1622 ResultLanes = InactiveLanesTakenFromOperand;
1623 OperandIdxForInactiveLanes = Index;
1628 return ResultLanes == InactiveLanesAreNotDefined;
1632 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1633 ResultLanes = InactiveLanesAreNotDefined;
1638 return ResultLanes == InactiveLanesAreUnused;
1642 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1643 ResultLanes = InactiveLanesAreUnused;
1653 ResultIsZeroInitialized =
true;
1664 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1669 return OperandIdxWithNoActiveLanes;
1674 OperandIdxWithNoActiveLanes = Index;
1679 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1682 unsigned IROpcode = 0;
1685 enum PredicationStyle {
1687 InactiveLanesTakenFromOperand,
1688 InactiveLanesAreNotDefined,
1689 InactiveLanesAreUnused
1692 bool ResultIsZeroInitialized =
false;
1693 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1694 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1702 return !isa<ScalableVectorType>(V->getType());
1710 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1711 case Intrinsic::aarch64_sve_fcvt_f16f32:
1712 case Intrinsic::aarch64_sve_fcvt_f16f64:
1713 case Intrinsic::aarch64_sve_fcvt_f32f16:
1714 case Intrinsic::aarch64_sve_fcvt_f32f64:
1715 case Intrinsic::aarch64_sve_fcvt_f64f16:
1716 case Intrinsic::aarch64_sve_fcvt_f64f32:
1717 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1718 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1719 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1720 case Intrinsic::aarch64_sve_fcvtzs:
1721 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1722 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1723 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1724 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1725 case Intrinsic::aarch64_sve_fcvtzu:
1726 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1727 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1728 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1729 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1730 case Intrinsic::aarch64_sve_revb:
1731 case Intrinsic::aarch64_sve_revh:
1732 case Intrinsic::aarch64_sve_revw:
1733 case Intrinsic::aarch64_sve_revd:
1734 case Intrinsic::aarch64_sve_scvtf:
1735 case Intrinsic::aarch64_sve_scvtf_f16i32:
1736 case Intrinsic::aarch64_sve_scvtf_f16i64:
1737 case Intrinsic::aarch64_sve_scvtf_f32i64:
1738 case Intrinsic::aarch64_sve_scvtf_f64i32:
1739 case Intrinsic::aarch64_sve_ucvtf:
1740 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1741 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1742 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1743 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1746 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1747 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1748 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1749 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1752 case Intrinsic::aarch64_sve_fabd:
1754 case Intrinsic::aarch64_sve_fadd:
1757 case Intrinsic::aarch64_sve_fdiv:
1760 case Intrinsic::aarch64_sve_fmax:
1762 case Intrinsic::aarch64_sve_fmaxnm:
1764 case Intrinsic::aarch64_sve_fmin:
1766 case Intrinsic::aarch64_sve_fminnm:
1768 case Intrinsic::aarch64_sve_fmla:
1770 case Intrinsic::aarch64_sve_fmls:
1772 case Intrinsic::aarch64_sve_fmul:
1775 case Intrinsic::aarch64_sve_fmulx:
1777 case Intrinsic::aarch64_sve_fnmla:
1779 case Intrinsic::aarch64_sve_fnmls:
1781 case Intrinsic::aarch64_sve_fsub:
1784 case Intrinsic::aarch64_sve_add:
1787 case Intrinsic::aarch64_sve_mla:
1789 case Intrinsic::aarch64_sve_mls:
1791 case Intrinsic::aarch64_sve_mul:
1794 case Intrinsic::aarch64_sve_sabd:
1796 case Intrinsic::aarch64_sve_sdiv:
1799 case Intrinsic::aarch64_sve_smax:
1801 case Intrinsic::aarch64_sve_smin:
1803 case Intrinsic::aarch64_sve_smulh:
1805 case Intrinsic::aarch64_sve_sub:
1808 case Intrinsic::aarch64_sve_uabd:
1810 case Intrinsic::aarch64_sve_udiv:
1813 case Intrinsic::aarch64_sve_umax:
1815 case Intrinsic::aarch64_sve_umin:
1817 case Intrinsic::aarch64_sve_umulh:
1819 case Intrinsic::aarch64_sve_asr:
1822 case Intrinsic::aarch64_sve_lsl:
1825 case Intrinsic::aarch64_sve_lsr:
1828 case Intrinsic::aarch64_sve_and:
1831 case Intrinsic::aarch64_sve_bic:
1833 case Intrinsic::aarch64_sve_eor:
1836 case Intrinsic::aarch64_sve_orr:
1839 case Intrinsic::aarch64_sve_shsub:
1841 case Intrinsic::aarch64_sve_shsubr:
1843 case Intrinsic::aarch64_sve_sqrshl:
1845 case Intrinsic::aarch64_sve_sqshl:
1847 case Intrinsic::aarch64_sve_sqsub:
1849 case Intrinsic::aarch64_sve_srshl:
1851 case Intrinsic::aarch64_sve_uhsub:
1853 case Intrinsic::aarch64_sve_uhsubr:
1855 case Intrinsic::aarch64_sve_uqrshl:
1857 case Intrinsic::aarch64_sve_uqshl:
1859 case Intrinsic::aarch64_sve_uqsub:
1861 case Intrinsic::aarch64_sve_urshl:
1864 case Intrinsic::aarch64_sve_add_u:
1867 case Intrinsic::aarch64_sve_and_u:
1870 case Intrinsic::aarch64_sve_asr_u:
1873 case Intrinsic::aarch64_sve_eor_u:
1876 case Intrinsic::aarch64_sve_fadd_u:
1879 case Intrinsic::aarch64_sve_fdiv_u:
1882 case Intrinsic::aarch64_sve_fmul_u:
1885 case Intrinsic::aarch64_sve_fsub_u:
1888 case Intrinsic::aarch64_sve_lsl_u:
1891 case Intrinsic::aarch64_sve_lsr_u:
1894 case Intrinsic::aarch64_sve_mul_u:
1897 case Intrinsic::aarch64_sve_orr_u:
1900 case Intrinsic::aarch64_sve_sdiv_u:
1903 case Intrinsic::aarch64_sve_sub_u:
1906 case Intrinsic::aarch64_sve_udiv_u:
1910 case Intrinsic::aarch64_sve_addqv:
1911 case Intrinsic::aarch64_sve_bic_z:
1912 case Intrinsic::aarch64_sve_brka_z:
1913 case Intrinsic::aarch64_sve_brkb_z:
1914 case Intrinsic::aarch64_sve_brkn_z:
1915 case Intrinsic::aarch64_sve_brkpa_z:
1916 case Intrinsic::aarch64_sve_brkpb_z:
1917 case Intrinsic::aarch64_sve_cntp:
1918 case Intrinsic::aarch64_sve_compact:
1919 case Intrinsic::aarch64_sve_eorv:
1920 case Intrinsic::aarch64_sve_eorqv:
1921 case Intrinsic::aarch64_sve_nand_z:
1922 case Intrinsic::aarch64_sve_nor_z:
1923 case Intrinsic::aarch64_sve_orn_z:
1924 case Intrinsic::aarch64_sve_orv:
1925 case Intrinsic::aarch64_sve_orqv:
1926 case Intrinsic::aarch64_sve_pnext:
1927 case Intrinsic::aarch64_sve_rdffr_z:
1928 case Intrinsic::aarch64_sve_saddv:
1929 case Intrinsic::aarch64_sve_uaddv:
1930 case Intrinsic::aarch64_sve_umaxv:
1931 case Intrinsic::aarch64_sve_umaxqv:
1932 case Intrinsic::aarch64_sve_facge:
1933 case Intrinsic::aarch64_sve_facgt:
1934 case Intrinsic::aarch64_sve_ld1:
1935 case Intrinsic::aarch64_sve_ld1_gather:
1936 case Intrinsic::aarch64_sve_ld1_gather_index:
1937 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1938 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1939 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1940 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1941 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1942 case Intrinsic::aarch64_sve_ld1q_gather_index:
1943 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1944 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1945 case Intrinsic::aarch64_sve_ld1ro:
1946 case Intrinsic::aarch64_sve_ld1rq:
1947 case Intrinsic::aarch64_sve_ld1udq:
1948 case Intrinsic::aarch64_sve_ld1uwq:
1949 case Intrinsic::aarch64_sve_ld2_sret:
1950 case Intrinsic::aarch64_sve_ld2q_sret:
1951 case Intrinsic::aarch64_sve_ld3_sret:
1952 case Intrinsic::aarch64_sve_ld3q_sret:
1953 case Intrinsic::aarch64_sve_ld4_sret:
1954 case Intrinsic::aarch64_sve_ld4q_sret:
1955 case Intrinsic::aarch64_sve_ldff1:
1956 case Intrinsic::aarch64_sve_ldff1_gather:
1957 case Intrinsic::aarch64_sve_ldff1_gather_index:
1958 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1959 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1960 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1961 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1962 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1963 case Intrinsic::aarch64_sve_ldnf1:
1964 case Intrinsic::aarch64_sve_ldnt1:
1965 case Intrinsic::aarch64_sve_ldnt1_gather:
1966 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1967 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1968 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1971 case Intrinsic::aarch64_sve_and_z:
1974 case Intrinsic::aarch64_sve_orr_z:
1977 case Intrinsic::aarch64_sve_eor_z:
1981 case Intrinsic::aarch64_sve_cmpeq:
1982 case Intrinsic::aarch64_sve_cmpeq_wide:
1985 case Intrinsic::aarch64_sve_cmpge:
1986 case Intrinsic::aarch64_sve_cmpge_wide:
1989 case Intrinsic::aarch64_sve_cmpgt:
1990 case Intrinsic::aarch64_sve_cmpgt_wide:
1993 case Intrinsic::aarch64_sve_cmphi:
1994 case Intrinsic::aarch64_sve_cmphi_wide:
1997 case Intrinsic::aarch64_sve_cmphs:
1998 case Intrinsic::aarch64_sve_cmphs_wide:
2001 case Intrinsic::aarch64_sve_cmple_wide:
2004 case Intrinsic::aarch64_sve_cmplo_wide:
2007 case Intrinsic::aarch64_sve_cmpls_wide:
2010 case Intrinsic::aarch64_sve_cmplt_wide:
2013 case Intrinsic::aarch64_sve_cmpne:
2014 case Intrinsic::aarch64_sve_cmpne_wide:
2017 case Intrinsic::aarch64_sve_fcmpeq:
2020 case Intrinsic::aarch64_sve_fcmpge:
2023 case Intrinsic::aarch64_sve_fcmpgt:
2026 case Intrinsic::aarch64_sve_fcmpne:
2029 case Intrinsic::aarch64_sve_fcmpuo:
2033 case Intrinsic::aarch64_sve_prf:
2034 case Intrinsic::aarch64_sve_prfb_gather_index:
2035 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
2036 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
2037 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
2038 case Intrinsic::aarch64_sve_prfd_gather_index:
2039 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
2040 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
2041 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
2042 case Intrinsic::aarch64_sve_prfh_gather_index:
2043 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
2044 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
2045 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
2046 case Intrinsic::aarch64_sve_prfw_gather_index:
2047 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
2048 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
2049 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
2052 case Intrinsic::aarch64_sve_st1_scatter:
2053 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
2054 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
2055 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
2056 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
2057 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
2058 case Intrinsic::aarch64_sve_st1dq:
2059 case Intrinsic::aarch64_sve_st1q_scatter_index:
2060 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
2061 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
2062 case Intrinsic::aarch64_sve_st1wq:
2063 case Intrinsic::aarch64_sve_stnt1:
2064 case Intrinsic::aarch64_sve_stnt1_scatter:
2065 case Intrinsic::aarch64_sve_stnt1_scatter_index:
2066 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
2067 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
2069 case Intrinsic::aarch64_sve_st2:
2070 case Intrinsic::aarch64_sve_st2q:
2072 case Intrinsic::aarch64_sve_st3:
2073 case Intrinsic::aarch64_sve_st3q:
2075 case Intrinsic::aarch64_sve_st4:
2076 case Intrinsic::aarch64_sve_st4q:
2084 Value *UncastedPred;
2090 Pred = UncastedPred;
2096 if (OrigPredTy->getMinNumElements() <=
2098 ->getMinNumElements())
2099 Pred = UncastedPred;
2103 return C &&
C->isAllOnesValue();
2110 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
2111 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2119static std::optional<Instruction *>
2126 Value *Op1 =
II.getOperand(1);
2127 Value *Op2 =
II.getOperand(2);
2152 Value *NarrowOp1, *NarrowOp2;
2163 else if (SimpleNarrow == NarrowOp1)
2165 else if (SimpleNarrow == NarrowOp2)
2170 SimpleNarrow->
getType(), SimpleNarrow);
2179 return std::nullopt;
2190 if (SimpleII == Inactive)
2198static std::optional<Instruction *>
2202 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2203 "Expected a compare operation!");
2210 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2211 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2212 "Unexpected wide compare!");
2228 const APInt *LHSVal, *RHSVal;
2230 return std::nullopt;
2253 return std::nullopt;
2267static std::optional<Instruction *>
2271 return std::nullopt;
2300 II.setCalledFunction(NewDecl);
2306 return std::nullopt;
2317 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2320 return std::nullopt;
2332static std::optional<Instruction *>
2334 auto m_ConvertToSVBool = [](
auto P) {
2338 Intrinsic::aarch64_sve_convert_from_svbool;
2361 return std::nullopt;
2365 case Intrinsic::aarch64_sve_and_z:
2366 case Intrinsic::aarch64_sve_bic_z:
2367 case Intrinsic::aarch64_sve_eor_z:
2368 case Intrinsic::aarch64_sve_nand_z:
2369 case Intrinsic::aarch64_sve_nor_z:
2370 case Intrinsic::aarch64_sve_orn_z:
2371 case Intrinsic::aarch64_sve_orr_z:
2374 return std::nullopt;
2377 Value *BinOpPred = BinOp->getOperand(0);
2378 Value *BinOpOp1 = BinOp->getOperand(1);
2379 Value *BinOpOp2 = BinOp->getOperand(2);
2381 Value *NarrowBinOpPred;
2383 return std::nullopt;
2385 Value *NarrowBinOpOp1 =
2387 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2388 if (BinOpOp1 != BinOpOp2)
2392 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2396static std::optional<Instruction *>
2403 return BinOpCombine;
2408 return std::nullopt;
2411 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2420 if (CursorVTy->getElementCount().getKnownMinValue() <
2421 IVTy->getElementCount().getKnownMinValue())
2425 if (Cursor->getType() == IVTy)
2426 EarliestReplacement = Cursor;
2431 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2432 Intrinsic::aarch64_sve_convert_to_svbool ||
2433 IntrinsicCursor->getIntrinsicID() ==
2434 Intrinsic::aarch64_sve_convert_from_svbool))
2437 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2438 Cursor = IntrinsicCursor->getOperand(0);
2443 if (!EarliestReplacement)
2444 return std::nullopt;
2452 auto *OpPredicate =
II.getOperand(0);
2469 II.getArgOperand(2));
2475 return std::nullopt;
2479 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2488 II.getArgOperand(0));
2497 if (!
II.hasOneUse())
2498 return std::nullopt;
2501 return std::nullopt;
2504 switch (
II.getIntrinsicID()) {
2505 case Intrinsic::aarch64_sve_cmpne:
2506 IID = Intrinsic::aarch64_sve_cmpeq;
2508 case Intrinsic::aarch64_sve_cmpne_wide:
2509 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2511 case Intrinsic::aarch64_sve_cmpeq:
2512 IID = Intrinsic::aarch64_sve_cmpne;
2514 case Intrinsic::aarch64_sve_cmpeq_wide:
2515 IID = Intrinsic::aarch64_sve_cmpne_wide;
2518 return std::nullopt;
2523 IID,
II.getOperand(1)->getType(),
2524 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2536 return std::nullopt;
2538 for (
auto *U :
II.users()) {
2541 Type *Ty =
II.getOperand(1)->getType();
2546 Intrinsic::aarch64_sve_umin, Ty,
2547 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2553 return std::nullopt;
2567 return std::nullopt;
2572 if (!SplatValue || !SplatValue->isZero())
2573 return std::nullopt;
2578 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2579 return std::nullopt;
2583 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2584 return std::nullopt;
2587 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2588 return std::nullopt;
2593 return std::nullopt;
2596 return std::nullopt;
2600 return std::nullopt;
2604 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2605 return std::nullopt;
2607 unsigned NumElts = VecTy->getNumElements();
2608 unsigned PredicateBits = 0;
2611 for (
unsigned I = 0;
I < NumElts; ++
I) {
2614 return std::nullopt;
2616 PredicateBits |= 1 << (
I * (16 / NumElts));
2620 if (PredicateBits == 0) {
2622 PFalse->takeName(&
II);
2628 for (
unsigned I = 0;
I < 16; ++
I)
2629 if ((PredicateBits & (1 <<
I)) != 0)
2632 unsigned PredSize = Mask & -Mask;
2637 for (
unsigned I = 0;
I < 16;
I += PredSize)
2638 if ((PredicateBits & (1 <<
I)) == 0)
2639 return std::nullopt;
2641 auto *ConvertToSVBool =
2644 auto *ConvertFromSVBool =
2646 II.getType(), ConvertToSVBool);
2654 Value *Pg =
II.getArgOperand(0);
2655 Value *Vec =
II.getArgOperand(1);
2656 auto IntrinsicID =
II.getIntrinsicID();
2657 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2669 auto OpC = OldBinOp->getOpcode();
2675 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2681 if (IsAfter &&
C &&
C->isNullValue()) {
2685 Extract->insertBefore(
II.getIterator());
2686 Extract->takeName(&
II);
2692 return std::nullopt;
2694 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2695 return std::nullopt;
2697 const auto PTruePattern =
2703 return std::nullopt;
2705 unsigned Idx = MinNumElts - 1;
2715 if (Idx >= PgVTy->getMinNumElements())
2716 return std::nullopt;
2721 Extract->insertBefore(
II.getIterator());
2722 Extract->takeName(&
II);
2735 Value *Pg =
II.getArgOperand(0);
2737 Value *Vec =
II.getArgOperand(2);
2740 if (!Ty->isIntegerTy())
2741 return std::nullopt;
2746 return std::nullopt;
2763 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2778static std::optional<Instruction *>
2782 if (
Pattern == AArch64SVEPredPattern::all) {
2791 return MinNumElts && NumElts >= MinNumElts
2793 II, ConstantInt::get(
II.getType(), MinNumElts)))
2797static std::optional<Instruction *>
2800 if (!ST->isStreaming())
2801 return std::nullopt;
2813 Value *PgVal =
II.getArgOperand(0);
2814 Value *OpVal =
II.getArgOperand(1);
2818 if (PgVal == OpVal &&
2819 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2820 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2835 return std::nullopt;
2839 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2840 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2854 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2855 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2856 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2857 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2858 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2859 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2860 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2861 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2862 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2863 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2864 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2865 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2866 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2876 return std::nullopt;
2879template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2880static std::optional<Instruction *>
2882 bool MergeIntoAddendOp) {
2884 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2885 if (MergeIntoAddendOp) {
2886 AddendOp =
II.getOperand(1);
2887 Mul =
II.getOperand(2);
2889 AddendOp =
II.getOperand(2);
2890 Mul =
II.getOperand(1);
2895 return std::nullopt;
2897 if (!
Mul->hasOneUse())
2898 return std::nullopt;
2901 if (
II.getType()->isFPOrFPVectorTy()) {
2906 return std::nullopt;
2908 return std::nullopt;
2913 if (MergeIntoAddendOp)
2923static std::optional<Instruction *>
2925 Value *Pred =
II.getOperand(0);
2926 Value *PtrOp =
II.getOperand(1);
2927 Type *VecTy =
II.getType();
2942static std::optional<Instruction *>
2944 Value *VecOp =
II.getOperand(0);
2945 Value *Pred =
II.getOperand(1);
2946 Value *PtrOp =
II.getOperand(2);
2962 case Intrinsic::aarch64_sve_fmul_u:
2963 return Instruction::BinaryOps::FMul;
2964 case Intrinsic::aarch64_sve_fadd_u:
2965 return Instruction::BinaryOps::FAdd;
2966 case Intrinsic::aarch64_sve_fsub_u:
2967 return Instruction::BinaryOps::FSub;
2969 return Instruction::BinaryOpsEnd;
2973static std::optional<Instruction *>
2976 if (
II.isStrictFP())
2977 return std::nullopt;
2979 auto *OpPredicate =
II.getOperand(0);
2981 if (BinOpCode == Instruction::BinaryOpsEnd ||
2983 return std::nullopt;
2985 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
2989static std::optional<Instruction *>
2991 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
2992 "Expected MLA_U intrinsic");
2993 Value *Acc =
II.getArgOperand(1);
2994 Value *MulOp0 =
II.getArgOperand(2);
2995 Value *MulOp1 =
II.getArgOperand(3);
3010 II.setArgOperand(2, MulOp1);
3011 II.setArgOperand(3, MulOp0);
3015 return std::nullopt;
3018static std::optional<Instruction *>
3020 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
3021 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
3022 "Expected SADALP or UADALP intrinsic");
3028 return std::nullopt;
3032 return std::nullopt;
3036 II.getIntrinsicID(), {II.getType()},
3037 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
3047 Intrinsic::aarch64_sve_mla>(
3051 Intrinsic::aarch64_sve_mad>(
3054 return std::nullopt;
3057static std::optional<Instruction *>
3061 Intrinsic::aarch64_sve_fmla>(IC,
II,
3066 Intrinsic::aarch64_sve_fmad>(IC,
II,
3071 Intrinsic::aarch64_sve_fmla>(IC,
II,
3074 return std::nullopt;
3077static std::optional<Instruction *>
3081 Intrinsic::aarch64_sve_fmla>(IC,
II,
3086 Intrinsic::aarch64_sve_fmad>(IC,
II,
3091 Intrinsic::aarch64_sve_fmla_u>(
3097static std::optional<Instruction *>
3101 Intrinsic::aarch64_sve_fmls>(IC,
II,
3106 Intrinsic::aarch64_sve_fnmsb>(
3111 Intrinsic::aarch64_sve_fmls>(IC,
II,
3114 return std::nullopt;
3117static std::optional<Instruction *>
3121 Intrinsic::aarch64_sve_fmls>(IC,
II,
3126 Intrinsic::aarch64_sve_fnmsb>(
3131 Intrinsic::aarch64_sve_fmls_u>(
3140 Intrinsic::aarch64_sve_mls>(
3143 return std::nullopt;
3148 Value *UnpackArg =
II.getArgOperand(0);
3150 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3151 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3164 return std::nullopt;
3168 auto *OpVal =
II.getOperand(0);
3169 auto *OpIndices =
II.getOperand(1);
3176 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3177 return std::nullopt;
3192 Type *RetTy =
II.getType();
3193 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3194 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3198 if ((
match(
II.getArgOperand(0),
3205 if (TyA ==
B->getType() &&
3210 TyA->getMinNumElements());
3216 return std::nullopt;
3224 if (
match(
II.getArgOperand(0),
3229 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3231 return std::nullopt;
3234static std::optional<Instruction *>
3236 Value *Mask =
II.getOperand(0);
3237 Value *BasePtr =
II.getOperand(1);
3238 Value *Index =
II.getOperand(2);
3249 BasePtr->getPointerAlignment(
II.getDataLayout());
3252 BasePtr, IndexBase);
3259 return std::nullopt;
3262static std::optional<Instruction *>
3264 Value *Val =
II.getOperand(0);
3265 Value *Mask =
II.getOperand(1);
3266 Value *BasePtr =
II.getOperand(2);
3267 Value *Index =
II.getOperand(3);
3277 BasePtr->getPointerAlignment(
II.getDataLayout());
3280 BasePtr, IndexBase);
3286 return std::nullopt;
3292 Value *Pred =
II.getOperand(0);
3293 Value *Vec =
II.getOperand(1);
3294 Value *DivVec =
II.getOperand(2);
3298 if (!SplatConstantInt)
3299 return std::nullopt;
3303 if (DivisorValue == -1)
3304 return std::nullopt;
3305 if (DivisorValue == 1)
3311 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3318 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3320 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3324 return std::nullopt;
3347 if (
I->getParent() != MainAnd->
getParent() ||
3355 size_t VecSize = Vec.
size();
3360 size_t HalfVecSize = VecSize / 2;
3364 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3372 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3390 return std::nullopt;
3397 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3398 CurrentInsertElt = InsertElt->getOperand(0);
3404 return std::nullopt;
3408 for (
size_t I = 0;
I < Elts.
size();
I++) {
3409 if (Elts[
I] ==
nullptr)
3414 if (InsertEltChain ==
nullptr)
3415 return std::nullopt;
3421 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3422 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3423 IIScalableTy->getMinNumElements() /
3428 auto *WideShuffleMaskTy =
3439 auto NarrowBitcast =
3452 return std::nullopt;
3457 Value *Pred =
II.getOperand(0);
3458 Value *Vec =
II.getOperand(1);
3459 Value *Shift =
II.getOperand(2);
3462 Value *AbsPred, *MergedValue;
3468 return std::nullopt;
3476 return std::nullopt;
3481 return std::nullopt;
3484 {
II.getType()}, {Pred, Vec, Shift});
3491 Value *Vec =
II.getOperand(0);
3496 return std::nullopt;
3499static std::optional<Instruction *>
3501 unsigned LookaheadThreshold) {
3503 auto *NI =
II.getNextNode();
3505 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3507 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3508 auto *NIBB = NI->getParent();
3509 NI = NI->getNextNode();
3511 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3512 NI = &*SuccBB->getFirstNonPHIOrLifetime();
3518 if (NextII &&
II.isIdenticalTo(NextII))
3521 return std::nullopt;
3529 {II.getType(), II.getOperand(0)->getType()},
3530 {II.getOperand(0), II.getOperand(1)}));
3537 if (PredPattern == AArch64SVEPredPattern::all ||
3538 PredPattern == AArch64SVEPredPattern::pow2)
3540 return std::nullopt;
3546 Value *Passthru =
II.getOperand(0);
3554 auto *Mask = ConstantInt::get(Ty, MaskValue);
3560 return std::nullopt;
3563static std::optional<Instruction *>
3570 return std::nullopt;
3576 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3586 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3596 return std::nullopt;
3602 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3610 return std::nullopt;
3613 II.getType(), {Pg, A, B});
3615 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3624 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3629 Value *
A, *PgLHS, *PgRHS;
3635 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3636 return std::nullopt;
3639 if (ConstB > ConstA)
3645 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3646 return std::nullopt;
3648 Type *VecTy =
A->getType();
3652 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3659std::optional<Instruction *>
3670 case Intrinsic::aarch64_dmb:
3672 case Intrinsic::aarch64_neon_fmaxnm:
3673 case Intrinsic::aarch64_neon_fminnm:
3675 case Intrinsic::aarch64_sve_convert_from_svbool:
3677 case Intrinsic::aarch64_sve_dup:
3679 case Intrinsic::aarch64_sve_dup_x:
3681 case Intrinsic::aarch64_sve_cmpeq:
3682 case Intrinsic::aarch64_sve_cmpeq_wide:
3684 case Intrinsic::aarch64_sve_cmpne:
3685 case Intrinsic::aarch64_sve_cmpne_wide:
3687 case Intrinsic::aarch64_sve_rdffr:
3689 case Intrinsic::aarch64_sve_lasta:
3690 case Intrinsic::aarch64_sve_lastb:
3692 case Intrinsic::aarch64_sve_clasta_n:
3693 case Intrinsic::aarch64_sve_clastb_n:
3695 case Intrinsic::aarch64_sve_cntd:
3697 case Intrinsic::aarch64_sve_cntw:
3699 case Intrinsic::aarch64_sve_cnth:
3701 case Intrinsic::aarch64_sve_cntb:
3703 case Intrinsic::aarch64_sme_cntsd:
3705 case Intrinsic::aarch64_sve_ptest_any:
3706 case Intrinsic::aarch64_sve_ptest_first:
3707 case Intrinsic::aarch64_sve_ptest_last:
3709 case Intrinsic::aarch64_sve_fadd:
3711 case Intrinsic::aarch64_sve_fadd_u:
3713 case Intrinsic::aarch64_sve_fmul_u:
3715 case Intrinsic::aarch64_sve_fsub:
3717 case Intrinsic::aarch64_sve_fsub_u:
3719 case Intrinsic::aarch64_sve_add:
3721 case Intrinsic::aarch64_sve_add_u:
3723 Intrinsic::aarch64_sve_mla_u>(
3725 case Intrinsic::aarch64_sve_mla_u:
3727 case Intrinsic::aarch64_sve_sadalp:
3728 case Intrinsic::aarch64_sve_uadalp:
3730 case Intrinsic::aarch64_sve_sub:
3732 case Intrinsic::aarch64_sve_sub_u:
3734 Intrinsic::aarch64_sve_mls_u>(
3736 case Intrinsic::aarch64_sve_tbl:
3738 case Intrinsic::aarch64_sve_uunpkhi:
3739 case Intrinsic::aarch64_sve_uunpklo:
3740 case Intrinsic::aarch64_sve_sunpkhi:
3741 case Intrinsic::aarch64_sve_sunpklo:
3743 case Intrinsic::aarch64_sve_uzp1:
3745 case Intrinsic::aarch64_sve_zip1:
3746 case Intrinsic::aarch64_sve_zip2:
3748 case Intrinsic::aarch64_sve_ld1_gather_index:
3750 case Intrinsic::aarch64_sve_st1_scatter_index:
3752 case Intrinsic::aarch64_sve_ld1:
3754 case Intrinsic::aarch64_sve_st1:
3756 case Intrinsic::aarch64_sve_sdiv:
3758 case Intrinsic::aarch64_sve_sel:
3760 case Intrinsic::aarch64_sve_srshl:
3762 case Intrinsic::aarch64_sve_dupq_lane:
3764 case Intrinsic::aarch64_sve_insr:
3766 case Intrinsic::aarch64_sve_whilelo:
3768 case Intrinsic::aarch64_sve_ptrue:
3770 case Intrinsic::aarch64_sve_uxtb:
3772 case Intrinsic::aarch64_sve_uxth:
3774 case Intrinsic::aarch64_sve_uxtw:
3776 case Intrinsic::aarch64_sme_in_streaming_mode:
3778 case Intrinsic::aarch64_sve_umin_u:
3780 case Intrinsic::aarch64_sve_orr_u:
3782 case Intrinsic::aarch64_sve_and_z:
3786 return std::nullopt;
3793 SimplifyAndSetOp)
const {
3794 switch (
II.getIntrinsicID()) {
3797 case Intrinsic::aarch64_neon_fcvtxn:
3798 case Intrinsic::aarch64_neon_rshrn:
3799 case Intrinsic::aarch64_neon_sqrshrn:
3800 case Intrinsic::aarch64_neon_sqrshrun:
3801 case Intrinsic::aarch64_neon_sqshrn:
3802 case Intrinsic::aarch64_neon_sqshrun:
3803 case Intrinsic::aarch64_neon_sqxtn:
3804 case Intrinsic::aarch64_neon_sqxtun:
3805 case Intrinsic::aarch64_neon_uqrshrn:
3806 case Intrinsic::aarch64_neon_uqshrn:
3807 case Intrinsic::aarch64_neon_uqxtn:
3808 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3812 return std::nullopt;
3816 return ST->isSVEAvailable() ||
3817 (ST->isSVEorStreamingSVEAvailable() &&
3818 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3827 if (ST->useSVEForFixedLengthVectors() &&
3828 (ST->isSVEAvailable() ||
3829 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3831 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3832 else if (ST->isNeonAvailable())
3837 if (ST->isSVEAvailable() ||
3838 (ST->isSVEorStreamingSVEAvailable() &&
3839 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3847bool AArch64TTIImpl::isSingleExtWideningInstruction(
3849 Type *SrcOverrideTy)
const {
3864 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3867 Type *SrcTy = SrcOverrideTy;
3869 case Instruction::Add:
3870 case Instruction::Sub: {
3879 if (Opcode == Instruction::Sub)
3903 assert(SrcTy &&
"Expected some SrcTy");
3905 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3911 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3913 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3917 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3920Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3922 Type *SrcOverrideTy)
const {
3923 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3924 Opcode != Instruction::Mul)
3934 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3937 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3943 ->getScalarSizeInBits();
3946 unsigned MaxEltSize = 0;
3949 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3950 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3951 MaxEltSize = std::max(EltSize0, EltSize1);
3954 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3955 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3958 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3960 MaxEltSize = DstEltSize / 2;
3961 }
else if (Opcode == Instruction::Mul &&
3969 Known.Zero.countLeadingOnes() >
3974 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3978 if (MaxEltSize * 2 > DstEltSize)
3996 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
3997 (Src->isScalableTy() && !ST->hasSVE2()))
4007 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4011 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4015 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4016 Src->getScalarSizeInBits() !=
4040 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4054 if (
I && !
I->users().empty()) {
4058 auto GetUserAbsorbedCastCost =
4059 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4062 if (
Type *ExtTy = isBinExtWideningInstruction(
4064 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4077 if (isSingleExtWideningInstruction(
4079 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4083 if (Usr->getOpcode() == Instruction::Add) {
4084 if (
I == Usr->getOperand(1) ||
4096 return std::nullopt;
4105 unsigned SrcBits = Src->getScalarSizeInBits();
4108 Dst->getScalarSizeInBits() == 2 * SrcBits &&
4112 return std::nullopt;
4116 bool AllUsersAbsorbCast =
true;
4117 for (
const User *U :
I->users()) {
4119 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4121 AllUsersAbsorbCast =
false;
4124 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4127 if (AllUsersAbsorbCast)
4128 return MaxAbsorbedCost;
4138 Cmp->getParent() ==
I->getParent() &&
4143 EVT SrcTy = TLI->getValueType(
DL, Src);
4144 EVT DstTy = TLI->getValueType(
DL, Dst);
4148 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4158 bool SrcIsFloatOrVec =
4159 SrcLT.second.isVector() || SrcLT.second.isFloatingPoint();
4160 bool DstIsFloatOrVec =
4161 DstLT.second.isVector() || DstLT.second.isFloatingPoint();
4166 if (SrcIsFloatOrVec == DstIsFloatOrVec &&
4167 (SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits() ||
4168 (SrcLT.second.isScalableVector() &&
4169 SrcLT.second.getScalarSizeInBits() != 1 &&
4170 DstLT.second.getScalarSizeInBits() != 1)))
4173 return std::max(SrcLT.first, DstLT.first) *
4176 : ST->getVectorInsertExtractBaseCost());
4185 Instruction::ExtractElement, Src,
CostKind, -1,
nullptr,
nullptr);
4187 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH,
CostKind);
4191 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4196 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4225 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4228 ST->useSVEForFixedLengthVectors(WiderTy)) {
4229 std::pair<InstructionCost, MVT> LT =
4231 unsigned NumElements =
4247 const unsigned int SVE_EXT_COST = 1;
4248 const unsigned int SVE_FCVT_COST = 1;
4249 const unsigned int SVE_UNPACK_ONCE = 4;
4250 const unsigned int SVE_UNPACK_TWICE = 16;
4379 SVE_EXT_COST + SVE_FCVT_COST},
4384 SVE_EXT_COST + SVE_FCVT_COST},
4391 SVE_EXT_COST + SVE_FCVT_COST},
4395 SVE_EXT_COST + SVE_FCVT_COST},
4401 SVE_EXT_COST + SVE_FCVT_COST},
4404 SVE_EXT_COST + SVE_FCVT_COST},
4409 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4411 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4421 SVE_EXT_COST + SVE_FCVT_COST},
4426 SVE_EXT_COST + SVE_FCVT_COST},
4439 SVE_EXT_COST + SVE_FCVT_COST},
4443 SVE_EXT_COST + SVE_FCVT_COST},
4455 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4457 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4459 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4461 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4465 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4467 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4483 SVE_EXT_COST + SVE_FCVT_COST},
4488 SVE_EXT_COST + SVE_FCVT_COST},
4499 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4501 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4503 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4505 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4507 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4509 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4513 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4515 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4517 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4519 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4734 if (ST->hasFullFP16())
4746 Src->getScalarType(), CCH,
CostKind) +
4754 ST->isSVEorStreamingSVEAvailable() &&
4755 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4757 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4766 Opcode, LegalTy, Src, CCH,
CostKind,
I);
4769 return Part1 + Part2;
4776 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4788 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4801 CostKind, Index,
nullptr,
nullptr);
4805 auto DstVT = TLI->getValueType(
DL, Dst);
4806 auto SrcVT = TLI->getValueType(
DL, Src);
4811 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4817 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4827 case Instruction::SExt:
4832 case Instruction::ZExt:
4833 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4846 return Opcode == Instruction::PHI ? 0 : 1;
4855 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4857 assert(Ty->isVectorTy() &&
"This must be a vector type");
4864 if (!LT.second.isVector())
4869 if (LT.second.isFixedLengthVector()) {
4870 unsigned Width = LT.second.getVectorNumElements();
4871 Index = Index % Width;
4878 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4890 if (Index * Ty->getScalarSizeInBits() < 128)
4892 if (Index * Ty->getScalarSizeInBits() < 512 &&
4893 Opcode == Instruction::ExtractElement)
4895 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4896 if (Opcode == Instruction::ExtractElement)
4898 if (Opcode == Instruction::InsertElement)
4907 if (VIC == TTI::VectorInstrContext::Load) {
4908 if (ST->hasFastLD1Single())
4912 : ST->getVectorInsertExtractBaseCost() + 1;
4920 : ST->getVectorInsertExtractBaseCost() + 1;
4944 auto ExtractCanFuseWithFmul = [&]() {
4951 auto IsAllowedScalarTy = [&](
const Type *
T) {
4952 return T->isFloatTy() ||
T->isDoubleTy() ||
4953 (
T->isHalfTy() && ST->hasFullFP16());
4957 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4960 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4961 !BO->getType()->isVectorTy();
4966 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4970 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
4979 DenseMap<User *, unsigned> UserToExtractIdx;
4980 for (
auto *U :
Scalar->users()) {
4981 if (!IsUserFMulScalarTy(U))
4985 UserToExtractIdx[
U];
4987 if (UserToExtractIdx.
empty())
4989 for (
auto &[S, U, L] : ScalarUserAndIdx) {
4990 for (
auto *U : S->users()) {
4991 if (UserToExtractIdx.
contains(U)) {
4993 auto *Op0 =
FMul->getOperand(0);
4994 auto *Op1 =
FMul->getOperand(1);
4995 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
4996 UserToExtractIdx[
U] =
L;
5002 for (
auto &[U, L] : UserToExtractIdx) {
5014 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
5015 if (!IsUserFMulScalarTy(U))
5020 const auto *BO = cast<BinaryOperator>(U);
5021 const auto *OtherEE = dyn_cast<ExtractElementInst>(
5022 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
5024 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
5027 return IsExtractLaneEquivalentToZero(
5028 cast<ConstantInt>(OtherEE->getIndexOperand())
5031 OtherEE->getType()->getScalarSizeInBits());
5039 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
5040 ExtractCanFuseWithFmul())
5045 :
ST->getVectorInsertExtractBaseCost();
5054 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5057 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr,
nullptr,
5063 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5065 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr, Scalar,
5066 ScalarUserAndIdx, VIC);
5073 return getVectorInstrCostHelper(
I.getOpcode(), Ty,
CostKind, Index, &
I,
5080 unsigned Index)
const {
5091 : ST->getVectorInsertExtractBaseCost() + 1;
5103 if (ST->hasFastLD1Single()) {
5104 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5105 (VIC == TTI::VectorInstrContext::Load && Insert))
5109 if (Ty->getElementType()->isFloatingPointTy())
5112 unsigned VecInstCost =
5114 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5121 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5122 return std::nullopt;
5123 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5124 return std::nullopt;
5126 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5127 return std::nullopt;
5134 Cost += InstCost(PromotedTy);
5149 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5160 if (Opcode == Instruction::And && CtxI->
hasOneUse() &&
5168 const auto *UI = cast<Instruction>(U);
5169 return is_contained({Instruction::And, Instruction::Or},
5178 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5184 return BaseT::getArithmeticInstrCost(Opcode, Ty,
CostKind, Op1Info,
5185 Op2Info, Args, CtxI);
5191 if (
auto PromotedCost = getFP16BF16PromoteCost(
5192 Ty,
CostKind, Op1Info, Op2Info,
true,
5195 [&](
Type *PromotedTy) {
5196 return getArithmeticInstrCost(Opcode, PromotedTy,
CostKind,
5199 return *PromotedCost;
5202 if (Ty->getScalarType()->isFP128Ty())
5210 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5212 return getArithmeticInstrCost(Opcode, ExtTy,
CostKind) +
5213 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
5220 return BaseT::getArithmeticInstrCost(Opcode, Ty,
CostKind, Op1Info,
5230 ST->hasLimited64bitVectorMulBandwidth())
5238 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5241 if (
LT.second == MVT::v2i64) {
5245 return LT.first * Mul64CostFactor;
5266 if (
LT.second == MVT::nxv2i64)
5267 return LT.first * Mul64CostFactor;
5316 getArithmeticInstrCost(Instruction::Add, Ty,
CostKind,
5319 getArithmeticInstrCost(Instruction::AShr, Ty,
CostKind,
5322 getArithmeticInstrCost(Instruction::Mul, Ty,
CostKind,
5326 auto VT = TLI->getValueType(
DL, Ty);
5327 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5331 : (3 * AsrCost + AddCost);
5333 return MulCost + AsrCost + 2 * AddCost;
5335 }
else if (VT.isVector()) {
5346 Cost += 2 * AsrCost;
5351 ? (
LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5355 }
else if (
LT.second == MVT::v2i64) {
5356 return VT.getVectorNumElements() *
5364 return MulCost + 2 * AddCost + 2 * AsrCost;
5365 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5370 LT.second.isFixedLengthVector()) {
5380 return ExtractCost + InsertCost +
5388 auto VT = TLI->getValueType(
DL, Ty);
5392 return getArithmeticInstrCost(Instruction::LShr, Ty,
CostKind,
5396 return getArithmeticInstrCost(Instruction::And, Ty,
CostKind,
5404 bool HasMULH = VT == MVT::i64 ||
LT.second == MVT::nxv2i64 ||
5405 LT.second == MVT::nxv4i32 ||
LT.second == MVT::nxv8i16 ||
5406 LT.second == MVT::nxv16i8;
5407 bool Is128bit =
LT.second.is128BitVector();
5410 getArithmeticInstrCost(Instruction::Mul, Ty,
CostKind,
5413 getArithmeticInstrCost(Instruction::Add, Ty,
CostKind,
5416 getArithmeticInstrCost(Instruction::AShr, Ty,
CostKind,
5419 (HasMULH ? 0 : ShrCost) +
5420 AddCost * 2 + ShrCost;
5421 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5428 if (!VT.isVector() && VT.getSizeInBits() > 64)
5429 return getCallInstrCost(
nullptr, Ty, {Ty, Ty},
CostKind);
5432 Opcode, Ty,
CostKind, Op1Info, Op2Info);
5434 if (TLI->isOperationLegalOrCustom(
ISD,
LT.second) &&
ST->hasSVE()) {
5448 if (
nullptr != Entry)
5456 FVTy &&
LT.second.isFixedLengthVector()) {
5457 unsigned NumElts = FVTy->getNumElements();
5458 unsigned RegElts =
LT.second.getVectorNumElements();
5460 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5464 if (
LT.second.getScalarType() == MVT::i8)
5466 else if (
LT.second.getScalarType() == MVT::i16)
5479 return (4 + DivCost) * VTy->getNumElements();
5485 -1,
nullptr,
nullptr);
5512 LT.second.isFixedLengthVector())
5513 return 2 *
LT.first + 1;
5525 ((CtxI->hasOneUse() &&
5540 return 2 *
LT.first;
5542 return BaseT::getArithmeticInstrCost(Opcode, Ty,
CostKind, Op1Info,
5548 return getCallInstrCost(
nullptr, Ty, {Ty, Ty},
CostKind);
5549 return BaseT::getArithmeticInstrCost(Opcode, Ty,
CostKind, Op1Info,
5562 unsigned NumVectorInstToHideOverhead =
5563 ST->getCLOpts().neon_nonconst_stride_overhead;
5564 int MaxMergeDistance = 64;
5568 return NumVectorInstToHideOverhead;
5580 unsigned Opcode1,
unsigned Opcode2)
const {
5583 if (!
Sched.hasInstrSchedModel())
5586 auto GetRThroughput = [&](
unsigned Opcode,
bool Highest) {
5587 std::optional<double> Res;
5589 while (!Worklist.
empty()) {
5593 append_range(Worklist, AArch64_MC::getVariantSchedClassTargets(
5594 SchedClass,
Sched.getProcessorID()));
5600 if (!Res || (Highest ? RThroughput > *Res : RThroughput < *Res))
5605 std::optional<double> RThroughput1 =
5606 GetRThroughput(Opcode1,
true);
5607 std::optional<double> RThroughput2 =
5608 GetRThroughput(Opcode2,
false);
5609 return RThroughput1 && RThroughput2 && *RThroughput1 > *RThroughput2;
5620 const int AmortizationCost = 20;
5628 VecPred = CurrentPred;
5636 static const auto ValidMinMaxTys = {
5637 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5638 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5639 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5643 (ST->hasFullFP16() &&
5649 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5650 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5651 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5652 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5653 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5654 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5655 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5656 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5657 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5658 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5659 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5661 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5662 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5671 if (Opcode == Instruction::FCmp) {
5673 ValTy,
CostKind, Op1Info, Op2Info,
false,
5675 false, [&](
Type *PromotedTy) {
5687 return *PromotedCost;
5691 if (LT.second.getScalarType() != MVT::f64 &&
5692 LT.second.getScalarType() != MVT::f32 &&
5693 LT.second.getScalarType() != MVT::f16)
5698 unsigned Factor = 1;
5699 if (!CondTy->isVectorTy() &&
5713 AArch64::FCMEQv4f32))
5725 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5744 Opcode, ValTy, CondTy, VecPred,
CostKind, Op1Info, Op2Info,
I);
5748 AArch64::CMEQv4i32))
5756 if (ST->requiresStrictAlign()) {
5761 Options.AllowOverlappingLoads =
true;
5762 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5767 Options.LoadSizes = {8, 4, 2, 1};
5768 Options.AllowedTailExpansions = {3, 5, 6};
5773 return ST->hasSVE();
5779 switch (MICA.
getID()) {
5780 case Intrinsic::masked_scatter:
5781 case Intrinsic::masked_gather:
5783 case Intrinsic::masked_load:
5784 case Intrinsic::masked_store:
5785 case Intrinsic::masked_expandload:
5786 case Intrinsic::masked_compressstore:
5800 if (!LT.first.isValid())
5805 if (VT->getElementType()->isIntegerTy(1))
5811 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5817 if (MICA.
getID() == Intrinsic::masked_expandload) {
5830 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5850 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5851 return MemOpCost * 2;
5860 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5861 "Should be called on only load or stores.");
5863 case Instruction::Load:
5864 return ST->getCLOpts().sve_gather_overhead.value_or(
5865 ST->getGatherOverhead());
5867 case Instruction::Store:
5868 return ST->getCLOpts().sve_scatter_overhead.value_or(
5869 ST->getScatterOverhead());
5880 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5881 MICA.
getID() == Intrinsic::vp_gather)
5883 : Instruction::Store;
5893 if (!LT.first.isValid())
5897 if (!LT.second.isVector() ||
5899 VT->getElementType()->isIntegerTy(1))
5909 ElementCount LegalVF = LT.second.getVectorElementCount();
5912 {TTI::OK_AnyValue, TTI::OP_None},
I);
5928 EVT VT = TLI->getValueType(
DL, Ty,
true);
5930 if (VT == MVT::Other)
5935 if (!LT.first.isValid())
5941 if (VTy->getElementType()->isIntegerTy(1) &&
5942 !VTy->getElementCount().isKnownMultipleOf(
5948 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5949 : Intrinsic::masked_store;
5963 if (Opcode == Instruction::Store)
5967 if (ST->getFixedLoadLatency())
5968 return (LT.first - 1) + ST->getFixedLoadLatency();
5977 if (LT.second.isScalableVector() ||
5978 ST->useSVEForFixedLengthVectors(LT.second)) {
5979 Inst = AArch64::LDR_ZXI;
5980 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5981 switch (LT.second.getSizeInBits()) {
5983 Inst = AArch64::LDRBui;
5986 Inst = AArch64::LDRHui;
5989 Inst = AArch64::LDRSui;
5992 Inst = AArch64::LDRDui;
5995 Inst = AArch64::LDRQui;
6001 switch (LT.second.getSizeInBits()) {
6003 Inst = AArch64::LDRBBui;
6006 Inst = AArch64::LDRHHui;
6009 Inst = AArch64::LDRWui;
6012 Inst = AArch64::LDRXui;
6020 unsigned SchedClass =
TII->get(Inst).getSchedClass();
6022 ?
Sched.getSchedClassDesc(SchedClass)
6028 return (LT.first - 1) + ST->getLoadLatency();
6031 float NumLoads = (LT.first - 1).
getValue();
6032 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
6033 Sched.computeInstrLatency(*ST, *SCD);
6036 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
6037 LT.second.is128BitVector() && Alignment <
Align(16)) {
6043 const int AmortizationCost = 6;
6045 return LT.first * 2 * AmortizationCost;
6049 if (Ty->isPtrOrPtrVectorTy())
6054 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
6056 if (VT == MVT::v4i8)
6063 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
6064 Alignment !=
Align(1))
6076 if (Remainder != 0) {
6079 while (!TypeWorklist.
empty()) {
6089 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6101 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6102 assert(Factor >= 2 &&
"Invalid interleave factor");
6111 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6115 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6120 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6125 (UseMaskForCond || UseMaskForGaps ||
6126 (Factor > MaxNativeInterleaveFactor &&
6127 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6130 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6133 EC.divideCoefficientBy(Factor));
6139 if (EC.isKnownMultipleOf(Factor) &&
6140 TLI->isLegalInterleavedAccessType(SubVecTy,
DL, UseScalable))
6141 return Factor * TLI->getNumInterleavedAccesses(SubVecTy,
DL, UseScalable);
6146 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6152 if (UseMaskForCond) {
6153 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6154 : Intrinsic::masked_store;
6174 if (Opcode == Instruction::Store && Factor == 4 &&
6175 SubVecCost.second.getScalarSizeInBits() ==
6176 (4 * ResultCost.second.getScalarSizeInBits()))
6177 LegalizationCost *= 4;
6179 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6185 UseMaskForCond, UseMaskForGaps);
6192 for (
auto *
I : Tys) {
6193 if (!
I->isVectorTy())
6204 Align Alignment)
const {
6211 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6212 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6224 Size.getFixedValue() <= 16;
6229 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6230 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6249 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6256 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6262 bool HasUnorderedReductions)
const {
6265 return ST->getMaxInterleaveFactor();
6275 enum { MaxStridedLoads = 7 };
6277 int StridedLoads = 0;
6280 for (
const auto BB : L->blocks()) {
6281 for (
auto &
I : *BB) {
6287 if (L->isLoopInvariant(PtrValue))
6292 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6301 if (StridedLoads > MaxStridedLoads / 2)
6302 return StridedLoads;
6305 return StridedLoads;
6308 int StridedLoads = countStridedLoads(L, SE);
6310 <<
" strided loads\n");
6326 unsigned *FinalSize) {
6330 for (
auto *BB : L->getBlocks()) {
6331 for (
auto &
I : *BB) {
6337 if (!Cost.isValid())
6341 if (LoopCost > Budget)
6363 if (MaxTC > 0 && MaxTC <= 32)
6374 if (Blocks.
size() != 2)
6396 if (!L->isInnermost() || L->getNumBlocks() > 8)
6400 if (!L->getExitBlock())
6406 bool HasParellelizableReductions =
6407 L->getNumBlocks() == 1 &&
6408 any_of(L->getHeader()->phis(),
6410 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6413 if (HasParellelizableReductions &&
6435 if (HasParellelizableReductions) {
6446 if (Header == Latch) {
6449 unsigned Width = 10;
6455 unsigned MaxInstsPerLine = 16;
6457 unsigned BestUC = 1;
6458 unsigned SizeWithBestUC = BestUC *
Size;
6460 unsigned SizeWithUC = UC *
Size;
6461 if (SizeWithUC > 48)
6463 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6464 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6466 SizeWithBestUC = BestUC *
Size;
6476 for (
auto *BB : L->blocks()) {
6477 for (
auto &
I : *BB) {
6487 for (
auto *U :
I.users())
6489 LoadedValuesPlus.
insert(U);
6496 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6522 auto *I = dyn_cast<Instruction>(V);
6523 return I && DependsOnLoopLoad(I, Depth + 1);
6530 DependsOnLoopLoad(
I, 0)) {
6562 if (L->getLoopDepth() > 1)
6573 for (
auto *BB : L->getBlocks()) {
6574 for (
auto &
I : *BB) {
6578 if (IsVectorized &&
I.getType()->isVectorTy())
6589 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6598 if (ST->isAppleMLike())
6600 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6601 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6622 !ST->getSchedModel().isOutOfOrder()) {
6634 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6645 bool CanCreate)
const {
6649 case Intrinsic::aarch64_neon_st1x2:
6650 case Intrinsic::aarch64_neon_st1x3:
6651 case Intrinsic::aarch64_neon_st1x4:
6652 case Intrinsic::aarch64_neon_st2:
6653 case Intrinsic::aarch64_neon_st3:
6654 case Intrinsic::aarch64_neon_st4: {
6657 if (!CanCreate || !ST)
6659 unsigned NumElts = Inst->
arg_size() - 1;
6660 if (ST->getNumElements() != NumElts)
6662 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6668 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6670 Res = Builder.CreateInsertValue(Res, L, i);
6674 case Intrinsic::aarch64_neon_ld1x2:
6675 case Intrinsic::aarch64_neon_ld1x3:
6676 case Intrinsic::aarch64_neon_ld1x4:
6677 case Intrinsic::aarch64_neon_ld2:
6678 case Intrinsic::aarch64_neon_ld3:
6679 case Intrinsic::aarch64_neon_ld4:
6680 if (Inst->
getType() == ExpectedType)
6691 case Intrinsic::aarch64_neon_ld1x2:
6692 case Intrinsic::aarch64_neon_ld1x3:
6693 case Intrinsic::aarch64_neon_ld1x4:
6694 case Intrinsic::aarch64_neon_ld2:
6695 case Intrinsic::aarch64_neon_ld3:
6696 case Intrinsic::aarch64_neon_ld4:
6697 Info.ReadMem =
true;
6698 Info.WriteMem =
false;
6701 case Intrinsic::aarch64_neon_st1x2:
6702 case Intrinsic::aarch64_neon_st1x3:
6703 case Intrinsic::aarch64_neon_st1x4:
6704 case Intrinsic::aarch64_neon_st2:
6705 case Intrinsic::aarch64_neon_st3:
6706 case Intrinsic::aarch64_neon_st4:
6707 Info.ReadMem =
false;
6708 Info.WriteMem =
true;
6717 case Intrinsic::aarch64_neon_ld1x2:
6718 case Intrinsic::aarch64_neon_st1x2:
6719 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6721 case Intrinsic::aarch64_neon_ld1x3:
6722 case Intrinsic::aarch64_neon_st1x3:
6723 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6725 case Intrinsic::aarch64_neon_ld1x4:
6726 case Intrinsic::aarch64_neon_st1x4:
6727 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6729 case Intrinsic::aarch64_neon_ld2:
6730 case Intrinsic::aarch64_neon_st2:
6731 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6733 case Intrinsic::aarch64_neon_ld3:
6734 case Intrinsic::aarch64_neon_st3:
6735 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6737 case Intrinsic::aarch64_neon_ld4:
6738 case Intrinsic::aarch64_neon_st4:
6739 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6751 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6752 bool Considerable =
false;
6753 AllowPromotionWithoutCommonHeader =
false;
6756 Type *ConsideredSExtType =
6758 if (
I.getType() != ConsideredSExtType)
6762 for (
const User *U :
I.users()) {
6764 Considerable =
true;
6768 if (GEPInst->getNumOperands() > 2) {
6769 AllowPromotionWithoutCommonHeader =
true;
6774 return Considerable;
6825 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6835 return LegalizationCost + 2;
6845 LegalizationCost *= LT.first - 1;
6848 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6857 return LegalizationCost + 2;
6865 std::optional<FastMathFlags> FMF,
6881 return BaseCost + FixedVTy->getNumElements();
6895 MVT MTy = LT.second;
6900 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6948 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6949 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6961 return (LT.first - 1) +
Log2_32(NElts);
6966 return (LT.first - 1) + Entry->Cost;
6978 if (LT.first != 1) {
6984 ExtraCost *= LT.first - 1;
6987 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
6988 return Cost + ExtraCost;
6996 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
6998 EVT VecVT = TLI->getValueType(
DL, VecTy);
6999 EVT ResVT = TLI->getValueType(
DL, ResTy);
7009 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7011 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
7013 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
7015 return (LT.first - 1) * 2 + 2;
7026 EVT VecVT = TLI->getValueType(
DL, VecTy);
7027 EVT ResVT = TLI->getValueType(
DL, ResTy);
7030 RedOpcode == Instruction::Add) {
7036 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7038 return LT.first + 2;
7073 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
7074 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7088 if (LT.second.getScalarType() == MVT::i1) {
7097 assert(Entry &&
"Illegal Type for Splice");
7098 LegalizationCost += Entry->Cost;
7099 return LegalizationCost * LT.first;
7103 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7112 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7113 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7119 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7120 if (!FMF->allowReassoc() || !FMF->allowContract())
7124 "FastMathFlags only apply to floating-point partial reductions");
7128 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7129 "Unexpected values for OpBExtend or InputTypeB");
7133 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7134 InputTypeA != InputTypeB))
7145 assert(!OpBExtend &&
"Extended second operand without extended first.");
7146 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7152 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7155 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7168 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7177 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7183 std::pair<InstructionCost, MVT> AccumLT =
7185 std::pair<InstructionCost, MVT> InputLT =
7189 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7190 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7191 (AccumLT.second.isFixedLengthVector() &&
7192 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7196 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7204 if (AccumLT.second.getScalarType() == MVT::i32 &&
7205 InputLT.second.getScalarType() == MVT::i8) {
7207 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7208 return Cost + INegCost;
7210 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7211 return Cost + INegCost;
7216 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7217 return Cost * 3 + INegCost;
7220 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7222 if (AccumLT.second.getScalarType() == MVT::i64 &&
7223 InputLT.second.getScalarType() == MVT::i16)
7224 return Cost + INegCost;
7227 if (AccumLT.second.getScalarType() == MVT::i32 &&
7228 InputLT.second.getScalarType() == MVT::i16 &&
7229 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7232 if (AccumLT.second.getScalarType() == MVT::i64 &&
7233 InputLT.second.getScalarType() == MVT::i8)
7236 return Cost + INegCost;
7239 if (AccumLT.second.getScalarType() == MVT::i16 &&
7240 InputLT.second.getScalarType() == MVT::i8 &&
7241 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7259 if ((!BinOp || IsSExtMul) && !IsSub &&
7260 AccumLT.second.getScalarType() == MVT::i64 &&
7261 InputLT.second.getScalarType() == MVT::i8 &&
7262 IsSupported(
false, ST->hasDotProd()))
7267 if (Opcode == Instruction::FAdd && !IsSub &&
7268 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7269 AccumLT.second.getScalarType() == MVT::f32 &&
7270 InputLT.second.getScalarType() == MVT::f16)
7274 if (Ratio == 2 && !IsUSDot) {
7275 MVT InVT = InputLT.second.getScalarType();
7279 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7281 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7284 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7288 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7289 InVT == MVT::bf16 && IsSub)
7299 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7300 return Cost * 2 + FNegCost;
7304 AccumType, VF, OpAExtend, OpBExtend,
7315 "Expected the Mask to match the return size if given");
7317 "Expected the same scalar types");
7323 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7324 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7325 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7333 return std::max<InstructionCost>(1, LT.first / 4);
7341 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7343 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7346 unsigned TpNumElts = Mask.size();
7347 unsigned LTNumElts = LT.second.getVectorNumElements();
7348 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7350 LT.second.getVectorElementCount());
7352 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7354 for (
unsigned N = 0;
N < NumVecs;
N++) {
7358 unsigned Source1 = -1U, Source2 = -1U;
7359 unsigned NumSources = 0;
7360 for (
unsigned E = 0; E < LTNumElts; E++) {
7361 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7370 unsigned Source = MaskElt / LTNumElts;
7371 if (NumSources == 0) {
7374 }
else if (NumSources == 1 && Source != Source1) {
7377 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7383 if (Source == Source1)
7385 else if (Source == Source2)
7386 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7395 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7406 NTp, NTp,
CostKind, NMask, 0,
nullptr, Args,
7409 Result.first->second = NCost;
7423 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7424 if (LT.second.getFixedSizeInBits() >= 128 &&
7426 LT.second.getVectorNumElements() / 2) {
7429 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7443 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7446 return M.value() < 0 || M.value() == (int)M.index();
7452 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7453 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7462 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7463 ST->isSVEorStreamingSVEAvailable() &&
7468 if (ST->isSVEorStreamingSVEAvailable() &&
7482 if (IsLoad && LT.second.isVector() &&
7484 LT.second.getVectorElementCount()))
7490 if (Mask.size() == 4 &&
7492 (SrcTy->getScalarSizeInBits() == 16 ||
7493 SrcTy->getScalarSizeInBits() == 32) &&
7494 all_of(Mask, [](
int E) {
return E < 8; }))
7500 if (LT.second.isFixedLengthVector() &&
7501 LT.second.getVectorNumElements() == Mask.size() &&
7507 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7508 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7509 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7510 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7511 LT.second.getVectorNumElements(), 16) ||
7512 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7513 LT.second.getVectorNumElements(), 32) ||
7514 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7515 LT.second.getVectorNumElements(), 64) ||
7518 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7647 return LT.first * Entry->Cost;
7656 LT.second.getSizeInBits() <= 128 && SubTp) {
7658 if (SubLT.second.isVector()) {
7659 int NumElts = LT.second.getVectorNumElements();
7660 int NumSubElts = SubLT.second.getVectorNumElements();
7661 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7667 if (IsExtractSubvector)
7688 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7699 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7700 ST->useFixedOverScalableIfEqualCost());
7704 return ST->getEpilogueVectorizationMinVF();
7739 unsigned NumInsns = 0;
7741 NumInsns += BB->size();
7745 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7751 int64_t Scale,
unsigned AddrSpace)
const {
7774 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7779 if (
I->getOpcode() == Instruction::Or &&
7783 if (
I->getOpcode() == Instruction::Add ||
7784 I->getOpcode() == Instruction::Sub)
7798 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7809 return all_equal(Shuf->getShuffleMask());
7816 bool AllowSplat =
false) {
7821 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7822 auto *FullTy = FullV->
getType();
7823 auto *HalfTy = HalfV->getType();
7825 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7828 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7831 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7835 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7849 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7850 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7864 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7865 (M2Start != 0 && M2Start != (NumElements / 2)))
7867 if (S1Op1 && S2Op1 && M1Start != M2Start)
7877 return Ext->getType()->getScalarSizeInBits() ==
7878 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7892 Value *VectorOperand =
nullptr;
7909 if (!
GEP ||
GEP->getNumOperands() != 2)
7913 Value *Offsets =
GEP->getOperand(1);
7916 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7922 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7923 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7924 Ops.push_back(&
GEP->getOperandUse(1));
7960 switch (
II->getIntrinsicID()) {
7961 case Intrinsic::aarch64_neon_smull:
7962 case Intrinsic::aarch64_neon_umull:
7965 Ops.push_back(&
II->getOperandUse(0));
7966 Ops.push_back(&
II->getOperandUse(1));
7971 case Intrinsic::fma:
7972 case Intrinsic::fmuladd:
7979 Ops.push_back(&
II->getOperandUse(0));
7981 Ops.push_back(&
II->getOperandUse(1));
7984 case Intrinsic::aarch64_neon_sqdmull:
7985 case Intrinsic::aarch64_neon_sqdmulh:
7986 case Intrinsic::aarch64_neon_sqrdmulh:
7989 Ops.push_back(&
II->getOperandUse(0));
7991 Ops.push_back(&
II->getOperandUse(1));
7992 return !
Ops.empty();
7993 case Intrinsic::aarch64_neon_fmlal:
7994 case Intrinsic::aarch64_neon_fmlal2:
7995 case Intrinsic::aarch64_neon_fmlsl:
7996 case Intrinsic::aarch64_neon_fmlsl2:
7999 Ops.push_back(&
II->getOperandUse(1));
8001 Ops.push_back(&
II->getOperandUse(2));
8002 return !
Ops.empty();
8003 case Intrinsic::aarch64_sve_ptest_first:
8004 case Intrinsic::aarch64_sve_ptest_last:
8006 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
8007 Ops.push_back(&
II->getOperandUse(0));
8008 return !
Ops.empty();
8009 case Intrinsic::aarch64_sme_write_horiz:
8010 case Intrinsic::aarch64_sme_write_vert:
8011 case Intrinsic::aarch64_sme_writeq_horiz:
8012 case Intrinsic::aarch64_sme_writeq_vert: {
8014 if (!Idx || Idx->getOpcode() != Instruction::Add)
8016 Ops.push_back(&
II->getOperandUse(1));
8019 case Intrinsic::aarch64_sme_read_horiz:
8020 case Intrinsic::aarch64_sme_read_vert:
8021 case Intrinsic::aarch64_sme_readq_horiz:
8022 case Intrinsic::aarch64_sme_readq_vert:
8023 case Intrinsic::aarch64_sme_ld1b_vert:
8024 case Intrinsic::aarch64_sme_ld1h_vert:
8025 case Intrinsic::aarch64_sme_ld1w_vert:
8026 case Intrinsic::aarch64_sme_ld1d_vert:
8027 case Intrinsic::aarch64_sme_ld1q_vert:
8028 case Intrinsic::aarch64_sme_st1b_vert:
8029 case Intrinsic::aarch64_sme_st1h_vert:
8030 case Intrinsic::aarch64_sme_st1w_vert:
8031 case Intrinsic::aarch64_sme_st1d_vert:
8032 case Intrinsic::aarch64_sme_st1q_vert:
8033 case Intrinsic::aarch64_sme_ld1b_horiz:
8034 case Intrinsic::aarch64_sme_ld1h_horiz:
8035 case Intrinsic::aarch64_sme_ld1w_horiz:
8036 case Intrinsic::aarch64_sme_ld1d_horiz:
8037 case Intrinsic::aarch64_sme_ld1q_horiz:
8038 case Intrinsic::aarch64_sme_st1b_horiz:
8039 case Intrinsic::aarch64_sme_st1h_horiz:
8040 case Intrinsic::aarch64_sme_st1w_horiz:
8041 case Intrinsic::aarch64_sme_st1d_horiz:
8042 case Intrinsic::aarch64_sme_st1q_horiz: {
8044 if (!Idx || Idx->getOpcode() != Instruction::Add)
8046 Ops.push_back(&
II->getOperandUse(3));
8049 case Intrinsic::aarch64_neon_pmull:
8052 Ops.push_back(&
II->getOperandUse(0));
8053 Ops.push_back(&
II->getOperandUse(1));
8055 case Intrinsic::aarch64_neon_pmull64:
8057 II->getArgOperand(1)))
8059 Ops.push_back(&
II->getArgOperandUse(0));
8060 Ops.push_back(&
II->getArgOperandUse(1));
8062 case Intrinsic::masked_gather:
8065 Ops.push_back(&
II->getArgOperandUse(0));
8067 case Intrinsic::masked_scatter:
8070 Ops.push_back(&
II->getArgOperandUse(1));
8077 auto ShouldSinkCondition = [](
Value *
Cond,
8082 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8086 Ops.push_back(&
II->getOperandUse(0));
8090 switch (
I->getOpcode()) {
8091 case Instruction::GetElementPtr:
8092 case Instruction::Add:
8093 case Instruction::Sub:
8095 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8097 Ops.push_back(&
I->getOperandUse(
Op));
8102 case Instruction::Select: {
8103 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8106 Ops.push_back(&
I->getOperandUse(0));
8109 case Instruction::UncondBr:
8111 case Instruction::CondBr: {
8115 Ops.push_back(&
I->getOperandUse(0));
8118 case Instruction::FMul:
8123 Ops.push_back(&
I->getOperandUse(0));
8125 Ops.push_back(&
I->getOperandUse(1));
8135 case Instruction::Xor:
8138 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8140 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8145 case Instruction::And:
8146 case Instruction::Or:
8149 if (
I->getOpcode() == Instruction::Or &&
8154 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8157 for (
auto &
Op :
I->operands()) {
8169 Ops.push_back(&Not);
8170 Ops.push_back(&InsertElt);
8180 if (!
I->getType()->isVectorTy())
8181 return !
Ops.empty();
8183 switch (
I->getOpcode()) {
8184 case Instruction::Sub:
8185 case Instruction::Add: {
8194 Ops.push_back(&Ext1->getOperandUse(0));
8195 Ops.push_back(&Ext2->getOperandUse(0));
8198 Ops.push_back(&
I->getOperandUse(0));
8199 Ops.push_back(&
I->getOperandUse(1));
8203 case Instruction::Or: {
8206 if (ST->hasNEON()) {
8213 Ops.push_back(&
I->getOperandUse(0));
8214 Ops.push_back(&
I->getOperandUse(1));
8222 case Instruction::Mul: {
8223 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8226 if (Ty->isScalableTy())
8230 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8233 int NumZExts = 0, NumSExts = 0;
8234 for (
auto &
Op :
I->operands()) {
8241 auto *ExtOp = Ext->getOperand(0);
8242 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8243 Ops.push_back(&Ext->getOperandUse(0));
8251 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8252 I->getType()->getScalarSizeInBits())
8289 if (!ElementConstant || !ElementConstant->
isZero())
8292 unsigned Opcode = OperandInstr->
getOpcode();
8293 if (Opcode == Instruction::SExt)
8295 else if (Opcode == Instruction::ZExt)
8300 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8310 Ops.push_back(&Insert->getOperandUse(1));
8316 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8320 if (!ShouldSinkSplatForIndexedVariant(
I))
8325 Ops.push_back(&
I->getOperandUse(0));
8327 Ops.push_back(&
I->getOperandUse(1));
8329 return !
Ops.empty();
8331 case Instruction::FMul: {
8333 if (
I->getType()->isScalableTy())
8334 return !
Ops.empty();
8338 return !
Ops.empty();
8342 Ops.push_back(&
I->getOperandUse(0));
8344 Ops.push_back(&
I->getOperandUse(1));
8345 return !
Ops.empty();
8354 Align Alignment)
const {
8355 if (!(ST->isSVEAvailable() ||
8356 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8360 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8367 if (!LT.first.isValid())
8372 switch (LT.second.SimpleTy) {
static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static Error reportError(StringRef Message)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
Cost tables and simple lookup functions.
This file defines the DenseMap class.
static Value * getCondition(Instruction *I)
const HexagonInstrInfo * TII
This file provides the interface for the instcombine pass implementation.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file defines the LoopVectorizationLegality class.
static const Function * getCalledFunction(const Value *V)
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
static uint64_t getBits(uint64_t Val, int Start, int End)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
This file implements the C++20 <bit> header.
unsigned getVectorInsertExtractBaseCost() const
bool useSVEForFixedLengthVectors() const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getCostOfKeepingLiveOverCall(ArrayRef< Type * > Tys) const override
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool hasPossibleIncompatibleOps(const Function *F, bool ConsiderZA, bool ConsiderZT, bool ConsiderSM) const
Returns true if the function has explicit operations that can only be lowered using incompatible inst...
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src) const
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index) const override
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
bool preferFixedOverScalableIfEqualCost() const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind=TTI::TCK_RecipThroughput) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isElementTypeLegalForScalableVector(Type *Ty) const override
bool hasMultiVectorLoadStore(unsigned NumVectors, TTI::MaskSource Mask, VectorType *VectorTy, bool IsStore, std::optional< Instruction::CastOps > CastHint) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const override
bool preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
APInt getPriorityMask(const Function &F) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
bool shouldMaximizeVectorBandwidth(TargetTransformInfo::RegisterKind K) const override
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const override
bool useNeonVector(const Type *Ty) const
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
bool isLegalSpeculativeLoad(Type *DataType, unsigned AddressSpace) const override
bool isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
bool isElementTypeLegalForCompressStore(Type *Ty) const
InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, TTI::TargetCostKind CostKind) const override
unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, unsigned DefaultCallPenalty) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
The compiler must not inline when that may alter the behavior of the program.
unsigned getMaxNumElements(ElementCount VF) const
Try to return an estimate cost factor that can be used as a multiplier when scalarizing an operation ...
bool shouldTreatInstructionLikeSelect(const Instruction *I) const override
bool isMultiversionedFunction(const Function &F) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, ElementCount VF) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedGatherScatter(Type *DataType) const
InstructionCost getBranchMispredictPenalty() const override
bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const override
See if I should be considered for address type promotion.
APInt getFeatureMask(const Function &F) const override
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const override
bool enableScalableVectorization() const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Value * getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate=true) const override
bool hasKnownLowerThroughputFromSchedulingModel(unsigned Opcode1, unsigned Opcode2) const
Check whether Opcode1 has less throughput according to the scheduling model than Opcode2.
unsigned getEpilogueVectorizationMinVF() const override
InstructionCost getSpliceCost(VectorType *Tp, int Index, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) const override
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
void negate()
Negate this APInt in place.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
unsigned logBase2() const
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, Instruction *I=nullptr, int64_t ScalableOffset=0) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getCallInstrCost(Function *F, Type *RetTy, ArrayRef< Type * > Tys, TTI::TargetCostKind CostKind) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
std::pair< InstructionCost, MVT > getTypeLegalizationCost(Type *Ty) const
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
bool isTypeLegal(Type *Ty) const override
static BinaryOperator * CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Value *CopyO, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
static bool isFPPredicate(Predicate P)
static bool isIntPredicate(Predicate P)
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
const APInt & getValue() const
Return the constant as an APInt value reference.
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
LLVM_ABI Constant * getSplatValue(bool AllowPoison=false) const
If all elements of the vector constant have the same value, return that value.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
constexpr bool isScalar() const
Exactly one element.
static bool isCommutative(Predicate Pred)
This provides a helper for copying FMF from an instruction or setting specified flags.
Convenience struct for specifying and reasoning about fast-math flags.
bool noSignedZeros() const
bool allowContract() const
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
static bool isCommutative(Predicate P)
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Type * getDoubleTy()
Fetch the type representing a 64-bit floating point value.
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Type * getHalfTy()
Fetch the type representing a 16-bit floating point value.
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Value * CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, Value *Mask)
Create a call to Masked Store intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Type * getFloatTy()
Fetch the type representing a 32-bit floating point value.
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateInsertVector(Type *DstType, Value *SrcVec, Value *SubVec, Value *Idx, const Twine &Name="")
Create a call to the vector.insert intrinsic.
LLVM_ABI Value * CreateElementCount(Type *Ty, ElementCount EC)
Create an expression which evaluates to the number of elements in EC at runtime.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This instruction inserts a single (scalar) element into a VectorType value.
The core instruction combiner logic.
virtual Instruction * eraseInstFromFunction(Instruction &I)=0
Combiner aware instruction erasure.
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
static InstructionCost getInvalid(CostType Val=0)
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
Instruction * user_back()
iterator_range< user_iterator > users()
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
user_iterator user_begin()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
bool hasGroups() const
Returns true if we have any interleave groups.
const SmallVectorImpl< Type * > & getArgTypes() const
Type * getReturnType() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() const
Intrinsic::ID getID() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
iterator_range< block_iterator > blocks() const
RecurrenceSet & getFixedOrderRecurrences()
Return the fixed-order recurrences found in the loop.
DominatorTree * getDominatorTree() const
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
bool isFixedLengthVector() const
MVT getVectorElementType() const
Information for memory intrinsic cost model.
Align getAlignment() const
Type * getDataType() const
Intrinsic::ID getID() const
const Instruction * getInst() const
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
Type * getRecurrenceType() const
Returns the type of the recurrence.
RecurKind getRecurrenceKind() const
This node represents a polynomial recurrence on the trip count of the specified loop.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
This class represents an analyzed expression in the program.
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasStreamingInterfaceOrBody() const
SMECallAttrs is a utility class to hold the SMEAttrs for a callsite.
bool requiresSMChange() const
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
static ScalableVectorType * getDoubleElementsVectorType(ScalableVectorType *VTy)
The main scalar evolution driver.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI unsigned getSmallConstantTripMultiple(const Loop *L, const SCEV *ExitCount)
Returns the largest constant divisor of the trip count as a normal unsigned value,...
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
LLVM_ABI bool isBackedgeTakenCountMaxOrZero(const Loop *L)
Return true if the backedge taken count is either the value returned by getConstantMaxBackedgeTakenCo...
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
const SCEV * getSymbolicMaxBackedgeTakenCount(const Loop *L)
When successful, this returns a SCEV that is greater than or equal to (i.e.
This instruction constructs a fixed permutation of two input vectors.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isExtractSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &Index)
Return true if this shuffle mask is an extract subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Class to represent struct types.
TargetInstrInfo - Interface to description of machine instruction set.
std::pair< LegalizeTypeAction, EVT > LegalizeKind
LegalizeKind holds the legalization kind that needs to happen to EVT in order to type-legalize it.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
bool isFP128Ty() const
Return true if this is 'fp128'.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static VectorType * getInteger(VectorType *VTy)
This static method gets a VectorType with the same number of elements as the input type,...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
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...
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
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...
LLVM_ABI APInt getCpuSupportsMask(ArrayRef< StringRef > Features)
static constexpr unsigned SVEBitsPerBlock
LLVM_ABI APInt getFMVPriority(ArrayRef< StringRef > Features)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
@ ADD
Simple integer binary arithmetic operators.
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ FADD
Simple binary floating point operators.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI bool isTargetIntrinsic(ID IID)
isTargetIntrinsic - Returns true if IID is an intrinsic specific to a certain target.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
AllOnesConstantMatch m_AllOnes()
CheckType m_SpecificType(LLT Ty)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_Cmp()
Matches any compare instruction and ignore it.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::And > m_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R either in the form of L & R or L ?
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_nonnegative > m_NonNegative()
Match an integer or vector of non-negative values.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
auto m_VScale()
Matches a call to llvm.vscale().
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_Undef()
Match an arbitrary undef constant.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
LocationClass< Ty > location(Ty &L)
InstructionCost getVectorInstrCost(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, unsigned Opcode, Type *Val, const TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar, ArrayRef< std::tuple< Value *, User *, int > > ScalarUserAndIdx, TTI::VectorInstrContext VIC)
This is similar to TargetTransformInfo::getVectorInstrCost, but if ScalarTy is a FixedVectorType,...
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.
std::optional< unsigned > isDUPQMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPQMask - matches a splat of equivalent lanes within segments of a given number of elements.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
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,...
TailFoldingOpts
An enum to describe what types of loops we should attempt to tail-fold: Disabled: None Reductions: Lo...
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool isDUPFirstSegmentMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPFirstSegmentMask - matches a splat of the first 128b segment.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< const MDOperand * > findStringMetadataForLoop(const Loop *TheLoop, StringRef Name)
Find string metadata for loop.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
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 bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_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 isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
CostTblEntryT< uint16_t > CostTblEntry
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
Return the number of active elements for VL1 to VL256 predicate pattern, zero for all other patterns.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
constexpr bool valueOr(BoolOrDefault X, bool Default)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
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,...
unsigned getMatchingIROpode() const
bool inactiveLanesAreUnused() const
bool inactiveLanesAreNotDefined() const
bool hasMatchingUndefIntrinsic() const
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
bool hasGoverningPredicate() const
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
CmpInst::Predicate getCmpPredicate() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
bool inactiveLanesTakenFromOperand() const
static SVEIntrinsicInfo defaultUndefOp()
bool hasOperandWithNoActiveLanes() const
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
bool hasCmpPredicate() const
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() const
bool hasMatchingIROpode() const
SVEIntrinsicInfo & setCmpPredicate(CmpInst::Predicate Pred)
bool resultIsZeroInitialized() const
SVEIntrinsicInfo & setMatchingIROpcode(unsigned Opcode)
unsigned getOperandIdxInactiveLanesTakenFrom() const
static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex)
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isFixedLengthVector() const
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Machine model for scheduling, bundling, and heuristics.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Information about a load/store intrinsic defined by the target.
InterleavedAccessInfo * IAI
LoopVectorizationLegality * LVL
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...