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::loop_dependence_raw_mask:
1352 case Intrinsic::loop_dependence_war_mask: {
1354 if (ST->hasSVE2() || ST->hasSME()) {
1355 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1356 unsigned EltSizeInBytes =
1366 case Intrinsic::experimental_vector_extract_last_active:
1367 if (ST->isSVEorStreamingSVEAvailable()) {
1373 case Intrinsic::pow: {
1376 EVT VT = getTLI()->getValueType(
DL, RetTy);
1377 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1379 getTLI()->getLibcallLoweringInfo().getVectorLibcallImplOrMasked(LC) !=
1395 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1396 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1406 return (Sqrt * 2) +
FMul;
1417 case Intrinsic::sqrt:
1418 case Intrinsic::fabs:
1419 case Intrinsic::ceil:
1420 case Intrinsic::floor:
1421 case Intrinsic::nearbyint:
1422 case Intrinsic::round:
1423 case Intrinsic::rint:
1424 case Intrinsic::roundeven:
1425 case Intrinsic::trunc:
1426 case Intrinsic::minnum:
1427 case Intrinsic::maxnum:
1428 case Intrinsic::minimum:
1429 case Intrinsic::maximum: {
1447 auto RequiredType =
II.getType();
1450 assert(PN &&
"Expected Phi Node!");
1453 if (!PN->hasOneUse())
1454 return std::nullopt;
1456 for (
Value *IncValPhi : PN->incoming_values()) {
1459 Reinterpret->getIntrinsicID() !=
1460 Intrinsic::aarch64_sve_convert_to_svbool ||
1461 RequiredType != Reinterpret->getArgOperand(0)->getType())
1462 return std::nullopt;
1470 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1472 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1545 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1550 return GoverningPredicateIdx;
1555 GoverningPredicateIdx = Index;
1577 return UndefIntrinsic;
1582 UndefIntrinsic = IID;
1609 return CmpPredicate;
1614 CmpPredicate = Pred;
1630 return ResultLanes == InactiveLanesTakenFromOperand;
1635 return OperandIdxForInactiveLanes;
1639 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1640 ResultLanes = InactiveLanesTakenFromOperand;
1641 OperandIdxForInactiveLanes = Index;
1646 return ResultLanes == InactiveLanesAreNotDefined;
1650 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1651 ResultLanes = InactiveLanesAreNotDefined;
1656 return ResultLanes == InactiveLanesAreUnused;
1660 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1661 ResultLanes = InactiveLanesAreUnused;
1671 ResultIsZeroInitialized =
true;
1682 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1687 return OperandIdxWithNoActiveLanes;
1692 OperandIdxWithNoActiveLanes = Index;
1697 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1700 unsigned IROpcode = 0;
1703 enum PredicationStyle {
1705 InactiveLanesTakenFromOperand,
1706 InactiveLanesAreNotDefined,
1707 InactiveLanesAreUnused
1710 bool ResultIsZeroInitialized =
false;
1711 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1712 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1720 return !isa<ScalableVectorType>(V->getType());
1728 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1729 case Intrinsic::aarch64_sve_fcvt_f16f32:
1730 case Intrinsic::aarch64_sve_fcvt_f16f64:
1731 case Intrinsic::aarch64_sve_fcvt_f32f16:
1732 case Intrinsic::aarch64_sve_fcvt_f32f64:
1733 case Intrinsic::aarch64_sve_fcvt_f64f16:
1734 case Intrinsic::aarch64_sve_fcvt_f64f32:
1735 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1736 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1737 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1738 case Intrinsic::aarch64_sve_fcvtzs:
1739 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1740 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1741 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1742 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1743 case Intrinsic::aarch64_sve_fcvtzu:
1744 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1745 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1746 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1747 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1748 case Intrinsic::aarch64_sve_revb:
1749 case Intrinsic::aarch64_sve_revh:
1750 case Intrinsic::aarch64_sve_revw:
1751 case Intrinsic::aarch64_sve_revd:
1752 case Intrinsic::aarch64_sve_scvtf:
1753 case Intrinsic::aarch64_sve_scvtf_f16i32:
1754 case Intrinsic::aarch64_sve_scvtf_f16i64:
1755 case Intrinsic::aarch64_sve_scvtf_f32i64:
1756 case Intrinsic::aarch64_sve_scvtf_f64i32:
1757 case Intrinsic::aarch64_sve_ucvtf:
1758 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1759 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1760 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1761 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1764 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1765 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1766 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1767 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1770 case Intrinsic::aarch64_sve_fabd:
1772 case Intrinsic::aarch64_sve_fadd:
1775 case Intrinsic::aarch64_sve_fdiv:
1778 case Intrinsic::aarch64_sve_fmax:
1780 case Intrinsic::aarch64_sve_fmaxnm:
1782 case Intrinsic::aarch64_sve_fmin:
1784 case Intrinsic::aarch64_sve_fminnm:
1786 case Intrinsic::aarch64_sve_fmla:
1788 case Intrinsic::aarch64_sve_fmls:
1790 case Intrinsic::aarch64_sve_fmul:
1793 case Intrinsic::aarch64_sve_fmulx:
1795 case Intrinsic::aarch64_sve_fnmla:
1797 case Intrinsic::aarch64_sve_fnmls:
1799 case Intrinsic::aarch64_sve_fsub:
1802 case Intrinsic::aarch64_sve_add:
1805 case Intrinsic::aarch64_sve_mla:
1807 case Intrinsic::aarch64_sve_mls:
1809 case Intrinsic::aarch64_sve_mul:
1812 case Intrinsic::aarch64_sve_sabd:
1814 case Intrinsic::aarch64_sve_sdiv:
1817 case Intrinsic::aarch64_sve_smax:
1819 case Intrinsic::aarch64_sve_smin:
1821 case Intrinsic::aarch64_sve_smulh:
1823 case Intrinsic::aarch64_sve_sub:
1826 case Intrinsic::aarch64_sve_uabd:
1828 case Intrinsic::aarch64_sve_udiv:
1831 case Intrinsic::aarch64_sve_umax:
1833 case Intrinsic::aarch64_sve_umin:
1835 case Intrinsic::aarch64_sve_umulh:
1837 case Intrinsic::aarch64_sve_asr:
1840 case Intrinsic::aarch64_sve_lsl:
1843 case Intrinsic::aarch64_sve_lsr:
1846 case Intrinsic::aarch64_sve_and:
1849 case Intrinsic::aarch64_sve_bic:
1851 case Intrinsic::aarch64_sve_eor:
1854 case Intrinsic::aarch64_sve_orr:
1857 case Intrinsic::aarch64_sve_shsub:
1859 case Intrinsic::aarch64_sve_shsubr:
1861 case Intrinsic::aarch64_sve_sqrshl:
1863 case Intrinsic::aarch64_sve_sqshl:
1865 case Intrinsic::aarch64_sve_sqsub:
1867 case Intrinsic::aarch64_sve_srshl:
1869 case Intrinsic::aarch64_sve_uhsub:
1871 case Intrinsic::aarch64_sve_uhsubr:
1873 case Intrinsic::aarch64_sve_uqrshl:
1875 case Intrinsic::aarch64_sve_uqshl:
1877 case Intrinsic::aarch64_sve_uqsub:
1879 case Intrinsic::aarch64_sve_urshl:
1882 case Intrinsic::aarch64_sve_add_u:
1885 case Intrinsic::aarch64_sve_and_u:
1888 case Intrinsic::aarch64_sve_asr_u:
1891 case Intrinsic::aarch64_sve_eor_u:
1894 case Intrinsic::aarch64_sve_fadd_u:
1897 case Intrinsic::aarch64_sve_fdiv_u:
1900 case Intrinsic::aarch64_sve_fmul_u:
1903 case Intrinsic::aarch64_sve_fsub_u:
1906 case Intrinsic::aarch64_sve_lsl_u:
1909 case Intrinsic::aarch64_sve_lsr_u:
1912 case Intrinsic::aarch64_sve_mul_u:
1915 case Intrinsic::aarch64_sve_orr_u:
1918 case Intrinsic::aarch64_sve_sdiv_u:
1921 case Intrinsic::aarch64_sve_sub_u:
1924 case Intrinsic::aarch64_sve_udiv_u:
1928 case Intrinsic::aarch64_sve_addqv:
1929 case Intrinsic::aarch64_sve_bic_z:
1930 case Intrinsic::aarch64_sve_brka_z:
1931 case Intrinsic::aarch64_sve_brkb_z:
1932 case Intrinsic::aarch64_sve_brkn_z:
1933 case Intrinsic::aarch64_sve_brkpa_z:
1934 case Intrinsic::aarch64_sve_brkpb_z:
1935 case Intrinsic::aarch64_sve_cntp:
1936 case Intrinsic::aarch64_sve_compact:
1937 case Intrinsic::aarch64_sve_eorv:
1938 case Intrinsic::aarch64_sve_eorqv:
1939 case Intrinsic::aarch64_sve_nand_z:
1940 case Intrinsic::aarch64_sve_nor_z:
1941 case Intrinsic::aarch64_sve_orn_z:
1942 case Intrinsic::aarch64_sve_orv:
1943 case Intrinsic::aarch64_sve_orqv:
1944 case Intrinsic::aarch64_sve_pnext:
1945 case Intrinsic::aarch64_sve_rdffr_z:
1946 case Intrinsic::aarch64_sve_saddv:
1947 case Intrinsic::aarch64_sve_uaddv:
1948 case Intrinsic::aarch64_sve_umaxv:
1949 case Intrinsic::aarch64_sve_umaxqv:
1950 case Intrinsic::aarch64_sve_facge:
1951 case Intrinsic::aarch64_sve_facgt:
1952 case Intrinsic::aarch64_sve_ld1:
1953 case Intrinsic::aarch64_sve_ld1_gather:
1954 case Intrinsic::aarch64_sve_ld1_gather_index:
1955 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1956 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1957 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1958 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1959 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1960 case Intrinsic::aarch64_sve_ld1q_gather_index:
1961 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1962 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1963 case Intrinsic::aarch64_sve_ld1ro:
1964 case Intrinsic::aarch64_sve_ld1rq:
1965 case Intrinsic::aarch64_sve_ld1udq:
1966 case Intrinsic::aarch64_sve_ld1uwq:
1967 case Intrinsic::aarch64_sve_ld2_sret:
1968 case Intrinsic::aarch64_sve_ld2q_sret:
1969 case Intrinsic::aarch64_sve_ld3_sret:
1970 case Intrinsic::aarch64_sve_ld3q_sret:
1971 case Intrinsic::aarch64_sve_ld4_sret:
1972 case Intrinsic::aarch64_sve_ld4q_sret:
1973 case Intrinsic::aarch64_sve_ldff1:
1974 case Intrinsic::aarch64_sve_ldff1_gather:
1975 case Intrinsic::aarch64_sve_ldff1_gather_index:
1976 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1977 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1978 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1979 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1980 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1981 case Intrinsic::aarch64_sve_ldnf1:
1982 case Intrinsic::aarch64_sve_ldnt1:
1983 case Intrinsic::aarch64_sve_ldnt1_gather:
1984 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1985 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1986 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1989 case Intrinsic::aarch64_sve_and_z:
1992 case Intrinsic::aarch64_sve_orr_z:
1995 case Intrinsic::aarch64_sve_eor_z:
1999 case Intrinsic::aarch64_sve_cmpeq:
2000 case Intrinsic::aarch64_sve_cmpeq_wide:
2003 case Intrinsic::aarch64_sve_cmpge:
2004 case Intrinsic::aarch64_sve_cmpge_wide:
2007 case Intrinsic::aarch64_sve_cmpgt:
2008 case Intrinsic::aarch64_sve_cmpgt_wide:
2011 case Intrinsic::aarch64_sve_cmphi:
2012 case Intrinsic::aarch64_sve_cmphi_wide:
2015 case Intrinsic::aarch64_sve_cmphs:
2016 case Intrinsic::aarch64_sve_cmphs_wide:
2019 case Intrinsic::aarch64_sve_cmple_wide:
2022 case Intrinsic::aarch64_sve_cmplo_wide:
2025 case Intrinsic::aarch64_sve_cmpls_wide:
2028 case Intrinsic::aarch64_sve_cmplt_wide:
2031 case Intrinsic::aarch64_sve_cmpne:
2032 case Intrinsic::aarch64_sve_cmpne_wide:
2035 case Intrinsic::aarch64_sve_fcmpeq:
2038 case Intrinsic::aarch64_sve_fcmpge:
2041 case Intrinsic::aarch64_sve_fcmpgt:
2044 case Intrinsic::aarch64_sve_fcmpne:
2047 case Intrinsic::aarch64_sve_fcmpuo:
2051 case Intrinsic::aarch64_sve_prf:
2052 case Intrinsic::aarch64_sve_prfb_gather_index:
2053 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
2054 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
2055 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
2056 case Intrinsic::aarch64_sve_prfd_gather_index:
2057 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
2058 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
2059 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
2060 case Intrinsic::aarch64_sve_prfh_gather_index:
2061 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
2062 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
2063 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
2064 case Intrinsic::aarch64_sve_prfw_gather_index:
2065 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
2066 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
2067 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
2070 case Intrinsic::aarch64_sve_st1_scatter:
2071 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
2072 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
2073 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
2074 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
2075 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
2076 case Intrinsic::aarch64_sve_st1dq:
2077 case Intrinsic::aarch64_sve_st1q_scatter_index:
2078 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
2079 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
2080 case Intrinsic::aarch64_sve_st1wq:
2081 case Intrinsic::aarch64_sve_stnt1:
2082 case Intrinsic::aarch64_sve_stnt1_scatter:
2083 case Intrinsic::aarch64_sve_stnt1_scatter_index:
2084 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
2085 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
2087 case Intrinsic::aarch64_sve_st2:
2088 case Intrinsic::aarch64_sve_st2q:
2090 case Intrinsic::aarch64_sve_st3:
2091 case Intrinsic::aarch64_sve_st3q:
2093 case Intrinsic::aarch64_sve_st4:
2094 case Intrinsic::aarch64_sve_st4q:
2102 Value *UncastedPred;
2108 Pred = UncastedPred;
2114 if (OrigPredTy->getMinNumElements() <=
2116 ->getMinNumElements())
2117 Pred = UncastedPred;
2121 return C &&
C->isAllOnesValue();
2128 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
2129 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2137static std::optional<Instruction *>
2144 Value *Op1 =
II.getOperand(1);
2145 Value *Op2 =
II.getOperand(2);
2170 Value *NarrowOp1, *NarrowOp2;
2181 else if (SimpleNarrow == NarrowOp1)
2183 else if (SimpleNarrow == NarrowOp2)
2188 SimpleNarrow->
getType(), SimpleNarrow);
2197 return std::nullopt;
2208 if (SimpleII == Inactive)
2216static std::optional<Instruction *>
2220 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2221 "Expected a compare operation!");
2228 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2229 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2230 "Unexpected wide compare!");
2246 const APInt *LHSVal, *RHSVal;
2248 return std::nullopt;
2271 return std::nullopt;
2285static std::optional<Instruction *>
2289 return std::nullopt;
2318 II.setCalledFunction(NewDecl);
2324 return std::nullopt;
2335 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2338 return std::nullopt;
2350static std::optional<Instruction *>
2352 auto m_ConvertToSVBool = [](
auto P) {
2356 Intrinsic::aarch64_sve_convert_from_svbool;
2379 return std::nullopt;
2383 case Intrinsic::aarch64_sve_and_z:
2384 case Intrinsic::aarch64_sve_bic_z:
2385 case Intrinsic::aarch64_sve_eor_z:
2386 case Intrinsic::aarch64_sve_nand_z:
2387 case Intrinsic::aarch64_sve_nor_z:
2388 case Intrinsic::aarch64_sve_orn_z:
2389 case Intrinsic::aarch64_sve_orr_z:
2392 return std::nullopt;
2395 Value *BinOpPred = BinOp->getOperand(0);
2396 Value *BinOpOp1 = BinOp->getOperand(1);
2397 Value *BinOpOp2 = BinOp->getOperand(2);
2399 Value *NarrowBinOpPred;
2401 return std::nullopt;
2403 Value *NarrowBinOpOp1 =
2405 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2406 if (BinOpOp1 != BinOpOp2)
2410 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2414static std::optional<Instruction *>
2421 return BinOpCombine;
2426 return std::nullopt;
2429 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2438 if (CursorVTy->getElementCount().getKnownMinValue() <
2439 IVTy->getElementCount().getKnownMinValue())
2443 if (Cursor->getType() == IVTy)
2444 EarliestReplacement = Cursor;
2449 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2450 Intrinsic::aarch64_sve_convert_to_svbool ||
2451 IntrinsicCursor->getIntrinsicID() ==
2452 Intrinsic::aarch64_sve_convert_from_svbool))
2455 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2456 Cursor = IntrinsicCursor->getOperand(0);
2461 if (!EarliestReplacement)
2462 return std::nullopt;
2470 auto *OpPredicate =
II.getOperand(0);
2487 II.getArgOperand(2));
2493 return std::nullopt;
2497 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2506 II.getArgOperand(0));
2515 if (!
II.hasOneUse())
2516 return std::nullopt;
2519 return std::nullopt;
2522 switch (
II.getIntrinsicID()) {
2523 case Intrinsic::aarch64_sve_cmpne:
2524 IID = Intrinsic::aarch64_sve_cmpeq;
2526 case Intrinsic::aarch64_sve_cmpne_wide:
2527 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2529 case Intrinsic::aarch64_sve_cmpeq:
2530 IID = Intrinsic::aarch64_sve_cmpne;
2532 case Intrinsic::aarch64_sve_cmpeq_wide:
2533 IID = Intrinsic::aarch64_sve_cmpne_wide;
2536 return std::nullopt;
2541 IID,
II.getOperand(1)->getType(),
2542 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2554 return std::nullopt;
2556 for (
auto *U :
II.users()) {
2559 Type *Ty =
II.getOperand(1)->getType();
2564 Intrinsic::aarch64_sve_umin, Ty,
2565 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2571 return std::nullopt;
2585 return std::nullopt;
2590 if (!SplatValue || !SplatValue->isZero())
2591 return std::nullopt;
2596 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2597 return std::nullopt;
2601 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2602 return std::nullopt;
2605 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2606 return std::nullopt;
2611 return std::nullopt;
2614 return std::nullopt;
2618 return std::nullopt;
2622 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2623 return std::nullopt;
2625 unsigned NumElts = VecTy->getNumElements();
2626 unsigned PredicateBits = 0;
2629 for (
unsigned I = 0;
I < NumElts; ++
I) {
2632 return std::nullopt;
2634 PredicateBits |= 1 << (
I * (16 / NumElts));
2638 if (PredicateBits == 0) {
2640 PFalse->takeName(&
II);
2646 for (
unsigned I = 0;
I < 16; ++
I)
2647 if ((PredicateBits & (1 <<
I)) != 0)
2650 unsigned PredSize = Mask & -Mask;
2655 for (
unsigned I = 0;
I < 16;
I += PredSize)
2656 if ((PredicateBits & (1 <<
I)) == 0)
2657 return std::nullopt;
2659 auto *ConvertToSVBool =
2662 auto *ConvertFromSVBool =
2664 II.getType(), ConvertToSVBool);
2672 Value *Pg =
II.getArgOperand(0);
2673 Value *Vec =
II.getArgOperand(1);
2674 auto IntrinsicID =
II.getIntrinsicID();
2675 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2687 auto OpC = OldBinOp->getOpcode();
2693 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2699 if (IsAfter &&
C &&
C->isNullValue()) {
2703 Extract->insertBefore(
II.getIterator());
2704 Extract->takeName(&
II);
2710 return std::nullopt;
2712 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2713 return std::nullopt;
2715 const auto PTruePattern =
2721 return std::nullopt;
2723 unsigned Idx = MinNumElts - 1;
2733 if (Idx >= PgVTy->getMinNumElements())
2734 return std::nullopt;
2739 Extract->insertBefore(
II.getIterator());
2740 Extract->takeName(&
II);
2753 Value *Pg =
II.getArgOperand(0);
2755 Value *Vec =
II.getArgOperand(2);
2758 if (!Ty->isIntegerTy())
2759 return std::nullopt;
2764 return std::nullopt;
2781 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2796static std::optional<Instruction *>
2800 if (
Pattern == AArch64SVEPredPattern::all) {
2809 return MinNumElts && NumElts >= MinNumElts
2811 II, ConstantInt::get(
II.getType(), MinNumElts)))
2815static std::optional<Instruction *>
2818 if (!ST->isStreaming())
2819 return std::nullopt;
2831 Value *PgVal =
II.getArgOperand(0);
2832 Value *OpVal =
II.getArgOperand(1);
2836 if (PgVal == OpVal &&
2837 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2838 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2853 return std::nullopt;
2857 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2858 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2872 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2873 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2874 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2875 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2876 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2877 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2878 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2879 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2880 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2881 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2882 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2883 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2884 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2894 return std::nullopt;
2897template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2898static std::optional<Instruction *>
2900 bool MergeIntoAddendOp) {
2902 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2903 if (MergeIntoAddendOp) {
2904 AddendOp =
II.getOperand(1);
2905 Mul =
II.getOperand(2);
2907 AddendOp =
II.getOperand(2);
2908 Mul =
II.getOperand(1);
2913 return std::nullopt;
2915 if (!
Mul->hasOneUse())
2916 return std::nullopt;
2919 if (
II.getType()->isFPOrFPVectorTy()) {
2924 return std::nullopt;
2926 return std::nullopt;
2931 if (MergeIntoAddendOp)
2941static std::optional<Instruction *>
2943 Value *Pred =
II.getOperand(0);
2944 Value *PtrOp =
II.getOperand(1);
2945 Type *VecTy =
II.getType();
2960static std::optional<Instruction *>
2962 Value *VecOp =
II.getOperand(0);
2963 Value *Pred =
II.getOperand(1);
2964 Value *PtrOp =
II.getOperand(2);
2980 case Intrinsic::aarch64_sve_fmul_u:
2981 return Instruction::BinaryOps::FMul;
2982 case Intrinsic::aarch64_sve_fadd_u:
2983 return Instruction::BinaryOps::FAdd;
2984 case Intrinsic::aarch64_sve_fsub_u:
2985 return Instruction::BinaryOps::FSub;
2987 return Instruction::BinaryOpsEnd;
2991static std::optional<Instruction *>
2994 if (
II.isStrictFP())
2995 return std::nullopt;
2997 auto *OpPredicate =
II.getOperand(0);
2999 if (BinOpCode == Instruction::BinaryOpsEnd ||
3001 return std::nullopt;
3003 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
3007static std::optional<Instruction *>
3009 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
3010 "Expected MLA_U intrinsic");
3011 Value *Acc =
II.getArgOperand(1);
3012 Value *MulOp0 =
II.getArgOperand(2);
3013 Value *MulOp1 =
II.getArgOperand(3);
3028 II.setArgOperand(2, MulOp1);
3029 II.setArgOperand(3, MulOp0);
3033 return std::nullopt;
3036static std::optional<Instruction *>
3038 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
3039 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
3040 "Expected SADALP or UADALP intrinsic");
3046 return std::nullopt;
3050 return std::nullopt;
3054 II.getIntrinsicID(), {II.getType()},
3055 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
3065 Intrinsic::aarch64_sve_mla>(
3069 Intrinsic::aarch64_sve_mad>(
3072 return std::nullopt;
3075static std::optional<Instruction *>
3079 Intrinsic::aarch64_sve_fmla>(IC,
II,
3084 Intrinsic::aarch64_sve_fmad>(IC,
II,
3089 Intrinsic::aarch64_sve_fmla>(IC,
II,
3092 return std::nullopt;
3095static std::optional<Instruction *>
3099 Intrinsic::aarch64_sve_fmla>(IC,
II,
3104 Intrinsic::aarch64_sve_fmad>(IC,
II,
3109 Intrinsic::aarch64_sve_fmla_u>(
3115static std::optional<Instruction *>
3119 Intrinsic::aarch64_sve_fmls>(IC,
II,
3124 Intrinsic::aarch64_sve_fnmsb>(
3129 Intrinsic::aarch64_sve_fmls>(IC,
II,
3132 return std::nullopt;
3135static std::optional<Instruction *>
3139 Intrinsic::aarch64_sve_fmls>(IC,
II,
3144 Intrinsic::aarch64_sve_fnmsb>(
3149 Intrinsic::aarch64_sve_fmls_u>(
3158 Intrinsic::aarch64_sve_mls>(
3161 return std::nullopt;
3166 Value *UnpackArg =
II.getArgOperand(0);
3168 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3169 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3182 return std::nullopt;
3186 auto *OpVal =
II.getOperand(0);
3187 auto *OpIndices =
II.getOperand(1);
3194 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3195 return std::nullopt;
3210 Type *RetTy =
II.getType();
3211 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3212 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3216 if ((
match(
II.getArgOperand(0),
3223 if (TyA ==
B->getType() &&
3228 TyA->getMinNumElements());
3234 return std::nullopt;
3242 if (
match(
II.getArgOperand(0),
3247 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3249 return std::nullopt;
3252static std::optional<Instruction *>
3254 Value *Mask =
II.getOperand(0);
3255 Value *BasePtr =
II.getOperand(1);
3256 Value *Index =
II.getOperand(2);
3267 BasePtr->getPointerAlignment(
II.getDataLayout());
3270 BasePtr, IndexBase);
3277 return std::nullopt;
3280static std::optional<Instruction *>
3282 Value *Val =
II.getOperand(0);
3283 Value *Mask =
II.getOperand(1);
3284 Value *BasePtr =
II.getOperand(2);
3285 Value *Index =
II.getOperand(3);
3295 BasePtr->getPointerAlignment(
II.getDataLayout());
3298 BasePtr, IndexBase);
3304 return std::nullopt;
3310 Value *Pred =
II.getOperand(0);
3311 Value *Vec =
II.getOperand(1);
3312 Value *DivVec =
II.getOperand(2);
3316 if (!SplatConstantInt)
3317 return std::nullopt;
3321 if (DivisorValue == -1)
3322 return std::nullopt;
3323 if (DivisorValue == 1)
3329 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3336 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3338 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3342 return std::nullopt;
3365 if (
I->getParent() != MainAnd->
getParent() ||
3373 size_t VecSize = Vec.
size();
3378 size_t HalfVecSize = VecSize / 2;
3382 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3390 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3408 return std::nullopt;
3415 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3416 CurrentInsertElt = InsertElt->getOperand(0);
3422 return std::nullopt;
3426 for (
size_t I = 0;
I < Elts.
size();
I++) {
3427 if (Elts[
I] ==
nullptr)
3432 if (InsertEltChain ==
nullptr)
3433 return std::nullopt;
3439 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3440 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3441 IIScalableTy->getMinNumElements() /
3446 auto *WideShuffleMaskTy =
3457 auto NarrowBitcast =
3470 return std::nullopt;
3475 Value *Pred =
II.getOperand(0);
3476 Value *Vec =
II.getOperand(1);
3477 Value *Shift =
II.getOperand(2);
3480 Value *AbsPred, *MergedValue;
3486 return std::nullopt;
3494 return std::nullopt;
3499 return std::nullopt;
3502 {
II.getType()}, {Pred, Vec, Shift});
3509 Value *Vec =
II.getOperand(0);
3514 return std::nullopt;
3517static std::optional<Instruction *>
3519 unsigned LookaheadThreshold) {
3521 auto *NI =
II.getNextNode();
3523 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3525 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3526 auto *NIBB = NI->getParent();
3527 NI = NI->getNextNode();
3529 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3530 NI = &*SuccBB->getFirstNonPHIOrLifetime();
3536 if (NextII &&
II.isIdenticalTo(NextII))
3539 return std::nullopt;
3547 {II.getType(), II.getOperand(0)->getType()},
3548 {II.getOperand(0), II.getOperand(1)}));
3555 if (PredPattern == AArch64SVEPredPattern::all ||
3556 PredPattern == AArch64SVEPredPattern::pow2)
3558 return std::nullopt;
3564 Value *Passthru =
II.getOperand(0);
3572 auto *Mask = ConstantInt::get(Ty, MaskValue);
3578 return std::nullopt;
3581static std::optional<Instruction *>
3588 return std::nullopt;
3594 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3604 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3614 return std::nullopt;
3620 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3628 return std::nullopt;
3631 II.getType(), {Pg, A, B});
3633 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3642 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3647 Value *
A, *PgLHS, *PgRHS;
3653 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3654 return std::nullopt;
3657 if (ConstB > ConstA)
3663 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3664 return std::nullopt;
3666 Type *VecTy =
A->getType();
3670 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3677std::optional<Instruction *>
3688 case Intrinsic::aarch64_dmb:
3690 case Intrinsic::aarch64_neon_fmaxnm:
3691 case Intrinsic::aarch64_neon_fminnm:
3693 case Intrinsic::aarch64_sve_convert_from_svbool:
3695 case Intrinsic::aarch64_sve_dup:
3697 case Intrinsic::aarch64_sve_dup_x:
3699 case Intrinsic::aarch64_sve_cmpeq:
3700 case Intrinsic::aarch64_sve_cmpeq_wide:
3702 case Intrinsic::aarch64_sve_cmpne:
3703 case Intrinsic::aarch64_sve_cmpne_wide:
3705 case Intrinsic::aarch64_sve_rdffr:
3707 case Intrinsic::aarch64_sve_lasta:
3708 case Intrinsic::aarch64_sve_lastb:
3710 case Intrinsic::aarch64_sve_clasta_n:
3711 case Intrinsic::aarch64_sve_clastb_n:
3713 case Intrinsic::aarch64_sve_cntd:
3715 case Intrinsic::aarch64_sve_cntw:
3717 case Intrinsic::aarch64_sve_cnth:
3719 case Intrinsic::aarch64_sve_cntb:
3721 case Intrinsic::aarch64_sme_cntsd:
3723 case Intrinsic::aarch64_sve_ptest_any:
3724 case Intrinsic::aarch64_sve_ptest_first:
3725 case Intrinsic::aarch64_sve_ptest_last:
3727 case Intrinsic::aarch64_sve_fadd:
3729 case Intrinsic::aarch64_sve_fadd_u:
3731 case Intrinsic::aarch64_sve_fmul_u:
3733 case Intrinsic::aarch64_sve_fsub:
3735 case Intrinsic::aarch64_sve_fsub_u:
3737 case Intrinsic::aarch64_sve_add:
3739 case Intrinsic::aarch64_sve_add_u:
3741 Intrinsic::aarch64_sve_mla_u>(
3743 case Intrinsic::aarch64_sve_mla_u:
3745 case Intrinsic::aarch64_sve_sadalp:
3746 case Intrinsic::aarch64_sve_uadalp:
3748 case Intrinsic::aarch64_sve_sub:
3750 case Intrinsic::aarch64_sve_sub_u:
3752 Intrinsic::aarch64_sve_mls_u>(
3754 case Intrinsic::aarch64_sve_tbl:
3756 case Intrinsic::aarch64_sve_uunpkhi:
3757 case Intrinsic::aarch64_sve_uunpklo:
3758 case Intrinsic::aarch64_sve_sunpkhi:
3759 case Intrinsic::aarch64_sve_sunpklo:
3761 case Intrinsic::aarch64_sve_uzp1:
3763 case Intrinsic::aarch64_sve_zip1:
3764 case Intrinsic::aarch64_sve_zip2:
3766 case Intrinsic::aarch64_sve_ld1_gather_index:
3768 case Intrinsic::aarch64_sve_st1_scatter_index:
3770 case Intrinsic::aarch64_sve_ld1:
3772 case Intrinsic::aarch64_sve_st1:
3774 case Intrinsic::aarch64_sve_sdiv:
3776 case Intrinsic::aarch64_sve_sel:
3778 case Intrinsic::aarch64_sve_srshl:
3780 case Intrinsic::aarch64_sve_dupq_lane:
3782 case Intrinsic::aarch64_sve_insr:
3784 case Intrinsic::aarch64_sve_whilelo:
3786 case Intrinsic::aarch64_sve_ptrue:
3788 case Intrinsic::aarch64_sve_uxtb:
3790 case Intrinsic::aarch64_sve_uxth:
3792 case Intrinsic::aarch64_sve_uxtw:
3794 case Intrinsic::aarch64_sme_in_streaming_mode:
3796 case Intrinsic::aarch64_sve_umin_u:
3798 case Intrinsic::aarch64_sve_orr_u:
3800 case Intrinsic::aarch64_sve_and_z:
3804 return std::nullopt;
3811 SimplifyAndSetOp)
const {
3812 switch (
II.getIntrinsicID()) {
3815 case Intrinsic::aarch64_neon_fcvtxn:
3816 case Intrinsic::aarch64_neon_rshrn:
3817 case Intrinsic::aarch64_neon_sqrshrn:
3818 case Intrinsic::aarch64_neon_sqrshrun:
3819 case Intrinsic::aarch64_neon_sqshrn:
3820 case Intrinsic::aarch64_neon_sqshrun:
3821 case Intrinsic::aarch64_neon_sqxtn:
3822 case Intrinsic::aarch64_neon_sqxtun:
3823 case Intrinsic::aarch64_neon_uqrshrn:
3824 case Intrinsic::aarch64_neon_uqshrn:
3825 case Intrinsic::aarch64_neon_uqxtn:
3826 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3830 return std::nullopt;
3834 return ST->isSVEAvailable() ||
3835 (ST->isSVEorStreamingSVEAvailable() &&
3836 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3845 if (ST->useSVEForFixedLengthVectors() &&
3846 (ST->isSVEAvailable() ||
3847 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3849 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3850 else if (ST->isNeonAvailable())
3855 if (ST->isSVEAvailable() ||
3856 (ST->isSVEorStreamingSVEAvailable() &&
3857 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3865bool AArch64TTIImpl::isSingleExtWideningInstruction(
3867 Type *SrcOverrideTy)
const {
3882 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3885 Type *SrcTy = SrcOverrideTy;
3887 case Instruction::Add:
3888 case Instruction::Sub: {
3897 if (Opcode == Instruction::Sub)
3921 assert(SrcTy &&
"Expected some SrcTy");
3923 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3929 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3931 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3935 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3938Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3940 Type *SrcOverrideTy)
const {
3941 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3942 Opcode != Instruction::Mul)
3952 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3955 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3961 ->getScalarSizeInBits();
3964 unsigned MaxEltSize = 0;
3967 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3968 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3969 MaxEltSize = std::max(EltSize0, EltSize1);
3972 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3973 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3976 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3978 MaxEltSize = DstEltSize / 2;
3979 }
else if (Opcode == Instruction::Mul &&
3987 Known.Zero.countLeadingOnes() >
3992 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3996 if (MaxEltSize * 2 > DstEltSize)
4014 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
4015 (Src->isScalableTy() && !ST->hasSVE2()))
4025 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4029 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4033 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4034 Src->getScalarSizeInBits() !=
4058 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4072 if (
I && !
I->users().empty()) {
4076 auto GetUserAbsorbedCastCost =
4077 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4080 if (
Type *ExtTy = isBinExtWideningInstruction(
4082 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4095 if (isSingleExtWideningInstruction(
4097 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4101 if (Usr->getOpcode() == Instruction::Add) {
4102 if (
I == Usr->getOperand(1) ||
4114 return std::nullopt;
4123 unsigned SrcBits = Src->getScalarSizeInBits();
4126 Dst->getScalarSizeInBits() == 2 * SrcBits &&
4130 return std::nullopt;
4134 bool AllUsersAbsorbCast =
true;
4135 for (
const User *U :
I->users()) {
4137 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4139 AllUsersAbsorbCast =
false;
4142 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4145 if (AllUsersAbsorbCast)
4146 return MaxAbsorbedCost;
4156 Cmp->getParent() ==
I->getParent() &&
4161 EVT SrcTy = TLI->getValueType(
DL, Src);
4162 EVT DstTy = TLI->getValueType(
DL, Dst);
4166 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4176 bool SrcIsFloatOrVec =
4177 SrcLT.second.isVector() || SrcLT.second.isFloatingPoint();
4178 bool DstIsFloatOrVec =
4179 DstLT.second.isVector() || DstLT.second.isFloatingPoint();
4184 if (SrcIsFloatOrVec == DstIsFloatOrVec &&
4185 (SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits() ||
4186 (SrcLT.second.isScalableVector() &&
4187 SrcLT.second.getScalarSizeInBits() != 1 &&
4188 DstLT.second.getScalarSizeInBits() != 1)))
4191 return std::max(SrcLT.first, DstLT.first) *
4194 : ST->getVectorInsertExtractBaseCost());
4203 Instruction::ExtractElement, Src, CostKind, -1,
nullptr,
nullptr);
4205 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind);
4209 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4214 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4243 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4246 ST->useSVEForFixedLengthVectors(WiderTy)) {
4247 std::pair<InstructionCost, MVT> LT =
4249 unsigned NumElements =
4265 const unsigned int SVE_EXT_COST = 1;
4266 const unsigned int SVE_FCVT_COST = 1;
4267 const unsigned int SVE_UNPACK_ONCE = 4;
4268 const unsigned int SVE_UNPACK_TWICE = 16;
4397 SVE_EXT_COST + SVE_FCVT_COST},
4402 SVE_EXT_COST + SVE_FCVT_COST},
4409 SVE_EXT_COST + SVE_FCVT_COST},
4413 SVE_EXT_COST + SVE_FCVT_COST},
4419 SVE_EXT_COST + SVE_FCVT_COST},
4422 SVE_EXT_COST + SVE_FCVT_COST},
4427 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4429 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4439 SVE_EXT_COST + SVE_FCVT_COST},
4444 SVE_EXT_COST + SVE_FCVT_COST},
4457 SVE_EXT_COST + SVE_FCVT_COST},
4461 SVE_EXT_COST + SVE_FCVT_COST},
4473 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4475 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4477 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4479 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4483 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4485 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4501 SVE_EXT_COST + SVE_FCVT_COST},
4506 SVE_EXT_COST + SVE_FCVT_COST},
4517 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4519 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4521 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4523 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4525 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4527 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4531 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4533 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4535 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4537 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4752 if (ST->hasFullFP16())
4764 Src->getScalarType(), CCH, CostKind) +
4772 ST->isSVEorStreamingSVEAvailable() &&
4773 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4775 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4784 Opcode, LegalTy, Src, CCH, CostKind,
I);
4787 return Part1 + Part2;
4794 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4806 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4819 CostKind, Index,
nullptr,
nullptr);
4823 auto DstVT = TLI->getValueType(
DL, Dst);
4824 auto SrcVT = TLI->getValueType(
DL, Src);
4829 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4835 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4845 case Instruction::SExt:
4850 case Instruction::ZExt:
4851 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4864 return Opcode == Instruction::PHI ? 0 : 1;
4873 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4875 assert(Ty->isVectorTy() &&
"This must be a vector type");
4882 if (!LT.second.isVector())
4887 if (LT.second.isFixedLengthVector()) {
4888 unsigned Width = LT.second.getVectorNumElements();
4889 Index = Index % Width;
4896 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4908 if (Index * Ty->getScalarSizeInBits() < 128)
4910 if (Index * Ty->getScalarSizeInBits() < 512 &&
4911 Opcode == Instruction::ExtractElement)
4913 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4914 if (Opcode == Instruction::ExtractElement)
4916 if (Opcode == Instruction::InsertElement)
4925 if (VIC == TTI::VectorInstrContext::Load) {
4926 if (ST->hasFastLD1Single())
4930 : ST->getVectorInsertExtractBaseCost() + 1;
4938 : ST->getVectorInsertExtractBaseCost() + 1;
4962 auto ExtractCanFuseWithFmul = [&]() {
4969 auto IsAllowedScalarTy = [&](
const Type *
T) {
4970 return T->isFloatTy() ||
T->isDoubleTy() ||
4971 (
T->isHalfTy() && ST->hasFullFP16());
4975 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4978 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4979 !BO->getType()->isVectorTy();
4984 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4988 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
4997 DenseMap<User *, unsigned> UserToExtractIdx;
4998 for (
auto *U :
Scalar->users()) {
4999 if (!IsUserFMulScalarTy(U))
5003 UserToExtractIdx[
U];
5005 if (UserToExtractIdx.
empty())
5007 for (
auto &[S, U, L] : ScalarUserAndIdx) {
5008 for (
auto *U : S->users()) {
5009 if (UserToExtractIdx.
contains(U)) {
5011 auto *Op0 =
FMul->getOperand(0);
5012 auto *Op1 =
FMul->getOperand(1);
5013 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
5014 UserToExtractIdx[
U] =
L;
5020 for (
auto &[U, L] : UserToExtractIdx) {
5032 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
5033 if (!IsUserFMulScalarTy(U))
5038 const auto *BO = cast<BinaryOperator>(U);
5039 const auto *OtherEE = dyn_cast<ExtractElementInst>(
5040 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
5042 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
5045 return IsExtractLaneEquivalentToZero(
5046 cast<ConstantInt>(OtherEE->getIndexOperand())
5049 OtherEE->getType()->getScalarSizeInBits());
5057 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
5058 ExtractCanFuseWithFmul())
5063 :
ST->getVectorInsertExtractBaseCost();
5072 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5075 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr,
nullptr,
5081 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5083 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index,
nullptr, Scalar,
5084 ScalarUserAndIdx, VIC);
5091 return getVectorInstrCostHelper(
I.getOpcode(), Ty, CostKind, Index, &
I,
5098 unsigned Index)
const {
5109 : ST->getVectorInsertExtractBaseCost() + 1;
5121 if (ST->hasFastLD1Single()) {
5122 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5123 (VIC == TTI::VectorInstrContext::Load && Insert))
5127 if (Ty->getElementType()->isFloatingPointTy())
5130 unsigned VecInstCost =
5132 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5139 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5140 return std::nullopt;
5141 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5142 return std::nullopt;
5144 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5145 return std::nullopt;
5152 Cost += InstCost(PromotedTy);
5167 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5178 if (Opcode == Instruction::And && CtxI->
hasOneUse() &&
5186 const auto *UI = cast<Instruction>(U);
5187 return is_contained({Instruction::And, Instruction::Or},
5196 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5202 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5203 Op2Info, Args, CtxI);
5209 if (
auto PromotedCost = getFP16BF16PromoteCost(
5210 Ty, CostKind, Op1Info, Op2Info,
true,
5213 [&](
Type *PromotedTy) {
5214 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
5217 return *PromotedCost;
5220 if (Ty->getScalarType()->isFP128Ty())
5228 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5230 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
5231 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
5238 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5248 ST->hasLimited64bitVectorMulBandwidth())
5256 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5259 if (
LT.second == MVT::v2i64) {
5263 return LT.first * Mul64CostFactor;
5276 (getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind) +
5284 if (
LT.second == MVT::nxv2i64)
5285 return LT.first * Mul64CostFactor;
5334 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5337 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5340 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5344 auto VT = TLI->getValueType(
DL, Ty);
5345 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5349 : (3 * AsrCost + AddCost);
5351 return MulCost + AsrCost + 2 * AddCost;
5353 }
else if (VT.isVector()) {
5364 Cost += 2 * AsrCost;
5369 ? (
LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5373 }
else if (
LT.second == MVT::v2i64) {
5374 return VT.getVectorNumElements() *
5375 getArithmeticInstrCost(Opcode, Ty->
getScalarType(), CostKind,
5382 return MulCost + 2 * AddCost + 2 * AsrCost;
5383 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5388 LT.second.isFixedLengthVector()) {
5394 CostKind, -1,
nullptr,
nullptr);
5396 CostKind, -1,
nullptr,
nullptr);
5398 return ExtractCost + InsertCost +
5406 auto VT = TLI->getValueType(
DL, Ty);
5410 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
5414 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
5422 bool HasMULH = VT == MVT::i64 ||
LT.second == MVT::nxv2i64 ||
5423 LT.second == MVT::nxv4i32 ||
LT.second == MVT::nxv8i16 ||
5424 LT.second == MVT::nxv16i8;
5425 bool Is128bit =
LT.second.is128BitVector();
5428 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5431 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5434 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5437 (HasMULH ? 0 : ShrCost) +
5438 AddCost * 2 + ShrCost;
5439 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5446 if (!VT.isVector() && VT.getSizeInBits() > 64)
5447 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5450 Opcode, Ty, CostKind, Op1Info, Op2Info);
5452 if (TLI->isOperationLegalOrCustom(
ISD,
LT.second) &&
ST->hasSVE()) {
5466 if (
nullptr != Entry)
5474 FVTy &&
LT.second.isFixedLengthVector()) {
5475 unsigned NumElts = FVTy->getNumElements();
5476 unsigned RegElts =
LT.second.getVectorNumElements();
5478 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5482 if (
LT.second.getScalarType() == MVT::i8)
5484 else if (
LT.second.getScalarType() == MVT::i16)
5497 return (4 + DivCost) * VTy->getNumElements();
5503 -1,
nullptr,
nullptr);
5530 LT.second.isFixedLengthVector())
5531 return 2 *
LT.first + 1;
5543 ((CtxI->hasOneUse() &&
5558 return 2 *
LT.first;
5560 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5566 return getCallInstrCost(
nullptr, Ty, {Ty, Ty}, CostKind);
5567 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5580 unsigned NumVectorInstToHideOverhead =
5581 ST->getCLOpts().neon_nonconst_stride_overhead;
5582 int MaxMergeDistance = 64;
5586 return NumVectorInstToHideOverhead;
5598 unsigned Opcode1,
unsigned Opcode2)
const {
5601 if (!
Sched.hasInstrSchedModel())
5604 auto GetRThroughput = [&](
unsigned Opcode,
bool Highest) {
5605 std::optional<double> Res;
5607 while (!Worklist.
empty()) {
5611 append_range(Worklist, AArch64_MC::getVariantSchedClassTargets(
5612 SchedClass,
Sched.getProcessorID()));
5618 if (!Res || (Highest ? RThroughput > *Res : RThroughput < *Res))
5623 std::optional<double> RThroughput1 =
5624 GetRThroughput(Opcode1,
true);
5625 std::optional<double> RThroughput2 =
5626 GetRThroughput(Opcode2,
false);
5627 return RThroughput1 && RThroughput2 && *RThroughput1 > *RThroughput2;
5638 const int AmortizationCost = 20;
5646 VecPred = CurrentPred;
5654 static const auto ValidMinMaxTys = {
5655 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5656 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5657 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5661 (ST->hasFullFP16() &&
5667 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5668 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5669 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5670 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5671 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5672 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5673 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5674 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5675 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5676 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5677 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5679 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5680 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5689 if (Opcode == Instruction::FCmp) {
5691 ValTy, CostKind, Op1Info, Op2Info,
false,
5693 false, [&](
Type *PromotedTy) {
5696 CostKind, Op1Info, Op2Info);
5705 return *PromotedCost;
5709 if (LT.second.getScalarType() != MVT::f64 &&
5710 LT.second.getScalarType() != MVT::f32 &&
5711 LT.second.getScalarType() != MVT::f16)
5713 {ValTy, ValTy}, CostKind);
5716 unsigned Factor = 1;
5717 if (!CondTy->isVectorTy() &&
5731 AArch64::FCMEQv4f32))
5743 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5762 Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info,
I);
5766 AArch64::CMEQv4i32))
5774 if (ST->requiresStrictAlign()) {
5779 Options.AllowOverlappingLoads =
true;
5780 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5785 Options.LoadSizes = {8, 4, 2, 1};
5786 Options.AllowedTailExpansions = {3, 5, 6};
5791 return ST->hasSVE();
5797 switch (MICA.
getID()) {
5798 case Intrinsic::masked_scatter:
5799 case Intrinsic::masked_gather:
5801 case Intrinsic::masked_load:
5802 case Intrinsic::masked_store:
5803 case Intrinsic::masked_expandload:
5804 case Intrinsic::masked_compressstore:
5818 if (!LT.first.isValid())
5823 if (VT->getElementType()->isIntegerTy(1))
5829 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5835 if (MICA.
getID() == Intrinsic::masked_expandload) {
5848 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5868 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5869 return MemOpCost * 2;
5878 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5879 "Should be called on only load or stores.");
5881 case Instruction::Load:
5882 return ST->getCLOpts().sve_gather_overhead.value_or(
5883 ST->getGatherOverhead());
5885 case Instruction::Store:
5886 return ST->getCLOpts().sve_scatter_overhead.value_or(
5887 ST->getScatterOverhead());
5898 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5899 MICA.
getID() == Intrinsic::vp_gather)
5901 : Instruction::Store;
5911 if (!LT.first.isValid())
5915 if (!LT.second.isVector() ||
5917 VT->getElementType()->isIntegerTy(1))
5927 ElementCount LegalVF = LT.second.getVectorElementCount();
5930 {TTI::OK_AnyValue, TTI::OP_None},
I);
5946 EVT VT = TLI->getValueType(
DL, Ty,
true);
5948 if (VT == MVT::Other)
5953 if (!LT.first.isValid())
5959 if (VTy->getElementType()->isIntegerTy(1) &&
5960 !VTy->getElementCount().isKnownMultipleOf(
5966 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5967 : Intrinsic::masked_store;
5981 if (Opcode == Instruction::Store)
5985 if (ST->getFixedLoadLatency())
5986 return (LT.first - 1) + ST->getFixedLoadLatency();
5995 if (LT.second.isScalableVector() ||
5996 ST->useSVEForFixedLengthVectors(LT.second)) {
5997 Inst = AArch64::LDR_ZXI;
5998 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5999 switch (LT.second.getSizeInBits()) {
6001 Inst = AArch64::LDRBui;
6004 Inst = AArch64::LDRHui;
6007 Inst = AArch64::LDRSui;
6010 Inst = AArch64::LDRDui;
6013 Inst = AArch64::LDRQui;
6019 switch (LT.second.getSizeInBits()) {
6021 Inst = AArch64::LDRBBui;
6024 Inst = AArch64::LDRHHui;
6027 Inst = AArch64::LDRWui;
6030 Inst = AArch64::LDRXui;
6038 unsigned SchedClass =
TII->get(Inst).getSchedClass();
6040 ?
Sched.getSchedClassDesc(SchedClass)
6046 return (LT.first - 1) + ST->getLoadLatency();
6049 float NumLoads = (LT.first - 1).
getValue();
6050 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
6051 Sched.computeInstrLatency(*ST, *SCD);
6054 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
6055 LT.second.is128BitVector() && Alignment <
Align(16)) {
6061 const int AmortizationCost = 6;
6063 return LT.first * 2 * AmortizationCost;
6067 if (Ty->isPtrOrPtrVectorTy())
6072 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
6074 if (VT == MVT::v4i8)
6081 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
6082 Alignment !=
Align(1))
6094 if (Remainder != 0) {
6097 while (!TypeWorklist.
empty()) {
6107 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6119 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6120 assert(Factor >= 2 &&
"Invalid interleave factor");
6129 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6133 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6138 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6143 (UseMaskForCond || UseMaskForGaps ||
6144 (Factor > MaxNativeInterleaveFactor &&
6145 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6148 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6151 EC.divideCoefficientBy(Factor));
6157 if (EC.isKnownMultipleOf(Factor) &&
6158 TLI->isLegalInterleavedAccessType(SubVecTy,
DL, UseScalable))
6159 return Factor * TLI->getNumInterleavedAccesses(SubVecTy,
DL, UseScalable);
6164 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6170 if (UseMaskForCond) {
6171 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6172 : Intrinsic::masked_store;
6192 if (Opcode == Instruction::Store && Factor == 4 &&
6193 SubVecCost.second.getScalarSizeInBits() ==
6194 (4 * ResultCost.second.getScalarSizeInBits()))
6195 LegalizationCost *= 4;
6197 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6203 UseMaskForCond, UseMaskForGaps);
6210 for (
auto *
I : Tys) {
6211 if (!
I->isVectorTy())
6222 Align Alignment)
const {
6229 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6230 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6242 Size.getFixedValue() <= 16;
6247 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6248 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6267 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6274 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6280 bool HasUnorderedReductions)
const {
6283 return ST->getMaxInterleaveFactor();
6293 enum { MaxStridedLoads = 7 };
6295 int StridedLoads = 0;
6298 for (
const auto BB : L->blocks()) {
6299 for (
auto &
I : *BB) {
6305 if (L->isLoopInvariant(PtrValue))
6310 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6319 if (StridedLoads > MaxStridedLoads / 2)
6320 return StridedLoads;
6323 return StridedLoads;
6326 int StridedLoads = countStridedLoads(L, SE);
6328 <<
" strided loads\n");
6344 unsigned *FinalSize) {
6348 for (
auto *BB : L->getBlocks()) {
6349 for (
auto &
I : *BB) {
6355 if (!Cost.isValid())
6359 if (LoopCost > Budget)
6381 if (MaxTC > 0 && MaxTC <= 32)
6392 if (Blocks.
size() != 2)
6414 if (!L->isInnermost() || L->getNumBlocks() > 8)
6418 if (!L->getExitBlock())
6424 bool HasParellelizableReductions =
6425 L->getNumBlocks() == 1 &&
6426 any_of(L->getHeader()->phis(),
6428 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6431 if (HasParellelizableReductions &&
6453 if (HasParellelizableReductions) {
6464 if (Header == Latch) {
6467 unsigned Width = 10;
6473 unsigned MaxInstsPerLine = 16;
6475 unsigned BestUC = 1;
6476 unsigned SizeWithBestUC = BestUC *
Size;
6478 unsigned SizeWithUC = UC *
Size;
6479 if (SizeWithUC > 48)
6481 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6482 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6484 SizeWithBestUC = BestUC *
Size;
6494 for (
auto *BB : L->blocks()) {
6495 for (
auto &
I : *BB) {
6505 for (
auto *U :
I.users())
6507 LoadedValuesPlus.
insert(U);
6514 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6540 auto *I = dyn_cast<Instruction>(V);
6541 return I && DependsOnLoopLoad(I, Depth + 1);
6548 DependsOnLoopLoad(
I, 0)) {
6580 if (L->getLoopDepth() > 1)
6591 for (
auto *BB : L->getBlocks()) {
6592 for (
auto &
I : *BB) {
6596 if (IsVectorized &&
I.getType()->isVectorTy())
6607 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6616 if (ST->isAppleMLike())
6618 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6619 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6640 !ST->getSchedModel().isOutOfOrder()) {
6652 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6663 bool CanCreate)
const {
6667 case Intrinsic::aarch64_neon_st1x2:
6668 case Intrinsic::aarch64_neon_st1x3:
6669 case Intrinsic::aarch64_neon_st1x4:
6670 case Intrinsic::aarch64_neon_st2:
6671 case Intrinsic::aarch64_neon_st3:
6672 case Intrinsic::aarch64_neon_st4: {
6675 if (!CanCreate || !ST)
6677 unsigned NumElts = Inst->
arg_size() - 1;
6678 if (ST->getNumElements() != NumElts)
6680 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6686 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6688 Res = Builder.CreateInsertValue(Res, L, i);
6692 case Intrinsic::aarch64_neon_ld1x2:
6693 case Intrinsic::aarch64_neon_ld1x3:
6694 case Intrinsic::aarch64_neon_ld1x4:
6695 case Intrinsic::aarch64_neon_ld2:
6696 case Intrinsic::aarch64_neon_ld3:
6697 case Intrinsic::aarch64_neon_ld4:
6698 if (Inst->
getType() == ExpectedType)
6709 case Intrinsic::aarch64_neon_ld1x2:
6710 case Intrinsic::aarch64_neon_ld1x3:
6711 case Intrinsic::aarch64_neon_ld1x4:
6712 case Intrinsic::aarch64_neon_ld2:
6713 case Intrinsic::aarch64_neon_ld3:
6714 case Intrinsic::aarch64_neon_ld4:
6715 Info.ReadMem =
true;
6716 Info.WriteMem =
false;
6719 case Intrinsic::aarch64_neon_st1x2:
6720 case Intrinsic::aarch64_neon_st1x3:
6721 case Intrinsic::aarch64_neon_st1x4:
6722 case Intrinsic::aarch64_neon_st2:
6723 case Intrinsic::aarch64_neon_st3:
6724 case Intrinsic::aarch64_neon_st4:
6725 Info.ReadMem =
false;
6726 Info.WriteMem =
true;
6735 case Intrinsic::aarch64_neon_ld1x2:
6736 case Intrinsic::aarch64_neon_st1x2:
6737 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6739 case Intrinsic::aarch64_neon_ld1x3:
6740 case Intrinsic::aarch64_neon_st1x3:
6741 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6743 case Intrinsic::aarch64_neon_ld1x4:
6744 case Intrinsic::aarch64_neon_st1x4:
6745 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6747 case Intrinsic::aarch64_neon_ld2:
6748 case Intrinsic::aarch64_neon_st2:
6749 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6751 case Intrinsic::aarch64_neon_ld3:
6752 case Intrinsic::aarch64_neon_st3:
6753 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6755 case Intrinsic::aarch64_neon_ld4:
6756 case Intrinsic::aarch64_neon_st4:
6757 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6769 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6770 bool Considerable =
false;
6771 AllowPromotionWithoutCommonHeader =
false;
6774 Type *ConsideredSExtType =
6776 if (
I.getType() != ConsideredSExtType)
6780 for (
const User *U :
I.users()) {
6782 Considerable =
true;
6786 if (GEPInst->getNumOperands() > 2) {
6787 AllowPromotionWithoutCommonHeader =
true;
6792 return Considerable;
6843 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6853 return LegalizationCost + 2;
6863 LegalizationCost *= LT.first - 1;
6866 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6875 return LegalizationCost + 2;
6883 std::optional<FastMathFlags> FMF,
6899 return BaseCost + FixedVTy->getNumElements();
6913 MVT MTy = LT.second;
6918 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6966 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6967 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6979 return (LT.first - 1) +
Log2_32(NElts);
6984 return (LT.first - 1) + Entry->Cost;
6996 if (LT.first != 1) {
7002 ExtraCost *= LT.first - 1;
7005 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
7006 return Cost + ExtraCost;
7014 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
7016 EVT VecVT = TLI->getValueType(
DL, VecTy);
7017 EVT ResVT = TLI->getValueType(
DL, ResTy);
7027 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7029 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
7031 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
7033 return (LT.first - 1) * 2 + 2;
7044 EVT VecVT = TLI->getValueType(
DL, VecTy);
7045 EVT ResVT = TLI->getValueType(
DL, ResTy);
7048 RedOpcode == Instruction::Add) {
7054 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7056 return LT.first + 2;
7091 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
7092 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7106 if (LT.second.getScalarType() == MVT::i1) {
7115 assert(Entry &&
"Illegal Type for Splice");
7116 LegalizationCost += Entry->Cost;
7117 return LegalizationCost * LT.first;
7121 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7130 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7131 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7137 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7138 if (!FMF->allowReassoc() || !FMF->allowContract())
7142 "FastMathFlags only apply to floating-point partial reductions");
7146 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7147 "Unexpected values for OpBExtend or InputTypeB");
7151 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7152 InputTypeA != InputTypeB))
7163 assert(!OpBExtend &&
"Extended second operand without extended first.");
7164 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7170 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7173 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7186 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7195 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7201 std::pair<InstructionCost, MVT> AccumLT =
7203 std::pair<InstructionCost, MVT> InputLT =
7207 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7208 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7209 (AccumLT.second.isFixedLengthVector() &&
7210 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7214 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7222 if (AccumLT.second.getScalarType() == MVT::i32 &&
7223 InputLT.second.getScalarType() == MVT::i8) {
7225 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7226 return Cost + INegCost;
7228 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7229 return Cost + INegCost;
7234 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7235 return Cost * 3 + INegCost;
7238 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7240 if (AccumLT.second.getScalarType() == MVT::i64 &&
7241 InputLT.second.getScalarType() == MVT::i16)
7242 return Cost + INegCost;
7245 if (AccumLT.second.getScalarType() == MVT::i32 &&
7246 InputLT.second.getScalarType() == MVT::i16 &&
7247 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7250 if (AccumLT.second.getScalarType() == MVT::i64 &&
7251 InputLT.second.getScalarType() == MVT::i8)
7254 return Cost + INegCost;
7257 if (AccumLT.second.getScalarType() == MVT::i16 &&
7258 InputLT.second.getScalarType() == MVT::i8 &&
7259 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7277 if ((!BinOp || IsSExtMul) && !IsSub &&
7278 AccumLT.second.getScalarType() == MVT::i64 &&
7279 InputLT.second.getScalarType() == MVT::i8 &&
7280 IsSupported(
false, ST->hasDotProd()))
7285 if (Opcode == Instruction::FAdd && !IsSub &&
7286 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7287 AccumLT.second.getScalarType() == MVT::f32 &&
7288 InputLT.second.getScalarType() == MVT::f16)
7292 if (Ratio == 2 && !IsUSDot) {
7293 MVT InVT = InputLT.second.getScalarType();
7297 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7299 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7302 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7306 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7307 InVT == MVT::bf16 && IsSub)
7317 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7318 return Cost * 2 + FNegCost;
7322 AccumType, VF, OpAExtend, OpBExtend,
7323 BinOp, CostKind, FMF);
7333 "Expected the Mask to match the return size if given");
7335 "Expected the same scalar types");
7341 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7342 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7343 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7351 return std::max<InstructionCost>(1, LT.first / 4);
7359 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7361 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7364 unsigned TpNumElts = Mask.size();
7365 unsigned LTNumElts = LT.second.getVectorNumElements();
7366 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7368 LT.second.getVectorElementCount());
7370 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7372 for (
unsigned N = 0;
N < NumVecs;
N++) {
7376 unsigned Source1 = -1U, Source2 = -1U;
7377 unsigned NumSources = 0;
7378 for (
unsigned E = 0; E < LTNumElts; E++) {
7379 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7388 unsigned Source = MaskElt / LTNumElts;
7389 if (NumSources == 0) {
7392 }
else if (NumSources == 1 && Source != Source1) {
7395 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7401 if (Source == Source1)
7403 else if (Source == Source2)
7404 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7413 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7424 NTp, NTp, CostKind, NMask, 0,
nullptr, Args,
7427 Result.first->second = NCost;
7441 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7442 if (LT.second.getFixedSizeInBits() >= 128 &&
7444 LT.second.getVectorNumElements() / 2) {
7447 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7461 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7464 return M.value() < 0 || M.value() == (int)M.index();
7470 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7471 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7480 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7481 ST->isSVEorStreamingSVEAvailable() &&
7486 if (ST->isSVEorStreamingSVEAvailable() &&
7500 if (IsLoad && LT.second.isVector() &&
7502 LT.second.getVectorElementCount()))
7508 if (Mask.size() == 4 &&
7510 (SrcTy->getScalarSizeInBits() == 16 ||
7511 SrcTy->getScalarSizeInBits() == 32) &&
7512 all_of(Mask, [](
int E) {
return E < 8; }))
7518 if (LT.second.isFixedLengthVector() &&
7519 LT.second.getVectorNumElements() == Mask.size() &&
7525 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7526 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7527 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7528 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7529 LT.second.getVectorNumElements(), 16) ||
7530 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7531 LT.second.getVectorNumElements(), 32) ||
7532 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7533 LT.second.getVectorNumElements(), 64) ||
7536 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7665 return LT.first * Entry->Cost;
7674 LT.second.getSizeInBits() <= 128 && SubTp) {
7676 if (SubLT.second.isVector()) {
7677 int NumElts = LT.second.getVectorNumElements();
7678 int NumSubElts = SubLT.second.getVectorNumElements();
7679 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7685 if (IsExtractSubvector)
7706 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7717 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7718 ST->useFixedOverScalableIfEqualCost());
7722 return ST->getEpilogueVectorizationMinVF();
7757 unsigned NumInsns = 0;
7759 NumInsns += BB->size();
7763 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7769 int64_t Scale,
unsigned AddrSpace)
const {
7792 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7797 if (
I->getOpcode() == Instruction::Or &&
7801 if (
I->getOpcode() == Instruction::Add ||
7802 I->getOpcode() == Instruction::Sub)
7818 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7819 return std::tie(
C1.NumRegs,
C1.Insns,
C1.NumPrePostIndex,
C1.NumBaseAdds,
7820 C1.AddRecCost,
C1.NumIVMuls,
C1.ScaleCost,
C1.ImmCost,
7831 return all_equal(Shuf->getShuffleMask());
7838 bool AllowSplat =
false) {
7843 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7844 auto *FullTy = FullV->
getType();
7845 auto *HalfTy = HalfV->getType();
7847 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7850 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7853 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7857 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7871 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7872 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7886 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7887 (M2Start != 0 && M2Start != (NumElements / 2)))
7889 if (S1Op1 && S2Op1 && M1Start != M2Start)
7899 return Ext->getType()->getScalarSizeInBits() ==
7900 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7914 Value *VectorOperand =
nullptr;
7931 if (!
GEP ||
GEP->getNumOperands() != 2)
7935 Value *Offsets =
GEP->getOperand(1);
7938 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7944 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7945 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7946 Ops.push_back(&
GEP->getOperandUse(1));
7986 switch (
II->getIntrinsicID()) {
7987 case Intrinsic::aarch64_neon_smull:
7988 case Intrinsic::aarch64_neon_umull:
7991 Ops.push_back(&
II->getOperandUse(0));
7992 Ops.push_back(&
II->getOperandUse(1));
7997 case Intrinsic::fma:
7998 case Intrinsic::fmuladd:
8005 Ops.push_back(&
II->getOperandUse(0));
8007 Ops.push_back(&
II->getOperandUse(1));
8010 case Intrinsic::aarch64_neon_sqdmull:
8011 case Intrinsic::aarch64_neon_sqdmulh:
8012 case Intrinsic::aarch64_neon_sqrdmulh:
8015 Ops.push_back(&
II->getOperandUse(0));
8017 Ops.push_back(&
II->getOperandUse(1));
8018 return !
Ops.empty();
8019 case Intrinsic::aarch64_neon_fmlal:
8020 case Intrinsic::aarch64_neon_fmlal2:
8021 case Intrinsic::aarch64_neon_fmlsl:
8022 case Intrinsic::aarch64_neon_fmlsl2:
8025 Ops.push_back(&
II->getOperandUse(1));
8027 Ops.push_back(&
II->getOperandUse(2));
8028 return !
Ops.empty();
8029 case Intrinsic::aarch64_sve_ptest_first:
8030 case Intrinsic::aarch64_sve_ptest_last:
8032 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
8033 Ops.push_back(&
II->getOperandUse(0));
8034 return !
Ops.empty();
8035 case Intrinsic::aarch64_sme_write_horiz:
8036 case Intrinsic::aarch64_sme_write_vert:
8037 case Intrinsic::aarch64_sme_writeq_horiz:
8038 case Intrinsic::aarch64_sme_writeq_vert: {
8040 if (!Idx || Idx->getOpcode() != Instruction::Add)
8042 Ops.push_back(&
II->getOperandUse(1));
8045 case Intrinsic::aarch64_sme_read_horiz:
8046 case Intrinsic::aarch64_sme_read_vert:
8047 case Intrinsic::aarch64_sme_readq_horiz:
8048 case Intrinsic::aarch64_sme_readq_vert:
8049 case Intrinsic::aarch64_sme_ld1b_vert:
8050 case Intrinsic::aarch64_sme_ld1h_vert:
8051 case Intrinsic::aarch64_sme_ld1w_vert:
8052 case Intrinsic::aarch64_sme_ld1d_vert:
8053 case Intrinsic::aarch64_sme_ld1q_vert:
8054 case Intrinsic::aarch64_sme_st1b_vert:
8055 case Intrinsic::aarch64_sme_st1h_vert:
8056 case Intrinsic::aarch64_sme_st1w_vert:
8057 case Intrinsic::aarch64_sme_st1d_vert:
8058 case Intrinsic::aarch64_sme_st1q_vert:
8059 case Intrinsic::aarch64_sme_ld1b_horiz:
8060 case Intrinsic::aarch64_sme_ld1h_horiz:
8061 case Intrinsic::aarch64_sme_ld1w_horiz:
8062 case Intrinsic::aarch64_sme_ld1d_horiz:
8063 case Intrinsic::aarch64_sme_ld1q_horiz:
8064 case Intrinsic::aarch64_sme_st1b_horiz:
8065 case Intrinsic::aarch64_sme_st1h_horiz:
8066 case Intrinsic::aarch64_sme_st1w_horiz:
8067 case Intrinsic::aarch64_sme_st1d_horiz:
8068 case Intrinsic::aarch64_sme_st1q_horiz: {
8070 if (!Idx || Idx->getOpcode() != Instruction::Add)
8072 Ops.push_back(&
II->getOperandUse(3));
8075 case Intrinsic::aarch64_neon_pmull:
8078 Ops.push_back(&
II->getOperandUse(0));
8079 Ops.push_back(&
II->getOperandUse(1));
8081 case Intrinsic::aarch64_neon_pmull64:
8083 II->getArgOperand(1)))
8085 Ops.push_back(&
II->getArgOperandUse(0));
8086 Ops.push_back(&
II->getArgOperandUse(1));
8088 case Intrinsic::masked_gather:
8091 Ops.push_back(&
II->getArgOperandUse(0));
8093 case Intrinsic::masked_scatter:
8096 Ops.push_back(&
II->getArgOperandUse(1));
8103 auto ShouldSinkCondition = [](
Value *
Cond,
8108 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8112 Ops.push_back(&
II->getOperandUse(0));
8116 switch (
I->getOpcode()) {
8117 case Instruction::Store: {
8120 if (!
SI->isSimple() || !
II)
8129 Ops.push_back(&
SI->getOperandUse(0));
8134 case Instruction::GetElementPtr:
8135 case Instruction::Add:
8136 case Instruction::Sub:
8138 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8140 Ops.push_back(&
I->getOperandUse(
Op));
8145 case Instruction::Select: {
8146 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8149 Ops.push_back(&
I->getOperandUse(0));
8152 case Instruction::UncondBr:
8154 case Instruction::CondBr: {
8158 Ops.push_back(&
I->getOperandUse(0));
8161 case Instruction::FMul:
8166 Ops.push_back(&
I->getOperandUse(0));
8168 Ops.push_back(&
I->getOperandUse(1));
8178 case Instruction::Xor:
8181 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8183 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8188 case Instruction::And:
8189 case Instruction::Or:
8192 if (
I->getOpcode() == Instruction::Or &&
8197 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8200 for (
auto &
Op :
I->operands()) {
8212 Ops.push_back(&Not);
8213 Ops.push_back(&InsertElt);
8223 if (!
I->getType()->isVectorTy())
8224 return !
Ops.empty();
8226 switch (
I->getOpcode()) {
8227 case Instruction::Sub:
8228 case Instruction::Add: {
8237 Ops.push_back(&Ext1->getOperandUse(0));
8238 Ops.push_back(&Ext2->getOperandUse(0));
8241 Ops.push_back(&
I->getOperandUse(0));
8242 Ops.push_back(&
I->getOperandUse(1));
8246 case Instruction::Or: {
8249 if (ST->hasNEON()) {
8256 Ops.push_back(&
I->getOperandUse(0));
8257 Ops.push_back(&
I->getOperandUse(1));
8265 case Instruction::Mul: {
8266 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8269 if (Ty->isScalableTy())
8273 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8276 int NumZExts = 0, NumSExts = 0;
8277 for (
auto &
Op :
I->operands()) {
8284 auto *ExtOp = Ext->getOperand(0);
8285 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8286 Ops.push_back(&Ext->getOperandUse(0));
8294 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8295 I->getType()->getScalarSizeInBits())
8332 if (!ElementConstant || !ElementConstant->
isZero())
8335 unsigned Opcode = OperandInstr->
getOpcode();
8336 if (Opcode == Instruction::SExt)
8338 else if (Opcode == Instruction::ZExt)
8343 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8353 Ops.push_back(&Insert->getOperandUse(1));
8359 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8363 if (!ShouldSinkSplatForIndexedVariant(
I))
8368 Ops.push_back(&
I->getOperandUse(0));
8370 Ops.push_back(&
I->getOperandUse(1));
8372 return !
Ops.empty();
8374 case Instruction::FMul: {
8376 if (
I->getType()->isScalableTy())
8377 return !
Ops.empty();
8381 return !
Ops.empty();
8385 Ops.push_back(&
I->getOperandUse(0));
8387 Ops.push_back(&
I->getOperandUse(1));
8388 return !
Ops.empty();
8397 Align Alignment)
const {
8398 if (!(ST->isSVEAvailable() ||
8399 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8403 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8410 if (!LT.first.isValid())
8415 switch (LT.second.SimpleTy) {
static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static Error reportError(StringRef Message)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Cost tables and simple lookup functions.
This file defines the DenseMap class.
static Value * getCondition(Instruction *I)
const HexagonInstrInfo * TII
This file provides the interface for the instcombine pass implementation.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file defines the LoopVectorizationLegality class.
static const Function * getCalledFunction(const Value *V)
uint64_t IntrinsicInst * II
SmallVector< MachineOperand, 4 > Cond
static uint64_t getBits(uint64_t Val, int Start, int End)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
This file implements the C++20 <bit> header.
unsigned getVectorInsertExtractBaseCost() const
bool useSVEForFixedLengthVectors() const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getCostOfKeepingLiveOverCall(ArrayRef< Type * > Tys) const override
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool hasPossibleIncompatibleOps(const Function *F, bool ConsiderZA, bool ConsiderZT, bool ConsiderSM) const
Returns true if the function has explicit operations that can only be lowered using incompatible inst...
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src) const
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index) const override
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
bool preferFixedOverScalableIfEqualCost() const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
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.
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*...