24#include "llvm/IR/IntrinsicsAArch64.h"
36#define DEBUG_TYPE "aarch64tti"
39class TailFoldingOption {
54 bool NeedsDefault =
true;
58 void setNeedsDefault(
bool V) { NeedsDefault = V; }
74 "Initial bits should only include one of "
75 "(disabled|all|simple|default)");
76 Bits = NeedsDefault ? DefaultBits : InitialBits;
84 errs() <<
"invalid argument '" << Opt
85 <<
"' to -sve-tail-folding=; the option should be of the form\n"
86 " (disabled|all|default|simple)[+(reductions|recurrences"
87 "|reverse|noreductions|norecurrences|noreverse)]\n";
93 void operator=(
const std::string &Val) {
102 setNeedsDefault(
false);
107 unsigned StartIdx = 1;
108 if (TailFoldTypes[0] ==
"disabled")
110 else if (TailFoldTypes[0] ==
"all")
112 else if (TailFoldTypes[0] ==
"default")
113 setNeedsDefault(
true);
114 else if (TailFoldTypes[0] ==
"simple")
121 for (
unsigned I = StartIdx;
I < TailFoldTypes.
size();
I++) {
122 if (TailFoldTypes[
I] ==
"reductions")
124 else if (TailFoldTypes[
I] ==
"recurrences")
126 else if (TailFoldTypes[
I] ==
"reverse")
128 else if (TailFoldTypes[
I] ==
"noreductions")
130 else if (TailFoldTypes[
I] ==
"norecurrences")
132 else if (TailFoldTypes[
I] ==
"noreverse")
144 return (
getBits(DefaultBits) & Required) == Required;
154 "Control the use of vectorisation using tail-folding for SVE where the"
155 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
156 "\ndisabled (Initial) No loop types will vectorize using "
158 "\ndefault (Initial) Uses the default tail-folding settings for "
160 "\nall (Initial) All legal loop types will vectorize using "
162 "\nsimple (Initial) Use tail-folding for simple loops (not "
163 "reductions or recurrences)"
164 "\nreductions Use tail-folding for loops containing reductions"
165 "\nnoreductions Inverse of above"
166 "\nrecurrences Use tail-folding for loops containing fixed order "
168 "\nnorecurrences Inverse of above"
169 "\nreverse Use tail-folding for loops requiring reversed "
171 "\nnoreverse Inverse of above"),
180 bool ConsiderSM)
const {
181 if (!ConsiderZA && !ConsiderZT && !ConsiderSM)
184 bool IsAlwaysInline =
F->hasFnAttribute(Attribute::AlwaysInline);
191 bool AssumeVScaleIsEquivalent =
192 F->getReturnType()->isScalableTy() ||
193 any_of(
F->getFunctionType()->params(),
194 [](
const Type *
T) { return T->isScalableTy(); });
202 if (CB->isInlineAsm())
205 if (
CallAttrs.callee().isSMEABIRoutine())
214 if (ConsiderSM &&
CallAttrs.callee().hasStreamingCompatibleInterface())
226 return isa<FixedVectorType>(V->getType());
231 unsigned IID =
II->getIntrinsicID();
239 case Intrinsic::masked_gather:
240 case Intrinsic::masked_scatter:
241 case Intrinsic::masked_compressstore:
242 case Intrinsic::experimental_vector_histogram_add:
246 if (
I.getOperand(0)->getType()->isScalableTy())
249 case Intrinsic::vscale:
250 if (!AssumeVScaleIsEquivalent)
258 if (!AssumeVScaleIsEquivalent &&
259 (
I.getType()->isScalableTy() ||
262 [](
const Value *V) { return V->getType()->isScalableTy(); }) ||
264 .getSourceElementType()
277 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
278 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
279 FeatureStr.
split(Features,
",");
295 return F.hasFnAttribute(
"fmv-features");
347 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
348 CallAttrs.callee().hasStreamingInterfaceOrBody())
356 if (
CallAttrs.callee().hasStreamingBody()) {
361 bool ConsiderZA =
CallAttrs.requiresZASave();
362 bool ConsiderZT =
CallAttrs.requiresPreservingZT0() ||
363 CallAttrs.requiresPreservingAllZAState();
364 bool ConsiderSM =
CallAttrs.requiresSMChange();
369 if (ConsiderSM && (Caller->isStrictFP() || Callee->isStrictFP()))
393 auto FVTy = dyn_cast<FixedVectorType>(Ty);
395 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
404 unsigned DefaultCallPenalty)
const {
429 if (
F ==
Call.getCaller())
430 return ST->getCLOpts().call_penalty_sm_change * DefaultCallPenalty;
432 return ST->getCLOpts().inline_call_penalty_sm_change * DefaultCallPenalty;
435 return DefaultCallPenalty;
446 ST->isSVEorStreamingSVEAvailable() &&
447 !ST->disableMaximizeScalableBandwidth();
471 assert(Ty->isIntegerTy());
473 unsigned BitSize = Ty->getPrimitiveSizeInBits();
480 ImmVal =
Imm.sext((BitSize + 63) & ~0x3fU);
485 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
491 return std::max<InstructionCost>(1,
Cost);
498 assert(Ty->isIntegerTy());
500 unsigned BitSize = Ty->getPrimitiveSizeInBits();
506 unsigned ImmIdx = ~0U;
510 case Instruction::GetElementPtr:
515 case Instruction::Store:
518 case Instruction::Add:
519 case Instruction::Sub:
520 case Instruction::Mul:
521 case Instruction::UDiv:
522 case Instruction::SDiv:
523 case Instruction::URem:
524 case Instruction::SRem:
525 case Instruction::And:
526 case Instruction::Or:
527 case Instruction::Xor:
528 case Instruction::ICmp:
532 case Instruction::Shl:
533 case Instruction::LShr:
534 case Instruction::AShr:
538 case Instruction::Trunc:
539 case Instruction::ZExt:
540 case Instruction::SExt:
541 case Instruction::IntToPtr:
542 case Instruction::PtrToInt:
543 case Instruction::BitCast:
544 case Instruction::PHI:
545 case Instruction::Call:
546 case Instruction::Select:
547 case Instruction::Ret:
548 case Instruction::Load:
553 int NumConstants = (BitSize + 63) / 64;
566 assert(Ty->isIntegerTy());
568 unsigned BitSize = Ty->getPrimitiveSizeInBits();
577 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
583 case Intrinsic::sadd_with_overflow:
584 case Intrinsic::uadd_with_overflow:
585 case Intrinsic::ssub_with_overflow:
586 case Intrinsic::usub_with_overflow:
587 case Intrinsic::smul_with_overflow:
588 case Intrinsic::umul_with_overflow:
590 int NumConstants = (BitSize + 63) / 64;
597 case Intrinsic::experimental_stackmap:
598 if ((Idx < 2) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
601 case Intrinsic::experimental_patchpoint_void:
602 case Intrinsic::experimental_patchpoint:
603 if ((Idx < 4) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
606 case Intrinsic::experimental_gc_statepoint:
607 if ((Idx < 5) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
617 if (TyWidth == 32 || TyWidth == 64)
626 return ST->getMispredictionPenalty();
647 unsigned TotalHistCnts = 1;
657 unsigned EC = VTy->getElementCount().getKnownMinValue();
662 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
664 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
668 TotalHistCnts = EC / NaturalVectorWidth;
670 return InstructionCost(ST->getCLOpts().base_histcnt_cost * TotalHistCnts);
687 !
is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
691 switch (ICA.
getID()) {
692 case Intrinsic::experimental_vector_histogram_add: {
699 case Intrinsic::experimental_vector_histogram_uadd_sat:
700 case Intrinsic::experimental_vector_histogram_umax:
701 case Intrinsic::experimental_vector_histogram_umin:
704 case Intrinsic::clmul: {
709 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
713 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
718 -1,
nullptr,
nullptr) *
721 -1,
nullptr,
nullptr);
725 if (LT.second.SimpleTy == MVT::nxv2i64)
726 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
729 if (ST->hasSVE2() || ST->hasSME()) {
730 switch (LT.second.SimpleTy) {
745 if (LT.second.SimpleTy == MVT::nxv2i64)
749 switch (LT.second.SimpleTy) {
759 -1,
nullptr,
nullptr) *
762 -1,
nullptr,
nullptr));
771 return LT.first * 11;
773 return LT.first * 14;
780 case Intrinsic::smulh:
781 case Intrinsic::umulh: {
787 if (RetTy->getScalarSizeInBits() > 64)
801 return MulCost + ExtraCost;
806 return LT.first + ExtraCost;
822 return LT.first * Entry->Cost + ExtraCost;
826 case Intrinsic::umin:
827 case Intrinsic::umax:
828 case Intrinsic::smin:
829 case Intrinsic::smax: {
830 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
831 MVT::v8i16, MVT::v2i32, MVT::v4i32,
832 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
839 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
840 EVT VT = TLI->getValueType(
DL, RetTy,
true);
841 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
842 return LT.first * (IsSigned ? 5 : 3);
844 if (LT.second == MVT::v2i64)
850 case Intrinsic::scmp:
851 case Intrinsic::ucmp: {
853 {Intrinsic::scmp, MVT::i32, 3},
854 {Intrinsic::scmp, MVT::i64, 3},
855 {Intrinsic::scmp, MVT::v8i8, 3},
856 {Intrinsic::scmp, MVT::v16i8, 3},
857 {Intrinsic::scmp, MVT::v4i16, 3},
858 {Intrinsic::scmp, MVT::v8i16, 3},
859 {Intrinsic::scmp, MVT::v2i32, 3},
860 {Intrinsic::scmp, MVT::v4i32, 3},
861 {Intrinsic::scmp, MVT::v1i64, 3},
862 {Intrinsic::scmp, MVT::v2i64, 3},
868 return Entry->Cost * LT.first;
871 case Intrinsic::sadd_sat:
872 case Intrinsic::ssub_sat:
873 case Intrinsic::uadd_sat:
874 case Intrinsic::usub_sat: {
875 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
876 MVT::v8i16, MVT::v2i32, MVT::v4i32,
882 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
884 return LT.first * Instrs;
889 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
890 return LT.first * Instrs;
894 case Intrinsic::abs: {
895 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
896 MVT::v8i16, MVT::v2i32, MVT::v4i32,
897 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
898 MVT::nxv4i32, MVT::nxv2i64};
904 case Intrinsic::bswap: {
905 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
906 MVT::v4i32, MVT::v2i64};
909 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
914 case Intrinsic::fmuladd: {
919 (EltTy->
isHalfTy() && ST->hasFullFP16()))
923 case Intrinsic::stepvector: {
932 Cost += AddCost * (LT.first - 1);
936 case Intrinsic::vector_extract:
937 case Intrinsic::vector_insert: {
950 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
951 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
959 getTLI()->getTypeConversion(
C, SubVecVT);
961 getTLI()->getTypeConversion(
C, VecVT);
969 case Intrinsic::bitreverse: {
971 {Intrinsic::bitreverse, MVT::i32, 1},
972 {Intrinsic::bitreverse, MVT::i64, 1},
973 {Intrinsic::bitreverse, MVT::v8i8, 1},
974 {Intrinsic::bitreverse, MVT::v16i8, 1},
975 {Intrinsic::bitreverse, MVT::v4i16, 2},
976 {Intrinsic::bitreverse, MVT::v8i16, 2},
977 {Intrinsic::bitreverse, MVT::v2i32, 2},
978 {Intrinsic::bitreverse, MVT::v4i32, 2},
979 {Intrinsic::bitreverse, MVT::v1i64, 2},
980 {Intrinsic::bitreverse, MVT::v2i64, 2},
988 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
989 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
990 return LegalisationCost.first * Entry->Cost + 1;
992 return LegalisationCost.first * Entry->Cost;
996 case Intrinsic::pdep:
997 case Intrinsic::pext: {
998 unsigned BW = RetTy->getScalarSizeInBits();
999 if (!RetTy->isVectorTy() && ST->isSVEBitPermAvailable() && BW <= 64) {
1013 case Intrinsic::ctpop: {
1015 MVT MTy = LT.second;
1017 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
1020 return LT.first + ExtraCost;
1022 if (!ST->hasNEON()) {
1052 RetTy->getScalarSizeInBits()
1055 return LT.first * Entry->Cost + ExtraCost;
1059 case Intrinsic::sadd_with_overflow:
1060 case Intrinsic::uadd_with_overflow:
1061 case Intrinsic::ssub_with_overflow:
1062 case Intrinsic::usub_with_overflow:
1063 case Intrinsic::smul_with_overflow:
1064 case Intrinsic::umul_with_overflow: {
1066 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
1067 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
1068 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
1069 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
1070 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
1071 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
1072 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
1073 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
1074 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
1075 {Intrinsic::usub_with_overflow, MVT::i8, 3},
1076 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
1077 {Intrinsic::usub_with_overflow, MVT::i16, 3},
1078 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
1079 {Intrinsic::usub_with_overflow, MVT::i32, 1},
1080 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
1081 {Intrinsic::usub_with_overflow, MVT::i64, 1},
1082 {Intrinsic::smul_with_overflow, MVT::i8, 5},
1083 {Intrinsic::umul_with_overflow, MVT::i8, 4},
1084 {Intrinsic::smul_with_overflow, MVT::i16, 5},
1085 {Intrinsic::umul_with_overflow, MVT::i16, 4},
1086 {Intrinsic::smul_with_overflow, MVT::i32, 2},
1087 {Intrinsic::umul_with_overflow, MVT::i32, 2},
1088 {Intrinsic::smul_with_overflow, MVT::i64, 3},
1089 {Intrinsic::umul_with_overflow, MVT::i64, 3},
1091 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
1098 case Intrinsic::fptosi_sat:
1099 case Intrinsic::fptoui_sat: {
1102 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
1104 EVT MTy = TLI->getValueType(
DL, RetTy);
1107 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
1108 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
1109 LT.second == MVT::v2f64)) {
1111 (LT.second == MVT::f64 && MTy == MVT::i32) ||
1112 (LT.second == MVT::f32 && MTy == MVT::i64)))
1121 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
1128 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
1129 (LT.second == MVT::f16 && MTy == MVT::i64) ||
1130 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1144 if ((LT.second.getScalarType() == MVT::f32 ||
1145 LT.second.getScalarType() == MVT::f64 ||
1146 LT.second.getScalarType() == MVT::f16) &&
1149 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1150 if (LT.second.isVector())
1151 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1155 LegalTy, {LegalTy, LegalTy});
1159 LegalTy, {LegalTy, LegalTy});
1161 return LT.first *
Cost +
1162 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1168 RetTy = RetTy->getScalarType();
1169 if (LT.second.isVector()) {
1187 return LT.first *
Cost;
1189 case Intrinsic::fshl:
1190 case Intrinsic::fshr: {
1199 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1200 (RetTy->getPrimitiveSizeInBits() == 32 ||
1201 RetTy->getPrimitiveSizeInBits() == 64)) {
1214 {Intrinsic::fshl, MVT::v4i32, 2},
1215 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1216 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1217 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1223 return LegalisationCost.first * Entry->Cost;
1227 if (!RetTy->isIntegerTy())
1232 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1233 RetTy->getScalarSizeInBits() < 64) ||
1234 (RetTy->getScalarSizeInBits() % 64 != 0);
1235 unsigned ExtraCost = HigherCost ? 1 : 0;
1236 if (RetTy->getScalarSizeInBits() == 32 ||
1237 RetTy->getScalarSizeInBits() == 64)
1240 else if (HigherCost)
1244 return TyL.first + ExtraCost;
1246 case Intrinsic::get_active_lane_mask: {
1248 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1250 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1253 if (RetTy->isScalableTy()) {
1254 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1264 if (ST->hasSVE2p1() || ST->hasSME2()) {
1276 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1279 return Cost + (SplitCost * (
Cost - 1));
1294 case Intrinsic::experimental_vector_match: {
1295 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1301 unsigned SearchSize = NeedleTy->getNumElements();
1302 if (SearchSize <= 2)
1307 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1311 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1317 unsigned MatchesRequiredForNeedle =
1329 return Cost * LegalParts * MatchesRequiredForNeedle;
1331 case Intrinsic::cttz: {
1333 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1334 return LT.first * 2;
1335 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1336 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1337 return LT.first * 3;
1340 case Intrinsic::experimental_cttz_elts: {
1350 case Intrinsic::loop_dependence_raw_mask:
1351 case Intrinsic::loop_dependence_war_mask: {
1353 if (ST->hasSVE2() || ST->hasSME()) {
1354 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1355 unsigned EltSizeInBytes =
1365 case Intrinsic::experimental_vector_extract_last_active:
1366 if (ST->isSVEorStreamingSVEAvailable()) {
1372 case Intrinsic::pow: {
1375 EVT VT = getTLI()->getValueType(
DL, RetTy);
1376 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1378 getTLI()->getLibcallLoweringInfo().getVectorLibcallImplOrMasked(LC) !=
1394 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1395 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1405 return (Sqrt * 2) +
FMul;
1416 case Intrinsic::sqrt:
1417 case Intrinsic::fabs:
1418 case Intrinsic::ceil:
1419 case Intrinsic::floor:
1420 case Intrinsic::nearbyint:
1421 case Intrinsic::round:
1422 case Intrinsic::rint:
1423 case Intrinsic::roundeven:
1424 case Intrinsic::trunc:
1425 case Intrinsic::minnum:
1426 case Intrinsic::maxnum:
1427 case Intrinsic::minimum:
1428 case Intrinsic::maximum: {
1446 auto RequiredType =
II.getType();
1449 assert(PN &&
"Expected Phi Node!");
1452 if (!PN->hasOneUse())
1453 return std::nullopt;
1455 for (
Value *IncValPhi : PN->incoming_values()) {
1458 Reinterpret->getIntrinsicID() !=
1459 Intrinsic::aarch64_sve_convert_to_svbool ||
1460 RequiredType != Reinterpret->getArgOperand(0)->getType())
1461 return std::nullopt;
1469 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1471 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1544 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1549 return GoverningPredicateIdx;
1554 GoverningPredicateIdx = Index;
1576 return UndefIntrinsic;
1581 UndefIntrinsic = IID;
1608 return CmpPredicate;
1613 CmpPredicate = Pred;
1629 return ResultLanes == InactiveLanesTakenFromOperand;
1634 return OperandIdxForInactiveLanes;
1638 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1639 ResultLanes = InactiveLanesTakenFromOperand;
1640 OperandIdxForInactiveLanes = Index;
1645 return ResultLanes == InactiveLanesAreNotDefined;
1649 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1650 ResultLanes = InactiveLanesAreNotDefined;
1655 return ResultLanes == InactiveLanesAreUnused;
1659 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1660 ResultLanes = InactiveLanesAreUnused;
1670 ResultIsZeroInitialized =
true;
1681 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1686 return OperandIdxWithNoActiveLanes;
1691 OperandIdxWithNoActiveLanes = Index;
1696 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1699 unsigned IROpcode = 0;
1702 enum PredicationStyle {
1704 InactiveLanesTakenFromOperand,
1705 InactiveLanesAreNotDefined,
1706 InactiveLanesAreUnused
1709 bool ResultIsZeroInitialized =
false;
1710 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1711 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1719 return !isa<ScalableVectorType>(V->getType());
1727 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1728 case Intrinsic::aarch64_sve_fcvt_f16f32:
1729 case Intrinsic::aarch64_sve_fcvt_f16f64:
1730 case Intrinsic::aarch64_sve_fcvt_f32f16:
1731 case Intrinsic::aarch64_sve_fcvt_f32f64:
1732 case Intrinsic::aarch64_sve_fcvt_f64f16:
1733 case Intrinsic::aarch64_sve_fcvt_f64f32:
1734 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1735 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1736 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1737 case Intrinsic::aarch64_sve_fcvtzs:
1738 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1739 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1740 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1741 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1742 case Intrinsic::aarch64_sve_fcvtzu:
1743 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1744 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1745 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1746 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1747 case Intrinsic::aarch64_sve_revb:
1748 case Intrinsic::aarch64_sve_revh:
1749 case Intrinsic::aarch64_sve_revw:
1750 case Intrinsic::aarch64_sve_revd:
1751 case Intrinsic::aarch64_sve_scvtf:
1752 case Intrinsic::aarch64_sve_scvtf_f16i32:
1753 case Intrinsic::aarch64_sve_scvtf_f16i64:
1754 case Intrinsic::aarch64_sve_scvtf_f32i64:
1755 case Intrinsic::aarch64_sve_scvtf_f64i32:
1756 case Intrinsic::aarch64_sve_ucvtf:
1757 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1758 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1759 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1760 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1763 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1764 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1765 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1766 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1769 case Intrinsic::aarch64_sve_fabd:
1771 case Intrinsic::aarch64_sve_fadd:
1774 case Intrinsic::aarch64_sve_fdiv:
1777 case Intrinsic::aarch64_sve_fmax:
1779 case Intrinsic::aarch64_sve_fmaxnm:
1781 case Intrinsic::aarch64_sve_fmin:
1783 case Intrinsic::aarch64_sve_fminnm:
1785 case Intrinsic::aarch64_sve_fmla:
1787 case Intrinsic::aarch64_sve_fmls:
1789 case Intrinsic::aarch64_sve_fmul:
1792 case Intrinsic::aarch64_sve_fmulx:
1794 case Intrinsic::aarch64_sve_fnmla:
1796 case Intrinsic::aarch64_sve_fnmls:
1798 case Intrinsic::aarch64_sve_fsub:
1801 case Intrinsic::aarch64_sve_add:
1804 case Intrinsic::aarch64_sve_mla:
1806 case Intrinsic::aarch64_sve_mls:
1808 case Intrinsic::aarch64_sve_mul:
1811 case Intrinsic::aarch64_sve_sabd:
1813 case Intrinsic::aarch64_sve_sdiv:
1816 case Intrinsic::aarch64_sve_smax:
1818 case Intrinsic::aarch64_sve_smin:
1820 case Intrinsic::aarch64_sve_smulh:
1822 case Intrinsic::aarch64_sve_sub:
1825 case Intrinsic::aarch64_sve_uabd:
1827 case Intrinsic::aarch64_sve_udiv:
1830 case Intrinsic::aarch64_sve_umax:
1832 case Intrinsic::aarch64_sve_umin:
1834 case Intrinsic::aarch64_sve_umulh:
1836 case Intrinsic::aarch64_sve_asr:
1839 case Intrinsic::aarch64_sve_lsl:
1842 case Intrinsic::aarch64_sve_lsr:
1845 case Intrinsic::aarch64_sve_and:
1848 case Intrinsic::aarch64_sve_bic:
1850 case Intrinsic::aarch64_sve_eor:
1853 case Intrinsic::aarch64_sve_orr:
1856 case Intrinsic::aarch64_sve_shsub:
1858 case Intrinsic::aarch64_sve_shsubr:
1860 case Intrinsic::aarch64_sve_sqrshl:
1862 case Intrinsic::aarch64_sve_sqshl:
1864 case Intrinsic::aarch64_sve_sqsub:
1866 case Intrinsic::aarch64_sve_srshl:
1868 case Intrinsic::aarch64_sve_uhsub:
1870 case Intrinsic::aarch64_sve_uhsubr:
1872 case Intrinsic::aarch64_sve_uqrshl:
1874 case Intrinsic::aarch64_sve_uqshl:
1876 case Intrinsic::aarch64_sve_uqsub:
1878 case Intrinsic::aarch64_sve_urshl:
1881 case Intrinsic::aarch64_sve_add_u:
1884 case Intrinsic::aarch64_sve_and_u:
1887 case Intrinsic::aarch64_sve_asr_u:
1890 case Intrinsic::aarch64_sve_eor_u:
1893 case Intrinsic::aarch64_sve_fadd_u:
1896 case Intrinsic::aarch64_sve_fdiv_u:
1899 case Intrinsic::aarch64_sve_fmul_u:
1902 case Intrinsic::aarch64_sve_fsub_u:
1905 case Intrinsic::aarch64_sve_lsl_u:
1908 case Intrinsic::aarch64_sve_lsr_u:
1911 case Intrinsic::aarch64_sve_mul_u:
1914 case Intrinsic::aarch64_sve_orr_u:
1917 case Intrinsic::aarch64_sve_sdiv_u:
1920 case Intrinsic::aarch64_sve_sub_u:
1923 case Intrinsic::aarch64_sve_udiv_u:
1927 case Intrinsic::aarch64_sve_addqv:
1928 case Intrinsic::aarch64_sve_bic_z:
1929 case Intrinsic::aarch64_sve_brka_z:
1930 case Intrinsic::aarch64_sve_brkb_z:
1931 case Intrinsic::aarch64_sve_brkn_z:
1932 case Intrinsic::aarch64_sve_brkpa_z:
1933 case Intrinsic::aarch64_sve_brkpb_z:
1934 case Intrinsic::aarch64_sve_cntp:
1935 case Intrinsic::aarch64_sve_compact:
1936 case Intrinsic::aarch64_sve_eorv:
1937 case Intrinsic::aarch64_sve_eorqv:
1938 case Intrinsic::aarch64_sve_nand_z:
1939 case Intrinsic::aarch64_sve_nor_z:
1940 case Intrinsic::aarch64_sve_orn_z:
1941 case Intrinsic::aarch64_sve_orv:
1942 case Intrinsic::aarch64_sve_orqv:
1943 case Intrinsic::aarch64_sve_pnext:
1944 case Intrinsic::aarch64_sve_rdffr_z:
1945 case Intrinsic::aarch64_sve_saddv:
1946 case Intrinsic::aarch64_sve_uaddv:
1947 case Intrinsic::aarch64_sve_umaxv:
1948 case Intrinsic::aarch64_sve_umaxqv:
1949 case Intrinsic::aarch64_sve_facge:
1950 case Intrinsic::aarch64_sve_facgt:
1951 case Intrinsic::aarch64_sve_ld1:
1952 case Intrinsic::aarch64_sve_ld1_gather:
1953 case Intrinsic::aarch64_sve_ld1_gather_index:
1954 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1955 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1956 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1957 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1958 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1959 case Intrinsic::aarch64_sve_ld1q_gather_index:
1960 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1961 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1962 case Intrinsic::aarch64_sve_ld1ro:
1963 case Intrinsic::aarch64_sve_ld1rq:
1964 case Intrinsic::aarch64_sve_ld1udq:
1965 case Intrinsic::aarch64_sve_ld1uwq:
1966 case Intrinsic::aarch64_sve_ld2_sret:
1967 case Intrinsic::aarch64_sve_ld2q_sret:
1968 case Intrinsic::aarch64_sve_ld3_sret:
1969 case Intrinsic::aarch64_sve_ld3q_sret:
1970 case Intrinsic::aarch64_sve_ld4_sret:
1971 case Intrinsic::aarch64_sve_ld4q_sret:
1972 case Intrinsic::aarch64_sve_ldff1:
1973 case Intrinsic::aarch64_sve_ldff1_gather:
1974 case Intrinsic::aarch64_sve_ldff1_gather_index:
1975 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1976 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1977 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1978 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1979 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1980 case Intrinsic::aarch64_sve_ldnf1:
1981 case Intrinsic::aarch64_sve_ldnt1:
1982 case Intrinsic::aarch64_sve_ldnt1_gather:
1983 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1984 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1985 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1988 case Intrinsic::aarch64_sve_and_z:
1991 case Intrinsic::aarch64_sve_orr_z:
1994 case Intrinsic::aarch64_sve_eor_z:
1998 case Intrinsic::aarch64_sve_cmpeq:
1999 case Intrinsic::aarch64_sve_cmpeq_wide:
2002 case Intrinsic::aarch64_sve_cmpge:
2003 case Intrinsic::aarch64_sve_cmpge_wide:
2006 case Intrinsic::aarch64_sve_cmpgt:
2007 case Intrinsic::aarch64_sve_cmpgt_wide:
2010 case Intrinsic::aarch64_sve_cmphi:
2011 case Intrinsic::aarch64_sve_cmphi_wide:
2014 case Intrinsic::aarch64_sve_cmphs:
2015 case Intrinsic::aarch64_sve_cmphs_wide:
2018 case Intrinsic::aarch64_sve_cmple_wide:
2021 case Intrinsic::aarch64_sve_cmplo_wide:
2024 case Intrinsic::aarch64_sve_cmpls_wide:
2027 case Intrinsic::aarch64_sve_cmplt_wide:
2030 case Intrinsic::aarch64_sve_cmpne:
2031 case Intrinsic::aarch64_sve_cmpne_wide:
2034 case Intrinsic::aarch64_sve_fcmpeq:
2037 case Intrinsic::aarch64_sve_fcmpge:
2040 case Intrinsic::aarch64_sve_fcmpgt:
2043 case Intrinsic::aarch64_sve_fcmpne:
2046 case Intrinsic::aarch64_sve_fcmpuo:
2050 case Intrinsic::aarch64_sve_prf:
2051 case Intrinsic::aarch64_sve_prfb_gather_index:
2052 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
2053 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
2054 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
2055 case Intrinsic::aarch64_sve_prfd_gather_index:
2056 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
2057 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
2058 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
2059 case Intrinsic::aarch64_sve_prfh_gather_index:
2060 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
2061 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
2062 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
2063 case Intrinsic::aarch64_sve_prfw_gather_index:
2064 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
2065 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
2066 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
2069 case Intrinsic::aarch64_sve_st1_scatter:
2070 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
2071 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
2072 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
2073 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
2074 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
2075 case Intrinsic::aarch64_sve_st1dq:
2076 case Intrinsic::aarch64_sve_st1q_scatter_index:
2077 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
2078 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
2079 case Intrinsic::aarch64_sve_st1wq:
2080 case Intrinsic::aarch64_sve_stnt1:
2081 case Intrinsic::aarch64_sve_stnt1_scatter:
2082 case Intrinsic::aarch64_sve_stnt1_scatter_index:
2083 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
2084 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
2086 case Intrinsic::aarch64_sve_st2:
2087 case Intrinsic::aarch64_sve_st2q:
2089 case Intrinsic::aarch64_sve_st3:
2090 case Intrinsic::aarch64_sve_st3q:
2092 case Intrinsic::aarch64_sve_st4:
2093 case Intrinsic::aarch64_sve_st4q:
2101 Value *UncastedPred;
2107 Pred = UncastedPred;
2113 if (OrigPredTy->getMinNumElements() <=
2115 ->getMinNumElements())
2116 Pred = UncastedPred;
2120 return C &&
C->isAllOnesValue();
2127 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
2128 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2136static std::optional<Instruction *>
2143 Value *Op1 =
II.getOperand(1);
2144 Value *Op2 =
II.getOperand(2);
2169 Value *NarrowOp1, *NarrowOp2;
2180 else if (SimpleNarrow == NarrowOp1)
2182 else if (SimpleNarrow == NarrowOp2)
2187 SimpleNarrow->
getType(), SimpleNarrow);
2196 return std::nullopt;
2207 if (SimpleII == Inactive)
2215static std::optional<Instruction *>
2219 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2220 "Expected a compare operation!");
2227 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2228 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2229 "Unexpected wide compare!");
2245 const APInt *LHSVal, *RHSVal;
2247 return std::nullopt;
2270 return std::nullopt;
2284static std::optional<Instruction *>
2288 return std::nullopt;
2317 II.setCalledFunction(NewDecl);
2323 return std::nullopt;
2334 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2337 return std::nullopt;
2349static std::optional<Instruction *>
2351 auto m_ConvertToSVBool = [](
auto P) {
2355 Intrinsic::aarch64_sve_convert_from_svbool;
2378 return std::nullopt;
2382 case Intrinsic::aarch64_sve_and_z:
2383 case Intrinsic::aarch64_sve_bic_z:
2384 case Intrinsic::aarch64_sve_eor_z:
2385 case Intrinsic::aarch64_sve_nand_z:
2386 case Intrinsic::aarch64_sve_nor_z:
2387 case Intrinsic::aarch64_sve_orn_z:
2388 case Intrinsic::aarch64_sve_orr_z:
2391 return std::nullopt;
2394 Value *BinOpPred = BinOp->getOperand(0);
2395 Value *BinOpOp1 = BinOp->getOperand(1);
2396 Value *BinOpOp2 = BinOp->getOperand(2);
2398 Value *NarrowBinOpPred;
2400 return std::nullopt;
2402 Value *NarrowBinOpOp1 =
2404 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2405 if (BinOpOp1 != BinOpOp2)
2409 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2413static std::optional<Instruction *>
2420 return BinOpCombine;
2425 return std::nullopt;
2428 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2437 if (CursorVTy->getElementCount().getKnownMinValue() <
2438 IVTy->getElementCount().getKnownMinValue())
2442 if (Cursor->getType() == IVTy)
2443 EarliestReplacement = Cursor;
2448 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2449 Intrinsic::aarch64_sve_convert_to_svbool ||
2450 IntrinsicCursor->getIntrinsicID() ==
2451 Intrinsic::aarch64_sve_convert_from_svbool))
2454 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2455 Cursor = IntrinsicCursor->getOperand(0);
2460 if (!EarliestReplacement)
2461 return std::nullopt;
2469 auto *OpPredicate =
II.getOperand(0);
2486 II.getArgOperand(2));
2492 return std::nullopt;
2496 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2505 II.getArgOperand(0));
2514 if (!
II.hasOneUse())
2515 return std::nullopt;
2518 return std::nullopt;
2521 switch (
II.getIntrinsicID()) {
2522 case Intrinsic::aarch64_sve_cmpne:
2523 IID = Intrinsic::aarch64_sve_cmpeq;
2525 case Intrinsic::aarch64_sve_cmpne_wide:
2526 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2528 case Intrinsic::aarch64_sve_cmpeq:
2529 IID = Intrinsic::aarch64_sve_cmpne;
2531 case Intrinsic::aarch64_sve_cmpeq_wide:
2532 IID = Intrinsic::aarch64_sve_cmpne_wide;
2535 return std::nullopt;
2540 IID,
II.getOperand(1)->getType(),
2541 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2553 return std::nullopt;
2555 for (
auto *U :
II.users()) {
2558 Type *Ty =
II.getOperand(1)->getType();
2563 Intrinsic::aarch64_sve_umin, Ty,
2564 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2570 return std::nullopt;
2584 return std::nullopt;
2589 if (!SplatValue || !SplatValue->isZero())
2590 return std::nullopt;
2595 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2596 return std::nullopt;
2600 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2601 return std::nullopt;
2604 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2605 return std::nullopt;
2610 return std::nullopt;
2613 return std::nullopt;
2617 return std::nullopt;
2621 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2622 return std::nullopt;
2624 unsigned NumElts = VecTy->getNumElements();
2625 unsigned PredicateBits = 0;
2628 for (
unsigned I = 0;
I < NumElts; ++
I) {
2631 return std::nullopt;
2633 PredicateBits |= 1 << (
I * (16 / NumElts));
2637 if (PredicateBits == 0) {
2639 PFalse->takeName(&
II);
2645 for (
unsigned I = 0;
I < 16; ++
I)
2646 if ((PredicateBits & (1 <<
I)) != 0)
2649 unsigned PredSize = Mask & -Mask;
2654 for (
unsigned I = 0;
I < 16;
I += PredSize)
2655 if ((PredicateBits & (1 <<
I)) == 0)
2656 return std::nullopt;
2658 auto *ConvertToSVBool =
2661 auto *ConvertFromSVBool =
2663 II.getType(), ConvertToSVBool);
2671 Value *Pg =
II.getArgOperand(0);
2672 Value *Vec =
II.getArgOperand(1);
2673 auto IntrinsicID =
II.getIntrinsicID();
2674 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2686 auto OpC = OldBinOp->getOpcode();
2692 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2698 if (IsAfter &&
C &&
C->isNullValue()) {
2702 Extract->insertBefore(
II.getIterator());
2703 Extract->takeName(&
II);
2709 return std::nullopt;
2711 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2712 return std::nullopt;
2714 const auto PTruePattern =
2720 return std::nullopt;
2722 unsigned Idx = MinNumElts - 1;
2732 if (Idx >= PgVTy->getMinNumElements())
2733 return std::nullopt;
2738 Extract->insertBefore(
II.getIterator());
2739 Extract->takeName(&
II);
2752 Value *Pg =
II.getArgOperand(0);
2754 Value *Vec =
II.getArgOperand(2);
2757 if (!Ty->isIntegerTy())
2758 return std::nullopt;
2763 return std::nullopt;
2780 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2795static std::optional<Instruction *>
2799 if (
Pattern == AArch64SVEPredPattern::all) {
2808 return MinNumElts && NumElts >= MinNumElts
2810 II, ConstantInt::get(
II.getType(), MinNumElts)))
2814static std::optional<Instruction *>
2817 if (!ST->isStreaming())
2818 return std::nullopt;
2830 Value *PgVal =
II.getArgOperand(0);
2831 Value *OpVal =
II.getArgOperand(1);
2835 if (PgVal == OpVal &&
2836 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2837 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2852 return std::nullopt;
2856 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2857 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2871 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2872 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2873 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2874 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2875 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2876 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2877 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2878 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2879 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2880 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2881 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2882 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2883 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2893 return std::nullopt;
2896template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2897static std::optional<Instruction *>
2899 bool MergeIntoAddendOp) {
2901 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2902 if (MergeIntoAddendOp) {
2903 AddendOp =
II.getOperand(1);
2904 Mul =
II.getOperand(2);
2906 AddendOp =
II.getOperand(2);
2907 Mul =
II.getOperand(1);
2912 return std::nullopt;
2914 if (!
Mul->hasOneUse())
2915 return std::nullopt;
2918 if (
II.getType()->isFPOrFPVectorTy()) {
2923 return std::nullopt;
2925 return std::nullopt;
2930 if (MergeIntoAddendOp)
2940static std::optional<Instruction *>
2942 Value *Pred =
II.getOperand(0);
2943 Value *PtrOp =
II.getOperand(1);
2944 Type *VecTy =
II.getType();
2959static std::optional<Instruction *>
2961 Value *VecOp =
II.getOperand(0);
2962 Value *Pred =
II.getOperand(1);
2963 Value *PtrOp =
II.getOperand(2);
2979 case Intrinsic::aarch64_sve_fmul_u:
2980 return Instruction::BinaryOps::FMul;
2981 case Intrinsic::aarch64_sve_fadd_u:
2982 return Instruction::BinaryOps::FAdd;
2983 case Intrinsic::aarch64_sve_fsub_u:
2984 return Instruction::BinaryOps::FSub;
2986 return Instruction::BinaryOpsEnd;
2990static std::optional<Instruction *>
2993 if (
II.isStrictFP())
2994 return std::nullopt;
2996 auto *OpPredicate =
II.getOperand(0);
2998 if (BinOpCode == Instruction::BinaryOpsEnd ||
3000 return std::nullopt;
3002 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
3006static std::optional<Instruction *>
3008 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
3009 "Expected MLA_U intrinsic");
3010 Value *Acc =
II.getArgOperand(1);
3011 Value *MulOp0 =
II.getArgOperand(2);
3012 Value *MulOp1 =
II.getArgOperand(3);
3027 II.setArgOperand(2, MulOp1);
3028 II.setArgOperand(3, MulOp0);
3032 return std::nullopt;
3035static std::optional<Instruction *>
3037 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
3038 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
3039 "Expected SADALP or UADALP intrinsic");
3045 return std::nullopt;
3049 return std::nullopt;
3053 II.getIntrinsicID(), {II.getType()},
3054 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
3064 Intrinsic::aarch64_sve_mla>(
3068 Intrinsic::aarch64_sve_mad>(
3071 return std::nullopt;
3074static std::optional<Instruction *>
3078 Intrinsic::aarch64_sve_fmla>(IC,
II,
3083 Intrinsic::aarch64_sve_fmad>(IC,
II,
3088 Intrinsic::aarch64_sve_fmla>(IC,
II,
3091 return std::nullopt;
3094static std::optional<Instruction *>
3098 Intrinsic::aarch64_sve_fmla>(IC,
II,
3103 Intrinsic::aarch64_sve_fmad>(IC,
II,
3108 Intrinsic::aarch64_sve_fmla_u>(
3114static std::optional<Instruction *>
3118 Intrinsic::aarch64_sve_fmls>(IC,
II,
3123 Intrinsic::aarch64_sve_fnmsb>(
3128 Intrinsic::aarch64_sve_fmls>(IC,
II,
3131 return std::nullopt;
3134static std::optional<Instruction *>
3138 Intrinsic::aarch64_sve_fmls>(IC,
II,
3143 Intrinsic::aarch64_sve_fnmsb>(
3148 Intrinsic::aarch64_sve_fmls_u>(
3157 Intrinsic::aarch64_sve_mls>(
3160 return std::nullopt;
3165 Value *UnpackArg =
II.getArgOperand(0);
3167 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3168 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3181 return std::nullopt;
3185 auto *OpVal =
II.getOperand(0);
3186 auto *OpIndices =
II.getOperand(1);
3193 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3194 return std::nullopt;
3209 Type *RetTy =
II.getType();
3210 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3211 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3215 if ((
match(
II.getArgOperand(0),
3222 if (TyA ==
B->getType() &&
3227 TyA->getMinNumElements());
3233 return std::nullopt;
3241 if (
match(
II.getArgOperand(0),
3246 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3248 return std::nullopt;
3251static std::optional<Instruction *>
3253 Value *Mask =
II.getOperand(0);
3254 Value *BasePtr =
II.getOperand(1);
3255 Value *Index =
II.getOperand(2);
3266 BasePtr->getPointerAlignment(
II.getDataLayout());
3269 BasePtr, IndexBase);
3276 return std::nullopt;
3279static std::optional<Instruction *>
3281 Value *Val =
II.getOperand(0);
3282 Value *Mask =
II.getOperand(1);
3283 Value *BasePtr =
II.getOperand(2);
3284 Value *Index =
II.getOperand(3);
3294 BasePtr->getPointerAlignment(
II.getDataLayout());
3297 BasePtr, IndexBase);
3303 return std::nullopt;
3309 Value *Pred =
II.getOperand(0);
3310 Value *Vec =
II.getOperand(1);
3311 Value *DivVec =
II.getOperand(2);
3315 if (!SplatConstantInt)
3316 return std::nullopt;
3320 if (DivisorValue == -1)
3321 return std::nullopt;
3322 if (DivisorValue == 1)
3328 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3335 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3337 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3341 return std::nullopt;
3364 if (
I->getParent() != MainAnd->
getParent() ||
3372 size_t VecSize = Vec.
size();
3377 size_t HalfVecSize = VecSize / 2;
3381 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3389 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3407 return std::nullopt;
3414 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3415 CurrentInsertElt = InsertElt->getOperand(0);
3421 return std::nullopt;
3425 for (
size_t I = 0;
I < Elts.
size();
I++) {
3426 if (Elts[
I] ==
nullptr)
3431 if (InsertEltChain ==
nullptr)
3432 return std::nullopt;
3438 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3439 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3440 IIScalableTy->getMinNumElements() /
3445 auto *WideShuffleMaskTy =
3456 auto NarrowBitcast =
3469 return std::nullopt;
3474 Value *Pred =
II.getOperand(0);
3475 Value *Vec =
II.getOperand(1);
3476 Value *Shift =
II.getOperand(2);
3479 Value *AbsPred, *MergedValue;
3485 return std::nullopt;
3493 return std::nullopt;
3498 return std::nullopt;
3501 {
II.getType()}, {Pred, Vec, Shift});
3508 Value *Vec =
II.getOperand(0);
3513 return std::nullopt;
3516static std::optional<Instruction *>
3518 unsigned LookaheadThreshold) {
3520 auto *NI =
II.getNextNode();
3522 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3524 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3525 auto *NIBB = NI->getParent();
3526 NI = NI->getNextNode();
3528 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3529 NI = &*SuccBB->getFirstNonPHIOrLifetime();
3535 if (NextII &&
II.isIdenticalTo(NextII))
3538 return std::nullopt;
3546 {II.getType(), II.getOperand(0)->getType()},
3547 {II.getOperand(0), II.getOperand(1)}));
3554 if (PredPattern == AArch64SVEPredPattern::all ||
3555 PredPattern == AArch64SVEPredPattern::pow2)
3557 return std::nullopt;
3563 Value *Passthru =
II.getOperand(0);
3571 auto *Mask = ConstantInt::get(Ty, MaskValue);
3577 return std::nullopt;
3580static std::optional<Instruction *>
3587 return std::nullopt;
3593 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3603 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3613 return std::nullopt;
3619 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3627 return std::nullopt;
3630 II.getType(), {Pg, A, B});
3632 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3641 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3646 Value *
A, *PgLHS, *PgRHS;
3652 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3653 return std::nullopt;
3656 if (ConstB > ConstA)
3662 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3663 return std::nullopt;
3665 Type *VecTy =
A->getType();
3669 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3676std::optional<Instruction *>
3687 case Intrinsic::aarch64_dmb:
3689 case Intrinsic::aarch64_neon_fmaxnm:
3690 case Intrinsic::aarch64_neon_fminnm:
3692 case Intrinsic::aarch64_sve_convert_from_svbool:
3694 case Intrinsic::aarch64_sve_dup:
3696 case Intrinsic::aarch64_sve_dup_x:
3698 case Intrinsic::aarch64_sve_cmpeq:
3699 case Intrinsic::aarch64_sve_cmpeq_wide:
3701 case Intrinsic::aarch64_sve_cmpne:
3702 case Intrinsic::aarch64_sve_cmpne_wide:
3704 case Intrinsic::aarch64_sve_rdffr:
3706 case Intrinsic::aarch64_sve_lasta:
3707 case Intrinsic::aarch64_sve_lastb:
3709 case Intrinsic::aarch64_sve_clasta_n:
3710 case Intrinsic::aarch64_sve_clastb_n:
3712 case Intrinsic::aarch64_sve_cntd:
3714 case Intrinsic::aarch64_sve_cntw:
3716 case Intrinsic::aarch64_sve_cnth:
3718 case Intrinsic::aarch64_sve_cntb:
3720 case Intrinsic::aarch64_sme_cntsd:
3722 case Intrinsic::aarch64_sve_ptest_any:
3723 case Intrinsic::aarch64_sve_ptest_first:
3724 case Intrinsic::aarch64_sve_ptest_last:
3726 case Intrinsic::aarch64_sve_fadd:
3728 case Intrinsic::aarch64_sve_fadd_u:
3730 case Intrinsic::aarch64_sve_fmul_u:
3732 case Intrinsic::aarch64_sve_fsub:
3734 case Intrinsic::aarch64_sve_fsub_u:
3736 case Intrinsic::aarch64_sve_add:
3738 case Intrinsic::aarch64_sve_add_u:
3740 Intrinsic::aarch64_sve_mla_u>(
3742 case Intrinsic::aarch64_sve_mla_u:
3744 case Intrinsic::aarch64_sve_sadalp:
3745 case Intrinsic::aarch64_sve_uadalp:
3747 case Intrinsic::aarch64_sve_sub:
3749 case Intrinsic::aarch64_sve_sub_u:
3751 Intrinsic::aarch64_sve_mls_u>(
3753 case Intrinsic::aarch64_sve_tbl:
3755 case Intrinsic::aarch64_sve_uunpkhi:
3756 case Intrinsic::aarch64_sve_uunpklo:
3757 case Intrinsic::aarch64_sve_sunpkhi:
3758 case Intrinsic::aarch64_sve_sunpklo:
3760 case Intrinsic::aarch64_sve_uzp1:
3762 case Intrinsic::aarch64_sve_zip1:
3763 case Intrinsic::aarch64_sve_zip2:
3765 case Intrinsic::aarch64_sve_ld1_gather_index:
3767 case Intrinsic::aarch64_sve_st1_scatter_index:
3769 case Intrinsic::aarch64_sve_ld1:
3771 case Intrinsic::aarch64_sve_st1:
3773 case Intrinsic::aarch64_sve_sdiv:
3775 case Intrinsic::aarch64_sve_sel:
3777 case Intrinsic::aarch64_sve_srshl:
3779 case Intrinsic::aarch64_sve_dupq_lane:
3781 case Intrinsic::aarch64_sve_insr:
3783 case Intrinsic::aarch64_sve_whilelo:
3785 case Intrinsic::aarch64_sve_ptrue:
3787 case Intrinsic::aarch64_sve_uxtb:
3789 case Intrinsic::aarch64_sve_uxth:
3791 case Intrinsic::aarch64_sve_uxtw:
3793 case Intrinsic::aarch64_sme_in_streaming_mode:
3795 case Intrinsic::aarch64_sve_umin_u:
3797 case Intrinsic::aarch64_sve_orr_u:
3799 case Intrinsic::aarch64_sve_and_z:
3803 return std::nullopt;
3810 SimplifyAndSetOp)
const {
3811 switch (
II.getIntrinsicID()) {
3814 case Intrinsic::aarch64_neon_fcvtxn:
3815 case Intrinsic::aarch64_neon_rshrn:
3816 case Intrinsic::aarch64_neon_sqrshrn:
3817 case Intrinsic::aarch64_neon_sqrshrun:
3818 case Intrinsic::aarch64_neon_sqshrn:
3819 case Intrinsic::aarch64_neon_sqshrun:
3820 case Intrinsic::aarch64_neon_sqxtn:
3821 case Intrinsic::aarch64_neon_sqxtun:
3822 case Intrinsic::aarch64_neon_uqrshrn:
3823 case Intrinsic::aarch64_neon_uqshrn:
3824 case Intrinsic::aarch64_neon_uqxtn:
3825 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3829 return std::nullopt;
3833 return ST->isSVEAvailable() ||
3834 (ST->isSVEorStreamingSVEAvailable() &&
3835 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3844 if (ST->useSVEForFixedLengthVectors() &&
3845 (ST->isSVEAvailable() ||
3846 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3848 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3849 else if (ST->isNeonAvailable())
3854 if (ST->isSVEAvailable() ||
3855 (ST->isSVEorStreamingSVEAvailable() &&
3856 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3864bool AArch64TTIImpl::isSingleExtWideningInstruction(
3866 Type *SrcOverrideTy)
const {
3881 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3884 Type *SrcTy = SrcOverrideTy;
3886 case Instruction::Add:
3887 case Instruction::Sub: {
3896 if (Opcode == Instruction::Sub)
3920 assert(SrcTy &&
"Expected some SrcTy");
3922 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3928 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3930 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3934 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3937Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3939 Type *SrcOverrideTy)
const {
3940 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3941 Opcode != Instruction::Mul)
3951 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3954 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3960 ->getScalarSizeInBits();
3963 unsigned MaxEltSize = 0;
3966 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3967 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3968 MaxEltSize = std::max(EltSize0, EltSize1);
3971 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3972 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3975 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3977 MaxEltSize = DstEltSize / 2;
3978 }
else if (Opcode == Instruction::Mul &&
3986 Known.Zero.countLeadingOnes() >
3991 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3995 if (MaxEltSize * 2 > DstEltSize)
4013 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
4014 (Src->isScalableTy() && !ST->hasSVE2()))
4024 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4028 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4032 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4033 Src->getScalarSizeInBits() !=
4057 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4071 if (
I && !
I->users().empty()) {
4075 auto GetUserAbsorbedCastCost =
4076 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4079 if (
Type *ExtTy = isBinExtWideningInstruction(
4081 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4094 if (isSingleExtWideningInstruction(
4096 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4100 if (Usr->getOpcode() == Instruction::Add) {
4101 if (
I == Usr->getOperand(1) ||
4113 return std::nullopt;
4122 unsigned SrcBits = Src->getScalarSizeInBits();
4125 Dst->getScalarSizeInBits() == 2 * SrcBits &&
4129 return std::nullopt;
4133 bool AllUsersAbsorbCast =
true;
4134 for (
const User *U :
I->users()) {
4136 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4138 AllUsersAbsorbCast =
false;
4141 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4144 if (AllUsersAbsorbCast)
4145 return MaxAbsorbedCost;
4155 Cmp->getParent() ==
I->getParent() &&
4160 EVT SrcTy = TLI->getValueType(
DL, Src);
4161 EVT DstTy = TLI->getValueType(
DL, Dst);
4165 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4175 bool SrcIsFloatOrVec =
4176 SrcLT.second.isVector() || SrcLT.second.isFloatingPoint();
4177 bool DstIsFloatOrVec =
4178 DstLT.second.isVector() || DstLT.second.isFloatingPoint();
4183 if (SrcIsFloatOrVec == DstIsFloatOrVec &&
4184 (SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits() ||
4185 (SrcLT.second.isScalableVector() &&
4186 SrcLT.second.getScalarSizeInBits() != 1 &&
4187 DstLT.second.getScalarSizeInBits() != 1)))
4190 return std::max(SrcLT.first, DstLT.first) *
4193 : ST->getVectorInsertExtractBaseCost());
4202 Instruction::ExtractElement, Src, CostKind, -1,
nullptr,
nullptr);
4204 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind);
4208 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4213 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4242 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4245 ST->useSVEForFixedLengthVectors(WiderTy)) {
4246 std::pair<InstructionCost, MVT> LT =
4248 unsigned NumElements =
4264 const unsigned int SVE_EXT_COST = 1;
4265 const unsigned int SVE_FCVT_COST = 1;
4266 const unsigned int SVE_UNPACK_ONCE = 4;
4267 const unsigned int SVE_UNPACK_TWICE = 16;
4396 SVE_EXT_COST + SVE_FCVT_COST},
4401 SVE_EXT_COST + SVE_FCVT_COST},
4408 SVE_EXT_COST + SVE_FCVT_COST},
4412 SVE_EXT_COST + SVE_FCVT_COST},
4418 SVE_EXT_COST + SVE_FCVT_COST},
4421 SVE_EXT_COST + SVE_FCVT_COST},
4426 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4428 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4438 SVE_EXT_COST + SVE_FCVT_COST},
4443 SVE_EXT_COST + SVE_FCVT_COST},
4456 SVE_EXT_COST + SVE_FCVT_COST},
4460 SVE_EXT_COST + SVE_FCVT_COST},
4472 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4474 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4476 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4478 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4482 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4484 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4500 SVE_EXT_COST + SVE_FCVT_COST},
4505 SVE_EXT_COST + SVE_FCVT_COST},
4516 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4518 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4520 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4522 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4524 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4526 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4530 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4532 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4534 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4536 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4751 if (ST->hasFullFP16())
4763 Src->getScalarType(), CCH, CostKind) +
4771 ST->isSVEorStreamingSVEAvailable() &&
4772 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4774 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4783 Opcode, LegalTy, Src, CCH, CostKind,
I);
4786 return Part1 + Part2;
4793 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4805 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4818 CostKind, Index,
nullptr,
nullptr);
4822 auto DstVT = TLI->getValueType(
DL, Dst);
4823 auto SrcVT = TLI->getValueType(
DL, Src);
4828 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4834 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4844 case Instruction::SExt:
4849 case Instruction::ZExt:
4850 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4863 return Opcode == Instruction::PHI ? 0 : 1;
4872 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4874 assert(Ty->isVectorTy() &&
"This must be a vector type");
4881 if (!LT.second.isVector())
4886 if (LT.second.isFixedLengthVector()) {
4887 unsigned Width = LT.second.getVectorNumElements();
4888 Index = Index % Width;
4895 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4907 if (Index * Ty->getScalarSizeInBits() < 128)
4909 if (Index * Ty->getScalarSizeInBits() < 512 &&
4910 Opcode == Instruction::ExtractElement)
4912 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4913 if (Opcode == Instruction::ExtractElement)
4915 if (Opcode == Instruction::InsertElement)
4924 if (VIC == TTI::VectorInstrContext::Load) {
4925 if (ST->hasFastLD1Single())
4929 : ST->getVectorInsertExtractBaseCost() + 1;
4937 : ST->getVectorInsertExtractBaseCost() + 1;
4961 auto ExtractCanFuseWithFmul = [&]() {
4968 auto IsAllowedScalarTy = [&](
const Type *
T) {
4969 return T->isFloatTy() ||
T->isDoubleTy() ||
4970 (
T->isHalfTy() && ST->hasFullFP16());
4974 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4977 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4978 !BO->getType()->isVectorTy();
4983 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4987 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
4996 DenseMap<User *, unsigned> UserToExtractIdx;
4997 for (
auto *U :
Scalar->users()) {
4998 if (!IsUserFMulScalarTy(U))
5002 UserToExtractIdx[
U];
5004 if (UserToExtractIdx.
empty())
5006 for (
auto &[S, U, L] : ScalarUserAndIdx) {
5007 for (
auto *U : S->users()) {
5008 if (UserToExtractIdx.
contains(U)) {
5010 auto *Op0 =
FMul->getOperand(0);
5011 auto *Op1 =
FMul->getOperand(1);
5012 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
5013 UserToExtractIdx[
U] =
L;
5019 for (
auto &[U, L] : UserToExtractIdx) {
5031 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
5032 if (!IsUserFMulScalarTy(U))
5037 const auto *BO = cast<BinaryOperator>(U);
5038 const auto *OtherEE = dyn_cast<ExtractElementInst>(
5039 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
5041 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
5044 return IsExtractLaneEquivalentToZero(
5045 cast<ConstantInt>(OtherEE->getIndexOperand())
5048 OtherEE->getType()->getScalarSizeInBits());
5056 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
5057 ExtractCanFuseWithFmul())
5062 :
ST->getVectorInsertExtractBaseCost();
5071 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5074 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr,
nullptr,
5080 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5082 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr, Scalar,
5083 ScalarUserAndIdx, VIC);
5090 return getVectorInstrCostHelper(
I.getOpcode(), Ty, CostKind, Index, &
I,
5097 unsigned Index)
const {
5108 : ST->getVectorInsertExtractBaseCost() + 1;
5120 if (ST->hasFastLD1Single()) {
5121 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5122 (VIC == TTI::VectorInstrContext::Load && Insert))
5126 if (Ty->getElementType()->isFloatingPointTy())
5129 unsigned VecInstCost =
5131 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5138 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5139 return std::nullopt;
5140 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5141 return std::nullopt;
5143 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5144 return std::nullopt;
5151 Cost += InstCost(PromotedTy);
5166 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5177 if (Opcode == Instruction::And && CtxI->
hasOneUse() &&
5185 const auto *UI = cast<Instruction>(U);
5186 return is_contained({Instruction::And, Instruction::Or},
5195 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5201 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5202 Op2Info, Args, CtxI);
5208 if (
auto PromotedCost = getFP16BF16PromoteCost(
5209 Ty, CostKind, Op1Info, Op2Info,
true,
5212 [&](
Type *PromotedTy) {
5213 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
5216 return *PromotedCost;
5219 if (Ty->getScalarType()->isFP128Ty())
5227 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5229 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
5230 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
5237 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5247 ST->hasLimited64bitVectorMulBandwidth())
5255 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5258 if (
LT.second == MVT::v2i64) {
5262 return LT.first * Mul64CostFactor;
5275 (getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind) +
5283 if (
LT.second == MVT::nxv2i64)
5284 return LT.first * Mul64CostFactor;
5333 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5336 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5339 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5343 auto VT = TLI->getValueType(
DL, Ty);
5344 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5348 : (3 * AsrCost + AddCost);
5350 return MulCost + AsrCost + 2 * AddCost;
5352 }
else if (VT.isVector()) {
5363 Cost += 2 * AsrCost;
5368 ? (
LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5372 }
else if (
LT.second == MVT::v2i64) {
5373 return VT.getVectorNumElements() *
5374 getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind,
5381 return MulCost + 2 * AddCost + 2 * AsrCost;
5382 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5387 LT.second.isFixedLengthVector()) {
5393 CostKind, -1,
nullptr,
nullptr);
5395 CostKind, -1,
nullptr,
nullptr);
5397 return ExtractCost + InsertCost +
5405 auto VT = TLI->getValueType(
DL, Ty);
5409 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
5413 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
5421 bool HasMULH = VT == MVT::i64 ||
LT.second == MVT::nxv2i64 ||
5422 LT.second == MVT::nxv4i32 ||
LT.second == MVT::nxv8i16 ||
5423 LT.second == MVT::nxv16i8;
5424 bool Is128bit =
LT.second.is128BitVector();
5427 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5430 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5433 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5436 (HasMULH ? 0 : ShrCost) +
5437 AddCost * 2 + ShrCost;
5438 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5445 if (!VT.isVector() && VT.getSizeInBits() > 64)
5446 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5449 Opcode, Ty, CostKind, Op1Info, Op2Info);
5451 if (TLI->isOperationLegalOrCustom(
ISD,
LT.second) &&
ST->hasSVE()) {
5465 if (
nullptr != Entry)
5473 FVTy &&
LT.second.isFixedLengthVector()) {
5474 unsigned NumElts = FVTy->getNumElements();
5475 unsigned RegElts =
LT.second.getVectorNumElements();
5477 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5481 if (
LT.second.getScalarType() == MVT::i8)
5483 else if (
LT.second.getScalarType() == MVT::i16)
5496 return (4 + DivCost) * VTy->getNumElements();
5502 -1,
nullptr,
nullptr);
5529 LT.second.isFixedLengthVector())
5530 return 2 *
LT.first + 1;
5542 ((CtxI->hasOneUse() &&
5557 return 2 *
LT.first;
5559 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5565 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5566 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5579 unsigned NumVectorInstToHideOverhead =
5580 ST->getCLOpts().neon_nonconst_stride_overhead;
5581 int MaxMergeDistance = 64;
5585 return NumVectorInstToHideOverhead;
5597 unsigned Opcode1,
unsigned Opcode2)
const {
5600 if (!
Sched.hasInstrSchedModel())
5603 auto GetRThroughput = [&](
unsigned Opcode,
bool Highest) {
5604 std::optional<double> Res;
5606 while (!Worklist.
empty()) {
5610 append_range(Worklist, AArch64_MC::getVariantSchedClassTargets(
5611 SchedClass,
Sched.getProcessorID()));
5617 if (!Res || (Highest ? RThroughput > *Res : RThroughput < *Res))
5622 std::optional<double> RThroughput1 =
5623 GetRThroughput(Opcode1,
true);
5624 std::optional<double> RThroughput2 =
5625 GetRThroughput(Opcode2,
false);
5626 return RThroughput1 && RThroughput2 && *RThroughput1 > *RThroughput2;
5637 const int AmortizationCost = 20;
5645 VecPred = CurrentPred;
5653 static const auto ValidMinMaxTys = {
5654 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5655 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5656 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5660 (ST->hasFullFP16() &&
5666 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5667 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5668 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5669 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5670 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5671 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5672 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5673 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5674 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5675 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5676 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5678 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5679 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5688 if (Opcode == Instruction::FCmp) {
5690 ValTy, CostKind, Op1Info, Op2Info,
false,
5692 false, [&](
Type *PromotedTy) {
5695 CostKind, Op1Info, Op2Info);
5704 return *PromotedCost;
5708 if (LT.second.getScalarType() != MVT::f64 &&
5709 LT.second.getScalarType() != MVT::f32 &&
5710 LT.second.getScalarType() != MVT::f16)
5712 {ValTy, ValTy}, CostKind);
5715 unsigned Factor = 1;
5716 if (!CondTy->isVectorTy() &&
5730 AArch64::FCMEQv4f32))
5742 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5761 Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info,
I);
5765 AArch64::CMEQv4i32))
5773 if (ST->requiresStrictAlign()) {
5778 Options.AllowOverlappingLoads =
true;
5779 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5784 Options.LoadSizes = {8, 4, 2, 1};
5785 Options.AllowedTailExpansions = {3, 5, 6};
5790 return ST->hasSVE();
5796 switch (MICA.
getID()) {
5797 case Intrinsic::masked_scatter:
5798 case Intrinsic::masked_gather:
5800 case Intrinsic::masked_load:
5801 case Intrinsic::masked_store:
5802 case Intrinsic::masked_expandload:
5803 case Intrinsic::masked_compressstore:
5817 if (!LT.first.isValid())
5822 if (VT->getElementType()->isIntegerTy(1))
5828 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5834 if (MICA.
getID() == Intrinsic::masked_expandload) {
5847 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5867 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5868 return MemOpCost * 2;
5877 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5878 "Should be called on only load or stores.");
5880 case Instruction::Load:
5881 return ST->getCLOpts().sve_gather_overhead.value_or(
5882 ST->getGatherOverhead());
5884 case Instruction::Store:
5885 return ST->getCLOpts().sve_scatter_overhead.value_or(
5886 ST->getScatterOverhead());
5897 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5898 MICA.
getID() == Intrinsic::vp_gather)
5900 : Instruction::Store;
5910 if (!LT.first.isValid())
5914 if (!LT.second.isVector() ||
5916 VT->getElementType()->isIntegerTy(1))
5926 ElementCount LegalVF = LT.second.getVectorElementCount();
5929 {TTI::OK_AnyValue, TTI::OP_None},
I);
5945 EVT VT = TLI->getValueType(
DL, Ty,
true);
5947 if (VT == MVT::Other)
5952 if (!LT.first.isValid())
5958 if (VTy->getElementType()->isIntegerTy(1) &&
5959 !VTy->getElementCount().isKnownMultipleOf(
5965 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5966 : Intrinsic::masked_store;
5980 if (Opcode == Instruction::Store)
5984 if (ST->getFixedLoadLatency())
5985 return (LT.first - 1) + ST->getFixedLoadLatency();
5994 if (LT.second.isScalableVector() ||
5995 ST->useSVEForFixedLengthVectors(LT.second)) {
5996 Inst = AArch64::LDR_ZXI;
5997 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5998 switch (LT.second.getSizeInBits()) {
6000 Inst = AArch64::LDRBui;
6003 Inst = AArch64::LDRHui;
6006 Inst = AArch64::LDRSui;
6009 Inst = AArch64::LDRDui;
6012 Inst = AArch64::LDRQui;
6018 switch (LT.second.getSizeInBits()) {
6020 Inst = AArch64::LDRBBui;
6023 Inst = AArch64::LDRHHui;
6026 Inst = AArch64::LDRWui;
6029 Inst = AArch64::LDRXui;
6037 unsigned SchedClass =
TII->get(Inst).getSchedClass();
6039 ?
Sched.getSchedClassDesc(SchedClass)
6045 return (LT.first - 1) + ST->getLoadLatency();
6048 float NumLoads = (LT.first - 1).
getValue();
6049 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
6050 Sched.computeInstrLatency(*ST, *SCD);
6053 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
6054 LT.second.is128BitVector() && Alignment <
Align(16)) {
6060 const int AmortizationCost = 6;
6062 return LT.first * 2 * AmortizationCost;
6066 if (Ty->isPtrOrPtrVectorTy())
6071 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
6073 if (VT == MVT::v4i8)
6080 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
6081 Alignment !=
Align(1))
6093 if (Remainder != 0) {
6096 while (!TypeWorklist.
empty()) {
6106 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6118 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6119 assert(Factor >= 2 &&
"Invalid interleave factor");
6128 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6132 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6137 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6142 (UseMaskForCond || UseMaskForGaps ||
6143 (Factor > MaxNativeInterleaveFactor &&
6144 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6147 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6150 EC.divideCoefficientBy(Factor));
6156 if (EC.isKnownMultipleOf(Factor) &&
6157 TLI->isLegalInterleavedAccessType(SubVecTy,
DL, UseScalable))
6158 return Factor * TLI->getNumInterleavedAccesses(SubVecTy,
DL, UseScalable);
6163 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6169 if (UseMaskForCond) {
6170 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6171 : Intrinsic::masked_store;
6191 if (Opcode == Instruction::Store && Factor == 4 &&
6192 SubVecCost.second.getScalarSizeInBits() ==
6193 (4 * ResultCost.second.getScalarSizeInBits()))
6194 LegalizationCost *= 4;
6196 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6202 UseMaskForCond, UseMaskForGaps);
6209 for (
auto *
I : Tys) {
6210 if (!
I->isVectorTy())
6221 Align Alignment)
const {
6228 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6229 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6241 Size.getFixedValue() <= 16;
6246 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6247 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6266 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6273 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6279 bool HasUnorderedReductions)
const {
6282 return ST->getMaxInterleaveFactor();
6292 enum { MaxStridedLoads = 7 };
6294 int StridedLoads = 0;
6297 for (
const auto BB : L->blocks()) {
6298 for (
auto &
I : *BB) {
6304 if (L->isLoopInvariant(PtrValue))
6309 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6318 if (StridedLoads > MaxStridedLoads / 2)
6319 return StridedLoads;
6322 return StridedLoads;
6325 int StridedLoads = countStridedLoads(L, SE);
6327 <<
" strided loads\n");
6343 unsigned *FinalSize) {
6347 for (
auto *BB : L->getBlocks()) {
6348 for (
auto &
I : *BB) {
6354 if (!Cost.isValid())
6358 if (LoopCost > Budget)
6380 if (MaxTC > 0 && MaxTC <= 32)
6391 if (Blocks.
size() != 2)
6413 if (!L->isInnermost() || L->getNumBlocks() > 8)
6417 if (!L->getExitBlock())
6423 bool HasParellelizableReductions =
6424 L->getNumBlocks() == 1 &&
6425 any_of(L->getHeader()->phis(),
6427 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6430 if (HasParellelizableReductions &&
6452 if (HasParellelizableReductions) {
6463 if (Header == Latch) {
6466 unsigned Width = 10;
6472 unsigned MaxInstsPerLine = 16;
6474 unsigned BestUC = 1;
6475 unsigned SizeWithBestUC = BestUC *
Size;
6477 unsigned SizeWithUC = UC *
Size;
6478 if (SizeWithUC > 48)
6480 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6481 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6483 SizeWithBestUC = BestUC *
Size;
6493 for (
auto *BB : L->blocks()) {
6494 for (
auto &
I : *BB) {
6504 for (
auto *U :
I.users())
6506 LoadedValuesPlus.
insert(U);
6513 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6539 auto *I = dyn_cast<Instruction>(V);
6540 return I && DependsOnLoopLoad(I, Depth + 1);
6547 DependsOnLoopLoad(
I, 0)) {
6579 if (L->getLoopDepth() > 1)
6590 for (
auto *BB : L->getBlocks()) {
6591 for (
auto &
I : *BB) {
6595 if (IsVectorized &&
I.getType()->isVectorTy())
6606 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6615 if (ST->isAppleMLike())
6617 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6618 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6639 !ST->getSchedModel().isOutOfOrder()) {
6651 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6662 bool CanCreate)
const {
6666 case Intrinsic::aarch64_neon_st1x2:
6667 case Intrinsic::aarch64_neon_st1x3:
6668 case Intrinsic::aarch64_neon_st1x4:
6669 case Intrinsic::aarch64_neon_st2:
6670 case Intrinsic::aarch64_neon_st3:
6671 case Intrinsic::aarch64_neon_st4: {
6674 if (!CanCreate || !ST)
6676 unsigned NumElts = Inst->
arg_size() - 1;
6677 if (ST->getNumElements() != NumElts)
6679 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6685 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6687 Res = Builder.CreateInsertValue(Res, L, i);
6691 case Intrinsic::aarch64_neon_ld1x2:
6692 case Intrinsic::aarch64_neon_ld1x3:
6693 case Intrinsic::aarch64_neon_ld1x4:
6694 case Intrinsic::aarch64_neon_ld2:
6695 case Intrinsic::aarch64_neon_ld3:
6696 case Intrinsic::aarch64_neon_ld4:
6697 if (Inst->
getType() == ExpectedType)
6708 case Intrinsic::aarch64_neon_ld1x2:
6709 case Intrinsic::aarch64_neon_ld1x3:
6710 case Intrinsic::aarch64_neon_ld1x4:
6711 case Intrinsic::aarch64_neon_ld2:
6712 case Intrinsic::aarch64_neon_ld3:
6713 case Intrinsic::aarch64_neon_ld4:
6714 Info.ReadMem =
true;
6715 Info.WriteMem =
false;
6718 case Intrinsic::aarch64_neon_st1x2:
6719 case Intrinsic::aarch64_neon_st1x3:
6720 case Intrinsic::aarch64_neon_st1x4:
6721 case Intrinsic::aarch64_neon_st2:
6722 case Intrinsic::aarch64_neon_st3:
6723 case Intrinsic::aarch64_neon_st4:
6724 Info.ReadMem =
false;
6725 Info.WriteMem =
true;
6734 case Intrinsic::aarch64_neon_ld1x2:
6735 case Intrinsic::aarch64_neon_st1x2:
6736 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6738 case Intrinsic::aarch64_neon_ld1x3:
6739 case Intrinsic::aarch64_neon_st1x3:
6740 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6742 case Intrinsic::aarch64_neon_ld1x4:
6743 case Intrinsic::aarch64_neon_st1x4:
6744 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6746 case Intrinsic::aarch64_neon_ld2:
6747 case Intrinsic::aarch64_neon_st2:
6748 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6750 case Intrinsic::aarch64_neon_ld3:
6751 case Intrinsic::aarch64_neon_st3:
6752 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6754 case Intrinsic::aarch64_neon_ld4:
6755 case Intrinsic::aarch64_neon_st4:
6756 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6768 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6769 bool Considerable =
false;
6770 AllowPromotionWithoutCommonHeader =
false;
6773 Type *ConsideredSExtType =
6775 if (
I.getType() != ConsideredSExtType)
6779 for (
const User *U :
I.users()) {
6781 Considerable =
true;
6785 if (GEPInst->getNumOperands() > 2) {
6786 AllowPromotionWithoutCommonHeader =
true;
6791 return Considerable;
6842 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6852 return LegalizationCost + 2;
6862 LegalizationCost *= LT.first - 1;
6865 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6874 return LegalizationCost + 2;
6882 std::optional<FastMathFlags> FMF,
6898 return BaseCost + FixedVTy->getNumElements();
6912 MVT MTy = LT.second;
6917 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6965 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6966 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6978 return (LT.first - 1) +
Log2_32(NElts);
6983 return (LT.first - 1) + Entry->Cost;
6995 if (LT.first != 1) {
7001 ExtraCost *= LT.first - 1;
7004 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
7005 return Cost + ExtraCost;
7013 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
7015 EVT VecVT = TLI->getValueType(
DL, VecTy);
7016 EVT ResVT = TLI->getValueType(
DL, ResTy);
7026 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7028 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
7030 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
7032 return (LT.first - 1) * 2 + 2;
7043 EVT VecVT = TLI->getValueType(
DL, VecTy);
7044 EVT ResVT = TLI->getValueType(
DL, ResTy);
7047 RedOpcode == Instruction::Add) {
7053 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7055 return LT.first + 2;
7090 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
7091 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7105 if (LT.second.getScalarType() == MVT::i1) {
7114 assert(Entry &&
"Illegal Type for Splice");
7115 LegalizationCost += Entry->Cost;
7116 return LegalizationCost * LT.first;
7120 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7129 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7130 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7136 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7137 if (!FMF->allowReassoc() || !FMF->allowContract())
7141 "FastMathFlags only apply to floating-point partial reductions");
7145 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7146 "Unexpected values for OpBExtend or InputTypeB");
7150 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7151 InputTypeA != InputTypeB))
7162 assert(!OpBExtend &&
"Extended second operand without extended first.");
7163 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7169 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7172 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7185 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7194 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7200 std::pair<InstructionCost, MVT> AccumLT =
7202 std::pair<InstructionCost, MVT> InputLT =
7206 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7207 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7208 (AccumLT.second.isFixedLengthVector() &&
7209 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7213 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7221 if (AccumLT.second.getScalarType() == MVT::i32 &&
7222 InputLT.second.getScalarType() == MVT::i8) {
7224 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7225 return Cost + INegCost;
7227 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7228 return Cost + INegCost;
7233 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7234 return Cost * 3 + INegCost;
7237 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7239 if (AccumLT.second.getScalarType() == MVT::i64 &&
7240 InputLT.second.getScalarType() == MVT::i16)
7241 return Cost + INegCost;
7244 if (AccumLT.second.getScalarType() == MVT::i32 &&
7245 InputLT.second.getScalarType() == MVT::i16 &&
7246 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7249 if (AccumLT.second.getScalarType() == MVT::i64 &&
7250 InputLT.second.getScalarType() == MVT::i8)
7253 return Cost + INegCost;
7256 if (AccumLT.second.getScalarType() == MVT::i16 &&
7257 InputLT.second.getScalarType() == MVT::i8 &&
7258 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7276 if ((!BinOp || IsSExtMul) && !IsSub &&
7277 AccumLT.second.getScalarType() == MVT::i64 &&
7278 InputLT.second.getScalarType() == MVT::i8 &&
7279 IsSupported(
false, ST->hasDotProd()))
7284 if (Opcode == Instruction::FAdd && !IsSub &&
7285 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7286 AccumLT.second.getScalarType() == MVT::f32 &&
7287 InputLT.second.getScalarType() == MVT::f16)
7291 if (Ratio == 2 && !IsUSDot) {
7292 MVT InVT = InputLT.second.getScalarType();
7296 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7298 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7301 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7305 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7306 InVT == MVT::bf16 && IsSub)
7316 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7317 return Cost * 2 + FNegCost;
7321 AccumType, VF, OpAExtend, OpBExtend,
7322 BinOp, CostKind, FMF);
7332 "Expected the Mask to match the return size if given");
7334 "Expected the same scalar types");
7340 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7341 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7342 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7350 return std::max<InstructionCost>(1, LT.first / 4);
7358 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7360 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7363 unsigned TpNumElts = Mask.size();
7364 unsigned LTNumElts = LT.second.getVectorNumElements();
7365 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7367 LT.second.getVectorElementCount());
7369 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7371 for (
unsigned N = 0;
N < NumVecs;
N++) {
7375 unsigned Source1 = -1U, Source2 = -1U;
7376 unsigned NumSources = 0;
7377 for (
unsigned E = 0; E < LTNumElts; E++) {
7378 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7387 unsigned Source = MaskElt / LTNumElts;
7388 if (NumSources == 0) {
7391 }
else if (NumSources == 1 && Source != Source1) {
7394 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7400 if (Source == Source1)
7402 else if (Source == Source2)
7403 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7412 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7423 NTp, NTp, CostKind, NMask, 0,
nullptr, Args,
7426 Result.first->second = NCost;
7440 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7441 if (LT.second.getFixedSizeInBits() >= 128 &&
7443 LT.second.getVectorNumElements() / 2) {
7446 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7460 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7463 return M.value() < 0 || M.value() == (int)M.index();
7469 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7470 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7479 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7480 ST->isSVEorStreamingSVEAvailable() &&
7485 if (ST->isSVEorStreamingSVEAvailable() &&
7499 if (IsLoad && LT.second.isVector() &&
7501 LT.second.getVectorElementCount()))
7507 if (Mask.size() == 4 &&
7509 (SrcTy->getScalarSizeInBits() == 16 ||
7510 SrcTy->getScalarSizeInBits() == 32) &&
7511 all_of(Mask, [](
int E) {
return E < 8; }))
7517 if (LT.second.isFixedLengthVector() &&
7518 LT.second.getVectorNumElements() == Mask.size() &&
7524 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7525 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7526 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7527 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7528 LT.second.getVectorNumElements(), 16) ||
7529 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7530 LT.second.getVectorNumElements(), 32) ||
7531 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7532 LT.second.getVectorNumElements(), 64) ||
7535 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7664 return LT.first * Entry->Cost;
7673 LT.second.getSizeInBits() <= 128 && SubTp) {
7675 if (SubLT.second.isVector()) {
7676 int NumElts = LT.second.getVectorNumElements();
7677 int NumSubElts = SubLT.second.getVectorNumElements();
7678 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7684 if (IsExtractSubvector)
7705 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7716 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7717 ST->useFixedOverScalableIfEqualCost());
7721 return ST->getEpilogueVectorizationMinVF();
7756 unsigned NumInsns = 0;
7758 NumInsns += BB->size();
7762 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7768 int64_t Scale,
unsigned AddrSpace)
const {
7791 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7796 if (
I->getOpcode() == Instruction::Or &&
7800 if (
I->getOpcode() == Instruction::Add ||
7801 I->getOpcode() == Instruction::Sub)
7815 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7816 return std::tie(
C1.NumRegs,
C1.Insns,
C1.NumBaseAdds,
C1.AddRecCost,
7817 C1.NumIVMuls,
C1.ScaleCost,
C1.ImmCost,
C1.SetupCost) <
7826 return all_equal(Shuf->getShuffleMask());
7833 bool AllowSplat =
false) {
7838 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7839 auto *FullTy = FullV->
getType();
7840 auto *HalfTy = HalfV->getType();
7842 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7845 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7848 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7852 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7866 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7867 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7881 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7882 (M2Start != 0 && M2Start != (NumElements / 2)))
7884 if (S1Op1 && S2Op1 && M1Start != M2Start)
7894 return Ext->getType()->getScalarSizeInBits() ==
7895 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7909 Value *VectorOperand =
nullptr;
7926 if (!
GEP ||
GEP->getNumOperands() != 2)
7930 Value *Offsets =
GEP->getOperand(1);
7933 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7939 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7940 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7941 Ops.push_back(&
GEP->getOperandUse(1));
7977 switch (
II->getIntrinsicID()) {
7978 case Intrinsic::aarch64_neon_smull:
7979 case Intrinsic::aarch64_neon_umull:
7982 Ops.push_back(&
II->getOperandUse(0));
7983 Ops.push_back(&
II->getOperandUse(1));
7988 case Intrinsic::fma:
7989 case Intrinsic::fmuladd:
7996 Ops.push_back(&
II->getOperandUse(0));
7998 Ops.push_back(&
II->getOperandUse(1));
8001 case Intrinsic::aarch64_neon_sqdmull:
8002 case Intrinsic::aarch64_neon_sqdmulh:
8003 case Intrinsic::aarch64_neon_sqrdmulh:
8006 Ops.push_back(&
II->getOperandUse(0));
8008 Ops.push_back(&
II->getOperandUse(1));
8009 return !
Ops.empty();
8010 case Intrinsic::aarch64_neon_fmlal:
8011 case Intrinsic::aarch64_neon_fmlal2:
8012 case Intrinsic::aarch64_neon_fmlsl:
8013 case Intrinsic::aarch64_neon_fmlsl2:
8016 Ops.push_back(&
II->getOperandUse(1));
8018 Ops.push_back(&
II->getOperandUse(2));
8019 return !
Ops.empty();
8020 case Intrinsic::aarch64_sve_ptest_first:
8021 case Intrinsic::aarch64_sve_ptest_last:
8023 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
8024 Ops.push_back(&
II->getOperandUse(0));
8025 return !
Ops.empty();
8026 case Intrinsic::aarch64_sme_write_horiz:
8027 case Intrinsic::aarch64_sme_write_vert:
8028 case Intrinsic::aarch64_sme_writeq_horiz:
8029 case Intrinsic::aarch64_sme_writeq_vert: {
8031 if (!Idx || Idx->getOpcode() != Instruction::Add)
8033 Ops.push_back(&
II->getOperandUse(1));
8036 case Intrinsic::aarch64_sme_read_horiz:
8037 case Intrinsic::aarch64_sme_read_vert:
8038 case Intrinsic::aarch64_sme_readq_horiz:
8039 case Intrinsic::aarch64_sme_readq_vert:
8040 case Intrinsic::aarch64_sme_ld1b_vert:
8041 case Intrinsic::aarch64_sme_ld1h_vert:
8042 case Intrinsic::aarch64_sme_ld1w_vert:
8043 case Intrinsic::aarch64_sme_ld1d_vert:
8044 case Intrinsic::aarch64_sme_ld1q_vert:
8045 case Intrinsic::aarch64_sme_st1b_vert:
8046 case Intrinsic::aarch64_sme_st1h_vert:
8047 case Intrinsic::aarch64_sme_st1w_vert:
8048 case Intrinsic::aarch64_sme_st1d_vert:
8049 case Intrinsic::aarch64_sme_st1q_vert:
8050 case Intrinsic::aarch64_sme_ld1b_horiz:
8051 case Intrinsic::aarch64_sme_ld1h_horiz:
8052 case Intrinsic::aarch64_sme_ld1w_horiz:
8053 case Intrinsic::aarch64_sme_ld1d_horiz:
8054 case Intrinsic::aarch64_sme_ld1q_horiz:
8055 case Intrinsic::aarch64_sme_st1b_horiz:
8056 case Intrinsic::aarch64_sme_st1h_horiz:
8057 case Intrinsic::aarch64_sme_st1w_horiz:
8058 case Intrinsic::aarch64_sme_st1d_horiz:
8059 case Intrinsic::aarch64_sme_st1q_horiz: {
8061 if (!Idx || Idx->getOpcode() != Instruction::Add)
8063 Ops.push_back(&
II->getOperandUse(3));
8066 case Intrinsic::aarch64_neon_pmull:
8069 Ops.push_back(&
II->getOperandUse(0));
8070 Ops.push_back(&
II->getOperandUse(1));
8072 case Intrinsic::aarch64_neon_pmull64:
8074 II->getArgOperand(1)))
8076 Ops.push_back(&
II->getArgOperandUse(0));
8077 Ops.push_back(&
II->getArgOperandUse(1));
8079 case Intrinsic::masked_gather:
8082 Ops.push_back(&
II->getArgOperandUse(0));
8084 case Intrinsic::masked_scatter:
8087 Ops.push_back(&
II->getArgOperandUse(1));
8094 auto ShouldSinkCondition = [](
Value *
Cond,
8099 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8103 Ops.push_back(&
II->getOperandUse(0));
8107 switch (
I->getOpcode()) {
8108 case Instruction::GetElementPtr:
8109 case Instruction::Add:
8110 case Instruction::Sub:
8112 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8114 Ops.push_back(&
I->getOperandUse(
Op));
8119 case Instruction::Select: {
8120 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8123 Ops.push_back(&
I->getOperandUse(0));
8126 case Instruction::UncondBr:
8128 case Instruction::CondBr: {
8132 Ops.push_back(&
I->getOperandUse(0));
8135 case Instruction::FMul:
8140 Ops.push_back(&
I->getOperandUse(0));
8142 Ops.push_back(&
I->getOperandUse(1));
8152 case Instruction::Xor:
8155 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8157 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8162 case Instruction::And:
8163 case Instruction::Or:
8166 if (
I->getOpcode() == Instruction::Or &&
8171 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8174 for (
auto &
Op :
I->operands()) {
8186 Ops.push_back(&Not);
8187 Ops.push_back(&InsertElt);
8197 if (!
I->getType()->isVectorTy())
8198 return !
Ops.empty();
8200 switch (
I->getOpcode()) {
8201 case Instruction::Sub:
8202 case Instruction::Add: {
8211 Ops.push_back(&Ext1->getOperandUse(0));
8212 Ops.push_back(&Ext2->getOperandUse(0));
8215 Ops.push_back(&
I->getOperandUse(0));
8216 Ops.push_back(&
I->getOperandUse(1));
8220 case Instruction::Or: {
8223 if (ST->hasNEON()) {
8230 Ops.push_back(&
I->getOperandUse(0));
8231 Ops.push_back(&
I->getOperandUse(1));
8239 case Instruction::Mul: {
8240 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8243 if (Ty->isScalableTy())
8247 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8250 int NumZExts = 0, NumSExts = 0;
8251 for (
auto &
Op :
I->operands()) {
8258 auto *ExtOp = Ext->getOperand(0);
8259 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8260 Ops.push_back(&Ext->getOperandUse(0));
8268 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8269 I->getType()->getScalarSizeInBits())
8306 if (!ElementConstant || !ElementConstant->
isZero())
8309 unsigned Opcode = OperandInstr->
getOpcode();
8310 if (Opcode == Instruction::SExt)
8312 else if (Opcode == Instruction::ZExt)
8317 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8327 Ops.push_back(&Insert->getOperandUse(1));
8333 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8337 if (!ShouldSinkSplatForIndexedVariant(
I))
8342 Ops.push_back(&
I->getOperandUse(0));
8344 Ops.push_back(&
I->getOperandUse(1));
8346 return !
Ops.empty();
8348 case Instruction::FMul: {
8350 if (
I->getType()->isScalableTy())
8351 return !
Ops.empty();
8355 return !
Ops.empty();
8359 Ops.push_back(&
I->getOperandUse(0));
8361 Ops.push_back(&
I->getOperandUse(1));
8362 return !
Ops.empty();
8371 Align Alignment)
const {
8372 if (!(ST->isSVEAvailable() ||
8373 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8377 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8384 if (!LT.first.isValid())
8389 switch (LT.second.SimpleTy) {
static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static Error reportError(StringRef Message)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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 unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
This file implements the C++20 <bit> header.
unsigned getVectorInsertExtractBaseCost() const
bool useSVEForFixedLengthVectors() const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getCostOfKeepingLiveOverCall(ArrayRef< Type * > Tys) const override
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool hasPossibleIncompatibleOps(const Function *F, bool ConsiderZA, bool ConsiderZT, bool ConsiderSM) const
Returns true if the function has explicit operations that can only be lowered using incompatible inst...
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src) const
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index) const override
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
bool preferFixedOverScalableIfEqualCost() const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind=TTI::TCK_RecipThroughput) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isElementTypeLegalForScalableVector(Type *Ty) const override
bool hasMultiVectorLoadStore(unsigned NumVectors, TTI::MaskSource Mask, VectorType *VectorTy, bool IsStore, std::optional< Instruction::CastOps > CastHint) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const override
bool preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
APInt getPriorityMask(const Function &F) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
bool shouldMaximizeVectorBandwidth(TargetTransformInfo::RegisterKind K) const override
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const override
bool useNeonVector(const Type *Ty) const
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
bool isLegalSpeculativeLoad(Type *DataType, unsigned AddressSpace) const override
bool isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
bool isElementTypeLegalForCompressStore(Type *Ty) const
InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, TTI::TargetCostKind CostKind) const override
unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, unsigned DefaultCallPenalty) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
The compiler must not inline when that may alter the behavior of the program.
unsigned getMaxNumElements(ElementCount VF) const
Try to return an estimate cost factor that can be used as a multiplier when scalarizing an operation ...
bool shouldTreatInstructionLikeSelect(const Instruction *I) const override
bool isMultiversionedFunction(const Function &F) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, ElementCount VF) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedGatherScatter(Type *DataType) const
InstructionCost getBranchMispredictPenalty() const override
bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const override
See if I should be considered for address type promotion.
APInt getFeatureMask(const Function &F) const override
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const override
bool enableScalableVectorization() const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Value * getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate=true) const override
bool hasKnownLowerThroughputFromSchedulingModel(unsigned Opcode1, unsigned Opcode2) const
Check whether Opcode1 has less throughput according to the scheduling model than Opcode2.
unsigned getEpilogueVectorizationMinVF() const override
InstructionCost getSpliceCost(VectorType *Tp, int Index, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) const override
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
void negate()
Negate this APInt in place.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
unsigned logBase2() const
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, Instruction *I=nullptr, int64_t ScalableOffset=0) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getCallInstrCost(Function *F, Type *RetTy, ArrayRef< Type * > Tys, TTI::TargetCostKind CostKind) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
std::pair< InstructionCost, MVT > getTypeLegalizationCost(Type *Ty) const
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
bool isTypeLegal(Type *Ty) const override
static BinaryOperator * CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Value *CopyO, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
static bool isFPPredicate(Predicate P)
static bool isIntPredicate(Predicate P)
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
const APInt & getValue() const
Return the constant as an APInt value reference.
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
LLVM_ABI Constant * getSplatValue(bool AllowPoison=false) const
If all elements of the vector constant have the same value, return that value.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
constexpr bool isScalar() const
Exactly one element.
static bool isCommutative(Predicate Pred)
This provides a helper for copying FMF from an instruction or setting specified flags.
Convenience struct for specifying and reasoning about fast-math flags.
bool noSignedZeros() const
bool allowContract() const
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
static bool isCommutative(Predicate P)
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Type * getDoubleTy()
Fetch the type representing a 64-bit floating point value.
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Type * getHalfTy()
Fetch the type representing a 16-bit floating point value.
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Value * CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, Value *Mask)
Create a call to Masked Store intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Type * getFloatTy()
Fetch the type representing a 32-bit floating point value.
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateInsertVector(Type *DstType, Value *SrcVec, Value *SubVec, Value *Idx, const Twine &Name="")
Create a call to the vector.insert intrinsic.
LLVM_ABI Value * CreateElementCount(Type *Ty, ElementCount EC)
Create an expression which evaluates to the number of elements in EC at runtime.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This instruction inserts a single (scalar) element into a VectorType value.
The core instruction combiner logic.
virtual Instruction * eraseInstFromFunction(Instruction &I)=0
Combiner aware instruction erasure.
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
static InstructionCost getInvalid(CostType Val=0)
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
Instruction * user_back()
iterator_range< user_iterator > users()
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
user_iterator user_begin()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
bool hasGroups() const
Returns true if we have any interleave groups.
const SmallVectorImpl< Type * > & getArgTypes() const
Type * getReturnType() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() const
Intrinsic::ID getID() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
iterator_range< block_iterator > blocks() const
RecurrenceSet & getFixedOrderRecurrences()
Return the fixed-order recurrences found in the loop.
DominatorTree * getDominatorTree() const
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
bool isFixedLengthVector() const
MVT getVectorElementType() const
Information for memory intrinsic cost model.
Align getAlignment() const
Type * getDataType() const
Intrinsic::ID getID() const
const Instruction * getInst() const
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
Type * getRecurrenceType() const
Returns the type of the recurrence.
RecurKind getRecurrenceKind() const
This node represents a polynomial recurrence on the trip count of the specified loop.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
This class represents an analyzed expression in the program.
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasStreamingInterfaceOrBody() const
SMECallAttrs is a utility class to hold the SMEAttrs for a callsite.
bool requiresSMChange() const
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
static ScalableVectorType * getDoubleElementsVectorType(ScalableVectorType *VTy)
The main scalar evolution driver.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI unsigned getSmallConstantTripMultiple(const Loop *L, const SCEV *ExitCount)
Returns the largest constant divisor of the trip count as a normal unsigned value,...
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
LLVM_ABI bool isBackedgeTakenCountMaxOrZero(const Loop *L)
Return true if the backedge taken count is either the value returned by getConstantMaxBackedgeTakenCo...
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
const SCEV * getSymbolicMaxBackedgeTakenCount(const Loop *L)
When successful, this returns a SCEV that is greater than or equal to (i.e.
This instruction constructs a fixed permutation of two input vectors.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isExtractSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &Index)
Return true if this shuffle mask is an extract subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Class to represent struct types.
TargetInstrInfo - Interface to description of machine instruction set.
std::pair< LegalizeTypeAction, EVT > LegalizeKind
LegalizeKind holds the legalization kind that needs to happen to EVT in order to type-legalize it.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
bool isFP128Ty() const
Return true if this is 'fp128'.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static VectorType * getInteger(VectorType *VTy)
This static method gets a VectorType with the same number of elements as the input type,...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
LLVM_ABI APInt getCpuSupportsMask(ArrayRef< StringRef > Features)
static constexpr unsigned SVEBitsPerBlock
LLVM_ABI APInt getFMVPriority(ArrayRef< StringRef > Features)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
@ ADD
Simple integer binary arithmetic operators.
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ FADD
Simple binary floating point operators.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI bool isTargetIntrinsic(ID IID)
isTargetIntrinsic - Returns true if IID is an intrinsic specific to a certain target.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
AllOnesConstantMatch m_AllOnes()
CheckType m_SpecificType(LLT Ty)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_Cmp()
Matches any compare instruction and ignore it.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::And > m_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R either in the form of L & R or L ?
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_nonnegative > m_NonNegative()
Match an integer or vector of non-negative values.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
auto m_VScale()
Matches a call to llvm.vscale().
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_Undef()
Match an arbitrary undef constant.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
LocationClass< Ty > location(Ty &L)
InstructionCost getVectorInstrCost(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, unsigned Opcode, Type *Val, const TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar, ArrayRef< std::tuple< Value *, User *, int > > ScalarUserAndIdx, TTI::VectorInstrContext VIC)
This is similar to TargetTransformInfo::getVectorInstrCost, but if ScalarTy is a FixedVectorType,...
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
std::optional< unsigned > isDUPQMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPQMask - matches a splat of equivalent lanes within segments of a given number of elements.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> (WhichResultOut = 0,...
TailFoldingOpts
An enum to describe what types of loops we should attempt to tail-fold: Disabled: None Reductions: Lo...
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool isDUPFirstSegmentMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPFirstSegmentMask - matches a splat of the first 128b segment.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< const MDOperand * > findStringMetadataForLoop(const Loop *TheLoop, StringRef Name)
Find string metadata for loop.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
CostTblEntryT< uint16_t > CostTblEntry
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
Return the number of active elements for VL1 to VL256 predicate pattern, zero for all other patterns.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
constexpr bool valueOr(BoolOrDefault X, bool Default)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
unsigned getMatchingIROpode() const
bool inactiveLanesAreUnused() const
bool inactiveLanesAreNotDefined() const
bool hasMatchingUndefIntrinsic() const
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
bool hasGoverningPredicate() const
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
CmpInst::Predicate getCmpPredicate() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
bool inactiveLanesTakenFromOperand() const
static SVEIntrinsicInfo defaultUndefOp()
bool hasOperandWithNoActiveLanes() const
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
bool hasCmpPredicate() const
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() const
bool hasMatchingIROpode() const
SVEIntrinsicInfo & setCmpPredicate(CmpInst::Predicate Pred)
bool resultIsZeroInitialized() const
SVEIntrinsicInfo & setMatchingIROpcode(unsigned Opcode)
unsigned getOperandIdxInactiveLanesTakenFrom() const
static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex)
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isFixedLengthVector() const
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Machine model for scheduling, bundling, and heuristics.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Information about a load/store intrinsic defined by the target.
InterleavedAccessInfo * IAI
LoopVectorizationLegality * LVL
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...