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"),
190 unsigned IID =
II->getIntrinsicID();
197 case Intrinsic::vscale:
199 case Intrinsic::masked_gather:
203 if (
I->getOperand(0)->getType()->isScalableTy())
206 case Intrinsic::masked_scatter:
207 case Intrinsic::masked_compressstore:
208 case Intrinsic::experimental_vector_histogram_add:
212 if (
I->getOperand(0)->getType()->isScalableTy())
220 if (
I->getType()->isScalableTy() ||
222 [](
const Value *V) { return V->getType()->isScalableTy(); }) ||
236 bool ConsiderZA,
bool ConsiderZT,
238 if (!ConsiderZA && !ConsiderZT && !ConsiderSM)
241 bool IsAlwaysInline =
F->hasFnAttribute(Attribute::AlwaysInline);
248 bool AssumeVScaleIsEquivalent =
249 F->getReturnType()->isScalableTy() ||
250 any_of(
F->getFunctionType()->params(),
251 [](
const Type *
T) { return T->isScalableTy(); });
259 if (CB->isInlineAsm())
262 if (
CallAttrs.callee().isSMEABIRoutine())
271 if (ConsiderSM &&
CallAttrs.callee().hasStreamingCompatibleInterface())
283 return isa<FixedVectorType>(V->getType());
289 (!AssumeVScaleIsEquivalent &&
301 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
302 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
303 FeatureStr.
split(Features,
",");
319 return F.hasFnAttribute(
"fmv-features");
371 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
372 CallAttrs.callee().hasStreamingInterfaceOrBody())
380 if (
CallAttrs.callee().hasStreamingBody()) {
385 bool ConsiderZA =
CallAttrs.requiresZASave();
386 bool ConsiderZT =
CallAttrs.requiresPreservingZT0() ||
387 CallAttrs.requiresPreservingAllZAState();
388 bool ConsiderSM =
CallAttrs.requiresSMChange();
393 if (ConsiderSM && (Caller->isStrictFP() || Callee->isStrictFP()))
418 auto FVTy = dyn_cast<FixedVectorType>(Ty);
420 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
429 unsigned DefaultCallPenalty)
const {
454 if (
F ==
Call.getCaller())
455 return ST->getCLOpts().call_penalty_sm_change * DefaultCallPenalty;
457 return ST->getCLOpts().inline_call_penalty_sm_change * DefaultCallPenalty;
460 return DefaultCallPenalty;
471 ST->isSVEorStreamingSVEAvailable() &&
472 !ST->disableMaximizeScalableBandwidth();
496 assert(Ty->isIntegerTy());
498 unsigned BitSize = Ty->getPrimitiveSizeInBits();
505 ImmVal =
Imm.sext((BitSize + 63) & ~0x3fU);
510 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
516 return std::max<InstructionCost>(1,
Cost);
523 assert(Ty->isIntegerTy());
525 unsigned BitSize = Ty->getPrimitiveSizeInBits();
531 unsigned ImmIdx = ~0U;
535 case Instruction::GetElementPtr:
540 case Instruction::Store:
543 case Instruction::Add:
544 case Instruction::Sub:
545 case Instruction::Mul:
546 case Instruction::UDiv:
547 case Instruction::SDiv:
548 case Instruction::URem:
549 case Instruction::SRem:
550 case Instruction::And:
551 case Instruction::Or:
552 case Instruction::Xor:
553 case Instruction::ICmp:
557 case Instruction::Shl:
558 case Instruction::LShr:
559 case Instruction::AShr:
563 case Instruction::Trunc:
564 case Instruction::ZExt:
565 case Instruction::SExt:
566 case Instruction::IntToPtr:
567 case Instruction::PtrToInt:
568 case Instruction::BitCast:
569 case Instruction::PHI:
570 case Instruction::Call:
571 case Instruction::Select:
572 case Instruction::Ret:
573 case Instruction::Load:
578 int NumConstants = (BitSize + 63) / 64;
591 assert(Ty->isIntegerTy());
593 unsigned BitSize = Ty->getPrimitiveSizeInBits();
602 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
608 case Intrinsic::sadd_with_overflow:
609 case Intrinsic::uadd_with_overflow:
610 case Intrinsic::ssub_with_overflow:
611 case Intrinsic::usub_with_overflow:
612 case Intrinsic::smul_with_overflow:
613 case Intrinsic::umul_with_overflow:
615 int NumConstants = (BitSize + 63) / 64;
622 case Intrinsic::experimental_stackmap:
623 if ((Idx < 2) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
626 case Intrinsic::experimental_patchpoint_void:
627 case Intrinsic::experimental_patchpoint:
628 if ((Idx < 4) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
631 case Intrinsic::experimental_gc_statepoint:
632 if ((Idx < 5) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
642 if (TyWidth == 32 || TyWidth == 64)
651 return ST->getMispredictionPenalty();
672 unsigned TotalHistCnts = 1;
682 unsigned EC = VTy->getElementCount().getKnownMinValue();
687 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
689 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
693 TotalHistCnts = EC / NaturalVectorWidth;
695 return InstructionCost(ST->getCLOpts().base_histcnt_cost * TotalHistCnts);
712 !
is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
716 switch (ICA.
getID()) {
717 case Intrinsic::experimental_vector_histogram_add: {
724 case Intrinsic::experimental_vector_histogram_uadd_sat:
725 case Intrinsic::experimental_vector_histogram_umax:
726 case Intrinsic::experimental_vector_histogram_umin:
729 case Intrinsic::clmul: {
734 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
738 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
743 -1,
nullptr,
nullptr) *
746 -1,
nullptr,
nullptr);
750 if (LT.second.SimpleTy == MVT::nxv2i64)
751 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
754 if (ST->hasSVE2() || ST->hasSME()) {
755 switch (LT.second.SimpleTy) {
770 if (LT.second.SimpleTy == MVT::nxv2i64)
774 switch (LT.second.SimpleTy) {
784 -1,
nullptr,
nullptr) *
787 -1,
nullptr,
nullptr));
796 return LT.first * 11;
798 return LT.first * 14;
805 case Intrinsic::smulh:
806 case Intrinsic::umulh: {
812 if (RetTy->getScalarSizeInBits() > 64)
826 return MulCost + ExtraCost;
831 return LT.first + ExtraCost;
847 return LT.first * Entry->Cost + ExtraCost;
851 case Intrinsic::umin:
852 case Intrinsic::umax:
853 case Intrinsic::smin:
854 case Intrinsic::smax: {
855 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
856 MVT::v8i16, MVT::v2i32, MVT::v4i32,
857 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
864 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
865 EVT VT = TLI->getValueType(
DL, RetTy,
true);
866 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
867 return LT.first * (IsSigned ? 5 : 3);
869 if (LT.second == MVT::v2i64)
875 case Intrinsic::scmp:
876 case Intrinsic::ucmp: {
878 {Intrinsic::scmp, MVT::i32, 3},
879 {Intrinsic::scmp, MVT::i64, 3},
880 {Intrinsic::scmp, MVT::v8i8, 3},
881 {Intrinsic::scmp, MVT::v16i8, 3},
882 {Intrinsic::scmp, MVT::v4i16, 3},
883 {Intrinsic::scmp, MVT::v8i16, 3},
884 {Intrinsic::scmp, MVT::v2i32, 3},
885 {Intrinsic::scmp, MVT::v4i32, 3},
886 {Intrinsic::scmp, MVT::v1i64, 3},
887 {Intrinsic::scmp, MVT::v2i64, 3},
893 return Entry->Cost * LT.first;
896 case Intrinsic::sadd_sat:
897 case Intrinsic::ssub_sat:
898 case Intrinsic::uadd_sat:
899 case Intrinsic::usub_sat: {
900 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
901 MVT::v8i16, MVT::v2i32, MVT::v4i32,
907 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
909 return LT.first * Instrs;
914 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
915 return LT.first * Instrs;
919 case Intrinsic::abs: {
920 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
921 MVT::v8i16, MVT::v2i32, MVT::v4i32,
922 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
923 MVT::nxv4i32, MVT::nxv2i64};
929 case Intrinsic::bswap: {
930 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
931 MVT::v4i32, MVT::v2i64};
934 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
939 case Intrinsic::fmuladd: {
944 (EltTy->
isHalfTy() && ST->hasFullFP16()))
948 case Intrinsic::stepvector: {
957 Cost += AddCost * (LT.first - 1);
961 case Intrinsic::vector_extract:
962 case Intrinsic::vector_insert: {
975 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
976 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
984 getTLI()->getTypeConversion(
C, SubVecVT);
986 getTLI()->getTypeConversion(
C, VecVT);
994 case Intrinsic::bitreverse: {
996 {Intrinsic::bitreverse, MVT::i32, 1},
997 {Intrinsic::bitreverse, MVT::i64, 1},
998 {Intrinsic::bitreverse, MVT::v8i8, 1},
999 {Intrinsic::bitreverse, MVT::v16i8, 1},
1000 {Intrinsic::bitreverse, MVT::v4i16, 2},
1001 {Intrinsic::bitreverse, MVT::v8i16, 2},
1002 {Intrinsic::bitreverse, MVT::v2i32, 2},
1003 {Intrinsic::bitreverse, MVT::v4i32, 2},
1004 {Intrinsic::bitreverse, MVT::v1i64, 2},
1005 {Intrinsic::bitreverse, MVT::v2i64, 2},
1013 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
1014 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
1015 return LegalisationCost.first * Entry->Cost + 1;
1017 return LegalisationCost.first * Entry->Cost;
1021 case Intrinsic::ctpop: {
1023 MVT MTy = LT.second;
1025 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
1028 return LT.first + ExtraCost;
1030 if (!ST->hasNEON()) {
1060 RetTy->getScalarSizeInBits()
1063 return LT.first * Entry->Cost + ExtraCost;
1067 case Intrinsic::sadd_with_overflow:
1068 case Intrinsic::uadd_with_overflow:
1069 case Intrinsic::ssub_with_overflow:
1070 case Intrinsic::usub_with_overflow:
1071 case Intrinsic::smul_with_overflow:
1072 case Intrinsic::umul_with_overflow: {
1074 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
1075 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
1076 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
1077 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
1078 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
1079 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
1080 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
1081 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
1082 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
1083 {Intrinsic::usub_with_overflow, MVT::i8, 3},
1084 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
1085 {Intrinsic::usub_with_overflow, MVT::i16, 3},
1086 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
1087 {Intrinsic::usub_with_overflow, MVT::i32, 1},
1088 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
1089 {Intrinsic::usub_with_overflow, MVT::i64, 1},
1090 {Intrinsic::smul_with_overflow, MVT::i8, 5},
1091 {Intrinsic::umul_with_overflow, MVT::i8, 4},
1092 {Intrinsic::smul_with_overflow, MVT::i16, 5},
1093 {Intrinsic::umul_with_overflow, MVT::i16, 4},
1094 {Intrinsic::smul_with_overflow, MVT::i32, 2},
1095 {Intrinsic::umul_with_overflow, MVT::i32, 2},
1096 {Intrinsic::smul_with_overflow, MVT::i64, 3},
1097 {Intrinsic::umul_with_overflow, MVT::i64, 3},
1099 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
1106 case Intrinsic::fptosi_sat:
1107 case Intrinsic::fptoui_sat: {
1110 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
1112 EVT MTy = TLI->getValueType(
DL, RetTy);
1115 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
1116 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
1117 LT.second == MVT::v2f64)) {
1119 (LT.second == MVT::f64 && MTy == MVT::i32) ||
1120 (LT.second == MVT::f32 && MTy == MVT::i64)))
1129 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
1136 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
1137 (LT.second == MVT::f16 && MTy == MVT::i64) ||
1138 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1152 if ((LT.second.getScalarType() == MVT::f32 ||
1153 LT.second.getScalarType() == MVT::f64 ||
1154 LT.second.getScalarType() == MVT::f16) &&
1157 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1158 if (LT.second.isVector())
1159 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1163 LegalTy, {LegalTy, LegalTy});
1167 LegalTy, {LegalTy, LegalTy});
1169 return LT.first *
Cost +
1170 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1176 RetTy = RetTy->getScalarType();
1177 if (LT.second.isVector()) {
1195 return LT.first *
Cost;
1197 case Intrinsic::fshl:
1198 case Intrinsic::fshr: {
1207 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1208 (RetTy->getPrimitiveSizeInBits() == 32 ||
1209 RetTy->getPrimitiveSizeInBits() == 64)) {
1222 {Intrinsic::fshl, MVT::v4i32, 2},
1223 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1224 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1225 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1231 return LegalisationCost.first * Entry->Cost;
1235 if (!RetTy->isIntegerTy())
1240 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1241 RetTy->getScalarSizeInBits() < 64) ||
1242 (RetTy->getScalarSizeInBits() % 64 != 0);
1243 unsigned ExtraCost = HigherCost ? 1 : 0;
1244 if (RetTy->getScalarSizeInBits() == 32 ||
1245 RetTy->getScalarSizeInBits() == 64)
1248 else if (HigherCost)
1252 return TyL.first + ExtraCost;
1254 case Intrinsic::get_active_lane_mask: {
1256 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1258 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1261 if (RetTy->isScalableTy()) {
1262 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1272 if (ST->hasSVE2p1() || ST->hasSME2()) {
1284 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1287 return Cost + (SplitCost * (
Cost - 1));
1302 case Intrinsic::experimental_vector_match: {
1303 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1309 unsigned SearchSize = NeedleTy->getNumElements();
1310 if (SearchSize <= 2)
1315 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1319 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1325 unsigned MatchesRequiredForNeedle =
1337 return Cost * LegalParts * MatchesRequiredForNeedle;
1339 case Intrinsic::cttz: {
1341 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1342 return LT.first * 2;
1343 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1344 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1345 return LT.first * 3;
1348 case Intrinsic::experimental_cttz_elts: {
1358 case Intrinsic::loop_dependence_raw_mask:
1359 case Intrinsic::loop_dependence_war_mask: {
1361 if (ST->hasSVE2() || ST->hasSME()) {
1362 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1363 unsigned EltSizeInBytes =
1373 case Intrinsic::experimental_vector_extract_last_active:
1374 if (ST->isSVEorStreamingSVEAvailable()) {
1380 case Intrinsic::pow: {
1383 EVT VT = getTLI()->getValueType(
DL, RetTy);
1384 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1385 bool HasLibcall = getTLI()->getLibcallImpl(LC) != RTLIB::Unsupported;
1400 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1401 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1411 return (Sqrt * 2) +
FMul;
1422 case Intrinsic::sqrt:
1423 case Intrinsic::fabs:
1424 case Intrinsic::ceil:
1425 case Intrinsic::floor:
1426 case Intrinsic::nearbyint:
1427 case Intrinsic::round:
1428 case Intrinsic::rint:
1429 case Intrinsic::roundeven:
1430 case Intrinsic::trunc:
1431 case Intrinsic::minnum:
1432 case Intrinsic::maxnum:
1433 case Intrinsic::minimum:
1434 case Intrinsic::maximum: {
1452 auto RequiredType =
II.getType();
1455 assert(PN &&
"Expected Phi Node!");
1458 if (!PN->hasOneUse())
1459 return std::nullopt;
1461 for (
Value *IncValPhi : PN->incoming_values()) {
1464 Reinterpret->getIntrinsicID() !=
1465 Intrinsic::aarch64_sve_convert_to_svbool ||
1466 RequiredType != Reinterpret->getArgOperand(0)->getType())
1467 return std::nullopt;
1475 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1477 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1550 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1555 return GoverningPredicateIdx;
1560 GoverningPredicateIdx = Index;
1582 return UndefIntrinsic;
1587 UndefIntrinsic = IID;
1614 return CmpPredicate;
1619 CmpPredicate = Pred;
1635 return ResultLanes == InactiveLanesTakenFromOperand;
1640 return OperandIdxForInactiveLanes;
1644 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1645 ResultLanes = InactiveLanesTakenFromOperand;
1646 OperandIdxForInactiveLanes = Index;
1651 return ResultLanes == InactiveLanesAreNotDefined;
1655 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1656 ResultLanes = InactiveLanesAreNotDefined;
1661 return ResultLanes == InactiveLanesAreUnused;
1665 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1666 ResultLanes = InactiveLanesAreUnused;
1676 ResultIsZeroInitialized =
true;
1687 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1692 return OperandIdxWithNoActiveLanes;
1697 OperandIdxWithNoActiveLanes = Index;
1702 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1705 unsigned IROpcode = 0;
1708 enum PredicationStyle {
1710 InactiveLanesTakenFromOperand,
1711 InactiveLanesAreNotDefined,
1712 InactiveLanesAreUnused
1715 bool ResultIsZeroInitialized =
false;
1716 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1717 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1725 return !isa<ScalableVectorType>(V->getType());
1733 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1734 case Intrinsic::aarch64_sve_fcvt_f16f32:
1735 case Intrinsic::aarch64_sve_fcvt_f16f64:
1736 case Intrinsic::aarch64_sve_fcvt_f32f16:
1737 case Intrinsic::aarch64_sve_fcvt_f32f64:
1738 case Intrinsic::aarch64_sve_fcvt_f64f16:
1739 case Intrinsic::aarch64_sve_fcvt_f64f32:
1740 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1741 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1742 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1743 case Intrinsic::aarch64_sve_fcvtzs:
1744 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1745 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1746 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1747 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1748 case Intrinsic::aarch64_sve_fcvtzu:
1749 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1750 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1751 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1752 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1753 case Intrinsic::aarch64_sve_revb:
1754 case Intrinsic::aarch64_sve_revh:
1755 case Intrinsic::aarch64_sve_revw:
1756 case Intrinsic::aarch64_sve_revd:
1757 case Intrinsic::aarch64_sve_scvtf:
1758 case Intrinsic::aarch64_sve_scvtf_f16i32:
1759 case Intrinsic::aarch64_sve_scvtf_f16i64:
1760 case Intrinsic::aarch64_sve_scvtf_f32i64:
1761 case Intrinsic::aarch64_sve_scvtf_f64i32:
1762 case Intrinsic::aarch64_sve_ucvtf:
1763 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1764 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1765 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1766 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1769 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1770 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1771 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1772 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1775 case Intrinsic::aarch64_sve_fabd:
1777 case Intrinsic::aarch64_sve_fadd:
1780 case Intrinsic::aarch64_sve_fdiv:
1783 case Intrinsic::aarch64_sve_fmax:
1785 case Intrinsic::aarch64_sve_fmaxnm:
1787 case Intrinsic::aarch64_sve_fmin:
1789 case Intrinsic::aarch64_sve_fminnm:
1791 case Intrinsic::aarch64_sve_fmla:
1793 case Intrinsic::aarch64_sve_fmls:
1795 case Intrinsic::aarch64_sve_fmul:
1798 case Intrinsic::aarch64_sve_fmulx:
1800 case Intrinsic::aarch64_sve_fnmla:
1802 case Intrinsic::aarch64_sve_fnmls:
1804 case Intrinsic::aarch64_sve_fsub:
1807 case Intrinsic::aarch64_sve_add:
1810 case Intrinsic::aarch64_sve_mla:
1812 case Intrinsic::aarch64_sve_mls:
1814 case Intrinsic::aarch64_sve_mul:
1817 case Intrinsic::aarch64_sve_sabd:
1819 case Intrinsic::aarch64_sve_sdiv:
1822 case Intrinsic::aarch64_sve_smax:
1824 case Intrinsic::aarch64_sve_smin:
1826 case Intrinsic::aarch64_sve_smulh:
1828 case Intrinsic::aarch64_sve_sub:
1831 case Intrinsic::aarch64_sve_uabd:
1833 case Intrinsic::aarch64_sve_udiv:
1836 case Intrinsic::aarch64_sve_umax:
1838 case Intrinsic::aarch64_sve_umin:
1840 case Intrinsic::aarch64_sve_umulh:
1842 case Intrinsic::aarch64_sve_asr:
1845 case Intrinsic::aarch64_sve_lsl:
1848 case Intrinsic::aarch64_sve_lsr:
1851 case Intrinsic::aarch64_sve_and:
1854 case Intrinsic::aarch64_sve_bic:
1856 case Intrinsic::aarch64_sve_eor:
1859 case Intrinsic::aarch64_sve_orr:
1862 case Intrinsic::aarch64_sve_shsub:
1864 case Intrinsic::aarch64_sve_shsubr:
1866 case Intrinsic::aarch64_sve_sqrshl:
1868 case Intrinsic::aarch64_sve_sqshl:
1870 case Intrinsic::aarch64_sve_sqsub:
1872 case Intrinsic::aarch64_sve_srshl:
1874 case Intrinsic::aarch64_sve_uhsub:
1876 case Intrinsic::aarch64_sve_uhsubr:
1878 case Intrinsic::aarch64_sve_uqrshl:
1880 case Intrinsic::aarch64_sve_uqshl:
1882 case Intrinsic::aarch64_sve_uqsub:
1884 case Intrinsic::aarch64_sve_urshl:
1887 case Intrinsic::aarch64_sve_add_u:
1890 case Intrinsic::aarch64_sve_and_u:
1893 case Intrinsic::aarch64_sve_asr_u:
1896 case Intrinsic::aarch64_sve_eor_u:
1899 case Intrinsic::aarch64_sve_fadd_u:
1902 case Intrinsic::aarch64_sve_fdiv_u:
1905 case Intrinsic::aarch64_sve_fmul_u:
1908 case Intrinsic::aarch64_sve_fsub_u:
1911 case Intrinsic::aarch64_sve_lsl_u:
1914 case Intrinsic::aarch64_sve_lsr_u:
1917 case Intrinsic::aarch64_sve_mul_u:
1920 case Intrinsic::aarch64_sve_orr_u:
1923 case Intrinsic::aarch64_sve_sdiv_u:
1926 case Intrinsic::aarch64_sve_sub_u:
1929 case Intrinsic::aarch64_sve_udiv_u:
1933 case Intrinsic::aarch64_sve_addqv:
1934 case Intrinsic::aarch64_sve_bic_z:
1935 case Intrinsic::aarch64_sve_brka_z:
1936 case Intrinsic::aarch64_sve_brkb_z:
1937 case Intrinsic::aarch64_sve_brkn_z:
1938 case Intrinsic::aarch64_sve_brkpa_z:
1939 case Intrinsic::aarch64_sve_brkpb_z:
1940 case Intrinsic::aarch64_sve_cntp:
1941 case Intrinsic::aarch64_sve_compact:
1942 case Intrinsic::aarch64_sve_eorv:
1943 case Intrinsic::aarch64_sve_eorqv:
1944 case Intrinsic::aarch64_sve_nand_z:
1945 case Intrinsic::aarch64_sve_nor_z:
1946 case Intrinsic::aarch64_sve_orn_z:
1947 case Intrinsic::aarch64_sve_orv:
1948 case Intrinsic::aarch64_sve_orqv:
1949 case Intrinsic::aarch64_sve_pnext:
1950 case Intrinsic::aarch64_sve_rdffr_z:
1951 case Intrinsic::aarch64_sve_saddv:
1952 case Intrinsic::aarch64_sve_uaddv:
1953 case Intrinsic::aarch64_sve_umaxv:
1954 case Intrinsic::aarch64_sve_umaxqv:
1955 case Intrinsic::aarch64_sve_facge:
1956 case Intrinsic::aarch64_sve_facgt:
1957 case Intrinsic::aarch64_sve_ld1:
1958 case Intrinsic::aarch64_sve_ld1_gather:
1959 case Intrinsic::aarch64_sve_ld1_gather_index:
1960 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1961 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1962 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1963 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1964 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1965 case Intrinsic::aarch64_sve_ld1q_gather_index:
1966 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1967 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1968 case Intrinsic::aarch64_sve_ld1ro:
1969 case Intrinsic::aarch64_sve_ld1rq:
1970 case Intrinsic::aarch64_sve_ld1udq:
1971 case Intrinsic::aarch64_sve_ld1uwq:
1972 case Intrinsic::aarch64_sve_ld2_sret:
1973 case Intrinsic::aarch64_sve_ld2q_sret:
1974 case Intrinsic::aarch64_sve_ld3_sret:
1975 case Intrinsic::aarch64_sve_ld3q_sret:
1976 case Intrinsic::aarch64_sve_ld4_sret:
1977 case Intrinsic::aarch64_sve_ld4q_sret:
1978 case Intrinsic::aarch64_sve_ldff1:
1979 case Intrinsic::aarch64_sve_ldff1_gather:
1980 case Intrinsic::aarch64_sve_ldff1_gather_index:
1981 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1982 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1983 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1984 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1985 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1986 case Intrinsic::aarch64_sve_ldnf1:
1987 case Intrinsic::aarch64_sve_ldnt1:
1988 case Intrinsic::aarch64_sve_ldnt1_gather:
1989 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1990 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1991 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1994 case Intrinsic::aarch64_sve_and_z:
1997 case Intrinsic::aarch64_sve_orr_z:
2000 case Intrinsic::aarch64_sve_eor_z:
2004 case Intrinsic::aarch64_sve_cmpeq:
2005 case Intrinsic::aarch64_sve_cmpeq_wide:
2008 case Intrinsic::aarch64_sve_cmpge:
2009 case Intrinsic::aarch64_sve_cmpge_wide:
2012 case Intrinsic::aarch64_sve_cmpgt:
2013 case Intrinsic::aarch64_sve_cmpgt_wide:
2016 case Intrinsic::aarch64_sve_cmphi:
2017 case Intrinsic::aarch64_sve_cmphi_wide:
2020 case Intrinsic::aarch64_sve_cmphs:
2021 case Intrinsic::aarch64_sve_cmphs_wide:
2024 case Intrinsic::aarch64_sve_cmple_wide:
2027 case Intrinsic::aarch64_sve_cmplo_wide:
2030 case Intrinsic::aarch64_sve_cmpls_wide:
2033 case Intrinsic::aarch64_sve_cmplt_wide:
2036 case Intrinsic::aarch64_sve_cmpne:
2037 case Intrinsic::aarch64_sve_cmpne_wide:
2040 case Intrinsic::aarch64_sve_fcmpeq:
2043 case Intrinsic::aarch64_sve_fcmpge:
2046 case Intrinsic::aarch64_sve_fcmpgt:
2049 case Intrinsic::aarch64_sve_fcmpne:
2052 case Intrinsic::aarch64_sve_fcmpuo:
2056 case Intrinsic::aarch64_sve_prf:
2057 case Intrinsic::aarch64_sve_prfb_gather_index:
2058 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
2059 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
2060 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
2061 case Intrinsic::aarch64_sve_prfd_gather_index:
2062 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
2063 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
2064 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
2065 case Intrinsic::aarch64_sve_prfh_gather_index:
2066 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
2067 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
2068 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
2069 case Intrinsic::aarch64_sve_prfw_gather_index:
2070 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
2071 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
2072 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
2075 case Intrinsic::aarch64_sve_st1_scatter:
2076 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
2077 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
2078 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
2079 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
2080 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
2081 case Intrinsic::aarch64_sve_st1dq:
2082 case Intrinsic::aarch64_sve_st1q_scatter_index:
2083 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
2084 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
2085 case Intrinsic::aarch64_sve_st1wq:
2086 case Intrinsic::aarch64_sve_stnt1:
2087 case Intrinsic::aarch64_sve_stnt1_scatter:
2088 case Intrinsic::aarch64_sve_stnt1_scatter_index:
2089 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
2090 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
2092 case Intrinsic::aarch64_sve_st2:
2093 case Intrinsic::aarch64_sve_st2q:
2095 case Intrinsic::aarch64_sve_st3:
2096 case Intrinsic::aarch64_sve_st3q:
2098 case Intrinsic::aarch64_sve_st4:
2099 case Intrinsic::aarch64_sve_st4q:
2107 Value *UncastedPred;
2113 Pred = UncastedPred;
2119 if (OrigPredTy->getMinNumElements() <=
2121 ->getMinNumElements())
2122 Pred = UncastedPred;
2126 return C &&
C->isAllOnesValue();
2133 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
2134 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2142static std::optional<Instruction *>
2149 Value *Op1 =
II.getOperand(1);
2150 Value *Op2 =
II.getOperand(2);
2175 Value *NarrowOp1, *NarrowOp2;
2186 else if (SimpleNarrow == NarrowOp1)
2188 else if (SimpleNarrow == NarrowOp2)
2193 SimpleNarrow->
getType(), SimpleNarrow);
2202 return std::nullopt;
2213 if (SimpleII == Inactive)
2221static std::optional<Instruction *>
2225 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2226 "Expected a compare operation!");
2233 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2234 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2235 "Unexpected wide compare!");
2251 const APInt *LHSVal, *RHSVal;
2253 return std::nullopt;
2276 return std::nullopt;
2290static std::optional<Instruction *>
2294 return std::nullopt;
2323 II.setCalledFunction(NewDecl);
2329 return std::nullopt;
2340 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2343 return std::nullopt;
2355static std::optional<Instruction *>
2357 auto m_ConvertToSVBool = [](
auto P) {
2361 Intrinsic::aarch64_sve_convert_from_svbool;
2384 return std::nullopt;
2388 case Intrinsic::aarch64_sve_and_z:
2389 case Intrinsic::aarch64_sve_bic_z:
2390 case Intrinsic::aarch64_sve_eor_z:
2391 case Intrinsic::aarch64_sve_nand_z:
2392 case Intrinsic::aarch64_sve_nor_z:
2393 case Intrinsic::aarch64_sve_orn_z:
2394 case Intrinsic::aarch64_sve_orr_z:
2397 return std::nullopt;
2400 Value *BinOpPred = BinOp->getOperand(0);
2401 Value *BinOpOp1 = BinOp->getOperand(1);
2402 Value *BinOpOp2 = BinOp->getOperand(2);
2404 Value *NarrowBinOpPred;
2406 return std::nullopt;
2408 Value *NarrowBinOpOp1 =
2410 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2411 if (BinOpOp1 != BinOpOp2)
2415 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2419static std::optional<Instruction *>
2426 return BinOpCombine;
2431 return std::nullopt;
2434 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2443 if (CursorVTy->getElementCount().getKnownMinValue() <
2444 IVTy->getElementCount().getKnownMinValue())
2448 if (Cursor->getType() == IVTy)
2449 EarliestReplacement = Cursor;
2454 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2455 Intrinsic::aarch64_sve_convert_to_svbool ||
2456 IntrinsicCursor->getIntrinsicID() ==
2457 Intrinsic::aarch64_sve_convert_from_svbool))
2460 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2461 Cursor = IntrinsicCursor->getOperand(0);
2466 if (!EarliestReplacement)
2467 return std::nullopt;
2475 auto *OpPredicate =
II.getOperand(0);
2492 II.getArgOperand(2));
2498 return std::nullopt;
2502 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2511 II.getArgOperand(0));
2520 if (!
II.hasOneUse())
2521 return std::nullopt;
2524 return std::nullopt;
2527 switch (
II.getIntrinsicID()) {
2528 case Intrinsic::aarch64_sve_cmpne:
2529 IID = Intrinsic::aarch64_sve_cmpeq;
2531 case Intrinsic::aarch64_sve_cmpne_wide:
2532 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2534 case Intrinsic::aarch64_sve_cmpeq:
2535 IID = Intrinsic::aarch64_sve_cmpne;
2537 case Intrinsic::aarch64_sve_cmpeq_wide:
2538 IID = Intrinsic::aarch64_sve_cmpne_wide;
2541 return std::nullopt;
2546 IID,
II.getOperand(1)->getType(),
2547 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2559 return std::nullopt;
2561 for (
auto *U :
II.users()) {
2564 Type *Ty =
II.getOperand(1)->getType();
2569 Intrinsic::aarch64_sve_umin, Ty,
2570 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2576 return std::nullopt;
2590 return std::nullopt;
2595 if (!SplatValue || !SplatValue->isZero())
2596 return std::nullopt;
2601 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2602 return std::nullopt;
2606 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2607 return std::nullopt;
2610 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2611 return std::nullopt;
2616 return std::nullopt;
2619 return std::nullopt;
2623 return std::nullopt;
2627 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2628 return std::nullopt;
2630 unsigned NumElts = VecTy->getNumElements();
2631 unsigned PredicateBits = 0;
2634 for (
unsigned I = 0;
I < NumElts; ++
I) {
2637 return std::nullopt;
2639 PredicateBits |= 1 << (
I * (16 / NumElts));
2643 if (PredicateBits == 0) {
2645 PFalse->takeName(&
II);
2651 for (
unsigned I = 0;
I < 16; ++
I)
2652 if ((PredicateBits & (1 <<
I)) != 0)
2655 unsigned PredSize = Mask & -Mask;
2660 for (
unsigned I = 0;
I < 16;
I += PredSize)
2661 if ((PredicateBits & (1 <<
I)) == 0)
2662 return std::nullopt;
2664 auto *ConvertToSVBool =
2667 auto *ConvertFromSVBool =
2669 II.getType(), ConvertToSVBool);
2677 Value *Pg =
II.getArgOperand(0);
2678 Value *Vec =
II.getArgOperand(1);
2679 auto IntrinsicID =
II.getIntrinsicID();
2680 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2692 auto OpC = OldBinOp->getOpcode();
2698 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2704 if (IsAfter &&
C &&
C->isNullValue()) {
2708 Extract->insertBefore(
II.getIterator());
2709 Extract->takeName(&
II);
2715 return std::nullopt;
2717 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2718 return std::nullopt;
2720 const auto PTruePattern =
2726 return std::nullopt;
2728 unsigned Idx = MinNumElts - 1;
2738 if (Idx >= PgVTy->getMinNumElements())
2739 return std::nullopt;
2744 Extract->insertBefore(
II.getIterator());
2745 Extract->takeName(&
II);
2758 Value *Pg =
II.getArgOperand(0);
2760 Value *Vec =
II.getArgOperand(2);
2763 if (!Ty->isIntegerTy())
2764 return std::nullopt;
2769 return std::nullopt;
2786 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2801static std::optional<Instruction *>
2805 if (
Pattern == AArch64SVEPredPattern::all) {
2814 return MinNumElts && NumElts >= MinNumElts
2816 II, ConstantInt::get(
II.getType(), MinNumElts)))
2820static std::optional<Instruction *>
2823 if (!ST->isStreaming())
2824 return std::nullopt;
2836 Value *PgVal =
II.getArgOperand(0);
2837 Value *OpVal =
II.getArgOperand(1);
2841 if (PgVal == OpVal &&
2842 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2843 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2858 return std::nullopt;
2862 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2863 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2877 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2878 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2879 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2880 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2881 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2882 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2883 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2884 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2885 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2886 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2887 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2888 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2889 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2899 return std::nullopt;
2902template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2903static std::optional<Instruction *>
2905 bool MergeIntoAddendOp) {
2907 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2908 if (MergeIntoAddendOp) {
2909 AddendOp =
II.getOperand(1);
2910 Mul =
II.getOperand(2);
2912 AddendOp =
II.getOperand(2);
2913 Mul =
II.getOperand(1);
2918 return std::nullopt;
2920 if (!
Mul->hasOneUse())
2921 return std::nullopt;
2924 if (
II.getType()->isFPOrFPVectorTy()) {
2929 return std::nullopt;
2931 return std::nullopt;
2936 if (MergeIntoAddendOp)
2946static std::optional<Instruction *>
2948 Value *Pred =
II.getOperand(0);
2949 Value *PtrOp =
II.getOperand(1);
2950 Type *VecTy =
II.getType();
2965static std::optional<Instruction *>
2967 Value *VecOp =
II.getOperand(0);
2968 Value *Pred =
II.getOperand(1);
2969 Value *PtrOp =
II.getOperand(2);
2985 case Intrinsic::aarch64_sve_fmul_u:
2986 return Instruction::BinaryOps::FMul;
2987 case Intrinsic::aarch64_sve_fadd_u:
2988 return Instruction::BinaryOps::FAdd;
2989 case Intrinsic::aarch64_sve_fsub_u:
2990 return Instruction::BinaryOps::FSub;
2992 return Instruction::BinaryOpsEnd;
2996static std::optional<Instruction *>
2999 if (
II.isStrictFP())
3000 return std::nullopt;
3002 auto *OpPredicate =
II.getOperand(0);
3004 if (BinOpCode == Instruction::BinaryOpsEnd ||
3006 return std::nullopt;
3008 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
3012static std::optional<Instruction *>
3014 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
3015 "Expected MLA_U intrinsic");
3016 Value *Acc =
II.getArgOperand(1);
3017 Value *MulOp0 =
II.getArgOperand(2);
3018 Value *MulOp1 =
II.getArgOperand(3);
3033 II.setArgOperand(2, MulOp1);
3034 II.setArgOperand(3, MulOp0);
3038 return std::nullopt;
3041static std::optional<Instruction *>
3043 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
3044 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
3045 "Expected SADALP or UADALP intrinsic");
3051 return std::nullopt;
3055 return std::nullopt;
3059 II.getIntrinsicID(), {II.getType()},
3060 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
3070 Intrinsic::aarch64_sve_mla>(
3074 Intrinsic::aarch64_sve_mad>(
3077 return std::nullopt;
3080static std::optional<Instruction *>
3084 Intrinsic::aarch64_sve_fmla>(IC,
II,
3089 Intrinsic::aarch64_sve_fmad>(IC,
II,
3094 Intrinsic::aarch64_sve_fmla>(IC,
II,
3097 return std::nullopt;
3100static std::optional<Instruction *>
3104 Intrinsic::aarch64_sve_fmla>(IC,
II,
3109 Intrinsic::aarch64_sve_fmad>(IC,
II,
3114 Intrinsic::aarch64_sve_fmla_u>(
3120static std::optional<Instruction *>
3124 Intrinsic::aarch64_sve_fmls>(IC,
II,
3129 Intrinsic::aarch64_sve_fnmsb>(
3134 Intrinsic::aarch64_sve_fmls>(IC,
II,
3137 return std::nullopt;
3140static std::optional<Instruction *>
3144 Intrinsic::aarch64_sve_fmls>(IC,
II,
3149 Intrinsic::aarch64_sve_fnmsb>(
3154 Intrinsic::aarch64_sve_fmls_u>(
3163 Intrinsic::aarch64_sve_mls>(
3166 return std::nullopt;
3171 Value *UnpackArg =
II.getArgOperand(0);
3173 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3174 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3187 return std::nullopt;
3191 auto *OpVal =
II.getOperand(0);
3192 auto *OpIndices =
II.getOperand(1);
3199 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3200 return std::nullopt;
3215 Type *RetTy =
II.getType();
3216 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3217 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3221 if ((
match(
II.getArgOperand(0),
3228 if (TyA ==
B->getType() &&
3233 TyA->getMinNumElements());
3239 return std::nullopt;
3247 if (
match(
II.getArgOperand(0),
3252 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3254 return std::nullopt;
3257static std::optional<Instruction *>
3259 Value *Mask =
II.getOperand(0);
3260 Value *BasePtr =
II.getOperand(1);
3261 Value *Index =
II.getOperand(2);
3272 BasePtr->getPointerAlignment(
II.getDataLayout());
3275 BasePtr, IndexBase);
3282 return std::nullopt;
3285static std::optional<Instruction *>
3287 Value *Val =
II.getOperand(0);
3288 Value *Mask =
II.getOperand(1);
3289 Value *BasePtr =
II.getOperand(2);
3290 Value *Index =
II.getOperand(3);
3300 BasePtr->getPointerAlignment(
II.getDataLayout());
3303 BasePtr, IndexBase);
3309 return std::nullopt;
3315 Value *Pred =
II.getOperand(0);
3316 Value *Vec =
II.getOperand(1);
3317 Value *DivVec =
II.getOperand(2);
3321 if (!SplatConstantInt)
3322 return std::nullopt;
3326 if (DivisorValue == -1)
3327 return std::nullopt;
3328 if (DivisorValue == 1)
3334 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3341 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3343 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3347 return std::nullopt;
3351 size_t VecSize = Vec.
size();
3356 size_t HalfVecSize = VecSize / 2;
3360 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3368 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3386 return std::nullopt;
3393 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3394 CurrentInsertElt = InsertElt->getOperand(0);
3400 return std::nullopt;
3404 for (
size_t I = 0;
I < Elts.
size();
I++) {
3405 if (Elts[
I] ==
nullptr)
3410 if (InsertEltChain ==
nullptr)
3411 return std::nullopt;
3417 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3418 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3419 IIScalableTy->getMinNumElements() /
3424 auto *WideShuffleMaskTy =
3435 auto NarrowBitcast =
3448 return std::nullopt;
3453 Value *Pred =
II.getOperand(0);
3454 Value *Vec =
II.getOperand(1);
3455 Value *Shift =
II.getOperand(2);
3458 Value *AbsPred, *MergedValue;
3464 return std::nullopt;
3472 return std::nullopt;
3477 return std::nullopt;
3480 {
II.getType()}, {Pred, Vec, Shift});
3487 Value *Vec =
II.getOperand(0);
3492 return std::nullopt;
3495static std::optional<Instruction *>
3497 unsigned LookaheadThreshold) {
3499 auto *NI =
II.getNextNode();
3501 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3503 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3504 auto *NIBB = NI->getParent();
3505 NI = NI->getNextNode();
3507 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3508 NI = &*SuccBB->getFirstNonPHIOrDbgOrLifetime();
3514 if (NextII &&
II.isIdenticalTo(NextII))
3517 return std::nullopt;
3525 {II.getType(), II.getOperand(0)->getType()},
3526 {II.getOperand(0), II.getOperand(1)}));
3533 if (PredPattern == AArch64SVEPredPattern::all ||
3534 PredPattern == AArch64SVEPredPattern::pow2)
3536 return std::nullopt;
3542 Value *Passthru =
II.getOperand(0);
3550 auto *Mask = ConstantInt::get(Ty, MaskValue);
3556 return std::nullopt;
3559static std::optional<Instruction *>
3566 return std::nullopt;
3572 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3582 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3592 return std::nullopt;
3598 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3606 return std::nullopt;
3609 II.getType(), {Pg, A, B});
3611 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3620 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3625 Value *
A, *PgLHS, *PgRHS;
3631 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3632 return std::nullopt;
3635 if (ConstB > ConstA)
3641 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3642 return std::nullopt;
3644 Type *VecTy =
A->getType();
3648 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3655std::optional<Instruction *>
3666 case Intrinsic::aarch64_dmb:
3668 case Intrinsic::aarch64_neon_fmaxnm:
3669 case Intrinsic::aarch64_neon_fminnm:
3671 case Intrinsic::aarch64_sve_convert_from_svbool:
3673 case Intrinsic::aarch64_sve_dup:
3675 case Intrinsic::aarch64_sve_dup_x:
3677 case Intrinsic::aarch64_sve_cmpeq:
3678 case Intrinsic::aarch64_sve_cmpeq_wide:
3680 case Intrinsic::aarch64_sve_cmpne:
3681 case Intrinsic::aarch64_sve_cmpne_wide:
3683 case Intrinsic::aarch64_sve_rdffr:
3685 case Intrinsic::aarch64_sve_lasta:
3686 case Intrinsic::aarch64_sve_lastb:
3688 case Intrinsic::aarch64_sve_clasta_n:
3689 case Intrinsic::aarch64_sve_clastb_n:
3691 case Intrinsic::aarch64_sve_cntd:
3693 case Intrinsic::aarch64_sve_cntw:
3695 case Intrinsic::aarch64_sve_cnth:
3697 case Intrinsic::aarch64_sve_cntb:
3699 case Intrinsic::aarch64_sme_cntsd:
3701 case Intrinsic::aarch64_sve_ptest_any:
3702 case Intrinsic::aarch64_sve_ptest_first:
3703 case Intrinsic::aarch64_sve_ptest_last:
3705 case Intrinsic::aarch64_sve_fadd:
3707 case Intrinsic::aarch64_sve_fadd_u:
3709 case Intrinsic::aarch64_sve_fmul_u:
3711 case Intrinsic::aarch64_sve_fsub:
3713 case Intrinsic::aarch64_sve_fsub_u:
3715 case Intrinsic::aarch64_sve_add:
3717 case Intrinsic::aarch64_sve_add_u:
3719 Intrinsic::aarch64_sve_mla_u>(
3721 case Intrinsic::aarch64_sve_mla_u:
3723 case Intrinsic::aarch64_sve_sadalp:
3724 case Intrinsic::aarch64_sve_uadalp:
3726 case Intrinsic::aarch64_sve_sub:
3728 case Intrinsic::aarch64_sve_sub_u:
3730 Intrinsic::aarch64_sve_mls_u>(
3732 case Intrinsic::aarch64_sve_tbl:
3734 case Intrinsic::aarch64_sve_uunpkhi:
3735 case Intrinsic::aarch64_sve_uunpklo:
3736 case Intrinsic::aarch64_sve_sunpkhi:
3737 case Intrinsic::aarch64_sve_sunpklo:
3739 case Intrinsic::aarch64_sve_uzp1:
3741 case Intrinsic::aarch64_sve_zip1:
3742 case Intrinsic::aarch64_sve_zip2:
3744 case Intrinsic::aarch64_sve_ld1_gather_index:
3746 case Intrinsic::aarch64_sve_st1_scatter_index:
3748 case Intrinsic::aarch64_sve_ld1:
3750 case Intrinsic::aarch64_sve_st1:
3752 case Intrinsic::aarch64_sve_sdiv:
3754 case Intrinsic::aarch64_sve_sel:
3756 case Intrinsic::aarch64_sve_srshl:
3758 case Intrinsic::aarch64_sve_dupq_lane:
3760 case Intrinsic::aarch64_sve_insr:
3762 case Intrinsic::aarch64_sve_whilelo:
3764 case Intrinsic::aarch64_sve_ptrue:
3766 case Intrinsic::aarch64_sve_uxtb:
3768 case Intrinsic::aarch64_sve_uxth:
3770 case Intrinsic::aarch64_sve_uxtw:
3772 case Intrinsic::aarch64_sme_in_streaming_mode:
3774 case Intrinsic::aarch64_sve_umin_u:
3776 case Intrinsic::aarch64_sve_orr_u:
3778 case Intrinsic::aarch64_sve_and_z:
3782 return std::nullopt;
3789 SimplifyAndSetOp)
const {
3790 switch (
II.getIntrinsicID()) {
3793 case Intrinsic::aarch64_neon_fcvtxn:
3794 case Intrinsic::aarch64_neon_rshrn:
3795 case Intrinsic::aarch64_neon_sqrshrn:
3796 case Intrinsic::aarch64_neon_sqrshrun:
3797 case Intrinsic::aarch64_neon_sqshrn:
3798 case Intrinsic::aarch64_neon_sqshrun:
3799 case Intrinsic::aarch64_neon_sqxtn:
3800 case Intrinsic::aarch64_neon_sqxtun:
3801 case Intrinsic::aarch64_neon_uqrshrn:
3802 case Intrinsic::aarch64_neon_uqshrn:
3803 case Intrinsic::aarch64_neon_uqxtn:
3804 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3808 return std::nullopt;
3812 return ST->isSVEAvailable() ||
3813 (ST->isSVEorStreamingSVEAvailable() &&
3814 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3823 if (ST->useSVEForFixedLengthVectors() &&
3824 (ST->isSVEAvailable() ||
3825 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3827 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3828 else if (ST->isNeonAvailable())
3833 if (ST->isSVEAvailable() ||
3834 (ST->isSVEorStreamingSVEAvailable() &&
3835 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3843bool AArch64TTIImpl::isSingleExtWideningInstruction(
3845 Type *SrcOverrideTy)
const {
3860 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3863 Type *SrcTy = SrcOverrideTy;
3865 case Instruction::Add:
3866 case Instruction::Sub: {
3875 if (Opcode == Instruction::Sub)
3899 assert(SrcTy &&
"Expected some SrcTy");
3901 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3907 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3909 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3913 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3916Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3918 Type *SrcOverrideTy)
const {
3919 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3920 Opcode != Instruction::Mul)
3930 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3933 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3939 ->getScalarSizeInBits();
3942 unsigned MaxEltSize = 0;
3945 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3946 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3947 MaxEltSize = std::max(EltSize0, EltSize1);
3950 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3951 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3954 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3956 MaxEltSize = DstEltSize / 2;
3957 }
else if (Opcode == Instruction::Mul &&
3965 Known.Zero.countLeadingOnes() >
3970 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3974 if (MaxEltSize * 2 > DstEltSize)
3992 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
3993 (Src->isScalableTy() && !ST->hasSVE2()))
4003 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4007 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4011 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4012 Src->getScalarSizeInBits() !=
4036 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4050 if (
I && !
I->users().empty()) {
4054 auto GetUserAbsorbedCastCost =
4055 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4058 if (
Type *ExtTy = isBinExtWideningInstruction(
4060 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4073 if (isSingleExtWideningInstruction(
4075 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4079 if (Usr->getOpcode() == Instruction::Add) {
4080 if (
I == Usr->getOperand(1) ||
4096 return std::nullopt;
4100 bool AllUsersAbsorbCast =
true;
4101 for (
const User *U :
I->users()) {
4103 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4105 AllUsersAbsorbCast =
false;
4108 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4111 if (AllUsersAbsorbCast)
4112 return MaxAbsorbedCost;
4115 EVT SrcTy = TLI->getValueType(
DL, Src);
4116 EVT DstTy = TLI->getValueType(
DL, Dst);
4120 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4130 Instruction::ExtractElement, Src,
CostKind, -1,
nullptr,
nullptr);
4132 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH,
CostKind);
4136 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4141 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4170 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4173 ST->useSVEForFixedLengthVectors(WiderTy)) {
4174 std::pair<InstructionCost, MVT> LT =
4176 unsigned NumElements =
4192 const unsigned int SVE_EXT_COST = 1;
4193 const unsigned int SVE_FCVT_COST = 1;
4194 const unsigned int SVE_UNPACK_ONCE = 4;
4195 const unsigned int SVE_UNPACK_TWICE = 16;
4324 SVE_EXT_COST + SVE_FCVT_COST},
4329 SVE_EXT_COST + SVE_FCVT_COST},
4336 SVE_EXT_COST + SVE_FCVT_COST},
4340 SVE_EXT_COST + SVE_FCVT_COST},
4346 SVE_EXT_COST + SVE_FCVT_COST},
4349 SVE_EXT_COST + SVE_FCVT_COST},
4354 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4356 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4366 SVE_EXT_COST + SVE_FCVT_COST},
4371 SVE_EXT_COST + SVE_FCVT_COST},
4384 SVE_EXT_COST + SVE_FCVT_COST},
4388 SVE_EXT_COST + SVE_FCVT_COST},
4400 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4402 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4404 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4406 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4410 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4412 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4428 SVE_EXT_COST + SVE_FCVT_COST},
4433 SVE_EXT_COST + SVE_FCVT_COST},
4444 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4446 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4448 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4450 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4452 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4454 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4458 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4460 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4462 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4464 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4689 if (ST->hasFullFP16())
4701 Src->getScalarType(), CCH,
CostKind) +
4709 ST->isSVEorStreamingSVEAvailable() &&
4710 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4712 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4721 Opcode, LegalTy, Src, CCH,
CostKind,
I);
4724 return Part1 + Part2;
4731 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4743 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4756 CostKind, Index,
nullptr,
nullptr);
4760 auto DstVT = TLI->getValueType(
DL, Dst);
4761 auto SrcVT = TLI->getValueType(
DL, Src);
4766 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4772 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4782 case Instruction::SExt:
4787 case Instruction::ZExt:
4788 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4801 return Opcode == Instruction::PHI ? 0 : 1;
4810 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4812 assert(Ty->isVectorTy() &&
"This must be a vector type");
4819 if (!LT.second.isVector())
4824 if (LT.second.isFixedLengthVector()) {
4825 unsigned Width = LT.second.getVectorNumElements();
4826 Index = Index % Width;
4833 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4845 if (Index * Ty->getScalarSizeInBits() < 128)
4847 if (Index * Ty->getScalarSizeInBits() < 512 &&
4848 Opcode == Instruction::ExtractElement)
4850 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4851 if (Opcode == Instruction::ExtractElement)
4853 if (Opcode == Instruction::InsertElement)
4862 if (VIC == TTI::VectorInstrContext::Load) {
4863 if (ST->hasFastLD1Single())
4867 : ST->getVectorInsertExtractBaseCost() + 1;
4875 : ST->getVectorInsertExtractBaseCost() + 1;
4899 auto ExtractCanFuseWithFmul = [&]() {
4906 auto IsAllowedScalarTy = [&](
const Type *
T) {
4907 return T->isFloatTy() ||
T->isDoubleTy() ||
4908 (
T->isHalfTy() && ST->hasFullFP16());
4912 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4915 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4916 !BO->getType()->isVectorTy();
4921 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4925 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
4934 DenseMap<User *, unsigned> UserToExtractIdx;
4935 for (
auto *U :
Scalar->users()) {
4936 if (!IsUserFMulScalarTy(U))
4940 UserToExtractIdx[
U];
4942 if (UserToExtractIdx.
empty())
4944 for (
auto &[S, U, L] : ScalarUserAndIdx) {
4945 for (
auto *U : S->users()) {
4946 if (UserToExtractIdx.
contains(U)) {
4948 auto *Op0 =
FMul->getOperand(0);
4949 auto *Op1 =
FMul->getOperand(1);
4950 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
4951 UserToExtractIdx[
U] =
L;
4957 for (
auto &[U, L] : UserToExtractIdx) {
4969 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
4970 if (!IsUserFMulScalarTy(U))
4975 const auto *BO = cast<BinaryOperator>(U);
4976 const auto *OtherEE = dyn_cast<ExtractElementInst>(
4977 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
4979 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
4982 return IsExtractLaneEquivalentToZero(
4983 cast<ConstantInt>(OtherEE->getIndexOperand())
4986 OtherEE->getType()->getScalarSizeInBits());
4994 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
4995 ExtractCanFuseWithFmul())
5000 :
ST->getVectorInsertExtractBaseCost();
5009 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5012 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr,
nullptr,
5018 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5020 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr, Scalar,
5021 ScalarUserAndIdx, VIC);
5028 return getVectorInstrCostHelper(
I.getOpcode(), Ty,
CostKind, Index, &
I,
5035 unsigned Index)
const {
5046 : ST->getVectorInsertExtractBaseCost() + 1;
5058 if (ST->hasFastLD1Single()) {
5059 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5060 (VIC == TTI::VectorInstrContext::Load && Insert))
5064 if (Ty->getElementType()->isFloatingPointTy())
5067 unsigned VecInstCost =
5069 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5076 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5077 return std::nullopt;
5078 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5079 return std::nullopt;
5081 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5082 return std::nullopt;
5089 Cost += InstCost(PromotedTy);
5104 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5118 Op2Info, Args, CtxI);
5125 Ty,
CostKind, Op1Info, Op2Info,
true,
5128 [&](
Type *PromotedTy) {
5132 return *PromotedCost;
5135 if (Ty->getScalarType()->isFP128Ty())
5143 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5163 ST->hasLimited64bitVectorMulBandwidth())
5166 if (Ty->getScalarSizeInBits() > 64) {
5171 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5174 if (LT.second == MVT::v2i64) {
5178 return LT.first * Mul64CostFactor;
5199 if (LT.second == MVT::nxv2i64)
5200 return LT.first * Mul64CostFactor;
5259 auto VT = TLI->getValueType(
DL, Ty);
5260 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5264 : (3 * AsrCost + AddCost);
5266 return MulCost + AsrCost + 2 * AddCost;
5268 }
else if (VT.isVector()) {
5278 if (Ty->isScalableTy() && ST->hasSVE())
5279 Cost += 2 * AsrCost;
5284 ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5288 }
else if (LT.second == MVT::v2i64) {
5289 return VT.getVectorNumElements() *
5296 if (Ty->isScalableTy() && ST->hasSVE())
5297 return MulCost + 2 * AddCost + 2 * AsrCost;
5298 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5303 LT.second.isFixedLengthVector()) {
5313 return ExtractCost + InsertCost +
5321 auto VT = TLI->getValueType(
DL, Ty);
5337 bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||
5338 LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||
5339 LT.second == MVT::nxv16i8;
5340 bool Is128bit = LT.second.is128BitVector();
5352 (HasMULH ? 0 : ShrCost) +
5353 AddCost * 2 + ShrCost;
5354 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5361 if (!VT.isVector() && VT.getSizeInBits() > 64)
5365 Opcode, Ty,
CostKind, Op1Info, Op2Info);
5367 if (TLI->isOperationLegalOrCustom(
ISD, LT.second) && ST->hasSVE()) {
5371 Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {
5381 if (
nullptr != Entry)
5389 FVTy && LT.second.isFixedLengthVector()) {
5390 unsigned NumElts = FVTy->getNumElements();
5391 unsigned RegElts = LT.second.getVectorNumElements();
5393 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5397 if (LT.second.getScalarType() == MVT::i8)
5399 else if (LT.second.getScalarType() == MVT::i16)
5411 Opcode, Ty->getScalarType(),
CostKind, Op1Info, Op2Info);
5412 return (4 + DivCost) * VTy->getNumElements();
5418 -1,
nullptr,
nullptr);
5445 LT.second.isFixedLengthVector())
5446 return 2 * LT.first + 1;
5455 if ((Ty->isFloatTy() || Ty->isDoubleTy() ||
5456 (Ty->isHalfTy() && ST->hasFullFP16())) &&
5465 if (!Ty->getScalarType()->isFP128Ty())
5472 if (!Ty->getScalarType()->isFP128Ty())
5473 return 2 * LT.first;
5480 if (!Ty->isVectorTy())
5495 unsigned NumVectorInstToHideOverhead =
5496 ST->getCLOpts().neon_nonconst_stride_overhead;
5497 int MaxMergeDistance = 64;
5501 return NumVectorInstToHideOverhead;
5511 unsigned Opcode1,
unsigned Opcode2)
const {
5514 if (!
Sched.hasInstrSchedModel())
5518 Sched.getSchedClassDesc(
TII->get(Opcode1).getSchedClass());
5520 Sched.getSchedClassDesc(
TII->get(Opcode2).getSchedClass());
5526 "Cannot handle variant scheduling classes without an MI");
5542 const int AmortizationCost = 20;
5550 VecPred = CurrentPred;
5558 static const auto ValidMinMaxTys = {
5559 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5560 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5561 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5565 (ST->hasFullFP16() &&
5571 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5572 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5573 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5574 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5575 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5576 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5577 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5578 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5579 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5580 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5581 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5583 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5584 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5593 if (Opcode == Instruction::FCmp) {
5595 ValTy,
CostKind, Op1Info, Op2Info,
false,
5597 false, [&](
Type *PromotedTy) {
5609 return *PromotedCost;
5613 if (LT.second.getScalarType() != MVT::f64 &&
5614 LT.second.getScalarType() != MVT::f32 &&
5615 LT.second.getScalarType() != MVT::f16)
5620 unsigned Factor = 1;
5621 if (!CondTy->isVectorTy() &&
5635 AArch64::FCMEQv4f32))
5647 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5666 Op1Info, Op2Info,
I);
5672 if (ST->requiresStrictAlign()) {
5677 Options.AllowOverlappingLoads =
true;
5678 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5683 Options.LoadSizes = {8, 4, 2, 1};
5684 Options.AllowedTailExpansions = {3, 5, 6};
5689 return ST->hasSVE();
5695 switch (MICA.
getID()) {
5696 case Intrinsic::masked_scatter:
5697 case Intrinsic::masked_gather:
5699 case Intrinsic::masked_load:
5700 case Intrinsic::masked_store:
5701 case Intrinsic::masked_expandload:
5702 case Intrinsic::masked_compressstore:
5716 if (!LT.first.isValid())
5721 if (VT->getElementType()->isIntegerTy(1))
5727 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5733 if (MICA.
getID() == Intrinsic::masked_expandload) {
5746 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5766 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5767 return MemOpCost * 2;
5776 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5777 "Should be called on only load or stores.");
5779 case Instruction::Load:
5780 return ST->getCLOpts().sve_gather_overhead.value_or(
5781 ST->getGatherOverhead());
5783 case Instruction::Store:
5784 return ST->getCLOpts().sve_scatter_overhead.value_or(
5785 ST->getScatterOverhead());
5796 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5797 MICA.
getID() == Intrinsic::vp_gather)
5799 : Instruction::Store;
5809 if (!LT.first.isValid())
5813 if (!LT.second.isVector() ||
5815 VT->getElementType()->isIntegerTy(1))
5825 ElementCount LegalVF = LT.second.getVectorElementCount();
5828 {TTI::OK_AnyValue, TTI::OP_None},
I);
5844 EVT VT = TLI->getValueType(
DL, Ty,
true);
5846 if (VT == MVT::Other)
5851 if (!LT.first.isValid())
5857 if (VTy->getElementType()->isIntegerTy(1) &&
5858 !VTy->getElementCount().isKnownMultipleOf(
5864 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5865 : Intrinsic::masked_store;
5879 if (Opcode == Instruction::Store)
5883 if (ST->getFixedLoadLatency())
5884 return (LT.first - 1) + ST->getFixedLoadLatency();
5893 if (LT.second.isScalableVector() ||
5894 ST->useSVEForFixedLengthVectors(LT.second)) {
5895 Inst = AArch64::LDR_ZXI;
5896 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5897 switch (LT.second.getSizeInBits()) {
5899 Inst = AArch64::LDRBui;
5902 Inst = AArch64::LDRHui;
5905 Inst = AArch64::LDRSui;
5908 Inst = AArch64::LDRDui;
5911 Inst = AArch64::LDRQui;
5917 switch (LT.second.getSizeInBits()) {
5919 Inst = AArch64::LDRBBui;
5922 Inst = AArch64::LDRHHui;
5925 Inst = AArch64::LDRWui;
5928 Inst = AArch64::LDRXui;
5936 unsigned SchedClass =
TII->get(Inst).getSchedClass();
5938 ?
Sched.getSchedClassDesc(SchedClass)
5944 return (LT.first - 1) + ST->getLoadLatency();
5947 float NumLoads = (LT.first - 1).
getValue();
5948 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
5949 Sched.computeInstrLatency(*ST, *SCD);
5952 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
5953 LT.second.is128BitVector() && Alignment <
Align(16)) {
5959 const int AmortizationCost = 6;
5961 return LT.first * 2 * AmortizationCost;
5965 if (Ty->isPtrOrPtrVectorTy())
5970 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
5972 if (VT == MVT::v4i8)
5979 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
5980 Alignment !=
Align(1))
5992 if (Remainder != 0) {
5995 while (!TypeWorklist.
empty()) {
6005 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6017 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6018 assert(Factor >= 2 &&
"Invalid interleave factor");
6027 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6031 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6036 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6041 (UseMaskForCond || UseMaskForGaps ||
6042 (Factor > MaxNativeInterleaveFactor &&
6043 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6046 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6049 EC.divideCoefficientBy(Factor));
6055 if (EC.isKnownMultipleOf(Factor) &&
6056 TLI->isLegalInterleavedAccessType(SubVecTy,
DL, UseScalable))
6057 return Factor * TLI->getNumInterleavedAccesses(SubVecTy,
DL, UseScalable);
6062 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6068 if (UseMaskForCond) {
6069 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6070 : Intrinsic::masked_store;
6090 if (Opcode == Instruction::Store && Factor == 4 &&
6091 SubVecCost.second.getScalarSizeInBits() ==
6092 (4 * ResultCost.second.getScalarSizeInBits()))
6093 LegalizationCost *= 4;
6095 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6101 UseMaskForCond, UseMaskForGaps);
6108 for (
auto *
I : Tys) {
6109 if (!
I->isVectorTy())
6120 Align Alignment)
const {
6127 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6128 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6140 Size.getFixedValue() <= 16;
6145 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6146 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6165 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6172 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6178 bool HasUnorderedReductions)
const {
6181 return ST->getMaxInterleaveFactor();
6191 enum { MaxStridedLoads = 7 };
6193 int StridedLoads = 0;
6196 for (
const auto BB : L->blocks()) {
6197 for (
auto &
I : *BB) {
6203 if (L->isLoopInvariant(PtrValue))
6208 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6217 if (StridedLoads > MaxStridedLoads / 2)
6218 return StridedLoads;
6221 return StridedLoads;
6224 int StridedLoads = countStridedLoads(L, SE);
6226 <<
" strided loads\n");
6242 unsigned *FinalSize) {
6246 for (
auto *BB : L->getBlocks()) {
6247 for (
auto &
I : *BB) {
6253 if (!Cost.isValid())
6257 if (LoopCost > Budget)
6279 if (MaxTC > 0 && MaxTC <= 32)
6290 if (Blocks.
size() != 2)
6312 if (!L->isInnermost() || L->getNumBlocks() > 8)
6316 if (!L->getExitBlock())
6322 bool HasParellelizableReductions =
6323 L->getNumBlocks() == 1 &&
6324 any_of(L->getHeader()->phis(),
6326 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6329 if (HasParellelizableReductions &&
6351 if (HasParellelizableReductions) {
6362 if (Header == Latch) {
6365 unsigned Width = 10;
6371 unsigned MaxInstsPerLine = 16;
6373 unsigned BestUC = 1;
6374 unsigned SizeWithBestUC = BestUC *
Size;
6376 unsigned SizeWithUC = UC *
Size;
6377 if (SizeWithUC > 48)
6379 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6380 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6382 SizeWithBestUC = BestUC *
Size;
6392 for (
auto *BB : L->blocks()) {
6393 for (
auto &
I : *BB) {
6403 for (
auto *U :
I.users())
6405 LoadedValuesPlus.
insert(U);
6412 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6438 auto *I = dyn_cast<Instruction>(V);
6439 return I && DependsOnLoopLoad(I, Depth + 1);
6446 DependsOnLoopLoad(
I, 0)) {
6478 if (L->getLoopDepth() > 1)
6489 for (
auto *BB : L->getBlocks()) {
6490 for (
auto &
I : *BB) {
6494 if (IsVectorized &&
I.getType()->isVectorTy())
6505 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6514 if (ST->isAppleMLike())
6516 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6517 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6538 !ST->getSchedModel().isOutOfOrder()) {
6550 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6561 bool CanCreate)
const {
6565 case Intrinsic::aarch64_neon_st1x2:
6566 case Intrinsic::aarch64_neon_st1x3:
6567 case Intrinsic::aarch64_neon_st1x4:
6568 case Intrinsic::aarch64_neon_st2:
6569 case Intrinsic::aarch64_neon_st3:
6570 case Intrinsic::aarch64_neon_st4: {
6573 if (!CanCreate || !ST)
6575 unsigned NumElts = Inst->
arg_size() - 1;
6576 if (ST->getNumElements() != NumElts)
6578 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6584 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6586 Res = Builder.CreateInsertValue(Res, L, i);
6590 case Intrinsic::aarch64_neon_ld1x2:
6591 case Intrinsic::aarch64_neon_ld1x3:
6592 case Intrinsic::aarch64_neon_ld1x4:
6593 case Intrinsic::aarch64_neon_ld2:
6594 case Intrinsic::aarch64_neon_ld3:
6595 case Intrinsic::aarch64_neon_ld4:
6596 if (Inst->
getType() == ExpectedType)
6607 case Intrinsic::aarch64_neon_ld1x2:
6608 case Intrinsic::aarch64_neon_ld1x3:
6609 case Intrinsic::aarch64_neon_ld1x4:
6610 case Intrinsic::aarch64_neon_ld2:
6611 case Intrinsic::aarch64_neon_ld3:
6612 case Intrinsic::aarch64_neon_ld4:
6613 Info.ReadMem =
true;
6614 Info.WriteMem =
false;
6617 case Intrinsic::aarch64_neon_st1x2:
6618 case Intrinsic::aarch64_neon_st1x3:
6619 case Intrinsic::aarch64_neon_st1x4:
6620 case Intrinsic::aarch64_neon_st2:
6621 case Intrinsic::aarch64_neon_st3:
6622 case Intrinsic::aarch64_neon_st4:
6623 Info.ReadMem =
false;
6624 Info.WriteMem =
true;
6633 case Intrinsic::aarch64_neon_ld1x2:
6634 case Intrinsic::aarch64_neon_st1x2:
6635 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6637 case Intrinsic::aarch64_neon_ld1x3:
6638 case Intrinsic::aarch64_neon_st1x3:
6639 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6641 case Intrinsic::aarch64_neon_ld1x4:
6642 case Intrinsic::aarch64_neon_st1x4:
6643 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6645 case Intrinsic::aarch64_neon_ld2:
6646 case Intrinsic::aarch64_neon_st2:
6647 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6649 case Intrinsic::aarch64_neon_ld3:
6650 case Intrinsic::aarch64_neon_st3:
6651 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6653 case Intrinsic::aarch64_neon_ld4:
6654 case Intrinsic::aarch64_neon_st4:
6655 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6667 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6668 bool Considerable =
false;
6669 AllowPromotionWithoutCommonHeader =
false;
6672 Type *ConsideredSExtType =
6674 if (
I.getType() != ConsideredSExtType)
6678 for (
const User *U :
I.users()) {
6680 Considerable =
true;
6684 if (GEPInst->getNumOperands() > 2) {
6685 AllowPromotionWithoutCommonHeader =
true;
6690 return Considerable;
6741 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6751 return LegalizationCost + 2;
6761 LegalizationCost *= LT.first - 1;
6764 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6773 return LegalizationCost + 2;
6781 std::optional<FastMathFlags> FMF,
6797 return BaseCost + FixedVTy->getNumElements();
6811 MVT MTy = LT.second;
6816 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6864 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6865 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6877 return (LT.first - 1) +
Log2_32(NElts);
6882 return (LT.first - 1) + Entry->Cost;
6894 if (LT.first != 1) {
6900 ExtraCost *= LT.first - 1;
6903 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
6904 return Cost + ExtraCost;
6912 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
6914 EVT VecVT = TLI->getValueType(
DL, VecTy);
6915 EVT ResVT = TLI->getValueType(
DL, ResTy);
6925 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6927 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
6929 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
6931 return (LT.first - 1) * 2 + 2;
6942 EVT VecVT = TLI->getValueType(
DL, VecTy);
6943 EVT ResVT = TLI->getValueType(
DL, ResTy);
6946 RedOpcode == Instruction::Add) {
6952 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6954 return LT.first + 2;
6989 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
6990 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7004 if (LT.second.getScalarType() == MVT::i1) {
7013 assert(Entry &&
"Illegal Type for Splice");
7014 LegalizationCost += Entry->Cost;
7015 return LegalizationCost * LT.first;
7019 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7028 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7029 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7035 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7036 if (!FMF->allowReassoc() || !FMF->allowContract())
7040 "FastMathFlags only apply to floating-point partial reductions");
7044 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7045 "Unexpected values for OpBExtend or InputTypeB");
7049 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7050 InputTypeA != InputTypeB))
7061 assert(!OpBExtend &&
"Extended second operand without extended first.");
7062 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7068 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7071 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7084 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7093 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7099 std::pair<InstructionCost, MVT> AccumLT =
7101 std::pair<InstructionCost, MVT> InputLT =
7105 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7106 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7107 (AccumLT.second.isFixedLengthVector() &&
7108 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7112 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7120 if (AccumLT.second.getScalarType() == MVT::i32 &&
7121 InputLT.second.getScalarType() == MVT::i8) {
7123 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7124 return Cost + INegCost;
7126 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7127 return Cost + INegCost;
7132 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7133 return Cost * 3 + INegCost;
7136 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7138 if (AccumLT.second.getScalarType() == MVT::i64 &&
7139 InputLT.second.getScalarType() == MVT::i16)
7140 return Cost + INegCost;
7143 if (AccumLT.second.getScalarType() == MVT::i32 &&
7144 InputLT.second.getScalarType() == MVT::i16 &&
7145 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7148 if (AccumLT.second.getScalarType() == MVT::i64 &&
7149 InputLT.second.getScalarType() == MVT::i8)
7155 return Cost + INegCost;
7158 if (AccumLT.second.getScalarType() == MVT::i16 &&
7159 InputLT.second.getScalarType() == MVT::i8 &&
7160 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7166 if (Opcode == Instruction::FAdd && !IsSub &&
7167 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7168 AccumLT.second.getScalarType() == MVT::f32 &&
7169 InputLT.second.getScalarType() == MVT::f16)
7173 if (Ratio == 2 && !IsUSDot) {
7174 MVT InVT = InputLT.second.getScalarType();
7178 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7180 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7183 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7187 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7188 InVT == MVT::bf16 && IsSub)
7198 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7199 return Cost * 2 + FNegCost;
7203 AccumType, VF, OpAExtend, OpBExtend,
7214 "Expected the Mask to match the return size if given");
7216 "Expected the same scalar types");
7222 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7223 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7224 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7232 return std::max<InstructionCost>(1, LT.first / 4);
7240 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7242 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7245 unsigned TpNumElts = Mask.size();
7246 unsigned LTNumElts = LT.second.getVectorNumElements();
7247 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7249 LT.second.getVectorElementCount());
7251 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7253 for (
unsigned N = 0;
N < NumVecs;
N++) {
7257 unsigned Source1 = -1U, Source2 = -1U;
7258 unsigned NumSources = 0;
7259 for (
unsigned E = 0; E < LTNumElts; E++) {
7260 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7269 unsigned Source = MaskElt / LTNumElts;
7270 if (NumSources == 0) {
7273 }
else if (NumSources == 1 && Source != Source1) {
7276 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7282 if (Source == Source1)
7284 else if (Source == Source2)
7285 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7294 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7305 NTp, NTp,
CostKind, NMask, 0,
nullptr, Args,
7308 Result.first->second = NCost;
7322 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7323 if (LT.second.getFixedSizeInBits() >= 128 &&
7325 LT.second.getVectorNumElements() / 2) {
7328 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7342 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7345 return M.value() < 0 || M.value() == (int)M.index();
7351 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7352 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7361 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7362 ST->isSVEorStreamingSVEAvailable() &&
7367 if (ST->isSVEorStreamingSVEAvailable() &&
7381 if (IsLoad && LT.second.isVector() &&
7383 LT.second.getVectorElementCount()))
7389 if (Mask.size() == 4 &&
7391 (SrcTy->getScalarSizeInBits() == 16 ||
7392 SrcTy->getScalarSizeInBits() == 32) &&
7393 all_of(Mask, [](
int E) {
return E < 8; }))
7399 if (LT.second.isFixedLengthVector() &&
7400 LT.second.getVectorNumElements() == Mask.size() &&
7406 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7407 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7408 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7409 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7410 LT.second.getVectorNumElements(), 16) ||
7411 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7412 LT.second.getVectorNumElements(), 32) ||
7413 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7414 LT.second.getVectorNumElements(), 64) ||
7417 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7546 return LT.first * Entry->Cost;
7555 LT.second.getSizeInBits() <= 128 && SubTp) {
7557 if (SubLT.second.isVector()) {
7558 int NumElts = LT.second.getVectorNumElements();
7559 int NumSubElts = SubLT.second.getVectorNumElements();
7560 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7566 if (IsExtractSubvector)
7587 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7598 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7599 ST->useFixedOverScalableIfEqualCost());
7603 return ST->getEpilogueVectorizationMinVF();
7638 unsigned NumInsns = 0;
7640 NumInsns += BB->size();
7644 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7650 int64_t Scale,
unsigned AddrSpace)
const {
7672 int64_t BaseOffset,
bool HasBaseReg,
7673 int64_t Scale,
unsigned AddrSpace,
7675 int64_t ScalableOffset)
const {
7683 EVT MemVT = TLI->getValueType(
DL, Ty);
7688 EVT LegalVT = TLI->getLegalTypeToTransformTo(Ctx, MemVT);
7693 "expected vector split");
7700 if (ScalableOffset && ScalableOffset % LegalNumBytes == 0)
7706 AddrSpace,
I, ScalableOffset);
7711 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7716 if (
I->getOpcode() == Instruction::Or &&
7720 if (
I->getOpcode() == Instruction::Add ||
7721 I->getOpcode() == Instruction::Sub)
7735 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7746 return all_equal(Shuf->getShuffleMask());
7753 bool AllowSplat =
false) {
7758 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7759 auto *FullTy = FullV->
getType();
7760 auto *HalfTy = HalfV->getType();
7762 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7765 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7768 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7772 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7786 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7787 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7801 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7802 (M2Start != 0 && M2Start != (NumElements / 2)))
7804 if (S1Op1 && S2Op1 && M1Start != M2Start)
7814 return Ext->getType()->getScalarSizeInBits() ==
7815 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7829 Value *VectorOperand =
nullptr;
7846 if (!
GEP ||
GEP->getNumOperands() != 2)
7850 Value *Offsets =
GEP->getOperand(1);
7853 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7859 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7860 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7861 Ops.push_back(&
GEP->getOperandUse(1));
7897 switch (
II->getIntrinsicID()) {
7898 case Intrinsic::aarch64_neon_smull:
7899 case Intrinsic::aarch64_neon_umull:
7902 Ops.push_back(&
II->getOperandUse(0));
7903 Ops.push_back(&
II->getOperandUse(1));
7908 case Intrinsic::fma:
7909 case Intrinsic::fmuladd:
7916 Ops.push_back(&
II->getOperandUse(0));
7918 Ops.push_back(&
II->getOperandUse(1));
7921 case Intrinsic::aarch64_neon_sqdmull:
7922 case Intrinsic::aarch64_neon_sqdmulh:
7923 case Intrinsic::aarch64_neon_sqrdmulh:
7926 Ops.push_back(&
II->getOperandUse(0));
7928 Ops.push_back(&
II->getOperandUse(1));
7929 return !
Ops.empty();
7930 case Intrinsic::aarch64_neon_fmlal:
7931 case Intrinsic::aarch64_neon_fmlal2:
7932 case Intrinsic::aarch64_neon_fmlsl:
7933 case Intrinsic::aarch64_neon_fmlsl2:
7936 Ops.push_back(&
II->getOperandUse(1));
7938 Ops.push_back(&
II->getOperandUse(2));
7939 return !
Ops.empty();
7940 case Intrinsic::aarch64_sve_ptest_first:
7941 case Intrinsic::aarch64_sve_ptest_last:
7943 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
7944 Ops.push_back(&
II->getOperandUse(0));
7945 return !
Ops.empty();
7946 case Intrinsic::aarch64_sme_write_horiz:
7947 case Intrinsic::aarch64_sme_write_vert:
7948 case Intrinsic::aarch64_sme_writeq_horiz:
7949 case Intrinsic::aarch64_sme_writeq_vert: {
7951 if (!Idx || Idx->getOpcode() != Instruction::Add)
7953 Ops.push_back(&
II->getOperandUse(1));
7956 case Intrinsic::aarch64_sme_read_horiz:
7957 case Intrinsic::aarch64_sme_read_vert:
7958 case Intrinsic::aarch64_sme_readq_horiz:
7959 case Intrinsic::aarch64_sme_readq_vert:
7960 case Intrinsic::aarch64_sme_ld1b_vert:
7961 case Intrinsic::aarch64_sme_ld1h_vert:
7962 case Intrinsic::aarch64_sme_ld1w_vert:
7963 case Intrinsic::aarch64_sme_ld1d_vert:
7964 case Intrinsic::aarch64_sme_ld1q_vert:
7965 case Intrinsic::aarch64_sme_st1b_vert:
7966 case Intrinsic::aarch64_sme_st1h_vert:
7967 case Intrinsic::aarch64_sme_st1w_vert:
7968 case Intrinsic::aarch64_sme_st1d_vert:
7969 case Intrinsic::aarch64_sme_st1q_vert:
7970 case Intrinsic::aarch64_sme_ld1b_horiz:
7971 case Intrinsic::aarch64_sme_ld1h_horiz:
7972 case Intrinsic::aarch64_sme_ld1w_horiz:
7973 case Intrinsic::aarch64_sme_ld1d_horiz:
7974 case Intrinsic::aarch64_sme_ld1q_horiz:
7975 case Intrinsic::aarch64_sme_st1b_horiz:
7976 case Intrinsic::aarch64_sme_st1h_horiz:
7977 case Intrinsic::aarch64_sme_st1w_horiz:
7978 case Intrinsic::aarch64_sme_st1d_horiz:
7979 case Intrinsic::aarch64_sme_st1q_horiz: {
7981 if (!Idx || Idx->getOpcode() != Instruction::Add)
7983 Ops.push_back(&
II->getOperandUse(3));
7986 case Intrinsic::aarch64_neon_pmull:
7989 Ops.push_back(&
II->getOperandUse(0));
7990 Ops.push_back(&
II->getOperandUse(1));
7992 case Intrinsic::aarch64_neon_pmull64:
7994 II->getArgOperand(1)))
7996 Ops.push_back(&
II->getArgOperandUse(0));
7997 Ops.push_back(&
II->getArgOperandUse(1));
7999 case Intrinsic::masked_gather:
8002 Ops.push_back(&
II->getArgOperandUse(0));
8004 case Intrinsic::masked_scatter:
8007 Ops.push_back(&
II->getArgOperandUse(1));
8014 auto ShouldSinkCondition = [](
Value *
Cond,
8019 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8023 Ops.push_back(&
II->getOperandUse(0));
8027 switch (
I->getOpcode()) {
8028 case Instruction::GetElementPtr:
8029 case Instruction::Add:
8030 case Instruction::Sub:
8032 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8034 Ops.push_back(&
I->getOperandUse(
Op));
8039 case Instruction::Select: {
8040 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8043 Ops.push_back(&
I->getOperandUse(0));
8046 case Instruction::UncondBr:
8048 case Instruction::CondBr: {
8052 Ops.push_back(&
I->getOperandUse(0));
8055 case Instruction::FMul:
8060 Ops.push_back(&
I->getOperandUse(0));
8062 Ops.push_back(&
I->getOperandUse(1));
8072 case Instruction::Xor:
8075 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8077 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8082 case Instruction::And:
8083 case Instruction::Or:
8086 if (
I->getOpcode() == Instruction::Or &&
8091 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8094 for (
auto &
Op :
I->operands()) {
8106 Ops.push_back(&Not);
8107 Ops.push_back(&InsertElt);
8117 if (!
I->getType()->isVectorTy())
8118 return !
Ops.empty();
8120 switch (
I->getOpcode()) {
8121 case Instruction::Sub:
8122 case Instruction::Add: {
8131 Ops.push_back(&Ext1->getOperandUse(0));
8132 Ops.push_back(&Ext2->getOperandUse(0));
8135 Ops.push_back(&
I->getOperandUse(0));
8136 Ops.push_back(&
I->getOperandUse(1));
8140 case Instruction::Or: {
8143 if (ST->hasNEON()) {
8157 if (
I->getParent() != MainAnd->
getParent() ||
8162 if (
I->getParent() != IA->getParent() ||
8163 I->getParent() != IB->getParent())
8168 Ops.push_back(&
I->getOperandUse(0));
8169 Ops.push_back(&
I->getOperandUse(1));
8178 case Instruction::Mul: {
8179 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8182 if (Ty->isScalableTy())
8186 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8189 int NumZExts = 0, NumSExts = 0;
8190 for (
auto &
Op :
I->operands()) {
8197 auto *ExtOp = Ext->getOperand(0);
8198 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8199 Ops.push_back(&Ext->getOperandUse(0));
8207 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8208 I->getType()->getScalarSizeInBits())
8245 if (!ElementConstant || !ElementConstant->
isZero())
8248 unsigned Opcode = OperandInstr->
getOpcode();
8249 if (Opcode == Instruction::SExt)
8251 else if (Opcode == Instruction::ZExt)
8256 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8266 Ops.push_back(&Insert->getOperandUse(1));
8272 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8276 if (!ShouldSinkSplatForIndexedVariant(
I))
8281 Ops.push_back(&
I->getOperandUse(0));
8283 Ops.push_back(&
I->getOperandUse(1));
8285 return !
Ops.empty();
8287 case Instruction::FMul: {
8289 if (
I->getType()->isScalableTy())
8290 return !
Ops.empty();
8294 return !
Ops.empty();
8298 Ops.push_back(&
I->getOperandUse(0));
8300 Ops.push_back(&
I->getOperandUse(1));
8301 return !
Ops.empty();
8310 Align Alignment)
const {
8311 if (!(ST->isSVEAvailable() ||
8312 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8316 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8323 if (!LT.first.isValid())
8328 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")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
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
const SmallVectorImpl< MachineOperand > & 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 isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src) const
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index) const override
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
bool preferFixedOverScalableIfEqualCost() const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind=TTI::TCK_RecipThroughput) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isElementTypeLegalForScalableVector(Type *Ty) const override
bool hasMultiVectorLoadStore(unsigned NumVectors, TTI::MaskSource Mask, VectorType *VectorTy, bool IsStore, std::optional< Instruction::CastOps > CastHint) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const override
bool preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
APInt getPriorityMask(const Function &F) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
bool shouldMaximizeVectorBandwidth(TargetTransformInfo::RegisterKind K) const override
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const override
bool useNeonVector(const Type *Ty) const
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
bool isLegalSpeculativeLoad(Type *DataType, unsigned AddressSpace) const override
bool isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
bool isElementTypeLegalForCompressStore(Type *Ty) const
InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, TTI::TargetCostKind CostKind) const override
unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, unsigned DefaultCallPenalty) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
The compiler must not inline when that may alter the behavior of the program.
unsigned getMaxNumElements(ElementCount VF) const
Try to return an estimate cost factor that can be used as a multiplier when scalarizing an operation ...
bool shouldTreatInstructionLikeSelect(const Instruction *I) const override
bool isMultiversionedFunction(const Function &F) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, ElementCount VF) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedGatherScatter(Type *DataType) const
InstructionCost getBranchMispredictPenalty() const override
bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const override
See if I should be considered for address type promotion.
APInt getFeatureMask(const Function &F) const override
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const override
bool enableScalableVectorization() const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Value * getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate=true) const override
bool hasKnownLowerThroughputFromSchedulingModel(unsigned Opcode1, unsigned Opcode2) const
Check whether Opcode1 has less throughput according to the scheduling model than Opcode2.
unsigned getEpilogueVectorizationMinVF() const override
InstructionCost getSpliceCost(VectorType *Tp, int Index, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
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
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 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 getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Opd2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=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:
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
user_iterator user_begin()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
bool hasGroups() const
Returns true if we have any interleave groups.
const SmallVectorImpl< Type * > & getArgTypes() const
Type * getReturnType() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() const
Intrinsic::ID getID() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
iterator_range< block_iterator > blocks() const
RecurrenceSet & getFixedOrderRecurrences()
Return the fixed-order recurrences found in the loop.
DominatorTree * getDominatorTree() const
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
bool isFixedLengthVector() const
MVT getVectorElementType() const
Information for memory intrinsic cost model.
Align getAlignment() const
Type * getDataType() const
Intrinsic::ID getID() const
const Instruction * getInst() const
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
Type * getRecurrenceType() const
Returns the type of the recurrence.
RecurKind getRecurrenceKind() const
This node represents a polynomial recurrence on the trip count of the specified loop.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
This class represents an analyzed expression in the program.
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasStreamingInterfaceOrBody() const
SMECallAttrs is a utility class to hold the SMEAttrs for a callsite.
bool requiresSMChange() const
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
static ScalableVectorType * getDoubleElementsVectorType(ScalableVectorType *VTy)
The main scalar evolution driver.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI unsigned getSmallConstantTripMultiple(const Loop *L, const SCEV *ExitCount)
Returns the largest constant divisor of the trip count as a normal unsigned value,...
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
LLVM_ABI bool isBackedgeTakenCountMaxOrZero(const Loop *L)
Return true if the backedge taken count is either the value returned by getConstantMaxBackedgeTakenCo...
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
const SCEV * getSymbolicMaxBackedgeTakenCount(const Loop *L)
When successful, this returns a SCEV that is greater than or equal to (i.e.
This instruction constructs a fixed permutation of two input vectors.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isExtractSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &Index)
Return true if this shuffle mask is an extract subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Class to represent struct types.
TargetInstrInfo - Interface to description of machine instruction set.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
std::pair< LegalizeTypeAction, EVT > LegalizeKind
LegalizeKind holds the legalization kind that needs to happen to EVT in order to type-legalize it.
const RTLIB::RuntimeLibcallsInfo & getRuntimeLibcallsInfo() const
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.
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.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_Undef()
Match an arbitrary undef constant.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
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)
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.
@ LLVM_MARK_AS_BITMASK_ENUM
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool isDUPFirstSegmentMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPFirstSegmentMask - matches a splat of the first 128b segment.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< const MDOperand * > findStringMetadataForLoop(const Loop *TheLoop, StringRef Name)
Find string metadata for loop.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
CostTblEntryT< uint16_t > CostTblEntry
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
Return the number of active elements for VL1 to VL256 predicate pattern, zero for all other patterns.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
constexpr bool valueOr(BoolOrDefault X, bool Default)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
unsigned getMatchingIROpode() const
bool inactiveLanesAreUnused() const
bool inactiveLanesAreNotDefined() const
bool hasMatchingUndefIntrinsic() const
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
bool hasGoverningPredicate() const
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
CmpInst::Predicate getCmpPredicate() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
bool inactiveLanesTakenFromOperand() const
static SVEIntrinsicInfo defaultUndefOp()
bool hasOperandWithNoActiveLanes() const
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
bool hasCmpPredicate() const
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() const
bool hasMatchingIROpode() const
SVEIntrinsicInfo & setCmpPredicate(CmpInst::Predicate Pred)
bool resultIsZeroInitialized() const
SVEIntrinsicInfo & setMatchingIROpcode(unsigned Opcode)
unsigned getOperandIdxInactiveLanesTakenFrom() const
static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex)
This struct is a compact representation of a valid (non-zero power of two) alignment.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isScalableVT() const
Return true if the type is a scalable type.
bool isFixedLengthVector() const
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Machine model for scheduling, bundling, and heuristics.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Information about a load/store intrinsic defined by the target.
InterleavedAccessInfo * IAI
LoopVectorizationLegality * LVL
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...