25#include "llvm/IR/IntrinsicsAArch64.h"
37#define DEBUG_TYPE "aarch64tti"
40class TailFoldingOption {
55 bool NeedsDefault =
true;
59 void setNeedsDefault(
bool V) { NeedsDefault =
V; }
75 "Initial bits should only include one of "
76 "(disabled|all|simple|default)");
77 Bits = NeedsDefault ? DefaultBits : InitialBits;
85 errs() <<
"invalid argument '" << Opt
86 <<
"' to -sve-tail-folding=; the option should be of the form\n"
87 " (disabled|all|default|simple)[+(reductions|recurrences"
88 "|reverse|noreductions|norecurrences|noreverse)]\n";
94 void operator=(
const std::string &Val) {
103 setNeedsDefault(
false);
108 unsigned StartIdx = 1;
109 if (TailFoldTypes[0] ==
"disabled")
111 else if (TailFoldTypes[0] ==
"all")
113 else if (TailFoldTypes[0] ==
"default")
114 setNeedsDefault(
true);
115 else if (TailFoldTypes[0] ==
"simple")
122 for (
unsigned I = StartIdx;
I < TailFoldTypes.
size();
I++) {
123 if (TailFoldTypes[
I] ==
"reductions")
125 else if (TailFoldTypes[
I] ==
"recurrences")
127 else if (TailFoldTypes[
I] ==
"reverse")
129 else if (TailFoldTypes[
I] ==
"noreductions")
131 else if (TailFoldTypes[
I] ==
"norecurrences")
133 else if (TailFoldTypes[
I] ==
"noreverse")
145 return (
getBits(DefaultBits) & Required) == Required;
155 "Control the use of vectorisation using tail-folding for SVE where the"
156 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
157 "\ndisabled (Initial) No loop types will vectorize using "
159 "\ndefault (Initial) Uses the default tail-folding settings for "
161 "\nall (Initial) All legal loop types will vectorize using "
163 "\nsimple (Initial) Use tail-folding for simple loops (not "
164 "reductions or recurrences)"
165 "\nreductions Use tail-folding for loops containing reductions"
166 "\nnoreductions Inverse of above"
167 "\nrecurrences Use tail-folding for loops containing fixed order "
169 "\nnorecurrences Inverse of above"
170 "\nreverse Use tail-folding for loops requiring reversed "
172 "\nnoreverse Inverse of above"),
181 bool ConsiderSM)
const {
182 if (!ConsiderZA && !ConsiderZT && !ConsiderSM)
185 bool IsAlwaysInline =
F->hasFnAttribute(Attribute::AlwaysInline);
192 bool AssumeVScaleIsEquivalent =
193 F->getReturnType()->isScalableTy() ||
194 any_of(
F->getFunctionType()->params(),
195 [](
const Type *
T) { return T->isScalableTy(); });
203 if (CB->isInlineAsm())
206 if (
CallAttrs.callee().isSMEABIRoutine())
215 if (ConsiderSM &&
CallAttrs.callee().hasStreamingCompatibleInterface())
225 if (
II &&
II->getCalledFunction()->isTargetIntrinsic())
230 if (!AssumeVScaleIsEquivalent &&
231 ((
II &&
II->getIntrinsicID() == Intrinsic::vscale) ||
232 I.getType()->isScalableTy() ||
235 [](
const Value *V) { return V->getType()->isScalableTy(); }) ||
237 .getSourceElementType()
247 return isa<FixedVectorType>(V->getType());
265 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
266 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
267 FeatureStr.
split(Features,
",");
283 return F.hasFnAttribute(
"fmv-features");
335 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
336 CallAttrs.callee().hasStreamingInterfaceOrBody())
344 if (
CallAttrs.callee().hasStreamingBody()) {
349 bool ConsiderZA =
CallAttrs.requiresZASave();
350 bool ConsiderZT =
CallAttrs.requiresPreservingZT0() ||
351 CallAttrs.requiresPreservingAllZAState();
352 bool ConsiderSM =
CallAttrs.requiresSMChange();
357 if (ConsiderSM && (Caller->isStrictFP() || Callee->isStrictFP()))
381 auto FVTy = dyn_cast<FixedVectorType>(Ty);
383 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
392 unsigned DefaultCallPenalty)
const {
417 if (
F ==
Call.getCaller())
418 return ST->getCLOpts().call_penalty_sm_change * DefaultCallPenalty;
420 return ST->getCLOpts().inline_call_penalty_sm_change * DefaultCallPenalty;
423 return DefaultCallPenalty;
443 ST->isSVEorStreamingSVEAvailable() &&
444 !ST->disableMaximizeScalableBandwidth();
468 assert(Ty->isIntegerTy());
470 unsigned BitSize = Ty->getPrimitiveSizeInBits();
477 ImmVal =
Imm.sext((BitSize + 63) & ~0x3fU);
482 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
488 return std::max<InstructionCost>(1,
Cost);
495 assert(Ty->isIntegerTy());
497 unsigned BitSize = Ty->getPrimitiveSizeInBits();
503 unsigned ImmIdx = ~0U;
507 case Instruction::GetElementPtr:
512 case Instruction::Store:
515 case Instruction::Add:
516 case Instruction::Sub:
517 case Instruction::Mul:
518 case Instruction::UDiv:
519 case Instruction::SDiv:
520 case Instruction::URem:
521 case Instruction::SRem:
522 case Instruction::And:
523 case Instruction::Or:
524 case Instruction::Xor:
525 case Instruction::ICmp:
529 case Instruction::Shl:
530 case Instruction::LShr:
531 case Instruction::AShr:
535 case Instruction::Trunc:
536 case Instruction::ZExt:
537 case Instruction::SExt:
538 case Instruction::IntToPtr:
539 case Instruction::PtrToInt:
540 case Instruction::BitCast:
541 case Instruction::PHI:
542 case Instruction::Call:
543 case Instruction::Select:
544 case Instruction::Ret:
545 case Instruction::Load:
550 int NumConstants = (BitSize + 63) / 64;
563 assert(Ty->isIntegerTy());
565 unsigned BitSize = Ty->getPrimitiveSizeInBits();
574 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
580 case Intrinsic::sadd_with_overflow:
581 case Intrinsic::uadd_with_overflow:
582 case Intrinsic::ssub_with_overflow:
583 case Intrinsic::usub_with_overflow:
584 case Intrinsic::smul_with_overflow:
585 case Intrinsic::umul_with_overflow:
587 int NumConstants = (BitSize + 63) / 64;
594 case Intrinsic::experimental_stackmap:
595 if ((Idx < 2) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
598 case Intrinsic::experimental_patchpoint_void:
599 case Intrinsic::experimental_patchpoint:
600 if ((Idx < 4) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
603 case Intrinsic::experimental_gc_statepoint:
604 if ((Idx < 5) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
614 if (TyWidth == 32 || TyWidth == 64)
623 return ST->getMispredictionPenalty();
639 if (!ST->isSVEAvailable() || !ST->hasSVE2())
644 unsigned TotalHistCnts = 1;
654 unsigned EC = VTy->getElementCount().getKnownMinValue();
659 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
661 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
665 TotalHistCnts = EC / NaturalVectorWidth;
667 return InstructionCost(ST->getCLOpts().base_histcnt_cost * TotalHistCnts);
684 !
is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
688 switch (ICA.
getID()) {
689 case Intrinsic::experimental_vector_histogram_add: {
696 case Intrinsic::experimental_vector_histogram_uadd_sat:
697 case Intrinsic::experimental_vector_histogram_umax:
698 case Intrinsic::experimental_vector_histogram_umin:
701 case Intrinsic::clmul: {
706 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
710 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
715 -1,
nullptr,
nullptr) *
718 -1,
nullptr,
nullptr);
722 if (LT.second.SimpleTy == MVT::nxv2i64)
723 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
726 if (ST->hasSVE2() || ST->hasSME()) {
727 switch (LT.second.SimpleTy) {
742 if (LT.second.SimpleTy == MVT::nxv2i64)
746 switch (LT.second.SimpleTy) {
756 -1,
nullptr,
nullptr) *
759 -1,
nullptr,
nullptr));
768 return LT.first * 11;
770 return LT.first * 14;
777 case Intrinsic::smulh:
778 case Intrinsic::umulh: {
784 if (RetTy->getScalarSizeInBits() > 64)
798 return MulCost + ExtraCost;
803 return LT.first + ExtraCost;
819 return LT.first * Entry->Cost + ExtraCost;
823 case Intrinsic::umin:
824 case Intrinsic::umax:
825 case Intrinsic::smin:
826 case Intrinsic::smax: {
827 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
828 MVT::v8i16, MVT::v2i32, MVT::v4i32,
829 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
836 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
837 EVT VT = TLI->getValueType(
DL, RetTy,
true);
838 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
839 return LT.first * (IsSigned ? 5 : 3);
841 if (LT.second == MVT::v2i64)
847 case Intrinsic::scmp:
848 case Intrinsic::ucmp: {
850 {Intrinsic::scmp, MVT::i32, 3},
851 {Intrinsic::scmp, MVT::i64, 3},
852 {Intrinsic::scmp, MVT::v8i8, 3},
853 {Intrinsic::scmp, MVT::v16i8, 3},
854 {Intrinsic::scmp, MVT::v4i16, 3},
855 {Intrinsic::scmp, MVT::v8i16, 3},
856 {Intrinsic::scmp, MVT::v2i32, 3},
857 {Intrinsic::scmp, MVT::v4i32, 3},
858 {Intrinsic::scmp, MVT::v1i64, 3},
859 {Intrinsic::scmp, MVT::v2i64, 3},
865 return Entry->Cost * LT.first;
868 case Intrinsic::sadd_sat:
869 case Intrinsic::ssub_sat:
870 case Intrinsic::uadd_sat:
871 case Intrinsic::usub_sat: {
872 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
873 MVT::v8i16, MVT::v2i32, MVT::v4i32,
879 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
881 return LT.first * Instrs;
886 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
887 return LT.first * Instrs;
891 case Intrinsic::abs: {
892 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
893 MVT::v8i16, MVT::v2i32, MVT::v4i32,
894 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
895 MVT::nxv4i32, MVT::nxv2i64};
901 case Intrinsic::bswap: {
902 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
903 MVT::v4i32, MVT::v2i64};
906 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
911 case Intrinsic::fmuladd: {
916 (EltTy->
isHalfTy() && ST->hasFullFP16()))
920 case Intrinsic::stepvector: {
929 Cost += AddCost * (LT.first - 1);
933 case Intrinsic::vector_extract:
934 case Intrinsic::vector_insert: {
947 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
948 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
956 getTLI()->getTypeConversion(
C, SubVecVT);
958 getTLI()->getTypeConversion(
C, VecVT);
966 case Intrinsic::bitreverse: {
968 {Intrinsic::bitreverse, MVT::i32, 1},
969 {Intrinsic::bitreverse, MVT::i64, 1},
970 {Intrinsic::bitreverse, MVT::v8i8, 1},
971 {Intrinsic::bitreverse, MVT::v16i8, 1},
972 {Intrinsic::bitreverse, MVT::v4i16, 2},
973 {Intrinsic::bitreverse, MVT::v8i16, 2},
974 {Intrinsic::bitreverse, MVT::v2i32, 2},
975 {Intrinsic::bitreverse, MVT::v4i32, 2},
976 {Intrinsic::bitreverse, MVT::v1i64, 2},
977 {Intrinsic::bitreverse, MVT::v2i64, 2},
985 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
986 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
987 return LegalisationCost.first * Entry->Cost + 1;
989 return LegalisationCost.first * Entry->Cost;
993 case Intrinsic::pdep:
994 case Intrinsic::pext: {
995 unsigned BW = RetTy->getScalarSizeInBits();
996 if (!RetTy->isVectorTy() && ST->isSVEBitPermAvailable() && BW <= 64) {
1010 case Intrinsic::ctpop: {
1012 MVT MTy = LT.second;
1014 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
1017 return LT.first + ExtraCost;
1019 if (!ST->hasNEON()) {
1049 RetTy->getScalarSizeInBits()
1052 return LT.first * Entry->Cost + ExtraCost;
1056 case Intrinsic::sadd_with_overflow:
1057 case Intrinsic::uadd_with_overflow:
1058 case Intrinsic::ssub_with_overflow:
1059 case Intrinsic::usub_with_overflow:
1060 case Intrinsic::smul_with_overflow:
1061 case Intrinsic::umul_with_overflow: {
1063 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
1064 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
1065 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
1066 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
1067 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
1068 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
1069 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
1070 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
1071 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
1072 {Intrinsic::usub_with_overflow, MVT::i8, 3},
1073 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
1074 {Intrinsic::usub_with_overflow, MVT::i16, 3},
1075 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
1076 {Intrinsic::usub_with_overflow, MVT::i32, 1},
1077 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
1078 {Intrinsic::usub_with_overflow, MVT::i64, 1},
1079 {Intrinsic::smul_with_overflow, MVT::i8, 5},
1080 {Intrinsic::umul_with_overflow, MVT::i8, 4},
1081 {Intrinsic::smul_with_overflow, MVT::i16, 5},
1082 {Intrinsic::umul_with_overflow, MVT::i16, 4},
1083 {Intrinsic::smul_with_overflow, MVT::i32, 2},
1084 {Intrinsic::umul_with_overflow, MVT::i32, 2},
1085 {Intrinsic::smul_with_overflow, MVT::i64, 3},
1086 {Intrinsic::umul_with_overflow, MVT::i64, 3},
1088 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
1095 case Intrinsic::fptosi_sat:
1096 case Intrinsic::fptoui_sat: {
1099 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
1101 EVT MTy = TLI->getValueType(
DL, RetTy);
1104 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
1105 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
1106 LT.second == MVT::v2f64)) {
1108 (LT.second == MVT::f64 && MTy == MVT::i32) ||
1109 (LT.second == MVT::f32 && MTy == MVT::i64)))
1118 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
1125 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
1126 (LT.second == MVT::f16 && MTy == MVT::i64) ||
1127 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1141 if ((LT.second.getScalarType() == MVT::f32 ||
1142 LT.second.getScalarType() == MVT::f64 ||
1143 LT.second.getScalarType() == MVT::f16) &&
1146 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1147 if (LT.second.isVector())
1148 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1152 LegalTy, {LegalTy, LegalTy});
1156 LegalTy, {LegalTy, LegalTy});
1158 return LT.first *
Cost +
1159 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1165 RetTy = RetTy->getScalarType();
1166 if (LT.second.isVector()) {
1184 return LT.first *
Cost;
1186 case Intrinsic::fshl:
1187 case Intrinsic::fshr: {
1196 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1197 (RetTy->getPrimitiveSizeInBits() == 32 ||
1198 RetTy->getPrimitiveSizeInBits() == 64)) {
1211 {Intrinsic::fshl, MVT::v4i32, 2},
1212 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1213 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1214 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1220 return LegalisationCost.first * Entry->Cost;
1224 if (!RetTy->isIntegerTy())
1229 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1230 RetTy->getScalarSizeInBits() < 64) ||
1231 (RetTy->getScalarSizeInBits() % 64 != 0);
1232 unsigned ExtraCost = HigherCost ? 1 : 0;
1233 if (RetTy->getScalarSizeInBits() == 32 ||
1234 RetTy->getScalarSizeInBits() == 64)
1237 else if (HigherCost)
1241 return TyL.first + ExtraCost;
1243 case Intrinsic::get_active_lane_mask: {
1245 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1247 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1250 if (RetTy->isScalableTy()) {
1251 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1261 if (ST->hasSVE2p1() || ST->hasSME2()) {
1273 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1276 return Cost + (SplitCost * (
Cost - 1));
1291 case Intrinsic::experimental_vector_match: {
1292 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1298 unsigned SearchSize = NeedleTy->getNumElements();
1299 if (SearchSize <= 2)
1304 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1308 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1314 unsigned MatchesRequiredForNeedle =
1326 return Cost * LegalParts * MatchesRequiredForNeedle;
1328 case Intrinsic::cttz: {
1330 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1331 return LT.first * 2;
1332 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1333 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1334 return LT.first * 3;
1337 case Intrinsic::experimental_cttz_elts: {
1347 case Intrinsic::mask_beforefirst: {
1348 if (!ST->isSVEorStreamingSVEAvailable() ||
1350 !TLI->isTypeLegal(getTLI()->getValueType(
DL, RetTy)))
1357 case Intrinsic::loop_dependence_raw_mask:
1358 case Intrinsic::loop_dependence_war_mask: {
1360 if (ST->hasSVE2() || ST->hasSME()) {
1361 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1362 unsigned EltSizeInBytes =
1372 case Intrinsic::experimental_vector_extract_last_active:
1373 if (ST->isSVEorStreamingSVEAvailable()) {
1379 case Intrinsic::pow: {
1382 EVT VT = getTLI()->getValueType(
DL, RetTy);
1383 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1385 getTLI()->getLibcallLoweringInfo().getVectorLibcallImplOrMasked(LC) !=
1401 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1402 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1412 return (Sqrt * 2) +
FMul;
1423 case Intrinsic::sqrt:
1424 case Intrinsic::fabs:
1425 case Intrinsic::ceil:
1426 case Intrinsic::floor:
1427 case Intrinsic::nearbyint:
1428 case Intrinsic::round:
1429 case Intrinsic::rint:
1430 case Intrinsic::roundeven:
1431 case Intrinsic::trunc:
1432 case Intrinsic::minnum:
1433 case Intrinsic::maxnum:
1434 case Intrinsic::minimum:
1435 case Intrinsic::maximum: {
1453 auto RequiredType =
II.getType();
1456 assert(PN &&
"Expected Phi Node!");
1459 if (!PN->hasOneUse())
1460 return std::nullopt;
1462 for (
Value *IncValPhi : PN->incoming_values()) {
1465 Reinterpret->getIntrinsicID() !=
1466 Intrinsic::aarch64_sve_convert_to_svbool ||
1467 RequiredType != Reinterpret->getArgOperand(0)->getType())
1468 return std::nullopt;
1476 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1478 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1551 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1556 return GoverningPredicateIdx;
1561 GoverningPredicateIdx = Index;
1583 return UndefIntrinsic;
1588 UndefIntrinsic = IID;
1615 return CmpPredicate;
1620 CmpPredicate = Pred;
1636 return ResultLanes == InactiveLanesTakenFromOperand;
1641 return OperandIdxForInactiveLanes;
1645 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1646 ResultLanes = InactiveLanesTakenFromOperand;
1647 OperandIdxForInactiveLanes = Index;
1652 return ResultLanes == InactiveLanesAreNotDefined;
1656 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1657 ResultLanes = InactiveLanesAreNotDefined;
1662 return ResultLanes == InactiveLanesAreUnused;
1666 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1667 ResultLanes = InactiveLanesAreUnused;
1677 ResultIsZeroInitialized =
true;
1688 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1693 return OperandIdxWithNoActiveLanes;
1698 OperandIdxWithNoActiveLanes = Index;
1703 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1706 unsigned IROpcode = 0;
1709 enum PredicationStyle {
1711 InactiveLanesTakenFromOperand,
1712 InactiveLanesAreNotDefined,
1713 InactiveLanesAreUnused
1716 bool ResultIsZeroInitialized =
false;
1717 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1718 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1726 return !isa<ScalableVectorType>(V->getType());
1734 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1735 case Intrinsic::aarch64_sve_fcvt_f16f32:
1736 case Intrinsic::aarch64_sve_fcvt_f16f64:
1737 case Intrinsic::aarch64_sve_fcvt_f32f16:
1738 case Intrinsic::aarch64_sve_fcvt_f32f64:
1739 case Intrinsic::aarch64_sve_fcvt_f64f16:
1740 case Intrinsic::aarch64_sve_fcvt_f64f32:
1741 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1742 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1743 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1744 case Intrinsic::aarch64_sve_fcvtzs:
1745 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1746 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1747 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1748 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1749 case Intrinsic::aarch64_sve_fcvtzu:
1750 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1751 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1752 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1753 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1754 case Intrinsic::aarch64_sve_revb:
1755 case Intrinsic::aarch64_sve_revh:
1756 case Intrinsic::aarch64_sve_revw:
1757 case Intrinsic::aarch64_sve_revd:
1758 case Intrinsic::aarch64_sve_scvtf:
1759 case Intrinsic::aarch64_sve_scvtf_f16i32:
1760 case Intrinsic::aarch64_sve_scvtf_f16i64:
1761 case Intrinsic::aarch64_sve_scvtf_f32i64:
1762 case Intrinsic::aarch64_sve_scvtf_f64i32:
1763 case Intrinsic::aarch64_sve_ucvtf:
1764 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1765 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1766 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1767 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1770 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1771 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1772 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1773 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1776 case Intrinsic::aarch64_sve_fabd:
1778 case Intrinsic::aarch64_sve_fadd:
1781 case Intrinsic::aarch64_sve_fdiv:
1784 case Intrinsic::aarch64_sve_fmax:
1786 case Intrinsic::aarch64_sve_fmaxnm:
1788 case Intrinsic::aarch64_sve_fmin:
1790 case Intrinsic::aarch64_sve_fminnm:
1792 case Intrinsic::aarch64_sve_fmla:
1794 case Intrinsic::aarch64_sve_fmls:
1796 case Intrinsic::aarch64_sve_fmul:
1799 case Intrinsic::aarch64_sve_fmulx:
1801 case Intrinsic::aarch64_sve_fnmla:
1803 case Intrinsic::aarch64_sve_fnmls:
1805 case Intrinsic::aarch64_sve_fsub:
1808 case Intrinsic::aarch64_sve_add:
1811 case Intrinsic::aarch64_sve_mla:
1813 case Intrinsic::aarch64_sve_mls:
1815 case Intrinsic::aarch64_sve_mul:
1818 case Intrinsic::aarch64_sve_sabd:
1820 case Intrinsic::aarch64_sve_sdiv:
1823 case Intrinsic::aarch64_sve_smax:
1825 case Intrinsic::aarch64_sve_smin:
1827 case Intrinsic::aarch64_sve_smulh:
1829 case Intrinsic::aarch64_sve_sub:
1832 case Intrinsic::aarch64_sve_uabd:
1834 case Intrinsic::aarch64_sve_udiv:
1837 case Intrinsic::aarch64_sve_umax:
1839 case Intrinsic::aarch64_sve_umin:
1841 case Intrinsic::aarch64_sve_umulh:
1843 case Intrinsic::aarch64_sve_asr:
1846 case Intrinsic::aarch64_sve_lsl:
1849 case Intrinsic::aarch64_sve_lsr:
1852 case Intrinsic::aarch64_sve_and:
1855 case Intrinsic::aarch64_sve_bic:
1857 case Intrinsic::aarch64_sve_eor:
1860 case Intrinsic::aarch64_sve_orr:
1863 case Intrinsic::aarch64_sve_shsub:
1865 case Intrinsic::aarch64_sve_shsubr:
1867 case Intrinsic::aarch64_sve_sqrshl:
1869 case Intrinsic::aarch64_sve_sqshl:
1871 case Intrinsic::aarch64_sve_sqsub:
1873 case Intrinsic::aarch64_sve_srshl:
1875 case Intrinsic::aarch64_sve_uhsub:
1877 case Intrinsic::aarch64_sve_uhsubr:
1879 case Intrinsic::aarch64_sve_uqrshl:
1881 case Intrinsic::aarch64_sve_uqshl:
1883 case Intrinsic::aarch64_sve_uqsub:
1885 case Intrinsic::aarch64_sve_urshl:
1888 case Intrinsic::aarch64_sve_add_u:
1891 case Intrinsic::aarch64_sve_and_u:
1894 case Intrinsic::aarch64_sve_asr_u:
1897 case Intrinsic::aarch64_sve_eor_u:
1900 case Intrinsic::aarch64_sve_fadd_u:
1903 case Intrinsic::aarch64_sve_fdiv_u:
1906 case Intrinsic::aarch64_sve_fmul_u:
1909 case Intrinsic::aarch64_sve_fsub_u:
1912 case Intrinsic::aarch64_sve_lsl_u:
1915 case Intrinsic::aarch64_sve_lsr_u:
1918 case Intrinsic::aarch64_sve_mul_u:
1921 case Intrinsic::aarch64_sve_orr_u:
1924 case Intrinsic::aarch64_sve_sdiv_u:
1927 case Intrinsic::aarch64_sve_sub_u:
1930 case Intrinsic::aarch64_sve_udiv_u:
1934 case Intrinsic::aarch64_sve_addqv:
1935 case Intrinsic::aarch64_sve_bic_z:
1936 case Intrinsic::aarch64_sve_brka_z:
1937 case Intrinsic::aarch64_sve_brkb_z:
1938 case Intrinsic::aarch64_sve_brkn_z:
1939 case Intrinsic::aarch64_sve_brkpa_z:
1940 case Intrinsic::aarch64_sve_brkpb_z:
1941 case Intrinsic::aarch64_sve_cntp:
1942 case Intrinsic::aarch64_sve_compact:
1943 case Intrinsic::aarch64_sve_eorv:
1944 case Intrinsic::aarch64_sve_eorqv:
1945 case Intrinsic::aarch64_sve_nand_z:
1946 case Intrinsic::aarch64_sve_nor_z:
1947 case Intrinsic::aarch64_sve_orn_z:
1948 case Intrinsic::aarch64_sve_orv:
1949 case Intrinsic::aarch64_sve_orqv:
1950 case Intrinsic::aarch64_sve_pnext:
1951 case Intrinsic::aarch64_sve_rdffr_z:
1952 case Intrinsic::aarch64_sve_saddv:
1953 case Intrinsic::aarch64_sve_uaddv:
1954 case Intrinsic::aarch64_sve_umaxv:
1955 case Intrinsic::aarch64_sve_umaxqv:
1956 case Intrinsic::aarch64_sve_facge:
1957 case Intrinsic::aarch64_sve_facgt:
1958 case Intrinsic::aarch64_sve_ld1:
1959 case Intrinsic::aarch64_sve_ld1_gather:
1960 case Intrinsic::aarch64_sve_ld1_gather_index:
1961 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1962 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1963 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1964 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1965 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1966 case Intrinsic::aarch64_sve_ld1q_gather_index:
1967 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1968 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1969 case Intrinsic::aarch64_sve_ld1ro:
1970 case Intrinsic::aarch64_sve_ld1rq:
1971 case Intrinsic::aarch64_sve_ld1udq:
1972 case Intrinsic::aarch64_sve_ld1uwq:
1973 case Intrinsic::aarch64_sve_ld2_sret:
1974 case Intrinsic::aarch64_sve_ld2q_sret:
1975 case Intrinsic::aarch64_sve_ld3_sret:
1976 case Intrinsic::aarch64_sve_ld3q_sret:
1977 case Intrinsic::aarch64_sve_ld4_sret:
1978 case Intrinsic::aarch64_sve_ld4q_sret:
1979 case Intrinsic::aarch64_sve_ldff1:
1980 case Intrinsic::aarch64_sve_ldff1_gather:
1981 case Intrinsic::aarch64_sve_ldff1_gather_index:
1982 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1983 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1984 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1985 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1986 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1987 case Intrinsic::aarch64_sve_ldnf1:
1988 case Intrinsic::aarch64_sve_ldnt1:
1989 case Intrinsic::aarch64_sve_ldnt1_gather:
1990 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1991 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1992 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1995 case Intrinsic::aarch64_sve_and_z:
1998 case Intrinsic::aarch64_sve_orr_z:
2001 case Intrinsic::aarch64_sve_eor_z:
2005 case Intrinsic::aarch64_sve_cmpeq:
2006 case Intrinsic::aarch64_sve_cmpeq_wide:
2009 case Intrinsic::aarch64_sve_cmpge:
2010 case Intrinsic::aarch64_sve_cmpge_wide:
2013 case Intrinsic::aarch64_sve_cmpgt:
2014 case Intrinsic::aarch64_sve_cmpgt_wide:
2017 case Intrinsic::aarch64_sve_cmphi:
2018 case Intrinsic::aarch64_sve_cmphi_wide:
2021 case Intrinsic::aarch64_sve_cmphs:
2022 case Intrinsic::aarch64_sve_cmphs_wide:
2025 case Intrinsic::aarch64_sve_cmple_wide:
2028 case Intrinsic::aarch64_sve_cmplo_wide:
2031 case Intrinsic::aarch64_sve_cmpls_wide:
2034 case Intrinsic::aarch64_sve_cmplt_wide:
2037 case Intrinsic::aarch64_sve_cmpne:
2038 case Intrinsic::aarch64_sve_cmpne_wide:
2041 case Intrinsic::aarch64_sve_fcmpeq:
2044 case Intrinsic::aarch64_sve_fcmpge:
2047 case Intrinsic::aarch64_sve_fcmpgt:
2050 case Intrinsic::aarch64_sve_fcmpne:
2053 case Intrinsic::aarch64_sve_fcmpuo:
2057 case Intrinsic::aarch64_sve_prf:
2058 case Intrinsic::aarch64_sve_prfb_gather_index:
2059 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
2060 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
2061 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
2062 case Intrinsic::aarch64_sve_prfd_gather_index:
2063 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
2064 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
2065 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
2066 case Intrinsic::aarch64_sve_prfh_gather_index:
2067 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
2068 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
2069 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
2070 case Intrinsic::aarch64_sve_prfw_gather_index:
2071 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
2072 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
2073 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
2076 case Intrinsic::aarch64_sve_st1_scatter:
2077 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
2078 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
2079 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
2080 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
2081 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
2082 case Intrinsic::aarch64_sve_st1dq:
2083 case Intrinsic::aarch64_sve_st1q_scatter_index:
2084 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
2085 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
2086 case Intrinsic::aarch64_sve_st1wq:
2087 case Intrinsic::aarch64_sve_stnt1:
2088 case Intrinsic::aarch64_sve_stnt1_scatter:
2089 case Intrinsic::aarch64_sve_stnt1_scatter_index:
2090 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
2091 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
2093 case Intrinsic::aarch64_sve_st2:
2094 case Intrinsic::aarch64_sve_st2q:
2096 case Intrinsic::aarch64_sve_st3:
2097 case Intrinsic::aarch64_sve_st3q:
2099 case Intrinsic::aarch64_sve_st4:
2100 case Intrinsic::aarch64_sve_st4q:
2108 Value *UncastedPred;
2114 Pred = UncastedPred;
2120 if (OrigPredTy->getMinNumElements() <=
2122 ->getMinNumElements())
2123 Pred = UncastedPred;
2127 return C &&
C->isAllOnesValue();
2134 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
2135 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2143static std::optional<Instruction *>
2150 Value *Op1 =
II.getOperand(1);
2151 Value *Op2 =
II.getOperand(2);
2176 Value *NarrowOp1, *NarrowOp2;
2187 else if (SimpleNarrow == NarrowOp1)
2189 else if (SimpleNarrow == NarrowOp2)
2194 SimpleNarrow->
getType(), SimpleNarrow);
2203 return std::nullopt;
2214 if (SimpleII == Inactive)
2222static std::optional<Instruction *>
2226 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2227 "Expected a compare operation!");
2234 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2235 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2236 "Unexpected wide compare!");
2252 const APInt *LHSVal, *RHSVal;
2254 return std::nullopt;
2277 return std::nullopt;
2291static std::optional<Instruction *>
2295 return std::nullopt;
2324 II.setCalledFunction(NewDecl);
2330 return std::nullopt;
2341 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2344 return std::nullopt;
2356static std::optional<Instruction *>
2358 auto m_ConvertToSVBool = [](
auto P) {
2362 Intrinsic::aarch64_sve_convert_from_svbool;
2385 return std::nullopt;
2389 case Intrinsic::aarch64_sve_and_z:
2390 case Intrinsic::aarch64_sve_bic_z:
2391 case Intrinsic::aarch64_sve_eor_z:
2392 case Intrinsic::aarch64_sve_nand_z:
2393 case Intrinsic::aarch64_sve_nor_z:
2394 case Intrinsic::aarch64_sve_orn_z:
2395 case Intrinsic::aarch64_sve_orr_z:
2398 return std::nullopt;
2401 Value *BinOpPred = BinOp->getOperand(0);
2402 Value *BinOpOp1 = BinOp->getOperand(1);
2403 Value *BinOpOp2 = BinOp->getOperand(2);
2405 Value *NarrowBinOpPred;
2407 return std::nullopt;
2409 Value *NarrowBinOpOp1 =
2411 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2412 if (BinOpOp1 != BinOpOp2)
2416 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2420static std::optional<Instruction *>
2427 return BinOpCombine;
2432 return std::nullopt;
2435 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2444 if (CursorVTy->getElementCount().getKnownMinValue() <
2445 IVTy->getElementCount().getKnownMinValue())
2449 if (Cursor->getType() == IVTy)
2450 EarliestReplacement = Cursor;
2455 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2456 Intrinsic::aarch64_sve_convert_to_svbool ||
2457 IntrinsicCursor->getIntrinsicID() ==
2458 Intrinsic::aarch64_sve_convert_from_svbool))
2461 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2462 Cursor = IntrinsicCursor->getOperand(0);
2467 if (!EarliestReplacement)
2468 return std::nullopt;
2476 auto *OpPredicate =
II.getOperand(0);
2493 II.getArgOperand(2));
2499 return std::nullopt;
2503 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2512 II.getArgOperand(0));
2521 if (!
II.hasOneUse())
2522 return std::nullopt;
2525 return std::nullopt;
2528 switch (
II.getIntrinsicID()) {
2529 case Intrinsic::aarch64_sve_cmpne:
2530 IID = Intrinsic::aarch64_sve_cmpeq;
2532 case Intrinsic::aarch64_sve_cmpne_wide:
2533 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2535 case Intrinsic::aarch64_sve_cmpeq:
2536 IID = Intrinsic::aarch64_sve_cmpne;
2538 case Intrinsic::aarch64_sve_cmpeq_wide:
2539 IID = Intrinsic::aarch64_sve_cmpne_wide;
2542 return std::nullopt;
2547 IID,
II.getOperand(1)->getType(),
2548 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2560 return std::nullopt;
2562 for (
auto *U :
II.users()) {
2565 Type *Ty =
II.getOperand(1)->getType();
2570 Intrinsic::aarch64_sve_umin, Ty,
2571 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2577 return std::nullopt;
2591 return std::nullopt;
2596 if (!SplatValue || !SplatValue->isZero())
2597 return std::nullopt;
2602 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2603 return std::nullopt;
2607 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2608 return std::nullopt;
2611 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2612 return std::nullopt;
2617 return std::nullopt;
2620 return std::nullopt;
2624 return std::nullopt;
2628 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2629 return std::nullopt;
2631 unsigned NumElts = VecTy->getNumElements();
2632 unsigned PredicateBits = 0;
2635 for (
unsigned I = 0;
I < NumElts; ++
I) {
2638 return std::nullopt;
2640 PredicateBits |= 1 << (
I * (16 / NumElts));
2644 if (PredicateBits == 0) {
2646 PFalse->takeName(&
II);
2652 for (
unsigned I = 0;
I < 16; ++
I)
2653 if ((PredicateBits & (1 <<
I)) != 0)
2656 unsigned PredSize = Mask & -Mask;
2661 for (
unsigned I = 0;
I < 16;
I += PredSize)
2662 if ((PredicateBits & (1 <<
I)) == 0)
2663 return std::nullopt;
2665 auto *ConvertToSVBool =
2668 auto *ConvertFromSVBool =
2670 II.getType(), ConvertToSVBool);
2678 Value *Pg =
II.getArgOperand(0);
2679 Value *Vec =
II.getArgOperand(1);
2680 auto IntrinsicID =
II.getIntrinsicID();
2681 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2693 auto OpC = OldBinOp->getOpcode();
2699 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2705 if (IsAfter &&
C &&
C->isNullValue()) {
2709 Extract->insertBefore(
II.getIterator());
2710 Extract->takeName(&
II);
2716 return std::nullopt;
2718 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2719 return std::nullopt;
2721 const auto PTruePattern =
2727 return std::nullopt;
2729 unsigned Idx = MinNumElts - 1;
2739 if (Idx >= PgVTy->getMinNumElements())
2740 return std::nullopt;
2745 Extract->insertBefore(
II.getIterator());
2746 Extract->takeName(&
II);
2759 Value *Pg =
II.getArgOperand(0);
2760 Value *Fallback =
II.getArgOperand(1);
2761 Value *Vec =
II.getArgOperand(2);
2764 if (!Ty->isIntegerTy())
2765 return std::nullopt;
2770 return std::nullopt;
2787 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2802static std::optional<Instruction *>
2806 if (
Pattern == AArch64SVEPredPattern::all) {
2815 return MinNumElts && NumElts >= MinNumElts
2817 II, ConstantInt::get(
II.getType(), MinNumElts)))
2821static std::optional<Instruction *>
2824 if (!ST->isStreaming())
2825 return std::nullopt;
2837 Value *PgVal =
II.getArgOperand(0);
2838 Value *OpVal =
II.getArgOperand(1);
2842 if (PgVal == OpVal &&
2843 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2844 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2859 return std::nullopt;
2863 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2864 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2878 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2879 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2880 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2881 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2882 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2883 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2884 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2885 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2886 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2887 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2888 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2889 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2890 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2900 return std::nullopt;
2903template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2904static std::optional<Instruction *>
2906 bool MergeIntoAddendOp) {
2908 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2909 if (MergeIntoAddendOp) {
2910 AddendOp =
II.getOperand(1);
2911 Mul =
II.getOperand(2);
2913 AddendOp =
II.getOperand(2);
2914 Mul =
II.getOperand(1);
2919 return std::nullopt;
2921 if (!
Mul->hasOneUse())
2922 return std::nullopt;
2925 if (
II.getType()->isFPOrFPVectorTy()) {
2930 return std::nullopt;
2932 return std::nullopt;
2937 if (MergeIntoAddendOp)
2947static std::optional<Instruction *>
2950 Value *PtrOp =
II.getOperand(1);
2951 Type *VecTy =
II.getType();
2966static std::optional<Instruction *>
2968 Value *VecOp =
II.getOperand(0);
2970 Value *PtrOp =
II.getOperand(2);
2986 case Intrinsic::aarch64_sve_fmul_u:
2987 return Instruction::BinaryOps::FMul;
2988 case Intrinsic::aarch64_sve_fadd_u:
2989 return Instruction::BinaryOps::FAdd;
2990 case Intrinsic::aarch64_sve_fsub_u:
2991 return Instruction::BinaryOps::FSub;
2993 return Instruction::BinaryOpsEnd;
2997static std::optional<Instruction *>
3000 if (
II.isStrictFP())
3001 return std::nullopt;
3003 auto *OpPredicate =
II.getOperand(0);
3005 if (BinOpCode == Instruction::BinaryOpsEnd ||
3007 return std::nullopt;
3009 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
3013static std::optional<Instruction *>
3015 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
3016 "Expected MLA_U intrinsic");
3017 Value *Acc =
II.getArgOperand(1);
3018 Value *MulOp0 =
II.getArgOperand(2);
3019 Value *MulOp1 =
II.getArgOperand(3);
3034 II.setArgOperand(2, MulOp1);
3035 II.setArgOperand(3, MulOp0);
3039 return std::nullopt;
3042static std::optional<Instruction *>
3044 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
3045 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
3046 "Expected SADALP or UADALP intrinsic");
3052 return std::nullopt;
3056 return std::nullopt;
3060 II.getIntrinsicID(), {II.getType()},
3061 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
3071 Intrinsic::aarch64_sve_mla>(
3075 Intrinsic::aarch64_sve_mad>(
3078 return std::nullopt;
3081static std::optional<Instruction *>
3085 Intrinsic::aarch64_sve_fmla>(IC,
II,
3090 Intrinsic::aarch64_sve_fmad>(IC,
II,
3095 Intrinsic::aarch64_sve_fmla>(IC,
II,
3098 return std::nullopt;
3101static std::optional<Instruction *>
3105 Intrinsic::aarch64_sve_fmla>(IC,
II,
3110 Intrinsic::aarch64_sve_fmad>(IC,
II,
3115 Intrinsic::aarch64_sve_fmla_u>(
3121static std::optional<Instruction *>
3125 Intrinsic::aarch64_sve_fmls>(IC,
II,
3130 Intrinsic::aarch64_sve_fnmsb>(
3135 Intrinsic::aarch64_sve_fmls>(IC,
II,
3138 return std::nullopt;
3141static std::optional<Instruction *>
3145 Intrinsic::aarch64_sve_fmls>(IC,
II,
3150 Intrinsic::aarch64_sve_fnmsb>(
3155 Intrinsic::aarch64_sve_fmls_u>(
3164 Intrinsic::aarch64_sve_mls>(
3167 return std::nullopt;
3172 Value *UnpackArg =
II.getArgOperand(0);
3174 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3175 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3188 return std::nullopt;
3192 auto *OpVal =
II.getOperand(0);
3193 auto *OpIndices =
II.getOperand(1);
3200 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3201 return std::nullopt;
3216 Type *RetTy =
II.getType();
3217 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3218 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3222 if ((
match(
II.getArgOperand(0),
3229 if (TyA ==
B->getType() &&
3234 TyA->getMinNumElements());
3240 return std::nullopt;
3248 if (
match(
II.getArgOperand(0),
3253 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3255 return std::nullopt;
3258static std::optional<Instruction *>
3260 Value *Mask =
II.getOperand(0);
3261 Value *BasePtr =
II.getOperand(1);
3262 Value *Index =
II.getOperand(2);
3273 BasePtr->getPointerAlignment(
II.getDataLayout());
3276 BasePtr, IndexBase);
3283 return std::nullopt;
3286static std::optional<Instruction *>
3288 Value *Val =
II.getOperand(0);
3289 Value *Mask =
II.getOperand(1);
3290 Value *BasePtr =
II.getOperand(2);
3291 Value *Index =
II.getOperand(3);
3301 BasePtr->getPointerAlignment(
II.getDataLayout());
3304 BasePtr, IndexBase);
3310 return std::nullopt;
3317 Value *Vec =
II.getOperand(1);
3318 Value *DivVec =
II.getOperand(2);
3322 if (!SplatConstantInt)
3323 return std::nullopt;
3327 if (DivisorValue == -1)
3328 return std::nullopt;
3329 if (DivisorValue == 1)
3335 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {
Pred, Vec, DivisorLog2});
3342 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {
Pred, Vec, DivisorLog2});
3344 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD,
Pred, ASRD});
3348 return std::nullopt;
3371 if (
I->getParent() != MainAnd->
getParent() ||
3379 size_t VecSize = Vec.
size();
3384 size_t HalfVecSize = VecSize / 2;
3388 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3396 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3412 return std::nullopt;
3419 return std::nullopt;
3426 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3427 CurrentInsertElt = InsertElt->getOperand(0);
3433 return std::nullopt;
3437 for (
size_t I = 0;
I < Elts.
size();
I++) {
3438 if (Elts[
I] ==
nullptr)
3443 if (InsertEltChain ==
nullptr)
3444 return std::nullopt;
3450 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3451 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3452 IIScalableTy->getMinNumElements() /
3457 auto *WideShuffleMaskTy =
3468 auto NarrowBitcast =
3481 return std::nullopt;
3487 Value *Vec =
II.getOperand(1);
3488 Value *Shift =
II.getOperand(2);
3491 Value *AbsPred, *MergedValue;
3497 return std::nullopt;
3505 return std::nullopt;
3510 return std::nullopt;
3513 {
II.getType()}, {
Pred, Vec, Shift});
3520 Value *Vec =
II.getOperand(0);
3525 return std::nullopt;
3528static std::optional<Instruction *>
3530 unsigned LookaheadThreshold) {
3532 auto *NI =
II.getNextNode();
3534 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3536 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3537 auto *NIBB = NI->getParent();
3538 NI = NI->getNextNode();
3540 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3541 NI = &*SuccBB->getFirstNonPHIOrLifetime();
3547 if (NextII &&
II.isIdenticalTo(NextII))
3550 return std::nullopt;
3558 {II.getType(), II.getOperand(0)->getType()},
3559 {II.getOperand(0), II.getOperand(1)}));
3566 if (PredPattern == AArch64SVEPredPattern::all ||
3567 PredPattern == AArch64SVEPredPattern::pow2)
3569 return std::nullopt;
3575 Value *Passthru =
II.getOperand(0);
3583 auto *Mask = ConstantInt::get(Ty, MaskValue);
3589 return std::nullopt;
3592static std::optional<Instruction *>
3599 return std::nullopt;
3605 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3615 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3625 return std::nullopt;
3631 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3639 return std::nullopt;
3642 II.getType(), {Pg, A, B});
3644 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3653 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3658 Value *
A, *PgLHS, *PgRHS;
3664 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3665 return std::nullopt;
3668 if (ConstB > ConstA)
3674 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3675 return std::nullopt;
3677 Type *VecTy =
A->getType();
3681 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3688std::optional<Instruction *>
3699 case Intrinsic::aarch64_dmb:
3701 case Intrinsic::aarch64_neon_fmaxnm:
3702 case Intrinsic::aarch64_neon_fminnm:
3704 case Intrinsic::aarch64_sve_convert_from_svbool:
3706 case Intrinsic::aarch64_sve_dup:
3708 case Intrinsic::aarch64_sve_dup_x:
3710 case Intrinsic::aarch64_sve_cmpeq:
3711 case Intrinsic::aarch64_sve_cmpeq_wide:
3713 case Intrinsic::aarch64_sve_cmpne:
3714 case Intrinsic::aarch64_sve_cmpne_wide:
3716 case Intrinsic::aarch64_sve_rdffr:
3718 case Intrinsic::aarch64_sve_lasta:
3719 case Intrinsic::aarch64_sve_lastb:
3721 case Intrinsic::aarch64_sve_clasta_n:
3722 case Intrinsic::aarch64_sve_clastb_n:
3724 case Intrinsic::aarch64_sve_cntd:
3726 case Intrinsic::aarch64_sve_cntw:
3728 case Intrinsic::aarch64_sve_cnth:
3730 case Intrinsic::aarch64_sve_cntb:
3732 case Intrinsic::aarch64_sme_cntsd:
3734 case Intrinsic::aarch64_sve_ptest_any:
3735 case Intrinsic::aarch64_sve_ptest_first:
3736 case Intrinsic::aarch64_sve_ptest_last:
3738 case Intrinsic::aarch64_sve_fadd:
3740 case Intrinsic::aarch64_sve_fadd_u:
3742 case Intrinsic::aarch64_sve_fmul_u:
3744 case Intrinsic::aarch64_sve_fsub:
3746 case Intrinsic::aarch64_sve_fsub_u:
3748 case Intrinsic::aarch64_sve_add:
3750 case Intrinsic::aarch64_sve_add_u:
3752 Intrinsic::aarch64_sve_mla_u>(
3754 case Intrinsic::aarch64_sve_mla_u:
3756 case Intrinsic::aarch64_sve_sadalp:
3757 case Intrinsic::aarch64_sve_uadalp:
3759 case Intrinsic::aarch64_sve_sub:
3761 case Intrinsic::aarch64_sve_sub_u:
3763 Intrinsic::aarch64_sve_mls_u>(
3765 case Intrinsic::aarch64_sve_tbl:
3767 case Intrinsic::aarch64_sve_uunpkhi:
3768 case Intrinsic::aarch64_sve_uunpklo:
3769 case Intrinsic::aarch64_sve_sunpkhi:
3770 case Intrinsic::aarch64_sve_sunpklo:
3772 case Intrinsic::aarch64_sve_uzp1:
3774 case Intrinsic::aarch64_sve_zip1:
3775 case Intrinsic::aarch64_sve_zip2:
3777 case Intrinsic::aarch64_sve_ld1_gather_index:
3779 case Intrinsic::aarch64_sve_st1_scatter_index:
3781 case Intrinsic::aarch64_sve_ld1:
3783 case Intrinsic::aarch64_sve_st1:
3785 case Intrinsic::aarch64_sve_sdiv:
3787 case Intrinsic::aarch64_sve_sel:
3789 case Intrinsic::aarch64_sve_srshl:
3791 case Intrinsic::aarch64_sve_dupq_lane:
3793 case Intrinsic::aarch64_sve_insr:
3795 case Intrinsic::aarch64_sve_whilelo:
3797 case Intrinsic::aarch64_sve_ptrue:
3799 case Intrinsic::aarch64_sve_uxtb:
3801 case Intrinsic::aarch64_sve_uxth:
3803 case Intrinsic::aarch64_sve_uxtw:
3805 case Intrinsic::aarch64_sme_in_streaming_mode:
3807 case Intrinsic::aarch64_sve_umin_u:
3809 case Intrinsic::aarch64_sve_orr_u:
3811 case Intrinsic::aarch64_sve_and_z:
3815 return std::nullopt;
3822 SimplifyAndSetOp)
const {
3823 switch (
II.getIntrinsicID()) {
3826 case Intrinsic::aarch64_neon_fcvtxn:
3827 case Intrinsic::aarch64_neon_rshrn:
3828 case Intrinsic::aarch64_neon_sqrshrn:
3829 case Intrinsic::aarch64_neon_sqrshrun:
3830 case Intrinsic::aarch64_neon_sqshrn:
3831 case Intrinsic::aarch64_neon_sqshrun:
3832 case Intrinsic::aarch64_neon_sqxtn:
3833 case Intrinsic::aarch64_neon_sqxtun:
3834 case Intrinsic::aarch64_neon_uqrshrn:
3835 case Intrinsic::aarch64_neon_uqshrn:
3836 case Intrinsic::aarch64_neon_uqxtn:
3837 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3841 return std::nullopt;
3845 return ST->isSVEAvailable() ||
3846 (ST->isSVEorStreamingSVEAvailable() &&
3847 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3856 if (ST->useSVEForFixedLengthVectors() &&
3857 (ST->isSVEAvailable() ||
3858 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3860 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3861 else if (ST->isNeonAvailable())
3866 if (ST->isSVEAvailable() ||
3867 (ST->isSVEorStreamingSVEAvailable() &&
3868 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3876bool AArch64TTIImpl::isSingleExtWideningInstruction(
3878 Type *SrcOverrideTy)
const {
3893 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3896 Type *SrcTy = SrcOverrideTy;
3898 case Instruction::Add:
3899 case Instruction::Sub: {
3908 if (Opcode == Instruction::Sub)
3932 assert(SrcTy &&
"Expected some SrcTy");
3934 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3940 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3942 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3946 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3949Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3951 Type *SrcOverrideTy)
const {
3952 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3953 Opcode != Instruction::Mul)
3963 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3966 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3972 ->getScalarSizeInBits();
3975 unsigned MaxEltSize = 0;
3978 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3979 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3980 MaxEltSize = std::max(EltSize0, EltSize1);
3983 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3984 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3987 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3989 MaxEltSize = DstEltSize / 2;
3990 }
else if (Opcode == Instruction::Mul &&
3998 Known.Zero.countLeadingOnes() >
4003 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
4007 if (MaxEltSize * 2 > DstEltSize)
4025 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
4026 (Src->isScalableTy() && !ST->hasSVE2()))
4036 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4040 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4044 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4045 Src->getScalarSizeInBits() !=
4069 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4085 Src->isIntOrIntVectorTy(1) && !
isPowerOf2_32(SrcVTy->getNumElements()) &&
4087 unsigned NumElts = SrcVTy->getNumElements();
4096 if (
I && !
I->users().empty()) {
4100 auto GetUserAbsorbedCastCost =
4101 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4104 if (
Type *ExtTy = isBinExtWideningInstruction(
4106 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4119 if (isSingleExtWideningInstruction(
4121 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4125 if (Usr->getOpcode() == Instruction::Add) {
4126 if (
I == Usr->getOperand(1) ||
4138 return std::nullopt;
4147 unsigned SrcBits = Src->getScalarSizeInBits();
4150 Dst->getScalarSizeInBits() == 2 * SrcBits &&
4154 return std::nullopt;
4158 bool AllUsersAbsorbCast =
true;
4159 for (
const User *U :
I->users()) {
4161 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4163 AllUsersAbsorbCast =
false;
4166 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4169 if (AllUsersAbsorbCast)
4170 return MaxAbsorbedCost;
4180 Cmp->getParent() ==
I->getParent() &&
4185 EVT SrcTy = TLI->getValueType(
DL, Src);
4186 EVT DstTy = TLI->getValueType(
DL, Dst);
4190 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4200 bool SrcIsFloatOrVec =
4201 SrcLT.second.isVector() || SrcLT.second.isFloatingPoint();
4202 bool DstIsFloatOrVec =
4203 DstLT.second.isVector() || DstLT.second.isFloatingPoint();
4208 if (SrcIsFloatOrVec == DstIsFloatOrVec &&
4209 (SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits() ||
4210 (SrcLT.second.isScalableVector() &&
4211 SrcLT.second.getScalarSizeInBits() != 1 &&
4212 DstLT.second.getScalarSizeInBits() != 1)))
4215 return std::max(SrcLT.first, DstLT.first) *
4218 : ST->getVectorInsertExtractBaseCost());
4227 Instruction::ExtractElement, Src, CostKind, -1,
nullptr,
nullptr);
4229 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind);
4233 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4238 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4267 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4270 ST->useSVEForFixedLengthVectors(WiderTy)) {
4271 std::pair<InstructionCost, MVT> LT =
4273 unsigned NumElements =
4289 const unsigned int SVE_EXT_COST = 1;
4290 const unsigned int SVE_FCVT_COST = 1;
4291 const unsigned int SVE_UNPACK_ONCE = 4;
4292 const unsigned int SVE_UNPACK_TWICE = 16;
4421 SVE_EXT_COST + SVE_FCVT_COST},
4426 SVE_EXT_COST + SVE_FCVT_COST},
4433 SVE_EXT_COST + SVE_FCVT_COST},
4437 SVE_EXT_COST + SVE_FCVT_COST},
4443 SVE_EXT_COST + SVE_FCVT_COST},
4446 SVE_EXT_COST + SVE_FCVT_COST},
4451 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4453 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4463 SVE_EXT_COST + SVE_FCVT_COST},
4468 SVE_EXT_COST + SVE_FCVT_COST},
4481 SVE_EXT_COST + SVE_FCVT_COST},
4485 SVE_EXT_COST + SVE_FCVT_COST},
4497 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4499 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4501 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4503 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4507 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4509 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4525 SVE_EXT_COST + SVE_FCVT_COST},
4530 SVE_EXT_COST + SVE_FCVT_COST},
4541 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4543 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4545 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4547 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4549 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4551 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4555 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4557 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4559 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4561 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4776 if (ST->hasFullFP16())
4788 Src->getScalarType(), CCH, CostKind) +
4796 ST->isSVEorStreamingSVEAvailable() &&
4797 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4799 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4808 Opcode, LegalTy, Src, CCH, CostKind,
I);
4811 return Part1 + Part2;
4818 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4830 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4843 CostKind, Index,
nullptr,
nullptr);
4847 auto DstVT = TLI->getValueType(
DL, Dst);
4848 auto SrcVT = TLI->getValueType(
DL, Src);
4853 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4859 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4869 case Instruction::SExt:
4874 case Instruction::ZExt:
4875 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4888 return Opcode == Instruction::PHI ? 0 : 1;
4897 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4899 assert(Ty->isVectorTy() &&
"This must be a vector type");
4906 if (!LT.second.isVector())
4911 if (LT.second.isFixedLengthVector()) {
4912 unsigned Width = LT.second.getVectorNumElements();
4913 Index = Index % Width;
4920 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4932 if (Index * Ty->getScalarSizeInBits() < 128)
4934 if (Index * Ty->getScalarSizeInBits() < 512 &&
4935 Opcode == Instruction::ExtractElement)
4937 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4938 if (Opcode == Instruction::ExtractElement)
4940 if (Opcode == Instruction::InsertElement)
4949 if (VIC == TTI::VectorInstrContext::Load) {
4950 if (ST->hasFastLD1Single())
4954 : ST->getVectorInsertExtractBaseCost() + 1;
4962 : ST->getVectorInsertExtractBaseCost() + 1;
4986 auto ExtractCanFuseWithFmul = [&]() {
4993 auto IsAllowedScalarTy = [&](
const Type *
T) {
4994 return T->isFloatTy() ||
T->isDoubleTy() ||
4995 (
T->isHalfTy() && ST->hasFullFP16());
4999 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
5002 return BO && BO->getOpcode() == BinaryOperator::FMul &&
5003 !BO->getType()->isVectorTy();
5008 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
5012 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
5021 DenseMap<User *, unsigned> UserToExtractIdx;
5022 for (
auto *U :
Scalar->users()) {
5023 if (!IsUserFMulScalarTy(U))
5027 UserToExtractIdx[
U];
5029 if (UserToExtractIdx.
empty())
5031 for (
auto &[S, U, L] : ScalarUserAndIdx) {
5032 for (
auto *U : S->users()) {
5033 if (UserToExtractIdx.
contains(U)) {
5035 auto *Op0 =
FMul->getOperand(0);
5036 auto *Op1 =
FMul->getOperand(1);
5037 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
5038 UserToExtractIdx[
U] =
L;
5044 for (
auto &[U, L] : UserToExtractIdx) {
5056 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
5057 if (!IsUserFMulScalarTy(U))
5062 const auto *BO = cast<BinaryOperator>(U);
5063 const auto *OtherEE = dyn_cast<ExtractElementInst>(
5064 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
5066 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
5069 return IsExtractLaneEquivalentToZero(
5070 cast<ConstantInt>(OtherEE->getIndexOperand())
5073 OtherEE->getType()->getScalarSizeInBits());
5081 if (Opcode == Instruction::ExtractElement && (
I ||
Scalar) &&
5082 ExtractCanFuseWithFmul())
5087 :
ST->getVectorInsertExtractBaseCost();
5096 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5099 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr,
nullptr,
5107 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr,
Scalar,
5108 ScalarUserAndIdx, VIC);
5115 return getVectorInstrCostHelper(
I.getOpcode(), Ty, CostKind, Index, &
I,
5122 unsigned Index)
const {
5133 : ST->getVectorInsertExtractBaseCost() + 1;
5145 if (ST->hasFastLD1Single()) {
5146 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5147 (VIC == TTI::VectorInstrContext::Load && Insert))
5151 if (Ty->getElementType()->isFloatingPointTy())
5154 unsigned VecInstCost =
5156 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5163 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5164 return std::nullopt;
5165 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5166 return std::nullopt;
5168 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5169 return std::nullopt;
5176 Cost += InstCost(PromotedTy);
5191 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5202 if (Opcode == Instruction::And && CtxI->
hasOneUse() &&
5210 const auto *UI = cast<Instruction>(U);
5211 return is_contained({Instruction::And, Instruction::Or},
5220 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5226 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5227 Op2Info, Args, CtxI);
5233 if (
auto PromotedCost = getFP16BF16PromoteCost(
5234 Ty, CostKind, Op1Info, Op2Info,
true,
5237 [&](
Type *PromotedTy) {
5238 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
5241 return *PromotedCost;
5244 if (Ty->getScalarType()->isFP128Ty())
5252 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5254 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
5255 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
5262 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5272 ST->hasLimited64bitVectorMulBandwidth())
5280 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5283 if (
LT.second == MVT::v2i64) {
5287 return LT.first * Mul64CostFactor;
5300 (getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind) +
5308 if (
LT.second == MVT::nxv2i64)
5309 return LT.first * Mul64CostFactor;
5358 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5361 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5364 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5369 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5373 : (3 * AsrCost + AddCost);
5375 return MulCost + AsrCost + 2 * AddCost;
5377 }
else if (VT.isVector()) {
5388 Cost += 2 * AsrCost;
5393 ? (
LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5397 }
else if (
LT.second == MVT::v2i64) {
5398 return VT.getVectorNumElements() *
5399 getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind,
5406 return MulCost + 2 * AddCost + 2 * AsrCost;
5407 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5412 LT.second.isFixedLengthVector()) {
5418 CostKind, -1,
nullptr,
nullptr);
5420 CostKind, -1,
nullptr,
nullptr);
5422 return ExtractCost + InsertCost +
5434 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
5438 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
5446 bool HasMULH = VT == MVT::i64 ||
LT.second == MVT::nxv2i64 ||
5447 LT.second == MVT::nxv4i32 ||
LT.second == MVT::nxv8i16 ||
5448 LT.second == MVT::nxv16i8;
5449 bool Is128bit =
LT.second.is128BitVector();
5452 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5455 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5458 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5461 (HasMULH ? 0 : ShrCost) +
5462 AddCost * 2 + ShrCost;
5463 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5470 if (!VT.isVector() && VT.getSizeInBits() > 64)
5471 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5474 Opcode, Ty, CostKind, Op1Info, Op2Info);
5490 if (
nullptr != Entry)
5498 FVTy &&
LT.second.isFixedLengthVector()) {
5499 unsigned NumElts = FVTy->getNumElements();
5500 unsigned RegElts =
LT.second.getVectorNumElements();
5502 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5506 if (
LT.second.getScalarType() == MVT::i8)
5508 else if (
LT.second.getScalarType() == MVT::i16)
5521 return (4 + DivCost) * VTy->getNumElements();
5527 -1,
nullptr,
nullptr);
5554 LT.second.isFixedLengthVector())
5555 return 2 *
LT.first + 1;
5567 ((CtxI->hasOneUse() &&
5582 return 2 *
LT.first;
5584 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5590 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5591 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5604 unsigned NumVectorInstToHideOverhead =
5605 ST->getCLOpts().neon_nonconst_stride_overhead;
5606 int MaxMergeDistance = 64;
5610 return NumVectorInstToHideOverhead;
5622 unsigned Opcode1,
unsigned Opcode2)
const {
5625 if (!
Sched.hasInstrSchedModel())
5628 auto GetRThroughput = [&](
unsigned Opcode,
bool Highest) {
5629 std::optional<double> Res;
5631 while (!Worklist.
empty()) {
5635 append_range(Worklist, AArch64_MC::getVariantSchedClassTargets(
5636 SchedClass,
Sched.getProcessorID()));
5642 if (!Res || (Highest ? RThroughput > *Res : RThroughput < *Res))
5647 std::optional<double> RThroughput1 =
5648 GetRThroughput(Opcode1,
true);
5649 std::optional<double> RThroughput2 =
5650 GetRThroughput(Opcode2,
false);
5651 return RThroughput1 && RThroughput2 && *RThroughput1 > *RThroughput2;
5662 const int AmortizationCost = 20;
5670 VecPred = CurrentPred;
5678 static const auto ValidMinMaxTys = {
5679 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5680 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5681 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5685 (ST->hasFullFP16() &&
5691 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5692 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5693 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5694 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5695 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5696 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5697 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5698 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5699 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5700 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5701 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5703 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5704 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5713 if (Opcode == Instruction::FCmp) {
5715 ValTy, CostKind, Op1Info, Op2Info,
false,
5717 false, [&](
Type *PromotedTy) {
5720 CostKind, Op1Info, Op2Info);
5729 return *PromotedCost;
5733 if (LT.second.getScalarType() != MVT::f64 &&
5734 LT.second.getScalarType() != MVT::f32 &&
5735 LT.second.getScalarType() != MVT::f16)
5737 {ValTy, ValTy}, CostKind);
5740 unsigned Factor = 1;
5741 if (!CondTy->isVectorTy() &&
5755 AArch64::FCMEQv4f32))
5767 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5786 Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info,
I);
5790 AArch64::CMEQv4i32))
5798 if (ST->requiresStrictAlign()) {
5803 Options.AllowOverlappingLoads =
true;
5804 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5809 Options.LoadSizes = {8, 4, 2, 1};
5810 Options.AllowedTailExpansions = {3, 5, 6};
5815 return ST->hasSVE();
5821 switch (MICA.
getID()) {
5822 case Intrinsic::masked_scatter:
5823 case Intrinsic::masked_gather:
5825 case Intrinsic::masked_load:
5826 case Intrinsic::masked_store:
5827 case Intrinsic::masked_expandload:
5828 case Intrinsic::masked_compressstore:
5842 if (!LT.first.isValid())
5847 if (VT->getElementType()->isIntegerTy(1))
5853 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5859 if (MICA.
getID() == Intrinsic::masked_expandload) {
5873 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5894 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5895 return MemOpCost * 2;
5904 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5905 "Should be called on only load or stores.");
5907 case Instruction::Load:
5908 return ST->getCLOpts().sve_gather_overhead.value_or(
5909 ST->getGatherOverhead());
5911 case Instruction::Store:
5912 return ST->getCLOpts().sve_scatter_overhead.value_or(
5913 ST->getScatterOverhead());
5924 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5925 MICA.
getID() == Intrinsic::vp_gather)
5927 : Instruction::Store;
5939 if (!LT.first.isValid())
5943 if (!LT.second.isVector() ||
5945 VT->getElementType()->isIntegerTy(1))
5955 ElementCount LegalVF = LT.second.getVectorElementCount();
5958 {TTI::OK_AnyValue, TTI::OP_None},
I);
5974 EVT VT = TLI->getValueType(
DL, Ty,
true);
5976 if (VT == MVT::Other)
5981 if (!LT.first.isValid())
5987 if (VTy->getElementType()->isIntegerTy(1) &&
5988 !VTy->getElementCount().isKnownMultipleOf(
5994 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5995 : Intrinsic::masked_store;
6009 if (Opcode == Instruction::Store)
6013 if (ST->getFixedLoadLatency())
6014 return (LT.first - 1) + ST->getFixedLoadLatency();
6023 if (LT.second.isScalableVector() ||
6024 ST->useSVEForFixedLengthVectors(LT.second)) {
6025 Inst = AArch64::LDR_ZXI;
6026 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
6027 switch (LT.second.getSizeInBits()) {
6029 Inst = AArch64::LDRBui;
6032 Inst = AArch64::LDRHui;
6035 Inst = AArch64::LDRSui;
6038 Inst = AArch64::LDRDui;
6041 Inst = AArch64::LDRQui;
6047 switch (LT.second.getSizeInBits()) {
6049 Inst = AArch64::LDRBBui;
6052 Inst = AArch64::LDRHHui;
6055 Inst = AArch64::LDRWui;
6058 Inst = AArch64::LDRXui;
6066 unsigned SchedClass =
TII->get(Inst).getSchedClass();
6068 ?
Sched.getSchedClassDesc(SchedClass)
6074 return (LT.first - 1) + ST->getLoadLatency();
6077 float NumLoads = (LT.first - 1).
getValue();
6078 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
6079 Sched.computeInstrLatency(*ST, *SCD);
6082 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
6083 LT.second.is128BitVector() && Alignment <
Align(16)) {
6089 const int AmortizationCost = 6;
6091 return LT.first * 2 * AmortizationCost;
6095 if (Ty->isPtrOrPtrVectorTy())
6100 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
6102 if (VT == MVT::v4i8)
6109 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
6110 Alignment !=
Align(1))
6122 if (Remainder != 0) {
6125 while (!TypeWorklist.
empty()) {
6135 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6147 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6148 assert(Factor >= 2 &&
"Invalid interleave factor");
6157 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6161 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6166 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6171 (UseMaskForCond || UseMaskForGaps ||
6172 (Factor > MaxNativeInterleaveFactor &&
6173 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6176 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6179 EC.divideCoefficientBy(Factor));
6185 if (EC.isKnownMultipleOf(Factor) &&
6186 TLI->isLegalInterleavedAccessType(
SubVecTy,
DL, UseScalable))
6187 return Factor * TLI->getNumInterleavedAccesses(
SubVecTy,
DL, UseScalable);
6192 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6198 if (UseMaskForCond) {
6199 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6200 : Intrinsic::masked_store;
6220 if (Opcode == Instruction::Store && Factor == 4 &&
6221 SubVecCost.second.getScalarSizeInBits() ==
6222 (4 * ResultCost.second.getScalarSizeInBits()))
6223 LegalizationCost *= 4;
6225 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6231 UseMaskForCond, UseMaskForGaps);
6238 for (
auto *
I : Tys) {
6239 if (!
I->isVectorTy())
6250 Align Alignment)
const {
6260 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6261 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6273 Size.getFixedValue() <= 16;
6278 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6279 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6302 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6305 TypeSize VectorWidth =
DL.getTypeSizeInBits(VectorTy);
6312 unsigned NumSVEVectors = (VectorWidth * NumVectors).getKnownMinValue() /
6314 return NumSVEVectors == 2 || NumSVEVectors == 4;
6325 bool HasUnorderedReductions)
const {
6328 return ST->getMaxInterleaveFactor();
6338 enum { MaxStridedLoads = 7 };
6340 int StridedLoads = 0;
6343 for (
const auto BB : L->blocks()) {
6344 for (
auto &
I : *BB) {
6350 if (L->isLoopInvariant(PtrValue))
6355 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6364 if (StridedLoads > MaxStridedLoads / 2)
6365 return StridedLoads;
6368 return StridedLoads;
6371 int StridedLoads = countStridedLoads(L, SE);
6373 <<
" strided loads\n");
6389 unsigned *FinalSize) {
6393 for (
auto *BB : L->getBlocks()) {
6394 for (
auto &
I : *BB) {
6400 if (!Cost.isValid())
6404 if (LoopCost > Budget)
6426 if (MaxTC > 0 && MaxTC <= 32)
6437 if (Blocks.
size() != 2)
6459 if (!L->isInnermost() || L->getNumBlocks() > 8)
6463 if (!L->getExitBlock())
6469 bool HasParellelizableReductions =
6470 L->getNumBlocks() == 1 &&
6471 any_of(L->getHeader()->phis(),
6473 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6476 if (HasParellelizableReductions &&
6498 if (HasParellelizableReductions) {
6509 if (Header == Latch) {
6512 unsigned Width = 10;
6518 unsigned MaxInstsPerLine = 16;
6520 unsigned BestUC = 1;
6521 unsigned SizeWithBestUC = BestUC *
Size;
6523 unsigned SizeWithUC = UC *
Size;
6524 if (SizeWithUC > 48)
6526 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6527 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6529 SizeWithBestUC = BestUC *
Size;
6539 for (
auto *BB : L->blocks()) {
6540 for (
auto &
I : *BB) {
6550 for (
auto *U :
I.users())
6552 LoadedValuesPlus.
insert(U);
6559 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6585 auto *I = dyn_cast<Instruction>(V);
6586 return I && DependsOnLoopLoad(I, Depth + 1);
6593 DependsOnLoopLoad(
I, 0)) {
6625 if (L->getLoopDepth() > 1)
6636 for (
auto *BB : L->getBlocks()) {
6637 for (
auto &
I : *BB) {
6641 if (IsVectorized &&
I.getType()->isVectorTy())
6652 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6661 if (ST->isAppleMLike())
6663 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6664 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6685 !ST->getSchedModel().isOutOfOrder()) {
6697 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6708 bool CanCreate)
const {
6712 case Intrinsic::aarch64_neon_st1x2:
6713 case Intrinsic::aarch64_neon_st1x3:
6714 case Intrinsic::aarch64_neon_st1x4:
6715 case Intrinsic::aarch64_neon_st2:
6716 case Intrinsic::aarch64_neon_st3:
6717 case Intrinsic::aarch64_neon_st4: {
6720 if (!CanCreate || !ST)
6722 unsigned NumElts = Inst->
arg_size() - 1;
6723 if (ST->getNumElements() != NumElts)
6725 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6731 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6733 Res = Builder.CreateInsertValue(Res, L, i);
6737 case Intrinsic::aarch64_neon_ld1x2:
6738 case Intrinsic::aarch64_neon_ld1x3:
6739 case Intrinsic::aarch64_neon_ld1x4:
6740 case Intrinsic::aarch64_neon_ld2:
6741 case Intrinsic::aarch64_neon_ld3:
6742 case Intrinsic::aarch64_neon_ld4:
6743 if (Inst->
getType() == ExpectedType)
6754 case Intrinsic::aarch64_neon_ld1x2:
6755 case Intrinsic::aarch64_neon_ld1x3:
6756 case Intrinsic::aarch64_neon_ld1x4:
6757 case Intrinsic::aarch64_neon_ld2:
6758 case Intrinsic::aarch64_neon_ld3:
6759 case Intrinsic::aarch64_neon_ld4:
6760 Info.ReadMem =
true;
6761 Info.WriteMem =
false;
6764 case Intrinsic::aarch64_neon_st1x2:
6765 case Intrinsic::aarch64_neon_st1x3:
6766 case Intrinsic::aarch64_neon_st1x4:
6767 case Intrinsic::aarch64_neon_st2:
6768 case Intrinsic::aarch64_neon_st3:
6769 case Intrinsic::aarch64_neon_st4:
6770 Info.ReadMem =
false;
6771 Info.WriteMem =
true;
6780 case Intrinsic::aarch64_neon_ld1x2:
6781 case Intrinsic::aarch64_neon_st1x2:
6782 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6784 case Intrinsic::aarch64_neon_ld1x3:
6785 case Intrinsic::aarch64_neon_st1x3:
6786 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6788 case Intrinsic::aarch64_neon_ld1x4:
6789 case Intrinsic::aarch64_neon_st1x4:
6790 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6792 case Intrinsic::aarch64_neon_ld2:
6793 case Intrinsic::aarch64_neon_st2:
6794 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6796 case Intrinsic::aarch64_neon_ld3:
6797 case Intrinsic::aarch64_neon_st3:
6798 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6800 case Intrinsic::aarch64_neon_ld4:
6801 case Intrinsic::aarch64_neon_st4:
6802 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6814 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6815 bool Considerable =
false;
6816 AllowPromotionWithoutCommonHeader =
false;
6819 Type *ConsideredSExtType =
6821 if (
I.getType() != ConsideredSExtType)
6825 for (
const User *U :
I.users()) {
6827 Considerable =
true;
6831 if (GEPInst->getNumOperands() > 2) {
6832 AllowPromotionWithoutCommonHeader =
true;
6837 return Considerable;
6888 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6898 return LegalizationCost + 2;
6908 LegalizationCost *= LT.first - 1;
6911 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6920 return LegalizationCost + 2;
6928 std::optional<FastMathFlags> FMF,
6944 return BaseCost + FixedVTy->getNumElements();
6958 MVT MTy = LT.second;
6963 int ISD = TLI->InstructionOpcodeToISD(Opcode);
7011 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
7012 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
7024 return (LT.first - 1) +
Log2_32(NElts);
7029 return (LT.first - 1) + Entry->Cost;
7041 if (LT.first != 1) {
7047 ExtraCost *= LT.first - 1;
7050 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
7051 return Cost + ExtraCost;
7059 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
7061 EVT VecVT = TLI->getValueType(
DL, VecTy);
7062 EVT ResVT = TLI->getValueType(
DL, ResTy);
7064 if (IsUnsigned && Opcode == Instruction::Add &&
7079 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7081 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
7083 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
7085 return (LT.first - 1) * 2 + 2;
7096 EVT VecVT = TLI->getValueType(
DL, VecTy);
7097 EVT ResVT = TLI->getValueType(
DL, ResTy);
7100 RedOpcode == Instruction::Add) {
7106 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7108 return LT.first + 2;
7143 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
7144 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7158 if (LT.second.getScalarType() == MVT::i1) {
7167 assert(Entry &&
"Illegal Type for Splice");
7168 LegalizationCost += Entry->Cost;
7169 return LegalizationCost * LT.first;
7173 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7182 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7183 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7189 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7190 if (!FMF->allowReassoc() || !FMF->allowContract())
7194 "FastMathFlags only apply to floating-point partial reductions");
7198 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7199 "Unexpected values for OpBExtend or InputTypeB");
7203 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7204 InputTypeA != InputTypeB))
7215 assert(!OpBExtend &&
"Extended second operand without extended first.");
7216 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7222 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7225 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7238 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7247 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7253 std::pair<InstructionCost, MVT> AccumLT =
7255 std::pair<InstructionCost, MVT> InputLT =
7259 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7260 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7261 (AccumLT.second.isFixedLengthVector() &&
7262 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7266 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7274 if (AccumLT.second.getScalarType() == MVT::i32 &&
7275 InputLT.second.getScalarType() == MVT::i8) {
7277 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7278 return Cost + INegCost;
7280 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7281 return Cost + INegCost;
7286 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7287 return Cost * 3 + INegCost;
7290 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7292 if (AccumLT.second.getScalarType() == MVT::i64 &&
7293 InputLT.second.getScalarType() == MVT::i16)
7294 return Cost + INegCost;
7297 if (AccumLT.second.getScalarType() == MVT::i32 &&
7298 InputLT.second.getScalarType() == MVT::i16 &&
7299 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7302 if (AccumLT.second.getScalarType() == MVT::i64 &&
7303 InputLT.second.getScalarType() == MVT::i8)
7306 return Cost + INegCost;
7309 if (AccumLT.second.getScalarType() == MVT::i16 &&
7310 InputLT.second.getScalarType() == MVT::i8 &&
7311 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7329 if ((!BinOp || IsSExtMul) && !IsSub &&
7330 AccumLT.second.getScalarType() == MVT::i64 &&
7331 InputLT.second.getScalarType() == MVT::i8 &&
7332 IsSupported(
false, ST->hasDotProd()))
7337 if (Opcode == Instruction::FAdd && !IsSub &&
7338 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7339 AccumLT.second.getScalarType() == MVT::f32 &&
7340 InputLT.second.getScalarType() == MVT::f16)
7344 if (Ratio == 2 && !IsUSDot) {
7345 MVT InVT = InputLT.second.getScalarType();
7349 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7351 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7354 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7358 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7359 InVT == MVT::bf16 && IsSub)
7369 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7370 return Cost * 2 + FNegCost;
7374 AccumType, VF, OpAExtend, OpBExtend,
7375 BinOp, CostKind, FMF);
7385 "Expected the Mask to match the return size if given");
7387 "Expected the same scalar types");
7393 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7394 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7395 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7403 return std::max<InstructionCost>(1, LT.first / 4);
7411 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7413 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7416 unsigned TpNumElts = Mask.size();
7417 unsigned LTNumElts = LT.second.getVectorNumElements();
7418 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7420 LT.second.getVectorElementCount());
7422 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7424 for (
unsigned N = 0;
N < NumVecs;
N++) {
7428 unsigned Source1 = -1U, Source2 = -1U;
7429 unsigned NumSources = 0;
7430 for (
unsigned E = 0; E < LTNumElts; E++) {
7431 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7440 unsigned Source = MaskElt / LTNumElts;
7441 if (NumSources == 0) {
7444 }
else if (NumSources == 1 && Source != Source1) {
7447 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7453 if (Source == Source1)
7455 else if (Source == Source2)
7456 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7465 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7476 NTp, NTp, CostKind, NMask, 0,
nullptr, Args,
7479 Result.first->second = NCost;
7493 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7494 if (LT.second.getFixedSizeInBits() >= 128 &&
7496 LT.second.getVectorNumElements() / 2) {
7499 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7513 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7516 return M.value() < 0 || M.value() == (int)M.index();
7522 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7523 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7532 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7533 ST->isSVEorStreamingSVEAvailable() &&
7538 if (ST->isSVEorStreamingSVEAvailable() &&
7552 if (IsLoad && LT.second.isVector() &&
7554 LT.second.getVectorElementCount()))
7560 if (Mask.size() == 4 &&
7562 (SrcTy->getScalarSizeInBits() == 16 ||
7563 SrcTy->getScalarSizeInBits() == 32) &&
7564 all_of(Mask, [](
int E) {
return E < 8; }))
7570 if (LT.second.isFixedLengthVector() &&
7571 LT.second.getVectorNumElements() == Mask.size() &&
7577 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7578 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7579 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7580 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7581 LT.second.getVectorNumElements(), 16) ||
7582 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7583 LT.second.getVectorNumElements(), 32) ||
7584 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7585 LT.second.getVectorNumElements(), 64) ||
7588 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7717 return LT.first * Entry->Cost;
7726 LT.second.getSizeInBits() <= 128 && SubTp) {
7728 if (SubLT.second.isVector()) {
7729 int NumElts = LT.second.getVectorNumElements();
7730 int NumSubElts = SubLT.second.getVectorNumElements();
7731 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7737 if (IsExtractSubvector)
7758 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7769 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7770 ST->useFixedOverScalableIfEqualCost());
7774 return ST->getEpilogueVectorizationMinVF();
7809 unsigned NumInsns = 0;
7811 NumInsns += BB->size();
7815 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7821 int64_t Scale,
unsigned AddrSpace)
const {
7844 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7849 if (
I->getOpcode() == Instruction::Or &&
7853 if (
I->getOpcode() == Instruction::Add ||
7854 I->getOpcode() == Instruction::Sub)
7870 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7871 return std::tie(
C1.NumRegs,
C1.Insns,
C1.NumPrePostIndex,
C1.NumBaseAdds,
7872 C1.AddRecCost,
C1.NumIVMuls,
C1.ScaleCost,
C1.ImmCost,
7883 return all_equal(Shuf->getShuffleMask());
7890 bool AllowSplat =
false) {
7895 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7896 auto *FullTy = FullV->
getType();
7897 auto *HalfTy = HalfV->getType();
7899 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7902 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7905 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7909 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7923 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7924 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7938 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7939 (M2Start != 0 && M2Start != (NumElements / 2)))
7941 if (S1Op1 && S2Op1 && M1Start != M2Start)
7951 return Ext->getType()->getScalarSizeInBits() ==
7952 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7966 Value *VectorOperand =
nullptr;
7983 if (!
GEP ||
GEP->getNumOperands() != 2)
7987 Value *Offsets =
GEP->getOperand(1);
7990 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7996 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7997 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7998 Ops.push_back(&
GEP->getOperandUse(1));
8038 switch (
II->getIntrinsicID()) {
8039 case Intrinsic::aarch64_neon_smull:
8040 case Intrinsic::aarch64_neon_umull:
8043 Ops.push_back(&
II->getOperandUse(0));
8044 Ops.push_back(&
II->getOperandUse(1));
8049 case Intrinsic::fma:
8050 case Intrinsic::fmuladd:
8057 Ops.push_back(&
II->getOperandUse(0));
8059 Ops.push_back(&
II->getOperandUse(1));
8062 case Intrinsic::aarch64_neon_sqdmull:
8063 case Intrinsic::aarch64_neon_sqdmulh:
8064 case Intrinsic::aarch64_neon_sqrdmulh:
8067 Ops.push_back(&
II->getOperandUse(0));
8069 Ops.push_back(&
II->getOperandUse(1));
8070 return !
Ops.empty();
8071 case Intrinsic::aarch64_neon_fmlal:
8072 case Intrinsic::aarch64_neon_fmlal2:
8073 case Intrinsic::aarch64_neon_fmlsl:
8074 case Intrinsic::aarch64_neon_fmlsl2:
8077 Ops.push_back(&
II->getOperandUse(1));
8079 Ops.push_back(&
II->getOperandUse(2));
8080 return !
Ops.empty();
8081 case Intrinsic::aarch64_sve_ptest_first:
8082 case Intrinsic::aarch64_sve_ptest_last:
8084 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
8085 Ops.push_back(&
II->getOperandUse(0));
8086 return !
Ops.empty();
8087 case Intrinsic::aarch64_sme_write_horiz:
8088 case Intrinsic::aarch64_sme_write_vert:
8089 case Intrinsic::aarch64_sme_writeq_horiz:
8090 case Intrinsic::aarch64_sme_writeq_vert: {
8092 if (!Idx || Idx->getOpcode() != Instruction::Add)
8094 Ops.push_back(&
II->getOperandUse(1));
8097 case Intrinsic::aarch64_sme_read_horiz:
8098 case Intrinsic::aarch64_sme_read_vert:
8099 case Intrinsic::aarch64_sme_readq_horiz:
8100 case Intrinsic::aarch64_sme_readq_vert:
8101 case Intrinsic::aarch64_sme_ld1b_vert:
8102 case Intrinsic::aarch64_sme_ld1h_vert:
8103 case Intrinsic::aarch64_sme_ld1w_vert:
8104 case Intrinsic::aarch64_sme_ld1d_vert:
8105 case Intrinsic::aarch64_sme_ld1q_vert:
8106 case Intrinsic::aarch64_sme_st1b_vert:
8107 case Intrinsic::aarch64_sme_st1h_vert:
8108 case Intrinsic::aarch64_sme_st1w_vert:
8109 case Intrinsic::aarch64_sme_st1d_vert:
8110 case Intrinsic::aarch64_sme_st1q_vert:
8111 case Intrinsic::aarch64_sme_ld1b_horiz:
8112 case Intrinsic::aarch64_sme_ld1h_horiz:
8113 case Intrinsic::aarch64_sme_ld1w_horiz:
8114 case Intrinsic::aarch64_sme_ld1d_horiz:
8115 case Intrinsic::aarch64_sme_ld1q_horiz:
8116 case Intrinsic::aarch64_sme_st1b_horiz:
8117 case Intrinsic::aarch64_sme_st1h_horiz:
8118 case Intrinsic::aarch64_sme_st1w_horiz:
8119 case Intrinsic::aarch64_sme_st1d_horiz:
8120 case Intrinsic::aarch64_sme_st1q_horiz: {
8122 if (!Idx || Idx->getOpcode() != Instruction::Add)
8124 Ops.push_back(&
II->getOperandUse(3));
8127 case Intrinsic::aarch64_neon_pmull:
8130 Ops.push_back(&
II->getOperandUse(0));
8131 Ops.push_back(&
II->getOperandUse(1));
8133 case Intrinsic::aarch64_neon_pmull64:
8135 II->getArgOperand(1)))
8137 Ops.push_back(&
II->getArgOperandUse(0));
8138 Ops.push_back(&
II->getArgOperandUse(1));
8140 case Intrinsic::masked_gather:
8143 Ops.push_back(&
II->getArgOperandUse(0));
8145 case Intrinsic::masked_scatter:
8148 Ops.push_back(&
II->getArgOperandUse(1));
8155 auto ShouldSinkCondition = [](
Value *
Cond,
8160 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8164 Ops.push_back(&
II->getOperandUse(0));
8168 switch (
I->getOpcode()) {
8169 case Instruction::Store: {
8172 if (!
SI->isSimple() || !
II)
8181 Ops.push_back(&
SI->getOperandUse(0));
8186 case Instruction::GetElementPtr:
8187 case Instruction::Add:
8188 case Instruction::Sub:
8190 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8192 Ops.push_back(&
I->getOperandUse(
Op));
8197 case Instruction::Select: {
8198 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8201 Ops.push_back(&
I->getOperandUse(0));
8204 case Instruction::UncondBr:
8206 case Instruction::CondBr: {
8210 Ops.push_back(&
I->getOperandUse(0));
8213 case Instruction::FMul:
8218 Ops.push_back(&
I->getOperandUse(0));
8220 Ops.push_back(&
I->getOperandUse(1));
8230 case Instruction::Xor:
8233 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8235 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8240 case Instruction::And:
8241 case Instruction::Or:
8244 if (
I->getOpcode() == Instruction::Or &&
8249 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8252 for (
auto &
Op :
I->operands()) {
8264 Ops.push_back(&Not);
8265 Ops.push_back(&InsertElt);
8275 if (!
I->getType()->isVectorTy())
8276 return !
Ops.empty();
8278 switch (
I->getOpcode()) {
8279 case Instruction::Sub:
8280 case Instruction::Add: {
8289 Ops.push_back(&Ext1->getOperandUse(0));
8290 Ops.push_back(&Ext2->getOperandUse(0));
8293 Ops.push_back(&
I->getOperandUse(0));
8294 Ops.push_back(&
I->getOperandUse(1));
8298 case Instruction::Or: {
8301 if (ST->hasNEON()) {
8308 Ops.push_back(&
I->getOperandUse(0));
8309 Ops.push_back(&
I->getOperandUse(1));
8317 case Instruction::Mul: {
8318 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8321 if (Ty->isScalableTy())
8325 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8328 int NumZExts = 0, NumSExts = 0;
8329 for (
auto &
Op :
I->operands()) {
8336 auto *ExtOp = Ext->getOperand(0);
8337 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8338 Ops.push_back(&Ext->getOperandUse(0));
8346 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8347 I->getType()->getScalarSizeInBits())
8384 if (!ElementConstant || !ElementConstant->
isZero())
8387 unsigned Opcode = OperandInstr->
getOpcode();
8388 if (Opcode == Instruction::SExt)
8390 else if (Opcode == Instruction::ZExt)
8395 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8405 Ops.push_back(&Insert->getOperandUse(1));
8411 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8415 if (!ShouldSinkSplatForIndexedVariant(
I))
8420 Ops.push_back(&
I->getOperandUse(0));
8422 Ops.push_back(&
I->getOperandUse(1));
8424 return !
Ops.empty();
8426 case Instruction::FMul: {
8428 if (
I->getType()->isScalableTy())
8429 return !
Ops.empty();
8433 return !
Ops.empty();
8437 Ops.push_back(&
I->getOperandUse(0));
8439 Ops.push_back(&
I->getOperandUse(1));
8440 return !
Ops.empty();
8449 Align Alignment)
const {
8450 if (!(ST->isSVEAvailable() ||
8451 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8455 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8462 if (!LT.first.isValid() || !LT.second.isVector())
8467 switch (LT.second.SimpleTy) {
const TargetLowering & TLI
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")
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
SmallVector< MachineOperand, 4 > Cond
static uint64_t getBits(uint64_t Val, int Start, int End)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
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
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops, const LoopInfo *LI) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
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
bool shouldMaximizeVectorBandwidth(TargetTransformInfo::VectorKind K, Type *ElementTy) 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 isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
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.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
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.
LLVM_ABI 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
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
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.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
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 bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
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.
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))
FNeg_match< OpTy, true > m_FNegOrFSubNegZero(const OpTy &X)
Match fneg X or fsub -0.0, 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)
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.
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,...
LLVM_ABI unsigned getInterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.interleaveN intrinsics.
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 isScalableVectorOf(EVT EltVT) const
Return true if this is a scalable vector with matching element type.
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.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isScalableVT() const
Return true if the type is a scalable type.
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*...