25#include "llvm/IR/IntrinsicsAArch64.h"
37#define DEBUG_TYPE "aarch64tti"
40class TailFoldingOption {
55 bool NeedsDefault =
true;
59 void setNeedsDefault(
bool V) { NeedsDefault =
V; }
75 "Initial bits should only include one of "
76 "(disabled|all|simple|default)");
77 Bits = NeedsDefault ? DefaultBits : InitialBits;
85 errs() <<
"invalid argument '" << Opt
86 <<
"' to -sve-tail-folding=; the option should be of the form\n"
87 " (disabled|all|default|simple)[+(reductions|recurrences"
88 "|reverse|noreductions|norecurrences|noreverse)]\n";
94 void operator=(
const std::string &Val) {
103 setNeedsDefault(
false);
108 unsigned StartIdx = 1;
109 if (TailFoldTypes[0] ==
"disabled")
111 else if (TailFoldTypes[0] ==
"all")
113 else if (TailFoldTypes[0] ==
"default")
114 setNeedsDefault(
true);
115 else if (TailFoldTypes[0] ==
"simple")
122 for (
unsigned I = StartIdx;
I < TailFoldTypes.
size();
I++) {
123 if (TailFoldTypes[
I] ==
"reductions")
125 else if (TailFoldTypes[
I] ==
"recurrences")
127 else if (TailFoldTypes[
I] ==
"reverse")
129 else if (TailFoldTypes[
I] ==
"noreductions")
131 else if (TailFoldTypes[
I] ==
"norecurrences")
133 else if (TailFoldTypes[
I] ==
"noreverse")
145 return (
getBits(DefaultBits) & Required) == Required;
155 "Control the use of vectorisation using tail-folding for SVE where the"
156 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
157 "\ndisabled (Initial) No loop types will vectorize using "
159 "\ndefault (Initial) Uses the default tail-folding settings for "
161 "\nall (Initial) All legal loop types will vectorize using "
163 "\nsimple (Initial) Use tail-folding for simple loops (not "
164 "reductions or recurrences)"
165 "\nreductions Use tail-folding for loops containing reductions"
166 "\nnoreductions Inverse of above"
167 "\nrecurrences Use tail-folding for loops containing fixed order "
169 "\nnorecurrences Inverse of above"
170 "\nreverse Use tail-folding for loops requiring reversed "
172 "\nnoreverse Inverse of above"),
181 bool ConsiderSM)
const {
182 if (!ConsiderZA && !ConsiderZT && !ConsiderSM)
185 bool IsAlwaysInline =
F->hasFnAttribute(Attribute::AlwaysInline);
192 bool AssumeVScaleIsEquivalent =
193 F->getReturnType()->isScalableTy() ||
194 any_of(
F->getFunctionType()->params(),
195 [](
const Type *
T) { return T->isScalableTy(); });
203 if (CB->isInlineAsm())
206 if (
CallAttrs.callee().isSMEABIRoutine())
215 if (ConsiderSM &&
CallAttrs.callee().hasStreamingCompatibleInterface())
227 return isa<FixedVectorType>(V->getType());
232 unsigned IID =
II->getIntrinsicID();
240 case Intrinsic::masked_gather:
241 case Intrinsic::masked_scatter:
242 case Intrinsic::masked_compressstore:
243 case Intrinsic::experimental_vector_histogram_add:
247 if (
I.getOperand(0)->getType()->isScalableTy())
250 case Intrinsic::vscale:
251 if (!AssumeVScaleIsEquivalent)
259 if (!AssumeVScaleIsEquivalent &&
260 (
I.getType()->isScalableTy() ||
263 [](
const Value *V) { return V->getType()->isScalableTy(); }) ||
265 .getSourceElementType()
278 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
279 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
280 FeatureStr.
split(Features,
",");
296 return F.hasFnAttribute(
"fmv-features");
348 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
349 CallAttrs.callee().hasStreamingInterfaceOrBody())
357 if (
CallAttrs.callee().hasStreamingBody()) {
362 bool ConsiderZA =
CallAttrs.requiresZASave();
363 bool ConsiderZT =
CallAttrs.requiresPreservingZT0() ||
364 CallAttrs.requiresPreservingAllZAState();
365 bool ConsiderSM =
CallAttrs.requiresSMChange();
370 if (ConsiderSM && (Caller->isStrictFP() || Callee->isStrictFP()))
394 auto FVTy = dyn_cast<FixedVectorType>(Ty);
396 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
405 unsigned DefaultCallPenalty)
const {
430 if (
F ==
Call.getCaller())
431 return ST->getCLOpts().call_penalty_sm_change * DefaultCallPenalty;
433 return ST->getCLOpts().inline_call_penalty_sm_change * DefaultCallPenalty;
436 return DefaultCallPenalty;
447 ST->isSVEorStreamingSVEAvailable() &&
448 !ST->disableMaximizeScalableBandwidth();
472 assert(Ty->isIntegerTy());
474 unsigned BitSize = Ty->getPrimitiveSizeInBits();
481 ImmVal =
Imm.sext((BitSize + 63) & ~0x3fU);
486 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
492 return std::max<InstructionCost>(1,
Cost);
499 assert(Ty->isIntegerTy());
501 unsigned BitSize = Ty->getPrimitiveSizeInBits();
507 unsigned ImmIdx = ~0U;
511 case Instruction::GetElementPtr:
516 case Instruction::Store:
519 case Instruction::Add:
520 case Instruction::Sub:
521 case Instruction::Mul:
522 case Instruction::UDiv:
523 case Instruction::SDiv:
524 case Instruction::URem:
525 case Instruction::SRem:
526 case Instruction::And:
527 case Instruction::Or:
528 case Instruction::Xor:
529 case Instruction::ICmp:
533 case Instruction::Shl:
534 case Instruction::LShr:
535 case Instruction::AShr:
539 case Instruction::Trunc:
540 case Instruction::ZExt:
541 case Instruction::SExt:
542 case Instruction::IntToPtr:
543 case Instruction::PtrToInt:
544 case Instruction::BitCast:
545 case Instruction::PHI:
546 case Instruction::Call:
547 case Instruction::Select:
548 case Instruction::Ret:
549 case Instruction::Load:
554 int NumConstants = (BitSize + 63) / 64;
567 assert(Ty->isIntegerTy());
569 unsigned BitSize = Ty->getPrimitiveSizeInBits();
578 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
584 case Intrinsic::sadd_with_overflow:
585 case Intrinsic::uadd_with_overflow:
586 case Intrinsic::ssub_with_overflow:
587 case Intrinsic::usub_with_overflow:
588 case Intrinsic::smul_with_overflow:
589 case Intrinsic::umul_with_overflow:
591 int NumConstants = (BitSize + 63) / 64;
598 case Intrinsic::experimental_stackmap:
599 if ((Idx < 2) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
602 case Intrinsic::experimental_patchpoint_void:
603 case Intrinsic::experimental_patchpoint:
604 if ((Idx < 4) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
607 case Intrinsic::experimental_gc_statepoint:
608 if ((Idx < 5) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
618 if (TyWidth == 32 || TyWidth == 64)
627 return ST->getMispredictionPenalty();
648 unsigned TotalHistCnts = 1;
658 unsigned EC = VTy->getElementCount().getKnownMinValue();
663 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
665 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
669 TotalHistCnts = EC / NaturalVectorWidth;
671 return InstructionCost(ST->getCLOpts().base_histcnt_cost * TotalHistCnts);
688 !
is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
692 switch (ICA.
getID()) {
693 case Intrinsic::experimental_vector_histogram_add: {
700 case Intrinsic::experimental_vector_histogram_uadd_sat:
701 case Intrinsic::experimental_vector_histogram_umax:
702 case Intrinsic::experimental_vector_histogram_umin:
705 case Intrinsic::clmul: {
710 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
714 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
719 -1,
nullptr,
nullptr) *
722 -1,
nullptr,
nullptr);
726 if (LT.second.SimpleTy == MVT::nxv2i64)
727 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
730 if (ST->hasSVE2() || ST->hasSME()) {
731 switch (LT.second.SimpleTy) {
746 if (LT.second.SimpleTy == MVT::nxv2i64)
750 switch (LT.second.SimpleTy) {
760 -1,
nullptr,
nullptr) *
763 -1,
nullptr,
nullptr));
772 return LT.first * 11;
774 return LT.first * 14;
781 case Intrinsic::smulh:
782 case Intrinsic::umulh: {
788 if (RetTy->getScalarSizeInBits() > 64)
802 return MulCost + ExtraCost;
807 return LT.first + ExtraCost;
823 return LT.first * Entry->Cost + ExtraCost;
827 case Intrinsic::umin:
828 case Intrinsic::umax:
829 case Intrinsic::smin:
830 case Intrinsic::smax: {
831 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
832 MVT::v8i16, MVT::v2i32, MVT::v4i32,
833 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
840 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
841 EVT VT = TLI->getValueType(
DL, RetTy,
true);
842 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
843 return LT.first * (IsSigned ? 5 : 3);
845 if (LT.second == MVT::v2i64)
851 case Intrinsic::scmp:
852 case Intrinsic::ucmp: {
854 {Intrinsic::scmp, MVT::i32, 3},
855 {Intrinsic::scmp, MVT::i64, 3},
856 {Intrinsic::scmp, MVT::v8i8, 3},
857 {Intrinsic::scmp, MVT::v16i8, 3},
858 {Intrinsic::scmp, MVT::v4i16, 3},
859 {Intrinsic::scmp, MVT::v8i16, 3},
860 {Intrinsic::scmp, MVT::v2i32, 3},
861 {Intrinsic::scmp, MVT::v4i32, 3},
862 {Intrinsic::scmp, MVT::v1i64, 3},
863 {Intrinsic::scmp, MVT::v2i64, 3},
869 return Entry->Cost * LT.first;
872 case Intrinsic::sadd_sat:
873 case Intrinsic::ssub_sat:
874 case Intrinsic::uadd_sat:
875 case Intrinsic::usub_sat: {
876 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
877 MVT::v8i16, MVT::v2i32, MVT::v4i32,
883 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
885 return LT.first * Instrs;
890 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
891 return LT.first * Instrs;
895 case Intrinsic::abs: {
896 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
897 MVT::v8i16, MVT::v2i32, MVT::v4i32,
898 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
899 MVT::nxv4i32, MVT::nxv2i64};
905 case Intrinsic::bswap: {
906 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
907 MVT::v4i32, MVT::v2i64};
910 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
915 case Intrinsic::fmuladd: {
920 (EltTy->
isHalfTy() && ST->hasFullFP16()))
924 case Intrinsic::stepvector: {
933 Cost += AddCost * (LT.first - 1);
937 case Intrinsic::vector_extract:
938 case Intrinsic::vector_insert: {
951 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
952 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
960 getTLI()->getTypeConversion(
C, SubVecVT);
962 getTLI()->getTypeConversion(
C, VecVT);
970 case Intrinsic::bitreverse: {
972 {Intrinsic::bitreverse, MVT::i32, 1},
973 {Intrinsic::bitreverse, MVT::i64, 1},
974 {Intrinsic::bitreverse, MVT::v8i8, 1},
975 {Intrinsic::bitreverse, MVT::v16i8, 1},
976 {Intrinsic::bitreverse, MVT::v4i16, 2},
977 {Intrinsic::bitreverse, MVT::v8i16, 2},
978 {Intrinsic::bitreverse, MVT::v2i32, 2},
979 {Intrinsic::bitreverse, MVT::v4i32, 2},
980 {Intrinsic::bitreverse, MVT::v1i64, 2},
981 {Intrinsic::bitreverse, MVT::v2i64, 2},
989 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
990 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
991 return LegalisationCost.first * Entry->Cost + 1;
993 return LegalisationCost.first * Entry->Cost;
997 case Intrinsic::pdep:
998 case Intrinsic::pext: {
999 unsigned BW = RetTy->getScalarSizeInBits();
1000 if (!RetTy->isVectorTy() && ST->isSVEBitPermAvailable() && BW <= 64) {
1014 case Intrinsic::ctpop: {
1016 MVT MTy = LT.second;
1018 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
1021 return LT.first + ExtraCost;
1023 if (!ST->hasNEON()) {
1053 RetTy->getScalarSizeInBits()
1056 return LT.first * Entry->Cost + ExtraCost;
1060 case Intrinsic::sadd_with_overflow:
1061 case Intrinsic::uadd_with_overflow:
1062 case Intrinsic::ssub_with_overflow:
1063 case Intrinsic::usub_with_overflow:
1064 case Intrinsic::smul_with_overflow:
1065 case Intrinsic::umul_with_overflow: {
1067 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
1068 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
1069 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
1070 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
1071 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
1072 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
1073 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
1074 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
1075 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
1076 {Intrinsic::usub_with_overflow, MVT::i8, 3},
1077 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
1078 {Intrinsic::usub_with_overflow, MVT::i16, 3},
1079 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
1080 {Intrinsic::usub_with_overflow, MVT::i32, 1},
1081 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
1082 {Intrinsic::usub_with_overflow, MVT::i64, 1},
1083 {Intrinsic::smul_with_overflow, MVT::i8, 5},
1084 {Intrinsic::umul_with_overflow, MVT::i8, 4},
1085 {Intrinsic::smul_with_overflow, MVT::i16, 5},
1086 {Intrinsic::umul_with_overflow, MVT::i16, 4},
1087 {Intrinsic::smul_with_overflow, MVT::i32, 2},
1088 {Intrinsic::umul_with_overflow, MVT::i32, 2},
1089 {Intrinsic::smul_with_overflow, MVT::i64, 3},
1090 {Intrinsic::umul_with_overflow, MVT::i64, 3},
1092 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
1099 case Intrinsic::fptosi_sat:
1100 case Intrinsic::fptoui_sat: {
1103 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
1105 EVT MTy = TLI->getValueType(
DL, RetTy);
1108 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
1109 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
1110 LT.second == MVT::v2f64)) {
1112 (LT.second == MVT::f64 && MTy == MVT::i32) ||
1113 (LT.second == MVT::f32 && MTy == MVT::i64)))
1122 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
1129 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
1130 (LT.second == MVT::f16 && MTy == MVT::i64) ||
1131 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1145 if ((LT.second.getScalarType() == MVT::f32 ||
1146 LT.second.getScalarType() == MVT::f64 ||
1147 LT.second.getScalarType() == MVT::f16) &&
1150 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1151 if (LT.second.isVector())
1152 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1156 LegalTy, {LegalTy, LegalTy});
1160 LegalTy, {LegalTy, LegalTy});
1162 return LT.first *
Cost +
1163 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1169 RetTy = RetTy->getScalarType();
1170 if (LT.second.isVector()) {
1188 return LT.first *
Cost;
1190 case Intrinsic::fshl:
1191 case Intrinsic::fshr: {
1200 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1201 (RetTy->getPrimitiveSizeInBits() == 32 ||
1202 RetTy->getPrimitiveSizeInBits() == 64)) {
1215 {Intrinsic::fshl, MVT::v4i32, 2},
1216 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1217 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1218 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1224 return LegalisationCost.first * Entry->Cost;
1228 if (!RetTy->isIntegerTy())
1233 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1234 RetTy->getScalarSizeInBits() < 64) ||
1235 (RetTy->getScalarSizeInBits() % 64 != 0);
1236 unsigned ExtraCost = HigherCost ? 1 : 0;
1237 if (RetTy->getScalarSizeInBits() == 32 ||
1238 RetTy->getScalarSizeInBits() == 64)
1241 else if (HigherCost)
1245 return TyL.first + ExtraCost;
1247 case Intrinsic::get_active_lane_mask: {
1249 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1251 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1254 if (RetTy->isScalableTy()) {
1255 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1265 if (ST->hasSVE2p1() || ST->hasSME2()) {
1277 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1280 return Cost + (SplitCost * (
Cost - 1));
1295 case Intrinsic::experimental_vector_match: {
1296 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1302 unsigned SearchSize = NeedleTy->getNumElements();
1303 if (SearchSize <= 2)
1308 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1312 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1318 unsigned MatchesRequiredForNeedle =
1330 return Cost * LegalParts * MatchesRequiredForNeedle;
1332 case Intrinsic::cttz: {
1334 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1335 return LT.first * 2;
1336 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1337 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1338 return LT.first * 3;
1341 case Intrinsic::experimental_cttz_elts: {
1351 case Intrinsic::mask_beforefirst: {
1352 if (!ST->isSVEorStreamingSVEAvailable() ||
1354 !TLI->isTypeLegal(getTLI()->getValueType(
DL, RetTy)))
1361 case Intrinsic::loop_dependence_raw_mask:
1362 case Intrinsic::loop_dependence_war_mask: {
1364 if (ST->hasSVE2() || ST->hasSME()) {
1365 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1366 unsigned EltSizeInBytes =
1376 case Intrinsic::experimental_vector_extract_last_active:
1377 if (ST->isSVEorStreamingSVEAvailable()) {
1383 case Intrinsic::pow: {
1386 EVT VT = getTLI()->getValueType(
DL, RetTy);
1387 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1389 getTLI()->getLibcallLoweringInfo().getVectorLibcallImplOrMasked(LC) !=
1405 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1406 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1416 return (Sqrt * 2) +
FMul;
1427 case Intrinsic::sqrt:
1428 case Intrinsic::fabs:
1429 case Intrinsic::ceil:
1430 case Intrinsic::floor:
1431 case Intrinsic::nearbyint:
1432 case Intrinsic::round:
1433 case Intrinsic::rint:
1434 case Intrinsic::roundeven:
1435 case Intrinsic::trunc:
1436 case Intrinsic::minnum:
1437 case Intrinsic::maxnum:
1438 case Intrinsic::minimum:
1439 case Intrinsic::maximum: {
1457 auto RequiredType =
II.getType();
1460 assert(PN &&
"Expected Phi Node!");
1463 if (!PN->hasOneUse())
1464 return std::nullopt;
1466 for (
Value *IncValPhi : PN->incoming_values()) {
1469 Reinterpret->getIntrinsicID() !=
1470 Intrinsic::aarch64_sve_convert_to_svbool ||
1471 RequiredType != Reinterpret->getArgOperand(0)->getType())
1472 return std::nullopt;
1480 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1482 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1555 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1560 return GoverningPredicateIdx;
1565 GoverningPredicateIdx = Index;
1587 return UndefIntrinsic;
1592 UndefIntrinsic = IID;
1619 return CmpPredicate;
1624 CmpPredicate = Pred;
1640 return ResultLanes == InactiveLanesTakenFromOperand;
1645 return OperandIdxForInactiveLanes;
1649 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1650 ResultLanes = InactiveLanesTakenFromOperand;
1651 OperandIdxForInactiveLanes = Index;
1656 return ResultLanes == InactiveLanesAreNotDefined;
1660 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1661 ResultLanes = InactiveLanesAreNotDefined;
1666 return ResultLanes == InactiveLanesAreUnused;
1670 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1671 ResultLanes = InactiveLanesAreUnused;
1681 ResultIsZeroInitialized =
true;
1692 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1697 return OperandIdxWithNoActiveLanes;
1702 OperandIdxWithNoActiveLanes = Index;
1707 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1710 unsigned IROpcode = 0;
1713 enum PredicationStyle {
1715 InactiveLanesTakenFromOperand,
1716 InactiveLanesAreNotDefined,
1717 InactiveLanesAreUnused
1720 bool ResultIsZeroInitialized =
false;
1721 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1722 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1730 return !isa<ScalableVectorType>(V->getType());
1738 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1739 case Intrinsic::aarch64_sve_fcvt_f16f32:
1740 case Intrinsic::aarch64_sve_fcvt_f16f64:
1741 case Intrinsic::aarch64_sve_fcvt_f32f16:
1742 case Intrinsic::aarch64_sve_fcvt_f32f64:
1743 case Intrinsic::aarch64_sve_fcvt_f64f16:
1744 case Intrinsic::aarch64_sve_fcvt_f64f32:
1745 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1746 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1747 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1748 case Intrinsic::aarch64_sve_fcvtzs:
1749 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1750 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1751 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1752 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1753 case Intrinsic::aarch64_sve_fcvtzu:
1754 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1755 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1756 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1757 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1758 case Intrinsic::aarch64_sve_revb:
1759 case Intrinsic::aarch64_sve_revh:
1760 case Intrinsic::aarch64_sve_revw:
1761 case Intrinsic::aarch64_sve_revd:
1762 case Intrinsic::aarch64_sve_scvtf:
1763 case Intrinsic::aarch64_sve_scvtf_f16i32:
1764 case Intrinsic::aarch64_sve_scvtf_f16i64:
1765 case Intrinsic::aarch64_sve_scvtf_f32i64:
1766 case Intrinsic::aarch64_sve_scvtf_f64i32:
1767 case Intrinsic::aarch64_sve_ucvtf:
1768 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1769 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1770 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1771 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1774 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1775 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1776 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1777 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1780 case Intrinsic::aarch64_sve_fabd:
1782 case Intrinsic::aarch64_sve_fadd:
1785 case Intrinsic::aarch64_sve_fdiv:
1788 case Intrinsic::aarch64_sve_fmax:
1790 case Intrinsic::aarch64_sve_fmaxnm:
1792 case Intrinsic::aarch64_sve_fmin:
1794 case Intrinsic::aarch64_sve_fminnm:
1796 case Intrinsic::aarch64_sve_fmla:
1798 case Intrinsic::aarch64_sve_fmls:
1800 case Intrinsic::aarch64_sve_fmul:
1803 case Intrinsic::aarch64_sve_fmulx:
1805 case Intrinsic::aarch64_sve_fnmla:
1807 case Intrinsic::aarch64_sve_fnmls:
1809 case Intrinsic::aarch64_sve_fsub:
1812 case Intrinsic::aarch64_sve_add:
1815 case Intrinsic::aarch64_sve_mla:
1817 case Intrinsic::aarch64_sve_mls:
1819 case Intrinsic::aarch64_sve_mul:
1822 case Intrinsic::aarch64_sve_sabd:
1824 case Intrinsic::aarch64_sve_sdiv:
1827 case Intrinsic::aarch64_sve_smax:
1829 case Intrinsic::aarch64_sve_smin:
1831 case Intrinsic::aarch64_sve_smulh:
1833 case Intrinsic::aarch64_sve_sub:
1836 case Intrinsic::aarch64_sve_uabd:
1838 case Intrinsic::aarch64_sve_udiv:
1841 case Intrinsic::aarch64_sve_umax:
1843 case Intrinsic::aarch64_sve_umin:
1845 case Intrinsic::aarch64_sve_umulh:
1847 case Intrinsic::aarch64_sve_asr:
1850 case Intrinsic::aarch64_sve_lsl:
1853 case Intrinsic::aarch64_sve_lsr:
1856 case Intrinsic::aarch64_sve_and:
1859 case Intrinsic::aarch64_sve_bic:
1861 case Intrinsic::aarch64_sve_eor:
1864 case Intrinsic::aarch64_sve_orr:
1867 case Intrinsic::aarch64_sve_shsub:
1869 case Intrinsic::aarch64_sve_shsubr:
1871 case Intrinsic::aarch64_sve_sqrshl:
1873 case Intrinsic::aarch64_sve_sqshl:
1875 case Intrinsic::aarch64_sve_sqsub:
1877 case Intrinsic::aarch64_sve_srshl:
1879 case Intrinsic::aarch64_sve_uhsub:
1881 case Intrinsic::aarch64_sve_uhsubr:
1883 case Intrinsic::aarch64_sve_uqrshl:
1885 case Intrinsic::aarch64_sve_uqshl:
1887 case Intrinsic::aarch64_sve_uqsub:
1889 case Intrinsic::aarch64_sve_urshl:
1892 case Intrinsic::aarch64_sve_add_u:
1895 case Intrinsic::aarch64_sve_and_u:
1898 case Intrinsic::aarch64_sve_asr_u:
1901 case Intrinsic::aarch64_sve_eor_u:
1904 case Intrinsic::aarch64_sve_fadd_u:
1907 case Intrinsic::aarch64_sve_fdiv_u:
1910 case Intrinsic::aarch64_sve_fmul_u:
1913 case Intrinsic::aarch64_sve_fsub_u:
1916 case Intrinsic::aarch64_sve_lsl_u:
1919 case Intrinsic::aarch64_sve_lsr_u:
1922 case Intrinsic::aarch64_sve_mul_u:
1925 case Intrinsic::aarch64_sve_orr_u:
1928 case Intrinsic::aarch64_sve_sdiv_u:
1931 case Intrinsic::aarch64_sve_sub_u:
1934 case Intrinsic::aarch64_sve_udiv_u:
1938 case Intrinsic::aarch64_sve_addqv:
1939 case Intrinsic::aarch64_sve_bic_z:
1940 case Intrinsic::aarch64_sve_brka_z:
1941 case Intrinsic::aarch64_sve_brkb_z:
1942 case Intrinsic::aarch64_sve_brkn_z:
1943 case Intrinsic::aarch64_sve_brkpa_z:
1944 case Intrinsic::aarch64_sve_brkpb_z:
1945 case Intrinsic::aarch64_sve_cntp:
1946 case Intrinsic::aarch64_sve_compact:
1947 case Intrinsic::aarch64_sve_eorv:
1948 case Intrinsic::aarch64_sve_eorqv:
1949 case Intrinsic::aarch64_sve_nand_z:
1950 case Intrinsic::aarch64_sve_nor_z:
1951 case Intrinsic::aarch64_sve_orn_z:
1952 case Intrinsic::aarch64_sve_orv:
1953 case Intrinsic::aarch64_sve_orqv:
1954 case Intrinsic::aarch64_sve_pnext:
1955 case Intrinsic::aarch64_sve_rdffr_z:
1956 case Intrinsic::aarch64_sve_saddv:
1957 case Intrinsic::aarch64_sve_uaddv:
1958 case Intrinsic::aarch64_sve_umaxv:
1959 case Intrinsic::aarch64_sve_umaxqv:
1960 case Intrinsic::aarch64_sve_facge:
1961 case Intrinsic::aarch64_sve_facgt:
1962 case Intrinsic::aarch64_sve_ld1:
1963 case Intrinsic::aarch64_sve_ld1_gather:
1964 case Intrinsic::aarch64_sve_ld1_gather_index:
1965 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1966 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1967 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1968 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1969 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1970 case Intrinsic::aarch64_sve_ld1q_gather_index:
1971 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1972 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1973 case Intrinsic::aarch64_sve_ld1ro:
1974 case Intrinsic::aarch64_sve_ld1rq:
1975 case Intrinsic::aarch64_sve_ld1udq:
1976 case Intrinsic::aarch64_sve_ld1uwq:
1977 case Intrinsic::aarch64_sve_ld2_sret:
1978 case Intrinsic::aarch64_sve_ld2q_sret:
1979 case Intrinsic::aarch64_sve_ld3_sret:
1980 case Intrinsic::aarch64_sve_ld3q_sret:
1981 case Intrinsic::aarch64_sve_ld4_sret:
1982 case Intrinsic::aarch64_sve_ld4q_sret:
1983 case Intrinsic::aarch64_sve_ldff1:
1984 case Intrinsic::aarch64_sve_ldff1_gather:
1985 case Intrinsic::aarch64_sve_ldff1_gather_index:
1986 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1987 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1988 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1989 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1990 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1991 case Intrinsic::aarch64_sve_ldnf1:
1992 case Intrinsic::aarch64_sve_ldnt1:
1993 case Intrinsic::aarch64_sve_ldnt1_gather:
1994 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1995 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1996 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1999 case Intrinsic::aarch64_sve_and_z:
2002 case Intrinsic::aarch64_sve_orr_z:
2005 case Intrinsic::aarch64_sve_eor_z:
2009 case Intrinsic::aarch64_sve_cmpeq:
2010 case Intrinsic::aarch64_sve_cmpeq_wide:
2013 case Intrinsic::aarch64_sve_cmpge:
2014 case Intrinsic::aarch64_sve_cmpge_wide:
2017 case Intrinsic::aarch64_sve_cmpgt:
2018 case Intrinsic::aarch64_sve_cmpgt_wide:
2021 case Intrinsic::aarch64_sve_cmphi:
2022 case Intrinsic::aarch64_sve_cmphi_wide:
2025 case Intrinsic::aarch64_sve_cmphs:
2026 case Intrinsic::aarch64_sve_cmphs_wide:
2029 case Intrinsic::aarch64_sve_cmple_wide:
2032 case Intrinsic::aarch64_sve_cmplo_wide:
2035 case Intrinsic::aarch64_sve_cmpls_wide:
2038 case Intrinsic::aarch64_sve_cmplt_wide:
2041 case Intrinsic::aarch64_sve_cmpne:
2042 case Intrinsic::aarch64_sve_cmpne_wide:
2045 case Intrinsic::aarch64_sve_fcmpeq:
2048 case Intrinsic::aarch64_sve_fcmpge:
2051 case Intrinsic::aarch64_sve_fcmpgt:
2054 case Intrinsic::aarch64_sve_fcmpne:
2057 case Intrinsic::aarch64_sve_fcmpuo:
2061 case Intrinsic::aarch64_sve_prf:
2062 case Intrinsic::aarch64_sve_prfb_gather_index:
2063 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
2064 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
2065 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
2066 case Intrinsic::aarch64_sve_prfd_gather_index:
2067 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
2068 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
2069 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
2070 case Intrinsic::aarch64_sve_prfh_gather_index:
2071 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
2072 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
2073 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
2074 case Intrinsic::aarch64_sve_prfw_gather_index:
2075 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
2076 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
2077 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
2080 case Intrinsic::aarch64_sve_st1_scatter:
2081 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
2082 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
2083 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
2084 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
2085 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
2086 case Intrinsic::aarch64_sve_st1dq:
2087 case Intrinsic::aarch64_sve_st1q_scatter_index:
2088 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
2089 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
2090 case Intrinsic::aarch64_sve_st1wq:
2091 case Intrinsic::aarch64_sve_stnt1:
2092 case Intrinsic::aarch64_sve_stnt1_scatter:
2093 case Intrinsic::aarch64_sve_stnt1_scatter_index:
2094 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
2095 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
2097 case Intrinsic::aarch64_sve_st2:
2098 case Intrinsic::aarch64_sve_st2q:
2100 case Intrinsic::aarch64_sve_st3:
2101 case Intrinsic::aarch64_sve_st3q:
2103 case Intrinsic::aarch64_sve_st4:
2104 case Intrinsic::aarch64_sve_st4q:
2112 Value *UncastedPred;
2118 Pred = UncastedPred;
2124 if (OrigPredTy->getMinNumElements() <=
2126 ->getMinNumElements())
2127 Pred = UncastedPred;
2131 return C &&
C->isAllOnesValue();
2138 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
2139 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2147static std::optional<Instruction *>
2154 Value *Op1 =
II.getOperand(1);
2155 Value *Op2 =
II.getOperand(2);
2180 Value *NarrowOp1, *NarrowOp2;
2191 else if (SimpleNarrow == NarrowOp1)
2193 else if (SimpleNarrow == NarrowOp2)
2198 SimpleNarrow->
getType(), SimpleNarrow);
2207 return std::nullopt;
2218 if (SimpleII == Inactive)
2226static std::optional<Instruction *>
2230 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2231 "Expected a compare operation!");
2238 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2239 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2240 "Unexpected wide compare!");
2256 const APInt *LHSVal, *RHSVal;
2258 return std::nullopt;
2281 return std::nullopt;
2295static std::optional<Instruction *>
2299 return std::nullopt;
2328 II.setCalledFunction(NewDecl);
2334 return std::nullopt;
2345 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2348 return std::nullopt;
2360static std::optional<Instruction *>
2362 auto m_ConvertToSVBool = [](
auto P) {
2366 Intrinsic::aarch64_sve_convert_from_svbool;
2389 return std::nullopt;
2393 case Intrinsic::aarch64_sve_and_z:
2394 case Intrinsic::aarch64_sve_bic_z:
2395 case Intrinsic::aarch64_sve_eor_z:
2396 case Intrinsic::aarch64_sve_nand_z:
2397 case Intrinsic::aarch64_sve_nor_z:
2398 case Intrinsic::aarch64_sve_orn_z:
2399 case Intrinsic::aarch64_sve_orr_z:
2402 return std::nullopt;
2405 Value *BinOpPred = BinOp->getOperand(0);
2406 Value *BinOpOp1 = BinOp->getOperand(1);
2407 Value *BinOpOp2 = BinOp->getOperand(2);
2409 Value *NarrowBinOpPred;
2411 return std::nullopt;
2413 Value *NarrowBinOpOp1 =
2415 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2416 if (BinOpOp1 != BinOpOp2)
2420 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2424static std::optional<Instruction *>
2431 return BinOpCombine;
2436 return std::nullopt;
2439 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2448 if (CursorVTy->getElementCount().getKnownMinValue() <
2449 IVTy->getElementCount().getKnownMinValue())
2453 if (Cursor->getType() == IVTy)
2454 EarliestReplacement = Cursor;
2459 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2460 Intrinsic::aarch64_sve_convert_to_svbool ||
2461 IntrinsicCursor->getIntrinsicID() ==
2462 Intrinsic::aarch64_sve_convert_from_svbool))
2465 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2466 Cursor = IntrinsicCursor->getOperand(0);
2471 if (!EarliestReplacement)
2472 return std::nullopt;
2480 auto *OpPredicate =
II.getOperand(0);
2497 II.getArgOperand(2));
2503 return std::nullopt;
2507 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2516 II.getArgOperand(0));
2525 if (!
II.hasOneUse())
2526 return std::nullopt;
2529 return std::nullopt;
2532 switch (
II.getIntrinsicID()) {
2533 case Intrinsic::aarch64_sve_cmpne:
2534 IID = Intrinsic::aarch64_sve_cmpeq;
2536 case Intrinsic::aarch64_sve_cmpne_wide:
2537 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2539 case Intrinsic::aarch64_sve_cmpeq:
2540 IID = Intrinsic::aarch64_sve_cmpne;
2542 case Intrinsic::aarch64_sve_cmpeq_wide:
2543 IID = Intrinsic::aarch64_sve_cmpne_wide;
2546 return std::nullopt;
2551 IID,
II.getOperand(1)->getType(),
2552 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2564 return std::nullopt;
2566 for (
auto *U :
II.users()) {
2569 Type *Ty =
II.getOperand(1)->getType();
2574 Intrinsic::aarch64_sve_umin, Ty,
2575 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2581 return std::nullopt;
2595 return std::nullopt;
2600 if (!SplatValue || !SplatValue->isZero())
2601 return std::nullopt;
2606 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2607 return std::nullopt;
2611 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2612 return std::nullopt;
2615 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2616 return std::nullopt;
2621 return std::nullopt;
2624 return std::nullopt;
2628 return std::nullopt;
2632 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2633 return std::nullopt;
2635 unsigned NumElts = VecTy->getNumElements();
2636 unsigned PredicateBits = 0;
2639 for (
unsigned I = 0;
I < NumElts; ++
I) {
2642 return std::nullopt;
2644 PredicateBits |= 1 << (
I * (16 / NumElts));
2648 if (PredicateBits == 0) {
2650 PFalse->takeName(&
II);
2656 for (
unsigned I = 0;
I < 16; ++
I)
2657 if ((PredicateBits & (1 <<
I)) != 0)
2660 unsigned PredSize = Mask & -Mask;
2665 for (
unsigned I = 0;
I < 16;
I += PredSize)
2666 if ((PredicateBits & (1 <<
I)) == 0)
2667 return std::nullopt;
2669 auto *ConvertToSVBool =
2672 auto *ConvertFromSVBool =
2674 II.getType(), ConvertToSVBool);
2682 Value *Pg =
II.getArgOperand(0);
2683 Value *Vec =
II.getArgOperand(1);
2684 auto IntrinsicID =
II.getIntrinsicID();
2685 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2697 auto OpC = OldBinOp->getOpcode();
2703 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2709 if (IsAfter &&
C &&
C->isNullValue()) {
2713 Extract->insertBefore(
II.getIterator());
2714 Extract->takeName(&
II);
2720 return std::nullopt;
2722 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2723 return std::nullopt;
2725 const auto PTruePattern =
2731 return std::nullopt;
2733 unsigned Idx = MinNumElts - 1;
2743 if (Idx >= PgVTy->getMinNumElements())
2744 return std::nullopt;
2749 Extract->insertBefore(
II.getIterator());
2750 Extract->takeName(&
II);
2763 Value *Pg =
II.getArgOperand(0);
2764 Value *Fallback =
II.getArgOperand(1);
2765 Value *Vec =
II.getArgOperand(2);
2768 if (!Ty->isIntegerTy())
2769 return std::nullopt;
2774 return std::nullopt;
2791 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2806static std::optional<Instruction *>
2810 if (
Pattern == AArch64SVEPredPattern::all) {
2819 return MinNumElts && NumElts >= MinNumElts
2821 II, ConstantInt::get(
II.getType(), MinNumElts)))
2825static std::optional<Instruction *>
2828 if (!ST->isStreaming())
2829 return std::nullopt;
2841 Value *PgVal =
II.getArgOperand(0);
2842 Value *OpVal =
II.getArgOperand(1);
2846 if (PgVal == OpVal &&
2847 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2848 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2863 return std::nullopt;
2867 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2868 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2882 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2883 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2884 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2885 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2886 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2887 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2888 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2889 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2890 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2891 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2892 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2893 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2894 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2904 return std::nullopt;
2907template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2908static std::optional<Instruction *>
2910 bool MergeIntoAddendOp) {
2912 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2913 if (MergeIntoAddendOp) {
2914 AddendOp =
II.getOperand(1);
2915 Mul =
II.getOperand(2);
2917 AddendOp =
II.getOperand(2);
2918 Mul =
II.getOperand(1);
2923 return std::nullopt;
2925 if (!
Mul->hasOneUse())
2926 return std::nullopt;
2929 if (
II.getType()->isFPOrFPVectorTy()) {
2934 return std::nullopt;
2936 return std::nullopt;
2941 if (MergeIntoAddendOp)
2951static std::optional<Instruction *>
2954 Value *PtrOp =
II.getOperand(1);
2955 Type *VecTy =
II.getType();
2970static std::optional<Instruction *>
2972 Value *VecOp =
II.getOperand(0);
2974 Value *PtrOp =
II.getOperand(2);
2990 case Intrinsic::aarch64_sve_fmul_u:
2991 return Instruction::BinaryOps::FMul;
2992 case Intrinsic::aarch64_sve_fadd_u:
2993 return Instruction::BinaryOps::FAdd;
2994 case Intrinsic::aarch64_sve_fsub_u:
2995 return Instruction::BinaryOps::FSub;
2997 return Instruction::BinaryOpsEnd;
3001static std::optional<Instruction *>
3004 if (
II.isStrictFP())
3005 return std::nullopt;
3007 auto *OpPredicate =
II.getOperand(0);
3009 if (BinOpCode == Instruction::BinaryOpsEnd ||
3011 return std::nullopt;
3013 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
3017static std::optional<Instruction *>
3019 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
3020 "Expected MLA_U intrinsic");
3021 Value *Acc =
II.getArgOperand(1);
3022 Value *MulOp0 =
II.getArgOperand(2);
3023 Value *MulOp1 =
II.getArgOperand(3);
3038 II.setArgOperand(2, MulOp1);
3039 II.setArgOperand(3, MulOp0);
3043 return std::nullopt;
3046static std::optional<Instruction *>
3048 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
3049 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
3050 "Expected SADALP or UADALP intrinsic");
3056 return std::nullopt;
3060 return std::nullopt;
3064 II.getIntrinsicID(), {II.getType()},
3065 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
3075 Intrinsic::aarch64_sve_mla>(
3079 Intrinsic::aarch64_sve_mad>(
3082 return std::nullopt;
3085static std::optional<Instruction *>
3089 Intrinsic::aarch64_sve_fmla>(IC,
II,
3094 Intrinsic::aarch64_sve_fmad>(IC,
II,
3099 Intrinsic::aarch64_sve_fmla>(IC,
II,
3102 return std::nullopt;
3105static std::optional<Instruction *>
3109 Intrinsic::aarch64_sve_fmla>(IC,
II,
3114 Intrinsic::aarch64_sve_fmad>(IC,
II,
3119 Intrinsic::aarch64_sve_fmla_u>(
3125static std::optional<Instruction *>
3129 Intrinsic::aarch64_sve_fmls>(IC,
II,
3134 Intrinsic::aarch64_sve_fnmsb>(
3139 Intrinsic::aarch64_sve_fmls>(IC,
II,
3142 return std::nullopt;
3145static std::optional<Instruction *>
3149 Intrinsic::aarch64_sve_fmls>(IC,
II,
3154 Intrinsic::aarch64_sve_fnmsb>(
3159 Intrinsic::aarch64_sve_fmls_u>(
3168 Intrinsic::aarch64_sve_mls>(
3171 return std::nullopt;
3176 Value *UnpackArg =
II.getArgOperand(0);
3178 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3179 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3192 return std::nullopt;
3196 auto *OpVal =
II.getOperand(0);
3197 auto *OpIndices =
II.getOperand(1);
3204 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3205 return std::nullopt;
3220 Type *RetTy =
II.getType();
3221 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3222 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3226 if ((
match(
II.getArgOperand(0),
3233 if (TyA ==
B->getType() &&
3238 TyA->getMinNumElements());
3244 return std::nullopt;
3252 if (
match(
II.getArgOperand(0),
3257 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3259 return std::nullopt;
3262static std::optional<Instruction *>
3264 Value *Mask =
II.getOperand(0);
3265 Value *BasePtr =
II.getOperand(1);
3266 Value *Index =
II.getOperand(2);
3277 BasePtr->getPointerAlignment(
II.getDataLayout());
3280 BasePtr, IndexBase);
3287 return std::nullopt;
3290static std::optional<Instruction *>
3292 Value *Val =
II.getOperand(0);
3293 Value *Mask =
II.getOperand(1);
3294 Value *BasePtr =
II.getOperand(2);
3295 Value *Index =
II.getOperand(3);
3305 BasePtr->getPointerAlignment(
II.getDataLayout());
3308 BasePtr, IndexBase);
3314 return std::nullopt;
3321 Value *Vec =
II.getOperand(1);
3322 Value *DivVec =
II.getOperand(2);
3326 if (!SplatConstantInt)
3327 return std::nullopt;
3331 if (DivisorValue == -1)
3332 return std::nullopt;
3333 if (DivisorValue == 1)
3339 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {
Pred, Vec, DivisorLog2});
3346 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {
Pred, Vec, DivisorLog2});
3348 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD,
Pred, ASRD});
3352 return std::nullopt;
3375 if (
I->getParent() != MainAnd->
getParent() ||
3383 size_t VecSize = Vec.
size();
3388 size_t HalfVecSize = VecSize / 2;
3392 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3400 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3416 return std::nullopt;
3423 return std::nullopt;
3430 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3431 CurrentInsertElt = InsertElt->getOperand(0);
3437 return std::nullopt;
3441 for (
size_t I = 0;
I < Elts.
size();
I++) {
3442 if (Elts[
I] ==
nullptr)
3447 if (InsertEltChain ==
nullptr)
3448 return std::nullopt;
3454 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3455 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3456 IIScalableTy->getMinNumElements() /
3461 auto *WideShuffleMaskTy =
3472 auto NarrowBitcast =
3485 return std::nullopt;
3491 Value *Vec =
II.getOperand(1);
3492 Value *Shift =
II.getOperand(2);
3495 Value *AbsPred, *MergedValue;
3501 return std::nullopt;
3509 return std::nullopt;
3514 return std::nullopt;
3517 {
II.getType()}, {
Pred, Vec, Shift});
3524 Value *Vec =
II.getOperand(0);
3529 return std::nullopt;
3532static std::optional<Instruction *>
3534 unsigned LookaheadThreshold) {
3536 auto *NI =
II.getNextNode();
3538 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3540 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3541 auto *NIBB = NI->getParent();
3542 NI = NI->getNextNode();
3544 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3545 NI = &*SuccBB->getFirstNonPHIOrLifetime();
3551 if (NextII &&
II.isIdenticalTo(NextII))
3554 return std::nullopt;
3562 {II.getType(), II.getOperand(0)->getType()},
3563 {II.getOperand(0), II.getOperand(1)}));
3570 if (PredPattern == AArch64SVEPredPattern::all ||
3571 PredPattern == AArch64SVEPredPattern::pow2)
3573 return std::nullopt;
3579 Value *Passthru =
II.getOperand(0);
3587 auto *Mask = ConstantInt::get(Ty, MaskValue);
3593 return std::nullopt;
3596static std::optional<Instruction *>
3603 return std::nullopt;
3609 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3619 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3629 return std::nullopt;
3635 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3643 return std::nullopt;
3646 II.getType(), {Pg, A, B});
3648 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3657 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3662 Value *
A, *PgLHS, *PgRHS;
3668 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3669 return std::nullopt;
3672 if (ConstB > ConstA)
3678 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3679 return std::nullopt;
3681 Type *VecTy =
A->getType();
3685 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3692std::optional<Instruction *>
3703 case Intrinsic::aarch64_dmb:
3705 case Intrinsic::aarch64_neon_fmaxnm:
3706 case Intrinsic::aarch64_neon_fminnm:
3708 case Intrinsic::aarch64_sve_convert_from_svbool:
3710 case Intrinsic::aarch64_sve_dup:
3712 case Intrinsic::aarch64_sve_dup_x:
3714 case Intrinsic::aarch64_sve_cmpeq:
3715 case Intrinsic::aarch64_sve_cmpeq_wide:
3717 case Intrinsic::aarch64_sve_cmpne:
3718 case Intrinsic::aarch64_sve_cmpne_wide:
3720 case Intrinsic::aarch64_sve_rdffr:
3722 case Intrinsic::aarch64_sve_lasta:
3723 case Intrinsic::aarch64_sve_lastb:
3725 case Intrinsic::aarch64_sve_clasta_n:
3726 case Intrinsic::aarch64_sve_clastb_n:
3728 case Intrinsic::aarch64_sve_cntd:
3730 case Intrinsic::aarch64_sve_cntw:
3732 case Intrinsic::aarch64_sve_cnth:
3734 case Intrinsic::aarch64_sve_cntb:
3736 case Intrinsic::aarch64_sme_cntsd:
3738 case Intrinsic::aarch64_sve_ptest_any:
3739 case Intrinsic::aarch64_sve_ptest_first:
3740 case Intrinsic::aarch64_sve_ptest_last:
3742 case Intrinsic::aarch64_sve_fadd:
3744 case Intrinsic::aarch64_sve_fadd_u:
3746 case Intrinsic::aarch64_sve_fmul_u:
3748 case Intrinsic::aarch64_sve_fsub:
3750 case Intrinsic::aarch64_sve_fsub_u:
3752 case Intrinsic::aarch64_sve_add:
3754 case Intrinsic::aarch64_sve_add_u:
3756 Intrinsic::aarch64_sve_mla_u>(
3758 case Intrinsic::aarch64_sve_mla_u:
3760 case Intrinsic::aarch64_sve_sadalp:
3761 case Intrinsic::aarch64_sve_uadalp:
3763 case Intrinsic::aarch64_sve_sub:
3765 case Intrinsic::aarch64_sve_sub_u:
3767 Intrinsic::aarch64_sve_mls_u>(
3769 case Intrinsic::aarch64_sve_tbl:
3771 case Intrinsic::aarch64_sve_uunpkhi:
3772 case Intrinsic::aarch64_sve_uunpklo:
3773 case Intrinsic::aarch64_sve_sunpkhi:
3774 case Intrinsic::aarch64_sve_sunpklo:
3776 case Intrinsic::aarch64_sve_uzp1:
3778 case Intrinsic::aarch64_sve_zip1:
3779 case Intrinsic::aarch64_sve_zip2:
3781 case Intrinsic::aarch64_sve_ld1_gather_index:
3783 case Intrinsic::aarch64_sve_st1_scatter_index:
3785 case Intrinsic::aarch64_sve_ld1:
3787 case Intrinsic::aarch64_sve_st1:
3789 case Intrinsic::aarch64_sve_sdiv:
3791 case Intrinsic::aarch64_sve_sel:
3793 case Intrinsic::aarch64_sve_srshl:
3795 case Intrinsic::aarch64_sve_dupq_lane:
3797 case Intrinsic::aarch64_sve_insr:
3799 case Intrinsic::aarch64_sve_whilelo:
3801 case Intrinsic::aarch64_sve_ptrue:
3803 case Intrinsic::aarch64_sve_uxtb:
3805 case Intrinsic::aarch64_sve_uxth:
3807 case Intrinsic::aarch64_sve_uxtw:
3809 case Intrinsic::aarch64_sme_in_streaming_mode:
3811 case Intrinsic::aarch64_sve_umin_u:
3813 case Intrinsic::aarch64_sve_orr_u:
3815 case Intrinsic::aarch64_sve_and_z:
3819 return std::nullopt;
3826 SimplifyAndSetOp)
const {
3827 switch (
II.getIntrinsicID()) {
3830 case Intrinsic::aarch64_neon_fcvtxn:
3831 case Intrinsic::aarch64_neon_rshrn:
3832 case Intrinsic::aarch64_neon_sqrshrn:
3833 case Intrinsic::aarch64_neon_sqrshrun:
3834 case Intrinsic::aarch64_neon_sqshrn:
3835 case Intrinsic::aarch64_neon_sqshrun:
3836 case Intrinsic::aarch64_neon_sqxtn:
3837 case Intrinsic::aarch64_neon_sqxtun:
3838 case Intrinsic::aarch64_neon_uqrshrn:
3839 case Intrinsic::aarch64_neon_uqshrn:
3840 case Intrinsic::aarch64_neon_uqxtn:
3841 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3845 return std::nullopt;
3849 return ST->isSVEAvailable() ||
3850 (ST->isSVEorStreamingSVEAvailable() &&
3851 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3860 if (ST->useSVEForFixedLengthVectors() &&
3861 (ST->isSVEAvailable() ||
3862 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3864 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3865 else if (ST->isNeonAvailable())
3870 if (ST->isSVEAvailable() ||
3871 (ST->isSVEorStreamingSVEAvailable() &&
3872 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3880bool AArch64TTIImpl::isSingleExtWideningInstruction(
3882 Type *SrcOverrideTy)
const {
3897 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3900 Type *SrcTy = SrcOverrideTy;
3902 case Instruction::Add:
3903 case Instruction::Sub: {
3912 if (Opcode == Instruction::Sub)
3936 assert(SrcTy &&
"Expected some SrcTy");
3938 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3944 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3946 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3950 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3953Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3955 Type *SrcOverrideTy)
const {
3956 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3957 Opcode != Instruction::Mul)
3967 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3970 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3976 ->getScalarSizeInBits();
3979 unsigned MaxEltSize = 0;
3982 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3983 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3984 MaxEltSize = std::max(EltSize0, EltSize1);
3987 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3988 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3991 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3993 MaxEltSize = DstEltSize / 2;
3994 }
else if (Opcode == Instruction::Mul &&
4002 Known.Zero.countLeadingOnes() >
4007 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
4011 if (MaxEltSize * 2 > DstEltSize)
4029 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
4030 (Src->isScalableTy() && !ST->hasSVE2()))
4040 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4044 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4048 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4049 Src->getScalarSizeInBits() !=
4073 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4087 if (
I && !
I->users().empty()) {
4091 auto GetUserAbsorbedCastCost =
4092 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4095 if (
Type *ExtTy = isBinExtWideningInstruction(
4097 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4110 if (isSingleExtWideningInstruction(
4112 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4116 if (Usr->getOpcode() == Instruction::Add) {
4117 if (
I == Usr->getOperand(1) ||
4129 return std::nullopt;
4138 unsigned SrcBits = Src->getScalarSizeInBits();
4141 Dst->getScalarSizeInBits() == 2 * SrcBits &&
4145 return std::nullopt;
4149 bool AllUsersAbsorbCast =
true;
4150 for (
const User *U :
I->users()) {
4152 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4154 AllUsersAbsorbCast =
false;
4157 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4160 if (AllUsersAbsorbCast)
4161 return MaxAbsorbedCost;
4171 Cmp->getParent() ==
I->getParent() &&
4176 EVT SrcTy = TLI->getValueType(
DL, Src);
4177 EVT DstTy = TLI->getValueType(
DL, Dst);
4181 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4191 bool SrcIsFloatOrVec =
4192 SrcLT.second.isVector() || SrcLT.second.isFloatingPoint();
4193 bool DstIsFloatOrVec =
4194 DstLT.second.isVector() || DstLT.second.isFloatingPoint();
4199 if (SrcIsFloatOrVec == DstIsFloatOrVec &&
4200 (SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits() ||
4201 (SrcLT.second.isScalableVector() &&
4202 SrcLT.second.getScalarSizeInBits() != 1 &&
4203 DstLT.second.getScalarSizeInBits() != 1)))
4206 return std::max(SrcLT.first, DstLT.first) *
4209 : ST->getVectorInsertExtractBaseCost());
4218 Instruction::ExtractElement, Src, CostKind, -1,
nullptr,
nullptr);
4220 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind);
4224 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4229 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4258 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4261 ST->useSVEForFixedLengthVectors(WiderTy)) {
4262 std::pair<InstructionCost, MVT> LT =
4264 unsigned NumElements =
4280 const unsigned int SVE_EXT_COST = 1;
4281 const unsigned int SVE_FCVT_COST = 1;
4282 const unsigned int SVE_UNPACK_ONCE = 4;
4283 const unsigned int SVE_UNPACK_TWICE = 16;
4412 SVE_EXT_COST + SVE_FCVT_COST},
4417 SVE_EXT_COST + SVE_FCVT_COST},
4424 SVE_EXT_COST + SVE_FCVT_COST},
4428 SVE_EXT_COST + SVE_FCVT_COST},
4434 SVE_EXT_COST + SVE_FCVT_COST},
4437 SVE_EXT_COST + SVE_FCVT_COST},
4442 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4444 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4454 SVE_EXT_COST + SVE_FCVT_COST},
4459 SVE_EXT_COST + SVE_FCVT_COST},
4472 SVE_EXT_COST + SVE_FCVT_COST},
4476 SVE_EXT_COST + SVE_FCVT_COST},
4488 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4490 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4492 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4494 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4498 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4500 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4516 SVE_EXT_COST + SVE_FCVT_COST},
4521 SVE_EXT_COST + SVE_FCVT_COST},
4532 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4534 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4536 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4538 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4540 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4542 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4546 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4548 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4550 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4552 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4767 if (ST->hasFullFP16())
4779 Src->getScalarType(), CCH, CostKind) +
4787 ST->isSVEorStreamingSVEAvailable() &&
4788 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4790 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4799 Opcode, LegalTy, Src, CCH, CostKind,
I);
4802 return Part1 + Part2;
4809 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4821 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4834 CostKind, Index,
nullptr,
nullptr);
4838 auto DstVT = TLI->getValueType(
DL, Dst);
4839 auto SrcVT = TLI->getValueType(
DL, Src);
4844 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4850 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4860 case Instruction::SExt:
4865 case Instruction::ZExt:
4866 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4879 return Opcode == Instruction::PHI ? 0 : 1;
4888 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4890 assert(Ty->isVectorTy() &&
"This must be a vector type");
4897 if (!LT.second.isVector())
4902 if (LT.second.isFixedLengthVector()) {
4903 unsigned Width = LT.second.getVectorNumElements();
4904 Index = Index % Width;
4911 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4923 if (Index * Ty->getScalarSizeInBits() < 128)
4925 if (Index * Ty->getScalarSizeInBits() < 512 &&
4926 Opcode == Instruction::ExtractElement)
4928 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4929 if (Opcode == Instruction::ExtractElement)
4931 if (Opcode == Instruction::InsertElement)
4940 if (VIC == TTI::VectorInstrContext::Load) {
4941 if (ST->hasFastLD1Single())
4945 : ST->getVectorInsertExtractBaseCost() + 1;
4953 : ST->getVectorInsertExtractBaseCost() + 1;
4977 auto ExtractCanFuseWithFmul = [&]() {
4984 auto IsAllowedScalarTy = [&](
const Type *
T) {
4985 return T->isFloatTy() ||
T->isDoubleTy() ||
4986 (
T->isHalfTy() && ST->hasFullFP16());
4990 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4993 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4994 !BO->getType()->isVectorTy();
4999 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
5003 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
5012 DenseMap<User *, unsigned> UserToExtractIdx;
5013 for (
auto *U :
Scalar->users()) {
5014 if (!IsUserFMulScalarTy(U))
5018 UserToExtractIdx[
U];
5020 if (UserToExtractIdx.
empty())
5022 for (
auto &[S, U, L] : ScalarUserAndIdx) {
5023 for (
auto *U : S->users()) {
5024 if (UserToExtractIdx.
contains(U)) {
5026 auto *Op0 =
FMul->getOperand(0);
5027 auto *Op1 =
FMul->getOperand(1);
5028 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
5029 UserToExtractIdx[
U] =
L;
5035 for (
auto &[U, L] : UserToExtractIdx) {
5047 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
5048 if (!IsUserFMulScalarTy(U))
5053 const auto *BO = cast<BinaryOperator>(U);
5054 const auto *OtherEE = dyn_cast<ExtractElementInst>(
5055 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
5057 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
5060 return IsExtractLaneEquivalentToZero(
5061 cast<ConstantInt>(OtherEE->getIndexOperand())
5064 OtherEE->getType()->getScalarSizeInBits());
5072 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
5073 ExtractCanFuseWithFmul())
5078 :
ST->getVectorInsertExtractBaseCost();
5087 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5090 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr,
nullptr,
5096 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5098 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr, Scalar,
5099 ScalarUserAndIdx, VIC);
5106 return getVectorInstrCostHelper(
I.getOpcode(), Ty, CostKind, Index, &
I,
5113 unsigned Index)
const {
5124 : ST->getVectorInsertExtractBaseCost() + 1;
5136 if (ST->hasFastLD1Single()) {
5137 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5138 (VIC == TTI::VectorInstrContext::Load && Insert))
5142 if (Ty->getElementType()->isFloatingPointTy())
5145 unsigned VecInstCost =
5147 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5154 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5155 return std::nullopt;
5156 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5157 return std::nullopt;
5159 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5160 return std::nullopt;
5167 Cost += InstCost(PromotedTy);
5182 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5193 if (Opcode == Instruction::And && CtxI->
hasOneUse() &&
5201 const auto *UI = cast<Instruction>(U);
5202 return is_contained({Instruction::And, Instruction::Or},
5211 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5217 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5218 Op2Info, Args, CtxI);
5224 if (
auto PromotedCost = getFP16BF16PromoteCost(
5225 Ty, CostKind, Op1Info, Op2Info,
true,
5228 [&](
Type *PromotedTy) {
5229 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
5232 return *PromotedCost;
5235 if (Ty->getScalarType()->isFP128Ty())
5243 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5245 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
5246 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
5253 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5263 ST->hasLimited64bitVectorMulBandwidth())
5271 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5274 if (
LT.second == MVT::v2i64) {
5278 return LT.first * Mul64CostFactor;
5291 (getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind) +
5299 if (
LT.second == MVT::nxv2i64)
5300 return LT.first * Mul64CostFactor;
5349 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5352 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5355 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5360 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5364 : (3 * AsrCost + AddCost);
5366 return MulCost + AsrCost + 2 * AddCost;
5368 }
else if (VT.isVector()) {
5379 Cost += 2 * AsrCost;
5384 ? (
LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5388 }
else if (
LT.second == MVT::v2i64) {
5389 return VT.getVectorNumElements() *
5390 getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind,
5397 return MulCost + 2 * AddCost + 2 * AsrCost;
5398 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5403 LT.second.isFixedLengthVector()) {
5409 CostKind, -1,
nullptr,
nullptr);
5411 CostKind, -1,
nullptr,
nullptr);
5413 return ExtractCost + InsertCost +
5425 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
5429 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
5437 bool HasMULH = VT == MVT::i64 ||
LT.second == MVT::nxv2i64 ||
5438 LT.second == MVT::nxv4i32 ||
LT.second == MVT::nxv8i16 ||
5439 LT.second == MVT::nxv16i8;
5440 bool Is128bit =
LT.second.is128BitVector();
5443 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5446 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5449 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5452 (HasMULH ? 0 : ShrCost) +
5453 AddCost * 2 + ShrCost;
5454 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5461 if (!VT.isVector() && VT.getSizeInBits() > 64)
5462 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5465 Opcode, Ty, CostKind, Op1Info, Op2Info);
5481 if (
nullptr != Entry)
5489 FVTy &&
LT.second.isFixedLengthVector()) {
5490 unsigned NumElts = FVTy->getNumElements();
5491 unsigned RegElts =
LT.second.getVectorNumElements();
5493 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5497 if (
LT.second.getScalarType() == MVT::i8)
5499 else if (
LT.second.getScalarType() == MVT::i16)
5512 return (4 + DivCost) * VTy->getNumElements();
5518 -1,
nullptr,
nullptr);
5545 LT.second.isFixedLengthVector())
5546 return 2 *
LT.first + 1;
5558 ((CtxI->hasOneUse() &&
5573 return 2 *
LT.first;
5575 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5581 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5582 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5595 unsigned NumVectorInstToHideOverhead =
5596 ST->getCLOpts().neon_nonconst_stride_overhead;
5597 int MaxMergeDistance = 64;
5601 return NumVectorInstToHideOverhead;
5613 unsigned Opcode1,
unsigned Opcode2)
const {
5616 if (!
Sched.hasInstrSchedModel())
5619 auto GetRThroughput = [&](
unsigned Opcode,
bool Highest) {
5620 std::optional<double> Res;
5622 while (!Worklist.
empty()) {
5626 append_range(Worklist, AArch64_MC::getVariantSchedClassTargets(
5627 SchedClass,
Sched.getProcessorID()));
5633 if (!Res || (Highest ? RThroughput > *Res : RThroughput < *Res))
5638 std::optional<double> RThroughput1 =
5639 GetRThroughput(Opcode1,
true);
5640 std::optional<double> RThroughput2 =
5641 GetRThroughput(Opcode2,
false);
5642 return RThroughput1 && RThroughput2 && *RThroughput1 > *RThroughput2;
5653 const int AmortizationCost = 20;
5661 VecPred = CurrentPred;
5669 static const auto ValidMinMaxTys = {
5670 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5671 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5672 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5676 (ST->hasFullFP16() &&
5682 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5683 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5684 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5685 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5686 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5687 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5688 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5689 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5690 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5691 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5692 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5694 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5695 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5704 if (Opcode == Instruction::FCmp) {
5706 ValTy, CostKind, Op1Info, Op2Info,
false,
5708 false, [&](
Type *PromotedTy) {
5711 CostKind, Op1Info, Op2Info);
5720 return *PromotedCost;
5724 if (LT.second.getScalarType() != MVT::f64 &&
5725 LT.second.getScalarType() != MVT::f32 &&
5726 LT.second.getScalarType() != MVT::f16)
5728 {ValTy, ValTy}, CostKind);
5731 unsigned Factor = 1;
5732 if (!CondTy->isVectorTy() &&
5746 AArch64::FCMEQv4f32))
5758 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5777 Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info,
I);
5781 AArch64::CMEQv4i32))
5789 if (ST->requiresStrictAlign()) {
5794 Options.AllowOverlappingLoads =
true;
5795 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5800 Options.LoadSizes = {8, 4, 2, 1};
5801 Options.AllowedTailExpansions = {3, 5, 6};
5806 return ST->hasSVE();
5812 switch (MICA.
getID()) {
5813 case Intrinsic::masked_scatter:
5814 case Intrinsic::masked_gather:
5816 case Intrinsic::masked_load:
5817 case Intrinsic::masked_store:
5818 case Intrinsic::masked_expandload:
5819 case Intrinsic::masked_compressstore:
5833 if (!LT.first.isValid())
5838 if (VT->getElementType()->isIntegerTy(1))
5844 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5850 if (MICA.
getID() == Intrinsic::masked_expandload) {
5864 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5885 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5886 return MemOpCost * 2;
5895 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5896 "Should be called on only load or stores.");
5898 case Instruction::Load:
5899 return ST->getCLOpts().sve_gather_overhead.value_or(
5900 ST->getGatherOverhead());
5902 case Instruction::Store:
5903 return ST->getCLOpts().sve_scatter_overhead.value_or(
5904 ST->getScatterOverhead());
5915 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5916 MICA.
getID() == Intrinsic::vp_gather)
5918 : Instruction::Store;
5928 if (!LT.first.isValid())
5932 if (!LT.second.isVector() ||
5934 VT->getElementType()->isIntegerTy(1))
5944 ElementCount LegalVF = LT.second.getVectorElementCount();
5947 {TTI::OK_AnyValue, TTI::OP_None},
I);
5963 EVT VT = TLI->getValueType(
DL, Ty,
true);
5965 if (VT == MVT::Other)
5970 if (!LT.first.isValid())
5976 if (VTy->getElementType()->isIntegerTy(1) &&
5977 !VTy->getElementCount().isKnownMultipleOf(
5983 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5984 : Intrinsic::masked_store;
5998 if (Opcode == Instruction::Store)
6002 if (ST->getFixedLoadLatency())
6003 return (LT.first - 1) + ST->getFixedLoadLatency();
6012 if (LT.second.isScalableVector() ||
6013 ST->useSVEForFixedLengthVectors(LT.second)) {
6014 Inst = AArch64::LDR_ZXI;
6015 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
6016 switch (LT.second.getSizeInBits()) {
6018 Inst = AArch64::LDRBui;
6021 Inst = AArch64::LDRHui;
6024 Inst = AArch64::LDRSui;
6027 Inst = AArch64::LDRDui;
6030 Inst = AArch64::LDRQui;
6036 switch (LT.second.getSizeInBits()) {
6038 Inst = AArch64::LDRBBui;
6041 Inst = AArch64::LDRHHui;
6044 Inst = AArch64::LDRWui;
6047 Inst = AArch64::LDRXui;
6055 unsigned SchedClass =
TII->get(Inst).getSchedClass();
6057 ?
Sched.getSchedClassDesc(SchedClass)
6063 return (LT.first - 1) + ST->getLoadLatency();
6066 float NumLoads = (LT.first - 1).
getValue();
6067 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
6068 Sched.computeInstrLatency(*ST, *SCD);
6071 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
6072 LT.second.is128BitVector() && Alignment <
Align(16)) {
6078 const int AmortizationCost = 6;
6080 return LT.first * 2 * AmortizationCost;
6084 if (Ty->isPtrOrPtrVectorTy())
6089 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
6091 if (VT == MVT::v4i8)
6098 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
6099 Alignment !=
Align(1))
6111 if (Remainder != 0) {
6114 while (!TypeWorklist.
empty()) {
6124 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6136 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6137 assert(Factor >= 2 &&
"Invalid interleave factor");
6146 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6150 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6155 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6160 (UseMaskForCond || UseMaskForGaps ||
6161 (Factor > MaxNativeInterleaveFactor &&
6162 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6165 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6168 EC.divideCoefficientBy(Factor));
6174 if (EC.isKnownMultipleOf(Factor) &&
6175 TLI->isLegalInterleavedAccessType(
SubVecTy,
DL, UseScalable))
6176 return Factor * TLI->getNumInterleavedAccesses(
SubVecTy,
DL, UseScalable);
6181 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6187 if (UseMaskForCond) {
6188 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6189 : Intrinsic::masked_store;
6209 if (Opcode == Instruction::Store && Factor == 4 &&
6210 SubVecCost.second.getScalarSizeInBits() ==
6211 (4 * ResultCost.second.getScalarSizeInBits()))
6212 LegalizationCost *= 4;
6214 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6220 UseMaskForCond, UseMaskForGaps);
6227 for (
auto *
I : Tys) {
6228 if (!
I->isVectorTy())
6239 Align Alignment)
const {
6249 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6250 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6262 Size.getFixedValue() <= 16;
6267 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6268 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6287 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6294 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6300 bool HasUnorderedReductions)
const {
6303 return ST->getMaxInterleaveFactor();
6313 enum { MaxStridedLoads = 7 };
6315 int StridedLoads = 0;
6318 for (
const auto BB : L->blocks()) {
6319 for (
auto &
I : *BB) {
6325 if (L->isLoopInvariant(PtrValue))
6330 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6339 if (StridedLoads > MaxStridedLoads / 2)
6340 return StridedLoads;
6343 return StridedLoads;
6346 int StridedLoads = countStridedLoads(L, SE);
6348 <<
" strided loads\n");
6364 unsigned *FinalSize) {
6368 for (
auto *BB : L->getBlocks()) {
6369 for (
auto &
I : *BB) {
6375 if (!Cost.isValid())
6379 if (LoopCost > Budget)
6401 if (MaxTC > 0 && MaxTC <= 32)
6412 if (Blocks.
size() != 2)
6434 if (!L->isInnermost() || L->getNumBlocks() > 8)
6438 if (!L->getExitBlock())
6444 bool HasParellelizableReductions =
6445 L->getNumBlocks() == 1 &&
6446 any_of(L->getHeader()->phis(),
6448 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6451 if (HasParellelizableReductions &&
6473 if (HasParellelizableReductions) {
6484 if (Header == Latch) {
6487 unsigned Width = 10;
6493 unsigned MaxInstsPerLine = 16;
6495 unsigned BestUC = 1;
6496 unsigned SizeWithBestUC = BestUC *
Size;
6498 unsigned SizeWithUC = UC *
Size;
6499 if (SizeWithUC > 48)
6501 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6502 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6504 SizeWithBestUC = BestUC *
Size;
6514 for (
auto *BB : L->blocks()) {
6515 for (
auto &
I : *BB) {
6525 for (
auto *U :
I.users())
6527 LoadedValuesPlus.
insert(U);
6534 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6560 auto *I = dyn_cast<Instruction>(V);
6561 return I && DependsOnLoopLoad(I, Depth + 1);
6568 DependsOnLoopLoad(
I, 0)) {
6600 if (L->getLoopDepth() > 1)
6611 for (
auto *BB : L->getBlocks()) {
6612 for (
auto &
I : *BB) {
6616 if (IsVectorized &&
I.getType()->isVectorTy())
6627 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6636 if (ST->isAppleMLike())
6638 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6639 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6660 !ST->getSchedModel().isOutOfOrder()) {
6672 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6683 bool CanCreate)
const {
6687 case Intrinsic::aarch64_neon_st1x2:
6688 case Intrinsic::aarch64_neon_st1x3:
6689 case Intrinsic::aarch64_neon_st1x4:
6690 case Intrinsic::aarch64_neon_st2:
6691 case Intrinsic::aarch64_neon_st3:
6692 case Intrinsic::aarch64_neon_st4: {
6695 if (!CanCreate || !ST)
6697 unsigned NumElts = Inst->
arg_size() - 1;
6698 if (ST->getNumElements() != NumElts)
6700 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6706 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6708 Res = Builder.CreateInsertValue(Res, L, i);
6712 case Intrinsic::aarch64_neon_ld1x2:
6713 case Intrinsic::aarch64_neon_ld1x3:
6714 case Intrinsic::aarch64_neon_ld1x4:
6715 case Intrinsic::aarch64_neon_ld2:
6716 case Intrinsic::aarch64_neon_ld3:
6717 case Intrinsic::aarch64_neon_ld4:
6718 if (Inst->
getType() == ExpectedType)
6729 case Intrinsic::aarch64_neon_ld1x2:
6730 case Intrinsic::aarch64_neon_ld1x3:
6731 case Intrinsic::aarch64_neon_ld1x4:
6732 case Intrinsic::aarch64_neon_ld2:
6733 case Intrinsic::aarch64_neon_ld3:
6734 case Intrinsic::aarch64_neon_ld4:
6735 Info.ReadMem =
true;
6736 Info.WriteMem =
false;
6739 case Intrinsic::aarch64_neon_st1x2:
6740 case Intrinsic::aarch64_neon_st1x3:
6741 case Intrinsic::aarch64_neon_st1x4:
6742 case Intrinsic::aarch64_neon_st2:
6743 case Intrinsic::aarch64_neon_st3:
6744 case Intrinsic::aarch64_neon_st4:
6745 Info.ReadMem =
false;
6746 Info.WriteMem =
true;
6755 case Intrinsic::aarch64_neon_ld1x2:
6756 case Intrinsic::aarch64_neon_st1x2:
6757 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6759 case Intrinsic::aarch64_neon_ld1x3:
6760 case Intrinsic::aarch64_neon_st1x3:
6761 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6763 case Intrinsic::aarch64_neon_ld1x4:
6764 case Intrinsic::aarch64_neon_st1x4:
6765 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6767 case Intrinsic::aarch64_neon_ld2:
6768 case Intrinsic::aarch64_neon_st2:
6769 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6771 case Intrinsic::aarch64_neon_ld3:
6772 case Intrinsic::aarch64_neon_st3:
6773 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6775 case Intrinsic::aarch64_neon_ld4:
6776 case Intrinsic::aarch64_neon_st4:
6777 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6789 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6790 bool Considerable =
false;
6791 AllowPromotionWithoutCommonHeader =
false;
6794 Type *ConsideredSExtType =
6796 if (
I.getType() != ConsideredSExtType)
6800 for (
const User *U :
I.users()) {
6802 Considerable =
true;
6806 if (GEPInst->getNumOperands() > 2) {
6807 AllowPromotionWithoutCommonHeader =
true;
6812 return Considerable;
6863 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6873 return LegalizationCost + 2;
6883 LegalizationCost *= LT.first - 1;
6886 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6895 return LegalizationCost + 2;
6903 std::optional<FastMathFlags> FMF,
6919 return BaseCost + FixedVTy->getNumElements();
6933 MVT MTy = LT.second;
6938 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6986 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6987 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6999 return (LT.first - 1) +
Log2_32(NElts);
7004 return (LT.first - 1) + Entry->Cost;
7016 if (LT.first != 1) {
7022 ExtraCost *= LT.first - 1;
7025 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
7026 return Cost + ExtraCost;
7034 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
7036 EVT VecVT = TLI->getValueType(
DL, VecTy);
7037 EVT ResVT = TLI->getValueType(
DL, ResTy);
7047 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7049 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
7051 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
7053 return (LT.first - 1) * 2 + 2;
7064 EVT VecVT = TLI->getValueType(
DL, VecTy);
7065 EVT ResVT = TLI->getValueType(
DL, ResTy);
7068 RedOpcode == Instruction::Add) {
7074 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7076 return LT.first + 2;
7111 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
7112 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7126 if (LT.second.getScalarType() == MVT::i1) {
7135 assert(Entry &&
"Illegal Type for Splice");
7136 LegalizationCost += Entry->Cost;
7137 return LegalizationCost * LT.first;
7141 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7150 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7151 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7157 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7158 if (!FMF->allowReassoc() || !FMF->allowContract())
7162 "FastMathFlags only apply to floating-point partial reductions");
7166 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7167 "Unexpected values for OpBExtend or InputTypeB");
7171 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7172 InputTypeA != InputTypeB))
7183 assert(!OpBExtend &&
"Extended second operand without extended first.");
7184 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7190 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7193 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7206 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7215 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7221 std::pair<InstructionCost, MVT> AccumLT =
7223 std::pair<InstructionCost, MVT> InputLT =
7227 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7228 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7229 (AccumLT.second.isFixedLengthVector() &&
7230 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7234 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7242 if (AccumLT.second.getScalarType() == MVT::i32 &&
7243 InputLT.second.getScalarType() == MVT::i8) {
7245 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7246 return Cost + INegCost;
7248 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7249 return Cost + INegCost;
7254 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7255 return Cost * 3 + INegCost;
7258 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7260 if (AccumLT.second.getScalarType() == MVT::i64 &&
7261 InputLT.second.getScalarType() == MVT::i16)
7262 return Cost + INegCost;
7265 if (AccumLT.second.getScalarType() == MVT::i32 &&
7266 InputLT.second.getScalarType() == MVT::i16 &&
7267 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7270 if (AccumLT.second.getScalarType() == MVT::i64 &&
7271 InputLT.second.getScalarType() == MVT::i8)
7274 return Cost + INegCost;
7277 if (AccumLT.second.getScalarType() == MVT::i16 &&
7278 InputLT.second.getScalarType() == MVT::i8 &&
7279 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7297 if ((!BinOp || IsSExtMul) && !IsSub &&
7298 AccumLT.second.getScalarType() == MVT::i64 &&
7299 InputLT.second.getScalarType() == MVT::i8 &&
7300 IsSupported(
false, ST->hasDotProd()))
7305 if (Opcode == Instruction::FAdd && !IsSub &&
7306 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7307 AccumLT.second.getScalarType() == MVT::f32 &&
7308 InputLT.second.getScalarType() == MVT::f16)
7312 if (Ratio == 2 && !IsUSDot) {
7313 MVT InVT = InputLT.second.getScalarType();
7317 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7319 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7322 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7326 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7327 InVT == MVT::bf16 && IsSub)
7337 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7338 return Cost * 2 + FNegCost;
7342 AccumType, VF, OpAExtend, OpBExtend,
7343 BinOp, CostKind, FMF);
7353 "Expected the Mask to match the return size if given");
7355 "Expected the same scalar types");
7361 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7362 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7363 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7371 return std::max<InstructionCost>(1, LT.first / 4);
7379 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7381 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7384 unsigned TpNumElts = Mask.size();
7385 unsigned LTNumElts = LT.second.getVectorNumElements();
7386 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7388 LT.second.getVectorElementCount());
7390 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7392 for (
unsigned N = 0;
N < NumVecs;
N++) {
7396 unsigned Source1 = -1U, Source2 = -1U;
7397 unsigned NumSources = 0;
7398 for (
unsigned E = 0; E < LTNumElts; E++) {
7399 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7408 unsigned Source = MaskElt / LTNumElts;
7409 if (NumSources == 0) {
7412 }
else if (NumSources == 1 && Source != Source1) {
7415 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7421 if (Source == Source1)
7423 else if (Source == Source2)
7424 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7433 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7444 NTp, NTp, CostKind, NMask, 0,
nullptr, Args,
7447 Result.first->second = NCost;
7461 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7462 if (LT.second.getFixedSizeInBits() >= 128 &&
7464 LT.second.getVectorNumElements() / 2) {
7467 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7481 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7484 return M.value() < 0 || M.value() == (int)M.index();
7490 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7491 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7500 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7501 ST->isSVEorStreamingSVEAvailable() &&
7506 if (ST->isSVEorStreamingSVEAvailable() &&
7520 if (IsLoad && LT.second.isVector() &&
7522 LT.second.getVectorElementCount()))
7528 if (Mask.size() == 4 &&
7530 (SrcTy->getScalarSizeInBits() == 16 ||
7531 SrcTy->getScalarSizeInBits() == 32) &&
7532 all_of(Mask, [](
int E) {
return E < 8; }))
7538 if (LT.second.isFixedLengthVector() &&
7539 LT.second.getVectorNumElements() == Mask.size() &&
7545 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7546 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7547 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7548 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7549 LT.second.getVectorNumElements(), 16) ||
7550 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7551 LT.second.getVectorNumElements(), 32) ||
7552 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7553 LT.second.getVectorNumElements(), 64) ||
7556 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7685 return LT.first * Entry->Cost;
7694 LT.second.getSizeInBits() <= 128 && SubTp) {
7696 if (SubLT.second.isVector()) {
7697 int NumElts = LT.second.getVectorNumElements();
7698 int NumSubElts = SubLT.second.getVectorNumElements();
7699 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7705 if (IsExtractSubvector)
7726 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7737 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7738 ST->useFixedOverScalableIfEqualCost());
7742 return ST->getEpilogueVectorizationMinVF();
7777 unsigned NumInsns = 0;
7779 NumInsns += BB->size();
7783 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7789 int64_t Scale,
unsigned AddrSpace)
const {
7812 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7817 if (
I->getOpcode() == Instruction::Or &&
7821 if (
I->getOpcode() == Instruction::Add ||
7822 I->getOpcode() == Instruction::Sub)
7838 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7839 return std::tie(
C1.NumRegs,
C1.Insns,
C1.NumPrePostIndex,
C1.NumBaseAdds,
7840 C1.AddRecCost,
C1.NumIVMuls,
C1.ScaleCost,
C1.ImmCost,
7851 return all_equal(Shuf->getShuffleMask());
7858 bool AllowSplat =
false) {
7863 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7864 auto *FullTy = FullV->
getType();
7865 auto *HalfTy = HalfV->getType();
7867 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7870 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7873 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7877 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7891 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7892 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7906 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7907 (M2Start != 0 && M2Start != (NumElements / 2)))
7909 if (S1Op1 && S2Op1 && M1Start != M2Start)
7919 return Ext->getType()->getScalarSizeInBits() ==
7920 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7934 Value *VectorOperand =
nullptr;
7951 if (!
GEP ||
GEP->getNumOperands() != 2)
7955 Value *Offsets =
GEP->getOperand(1);
7958 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7964 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7965 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7966 Ops.push_back(&
GEP->getOperandUse(1));
8006 switch (
II->getIntrinsicID()) {
8007 case Intrinsic::aarch64_neon_smull:
8008 case Intrinsic::aarch64_neon_umull:
8011 Ops.push_back(&
II->getOperandUse(0));
8012 Ops.push_back(&
II->getOperandUse(1));
8017 case Intrinsic::fma:
8018 case Intrinsic::fmuladd:
8025 Ops.push_back(&
II->getOperandUse(0));
8027 Ops.push_back(&
II->getOperandUse(1));
8030 case Intrinsic::aarch64_neon_sqdmull:
8031 case Intrinsic::aarch64_neon_sqdmulh:
8032 case Intrinsic::aarch64_neon_sqrdmulh:
8035 Ops.push_back(&
II->getOperandUse(0));
8037 Ops.push_back(&
II->getOperandUse(1));
8038 return !
Ops.empty();
8039 case Intrinsic::aarch64_neon_fmlal:
8040 case Intrinsic::aarch64_neon_fmlal2:
8041 case Intrinsic::aarch64_neon_fmlsl:
8042 case Intrinsic::aarch64_neon_fmlsl2:
8045 Ops.push_back(&
II->getOperandUse(1));
8047 Ops.push_back(&
II->getOperandUse(2));
8048 return !
Ops.empty();
8049 case Intrinsic::aarch64_sve_ptest_first:
8050 case Intrinsic::aarch64_sve_ptest_last:
8052 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
8053 Ops.push_back(&
II->getOperandUse(0));
8054 return !
Ops.empty();
8055 case Intrinsic::aarch64_sme_write_horiz:
8056 case Intrinsic::aarch64_sme_write_vert:
8057 case Intrinsic::aarch64_sme_writeq_horiz:
8058 case Intrinsic::aarch64_sme_writeq_vert: {
8060 if (!Idx || Idx->getOpcode() != Instruction::Add)
8062 Ops.push_back(&
II->getOperandUse(1));
8065 case Intrinsic::aarch64_sme_read_horiz:
8066 case Intrinsic::aarch64_sme_read_vert:
8067 case Intrinsic::aarch64_sme_readq_horiz:
8068 case Intrinsic::aarch64_sme_readq_vert:
8069 case Intrinsic::aarch64_sme_ld1b_vert:
8070 case Intrinsic::aarch64_sme_ld1h_vert:
8071 case Intrinsic::aarch64_sme_ld1w_vert:
8072 case Intrinsic::aarch64_sme_ld1d_vert:
8073 case Intrinsic::aarch64_sme_ld1q_vert:
8074 case Intrinsic::aarch64_sme_st1b_vert:
8075 case Intrinsic::aarch64_sme_st1h_vert:
8076 case Intrinsic::aarch64_sme_st1w_vert:
8077 case Intrinsic::aarch64_sme_st1d_vert:
8078 case Intrinsic::aarch64_sme_st1q_vert:
8079 case Intrinsic::aarch64_sme_ld1b_horiz:
8080 case Intrinsic::aarch64_sme_ld1h_horiz:
8081 case Intrinsic::aarch64_sme_ld1w_horiz:
8082 case Intrinsic::aarch64_sme_ld1d_horiz:
8083 case Intrinsic::aarch64_sme_ld1q_horiz:
8084 case Intrinsic::aarch64_sme_st1b_horiz:
8085 case Intrinsic::aarch64_sme_st1h_horiz:
8086 case Intrinsic::aarch64_sme_st1w_horiz:
8087 case Intrinsic::aarch64_sme_st1d_horiz:
8088 case Intrinsic::aarch64_sme_st1q_horiz: {
8090 if (!Idx || Idx->getOpcode() != Instruction::Add)
8092 Ops.push_back(&
II->getOperandUse(3));
8095 case Intrinsic::aarch64_neon_pmull:
8098 Ops.push_back(&
II->getOperandUse(0));
8099 Ops.push_back(&
II->getOperandUse(1));
8101 case Intrinsic::aarch64_neon_pmull64:
8103 II->getArgOperand(1)))
8105 Ops.push_back(&
II->getArgOperandUse(0));
8106 Ops.push_back(&
II->getArgOperandUse(1));
8108 case Intrinsic::masked_gather:
8111 Ops.push_back(&
II->getArgOperandUse(0));
8113 case Intrinsic::masked_scatter:
8116 Ops.push_back(&
II->getArgOperandUse(1));
8123 auto ShouldSinkCondition = [](
Value *
Cond,
8128 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8132 Ops.push_back(&
II->getOperandUse(0));
8136 switch (
I->getOpcode()) {
8137 case Instruction::Store: {
8140 if (!
SI->isSimple() || !
II)
8149 Ops.push_back(&
SI->getOperandUse(0));
8154 case Instruction::GetElementPtr:
8155 case Instruction::Add:
8156 case Instruction::Sub:
8158 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8160 Ops.push_back(&
I->getOperandUse(
Op));
8165 case Instruction::Select: {
8166 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8169 Ops.push_back(&
I->getOperandUse(0));
8172 case Instruction::UncondBr:
8174 case Instruction::CondBr: {
8178 Ops.push_back(&
I->getOperandUse(0));
8181 case Instruction::FMul:
8186 Ops.push_back(&
I->getOperandUse(0));
8188 Ops.push_back(&
I->getOperandUse(1));
8198 case Instruction::Xor:
8201 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8203 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8208 case Instruction::And:
8209 case Instruction::Or:
8212 if (
I->getOpcode() == Instruction::Or &&
8217 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8220 for (
auto &
Op :
I->operands()) {
8232 Ops.push_back(&Not);
8233 Ops.push_back(&InsertElt);
8243 if (!
I->getType()->isVectorTy())
8244 return !
Ops.empty();
8246 switch (
I->getOpcode()) {
8247 case Instruction::Sub:
8248 case Instruction::Add: {
8257 Ops.push_back(&Ext1->getOperandUse(0));
8258 Ops.push_back(&Ext2->getOperandUse(0));
8261 Ops.push_back(&
I->getOperandUse(0));
8262 Ops.push_back(&
I->getOperandUse(1));
8266 case Instruction::Or: {
8269 if (ST->hasNEON()) {
8276 Ops.push_back(&
I->getOperandUse(0));
8277 Ops.push_back(&
I->getOperandUse(1));
8285 case Instruction::Mul: {
8286 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8289 if (Ty->isScalableTy())
8293 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8296 int NumZExts = 0, NumSExts = 0;
8297 for (
auto &
Op :
I->operands()) {
8304 auto *ExtOp = Ext->getOperand(0);
8305 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8306 Ops.push_back(&Ext->getOperandUse(0));
8314 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8315 I->getType()->getScalarSizeInBits())
8352 if (!ElementConstant || !ElementConstant->
isZero())
8355 unsigned Opcode = OperandInstr->
getOpcode();
8356 if (Opcode == Instruction::SExt)
8358 else if (Opcode == Instruction::ZExt)
8363 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8373 Ops.push_back(&Insert->getOperandUse(1));
8379 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8383 if (!ShouldSinkSplatForIndexedVariant(
I))
8388 Ops.push_back(&
I->getOperandUse(0));
8390 Ops.push_back(&
I->getOperandUse(1));
8392 return !
Ops.empty();
8394 case Instruction::FMul: {
8396 if (
I->getType()->isScalableTy())
8397 return !
Ops.empty();
8401 return !
Ops.empty();
8405 Ops.push_back(&
I->getOperandUse(0));
8407 Ops.push_back(&
I->getOperandUse(1));
8408 return !
Ops.empty();
8417 Align Alignment)
const {
8418 if (!(ST->isSVEAvailable() ||
8419 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8423 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8430 if (!LT.first.isValid() || !LT.second.isVector())
8435 switch (LT.second.SimpleTy) {
const TargetLowering & TLI
static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static Error reportError(StringRef Message)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Cost tables and simple lookup functions.
This file defines the DenseMap class.
static Value * getCondition(Instruction *I)
const HexagonInstrInfo * TII
This file provides the interface for the instcombine pass implementation.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file defines the LoopVectorizationLegality class.
static const Function * getCalledFunction(const Value *V)
uint64_t IntrinsicInst * II
SmallVector< MachineOperand, 4 > Cond
static uint64_t getBits(uint64_t Val, int Start, int End)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
This file implements the C++20 <bit> header.
unsigned getVectorInsertExtractBaseCost() const
bool useSVEForFixedLengthVectors() const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getCostOfKeepingLiveOverCall(ArrayRef< Type * > Tys) const override
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool hasPossibleIncompatibleOps(const Function *F, bool ConsiderZA, bool ConsiderZT, bool ConsiderSM) const
Returns true if the function has explicit operations that can only be lowered using incompatible inst...
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src) const
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index) const override
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
bool preferFixedOverScalableIfEqualCost() const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops, const LoopInfo *LI) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind=TTI::TCK_RecipThroughput) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
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
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
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
RecurrenceSet & getFixedOrderRecurrences()
Return the fixed-order recurrences found in the loop.
DominatorTree * getDominatorTree() const
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
bool isFixedLengthVector() const
MVT getVectorElementType() const
Information for memory intrinsic cost model.
Align getAlignment() const
Type * getDataType() const
Intrinsic::ID getID() const
const Instruction * getInst() const
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
Type * getRecurrenceType() const
Returns the type of the recurrence.
RecurKind getRecurrenceKind() const
This node represents a polynomial recurrence on the trip count of the specified loop.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
This class represents an analyzed expression in the program.
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasStreamingInterfaceOrBody() const
SMECallAttrs is a utility class to hold the SMEAttrs for a callsite.
bool requiresSMChange() const
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
static ScalableVectorType * getDoubleElementsVectorType(ScalableVectorType *VTy)
The main scalar evolution driver.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI unsigned getSmallConstantTripMultiple(const Loop *L, const SCEV *ExitCount)
Returns the largest constant divisor of the trip count as a normal unsigned value,...
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
LLVM_ABI bool isBackedgeTakenCountMaxOrZero(const Loop *L)
Return true if the backedge taken count is either the value returned by getConstantMaxBackedgeTakenCo...
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
const SCEV * getSymbolicMaxBackedgeTakenCount(const Loop *L)
When successful, this returns a SCEV that is greater than or equal to (i.e.
This instruction constructs a fixed permutation of two input vectors.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isExtractSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &Index)
Return true if this shuffle mask is an extract subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Class to represent struct types.
TargetInstrInfo - Interface to description of machine instruction set.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
std::pair< LegalizeTypeAction, EVT > LegalizeKind
LegalizeKind holds the legalization kind that needs to happen to EVT in order to type-legalize it.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
bool isFP128Ty() const
Return true if this is 'fp128'.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static VectorType * getInteger(VectorType *VTy)
This static method gets a VectorType with the same number of elements as the input type,...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
constexpr 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))
FNeg_match< OpTy, true > m_FNegOrFSubNegZero(const OpTy &X)
Match fneg X or fsub -0.0, X.
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_Undef()
Match an arbitrary undef constant.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
LocationClass< Ty > location(Ty &L)
InstructionCost getVectorInstrCost(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, unsigned Opcode, Type *Val, const TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar, ArrayRef< std::tuple< Value *, User *, int > > ScalarUserAndIdx, TTI::VectorInstrContext VIC)
This is similar to TargetTransformInfo::getVectorInstrCost, but if ScalarTy is a FixedVectorType,...
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
std::optional< unsigned > isDUPQMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPQMask - matches a splat of equivalent lanes within segments of a given number of elements.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> (WhichResultOut = 0,...
TailFoldingOpts
An enum to describe what types of loops we should attempt to tail-fold: Disabled: None Reductions: Lo...
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool isDUPFirstSegmentMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPFirstSegmentMask - matches a splat of the first 128b segment.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
LLVM_ABI unsigned getInterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.interleaveN intrinsics.
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
CostTblEntryT< uint16_t > CostTblEntry
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
Return the number of active elements for VL1 to VL256 predicate pattern, zero for all other patterns.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
constexpr bool valueOr(BoolOrDefault X, bool Default)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
unsigned getMatchingIROpode() const
bool inactiveLanesAreUnused() const
bool inactiveLanesAreNotDefined() const
bool hasMatchingUndefIntrinsic() const
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
bool hasGoverningPredicate() const
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
CmpInst::Predicate getCmpPredicate() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
bool inactiveLanesTakenFromOperand() const
static SVEIntrinsicInfo defaultUndefOp()
bool hasOperandWithNoActiveLanes() const
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
bool hasCmpPredicate() const
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() const
bool hasMatchingIROpode() const
SVEIntrinsicInfo & setCmpPredicate(CmpInst::Predicate Pred)
bool resultIsZeroInitialized() const
SVEIntrinsicInfo & setMatchingIROpcode(unsigned Opcode)
unsigned getOperandIdxInactiveLanesTakenFrom() const
static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex)
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool 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*...