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:
200 case Intrinsic::masked_scatter:
201 case Intrinsic::masked_compressstore:
202 case Intrinsic::experimental_vector_histogram_add:
206 if (
I->getOperand(0)->getType()->isScalableTy())
214 if (
I->getType()->isScalableTy() ||
216 [](
const Value *V) { return V->getType()->isScalableTy(); }) ||
230 bool ConsiderZA,
bool ConsiderZT,
232 if (!ConsiderZA && !ConsiderZT && !ConsiderSM)
235 bool IsAlwaysInline =
F->hasFnAttribute(Attribute::AlwaysInline);
242 bool AssumeVScaleIsEquivalent =
243 F->getReturnType()->isScalableTy() ||
244 any_of(
F->getFunctionType()->params(),
245 [](
const Type *
T) { return T->isScalableTy(); });
253 if (CB->isInlineAsm())
256 if (
CallAttrs.callee().isSMEABIRoutine())
265 if (ConsiderSM &&
CallAttrs.callee().hasStreamingCompatibleInterface())
277 return isa<FixedVectorType>(V->getType());
283 (!AssumeVScaleIsEquivalent &&
295 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
296 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
297 FeatureStr.
split(Features,
",");
313 return F.hasFnAttribute(
"fmv-features");
365 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
366 CallAttrs.callee().hasStreamingInterfaceOrBody())
374 if (
CallAttrs.callee().hasStreamingBody()) {
379 bool ConsiderZA =
CallAttrs.requiresZASave();
380 bool ConsiderZT =
CallAttrs.requiresPreservingZT0() ||
381 CallAttrs.requiresPreservingAllZAState();
382 bool ConsiderSM =
CallAttrs.requiresSMChange();
387 if (ConsiderSM && (Caller->isStrictFP() || Callee->isStrictFP()))
412 auto FVTy = dyn_cast<FixedVectorType>(Ty);
414 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
423 unsigned DefaultCallPenalty)
const {
448 if (
F ==
Call.getCaller())
449 return ST->getCLOpts().call_penalty_sm_change * DefaultCallPenalty;
451 return ST->getCLOpts().inline_call_penalty_sm_change * DefaultCallPenalty;
454 return DefaultCallPenalty;
465 ST->isSVEorStreamingSVEAvailable() &&
466 !ST->disableMaximizeScalableBandwidth();
490 assert(Ty->isIntegerTy());
492 unsigned BitSize = Ty->getPrimitiveSizeInBits();
499 ImmVal =
Imm.sext((BitSize + 63) & ~0x3fU);
504 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
510 return std::max<InstructionCost>(1,
Cost);
517 assert(Ty->isIntegerTy());
519 unsigned BitSize = Ty->getPrimitiveSizeInBits();
525 unsigned ImmIdx = ~0U;
529 case Instruction::GetElementPtr:
534 case Instruction::Store:
537 case Instruction::Add:
538 case Instruction::Sub:
539 case Instruction::Mul:
540 case Instruction::UDiv:
541 case Instruction::SDiv:
542 case Instruction::URem:
543 case Instruction::SRem:
544 case Instruction::And:
545 case Instruction::Or:
546 case Instruction::Xor:
547 case Instruction::ICmp:
551 case Instruction::Shl:
552 case Instruction::LShr:
553 case Instruction::AShr:
557 case Instruction::Trunc:
558 case Instruction::ZExt:
559 case Instruction::SExt:
560 case Instruction::IntToPtr:
561 case Instruction::PtrToInt:
562 case Instruction::BitCast:
563 case Instruction::PHI:
564 case Instruction::Call:
565 case Instruction::Select:
566 case Instruction::Ret:
567 case Instruction::Load:
572 int NumConstants = (BitSize + 63) / 64;
585 assert(Ty->isIntegerTy());
587 unsigned BitSize = Ty->getPrimitiveSizeInBits();
596 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
602 case Intrinsic::sadd_with_overflow:
603 case Intrinsic::uadd_with_overflow:
604 case Intrinsic::ssub_with_overflow:
605 case Intrinsic::usub_with_overflow:
606 case Intrinsic::smul_with_overflow:
607 case Intrinsic::umul_with_overflow:
609 int NumConstants = (BitSize + 63) / 64;
616 case Intrinsic::experimental_stackmap:
617 if ((Idx < 2) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
620 case Intrinsic::experimental_patchpoint_void:
621 case Intrinsic::experimental_patchpoint:
622 if ((Idx < 4) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
625 case Intrinsic::experimental_gc_statepoint:
626 if ((Idx < 5) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
636 if (TyWidth == 32 || TyWidth == 64)
645 return ST->getMispredictionPenalty();
666 unsigned TotalHistCnts = 1;
676 unsigned EC = VTy->getElementCount().getKnownMinValue();
681 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
683 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
687 TotalHistCnts = EC / NaturalVectorWidth;
689 return InstructionCost(ST->getCLOpts().base_histcnt_cost * TotalHistCnts);
706 !
is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
710 switch (ICA.
getID()) {
711 case Intrinsic::experimental_vector_histogram_add: {
718 case Intrinsic::experimental_vector_histogram_uadd_sat:
719 case Intrinsic::experimental_vector_histogram_umax:
720 case Intrinsic::experimental_vector_histogram_umin:
723 case Intrinsic::clmul: {
728 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
732 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
737 -1,
nullptr,
nullptr) *
740 -1,
nullptr,
nullptr);
744 if (LT.second.SimpleTy == MVT::nxv2i64)
745 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
748 if (ST->hasSVE2() || ST->hasSME()) {
749 switch (LT.second.SimpleTy) {
764 if (LT.second.SimpleTy == MVT::nxv2i64)
768 switch (LT.second.SimpleTy) {
778 -1,
nullptr,
nullptr) *
781 -1,
nullptr,
nullptr));
790 return LT.first * 11;
792 return LT.first * 14;
799 case Intrinsic::smulh:
800 case Intrinsic::umulh: {
806 if (RetTy->getScalarSizeInBits() > 64)
820 return MulCost + ExtraCost;
825 return LT.first + ExtraCost;
841 return LT.first * Entry->Cost + ExtraCost;
845 case Intrinsic::umin:
846 case Intrinsic::umax:
847 case Intrinsic::smin:
848 case Intrinsic::smax: {
849 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
850 MVT::v8i16, MVT::v2i32, MVT::v4i32,
851 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
858 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
859 EVT VT = TLI->getValueType(
DL, RetTy,
true);
860 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
861 return LT.first * (IsSigned ? 5 : 3);
863 if (LT.second == MVT::v2i64)
869 case Intrinsic::scmp:
870 case Intrinsic::ucmp: {
872 {Intrinsic::scmp, MVT::i32, 3},
873 {Intrinsic::scmp, MVT::i64, 3},
874 {Intrinsic::scmp, MVT::v8i8, 3},
875 {Intrinsic::scmp, MVT::v16i8, 3},
876 {Intrinsic::scmp, MVT::v4i16, 3},
877 {Intrinsic::scmp, MVT::v8i16, 3},
878 {Intrinsic::scmp, MVT::v2i32, 3},
879 {Intrinsic::scmp, MVT::v4i32, 3},
880 {Intrinsic::scmp, MVT::v1i64, 3},
881 {Intrinsic::scmp, MVT::v2i64, 3},
887 return Entry->Cost * LT.first;
890 case Intrinsic::sadd_sat:
891 case Intrinsic::ssub_sat:
892 case Intrinsic::uadd_sat:
893 case Intrinsic::usub_sat: {
894 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
895 MVT::v8i16, MVT::v2i32, MVT::v4i32,
901 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
903 return LT.first * Instrs;
908 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
909 return LT.first * Instrs;
913 case Intrinsic::abs: {
914 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
915 MVT::v8i16, MVT::v2i32, MVT::v4i32,
916 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
917 MVT::nxv4i32, MVT::nxv2i64};
923 case Intrinsic::bswap: {
924 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
925 MVT::v4i32, MVT::v2i64};
928 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
933 case Intrinsic::fmuladd: {
938 (EltTy->
isHalfTy() && ST->hasFullFP16()))
942 case Intrinsic::stepvector: {
951 Cost += AddCost * (LT.first - 1);
955 case Intrinsic::vector_extract:
956 case Intrinsic::vector_insert: {
969 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
970 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
978 getTLI()->getTypeConversion(
C, SubVecVT);
980 getTLI()->getTypeConversion(
C, VecVT);
988 case Intrinsic::bitreverse: {
990 {Intrinsic::bitreverse, MVT::i32, 1},
991 {Intrinsic::bitreverse, MVT::i64, 1},
992 {Intrinsic::bitreverse, MVT::v8i8, 1},
993 {Intrinsic::bitreverse, MVT::v16i8, 1},
994 {Intrinsic::bitreverse, MVT::v4i16, 2},
995 {Intrinsic::bitreverse, MVT::v8i16, 2},
996 {Intrinsic::bitreverse, MVT::v2i32, 2},
997 {Intrinsic::bitreverse, MVT::v4i32, 2},
998 {Intrinsic::bitreverse, MVT::v1i64, 2},
999 {Intrinsic::bitreverse, MVT::v2i64, 2},
1007 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
1008 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
1009 return LegalisationCost.first * Entry->Cost + 1;
1011 return LegalisationCost.first * Entry->Cost;
1015 case Intrinsic::ctpop: {
1017 MVT MTy = LT.second;
1019 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
1022 return LT.first + ExtraCost;
1024 if (!ST->hasNEON()) {
1054 RetTy->getScalarSizeInBits()
1057 return LT.first * Entry->Cost + ExtraCost;
1061 case Intrinsic::sadd_with_overflow:
1062 case Intrinsic::uadd_with_overflow:
1063 case Intrinsic::ssub_with_overflow:
1064 case Intrinsic::usub_with_overflow:
1065 case Intrinsic::smul_with_overflow:
1066 case Intrinsic::umul_with_overflow: {
1068 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
1069 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
1070 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
1071 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
1072 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
1073 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
1074 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
1075 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
1076 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
1077 {Intrinsic::usub_with_overflow, MVT::i8, 3},
1078 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
1079 {Intrinsic::usub_with_overflow, MVT::i16, 3},
1080 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
1081 {Intrinsic::usub_with_overflow, MVT::i32, 1},
1082 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
1083 {Intrinsic::usub_with_overflow, MVT::i64, 1},
1084 {Intrinsic::smul_with_overflow, MVT::i8, 5},
1085 {Intrinsic::umul_with_overflow, MVT::i8, 4},
1086 {Intrinsic::smul_with_overflow, MVT::i16, 5},
1087 {Intrinsic::umul_with_overflow, MVT::i16, 4},
1088 {Intrinsic::smul_with_overflow, MVT::i32, 2},
1089 {Intrinsic::umul_with_overflow, MVT::i32, 2},
1090 {Intrinsic::smul_with_overflow, MVT::i64, 3},
1091 {Intrinsic::umul_with_overflow, MVT::i64, 3},
1093 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
1100 case Intrinsic::fptosi_sat:
1101 case Intrinsic::fptoui_sat: {
1104 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
1106 EVT MTy = TLI->getValueType(
DL, RetTy);
1109 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
1110 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
1111 LT.second == MVT::v2f64)) {
1113 (LT.second == MVT::f64 && MTy == MVT::i32) ||
1114 (LT.second == MVT::f32 && MTy == MVT::i64)))
1123 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
1130 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
1131 (LT.second == MVT::f16 && MTy == MVT::i64) ||
1132 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1146 if ((LT.second.getScalarType() == MVT::f32 ||
1147 LT.second.getScalarType() == MVT::f64 ||
1148 LT.second.getScalarType() == MVT::f16) &&
1151 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1152 if (LT.second.isVector())
1153 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1157 LegalTy, {LegalTy, LegalTy});
1161 LegalTy, {LegalTy, LegalTy});
1163 return LT.first *
Cost +
1164 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1170 RetTy = RetTy->getScalarType();
1171 if (LT.second.isVector()) {
1189 return LT.first *
Cost;
1191 case Intrinsic::fshl:
1192 case Intrinsic::fshr: {
1201 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1202 (RetTy->getPrimitiveSizeInBits() == 32 ||
1203 RetTy->getPrimitiveSizeInBits() == 64)) {
1216 {Intrinsic::fshl, MVT::v4i32, 2},
1217 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1218 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1219 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1225 return LegalisationCost.first * Entry->Cost;
1229 if (!RetTy->isIntegerTy())
1234 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1235 RetTy->getScalarSizeInBits() < 64) ||
1236 (RetTy->getScalarSizeInBits() % 64 != 0);
1237 unsigned ExtraCost = HigherCost ? 1 : 0;
1238 if (RetTy->getScalarSizeInBits() == 32 ||
1239 RetTy->getScalarSizeInBits() == 64)
1242 else if (HigherCost)
1246 return TyL.first + ExtraCost;
1248 case Intrinsic::get_active_lane_mask: {
1250 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1252 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1255 if (RetTy->isScalableTy()) {
1256 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1266 if (ST->hasSVE2p1() || ST->hasSME2()) {
1278 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1281 return Cost + (SplitCost * (
Cost - 1));
1296 case Intrinsic::experimental_vector_match: {
1297 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1303 unsigned SearchSize = NeedleTy->getNumElements();
1304 if (SearchSize <= 2)
1309 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1313 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1319 unsigned MatchesRequiredForNeedle =
1331 return Cost * LegalParts * MatchesRequiredForNeedle;
1333 case Intrinsic::cttz: {
1335 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1336 return LT.first * 2;
1337 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1338 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1339 return LT.first * 3;
1342 case Intrinsic::experimental_cttz_elts: {
1352 case Intrinsic::loop_dependence_raw_mask:
1353 case Intrinsic::loop_dependence_war_mask: {
1355 if (ST->hasSVE2() || ST->hasSME()) {
1356 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1357 unsigned EltSizeInBytes =
1367 case Intrinsic::experimental_vector_extract_last_active:
1368 if (ST->isSVEorStreamingSVEAvailable()) {
1374 case Intrinsic::pow: {
1377 EVT VT = getTLI()->getValueType(
DL, RetTy);
1378 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1380 getTLI()->getLibcallLoweringInfo().getVectorLibcallImplOrMasked(LC) !=
1396 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1397 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1407 return (Sqrt * 2) +
FMul;
1418 case Intrinsic::sqrt:
1419 case Intrinsic::fabs:
1420 case Intrinsic::ceil:
1421 case Intrinsic::floor:
1422 case Intrinsic::nearbyint:
1423 case Intrinsic::round:
1424 case Intrinsic::rint:
1425 case Intrinsic::roundeven:
1426 case Intrinsic::trunc:
1427 case Intrinsic::minnum:
1428 case Intrinsic::maxnum:
1429 case Intrinsic::minimum:
1430 case Intrinsic::maximum: {
1448 auto RequiredType =
II.getType();
1451 assert(PN &&
"Expected Phi Node!");
1454 if (!PN->hasOneUse())
1455 return std::nullopt;
1457 for (
Value *IncValPhi : PN->incoming_values()) {
1460 Reinterpret->getIntrinsicID() !=
1461 Intrinsic::aarch64_sve_convert_to_svbool ||
1462 RequiredType != Reinterpret->getArgOperand(0)->getType())
1463 return std::nullopt;
1471 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1473 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1546 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1551 return GoverningPredicateIdx;
1556 GoverningPredicateIdx = Index;
1578 return UndefIntrinsic;
1583 UndefIntrinsic = IID;
1610 return CmpPredicate;
1615 CmpPredicate = Pred;
1631 return ResultLanes == InactiveLanesTakenFromOperand;
1636 return OperandIdxForInactiveLanes;
1640 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1641 ResultLanes = InactiveLanesTakenFromOperand;
1642 OperandIdxForInactiveLanes = Index;
1647 return ResultLanes == InactiveLanesAreNotDefined;
1651 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1652 ResultLanes = InactiveLanesAreNotDefined;
1657 return ResultLanes == InactiveLanesAreUnused;
1661 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1662 ResultLanes = InactiveLanesAreUnused;
1672 ResultIsZeroInitialized =
true;
1683 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1688 return OperandIdxWithNoActiveLanes;
1693 OperandIdxWithNoActiveLanes = Index;
1698 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1701 unsigned IROpcode = 0;
1704 enum PredicationStyle {
1706 InactiveLanesTakenFromOperand,
1707 InactiveLanesAreNotDefined,
1708 InactiveLanesAreUnused
1711 bool ResultIsZeroInitialized =
false;
1712 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1713 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1721 return !isa<ScalableVectorType>(V->getType());
1729 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1730 case Intrinsic::aarch64_sve_fcvt_f16f32:
1731 case Intrinsic::aarch64_sve_fcvt_f16f64:
1732 case Intrinsic::aarch64_sve_fcvt_f32f16:
1733 case Intrinsic::aarch64_sve_fcvt_f32f64:
1734 case Intrinsic::aarch64_sve_fcvt_f64f16:
1735 case Intrinsic::aarch64_sve_fcvt_f64f32:
1736 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1737 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1738 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1739 case Intrinsic::aarch64_sve_fcvtzs:
1740 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1741 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1742 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1743 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1744 case Intrinsic::aarch64_sve_fcvtzu:
1745 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1746 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1747 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1748 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1749 case Intrinsic::aarch64_sve_revb:
1750 case Intrinsic::aarch64_sve_revh:
1751 case Intrinsic::aarch64_sve_revw:
1752 case Intrinsic::aarch64_sve_revd:
1753 case Intrinsic::aarch64_sve_scvtf:
1754 case Intrinsic::aarch64_sve_scvtf_f16i32:
1755 case Intrinsic::aarch64_sve_scvtf_f16i64:
1756 case Intrinsic::aarch64_sve_scvtf_f32i64:
1757 case Intrinsic::aarch64_sve_scvtf_f64i32:
1758 case Intrinsic::aarch64_sve_ucvtf:
1759 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1760 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1761 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1762 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1765 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1766 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1767 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1768 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1771 case Intrinsic::aarch64_sve_fabd:
1773 case Intrinsic::aarch64_sve_fadd:
1776 case Intrinsic::aarch64_sve_fdiv:
1779 case Intrinsic::aarch64_sve_fmax:
1781 case Intrinsic::aarch64_sve_fmaxnm:
1783 case Intrinsic::aarch64_sve_fmin:
1785 case Intrinsic::aarch64_sve_fminnm:
1787 case Intrinsic::aarch64_sve_fmla:
1789 case Intrinsic::aarch64_sve_fmls:
1791 case Intrinsic::aarch64_sve_fmul:
1794 case Intrinsic::aarch64_sve_fmulx:
1796 case Intrinsic::aarch64_sve_fnmla:
1798 case Intrinsic::aarch64_sve_fnmls:
1800 case Intrinsic::aarch64_sve_fsub:
1803 case Intrinsic::aarch64_sve_add:
1806 case Intrinsic::aarch64_sve_mla:
1808 case Intrinsic::aarch64_sve_mls:
1810 case Intrinsic::aarch64_sve_mul:
1813 case Intrinsic::aarch64_sve_sabd:
1815 case Intrinsic::aarch64_sve_sdiv:
1818 case Intrinsic::aarch64_sve_smax:
1820 case Intrinsic::aarch64_sve_smin:
1822 case Intrinsic::aarch64_sve_smulh:
1824 case Intrinsic::aarch64_sve_sub:
1827 case Intrinsic::aarch64_sve_uabd:
1829 case Intrinsic::aarch64_sve_udiv:
1832 case Intrinsic::aarch64_sve_umax:
1834 case Intrinsic::aarch64_sve_umin:
1836 case Intrinsic::aarch64_sve_umulh:
1838 case Intrinsic::aarch64_sve_asr:
1841 case Intrinsic::aarch64_sve_lsl:
1844 case Intrinsic::aarch64_sve_lsr:
1847 case Intrinsic::aarch64_sve_and:
1850 case Intrinsic::aarch64_sve_bic:
1852 case Intrinsic::aarch64_sve_eor:
1855 case Intrinsic::aarch64_sve_orr:
1858 case Intrinsic::aarch64_sve_shsub:
1860 case Intrinsic::aarch64_sve_shsubr:
1862 case Intrinsic::aarch64_sve_sqrshl:
1864 case Intrinsic::aarch64_sve_sqshl:
1866 case Intrinsic::aarch64_sve_sqsub:
1868 case Intrinsic::aarch64_sve_srshl:
1870 case Intrinsic::aarch64_sve_uhsub:
1872 case Intrinsic::aarch64_sve_uhsubr:
1874 case Intrinsic::aarch64_sve_uqrshl:
1876 case Intrinsic::aarch64_sve_uqshl:
1878 case Intrinsic::aarch64_sve_uqsub:
1880 case Intrinsic::aarch64_sve_urshl:
1883 case Intrinsic::aarch64_sve_add_u:
1886 case Intrinsic::aarch64_sve_and_u:
1889 case Intrinsic::aarch64_sve_asr_u:
1892 case Intrinsic::aarch64_sve_eor_u:
1895 case Intrinsic::aarch64_sve_fadd_u:
1898 case Intrinsic::aarch64_sve_fdiv_u:
1901 case Intrinsic::aarch64_sve_fmul_u:
1904 case Intrinsic::aarch64_sve_fsub_u:
1907 case Intrinsic::aarch64_sve_lsl_u:
1910 case Intrinsic::aarch64_sve_lsr_u:
1913 case Intrinsic::aarch64_sve_mul_u:
1916 case Intrinsic::aarch64_sve_orr_u:
1919 case Intrinsic::aarch64_sve_sdiv_u:
1922 case Intrinsic::aarch64_sve_sub_u:
1925 case Intrinsic::aarch64_sve_udiv_u:
1929 case Intrinsic::aarch64_sve_addqv:
1930 case Intrinsic::aarch64_sve_bic_z:
1931 case Intrinsic::aarch64_sve_brka_z:
1932 case Intrinsic::aarch64_sve_brkb_z:
1933 case Intrinsic::aarch64_sve_brkn_z:
1934 case Intrinsic::aarch64_sve_brkpa_z:
1935 case Intrinsic::aarch64_sve_brkpb_z:
1936 case Intrinsic::aarch64_sve_cntp:
1937 case Intrinsic::aarch64_sve_compact:
1938 case Intrinsic::aarch64_sve_eorv:
1939 case Intrinsic::aarch64_sve_eorqv:
1940 case Intrinsic::aarch64_sve_nand_z:
1941 case Intrinsic::aarch64_sve_nor_z:
1942 case Intrinsic::aarch64_sve_orn_z:
1943 case Intrinsic::aarch64_sve_orv:
1944 case Intrinsic::aarch64_sve_orqv:
1945 case Intrinsic::aarch64_sve_pnext:
1946 case Intrinsic::aarch64_sve_rdffr_z:
1947 case Intrinsic::aarch64_sve_saddv:
1948 case Intrinsic::aarch64_sve_uaddv:
1949 case Intrinsic::aarch64_sve_umaxv:
1950 case Intrinsic::aarch64_sve_umaxqv:
1951 case Intrinsic::aarch64_sve_facge:
1952 case Intrinsic::aarch64_sve_facgt:
1953 case Intrinsic::aarch64_sve_ld1:
1954 case Intrinsic::aarch64_sve_ld1_gather:
1955 case Intrinsic::aarch64_sve_ld1_gather_index:
1956 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1957 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1958 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1959 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1960 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1961 case Intrinsic::aarch64_sve_ld1q_gather_index:
1962 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1963 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1964 case Intrinsic::aarch64_sve_ld1ro:
1965 case Intrinsic::aarch64_sve_ld1rq:
1966 case Intrinsic::aarch64_sve_ld1udq:
1967 case Intrinsic::aarch64_sve_ld1uwq:
1968 case Intrinsic::aarch64_sve_ld2_sret:
1969 case Intrinsic::aarch64_sve_ld2q_sret:
1970 case Intrinsic::aarch64_sve_ld3_sret:
1971 case Intrinsic::aarch64_sve_ld3q_sret:
1972 case Intrinsic::aarch64_sve_ld4_sret:
1973 case Intrinsic::aarch64_sve_ld4q_sret:
1974 case Intrinsic::aarch64_sve_ldff1:
1975 case Intrinsic::aarch64_sve_ldff1_gather:
1976 case Intrinsic::aarch64_sve_ldff1_gather_index:
1977 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1978 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1979 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1980 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1981 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1982 case Intrinsic::aarch64_sve_ldnf1:
1983 case Intrinsic::aarch64_sve_ldnt1:
1984 case Intrinsic::aarch64_sve_ldnt1_gather:
1985 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1986 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1987 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1990 case Intrinsic::aarch64_sve_and_z:
1993 case Intrinsic::aarch64_sve_orr_z:
1996 case Intrinsic::aarch64_sve_eor_z:
2000 case Intrinsic::aarch64_sve_cmpeq:
2001 case Intrinsic::aarch64_sve_cmpeq_wide:
2004 case Intrinsic::aarch64_sve_cmpge:
2005 case Intrinsic::aarch64_sve_cmpge_wide:
2008 case Intrinsic::aarch64_sve_cmpgt:
2009 case Intrinsic::aarch64_sve_cmpgt_wide:
2012 case Intrinsic::aarch64_sve_cmphi:
2013 case Intrinsic::aarch64_sve_cmphi_wide:
2016 case Intrinsic::aarch64_sve_cmphs:
2017 case Intrinsic::aarch64_sve_cmphs_wide:
2020 case Intrinsic::aarch64_sve_cmple_wide:
2023 case Intrinsic::aarch64_sve_cmplo_wide:
2026 case Intrinsic::aarch64_sve_cmpls_wide:
2029 case Intrinsic::aarch64_sve_cmplt_wide:
2032 case Intrinsic::aarch64_sve_cmpne:
2033 case Intrinsic::aarch64_sve_cmpne_wide:
2036 case Intrinsic::aarch64_sve_fcmpeq:
2039 case Intrinsic::aarch64_sve_fcmpge:
2042 case Intrinsic::aarch64_sve_fcmpgt:
2045 case Intrinsic::aarch64_sve_fcmpne:
2048 case Intrinsic::aarch64_sve_fcmpuo:
2052 case Intrinsic::aarch64_sve_prf:
2053 case Intrinsic::aarch64_sve_prfb_gather_index:
2054 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
2055 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
2056 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
2057 case Intrinsic::aarch64_sve_prfd_gather_index:
2058 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
2059 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
2060 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
2061 case Intrinsic::aarch64_sve_prfh_gather_index:
2062 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
2063 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
2064 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
2065 case Intrinsic::aarch64_sve_prfw_gather_index:
2066 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
2067 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
2068 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
2071 case Intrinsic::aarch64_sve_st1_scatter:
2072 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
2073 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
2074 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
2075 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
2076 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
2077 case Intrinsic::aarch64_sve_st1dq:
2078 case Intrinsic::aarch64_sve_st1q_scatter_index:
2079 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
2080 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
2081 case Intrinsic::aarch64_sve_st1wq:
2082 case Intrinsic::aarch64_sve_stnt1:
2083 case Intrinsic::aarch64_sve_stnt1_scatter:
2084 case Intrinsic::aarch64_sve_stnt1_scatter_index:
2085 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
2086 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
2088 case Intrinsic::aarch64_sve_st2:
2089 case Intrinsic::aarch64_sve_st2q:
2091 case Intrinsic::aarch64_sve_st3:
2092 case Intrinsic::aarch64_sve_st3q:
2094 case Intrinsic::aarch64_sve_st4:
2095 case Intrinsic::aarch64_sve_st4q:
2103 Value *UncastedPred;
2109 Pred = UncastedPred;
2115 if (OrigPredTy->getMinNumElements() <=
2117 ->getMinNumElements())
2118 Pred = UncastedPred;
2122 return C &&
C->isAllOnesValue();
2129 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
2130 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2138static std::optional<Instruction *>
2145 Value *Op1 =
II.getOperand(1);
2146 Value *Op2 =
II.getOperand(2);
2171 Value *NarrowOp1, *NarrowOp2;
2182 else if (SimpleNarrow == NarrowOp1)
2184 else if (SimpleNarrow == NarrowOp2)
2189 SimpleNarrow->
getType(), SimpleNarrow);
2198 return std::nullopt;
2209 if (SimpleII == Inactive)
2217static std::optional<Instruction *>
2221 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2222 "Expected a compare operation!");
2229 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2230 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2231 "Unexpected wide compare!");
2247 const APInt *LHSVal, *RHSVal;
2249 return std::nullopt;
2272 return std::nullopt;
2286static std::optional<Instruction *>
2290 return std::nullopt;
2319 II.setCalledFunction(NewDecl);
2325 return std::nullopt;
2336 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2339 return std::nullopt;
2351static std::optional<Instruction *>
2353 auto m_ConvertToSVBool = [](
auto P) {
2357 Intrinsic::aarch64_sve_convert_from_svbool;
2380 return std::nullopt;
2384 case Intrinsic::aarch64_sve_and_z:
2385 case Intrinsic::aarch64_sve_bic_z:
2386 case Intrinsic::aarch64_sve_eor_z:
2387 case Intrinsic::aarch64_sve_nand_z:
2388 case Intrinsic::aarch64_sve_nor_z:
2389 case Intrinsic::aarch64_sve_orn_z:
2390 case Intrinsic::aarch64_sve_orr_z:
2393 return std::nullopt;
2396 Value *BinOpPred = BinOp->getOperand(0);
2397 Value *BinOpOp1 = BinOp->getOperand(1);
2398 Value *BinOpOp2 = BinOp->getOperand(2);
2400 Value *NarrowBinOpPred;
2402 return std::nullopt;
2404 Value *NarrowBinOpOp1 =
2406 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2407 if (BinOpOp1 != BinOpOp2)
2411 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2415static std::optional<Instruction *>
2422 return BinOpCombine;
2427 return std::nullopt;
2430 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2439 if (CursorVTy->getElementCount().getKnownMinValue() <
2440 IVTy->getElementCount().getKnownMinValue())
2444 if (Cursor->getType() == IVTy)
2445 EarliestReplacement = Cursor;
2450 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2451 Intrinsic::aarch64_sve_convert_to_svbool ||
2452 IntrinsicCursor->getIntrinsicID() ==
2453 Intrinsic::aarch64_sve_convert_from_svbool))
2456 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2457 Cursor = IntrinsicCursor->getOperand(0);
2462 if (!EarliestReplacement)
2463 return std::nullopt;
2471 auto *OpPredicate =
II.getOperand(0);
2488 II.getArgOperand(2));
2494 return std::nullopt;
2498 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2507 II.getArgOperand(0));
2516 if (!
II.hasOneUse())
2517 return std::nullopt;
2520 return std::nullopt;
2523 switch (
II.getIntrinsicID()) {
2524 case Intrinsic::aarch64_sve_cmpne:
2525 IID = Intrinsic::aarch64_sve_cmpeq;
2527 case Intrinsic::aarch64_sve_cmpne_wide:
2528 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2530 case Intrinsic::aarch64_sve_cmpeq:
2531 IID = Intrinsic::aarch64_sve_cmpne;
2533 case Intrinsic::aarch64_sve_cmpeq_wide:
2534 IID = Intrinsic::aarch64_sve_cmpne_wide;
2537 return std::nullopt;
2542 IID,
II.getOperand(1)->getType(),
2543 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2555 return std::nullopt;
2557 for (
auto *U :
II.users()) {
2560 Type *Ty =
II.getOperand(1)->getType();
2565 Intrinsic::aarch64_sve_umin, Ty,
2566 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2572 return std::nullopt;
2586 return std::nullopt;
2591 if (!SplatValue || !SplatValue->isZero())
2592 return std::nullopt;
2597 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2598 return std::nullopt;
2602 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2603 return std::nullopt;
2606 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2607 return std::nullopt;
2612 return std::nullopt;
2615 return std::nullopt;
2619 return std::nullopt;
2623 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2624 return std::nullopt;
2626 unsigned NumElts = VecTy->getNumElements();
2627 unsigned PredicateBits = 0;
2630 for (
unsigned I = 0;
I < NumElts; ++
I) {
2633 return std::nullopt;
2635 PredicateBits |= 1 << (
I * (16 / NumElts));
2639 if (PredicateBits == 0) {
2641 PFalse->takeName(&
II);
2647 for (
unsigned I = 0;
I < 16; ++
I)
2648 if ((PredicateBits & (1 <<
I)) != 0)
2651 unsigned PredSize = Mask & -Mask;
2656 for (
unsigned I = 0;
I < 16;
I += PredSize)
2657 if ((PredicateBits & (1 <<
I)) == 0)
2658 return std::nullopt;
2660 auto *ConvertToSVBool =
2663 auto *ConvertFromSVBool =
2665 II.getType(), ConvertToSVBool);
2673 Value *Pg =
II.getArgOperand(0);
2674 Value *Vec =
II.getArgOperand(1);
2675 auto IntrinsicID =
II.getIntrinsicID();
2676 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2688 auto OpC = OldBinOp->getOpcode();
2694 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2700 if (IsAfter &&
C &&
C->isNullValue()) {
2704 Extract->insertBefore(
II.getIterator());
2705 Extract->takeName(&
II);
2711 return std::nullopt;
2713 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2714 return std::nullopt;
2716 const auto PTruePattern =
2722 return std::nullopt;
2724 unsigned Idx = MinNumElts - 1;
2734 if (Idx >= PgVTy->getMinNumElements())
2735 return std::nullopt;
2740 Extract->insertBefore(
II.getIterator());
2741 Extract->takeName(&
II);
2754 Value *Pg =
II.getArgOperand(0);
2756 Value *Vec =
II.getArgOperand(2);
2759 if (!Ty->isIntegerTy())
2760 return std::nullopt;
2765 return std::nullopt;
2782 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2797static std::optional<Instruction *>
2801 if (
Pattern == AArch64SVEPredPattern::all) {
2810 return MinNumElts && NumElts >= MinNumElts
2812 II, ConstantInt::get(
II.getType(), MinNumElts)))
2816static std::optional<Instruction *>
2819 if (!ST->isStreaming())
2820 return std::nullopt;
2832 Value *PgVal =
II.getArgOperand(0);
2833 Value *OpVal =
II.getArgOperand(1);
2837 if (PgVal == OpVal &&
2838 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2839 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2854 return std::nullopt;
2858 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2859 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2873 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2874 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2875 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2876 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2877 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2878 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2879 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2880 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2881 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2882 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2883 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2884 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2885 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2895 return std::nullopt;
2898template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2899static std::optional<Instruction *>
2901 bool MergeIntoAddendOp) {
2903 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2904 if (MergeIntoAddendOp) {
2905 AddendOp =
II.getOperand(1);
2906 Mul =
II.getOperand(2);
2908 AddendOp =
II.getOperand(2);
2909 Mul =
II.getOperand(1);
2914 return std::nullopt;
2916 if (!
Mul->hasOneUse())
2917 return std::nullopt;
2920 if (
II.getType()->isFPOrFPVectorTy()) {
2925 return std::nullopt;
2927 return std::nullopt;
2932 if (MergeIntoAddendOp)
2942static std::optional<Instruction *>
2944 Value *Pred =
II.getOperand(0);
2945 Value *PtrOp =
II.getOperand(1);
2946 Type *VecTy =
II.getType();
2961static std::optional<Instruction *>
2963 Value *VecOp =
II.getOperand(0);
2964 Value *Pred =
II.getOperand(1);
2965 Value *PtrOp =
II.getOperand(2);
2981 case Intrinsic::aarch64_sve_fmul_u:
2982 return Instruction::BinaryOps::FMul;
2983 case Intrinsic::aarch64_sve_fadd_u:
2984 return Instruction::BinaryOps::FAdd;
2985 case Intrinsic::aarch64_sve_fsub_u:
2986 return Instruction::BinaryOps::FSub;
2988 return Instruction::BinaryOpsEnd;
2992static std::optional<Instruction *>
2995 if (
II.isStrictFP())
2996 return std::nullopt;
2998 auto *OpPredicate =
II.getOperand(0);
3000 if (BinOpCode == Instruction::BinaryOpsEnd ||
3002 return std::nullopt;
3004 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
3008static std::optional<Instruction *>
3010 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
3011 "Expected MLA_U intrinsic");
3012 Value *Acc =
II.getArgOperand(1);
3013 Value *MulOp0 =
II.getArgOperand(2);
3014 Value *MulOp1 =
II.getArgOperand(3);
3029 II.setArgOperand(2, MulOp1);
3030 II.setArgOperand(3, MulOp0);
3034 return std::nullopt;
3037static std::optional<Instruction *>
3039 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
3040 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
3041 "Expected SADALP or UADALP intrinsic");
3047 return std::nullopt;
3051 return std::nullopt;
3055 II.getIntrinsicID(), {II.getType()},
3056 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
3066 Intrinsic::aarch64_sve_mla>(
3070 Intrinsic::aarch64_sve_mad>(
3073 return std::nullopt;
3076static std::optional<Instruction *>
3080 Intrinsic::aarch64_sve_fmla>(IC,
II,
3085 Intrinsic::aarch64_sve_fmad>(IC,
II,
3090 Intrinsic::aarch64_sve_fmla>(IC,
II,
3093 return std::nullopt;
3096static std::optional<Instruction *>
3100 Intrinsic::aarch64_sve_fmla>(IC,
II,
3105 Intrinsic::aarch64_sve_fmad>(IC,
II,
3110 Intrinsic::aarch64_sve_fmla_u>(
3116static std::optional<Instruction *>
3120 Intrinsic::aarch64_sve_fmls>(IC,
II,
3125 Intrinsic::aarch64_sve_fnmsb>(
3130 Intrinsic::aarch64_sve_fmls>(IC,
II,
3133 return std::nullopt;
3136static std::optional<Instruction *>
3140 Intrinsic::aarch64_sve_fmls>(IC,
II,
3145 Intrinsic::aarch64_sve_fnmsb>(
3150 Intrinsic::aarch64_sve_fmls_u>(
3159 Intrinsic::aarch64_sve_mls>(
3162 return std::nullopt;
3167 Value *UnpackArg =
II.getArgOperand(0);
3169 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3170 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3183 return std::nullopt;
3187 auto *OpVal =
II.getOperand(0);
3188 auto *OpIndices =
II.getOperand(1);
3195 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3196 return std::nullopt;
3211 Type *RetTy =
II.getType();
3212 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3213 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3217 if ((
match(
II.getArgOperand(0),
3224 if (TyA ==
B->getType() &&
3229 TyA->getMinNumElements());
3235 return std::nullopt;
3243 if (
match(
II.getArgOperand(0),
3248 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3250 return std::nullopt;
3253static std::optional<Instruction *>
3255 Value *Mask =
II.getOperand(0);
3256 Value *BasePtr =
II.getOperand(1);
3257 Value *Index =
II.getOperand(2);
3268 BasePtr->getPointerAlignment(
II.getDataLayout());
3271 BasePtr, IndexBase);
3278 return std::nullopt;
3281static std::optional<Instruction *>
3283 Value *Val =
II.getOperand(0);
3284 Value *Mask =
II.getOperand(1);
3285 Value *BasePtr =
II.getOperand(2);
3286 Value *Index =
II.getOperand(3);
3296 BasePtr->getPointerAlignment(
II.getDataLayout());
3299 BasePtr, IndexBase);
3305 return std::nullopt;
3311 Value *Pred =
II.getOperand(0);
3312 Value *Vec =
II.getOperand(1);
3313 Value *DivVec =
II.getOperand(2);
3317 if (!SplatConstantInt)
3318 return std::nullopt;
3322 if (DivisorValue == -1)
3323 return std::nullopt;
3324 if (DivisorValue == 1)
3330 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3337 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3339 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3343 return std::nullopt;
3347 size_t VecSize = Vec.
size();
3352 size_t HalfVecSize = VecSize / 2;
3356 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3364 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3382 return std::nullopt;
3389 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3390 CurrentInsertElt = InsertElt->getOperand(0);
3396 return std::nullopt;
3400 for (
size_t I = 0;
I < Elts.
size();
I++) {
3401 if (Elts[
I] ==
nullptr)
3406 if (InsertEltChain ==
nullptr)
3407 return std::nullopt;
3413 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3414 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3415 IIScalableTy->getMinNumElements() /
3420 auto *WideShuffleMaskTy =
3431 auto NarrowBitcast =
3444 return std::nullopt;
3449 Value *Pred =
II.getOperand(0);
3450 Value *Vec =
II.getOperand(1);
3451 Value *Shift =
II.getOperand(2);
3454 Value *AbsPred, *MergedValue;
3460 return std::nullopt;
3468 return std::nullopt;
3473 return std::nullopt;
3476 {
II.getType()}, {Pred, Vec, Shift});
3483 Value *Vec =
II.getOperand(0);
3488 return std::nullopt;
3491static std::optional<Instruction *>
3493 unsigned LookaheadThreshold) {
3495 auto *NI =
II.getNextNode();
3497 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3499 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3500 auto *NIBB = NI->getParent();
3501 NI = NI->getNextNode();
3503 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3504 NI = &*SuccBB->getFirstNonPHIOrDbgOrLifetime();
3510 if (NextII &&
II.isIdenticalTo(NextII))
3513 return std::nullopt;
3521 {II.getType(), II.getOperand(0)->getType()},
3522 {II.getOperand(0), II.getOperand(1)}));
3529 if (PredPattern == AArch64SVEPredPattern::all ||
3530 PredPattern == AArch64SVEPredPattern::pow2)
3532 return std::nullopt;
3538 Value *Passthru =
II.getOperand(0);
3546 auto *Mask = ConstantInt::get(Ty, MaskValue);
3552 return std::nullopt;
3555static std::optional<Instruction *>
3562 return std::nullopt;
3568 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3578 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3588 return std::nullopt;
3594 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3602 return std::nullopt;
3605 II.getType(), {Pg, A, B});
3607 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3616 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3621 Value *
A, *PgLHS, *PgRHS;
3627 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3628 return std::nullopt;
3631 if (ConstB > ConstA)
3637 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3638 return std::nullopt;
3640 Type *VecTy =
A->getType();
3644 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3651std::optional<Instruction *>
3662 case Intrinsic::aarch64_dmb:
3664 case Intrinsic::aarch64_neon_fmaxnm:
3665 case Intrinsic::aarch64_neon_fminnm:
3667 case Intrinsic::aarch64_sve_convert_from_svbool:
3669 case Intrinsic::aarch64_sve_dup:
3671 case Intrinsic::aarch64_sve_dup_x:
3673 case Intrinsic::aarch64_sve_cmpeq:
3674 case Intrinsic::aarch64_sve_cmpeq_wide:
3676 case Intrinsic::aarch64_sve_cmpne:
3677 case Intrinsic::aarch64_sve_cmpne_wide:
3679 case Intrinsic::aarch64_sve_rdffr:
3681 case Intrinsic::aarch64_sve_lasta:
3682 case Intrinsic::aarch64_sve_lastb:
3684 case Intrinsic::aarch64_sve_clasta_n:
3685 case Intrinsic::aarch64_sve_clastb_n:
3687 case Intrinsic::aarch64_sve_cntd:
3689 case Intrinsic::aarch64_sve_cntw:
3691 case Intrinsic::aarch64_sve_cnth:
3693 case Intrinsic::aarch64_sve_cntb:
3695 case Intrinsic::aarch64_sme_cntsd:
3697 case Intrinsic::aarch64_sve_ptest_any:
3698 case Intrinsic::aarch64_sve_ptest_first:
3699 case Intrinsic::aarch64_sve_ptest_last:
3701 case Intrinsic::aarch64_sve_fadd:
3703 case Intrinsic::aarch64_sve_fadd_u:
3705 case Intrinsic::aarch64_sve_fmul_u:
3707 case Intrinsic::aarch64_sve_fsub:
3709 case Intrinsic::aarch64_sve_fsub_u:
3711 case Intrinsic::aarch64_sve_add:
3713 case Intrinsic::aarch64_sve_add_u:
3715 Intrinsic::aarch64_sve_mla_u>(
3717 case Intrinsic::aarch64_sve_mla_u:
3719 case Intrinsic::aarch64_sve_sadalp:
3720 case Intrinsic::aarch64_sve_uadalp:
3722 case Intrinsic::aarch64_sve_sub:
3724 case Intrinsic::aarch64_sve_sub_u:
3726 Intrinsic::aarch64_sve_mls_u>(
3728 case Intrinsic::aarch64_sve_tbl:
3730 case Intrinsic::aarch64_sve_uunpkhi:
3731 case Intrinsic::aarch64_sve_uunpklo:
3732 case Intrinsic::aarch64_sve_sunpkhi:
3733 case Intrinsic::aarch64_sve_sunpklo:
3735 case Intrinsic::aarch64_sve_uzp1:
3737 case Intrinsic::aarch64_sve_zip1:
3738 case Intrinsic::aarch64_sve_zip2:
3740 case Intrinsic::aarch64_sve_ld1_gather_index:
3742 case Intrinsic::aarch64_sve_st1_scatter_index:
3744 case Intrinsic::aarch64_sve_ld1:
3746 case Intrinsic::aarch64_sve_st1:
3748 case Intrinsic::aarch64_sve_sdiv:
3750 case Intrinsic::aarch64_sve_sel:
3752 case Intrinsic::aarch64_sve_srshl:
3754 case Intrinsic::aarch64_sve_dupq_lane:
3756 case Intrinsic::aarch64_sve_insr:
3758 case Intrinsic::aarch64_sve_whilelo:
3760 case Intrinsic::aarch64_sve_ptrue:
3762 case Intrinsic::aarch64_sve_uxtb:
3764 case Intrinsic::aarch64_sve_uxth:
3766 case Intrinsic::aarch64_sve_uxtw:
3768 case Intrinsic::aarch64_sme_in_streaming_mode:
3770 case Intrinsic::aarch64_sve_umin_u:
3772 case Intrinsic::aarch64_sve_orr_u:
3774 case Intrinsic::aarch64_sve_and_z:
3778 return std::nullopt;
3785 SimplifyAndSetOp)
const {
3786 switch (
II.getIntrinsicID()) {
3789 case Intrinsic::aarch64_neon_fcvtxn:
3790 case Intrinsic::aarch64_neon_rshrn:
3791 case Intrinsic::aarch64_neon_sqrshrn:
3792 case Intrinsic::aarch64_neon_sqrshrun:
3793 case Intrinsic::aarch64_neon_sqshrn:
3794 case Intrinsic::aarch64_neon_sqshrun:
3795 case Intrinsic::aarch64_neon_sqxtn:
3796 case Intrinsic::aarch64_neon_sqxtun:
3797 case Intrinsic::aarch64_neon_uqrshrn:
3798 case Intrinsic::aarch64_neon_uqshrn:
3799 case Intrinsic::aarch64_neon_uqxtn:
3800 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3804 return std::nullopt;
3808 return ST->isSVEAvailable() ||
3809 (ST->isSVEorStreamingSVEAvailable() &&
3810 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3819 if (ST->useSVEForFixedLengthVectors() &&
3820 (ST->isSVEAvailable() ||
3821 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3823 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3824 else if (ST->isNeonAvailable())
3829 if (ST->isSVEAvailable() ||
3830 (ST->isSVEorStreamingSVEAvailable() &&
3831 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3839bool AArch64TTIImpl::isSingleExtWideningInstruction(
3841 Type *SrcOverrideTy)
const {
3856 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3859 Type *SrcTy = SrcOverrideTy;
3861 case Instruction::Add:
3862 case Instruction::Sub: {
3871 if (Opcode == Instruction::Sub)
3895 assert(SrcTy &&
"Expected some SrcTy");
3897 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3903 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3905 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3909 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3912Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3914 Type *SrcOverrideTy)
const {
3915 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3916 Opcode != Instruction::Mul)
3926 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3929 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3935 ->getScalarSizeInBits();
3938 unsigned MaxEltSize = 0;
3941 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3942 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3943 MaxEltSize = std::max(EltSize0, EltSize1);
3946 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3947 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3950 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3952 MaxEltSize = DstEltSize / 2;
3953 }
else if (Opcode == Instruction::Mul &&
3961 Known.Zero.countLeadingOnes() >
3966 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3970 if (MaxEltSize * 2 > DstEltSize)
3988 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
3989 (Src->isScalableTy() && !ST->hasSVE2()))
3999 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4003 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4007 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4008 Src->getScalarSizeInBits() !=
4032 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4046 if (
I && !
I->users().empty()) {
4050 auto GetUserAbsorbedCastCost =
4051 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
4054 if (
Type *ExtTy = isBinExtWideningInstruction(
4056 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4069 if (isSingleExtWideningInstruction(
4071 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
4075 if (Usr->getOpcode() == Instruction::Add) {
4076 if (
I == Usr->getOperand(1) ||
4092 return std::nullopt;
4096 bool AllUsersAbsorbCast =
true;
4097 for (
const User *U :
I->users()) {
4099 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4101 AllUsersAbsorbCast =
false;
4104 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4107 if (AllUsersAbsorbCast)
4108 return MaxAbsorbedCost;
4111 EVT SrcTy = TLI->getValueType(
DL, Src);
4112 EVT DstTy = TLI->getValueType(
DL, Dst);
4116 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4126 Instruction::ExtractElement, Src,
CostKind, -1,
nullptr,
nullptr);
4128 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH,
CostKind);
4132 if (!SrcTy.isSimple() || !DstTy.
isSimple())
4137 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4166 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4169 ST->useSVEForFixedLengthVectors(WiderTy)) {
4170 std::pair<InstructionCost, MVT> LT =
4172 unsigned NumElements =
4188 const unsigned int SVE_EXT_COST = 1;
4189 const unsigned int SVE_FCVT_COST = 1;
4190 const unsigned int SVE_UNPACK_ONCE = 4;
4191 const unsigned int SVE_UNPACK_TWICE = 16;
4320 SVE_EXT_COST + SVE_FCVT_COST},
4325 SVE_EXT_COST + SVE_FCVT_COST},
4332 SVE_EXT_COST + SVE_FCVT_COST},
4336 SVE_EXT_COST + SVE_FCVT_COST},
4342 SVE_EXT_COST + SVE_FCVT_COST},
4345 SVE_EXT_COST + SVE_FCVT_COST},
4350 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4352 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4362 SVE_EXT_COST + SVE_FCVT_COST},
4367 SVE_EXT_COST + SVE_FCVT_COST},
4380 SVE_EXT_COST + SVE_FCVT_COST},
4384 SVE_EXT_COST + SVE_FCVT_COST},
4396 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4398 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4400 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4402 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4406 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4408 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4424 SVE_EXT_COST + SVE_FCVT_COST},
4429 SVE_EXT_COST + SVE_FCVT_COST},
4440 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4442 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4444 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4446 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4448 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4450 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4454 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4456 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4458 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4460 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4685 if (ST->hasFullFP16())
4697 Src->getScalarType(), CCH,
CostKind) +
4705 ST->isSVEorStreamingSVEAvailable() &&
4706 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4708 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4717 Opcode, LegalTy, Src, CCH,
CostKind,
I);
4720 return Part1 + Part2;
4727 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4739 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4752 CostKind, Index,
nullptr,
nullptr);
4756 auto DstVT = TLI->getValueType(
DL, Dst);
4757 auto SrcVT = TLI->getValueType(
DL, Src);
4762 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4768 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4778 case Instruction::SExt:
4783 case Instruction::ZExt:
4784 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4797 return Opcode == Instruction::PHI ? 0 : 1;
4806 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4808 assert(Ty->isVectorTy() &&
"This must be a vector type");
4815 if (!LT.second.isVector())
4820 if (LT.second.isFixedLengthVector()) {
4821 unsigned Width = LT.second.getVectorNumElements();
4822 Index = Index % Width;
4829 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4841 if (Index * Ty->getScalarSizeInBits() < 128)
4843 if (Index * Ty->getScalarSizeInBits() < 512 &&
4844 Opcode == Instruction::ExtractElement)
4846 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4847 if (Opcode == Instruction::ExtractElement)
4849 if (Opcode == Instruction::InsertElement)
4858 if (VIC == TTI::VectorInstrContext::Load) {
4859 if (ST->hasFastLD1Single())
4863 : ST->getVectorInsertExtractBaseCost() + 1;
4871 : ST->getVectorInsertExtractBaseCost() + 1;
4895 auto ExtractCanFuseWithFmul = [&]() {
4902 auto IsAllowedScalarTy = [&](
const Type *
T) {
4903 return T->isFloatTy() ||
T->isDoubleTy() ||
4904 (
T->isHalfTy() && ST->hasFullFP16());
4908 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4911 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4912 !BO->getType()->isVectorTy();
4917 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4921 return Idx == 0 || (RegWidth != 0 && (
Idx * EltSz) % RegWidth == 0);
4930 DenseMap<User *, unsigned> UserToExtractIdx;
4931 for (
auto *U :
Scalar->users()) {
4932 if (!IsUserFMulScalarTy(U))
4936 UserToExtractIdx[
U];
4938 if (UserToExtractIdx.
empty())
4940 for (
auto &[S, U, L] : ScalarUserAndIdx) {
4941 for (
auto *U : S->users()) {
4942 if (UserToExtractIdx.
contains(U)) {
4944 auto *Op0 =
FMul->getOperand(0);
4945 auto *Op1 =
FMul->getOperand(1);
4946 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
4947 UserToExtractIdx[
U] =
L;
4953 for (
auto &[U, L] : UserToExtractIdx) {
4965 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
4966 if (!IsUserFMulScalarTy(U))
4971 const auto *BO = cast<BinaryOperator>(U);
4972 const auto *OtherEE = dyn_cast<ExtractElementInst>(
4973 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
4975 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
4978 return IsExtractLaneEquivalentToZero(
4979 cast<ConstantInt>(OtherEE->getIndexOperand())
4982 OtherEE->getType()->getScalarSizeInBits());
4990 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
4991 ExtractCanFuseWithFmul())
4996 :
ST->getVectorInsertExtractBaseCost();
5005 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5008 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr,
nullptr,
5014 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5016 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr, Scalar,
5017 ScalarUserAndIdx, VIC);
5024 return getVectorInstrCostHelper(
I.getOpcode(), Ty,
CostKind, Index, &
I,
5031 unsigned Index)
const {
5042 : ST->getVectorInsertExtractBaseCost() + 1;
5054 if (ST->hasFastLD1Single()) {
5055 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5056 (VIC == TTI::VectorInstrContext::Load && Insert))
5060 if (Ty->getElementType()->isFloatingPointTy())
5063 unsigned VecInstCost =
5065 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
5072 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5073 return std::nullopt;
5074 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5075 return std::nullopt;
5077 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5078 return std::nullopt;
5085 Cost += InstCost(PromotedTy);
5100 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5114 Op2Info, Args, CtxI);
5121 Ty,
CostKind, Op1Info, Op2Info,
true,
5124 [&](
Type *PromotedTy) {
5128 return *PromotedCost;
5131 if (Ty->getScalarType()->isFP128Ty())
5139 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5159 ST->hasLimited64bitVectorMulBandwidth())
5162 if (Ty->getScalarSizeInBits() > 64) {
5167 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5170 if (LT.second == MVT::v2i64) {
5174 return LT.first * Mul64CostFactor;
5195 if (LT.second == MVT::nxv2i64)
5196 return LT.first * Mul64CostFactor;
5255 auto VT = TLI->getValueType(
DL, Ty);
5256 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5260 : (3 * AsrCost + AddCost);
5262 return MulCost + AsrCost + 2 * AddCost;
5264 }
else if (VT.isVector()) {
5274 if (Ty->isScalableTy() && ST->hasSVE())
5275 Cost += 2 * AsrCost;
5280 ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5284 }
else if (LT.second == MVT::v2i64) {
5285 return VT.getVectorNumElements() *
5292 if (Ty->isScalableTy() && ST->hasSVE())
5293 return MulCost + 2 * AddCost + 2 * AsrCost;
5294 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5299 LT.second.isFixedLengthVector()) {
5309 return ExtractCost + InsertCost +
5317 auto VT = TLI->getValueType(
DL, Ty);
5333 bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||
5334 LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||
5335 LT.second == MVT::nxv16i8;
5336 bool Is128bit = LT.second.is128BitVector();
5348 (HasMULH ? 0 : ShrCost) +
5349 AddCost * 2 + ShrCost;
5350 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5357 if (!VT.isVector() && VT.getSizeInBits() > 64)
5361 Opcode, Ty,
CostKind, Op1Info, Op2Info);
5363 if (TLI->isOperationLegalOrCustom(
ISD, LT.second) && ST->hasSVE()) {
5367 Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {
5377 if (
nullptr != Entry)
5385 FVTy && LT.second.isFixedLengthVector()) {
5386 unsigned NumElts = FVTy->getNumElements();
5387 unsigned RegElts = LT.second.getVectorNumElements();
5389 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5393 if (LT.second.getScalarType() == MVT::i8)
5395 else if (LT.second.getScalarType() == MVT::i16)
5407 Opcode, Ty->getScalarType(),
CostKind, Op1Info, Op2Info);
5408 return (4 + DivCost) * VTy->getNumElements();
5414 -1,
nullptr,
nullptr);
5441 LT.second.isFixedLengthVector())
5442 return 2 * LT.first + 1;
5451 if ((Ty->isFloatTy() || Ty->isDoubleTy() ||
5452 (Ty->isHalfTy() && ST->hasFullFP16())) &&
5461 if (!Ty->getScalarType()->isFP128Ty())
5468 if (!Ty->getScalarType()->isFP128Ty())
5469 return 2 * LT.first;
5476 if (!Ty->isVectorTy())
5491 unsigned NumVectorInstToHideOverhead =
5492 ST->getCLOpts().neon_nonconst_stride_overhead;
5493 int MaxMergeDistance = 64;
5497 return NumVectorInstToHideOverhead;
5507 unsigned Opcode1,
unsigned Opcode2)
const {
5510 if (!
Sched.hasInstrSchedModel())
5514 Sched.getSchedClassDesc(
TII->get(Opcode1).getSchedClass());
5516 Sched.getSchedClassDesc(
TII->get(Opcode2).getSchedClass());
5522 "Cannot handle variant scheduling classes without an MI");
5538 const int AmortizationCost = 20;
5546 VecPred = CurrentPred;
5554 static const auto ValidMinMaxTys = {
5555 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5556 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5557 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5561 (ST->hasFullFP16() &&
5567 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5568 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5569 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5570 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5571 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5572 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5573 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5574 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5575 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5576 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5577 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5579 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5580 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5589 if (Opcode == Instruction::FCmp) {
5591 ValTy,
CostKind, Op1Info, Op2Info,
false,
5593 false, [&](
Type *PromotedTy) {
5605 return *PromotedCost;
5609 if (LT.second.getScalarType() != MVT::f64 &&
5610 LT.second.getScalarType() != MVT::f32 &&
5611 LT.second.getScalarType() != MVT::f16)
5616 unsigned Factor = 1;
5617 if (!CondTy->isVectorTy() &&
5631 AArch64::FCMEQv4f32))
5643 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5662 Op1Info, Op2Info,
I);
5668 if (ST->requiresStrictAlign()) {
5673 Options.AllowOverlappingLoads =
true;
5674 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5679 Options.LoadSizes = {8, 4, 2, 1};
5680 Options.AllowedTailExpansions = {3, 5, 6};
5685 return ST->hasSVE();
5691 switch (MICA.
getID()) {
5692 case Intrinsic::masked_scatter:
5693 case Intrinsic::masked_gather:
5695 case Intrinsic::masked_load:
5696 case Intrinsic::masked_store:
5697 case Intrinsic::masked_expandload:
5698 case Intrinsic::masked_compressstore:
5712 if (!LT.first.isValid())
5717 if (VT->getElementType()->isIntegerTy(1))
5723 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5729 if (MICA.
getID() == Intrinsic::masked_expandload) {
5742 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5762 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5763 return MemOpCost * 2;
5772 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5773 "Should be called on only load or stores.");
5775 case Instruction::Load:
5776 return ST->getCLOpts().sve_gather_overhead.value_or(
5777 ST->getGatherOverhead());
5779 case Instruction::Store:
5780 return ST->getCLOpts().sve_scatter_overhead.value_or(
5781 ST->getScatterOverhead());
5792 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5793 MICA.
getID() == Intrinsic::vp_gather)
5795 : Instruction::Store;
5805 if (!LT.first.isValid())
5809 if (!LT.second.isVector() ||
5811 VT->getElementType()->isIntegerTy(1))
5821 ElementCount LegalVF = LT.second.getVectorElementCount();
5824 {TTI::OK_AnyValue, TTI::OP_None},
I);
5840 EVT VT = TLI->getValueType(
DL, Ty,
true);
5842 if (VT == MVT::Other)
5847 if (!LT.first.isValid())
5853 if (VTy->getElementType()->isIntegerTy(1) &&
5854 !VTy->getElementCount().isKnownMultipleOf(
5860 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5861 : Intrinsic::masked_store;
5875 if (Opcode == Instruction::Store)
5879 if (ST->getFixedLoadLatency())
5880 return (LT.first - 1) + ST->getFixedLoadLatency();
5889 if (LT.second.isScalableVector() ||
5890 ST->useSVEForFixedLengthVectors(LT.second)) {
5891 Inst = AArch64::LDR_ZXI;
5892 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5893 switch (LT.second.getSizeInBits()) {
5895 Inst = AArch64::LDRBui;
5898 Inst = AArch64::LDRHui;
5901 Inst = AArch64::LDRSui;
5904 Inst = AArch64::LDRDui;
5907 Inst = AArch64::LDRQui;
5913 switch (LT.second.getSizeInBits()) {
5915 Inst = AArch64::LDRBBui;
5918 Inst = AArch64::LDRHHui;
5921 Inst = AArch64::LDRWui;
5924 Inst = AArch64::LDRXui;
5932 unsigned SchedClass =
TII->get(Inst).getSchedClass();
5934 ?
Sched.getSchedClassDesc(SchedClass)
5940 return (LT.first - 1) + ST->getLoadLatency();
5943 float NumLoads = (LT.first - 1).
getValue();
5944 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
5945 Sched.computeInstrLatency(*ST, *SCD);
5948 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
5949 LT.second.is128BitVector() && Alignment <
Align(16)) {
5955 const int AmortizationCost = 6;
5957 return LT.first * 2 * AmortizationCost;
5961 if (Ty->isPtrOrPtrVectorTy())
5966 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
5968 if (VT == MVT::v4i8)
5975 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
5976 Alignment !=
Align(1))
5988 if (Remainder != 0) {
5991 while (!TypeWorklist.
empty()) {
6001 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
6013 bool UseMaskForCond,
bool UseMaskForGaps)
const {
6014 assert(Factor >= 2 &&
"Invalid interleave factor");
6023 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6027 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6032 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6037 (UseMaskForCond || UseMaskForGaps ||
6038 (Factor > MaxNativeInterleaveFactor &&
6039 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6042 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6045 EC.divideCoefficientBy(Factor));
6051 if (EC.isKnownMultipleOf(Factor) &&
6052 TLI->isLegalInterleavedAccessType(SubVecTy,
DL, UseScalable))
6053 return Factor * TLI->getNumInterleavedAccesses(SubVecTy,
DL, UseScalable);
6058 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6064 if (UseMaskForCond) {
6065 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6066 : Intrinsic::masked_store;
6086 if (Opcode == Instruction::Store && Factor == 4 &&
6087 SubVecCost.second.getScalarSizeInBits() ==
6088 (4 * ResultCost.second.getScalarSizeInBits()))
6089 LegalizationCost *= 4;
6091 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
6097 UseMaskForCond, UseMaskForGaps);
6104 for (
auto *
I : Tys) {
6105 if (!
I->isVectorTy())
6116 Align Alignment)
const {
6123 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6124 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6136 Size.getFixedValue() <= 16;
6141 bool IsStore, std::optional<Instruction::CastOps> CastHint)
const {
6142 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6161 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6168 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6174 bool HasUnorderedReductions)
const {
6177 return ST->getMaxInterleaveFactor();
6187 enum { MaxStridedLoads = 7 };
6189 int StridedLoads = 0;
6192 for (
const auto BB : L->blocks()) {
6193 for (
auto &
I : *BB) {
6199 if (L->isLoopInvariant(PtrValue))
6204 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
6213 if (StridedLoads > MaxStridedLoads / 2)
6214 return StridedLoads;
6217 return StridedLoads;
6220 int StridedLoads = countStridedLoads(L, SE);
6222 <<
" strided loads\n");
6238 unsigned *FinalSize) {
6242 for (
auto *BB : L->getBlocks()) {
6243 for (
auto &
I : *BB) {
6249 if (!Cost.isValid())
6253 if (LoopCost > Budget)
6275 if (MaxTC > 0 && MaxTC <= 32)
6286 if (Blocks.
size() != 2)
6308 if (!L->isInnermost() || L->getNumBlocks() > 8)
6312 if (!L->getExitBlock())
6318 bool HasParellelizableReductions =
6319 L->getNumBlocks() == 1 &&
6320 any_of(L->getHeader()->phis(),
6322 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6325 if (HasParellelizableReductions &&
6347 if (HasParellelizableReductions) {
6358 if (Header == Latch) {
6361 unsigned Width = 10;
6367 unsigned MaxInstsPerLine = 16;
6369 unsigned BestUC = 1;
6370 unsigned SizeWithBestUC = BestUC *
Size;
6372 unsigned SizeWithUC = UC *
Size;
6373 if (SizeWithUC > 48)
6375 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6376 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6378 SizeWithBestUC = BestUC *
Size;
6388 for (
auto *BB : L->blocks()) {
6389 for (
auto &
I : *BB) {
6399 for (
auto *U :
I.users())
6401 LoadedValuesPlus.
insert(U);
6408 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6434 auto *I = dyn_cast<Instruction>(V);
6435 return I && DependsOnLoopLoad(I, Depth + 1);
6442 DependsOnLoopLoad(
I, 0)) {
6474 if (L->getLoopDepth() > 1)
6485 for (
auto *BB : L->getBlocks()) {
6486 for (
auto &
I : *BB) {
6490 if (IsVectorized &&
I.getType()->isVectorTy())
6501 if (
Cost >= ST->getCLOpts().force_unroll_threshold)
6510 if (ST->isAppleMLike())
6512 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6513 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6534 !ST->getSchedModel().isOutOfOrder()) {
6546 if (
Cost < ST->getCLOpts().force_unroll_threshold)
6557 bool CanCreate)
const {
6561 case Intrinsic::aarch64_neon_st1x2:
6562 case Intrinsic::aarch64_neon_st1x3:
6563 case Intrinsic::aarch64_neon_st1x4:
6564 case Intrinsic::aarch64_neon_st2:
6565 case Intrinsic::aarch64_neon_st3:
6566 case Intrinsic::aarch64_neon_st4: {
6569 if (!CanCreate || !ST)
6571 unsigned NumElts = Inst->
arg_size() - 1;
6572 if (ST->getNumElements() != NumElts)
6574 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6580 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6582 Res = Builder.CreateInsertValue(Res, L, i);
6586 case Intrinsic::aarch64_neon_ld1x2:
6587 case Intrinsic::aarch64_neon_ld1x3:
6588 case Intrinsic::aarch64_neon_ld1x4:
6589 case Intrinsic::aarch64_neon_ld2:
6590 case Intrinsic::aarch64_neon_ld3:
6591 case Intrinsic::aarch64_neon_ld4:
6592 if (Inst->
getType() == ExpectedType)
6603 case Intrinsic::aarch64_neon_ld1x2:
6604 case Intrinsic::aarch64_neon_ld1x3:
6605 case Intrinsic::aarch64_neon_ld1x4:
6606 case Intrinsic::aarch64_neon_ld2:
6607 case Intrinsic::aarch64_neon_ld3:
6608 case Intrinsic::aarch64_neon_ld4:
6609 Info.ReadMem =
true;
6610 Info.WriteMem =
false;
6613 case Intrinsic::aarch64_neon_st1x2:
6614 case Intrinsic::aarch64_neon_st1x3:
6615 case Intrinsic::aarch64_neon_st1x4:
6616 case Intrinsic::aarch64_neon_st2:
6617 case Intrinsic::aarch64_neon_st3:
6618 case Intrinsic::aarch64_neon_st4:
6619 Info.ReadMem =
false;
6620 Info.WriteMem =
true;
6629 case Intrinsic::aarch64_neon_ld1x2:
6630 case Intrinsic::aarch64_neon_st1x2:
6631 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6633 case Intrinsic::aarch64_neon_ld1x3:
6634 case Intrinsic::aarch64_neon_st1x3:
6635 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6637 case Intrinsic::aarch64_neon_ld1x4:
6638 case Intrinsic::aarch64_neon_st1x4:
6639 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6641 case Intrinsic::aarch64_neon_ld2:
6642 case Intrinsic::aarch64_neon_st2:
6643 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6645 case Intrinsic::aarch64_neon_ld3:
6646 case Intrinsic::aarch64_neon_st3:
6647 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6649 case Intrinsic::aarch64_neon_ld4:
6650 case Intrinsic::aarch64_neon_st4:
6651 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6663 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6664 bool Considerable =
false;
6665 AllowPromotionWithoutCommonHeader =
false;
6668 Type *ConsideredSExtType =
6670 if (
I.getType() != ConsideredSExtType)
6674 for (
const User *U :
I.users()) {
6676 Considerable =
true;
6680 if (GEPInst->getNumOperands() > 2) {
6681 AllowPromotionWithoutCommonHeader =
true;
6686 return Considerable;
6737 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6747 return LegalizationCost + 2;
6757 LegalizationCost *= LT.first - 1;
6760 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6769 return LegalizationCost + 2;
6777 std::optional<FastMathFlags> FMF,
6793 return BaseCost + FixedVTy->getNumElements();
6807 MVT MTy = LT.second;
6812 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6860 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6861 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6873 return (LT.first - 1) +
Log2_32(NElts);
6878 return (LT.first - 1) + Entry->Cost;
6890 if (LT.first != 1) {
6896 ExtraCost *= LT.first - 1;
6899 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
6900 return Cost + ExtraCost;
6908 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
6910 EVT VecVT = TLI->getValueType(
DL, VecTy);
6911 EVT ResVT = TLI->getValueType(
DL, ResTy);
6921 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6923 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
6925 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
6927 return (LT.first - 1) * 2 + 2;
6938 EVT VecVT = TLI->getValueType(
DL, VecTy);
6939 EVT ResVT = TLI->getValueType(
DL, ResTy);
6942 RedOpcode == Instruction::Add) {
6948 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6950 return LT.first + 2;
6985 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
6986 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
7000 if (LT.second.getScalarType() == MVT::i1) {
7009 assert(Entry &&
"Illegal Type for Splice");
7010 LegalizationCost += Entry->Cost;
7011 return LegalizationCost * LT.first;
7015 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
7024 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7025 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7031 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
7032 if (!FMF->allowReassoc() || !FMF->allowContract())
7036 "FastMathFlags only apply to floating-point partial reductions");
7040 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
7041 "Unexpected values for OpBExtend or InputTypeB");
7045 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7046 InputTypeA != InputTypeB))
7057 assert(!OpBExtend &&
"Extended second operand without extended first.");
7058 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
7064 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
7067 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7080 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
7089 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
7095 std::pair<InstructionCost, MVT> AccumLT =
7097 std::pair<InstructionCost, MVT> InputLT =
7101 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
7102 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7103 (AccumLT.second.isFixedLengthVector() &&
7104 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7108 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7116 if (AccumLT.second.getScalarType() == MVT::i32 &&
7117 InputLT.second.getScalarType() == MVT::i8) {
7119 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
7120 return Cost + INegCost;
7122 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7123 return Cost + INegCost;
7128 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
7129 return Cost * 3 + INegCost;
7132 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7134 if (AccumLT.second.getScalarType() == MVT::i64 &&
7135 InputLT.second.getScalarType() == MVT::i16)
7136 return Cost + INegCost;
7139 if (AccumLT.second.getScalarType() == MVT::i32 &&
7140 InputLT.second.getScalarType() == MVT::i16 &&
7141 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7144 if (AccumLT.second.getScalarType() == MVT::i64 &&
7145 InputLT.second.getScalarType() == MVT::i8)
7148 return Cost + INegCost;
7151 if (AccumLT.second.getScalarType() == MVT::i16 &&
7152 InputLT.second.getScalarType() == MVT::i8 &&
7153 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7171 if ((!BinOp || IsSExtMul) && !IsSub &&
7172 AccumLT.second.getScalarType() == MVT::i64 &&
7173 InputLT.second.getScalarType() == MVT::i8 &&
7174 IsSupported(
false, ST->hasDotProd()))
7179 if (Opcode == Instruction::FAdd && !IsSub &&
7180 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7181 AccumLT.second.getScalarType() == MVT::f32 &&
7182 InputLT.second.getScalarType() == MVT::f16)
7186 if (Ratio == 2 && !IsUSDot) {
7187 MVT InVT = InputLT.second.getScalarType();
7191 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
7193 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
7196 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7200 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
7201 InVT == MVT::bf16 && IsSub)
7211 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7212 return Cost * 2 + FNegCost;
7216 AccumType, VF, OpAExtend, OpBExtend,
7227 "Expected the Mask to match the return size if given");
7229 "Expected the same scalar types");
7235 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7236 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7237 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7245 return std::max<InstructionCost>(1, LT.first / 4);
7253 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7255 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7258 unsigned TpNumElts = Mask.size();
7259 unsigned LTNumElts = LT.second.getVectorNumElements();
7260 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7262 LT.second.getVectorElementCount());
7264 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7266 for (
unsigned N = 0;
N < NumVecs;
N++) {
7270 unsigned Source1 = -1U, Source2 = -1U;
7271 unsigned NumSources = 0;
7272 for (
unsigned E = 0; E < LTNumElts; E++) {
7273 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7282 unsigned Source = MaskElt / LTNumElts;
7283 if (NumSources == 0) {
7286 }
else if (NumSources == 1 && Source != Source1) {
7289 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7295 if (Source == Source1)
7297 else if (Source == Source2)
7298 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7307 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7318 NTp, NTp,
CostKind, NMask, 0,
nullptr, Args,
7321 Result.first->second = NCost;
7335 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7336 if (LT.second.getFixedSizeInBits() >= 128 &&
7338 LT.second.getVectorNumElements() / 2) {
7341 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7355 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7358 return M.value() < 0 || M.value() == (int)M.index();
7364 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7365 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7374 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7375 ST->isSVEorStreamingSVEAvailable() &&
7380 if (ST->isSVEorStreamingSVEAvailable() &&
7394 if (IsLoad && LT.second.isVector() &&
7396 LT.second.getVectorElementCount()))
7402 if (Mask.size() == 4 &&
7404 (SrcTy->getScalarSizeInBits() == 16 ||
7405 SrcTy->getScalarSizeInBits() == 32) &&
7406 all_of(Mask, [](
int E) {
return E < 8; }))
7412 if (LT.second.isFixedLengthVector() &&
7413 LT.second.getVectorNumElements() == Mask.size() &&
7419 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7420 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7421 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7422 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7423 LT.second.getVectorNumElements(), 16) ||
7424 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7425 LT.second.getVectorNumElements(), 32) ||
7426 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7427 LT.second.getVectorNumElements(), 64) ||
7430 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7559 return LT.first * Entry->Cost;
7568 LT.second.getSizeInBits() <= 128 && SubTp) {
7570 if (SubLT.second.isVector()) {
7571 int NumElts = LT.second.getVectorNumElements();
7572 int NumSubElts = SubLT.second.getVectorNumElements();
7573 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7579 if (IsExtractSubvector)
7600 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7611 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7612 ST->useFixedOverScalableIfEqualCost());
7616 return ST->getEpilogueVectorizationMinVF();
7651 unsigned NumInsns = 0;
7653 NumInsns += BB->size();
7657 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7663 int64_t Scale,
unsigned AddrSpace)
const {
7686 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7691 if (
I->getOpcode() == Instruction::Or &&
7695 if (
I->getOpcode() == Instruction::Add ||
7696 I->getOpcode() == Instruction::Sub)
7710 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7721 return all_equal(Shuf->getShuffleMask());
7728 bool AllowSplat =
false) {
7733 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7734 auto *FullTy = FullV->
getType();
7735 auto *HalfTy = HalfV->getType();
7737 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7740 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7743 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7747 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7761 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7762 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7776 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7777 (M2Start != 0 && M2Start != (NumElements / 2)))
7779 if (S1Op1 && S2Op1 && M1Start != M2Start)
7789 return Ext->getType()->getScalarSizeInBits() ==
7790 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7804 Value *VectorOperand =
nullptr;
7821 if (!
GEP ||
GEP->getNumOperands() != 2)
7825 Value *Offsets =
GEP->getOperand(1);
7828 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7834 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7835 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7836 Ops.push_back(&
GEP->getOperandUse(1));
7872 switch (
II->getIntrinsicID()) {
7873 case Intrinsic::aarch64_neon_smull:
7874 case Intrinsic::aarch64_neon_umull:
7877 Ops.push_back(&
II->getOperandUse(0));
7878 Ops.push_back(&
II->getOperandUse(1));
7883 case Intrinsic::fma:
7884 case Intrinsic::fmuladd:
7891 Ops.push_back(&
II->getOperandUse(0));
7893 Ops.push_back(&
II->getOperandUse(1));
7896 case Intrinsic::aarch64_neon_sqdmull:
7897 case Intrinsic::aarch64_neon_sqdmulh:
7898 case Intrinsic::aarch64_neon_sqrdmulh:
7901 Ops.push_back(&
II->getOperandUse(0));
7903 Ops.push_back(&
II->getOperandUse(1));
7904 return !
Ops.empty();
7905 case Intrinsic::aarch64_neon_fmlal:
7906 case Intrinsic::aarch64_neon_fmlal2:
7907 case Intrinsic::aarch64_neon_fmlsl:
7908 case Intrinsic::aarch64_neon_fmlsl2:
7911 Ops.push_back(&
II->getOperandUse(1));
7913 Ops.push_back(&
II->getOperandUse(2));
7914 return !
Ops.empty();
7915 case Intrinsic::aarch64_sve_ptest_first:
7916 case Intrinsic::aarch64_sve_ptest_last:
7918 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
7919 Ops.push_back(&
II->getOperandUse(0));
7920 return !
Ops.empty();
7921 case Intrinsic::aarch64_sme_write_horiz:
7922 case Intrinsic::aarch64_sme_write_vert:
7923 case Intrinsic::aarch64_sme_writeq_horiz:
7924 case Intrinsic::aarch64_sme_writeq_vert: {
7926 if (!Idx || Idx->getOpcode() != Instruction::Add)
7928 Ops.push_back(&
II->getOperandUse(1));
7931 case Intrinsic::aarch64_sme_read_horiz:
7932 case Intrinsic::aarch64_sme_read_vert:
7933 case Intrinsic::aarch64_sme_readq_horiz:
7934 case Intrinsic::aarch64_sme_readq_vert:
7935 case Intrinsic::aarch64_sme_ld1b_vert:
7936 case Intrinsic::aarch64_sme_ld1h_vert:
7937 case Intrinsic::aarch64_sme_ld1w_vert:
7938 case Intrinsic::aarch64_sme_ld1d_vert:
7939 case Intrinsic::aarch64_sme_ld1q_vert:
7940 case Intrinsic::aarch64_sme_st1b_vert:
7941 case Intrinsic::aarch64_sme_st1h_vert:
7942 case Intrinsic::aarch64_sme_st1w_vert:
7943 case Intrinsic::aarch64_sme_st1d_vert:
7944 case Intrinsic::aarch64_sme_st1q_vert:
7945 case Intrinsic::aarch64_sme_ld1b_horiz:
7946 case Intrinsic::aarch64_sme_ld1h_horiz:
7947 case Intrinsic::aarch64_sme_ld1w_horiz:
7948 case Intrinsic::aarch64_sme_ld1d_horiz:
7949 case Intrinsic::aarch64_sme_ld1q_horiz:
7950 case Intrinsic::aarch64_sme_st1b_horiz:
7951 case Intrinsic::aarch64_sme_st1h_horiz:
7952 case Intrinsic::aarch64_sme_st1w_horiz:
7953 case Intrinsic::aarch64_sme_st1d_horiz:
7954 case Intrinsic::aarch64_sme_st1q_horiz: {
7956 if (!Idx || Idx->getOpcode() != Instruction::Add)
7958 Ops.push_back(&
II->getOperandUse(3));
7961 case Intrinsic::aarch64_neon_pmull:
7964 Ops.push_back(&
II->getOperandUse(0));
7965 Ops.push_back(&
II->getOperandUse(1));
7967 case Intrinsic::aarch64_neon_pmull64:
7969 II->getArgOperand(1)))
7971 Ops.push_back(&
II->getArgOperandUse(0));
7972 Ops.push_back(&
II->getArgOperandUse(1));
7974 case Intrinsic::masked_gather:
7977 Ops.push_back(&
II->getArgOperandUse(0));
7979 case Intrinsic::masked_scatter:
7982 Ops.push_back(&
II->getArgOperandUse(1));
7989 auto ShouldSinkCondition = [](
Value *
Cond,
7994 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
7998 Ops.push_back(&
II->getOperandUse(0));
8002 switch (
I->getOpcode()) {
8003 case Instruction::GetElementPtr:
8004 case Instruction::Add:
8005 case Instruction::Sub:
8007 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
8009 Ops.push_back(&
I->getOperandUse(
Op));
8014 case Instruction::Select: {
8015 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
8018 Ops.push_back(&
I->getOperandUse(0));
8021 case Instruction::UncondBr:
8023 case Instruction::CondBr: {
8027 Ops.push_back(&
I->getOperandUse(0));
8030 case Instruction::FMul:
8035 Ops.push_back(&
I->getOperandUse(0));
8037 Ops.push_back(&
I->getOperandUse(1));
8047 case Instruction::Xor:
8050 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8052 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8057 case Instruction::And:
8058 case Instruction::Or:
8061 if (
I->getOpcode() == Instruction::Or &&
8066 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
8069 for (
auto &
Op :
I->operands()) {
8081 Ops.push_back(&Not);
8082 Ops.push_back(&InsertElt);
8092 if (!
I->getType()->isVectorTy())
8093 return !
Ops.empty();
8095 switch (
I->getOpcode()) {
8096 case Instruction::Sub:
8097 case Instruction::Add: {
8106 Ops.push_back(&Ext1->getOperandUse(0));
8107 Ops.push_back(&Ext2->getOperandUse(0));
8110 Ops.push_back(&
I->getOperandUse(0));
8111 Ops.push_back(&
I->getOperandUse(1));
8115 case Instruction::Or: {
8118 if (ST->hasNEON()) {
8132 if (
I->getParent() != MainAnd->
getParent() ||
8137 if (
I->getParent() != IA->getParent() ||
8138 I->getParent() != IB->getParent())
8143 Ops.push_back(&
I->getOperandUse(0));
8144 Ops.push_back(&
I->getOperandUse(1));
8153 case Instruction::Mul: {
8154 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
8157 if (Ty->isScalableTy())
8161 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8164 int NumZExts = 0, NumSExts = 0;
8165 for (
auto &
Op :
I->operands()) {
8172 auto *ExtOp = Ext->getOperand(0);
8173 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8174 Ops.push_back(&Ext->getOperandUse(0));
8182 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8183 I->getType()->getScalarSizeInBits())
8220 if (!ElementConstant || !ElementConstant->
isZero())
8223 unsigned Opcode = OperandInstr->
getOpcode();
8224 if (Opcode == Instruction::SExt)
8226 else if (Opcode == Instruction::ZExt)
8231 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8241 Ops.push_back(&Insert->getOperandUse(1));
8247 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8251 if (!ShouldSinkSplatForIndexedVariant(
I))
8256 Ops.push_back(&
I->getOperandUse(0));
8258 Ops.push_back(&
I->getOperandUse(1));
8260 return !
Ops.empty();
8262 case Instruction::FMul: {
8264 if (
I->getType()->isScalableTy())
8265 return !
Ops.empty();
8269 return !
Ops.empty();
8273 Ops.push_back(&
I->getOperandUse(0));
8275 Ops.push_back(&
I->getOperandUse(1));
8276 return !
Ops.empty();
8285 Align Alignment)
const {
8286 if (!(ST->isSVEAvailable() ||
8287 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8291 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8298 if (!LT.first.isValid())
8303 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,...
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.
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.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isFixedLengthVector() const
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Machine model for scheduling, bundling, and heuristics.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Information about a load/store intrinsic defined by the target.
InterleavedAccessInfo * IAI
LoopVectorizationLegality * LVL
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...