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);
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)
3418 return std::nullopt;
3425 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3426 CurrentInsertElt = InsertElt->getOperand(0);
3432 return std::nullopt;
3436 for (
size_t I = 0;
I < Elts.
size();
I++) {
3437 if (Elts[
I] ==
nullptr)
3442 if (InsertEltChain ==
nullptr)
3443 return std::nullopt;
3449 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3450 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3451 IIScalableTy->getMinNumElements() /
3456 auto *WideShuffleMaskTy =
3467 auto NarrowBitcast =
3480 return std::nullopt;
3486 Value *Vec =
II.getOperand(1);
3487 Value *Shift =
II.getOperand(2);
3490 Value *AbsPred, *MergedValue;
3496 return std::nullopt;
3504 return std::nullopt;
3509 return std::nullopt;
3512 {
II.getType()}, {
Pred, Vec, Shift});
3519 Value *Vec =
II.getOperand(0);
3524 return std::nullopt;
3527static std::optional<Instruction *>
3529 unsigned LookaheadThreshold) {
3531 auto *NI =
II.getNextNode();
3533 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3535 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3536 auto *NIBB = NI->getParent();
3537 NI = NI->getNextNode();
3539 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3540 NI = &*SuccBB->getFirstNonPHIOrLifetime();
3546 if (NextII &&
II.isIdenticalTo(NextII))
3549 return std::nullopt;
3557 {II.getType(), II.getOperand(0)->getType()},
3558 {II.getOperand(0), II.getOperand(1)}));
3565 if (PredPattern == AArch64SVEPredPattern::all ||
3566 PredPattern == AArch64SVEPredPattern::pow2)
3568 return std::nullopt;
3574 Value *Passthru =
II.getOperand(0);
3582 auto *Mask = ConstantInt::get(Ty, MaskValue);
3588 return std::nullopt;
3591static std::optional<Instruction *>
3598 return std::nullopt;
3604 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3614 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3624 return std::nullopt;
3630 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3638 return std::nullopt;
3641 II.getType(), {Pg, A, B});
3643 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3652 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3657 Value *
A, *PgLHS, *PgRHS;
3663 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3664 return std::nullopt;
3667 if (ConstB > ConstA)
3673 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3674 return std::nullopt;
3676 Type *VecTy =
A->getType();
3680 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3687std::optional<Instruction *>
3698 case Intrinsic::aarch64_dmb:
3700 case Intrinsic::aarch64_neon_fmaxnm:
3701 case Intrinsic::aarch64_neon_fminnm:
3703 case Intrinsic::aarch64_sve_convert_from_svbool:
3705 case Intrinsic::aarch64_sve_dup:
3707 case Intrinsic::aarch64_sve_dup_x:
3709 case Intrinsic::aarch64_sve_cmpeq:
3710 case Intrinsic::aarch64_sve_cmpeq_wide:
3712 case Intrinsic::aarch64_sve_cmpne:
3713 case Intrinsic::aarch64_sve_cmpne_wide:
3715 case Intrinsic::aarch64_sve_rdffr:
3717 case Intrinsic::aarch64_sve_lasta:
3718 case Intrinsic::aarch64_sve_lastb:
3720 case Intrinsic::aarch64_sve_clasta_n:
3721 case Intrinsic::aarch64_sve_clastb_n:
3723 case Intrinsic::aarch64_sve_cntd:
3725 case Intrinsic::aarch64_sve_cntw:
3727 case Intrinsic::aarch64_sve_cnth:
3729 case Intrinsic::aarch64_sve_cntb:
3731 case Intrinsic::aarch64_sme_cntsd:
3733 case Intrinsic::aarch64_sve_ptest_any:
3734 case Intrinsic::aarch64_sve_ptest_first:
3735 case Intrinsic::aarch64_sve_ptest_last:
3737 case Intrinsic::aarch64_sve_fadd:
3739 case Intrinsic::aarch64_sve_fadd_u:
3741 case Intrinsic::aarch64_sve_fmul_u:
3743 case Intrinsic::aarch64_sve_fsub:
3745 case Intrinsic::aarch64_sve_fsub_u:
3747 case Intrinsic::aarch64_sve_add:
3749 case Intrinsic::aarch64_sve_add_u:
3751 Intrinsic::aarch64_sve_mla_u>(
3753 case Intrinsic::aarch64_sve_mla_u:
3755 case Intrinsic::aarch64_sve_sadalp:
3756 case Intrinsic::aarch64_sve_uadalp:
3758 case Intrinsic::aarch64_sve_sub:
3760 case Intrinsic::aarch64_sve_sub_u:
3762 Intrinsic::aarch64_sve_mls_u>(
3764 case Intrinsic::aarch64_sve_tbl:
3766 case Intrinsic::aarch64_sve_uunpkhi:
3767 case Intrinsic::aarch64_sve_uunpklo:
3768 case Intrinsic::aarch64_sve_sunpkhi:
3769 case Intrinsic::aarch64_sve_sunpklo:
3771 case Intrinsic::aarch64_sve_uzp1:
3773 case Intrinsic::aarch64_sve_zip1:
3774 case Intrinsic::aarch64_sve_zip2:
3776 case Intrinsic::aarch64_sve_ld1_gather_index:
3778 case Intrinsic::aarch64_sve_st1_scatter_index:
3780 case Intrinsic::aarch64_sve_ld1:
3782 case Intrinsic::aarch64_sve_st1:
3784 case Intrinsic::aarch64_sve_sdiv:
3786 case Intrinsic::aarch64_sve_sel:
3788 case Intrinsic::aarch64_sve_srshl:
3790 case Intrinsic::aarch64_sve_dupq_lane:
3792 case Intrinsic::aarch64_sve_insr:
3794 case Intrinsic::aarch64_sve_whilelo:
3796 case Intrinsic::aarch64_sve_ptrue:
3798 case Intrinsic::aarch64_sve_uxtb:
3800 case Intrinsic::aarch64_sve_uxth:
3802 case Intrinsic::aarch64_sve_uxtw:
3804 case Intrinsic::aarch64_sme_in_streaming_mode:
3806 case Intrinsic::aarch64_sve_umin_u:
3808 case Intrinsic::aarch64_sve_orr_u:
3810 case Intrinsic::aarch64_sve_and_z:
3814 return std::nullopt;
3821 SimplifyAndSetOp)
const {
3822 switch (
II.getIntrinsicID()) {
3825 case Intrinsic::aarch64_neon_fcvtxn:
3826 case Intrinsic::aarch64_neon_rshrn:
3827 case Intrinsic::aarch64_neon_sqrshrn:
3828 case Intrinsic::aarch64_neon_sqrshrun:
3829 case Intrinsic::aarch64_neon_sqshrn:
3830 case Intrinsic::aarch64_neon_sqshrun:
3831 case Intrinsic::aarch64_neon_sqxtn:
3832 case Intrinsic::aarch64_neon_sqxtun:
3833 case Intrinsic::aarch64_neon_uqrshrn:
3834 case Intrinsic::aarch64_neon_uqshrn:
3835 case Intrinsic::aarch64_neon_uqxtn:
3836 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3840 return std::nullopt;
3844 return ST->isSVEAvailable() ||
3845 (ST->isSVEorStreamingSVEAvailable() &&
3846 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3855 if (ST->useSVEForFixedLengthVectors() &&
3856 (ST->isSVEAvailable() ||
3857 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3859 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3860 else if (ST->isNeonAvailable())
3865 if (ST->isSVEAvailable() ||
3866 (ST->isSVEorStreamingSVEAvailable() &&
3867 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3875bool AArch64TTIImpl::isSingleExtWideningInstruction(
3877 Type *SrcOverrideTy)
const {
3892 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3895 Type *SrcTy = SrcOverrideTy;
3897 case Instruction::Add:
3898 case Instruction::Sub: {
3907 if (Opcode == Instruction::Sub)
3931 assert(SrcTy &&
"Expected some SrcTy");
3933 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3939 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3941 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3945 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3948Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3950 Type *SrcOverrideTy)
const {
3951 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3952 Opcode != Instruction::Mul)
3962 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3965 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3971 ->getScalarSizeInBits();
3974 unsigned MaxEltSize = 0;
3977 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3978 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3979 MaxEltSize = std::max(EltSize0, EltSize1);
3982 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3983 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3986 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3988 MaxEltSize = DstEltSize / 2;
3989 }
else if (Opcode == Instruction::Mul &&
3997 Known.Zero.countLeadingOnes() >
4002 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
4006 if (MaxEltSize * 2 > DstEltSize)
4024 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
4025 (Src->isScalableTy() && !ST->hasSVE2()))
4035 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4039 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4043 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4044 Src->getScalarSizeInBits() !=
4068 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4082 if (
I && !
I->users().empty()) {
4086 auto GetUserAbsorbedCastCost =
4087 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4090 if (
Type *ExtTy = isBinExtWideningInstruction(
4092 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4105 if (isSingleExtWideningInstruction(
4107 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4111 if (Usr->getOpcode() == Instruction::Add) {
4112 if (
I == Usr->getOperand(1) ||
4124 return std::nullopt;
4133 unsigned SrcBits = Src->getScalarSizeInBits();
4136 Dst->getScalarSizeInBits() == 2 * SrcBits &&
4140 return std::nullopt;
4144 bool AllUsersAbsorbCast =
true;
4145 for (
const User *U :
I->users()) {
4147 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4149 AllUsersAbsorbCast =
false;
4152 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4155 if (AllUsersAbsorbCast)
4156 return MaxAbsorbedCost;
4166 Cmp->getParent() ==
I->getParent() &&
4171 EVT SrcTy = TLI->getValueType(
DL, Src);
4172 EVT DstTy = TLI->getValueType(
DL, Dst);
4176 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4186 bool SrcIsFloatOrVec =
4187 SrcLT.second.isVector() || SrcLT.second.isFloatingPoint();
4188 bool DstIsFloatOrVec =
4189 DstLT.second.isVector() || DstLT.second.isFloatingPoint();
4194 if (SrcIsFloatOrVec == DstIsFloatOrVec &&
4195 (SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits() ||
4196 (SrcLT.second.isScalableVector() &&
4197 SrcLT.second.getScalarSizeInBits() != 1 &&
4198 DstLT.second.getScalarSizeInBits() != 1)))
4201 return std::max(SrcLT.first, DstLT.first) *
4204 : ST->getVectorInsertExtractBaseCost());
4213 Instruction::ExtractElement, Src, CostKind, -1,
nullptr,
nullptr);
4215 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind);
4219 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4224 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4253 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4256 ST->useSVEForFixedLengthVectors(WiderTy)) {
4257 std::pair<InstructionCost, MVT> LT =
4259 unsigned NumElements =
4275 const unsigned int SVE_EXT_COST = 1;
4276 const unsigned int SVE_FCVT_COST = 1;
4277 const unsigned int SVE_UNPACK_ONCE = 4;
4278 const unsigned int SVE_UNPACK_TWICE = 16;
4407 SVE_EXT_COST + SVE_FCVT_COST},
4412 SVE_EXT_COST + SVE_FCVT_COST},
4419 SVE_EXT_COST + SVE_FCVT_COST},
4423 SVE_EXT_COST + SVE_FCVT_COST},
4429 SVE_EXT_COST + SVE_FCVT_COST},
4432 SVE_EXT_COST + SVE_FCVT_COST},
4437 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4439 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4449 SVE_EXT_COST + SVE_FCVT_COST},
4454 SVE_EXT_COST + SVE_FCVT_COST},
4467 SVE_EXT_COST + SVE_FCVT_COST},
4471 SVE_EXT_COST + SVE_FCVT_COST},
4483 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4485 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4487 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4489 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4493 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4495 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4511 SVE_EXT_COST + SVE_FCVT_COST},
4516 SVE_EXT_COST + SVE_FCVT_COST},
4527 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4529 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4531 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4533 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4535 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4537 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4541 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4543 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4545 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4547 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4762 if (ST->hasFullFP16())
4774 Src->getScalarType(), CCH, CostKind) +
4782 ST->isSVEorStreamingSVEAvailable() &&
4783 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4785 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4794 Opcode, LegalTy, Src, CCH, CostKind,
I);
4797 return Part1 + Part2;
4804 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4816 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4829 CostKind, Index,
nullptr,
nullptr);
4833 auto DstVT = TLI->getValueType(
DL, Dst);
4834 auto SrcVT = TLI->getValueType(
DL, Src);
4839 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4845 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4855 case Instruction::SExt:
4860 case Instruction::ZExt:
4861 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4874 return Opcode == Instruction::PHI ? 0 : 1;
4883 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4885 assert(Ty->isVectorTy() &&
"This must be a vector type");
4892 if (!LT.second.isVector())
4897 if (LT.second.isFixedLengthVector()) {
4898 unsigned Width = LT.second.getVectorNumElements();
4899 Index = Index % Width;
4906 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4918 if (Index * Ty->getScalarSizeInBits() < 128)
4920 if (Index * Ty->getScalarSizeInBits() < 512 &&
4921 Opcode == Instruction::ExtractElement)
4923 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4924 if (Opcode == Instruction::ExtractElement)
4926 if (Opcode == Instruction::InsertElement)
4935 if (VIC == TTI::VectorInstrContext::Load) {
4936 if (ST->hasFastLD1Single())
4940 : ST->getVectorInsertExtractBaseCost() + 1;
4948 : ST->getVectorInsertExtractBaseCost() + 1;
4972 auto ExtractCanFuseWithFmul = [&]() {
4979 auto IsAllowedScalarTy = [&](
const Type *
T) {
4980 return T->isFloatTy() ||
T->isDoubleTy() ||
4981 (
T->isHalfTy() && ST->hasFullFP16());
4985 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4988 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4989 !BO->getType()->isVectorTy();
4994 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4998 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
5007 DenseMap<User *, unsigned> UserToExtractIdx;
5008 for (
auto *U :
Scalar->users()) {
5009 if (!IsUserFMulScalarTy(U))
5013 UserToExtractIdx[
U];
5015 if (UserToExtractIdx.
empty())
5017 for (
auto &[S, U, L] : ScalarUserAndIdx) {
5018 for (
auto *U : S->users()) {
5019 if (UserToExtractIdx.
contains(U)) {
5021 auto *Op0 =
FMul->getOperand(0);
5022 auto *Op1 =
FMul->getOperand(1);
5023 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
5024 UserToExtractIdx[
U] =
L;
5030 for (
auto &[U, L] : UserToExtractIdx) {
5042 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
5043 if (!IsUserFMulScalarTy(U))
5048 const auto *BO = cast<BinaryOperator>(U);
5049 const auto *OtherEE = dyn_cast<ExtractElementInst>(
5050 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
5052 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
5055 return IsExtractLaneEquivalentToZero(
5056 cast<ConstantInt>(OtherEE->getIndexOperand())
5059 OtherEE->getType()->getScalarSizeInBits());
5067 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
5068 ExtractCanFuseWithFmul())
5073 :
ST->getVectorInsertExtractBaseCost();
5082 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5085 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr,
nullptr,
5091 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5093 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr, Scalar,
5094 ScalarUserAndIdx, VIC);
5101 return getVectorInstrCostHelper(
I.getOpcode(), Ty, CostKind, Index, &
I,
5108 unsigned Index)
const {
5119 : ST->getVectorInsertExtractBaseCost() + 1;
5131 if (ST->hasFastLD1Single()) {
5132 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5133 (VIC == TTI::VectorInstrContext::Load && Insert))
5137 if (Ty->getElementType()->isFloatingPointTy())
5140 unsigned VecInstCost =
5142 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5149 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5150 return std::nullopt;
5151 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5152 return std::nullopt;
5154 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5155 return std::nullopt;
5162 Cost += InstCost(PromotedTy);
5177 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5188 if (Opcode == Instruction::And && CtxI->
hasOneUse() &&
5196 const auto *UI = cast<Instruction>(U);
5197 return is_contained({Instruction::And, Instruction::Or},
5206 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5212 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5213 Op2Info, Args, CtxI);
5219 if (
auto PromotedCost = getFP16BF16PromoteCost(
5220 Ty, CostKind, Op1Info, Op2Info,
true,
5223 [&](
Type *PromotedTy) {
5224 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
5227 return *PromotedCost;
5230 if (Ty->getScalarType()->isFP128Ty())
5238 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5240 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
5241 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
5248 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5258 ST->hasLimited64bitVectorMulBandwidth())
5266 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5269 if (
LT.second == MVT::v2i64) {
5273 return LT.first * Mul64CostFactor;
5286 (getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind) +
5294 if (
LT.second == MVT::nxv2i64)
5295 return LT.first * Mul64CostFactor;
5344 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5347 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5350 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5355 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5359 : (3 * AsrCost + AddCost);
5361 return MulCost + AsrCost + 2 * AddCost;
5363 }
else if (VT.isVector()) {
5374 Cost += 2 * AsrCost;
5379 ? (
LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5383 }
else if (
LT.second == MVT::v2i64) {
5384 return VT.getVectorNumElements() *
5385 getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind,
5392 return MulCost + 2 * AddCost + 2 * AsrCost;
5393 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5398 LT.second.isFixedLengthVector()) {
5404 CostKind, -1,
nullptr,
nullptr);
5406 CostKind, -1,
nullptr,
nullptr);
5408 return ExtractCost + InsertCost +
5420 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
5424 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
5432 bool HasMULH = VT == MVT::i64 ||
LT.second == MVT::nxv2i64 ||
5433 LT.second == MVT::nxv4i32 ||
LT.second == MVT::nxv8i16 ||
5434 LT.second == MVT::nxv16i8;
5435 bool Is128bit =
LT.second.is128BitVector();
5438 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5441 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5444 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5447 (HasMULH ? 0 : ShrCost) +
5448 AddCost * 2 + ShrCost;
5449 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5456 if (!VT.isVector() && VT.getSizeInBits() > 64)
5457 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5460 Opcode, Ty, CostKind, Op1Info, Op2Info);
5476 if (
nullptr != Entry)
5484 FVTy &&
LT.second.isFixedLengthVector()) {
5485 unsigned NumElts = FVTy->getNumElements();
5486 unsigned RegElts =
LT.second.getVectorNumElements();
5488 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5492 if (
LT.second.getScalarType() == MVT::i8)
5494 else if (
LT.second.getScalarType() == MVT::i16)
5507 return (4 + DivCost) * VTy->getNumElements();
5513 -1,
nullptr,
nullptr);
5540 LT.second.isFixedLengthVector())
5541 return 2 *
LT.first + 1;
5553 ((CtxI->hasOneUse() &&
5568 return 2 *
LT.first;
5570 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5576 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5577 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5590 unsigned NumVectorInstToHideOverhead =
5591 ST->getCLOpts().neon_nonconst_stride_overhead;
5592 int MaxMergeDistance = 64;
5596 return NumVectorInstToHideOverhead;
5608 unsigned Opcode1,
unsigned Opcode2)
const {
5611 if (!
Sched.hasInstrSchedModel())
5614 auto GetRThroughput = [&](
unsigned Opcode,
bool Highest) {
5615 std::optional<double> Res;
5617 while (!Worklist.
empty()) {
5621 append_range(Worklist, AArch64_MC::getVariantSchedClassTargets(
5622 SchedClass,
Sched.getProcessorID()));
5628 if (!Res || (Highest ? RThroughput > *Res : RThroughput < *Res))
5633 std::optional<double> RThroughput1 =
5634 GetRThroughput(Opcode1,
true);
5635 std::optional<double> RThroughput2 =
5636 GetRThroughput(Opcode2,
false);
5637 return RThroughput1 && RThroughput2 && *RThroughput1 > *RThroughput2;
5648 const int AmortizationCost = 20;
5656 VecPred = CurrentPred;
5664 static const auto ValidMinMaxTys = {
5665 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5666 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5667 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5671 (ST->hasFullFP16() &&
5677 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5678 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5679 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5680 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5681 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5682 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5683 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5684 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5685 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5686 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5687 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5689 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5690 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5699 if (Opcode == Instruction::FCmp) {
5701 ValTy, CostKind, Op1Info, Op2Info,
false,
5703 false, [&](
Type *PromotedTy) {
5706 CostKind, Op1Info, Op2Info);
5715 return *PromotedCost;
5719 if (LT.second.getScalarType() != MVT::f64 &&
5720 LT.second.getScalarType() != MVT::f32 &&
5721 LT.second.getScalarType() != MVT::f16)
5723 {ValTy, ValTy}, CostKind);
5726 unsigned Factor = 1;
5727 if (!CondTy->isVectorTy() &&
5741 AArch64::FCMEQv4f32))
5753 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5772 Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info,
I);
5776 AArch64::CMEQv4i32))
5784 if (ST->requiresStrictAlign()) {
5789 Options.AllowOverlappingLoads =
true;
5790 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5795 Options.LoadSizes = {8, 4, 2, 1};
5796 Options.AllowedTailExpansions = {3, 5, 6};
5801 return ST->hasSVE();
5807 switch (MICA.
getID()) {
5808 case Intrinsic::masked_scatter:
5809 case Intrinsic::masked_gather:
5811 case Intrinsic::masked_load:
5812 case Intrinsic::masked_store:
5813 case Intrinsic::masked_expandload:
5814 case Intrinsic::masked_compressstore:
5828 if (!LT.first.isValid())
5833 if (VT->getElementType()->isIntegerTy(1))
5839 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5845 if (MICA.
getID() == Intrinsic::masked_expandload) {
5858 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5878 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5879 return MemOpCost * 2;
5888 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5889 "Should be called on only load or stores.");
5891 case Instruction::Load:
5892 return ST->getCLOpts().sve_gather_overhead.value_or(
5893 ST->getGatherOverhead());
5895 case Instruction::Store:
5896 return ST->getCLOpts().sve_scatter_overhead.value_or(
5897 ST->getScatterOverhead());
5908 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5909 MICA.
getID() == Intrinsic::vp_gather)
5911 : Instruction::Store;
5921 if (!LT.first.isValid())
5925 if (!LT.second.isVector() ||
5927 VT->getElementType()->isIntegerTy(1))
5937 ElementCount LegalVF = LT.second.getVectorElementCount();
5940 {TTI::OK_AnyValue, TTI::OP_None},
I);
5956 EVT VT = TLI->getValueType(
DL, Ty,
true);
5958 if (VT == MVT::Other)
5963 if (!LT.first.isValid())
5969 if (VTy->getElementType()->isIntegerTy(1) &&
5970 !VTy->getElementCount().isKnownMultipleOf(
5976 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5977 : Intrinsic::masked_store;
5991 if (Opcode == Instruction::Store)
5995 if (ST->getFixedLoadLatency())
5996 return (LT.first - 1) + ST->getFixedLoadLatency();
6005 if (LT.second.isScalableVector() ||
6006 ST->useSVEForFixedLengthVectors(LT.second)) {
6007 Inst = AArch64::LDR_ZXI;
6008 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
6009 switch (LT.second.getSizeInBits()) {
6011 Inst = AArch64::LDRBui;
6014 Inst = AArch64::LDRHui;
6017 Inst = AArch64::LDRSui;
6020 Inst = AArch64::LDRDui;
6023 Inst = AArch64::LDRQui;
6029 switch (LT.second.getSizeInBits()) {
6031 Inst = AArch64::LDRBBui;
6034 Inst = AArch64::LDRHHui;
6037 Inst = AArch64::LDRWui;
6040 Inst = AArch64::LDRXui;
6048 unsigned SchedClass =
TII->get(Inst).getSchedClass();
6050 ?
Sched.getSchedClassDesc(SchedClass)
6056 return (LT.first - 1) + ST->getLoadLatency();
6059 float NumLoads = (LT.first - 1).
getValue();
6060 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
6061 Sched.computeInstrLatency(*ST, *SCD);
6064 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
6065 LT.second.is128BitVector() && Alignment <
Align(16)) {
6071 const int AmortizationCost = 6;
6073 return LT.first * 2 * AmortizationCost;
6077 if (Ty->isPtrOrPtrVectorTy())
6082 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
6084 if (VT == MVT::v4i8)
6091 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
6092 Alignment !=
Align(1))
6104 if (Remainder != 0) {
6107 while (!TypeWorklist.
empty()) {
6117 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6129 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6130 assert(Factor >= 2 &&
"Invalid interleave factor");
6139 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6143 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6148 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6153 (UseMaskForCond || UseMaskForGaps ||
6154 (Factor > MaxNativeInterleaveFactor &&
6155 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6158 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6161 EC.divideCoefficientBy(Factor));
6167 if (EC.isKnownMultipleOf(Factor) &&
6168 TLI->isLegalInterleavedAccessType(
SubVecTy,
DL, UseScalable))
6169 return Factor * TLI->getNumInterleavedAccesses(
SubVecTy,
DL, UseScalable);
6174 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6180 if (UseMaskForCond) {
6181 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6182 : Intrinsic::masked_store;
6202 if (Opcode == Instruction::Store && Factor == 4 &&
6203 SubVecCost.second.getScalarSizeInBits() ==
6204 (4 * ResultCost.second.getScalarSizeInBits()))
6205 LegalizationCost *= 4;
6207 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6213 UseMaskForCond, UseMaskForGaps);
6220 for (
auto *
I : Tys) {
6221 if (!
I->isVectorTy())
6232 Align Alignment)
const {
6239 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6240 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6252 Size.getFixedValue() <= 16;
6257 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6258 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6277 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6284 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6290 bool HasUnorderedReductions)
const {
6293 return ST->getMaxInterleaveFactor();
6303 enum { MaxStridedLoads = 7 };
6305 int StridedLoads = 0;
6308 for (
const auto BB : L->blocks()) {
6309 for (
auto &
I : *BB) {
6315 if (L->isLoopInvariant(PtrValue))
6320 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6329 if (StridedLoads > MaxStridedLoads / 2)
6330 return StridedLoads;
6333 return StridedLoads;
6336 int StridedLoads = countStridedLoads(L, SE);
6338 <<
" strided loads\n");
6354 unsigned *FinalSize) {
6358 for (
auto *BB : L->getBlocks()) {
6359 for (
auto &
I : *BB) {
6365 if (!Cost.isValid())
6369 if (LoopCost > Budget)
6391 if (MaxTC > 0 && MaxTC <= 32)
6402 if (Blocks.
size() != 2)
6424 if (!L->isInnermost() || L->getNumBlocks() > 8)
6428 if (!L->getExitBlock())
6434 bool HasParellelizableReductions =
6435 L->getNumBlocks() == 1 &&
6436 any_of(L->getHeader()->phis(),
6438 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6441 if (HasParellelizableReductions &&
6463 if (HasParellelizableReductions) {
6474 if (Header == Latch) {
6477 unsigned Width = 10;
6483 unsigned MaxInstsPerLine = 16;
6485 unsigned BestUC = 1;
6486 unsigned SizeWithBestUC = BestUC *
Size;
6488 unsigned SizeWithUC = UC *
Size;
6489 if (SizeWithUC > 48)
6491 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6492 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6494 SizeWithBestUC = BestUC *
Size;
6504 for (
auto *BB : L->blocks()) {
6505 for (
auto &
I : *BB) {
6515 for (
auto *U :
I.users())
6517 LoadedValuesPlus.
insert(U);
6524 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6550 auto *I = dyn_cast<Instruction>(V);
6551 return I && DependsOnLoopLoad(I, Depth + 1);
6558 DependsOnLoopLoad(
I, 0)) {
6590 if (L->getLoopDepth() > 1)
6601 for (
auto *BB : L->getBlocks()) {
6602 for (
auto &
I : *BB) {
6606 if (IsVectorized &&
I.getType()->isVectorTy())
6617 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6626 if (ST->isAppleMLike())
6628 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6629 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6650 !ST->getSchedModel().isOutOfOrder()) {
6662 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6673 bool CanCreate)
const {
6677 case Intrinsic::aarch64_neon_st1x2:
6678 case Intrinsic::aarch64_neon_st1x3:
6679 case Intrinsic::aarch64_neon_st1x4:
6680 case Intrinsic::aarch64_neon_st2:
6681 case Intrinsic::aarch64_neon_st3:
6682 case Intrinsic::aarch64_neon_st4: {
6685 if (!CanCreate || !ST)
6687 unsigned NumElts = Inst->
arg_size() - 1;
6688 if (ST->getNumElements() != NumElts)
6690 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6696 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6698 Res = Builder.CreateInsertValue(Res, L, i);
6702 case Intrinsic::aarch64_neon_ld1x2:
6703 case Intrinsic::aarch64_neon_ld1x3:
6704 case Intrinsic::aarch64_neon_ld1x4:
6705 case Intrinsic::aarch64_neon_ld2:
6706 case Intrinsic::aarch64_neon_ld3:
6707 case Intrinsic::aarch64_neon_ld4:
6708 if (Inst->
getType() == ExpectedType)
6719 case Intrinsic::aarch64_neon_ld1x2:
6720 case Intrinsic::aarch64_neon_ld1x3:
6721 case Intrinsic::aarch64_neon_ld1x4:
6722 case Intrinsic::aarch64_neon_ld2:
6723 case Intrinsic::aarch64_neon_ld3:
6724 case Intrinsic::aarch64_neon_ld4:
6725 Info.ReadMem =
true;
6726 Info.WriteMem =
false;
6729 case Intrinsic::aarch64_neon_st1x2:
6730 case Intrinsic::aarch64_neon_st1x3:
6731 case Intrinsic::aarch64_neon_st1x4:
6732 case Intrinsic::aarch64_neon_st2:
6733 case Intrinsic::aarch64_neon_st3:
6734 case Intrinsic::aarch64_neon_st4:
6735 Info.ReadMem =
false;
6736 Info.WriteMem =
true;
6745 case Intrinsic::aarch64_neon_ld1x2:
6746 case Intrinsic::aarch64_neon_st1x2:
6747 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6749 case Intrinsic::aarch64_neon_ld1x3:
6750 case Intrinsic::aarch64_neon_st1x3:
6751 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6753 case Intrinsic::aarch64_neon_ld1x4:
6754 case Intrinsic::aarch64_neon_st1x4:
6755 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6757 case Intrinsic::aarch64_neon_ld2:
6758 case Intrinsic::aarch64_neon_st2:
6759 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6761 case Intrinsic::aarch64_neon_ld3:
6762 case Intrinsic::aarch64_neon_st3:
6763 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6765 case Intrinsic::aarch64_neon_ld4:
6766 case Intrinsic::aarch64_neon_st4:
6767 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6779 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6780 bool Considerable =
false;
6781 AllowPromotionWithoutCommonHeader =
false;
6784 Type *ConsideredSExtType =
6786 if (
I.getType() != ConsideredSExtType)
6790 for (
const User *U :
I.users()) {
6792 Considerable =
true;
6796 if (GEPInst->getNumOperands() > 2) {
6797 AllowPromotionWithoutCommonHeader =
true;
6802 return Considerable;
6853 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6863 return LegalizationCost + 2;
6873 LegalizationCost *= LT.first - 1;
6876 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6885 return LegalizationCost + 2;
6893 std::optional<FastMathFlags> FMF,
6909 return BaseCost + FixedVTy->getNumElements();
6923 MVT MTy = LT.second;
6928 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6976 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6977 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6989 return (LT.first - 1) +
Log2_32(NElts);
6994 return (LT.first - 1) + Entry->Cost;
7006 if (LT.first != 1) {
7012 ExtraCost *= LT.first - 1;
7015 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
7016 return Cost + ExtraCost;
7024 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
7026 EVT VecVT = TLI->getValueType(
DL, VecTy);
7027 EVT ResVT = TLI->getValueType(
DL, ResTy);
7037 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7039 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
7041 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
7043 return (LT.first - 1) * 2 + 2;
7054 EVT VecVT = TLI->getValueType(
DL, VecTy);
7055 EVT ResVT = TLI->getValueType(
DL, ResTy);
7058 RedOpcode == Instruction::Add) {
7064 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7066 return LT.first + 2;
7101 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
7102 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7116 if (LT.second.getScalarType() == MVT::i1) {
7125 assert(Entry &&
"Illegal Type for Splice");
7126 LegalizationCost += Entry->Cost;
7127 return LegalizationCost * LT.first;
7131 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7140 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7141 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7147 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7148 if (!FMF->allowReassoc() || !FMF->allowContract())
7152 "FastMathFlags only apply to floating-point partial reductions");
7156 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7157 "Unexpected values for OpBExtend or InputTypeB");
7161 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7162 InputTypeA != InputTypeB))
7173 assert(!OpBExtend &&
"Extended second operand without extended first.");
7174 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7180 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7183 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7196 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7205 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7211 std::pair<InstructionCost, MVT> AccumLT =
7213 std::pair<InstructionCost, MVT> InputLT =
7217 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7218 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7219 (AccumLT.second.isFixedLengthVector() &&
7220 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7224 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7232 if (AccumLT.second.getScalarType() == MVT::i32 &&
7233 InputLT.second.getScalarType() == MVT::i8) {
7235 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7236 return Cost + INegCost;
7238 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7239 return Cost + INegCost;
7244 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7245 return Cost * 3 + INegCost;
7248 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7250 if (AccumLT.second.getScalarType() == MVT::i64 &&
7251 InputLT.second.getScalarType() == MVT::i16)
7252 return Cost + INegCost;
7255 if (AccumLT.second.getScalarType() == MVT::i32 &&
7256 InputLT.second.getScalarType() == MVT::i16 &&
7257 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7260 if (AccumLT.second.getScalarType() == MVT::i64 &&
7261 InputLT.second.getScalarType() == MVT::i8)
7264 return Cost + INegCost;
7267 if (AccumLT.second.getScalarType() == MVT::i16 &&
7268 InputLT.second.getScalarType() == MVT::i8 &&
7269 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7287 if ((!BinOp || IsSExtMul) && !IsSub &&
7288 AccumLT.second.getScalarType() == MVT::i64 &&
7289 InputLT.second.getScalarType() == MVT::i8 &&
7290 IsSupported(
false, ST->hasDotProd()))
7295 if (Opcode == Instruction::FAdd && !IsSub &&
7296 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7297 AccumLT.second.getScalarType() == MVT::f32 &&
7298 InputLT.second.getScalarType() == MVT::f16)
7302 if (Ratio == 2 && !IsUSDot) {
7303 MVT InVT = InputLT.second.getScalarType();
7307 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7309 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7312 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7316 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7317 InVT == MVT::bf16 && IsSub)
7327 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7328 return Cost * 2 + FNegCost;
7332 AccumType, VF, OpAExtend, OpBExtend,
7333 BinOp, CostKind, FMF);
7343 "Expected the Mask to match the return size if given");
7345 "Expected the same scalar types");
7351 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7352 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7353 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7361 return std::max<InstructionCost>(1, LT.first / 4);
7369 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7371 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7374 unsigned TpNumElts = Mask.size();
7375 unsigned LTNumElts = LT.second.getVectorNumElements();
7376 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7378 LT.second.getVectorElementCount());
7380 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7382 for (
unsigned N = 0;
N < NumVecs;
N++) {
7386 unsigned Source1 = -1U, Source2 = -1U;
7387 unsigned NumSources = 0;
7388 for (
unsigned E = 0; E < LTNumElts; E++) {
7389 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7398 unsigned Source = MaskElt / LTNumElts;
7399 if (NumSources == 0) {
7402 }
else if (NumSources == 1 && Source != Source1) {
7405 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7411 if (Source == Source1)
7413 else if (Source == Source2)
7414 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7423 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7434 NTp, NTp, CostKind, NMask, 0,
nullptr, Args,
7437 Result.first->second = NCost;
7451 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7452 if (LT.second.getFixedSizeInBits() >= 128 &&
7454 LT.second.getVectorNumElements() / 2) {
7457 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7471 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7474 return M.value() < 0 || M.value() == (int)M.index();
7480 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7481 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7490 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7491 ST->isSVEorStreamingSVEAvailable() &&
7496 if (ST->isSVEorStreamingSVEAvailable() &&
7510 if (IsLoad && LT.second.isVector() &&
7512 LT.second.getVectorElementCount()))
7518 if (Mask.size() == 4 &&
7520 (SrcTy->getScalarSizeInBits() == 16 ||
7521 SrcTy->getScalarSizeInBits() == 32) &&
7522 all_of(Mask, [](
int E) {
return E < 8; }))
7528 if (LT.second.isFixedLengthVector() &&
7529 LT.second.getVectorNumElements() == Mask.size() &&
7535 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7536 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7537 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7538 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7539 LT.second.getVectorNumElements(), 16) ||
7540 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7541 LT.second.getVectorNumElements(), 32) ||
7542 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7543 LT.second.getVectorNumElements(), 64) ||
7546 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7675 return LT.first * Entry->Cost;
7684 LT.second.getSizeInBits() <= 128 && SubTp) {
7686 if (SubLT.second.isVector()) {
7687 int NumElts = LT.second.getVectorNumElements();
7688 int NumSubElts = SubLT.second.getVectorNumElements();
7689 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7695 if (IsExtractSubvector)
7716 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7727 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7728 ST->useFixedOverScalableIfEqualCost());
7732 return ST->getEpilogueVectorizationMinVF();
7767 unsigned NumInsns = 0;
7769 NumInsns += BB->size();
7773 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7779 int64_t Scale,
unsigned AddrSpace)
const {
7802 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7807 if (
I->getOpcode() == Instruction::Or &&
7811 if (
I->getOpcode() == Instruction::Add ||
7812 I->getOpcode() == Instruction::Sub)
7828 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7829 return std::tie(
C1.NumRegs,
C1.Insns,
C1.NumPrePostIndex,
C1.NumBaseAdds,
7830 C1.AddRecCost,
C1.NumIVMuls,
C1.ScaleCost,
C1.ImmCost,
7841 return all_equal(Shuf->getShuffleMask());
7848 bool AllowSplat =
false) {
7853 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7854 auto *FullTy = FullV->
getType();
7855 auto *HalfTy = HalfV->getType();
7857 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7860 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7863 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7867 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7881 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7882 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7896 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7897 (M2Start != 0 && M2Start != (NumElements / 2)))
7899 if (S1Op1 && S2Op1 && M1Start != M2Start)
7909 return Ext->getType()->getScalarSizeInBits() ==
7910 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7924 Value *VectorOperand =
nullptr;
7941 if (!
GEP ||
GEP->getNumOperands() != 2)
7945 Value *Offsets =
GEP->getOperand(1);
7948 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7954 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7955 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7956 Ops.push_back(&
GEP->getOperandUse(1));
7996 switch (
II->getIntrinsicID()) {
7997 case Intrinsic::aarch64_neon_smull:
7998 case Intrinsic::aarch64_neon_umull:
8001 Ops.push_back(&
II->getOperandUse(0));
8002 Ops.push_back(&
II->getOperandUse(1));
8007 case Intrinsic::fma:
8008 case Intrinsic::fmuladd:
8015 Ops.push_back(&
II->getOperandUse(0));
8017 Ops.push_back(&
II->getOperandUse(1));
8020 case Intrinsic::aarch64_neon_sqdmull:
8021 case Intrinsic::aarch64_neon_sqdmulh:
8022 case Intrinsic::aarch64_neon_sqrdmulh:
8025 Ops.push_back(&
II->getOperandUse(0));
8027 Ops.push_back(&
II->getOperandUse(1));
8028 return !
Ops.empty();
8029 case Intrinsic::aarch64_neon_fmlal:
8030 case Intrinsic::aarch64_neon_fmlal2:
8031 case Intrinsic::aarch64_neon_fmlsl:
8032 case Intrinsic::aarch64_neon_fmlsl2:
8035 Ops.push_back(&
II->getOperandUse(1));
8037 Ops.push_back(&
II->getOperandUse(2));
8038 return !
Ops.empty();
8039 case Intrinsic::aarch64_sve_ptest_first:
8040 case Intrinsic::aarch64_sve_ptest_last:
8042 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
8043 Ops.push_back(&
II->getOperandUse(0));
8044 return !
Ops.empty();
8045 case Intrinsic::aarch64_sme_write_horiz:
8046 case Intrinsic::aarch64_sme_write_vert:
8047 case Intrinsic::aarch64_sme_writeq_horiz:
8048 case Intrinsic::aarch64_sme_writeq_vert: {
8050 if (!Idx || Idx->getOpcode() != Instruction::Add)
8052 Ops.push_back(&
II->getOperandUse(1));
8055 case Intrinsic::aarch64_sme_read_horiz:
8056 case Intrinsic::aarch64_sme_read_vert:
8057 case Intrinsic::aarch64_sme_readq_horiz:
8058 case Intrinsic::aarch64_sme_readq_vert:
8059 case Intrinsic::aarch64_sme_ld1b_vert:
8060 case Intrinsic::aarch64_sme_ld1h_vert:
8061 case Intrinsic::aarch64_sme_ld1w_vert:
8062 case Intrinsic::aarch64_sme_ld1d_vert:
8063 case Intrinsic::aarch64_sme_ld1q_vert:
8064 case Intrinsic::aarch64_sme_st1b_vert:
8065 case Intrinsic::aarch64_sme_st1h_vert:
8066 case Intrinsic::aarch64_sme_st1w_vert:
8067 case Intrinsic::aarch64_sme_st1d_vert:
8068 case Intrinsic::aarch64_sme_st1q_vert:
8069 case Intrinsic::aarch64_sme_ld1b_horiz:
8070 case Intrinsic::aarch64_sme_ld1h_horiz:
8071 case Intrinsic::aarch64_sme_ld1w_horiz:
8072 case Intrinsic::aarch64_sme_ld1d_horiz:
8073 case Intrinsic::aarch64_sme_ld1q_horiz:
8074 case Intrinsic::aarch64_sme_st1b_horiz:
8075 case Intrinsic::aarch64_sme_st1h_horiz:
8076 case Intrinsic::aarch64_sme_st1w_horiz:
8077 case Intrinsic::aarch64_sme_st1d_horiz:
8078 case Intrinsic::aarch64_sme_st1q_horiz: {
8080 if (!Idx || Idx->getOpcode() != Instruction::Add)
8082 Ops.push_back(&
II->getOperandUse(3));
8085 case Intrinsic::aarch64_neon_pmull:
8088 Ops.push_back(&
II->getOperandUse(0));
8089 Ops.push_back(&
II->getOperandUse(1));
8091 case Intrinsic::aarch64_neon_pmull64:
8093 II->getArgOperand(1)))
8095 Ops.push_back(&
II->getArgOperandUse(0));
8096 Ops.push_back(&
II->getArgOperandUse(1));
8098 case Intrinsic::masked_gather:
8101 Ops.push_back(&
II->getArgOperandUse(0));
8103 case Intrinsic::masked_scatter:
8106 Ops.push_back(&
II->getArgOperandUse(1));
8113 auto ShouldSinkCondition = [](
Value *
Cond,
8118 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8122 Ops.push_back(&
II->getOperandUse(0));
8126 switch (
I->getOpcode()) {
8127 case Instruction::Store: {
8130 if (!
SI->isSimple() || !
II)
8139 Ops.push_back(&
SI->getOperandUse(0));
8144 case Instruction::GetElementPtr:
8145 case Instruction::Add:
8146 case Instruction::Sub:
8148 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8150 Ops.push_back(&
I->getOperandUse(
Op));
8155 case Instruction::Select: {
8156 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8159 Ops.push_back(&
I->getOperandUse(0));
8162 case Instruction::UncondBr:
8164 case Instruction::CondBr: {
8168 Ops.push_back(&
I->getOperandUse(0));
8171 case Instruction::FMul:
8176 Ops.push_back(&
I->getOperandUse(0));
8178 Ops.push_back(&
I->getOperandUse(1));
8188 case Instruction::Xor:
8191 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8193 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8198 case Instruction::And:
8199 case Instruction::Or:
8202 if (
I->getOpcode() == Instruction::Or &&
8207 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8210 for (
auto &
Op :
I->operands()) {
8222 Ops.push_back(&Not);
8223 Ops.push_back(&InsertElt);
8233 if (!
I->getType()->isVectorTy())
8234 return !
Ops.empty();
8236 switch (
I->getOpcode()) {
8237 case Instruction::Sub:
8238 case Instruction::Add: {
8247 Ops.push_back(&Ext1->getOperandUse(0));
8248 Ops.push_back(&Ext2->getOperandUse(0));
8251 Ops.push_back(&
I->getOperandUse(0));
8252 Ops.push_back(&
I->getOperandUse(1));
8256 case Instruction::Or: {
8259 if (ST->hasNEON()) {
8266 Ops.push_back(&
I->getOperandUse(0));
8267 Ops.push_back(&
I->getOperandUse(1));
8275 case Instruction::Mul: {
8276 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8279 if (Ty->isScalableTy())
8283 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8286 int NumZExts = 0, NumSExts = 0;
8287 for (
auto &
Op :
I->operands()) {
8294 auto *ExtOp = Ext->getOperand(0);
8295 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8296 Ops.push_back(&Ext->getOperandUse(0));
8304 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8305 I->getType()->getScalarSizeInBits())
8342 if (!ElementConstant || !ElementConstant->
isZero())
8345 unsigned Opcode = OperandInstr->
getOpcode();
8346 if (Opcode == Instruction::SExt)
8348 else if (Opcode == Instruction::ZExt)
8353 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8363 Ops.push_back(&Insert->getOperandUse(1));
8369 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8373 if (!ShouldSinkSplatForIndexedVariant(
I))
8378 Ops.push_back(&
I->getOperandUse(0));
8380 Ops.push_back(&
I->getOperandUse(1));
8382 return !
Ops.empty();
8384 case Instruction::FMul: {
8386 if (
I->getType()->isScalableTy())
8387 return !
Ops.empty();
8391 return !
Ops.empty();
8395 Ops.push_back(&
I->getOperandUse(0));
8397 Ops.push_back(&
I->getOperandUse(1));
8398 return !
Ops.empty();
8407 Align Alignment)
const {
8408 if (!(ST->isSVEAvailable() ||
8409 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8413 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8420 if (!LT.first.isValid())
8425 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*...