24#include "llvm/IR/IntrinsicsAArch64.h"
36#define DEBUG_TYPE "aarch64tti"
42 "sve-prefer-fixed-over-scalable-if-equal",
cl::Hidden);
60 "Penalty of calling a function that requires a change to PSTATE.SM"));
64 cl::desc(
"Penalty of inlining a call that requires a change to PSTATE.SM"));
75 cl::desc(
"The cost of a histcnt instruction"));
79 cl::desc(
"The number of instructions to search for a redundant dmb"));
83 cl::desc(
"Threshold for forced unrolling of small loops in AArch64"));
86class TailFoldingOption {
101 bool NeedsDefault =
true;
105 void setNeedsDefault(
bool V) { NeedsDefault =
V; }
120 assert((InitialBits == TailFoldingOpts::Disabled || !NeedsDefault) &&
121 "Initial bits should only include one of "
122 "(disabled|all|simple|default)");
123 Bits = NeedsDefault ? DefaultBits : InitialBits;
125 Bits &= ~DisableBits;
131 errs() <<
"invalid argument '" << Opt
132 <<
"' to -sve-tail-folding=; the option should be of the form\n"
133 " (disabled|all|default|simple)[+(reductions|recurrences"
134 "|reverse|noreductions|norecurrences|noreverse)]\n";
140 void operator=(
const std::string &Val) {
149 setNeedsDefault(
false);
152 StringRef(Val).split(TailFoldTypes,
'+', -1,
false);
154 unsigned StartIdx = 1;
155 if (TailFoldTypes[0] ==
"disabled")
156 setInitialBits(TailFoldingOpts::Disabled);
157 else if (TailFoldTypes[0] ==
"all")
158 setInitialBits(TailFoldingOpts::All);
159 else if (TailFoldTypes[0] ==
"default")
160 setNeedsDefault(
true);
161 else if (TailFoldTypes[0] ==
"simple")
162 setInitialBits(TailFoldingOpts::Simple);
165 setInitialBits(TailFoldingOpts::Disabled);
168 for (
unsigned I = StartIdx;
I < TailFoldTypes.
size();
I++) {
169 if (TailFoldTypes[
I] ==
"reductions")
170 setEnableBit(TailFoldingOpts::Reductions);
171 else if (TailFoldTypes[
I] ==
"recurrences")
172 setEnableBit(TailFoldingOpts::Recurrences);
173 else if (TailFoldTypes[
I] ==
"reverse")
174 setEnableBit(TailFoldingOpts::Reverse);
175 else if (TailFoldTypes[
I] ==
"noreductions")
176 setDisableBit(TailFoldingOpts::Reductions);
177 else if (TailFoldTypes[
I] ==
"norecurrences")
178 setDisableBit(TailFoldingOpts::Recurrences);
179 else if (TailFoldTypes[
I] ==
"noreverse")
180 setDisableBit(TailFoldingOpts::Reverse);
197 "Control the use of vectorisation using tail-folding for SVE where the"
198 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
199 "\ndisabled (Initial) No loop types will vectorize using "
201 "\ndefault (Initial) Uses the default tail-folding settings for "
203 "\nall (Initial) All legal loop types will vectorize using "
205 "\nsimple (Initial) Use tail-folding for simple loops (not "
206 "reductions or recurrences)"
207 "\nreductions Use tail-folding for loops containing reductions"
208 "\nnoreductions Inverse of above"
209 "\nrecurrences Use tail-folding for loops containing fixed order "
211 "\nnorecurrences Inverse of above"
212 "\nreverse Use tail-folding for loops requiring reversed "
214 "\nnoreverse Inverse of above"),
259 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
260 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
261 FeatureStr.
split(Features,
",");
277 return F.hasFnAttribute(
"fmv-features");
287 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
288 CallAttrs.callee().hasStreamingInterfaceOrBody())
293 if (
CallAttrs.callee().hasStreamingBody()) {
303 CallAttrs.requiresPreservingAllZAState()) {
326 auto FVTy = dyn_cast<FixedVectorType>(Ty);
328 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
337 unsigned DefaultCallPenalty)
const {
362 if (
F ==
Call.getCaller())
368 return DefaultCallPenalty;
379 ST->isSVEorStreamingSVEAvailable() &&
380 !ST->disableMaximizeScalableBandwidth();
404 assert(Ty->isIntegerTy());
406 unsigned BitSize = Ty->getPrimitiveSizeInBits();
413 ImmVal = Imm.sext((BitSize + 63) & ~0x3fU);
418 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
424 return std::max<InstructionCost>(1,
Cost);
431 assert(Ty->isIntegerTy());
433 unsigned BitSize = Ty->getPrimitiveSizeInBits();
439 unsigned ImmIdx = ~0U;
443 case Instruction::GetElementPtr:
448 case Instruction::Store:
451 case Instruction::Add:
452 case Instruction::Sub:
453 case Instruction::Mul:
454 case Instruction::UDiv:
455 case Instruction::SDiv:
456 case Instruction::URem:
457 case Instruction::SRem:
458 case Instruction::And:
459 case Instruction::Or:
460 case Instruction::Xor:
461 case Instruction::ICmp:
465 case Instruction::Shl:
466 case Instruction::LShr:
467 case Instruction::AShr:
471 case Instruction::Trunc:
472 case Instruction::ZExt:
473 case Instruction::SExt:
474 case Instruction::IntToPtr:
475 case Instruction::PtrToInt:
476 case Instruction::BitCast:
477 case Instruction::PHI:
478 case Instruction::Call:
479 case Instruction::Select:
480 case Instruction::Ret:
481 case Instruction::Load:
486 int NumConstants = (BitSize + 63) / 64;
499 assert(Ty->isIntegerTy());
501 unsigned BitSize = Ty->getPrimitiveSizeInBits();
510 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
516 case Intrinsic::sadd_with_overflow:
517 case Intrinsic::uadd_with_overflow:
518 case Intrinsic::ssub_with_overflow:
519 case Intrinsic::usub_with_overflow:
520 case Intrinsic::smul_with_overflow:
521 case Intrinsic::umul_with_overflow:
523 int NumConstants = (BitSize + 63) / 64;
530 case Intrinsic::experimental_stackmap:
531 if ((Idx < 2) || (Imm.getBitWidth() <= 64 &&
isInt<64>(Imm.getSExtValue())))
534 case Intrinsic::experimental_patchpoint_void:
535 case Intrinsic::experimental_patchpoint:
536 if ((Idx < 4) || (Imm.getBitWidth() <= 64 &&
isInt<64>(Imm.getSExtValue())))
539 case Intrinsic::experimental_gc_statepoint:
540 if ((Idx < 5) || (Imm.getBitWidth() <= 64 &&
isInt<64>(Imm.getSExtValue())))
550 if (TyWidth == 32 || TyWidth == 64)
559 return ST->getMispredictionPenalty();
580 unsigned TotalHistCnts = 1;
590 unsigned EC = VTy->getElementCount().getKnownMinValue();
595 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
597 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
601 TotalHistCnts = EC / NaturalVectorWidth;
621 switch (ICA.
getID()) {
622 case Intrinsic::experimental_vector_histogram_add: {
629 case Intrinsic::clmul: {
634 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
638 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
643 -1,
nullptr,
nullptr) *
646 -1,
nullptr,
nullptr);
650 if (LT.second.SimpleTy == MVT::nxv2i64)
651 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
654 if (ST->hasSVE2() || ST->hasSME()) {
655 switch (LT.second.SimpleTy) {
670 if (LT.second.SimpleTy == MVT::nxv2i64)
674 switch (LT.second.SimpleTy) {
684 -1,
nullptr,
nullptr) *
687 -1,
nullptr,
nullptr));
696 return LT.first * 11;
698 return LT.first * 14;
705 case Intrinsic::umin:
706 case Intrinsic::umax:
707 case Intrinsic::smin:
708 case Intrinsic::smax: {
709 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
710 MVT::v8i16, MVT::v2i32, MVT::v4i32,
711 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
718 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
719 EVT VT = TLI->getValueType(
DL, RetTy,
true);
720 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
721 return LT.first * (IsSigned ? 5 : 3);
723 if (LT.second == MVT::v2i64)
729 case Intrinsic::scmp:
730 case Intrinsic::ucmp: {
732 {Intrinsic::scmp, MVT::i32, 3},
733 {Intrinsic::scmp, MVT::i64, 3},
734 {Intrinsic::scmp, MVT::v8i8, 3},
735 {Intrinsic::scmp, MVT::v16i8, 3},
736 {Intrinsic::scmp, MVT::v4i16, 3},
737 {Intrinsic::scmp, MVT::v8i16, 3},
738 {Intrinsic::scmp, MVT::v2i32, 3},
739 {Intrinsic::scmp, MVT::v4i32, 3},
740 {Intrinsic::scmp, MVT::v1i64, 3},
741 {Intrinsic::scmp, MVT::v2i64, 3},
747 return Entry->Cost * LT.first;
750 case Intrinsic::sadd_sat:
751 case Intrinsic::ssub_sat:
752 case Intrinsic::uadd_sat:
753 case Intrinsic::usub_sat: {
754 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
755 MVT::v8i16, MVT::v2i32, MVT::v4i32,
761 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
763 return LT.first * Instrs;
768 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
769 return LT.first * Instrs;
773 case Intrinsic::abs: {
774 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
775 MVT::v8i16, MVT::v2i32, MVT::v4i32,
776 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
777 MVT::nxv4i32, MVT::nxv2i64};
783 case Intrinsic::bswap: {
784 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
785 MVT::v4i32, MVT::v2i64};
788 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
793 case Intrinsic::fmuladd: {
798 (EltTy->
isHalfTy() && ST->hasFullFP16()))
802 case Intrinsic::stepvector: {
811 Cost += AddCost * (LT.first - 1);
815 case Intrinsic::vector_extract:
816 case Intrinsic::vector_insert: {
829 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
830 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
838 getTLI()->getTypeConversion(
C, SubVecVT);
840 getTLI()->getTypeConversion(
C, VecVT);
848 case Intrinsic::bitreverse: {
850 {Intrinsic::bitreverse, MVT::i32, 1},
851 {Intrinsic::bitreverse, MVT::i64, 1},
852 {Intrinsic::bitreverse, MVT::v8i8, 1},
853 {Intrinsic::bitreverse, MVT::v16i8, 1},
854 {Intrinsic::bitreverse, MVT::v4i16, 2},
855 {Intrinsic::bitreverse, MVT::v8i16, 2},
856 {Intrinsic::bitreverse, MVT::v2i32, 2},
857 {Intrinsic::bitreverse, MVT::v4i32, 2},
858 {Intrinsic::bitreverse, MVT::v1i64, 2},
859 {Intrinsic::bitreverse, MVT::v2i64, 2},
867 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
868 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
869 return LegalisationCost.first * Entry->Cost + 1;
871 return LegalisationCost.first * Entry->Cost;
875 case Intrinsic::ctpop: {
879 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
882 return LT.first + ExtraCost;
884 if (!ST->hasNEON()) {
914 RetTy->getScalarSizeInBits()
917 return LT.first * Entry->Cost + ExtraCost;
921 case Intrinsic::sadd_with_overflow:
922 case Intrinsic::uadd_with_overflow:
923 case Intrinsic::ssub_with_overflow:
924 case Intrinsic::usub_with_overflow:
925 case Intrinsic::smul_with_overflow:
926 case Intrinsic::umul_with_overflow: {
928 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
929 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
930 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
931 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
932 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
933 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
934 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
935 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
936 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
937 {Intrinsic::usub_with_overflow, MVT::i8, 3},
938 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
939 {Intrinsic::usub_with_overflow, MVT::i16, 3},
940 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
941 {Intrinsic::usub_with_overflow, MVT::i32, 1},
942 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
943 {Intrinsic::usub_with_overflow, MVT::i64, 1},
944 {Intrinsic::smul_with_overflow, MVT::i8, 5},
945 {Intrinsic::umul_with_overflow, MVT::i8, 4},
946 {Intrinsic::smul_with_overflow, MVT::i16, 5},
947 {Intrinsic::umul_with_overflow, MVT::i16, 4},
948 {Intrinsic::smul_with_overflow, MVT::i32, 2},
949 {Intrinsic::umul_with_overflow, MVT::i32, 2},
950 {Intrinsic::smul_with_overflow, MVT::i64, 3},
951 {Intrinsic::umul_with_overflow, MVT::i64, 3},
953 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
960 case Intrinsic::fptosi_sat:
961 case Intrinsic::fptoui_sat: {
964 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
966 EVT MTy = TLI->getValueType(
DL, RetTy);
969 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
970 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
971 LT.second == MVT::v2f64)) {
973 (LT.second == MVT::f64 && MTy == MVT::i32) ||
974 (LT.second == MVT::f32 && MTy == MVT::i64)))
983 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
990 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
991 (LT.second == MVT::f16 && MTy == MVT::i64) ||
992 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1006 if ((LT.second.getScalarType() == MVT::f32 ||
1007 LT.second.getScalarType() == MVT::f64 ||
1008 LT.second.getScalarType() == MVT::f16) &&
1011 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1012 if (LT.second.isVector())
1013 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1017 LegalTy, {LegalTy, LegalTy});
1021 LegalTy, {LegalTy, LegalTy});
1023 return LT.first *
Cost +
1024 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1030 RetTy = RetTy->getScalarType();
1031 if (LT.second.isVector()) {
1049 return LT.first *
Cost;
1051 case Intrinsic::fshl:
1052 case Intrinsic::fshr: {
1061 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1062 (RetTy->getPrimitiveSizeInBits() == 32 ||
1063 RetTy->getPrimitiveSizeInBits() == 64)) {
1076 {Intrinsic::fshl, MVT::v4i32, 2},
1077 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1078 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1079 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1085 return LegalisationCost.first * Entry->Cost;
1089 if (!RetTy->isIntegerTy())
1094 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1095 RetTy->getScalarSizeInBits() < 64) ||
1096 (RetTy->getScalarSizeInBits() % 64 != 0);
1097 unsigned ExtraCost = HigherCost ? 1 : 0;
1098 if (RetTy->getScalarSizeInBits() == 32 ||
1099 RetTy->getScalarSizeInBits() == 64)
1102 else if (HigherCost)
1106 return TyL.first + ExtraCost;
1108 case Intrinsic::get_active_lane_mask: {
1110 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1112 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1115 if (RetTy->isScalableTy()) {
1116 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1126 if (ST->hasSVE2p1() || ST->hasSME2()) {
1138 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1141 return Cost + (SplitCost * (
Cost - 1));
1156 case Intrinsic::experimental_vector_match: {
1159 unsigned SearchSize = NeedleTy->getNumElements();
1160 auto IsSupportedTypeAndSearchSize = [&]() {
1161 if (SearchVT == MVT::nxv8i16 || SearchVT == MVT::v8i16)
1162 return SearchSize == 8;
1164 if (SearchVT == MVT::nxv16i8 || SearchVT == MVT::v16i8 ||
1165 SearchVT == MVT::v8i8)
1166 return SearchSize == 8 || SearchSize == 16;
1171 if (!ST->hasSVE2() || !ST->isSVEAvailable() ||
1172 !IsSupportedTypeAndSearchSize())
1185 case Intrinsic::cttz: {
1187 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1188 return LT.first * 2;
1189 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1190 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1191 return LT.first * 3;
1194 case Intrinsic::experimental_cttz_elts: {
1196 if (!getTLI()->shouldExpandCttzElements(ArgVT)) {
1204 case Intrinsic::loop_dependence_raw_mask:
1205 case Intrinsic::loop_dependence_war_mask: {
1207 if (ST->hasSVE2() || ST->hasSME()) {
1208 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1209 unsigned EltSizeInBytes =
1219 case Intrinsic::experimental_vector_extract_last_active:
1220 if (ST->isSVEorStreamingSVEAvailable()) {
1226 case Intrinsic::pow: {
1229 EVT VT = getTLI()->getValueType(
DL, RetTy);
1230 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1231 bool HasLibcall = getTLI()->getLibcallImpl(LC) != RTLIB::Unsupported;
1246 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1247 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1257 return (Sqrt * 2) +
FMul;
1268 case Intrinsic::sqrt:
1269 case Intrinsic::fabs:
1270 case Intrinsic::ceil:
1271 case Intrinsic::floor:
1272 case Intrinsic::nearbyint:
1273 case Intrinsic::round:
1274 case Intrinsic::rint:
1275 case Intrinsic::roundeven:
1276 case Intrinsic::trunc:
1277 case Intrinsic::minnum:
1278 case Intrinsic::maxnum:
1279 case Intrinsic::minimum:
1280 case Intrinsic::maximum: {
1298 auto RequiredType =
II.getType();
1301 assert(PN &&
"Expected Phi Node!");
1304 if (!PN->hasOneUse())
1305 return std::nullopt;
1307 for (
Value *IncValPhi : PN->incoming_values()) {
1310 Reinterpret->getIntrinsicID() !=
1311 Intrinsic::aarch64_sve_convert_to_svbool ||
1312 RequiredType != Reinterpret->getArgOperand(0)->getType())
1313 return std::nullopt;
1321 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1323 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1396 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1401 return GoverningPredicateIdx;
1406 GoverningPredicateIdx = Index;
1428 return UndefIntrinsic;
1433 UndefIntrinsic = IID;
1460 return CmpPredicate;
1465 CmpPredicate = Pred;
1481 return ResultLanes == InactiveLanesTakenFromOperand;
1486 return OperandIdxForInactiveLanes;
1490 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1491 ResultLanes = InactiveLanesTakenFromOperand;
1492 OperandIdxForInactiveLanes = Index;
1497 return ResultLanes == InactiveLanesAreNotDefined;
1501 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1502 ResultLanes = InactiveLanesAreNotDefined;
1507 return ResultLanes == InactiveLanesAreUnused;
1511 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1512 ResultLanes = InactiveLanesAreUnused;
1522 ResultIsZeroInitialized =
true;
1533 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1538 return OperandIdxWithNoActiveLanes;
1543 OperandIdxWithNoActiveLanes = Index;
1548 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1551 unsigned IROpcode = 0;
1554 enum PredicationStyle {
1556 InactiveLanesTakenFromOperand,
1557 InactiveLanesAreNotDefined,
1558 InactiveLanesAreUnused
1561 bool ResultIsZeroInitialized =
false;
1562 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1563 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1571 return !isa<ScalableVectorType>(V->getType());
1579 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1580 case Intrinsic::aarch64_sve_fcvt_f16f32:
1581 case Intrinsic::aarch64_sve_fcvt_f16f64:
1582 case Intrinsic::aarch64_sve_fcvt_f32f16:
1583 case Intrinsic::aarch64_sve_fcvt_f32f64:
1584 case Intrinsic::aarch64_sve_fcvt_f64f16:
1585 case Intrinsic::aarch64_sve_fcvt_f64f32:
1586 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1587 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1588 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1589 case Intrinsic::aarch64_sve_fcvtzs:
1590 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1591 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1592 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1593 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1594 case Intrinsic::aarch64_sve_fcvtzu:
1595 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1596 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1597 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1598 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1599 case Intrinsic::aarch64_sve_revb:
1600 case Intrinsic::aarch64_sve_revh:
1601 case Intrinsic::aarch64_sve_revw:
1602 case Intrinsic::aarch64_sve_revd:
1603 case Intrinsic::aarch64_sve_scvtf:
1604 case Intrinsic::aarch64_sve_scvtf_f16i32:
1605 case Intrinsic::aarch64_sve_scvtf_f16i64:
1606 case Intrinsic::aarch64_sve_scvtf_f32i64:
1607 case Intrinsic::aarch64_sve_scvtf_f64i32:
1608 case Intrinsic::aarch64_sve_ucvtf:
1609 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1610 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1611 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1612 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1615 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1616 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1617 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1618 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1621 case Intrinsic::aarch64_sve_fabd:
1623 case Intrinsic::aarch64_sve_fadd:
1626 case Intrinsic::aarch64_sve_fdiv:
1629 case Intrinsic::aarch64_sve_fmax:
1631 case Intrinsic::aarch64_sve_fmaxnm:
1633 case Intrinsic::aarch64_sve_fmin:
1635 case Intrinsic::aarch64_sve_fminnm:
1637 case Intrinsic::aarch64_sve_fmla:
1639 case Intrinsic::aarch64_sve_fmls:
1641 case Intrinsic::aarch64_sve_fmul:
1644 case Intrinsic::aarch64_sve_fmulx:
1646 case Intrinsic::aarch64_sve_fnmla:
1648 case Intrinsic::aarch64_sve_fnmls:
1650 case Intrinsic::aarch64_sve_fsub:
1653 case Intrinsic::aarch64_sve_add:
1656 case Intrinsic::aarch64_sve_mla:
1658 case Intrinsic::aarch64_sve_mls:
1660 case Intrinsic::aarch64_sve_mul:
1663 case Intrinsic::aarch64_sve_sabd:
1665 case Intrinsic::aarch64_sve_sdiv:
1668 case Intrinsic::aarch64_sve_smax:
1670 case Intrinsic::aarch64_sve_smin:
1672 case Intrinsic::aarch64_sve_smulh:
1674 case Intrinsic::aarch64_sve_sub:
1677 case Intrinsic::aarch64_sve_uabd:
1679 case Intrinsic::aarch64_sve_udiv:
1682 case Intrinsic::aarch64_sve_umax:
1684 case Intrinsic::aarch64_sve_umin:
1686 case Intrinsic::aarch64_sve_umulh:
1688 case Intrinsic::aarch64_sve_asr:
1691 case Intrinsic::aarch64_sve_lsl:
1694 case Intrinsic::aarch64_sve_lsr:
1697 case Intrinsic::aarch64_sve_and:
1700 case Intrinsic::aarch64_sve_bic:
1702 case Intrinsic::aarch64_sve_eor:
1705 case Intrinsic::aarch64_sve_orr:
1708 case Intrinsic::aarch64_sve_shsub:
1710 case Intrinsic::aarch64_sve_shsubr:
1712 case Intrinsic::aarch64_sve_sqrshl:
1714 case Intrinsic::aarch64_sve_sqshl:
1716 case Intrinsic::aarch64_sve_sqsub:
1718 case Intrinsic::aarch64_sve_srshl:
1720 case Intrinsic::aarch64_sve_uhsub:
1722 case Intrinsic::aarch64_sve_uhsubr:
1724 case Intrinsic::aarch64_sve_uqrshl:
1726 case Intrinsic::aarch64_sve_uqshl:
1728 case Intrinsic::aarch64_sve_uqsub:
1730 case Intrinsic::aarch64_sve_urshl:
1733 case Intrinsic::aarch64_sve_add_u:
1736 case Intrinsic::aarch64_sve_and_u:
1739 case Intrinsic::aarch64_sve_asr_u:
1742 case Intrinsic::aarch64_sve_eor_u:
1745 case Intrinsic::aarch64_sve_fadd_u:
1748 case Intrinsic::aarch64_sve_fdiv_u:
1751 case Intrinsic::aarch64_sve_fmul_u:
1754 case Intrinsic::aarch64_sve_fsub_u:
1757 case Intrinsic::aarch64_sve_lsl_u:
1760 case Intrinsic::aarch64_sve_lsr_u:
1763 case Intrinsic::aarch64_sve_mul_u:
1766 case Intrinsic::aarch64_sve_orr_u:
1769 case Intrinsic::aarch64_sve_sdiv_u:
1772 case Intrinsic::aarch64_sve_sub_u:
1775 case Intrinsic::aarch64_sve_udiv_u:
1779 case Intrinsic::aarch64_sve_addqv:
1780 case Intrinsic::aarch64_sve_bic_z:
1781 case Intrinsic::aarch64_sve_brka_z:
1782 case Intrinsic::aarch64_sve_brkb_z:
1783 case Intrinsic::aarch64_sve_brkn_z:
1784 case Intrinsic::aarch64_sve_brkpa_z:
1785 case Intrinsic::aarch64_sve_brkpb_z:
1786 case Intrinsic::aarch64_sve_cntp:
1787 case Intrinsic::aarch64_sve_compact:
1788 case Intrinsic::aarch64_sve_eorv:
1789 case Intrinsic::aarch64_sve_eorqv:
1790 case Intrinsic::aarch64_sve_nand_z:
1791 case Intrinsic::aarch64_sve_nor_z:
1792 case Intrinsic::aarch64_sve_orn_z:
1793 case Intrinsic::aarch64_sve_orv:
1794 case Intrinsic::aarch64_sve_orqv:
1795 case Intrinsic::aarch64_sve_pnext:
1796 case Intrinsic::aarch64_sve_rdffr_z:
1797 case Intrinsic::aarch64_sve_saddv:
1798 case Intrinsic::aarch64_sve_uaddv:
1799 case Intrinsic::aarch64_sve_umaxv:
1800 case Intrinsic::aarch64_sve_umaxqv:
1801 case Intrinsic::aarch64_sve_facge:
1802 case Intrinsic::aarch64_sve_facgt:
1803 case Intrinsic::aarch64_sve_ld1:
1804 case Intrinsic::aarch64_sve_ld1_gather:
1805 case Intrinsic::aarch64_sve_ld1_gather_index:
1806 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1807 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1808 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1809 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1810 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1811 case Intrinsic::aarch64_sve_ld1q_gather_index:
1812 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1813 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1814 case Intrinsic::aarch64_sve_ld1ro:
1815 case Intrinsic::aarch64_sve_ld1rq:
1816 case Intrinsic::aarch64_sve_ld1udq:
1817 case Intrinsic::aarch64_sve_ld1uwq:
1818 case Intrinsic::aarch64_sve_ld2_sret:
1819 case Intrinsic::aarch64_sve_ld2q_sret:
1820 case Intrinsic::aarch64_sve_ld3_sret:
1821 case Intrinsic::aarch64_sve_ld3q_sret:
1822 case Intrinsic::aarch64_sve_ld4_sret:
1823 case Intrinsic::aarch64_sve_ld4q_sret:
1824 case Intrinsic::aarch64_sve_ldff1:
1825 case Intrinsic::aarch64_sve_ldff1_gather:
1826 case Intrinsic::aarch64_sve_ldff1_gather_index:
1827 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1828 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1829 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1830 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1831 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1832 case Intrinsic::aarch64_sve_ldnf1:
1833 case Intrinsic::aarch64_sve_ldnt1:
1834 case Intrinsic::aarch64_sve_ldnt1_gather:
1835 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1836 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1837 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1840 case Intrinsic::aarch64_sve_and_z:
1843 case Intrinsic::aarch64_sve_orr_z:
1846 case Intrinsic::aarch64_sve_eor_z:
1850 case Intrinsic::aarch64_sve_cmpeq:
1851 case Intrinsic::aarch64_sve_cmpeq_wide:
1854 case Intrinsic::aarch64_sve_cmpge:
1855 case Intrinsic::aarch64_sve_cmpge_wide:
1858 case Intrinsic::aarch64_sve_cmpgt:
1859 case Intrinsic::aarch64_sve_cmpgt_wide:
1862 case Intrinsic::aarch64_sve_cmphi:
1863 case Intrinsic::aarch64_sve_cmphi_wide:
1866 case Intrinsic::aarch64_sve_cmphs:
1867 case Intrinsic::aarch64_sve_cmphs_wide:
1870 case Intrinsic::aarch64_sve_cmple_wide:
1873 case Intrinsic::aarch64_sve_cmplo_wide:
1876 case Intrinsic::aarch64_sve_cmpls_wide:
1879 case Intrinsic::aarch64_sve_cmplt_wide:
1882 case Intrinsic::aarch64_sve_cmpne:
1883 case Intrinsic::aarch64_sve_cmpne_wide:
1886 case Intrinsic::aarch64_sve_fcmpeq:
1889 case Intrinsic::aarch64_sve_fcmpge:
1892 case Intrinsic::aarch64_sve_fcmpgt:
1895 case Intrinsic::aarch64_sve_fcmpne:
1898 case Intrinsic::aarch64_sve_fcmpuo:
1902 case Intrinsic::aarch64_sve_prf:
1903 case Intrinsic::aarch64_sve_prfb_gather_index:
1904 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
1905 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
1906 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
1907 case Intrinsic::aarch64_sve_prfd_gather_index:
1908 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
1909 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
1910 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
1911 case Intrinsic::aarch64_sve_prfh_gather_index:
1912 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
1913 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
1914 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
1915 case Intrinsic::aarch64_sve_prfw_gather_index:
1916 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
1917 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
1918 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
1921 case Intrinsic::aarch64_sve_st1_scatter:
1922 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
1923 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
1924 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
1925 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
1926 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
1927 case Intrinsic::aarch64_sve_st1dq:
1928 case Intrinsic::aarch64_sve_st1q_scatter_index:
1929 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
1930 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
1931 case Intrinsic::aarch64_sve_st1wq:
1932 case Intrinsic::aarch64_sve_stnt1:
1933 case Intrinsic::aarch64_sve_stnt1_scatter:
1934 case Intrinsic::aarch64_sve_stnt1_scatter_index:
1935 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
1936 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
1938 case Intrinsic::aarch64_sve_st2:
1939 case Intrinsic::aarch64_sve_st2q:
1941 case Intrinsic::aarch64_sve_st3:
1942 case Intrinsic::aarch64_sve_st3q:
1944 case Intrinsic::aarch64_sve_st4:
1945 case Intrinsic::aarch64_sve_st4q:
1953 Value *UncastedPred;
1959 Pred = UncastedPred;
1965 if (OrigPredTy->getMinNumElements() <=
1967 ->getMinNumElements())
1968 Pred = UncastedPred;
1972 return C &&
C->isAllOnesValue();
1979 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
1980 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
1988static std::optional<Instruction *>
1995 Value *Op1 =
II.getOperand(1);
1996 Value *Op2 =
II.getOperand(2);
2022 return std::nullopt;
2033 if (SimpleII == Inactive)
2041static std::optional<Instruction *>
2045 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2046 "Expected a compare operation!");
2053 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2054 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2055 "Unexpected wide compare!");
2071 const APInt *LHSVal, *RHSVal;
2073 return std::nullopt;
2096 return std::nullopt;
2110static std::optional<Instruction *>
2114 return std::nullopt;
2143 II.setCalledFunction(NewDecl);
2149 return std::nullopt;
2160 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2163 return std::nullopt;
2175static std::optional<Instruction *>
2177 auto m_ConvertToSVBool = [](
auto P) {
2181 Intrinsic::aarch64_sve_convert_from_svbool;
2204 return std::nullopt;
2208 case Intrinsic::aarch64_sve_and_z:
2209 case Intrinsic::aarch64_sve_bic_z:
2210 case Intrinsic::aarch64_sve_eor_z:
2211 case Intrinsic::aarch64_sve_nand_z:
2212 case Intrinsic::aarch64_sve_nor_z:
2213 case Intrinsic::aarch64_sve_orn_z:
2214 case Intrinsic::aarch64_sve_orr_z:
2217 return std::nullopt;
2220 Value *BinOpPred = BinOp->getOperand(0);
2221 Value *BinOpOp1 = BinOp->getOperand(1);
2222 Value *BinOpOp2 = BinOp->getOperand(2);
2224 Value *NarrowBinOpPred;
2226 return std::nullopt;
2228 Value *NarrowBinOpOp1 =
2230 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2231 if (BinOpOp1 != BinOpOp2)
2235 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2239static std::optional<Instruction *>
2246 return BinOpCombine;
2251 return std::nullopt;
2254 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2263 if (CursorVTy->getElementCount().getKnownMinValue() <
2264 IVTy->getElementCount().getKnownMinValue())
2268 if (Cursor->getType() == IVTy)
2269 EarliestReplacement = Cursor;
2274 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2275 Intrinsic::aarch64_sve_convert_to_svbool ||
2276 IntrinsicCursor->getIntrinsicID() ==
2277 Intrinsic::aarch64_sve_convert_from_svbool))
2280 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2281 Cursor = IntrinsicCursor->getOperand(0);
2286 if (!EarliestReplacement)
2287 return std::nullopt;
2295 auto *OpPredicate =
II.getOperand(0);
2312 II.getArgOperand(2));
2318 return std::nullopt;
2322 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2331 II.getArgOperand(0));
2340 if (!
II.hasOneUse())
2341 return std::nullopt;
2344 return std::nullopt;
2347 switch (
II.getIntrinsicID()) {
2348 case Intrinsic::aarch64_sve_cmpne:
2349 IID = Intrinsic::aarch64_sve_cmpeq;
2351 case Intrinsic::aarch64_sve_cmpne_wide:
2352 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2354 case Intrinsic::aarch64_sve_cmpeq:
2355 IID = Intrinsic::aarch64_sve_cmpne;
2357 case Intrinsic::aarch64_sve_cmpeq_wide:
2358 IID = Intrinsic::aarch64_sve_cmpne_wide;
2361 return std::nullopt;
2366 IID,
II.getOperand(1)->getType(),
2367 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2379 return std::nullopt;
2381 for (
auto *U :
II.users()) {
2384 Type *Ty =
II.getOperand(1)->getType();
2389 Intrinsic::aarch64_sve_umin, Ty,
2390 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2396 return std::nullopt;
2410 return std::nullopt;
2415 if (!SplatValue || !SplatValue->isZero())
2416 return std::nullopt;
2421 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2422 return std::nullopt;
2426 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2427 return std::nullopt;
2430 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2431 return std::nullopt;
2436 return std::nullopt;
2439 return std::nullopt;
2443 return std::nullopt;
2447 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2448 return std::nullopt;
2450 unsigned NumElts = VecTy->getNumElements();
2451 unsigned PredicateBits = 0;
2454 for (
unsigned I = 0;
I < NumElts; ++
I) {
2457 return std::nullopt;
2459 PredicateBits |= 1 << (
I * (16 / NumElts));
2463 if (PredicateBits == 0) {
2465 PFalse->takeName(&
II);
2471 for (
unsigned I = 0;
I < 16; ++
I)
2472 if ((PredicateBits & (1 <<
I)) != 0)
2475 unsigned PredSize = Mask & -Mask;
2480 for (
unsigned I = 0;
I < 16;
I += PredSize)
2481 if ((PredicateBits & (1 <<
I)) == 0)
2482 return std::nullopt;
2484 auto *ConvertToSVBool =
2487 auto *ConvertFromSVBool =
2489 II.getType(), ConvertToSVBool);
2497 Value *Pg =
II.getArgOperand(0);
2498 Value *Vec =
II.getArgOperand(1);
2499 auto IntrinsicID =
II.getIntrinsicID();
2500 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2512 auto OpC = OldBinOp->getOpcode();
2518 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2524 if (IsAfter &&
C &&
C->isNullValue()) {
2528 Extract->insertBefore(
II.getIterator());
2529 Extract->takeName(&
II);
2535 return std::nullopt;
2537 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2538 return std::nullopt;
2540 const auto PTruePattern =
2546 return std::nullopt;
2548 unsigned Idx = MinNumElts - 1;
2558 if (Idx >= PgVTy->getMinNumElements())
2559 return std::nullopt;
2564 Extract->insertBefore(
II.getIterator());
2565 Extract->takeName(&
II);
2578 Value *Pg =
II.getArgOperand(0);
2580 Value *Vec =
II.getArgOperand(2);
2583 if (!Ty->isIntegerTy())
2584 return std::nullopt;
2589 return std::nullopt;
2606 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2621static std::optional<Instruction *>
2625 if (
Pattern == AArch64SVEPredPattern::all) {
2634 return MinNumElts && NumElts >= MinNumElts
2636 II, ConstantInt::get(
II.getType(), MinNumElts)))
2640static std::optional<Instruction *>
2643 if (!ST->isStreaming())
2644 return std::nullopt;
2656 Value *PgVal =
II.getArgOperand(0);
2657 Value *OpVal =
II.getArgOperand(1);
2661 if (PgVal == OpVal &&
2662 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2663 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2678 return std::nullopt;
2682 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2683 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2697 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2698 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2699 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2700 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2701 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2702 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2703 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2704 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2705 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2706 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2707 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2708 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2709 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2719 return std::nullopt;
2722template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2723static std::optional<Instruction *>
2725 bool MergeIntoAddendOp) {
2727 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2728 if (MergeIntoAddendOp) {
2729 AddendOp =
II.getOperand(1);
2730 Mul =
II.getOperand(2);
2732 AddendOp =
II.getOperand(2);
2733 Mul =
II.getOperand(1);
2738 return std::nullopt;
2740 if (!
Mul->hasOneUse())
2741 return std::nullopt;
2744 if (
II.getType()->isFPOrFPVectorTy()) {
2749 return std::nullopt;
2751 return std::nullopt;
2756 if (MergeIntoAddendOp)
2766static std::optional<Instruction *>
2768 Value *Pred =
II.getOperand(0);
2769 Value *PtrOp =
II.getOperand(1);
2770 Type *VecTy =
II.getType();
2785static std::optional<Instruction *>
2787 Value *VecOp =
II.getOperand(0);
2788 Value *Pred =
II.getOperand(1);
2789 Value *PtrOp =
II.getOperand(2);
2805 case Intrinsic::aarch64_sve_fmul_u:
2806 return Instruction::BinaryOps::FMul;
2807 case Intrinsic::aarch64_sve_fadd_u:
2808 return Instruction::BinaryOps::FAdd;
2809 case Intrinsic::aarch64_sve_fsub_u:
2810 return Instruction::BinaryOps::FSub;
2812 return Instruction::BinaryOpsEnd;
2816static std::optional<Instruction *>
2819 if (
II.isStrictFP())
2820 return std::nullopt;
2822 auto *OpPredicate =
II.getOperand(0);
2824 if (BinOpCode == Instruction::BinaryOpsEnd ||
2826 return std::nullopt;
2828 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
2832static std::optional<Instruction *>
2834 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
2835 "Expected MLA_U intrinsic");
2836 Value *Acc =
II.getArgOperand(1);
2837 Value *MulOp0 =
II.getArgOperand(2);
2838 Value *MulOp1 =
II.getArgOperand(3);
2853 II.setArgOperand(2, MulOp1);
2854 II.setArgOperand(3, MulOp0);
2858 return std::nullopt;
2861static std::optional<Instruction *>
2863 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
2864 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
2865 "Expected SADALP or UADALP intrinsic");
2871 return std::nullopt;
2875 return std::nullopt;
2879 II.getIntrinsicID(), {II.getType()},
2880 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
2890 Intrinsic::aarch64_sve_mla>(
2894 Intrinsic::aarch64_sve_mad>(
2897 return std::nullopt;
2900static std::optional<Instruction *>
2904 Intrinsic::aarch64_sve_fmla>(IC,
II,
2909 Intrinsic::aarch64_sve_fmad>(IC,
II,
2914 Intrinsic::aarch64_sve_fmla>(IC,
II,
2917 return std::nullopt;
2920static std::optional<Instruction *>
2924 Intrinsic::aarch64_sve_fmla>(IC,
II,
2929 Intrinsic::aarch64_sve_fmad>(IC,
II,
2934 Intrinsic::aarch64_sve_fmla_u>(
2940static std::optional<Instruction *>
2944 Intrinsic::aarch64_sve_fmls>(IC,
II,
2949 Intrinsic::aarch64_sve_fnmsb>(
2954 Intrinsic::aarch64_sve_fmls>(IC,
II,
2957 return std::nullopt;
2960static std::optional<Instruction *>
2964 Intrinsic::aarch64_sve_fmls>(IC,
II,
2969 Intrinsic::aarch64_sve_fnmsb>(
2974 Intrinsic::aarch64_sve_fmls_u>(
2983 Intrinsic::aarch64_sve_mls>(
2986 return std::nullopt;
2991 Value *UnpackArg =
II.getArgOperand(0);
2993 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
2994 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3007 return std::nullopt;
3011 auto *OpVal =
II.getOperand(0);
3012 auto *OpIndices =
II.getOperand(1);
3019 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3020 return std::nullopt;
3035 Type *RetTy =
II.getType();
3036 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3037 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3041 if ((
match(
II.getArgOperand(0),
3048 if (TyA ==
B->getType() &&
3053 TyA->getMinNumElements());
3059 return std::nullopt;
3067 if (
match(
II.getArgOperand(0),
3072 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3074 return std::nullopt;
3077static std::optional<Instruction *>
3079 Value *Mask =
II.getOperand(0);
3080 Value *BasePtr =
II.getOperand(1);
3081 Value *Index =
II.getOperand(2);
3092 BasePtr->getPointerAlignment(
II.getDataLayout());
3095 BasePtr, IndexBase);
3102 return std::nullopt;
3105static std::optional<Instruction *>
3107 Value *Val =
II.getOperand(0);
3108 Value *Mask =
II.getOperand(1);
3109 Value *BasePtr =
II.getOperand(2);
3110 Value *Index =
II.getOperand(3);
3120 BasePtr->getPointerAlignment(
II.getDataLayout());
3123 BasePtr, IndexBase);
3129 return std::nullopt;
3135 Value *Pred =
II.getOperand(0);
3136 Value *Vec =
II.getOperand(1);
3137 Value *DivVec =
II.getOperand(2);
3141 if (!SplatConstantInt)
3142 return std::nullopt;
3146 if (DivisorValue == -1)
3147 return std::nullopt;
3148 if (DivisorValue == 1)
3154 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3161 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3163 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3167 return std::nullopt;
3171 size_t VecSize = Vec.
size();
3176 size_t HalfVecSize = VecSize / 2;
3180 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3188 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3206 return std::nullopt;
3213 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3214 CurrentInsertElt = InsertElt->getOperand(0);
3220 return std::nullopt;
3224 for (
size_t I = 0;
I < Elts.
size();
I++) {
3225 if (Elts[
I] ==
nullptr)
3230 if (InsertEltChain ==
nullptr)
3231 return std::nullopt;
3237 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3238 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3239 IIScalableTy->getMinNumElements() /
3244 auto *WideShuffleMaskTy =
3255 auto NarrowBitcast =
3268 return std::nullopt;
3273 Value *Pred =
II.getOperand(0);
3274 Value *Vec =
II.getOperand(1);
3275 Value *Shift =
II.getOperand(2);
3278 Value *AbsPred, *MergedValue;
3284 return std::nullopt;
3292 return std::nullopt;
3297 return std::nullopt;
3300 {
II.getType()}, {Pred, Vec, Shift});
3307 Value *Vec =
II.getOperand(0);
3312 return std::nullopt;
3318 auto *NI =
II.getNextNode();
3321 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3323 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3324 auto *NIBB = NI->getParent();
3325 NI = NI->getNextNode();
3327 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3328 NI = &*SuccBB->getFirstNonPHIOrDbgOrLifetime();
3334 if (NextII &&
II.isIdenticalTo(NextII))
3337 return std::nullopt;
3345 {II.getType(), II.getOperand(0)->getType()},
3346 {II.getOperand(0), II.getOperand(1)}));
3353 if (PredPattern == AArch64SVEPredPattern::all ||
3354 PredPattern == AArch64SVEPredPattern::pow2)
3356 return std::nullopt;
3362 Value *Passthru =
II.getOperand(0);
3370 auto *Mask = ConstantInt::get(Ty, MaskValue);
3376 return std::nullopt;
3379static std::optional<Instruction *>
3386 return std::nullopt;
3392 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3402 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3412 return std::nullopt;
3418 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3426 return std::nullopt;
3429 II.getType(), {Pg, A, B});
3431 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3440 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3445 Value *
A, *PgLHS, *PgRHS;
3451 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3452 return std::nullopt;
3455 if (ConstB > ConstA)
3461 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3462 return std::nullopt;
3464 Type *VecTy =
A->getType();
3468 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3475std::optional<Instruction *>
3486 case Intrinsic::aarch64_dmb:
3488 case Intrinsic::aarch64_neon_fmaxnm:
3489 case Intrinsic::aarch64_neon_fminnm:
3491 case Intrinsic::aarch64_sve_convert_from_svbool:
3493 case Intrinsic::aarch64_sve_dup:
3495 case Intrinsic::aarch64_sve_dup_x:
3497 case Intrinsic::aarch64_sve_cmpeq:
3498 case Intrinsic::aarch64_sve_cmpeq_wide:
3500 case Intrinsic::aarch64_sve_cmpne:
3501 case Intrinsic::aarch64_sve_cmpne_wide:
3503 case Intrinsic::aarch64_sve_rdffr:
3505 case Intrinsic::aarch64_sve_lasta:
3506 case Intrinsic::aarch64_sve_lastb:
3508 case Intrinsic::aarch64_sve_clasta_n:
3509 case Intrinsic::aarch64_sve_clastb_n:
3511 case Intrinsic::aarch64_sve_cntd:
3513 case Intrinsic::aarch64_sve_cntw:
3515 case Intrinsic::aarch64_sve_cnth:
3517 case Intrinsic::aarch64_sve_cntb:
3519 case Intrinsic::aarch64_sme_cntsd:
3521 case Intrinsic::aarch64_sve_ptest_any:
3522 case Intrinsic::aarch64_sve_ptest_first:
3523 case Intrinsic::aarch64_sve_ptest_last:
3525 case Intrinsic::aarch64_sve_fadd:
3527 case Intrinsic::aarch64_sve_fadd_u:
3529 case Intrinsic::aarch64_sve_fmul_u:
3531 case Intrinsic::aarch64_sve_fsub:
3533 case Intrinsic::aarch64_sve_fsub_u:
3535 case Intrinsic::aarch64_sve_add:
3537 case Intrinsic::aarch64_sve_add_u:
3539 Intrinsic::aarch64_sve_mla_u>(
3541 case Intrinsic::aarch64_sve_mla_u:
3543 case Intrinsic::aarch64_sve_sadalp:
3544 case Intrinsic::aarch64_sve_uadalp:
3546 case Intrinsic::aarch64_sve_sub:
3548 case Intrinsic::aarch64_sve_sub_u:
3550 Intrinsic::aarch64_sve_mls_u>(
3552 case Intrinsic::aarch64_sve_tbl:
3554 case Intrinsic::aarch64_sve_uunpkhi:
3555 case Intrinsic::aarch64_sve_uunpklo:
3556 case Intrinsic::aarch64_sve_sunpkhi:
3557 case Intrinsic::aarch64_sve_sunpklo:
3559 case Intrinsic::aarch64_sve_uzp1:
3561 case Intrinsic::aarch64_sve_zip1:
3562 case Intrinsic::aarch64_sve_zip2:
3564 case Intrinsic::aarch64_sve_ld1_gather_index:
3566 case Intrinsic::aarch64_sve_st1_scatter_index:
3568 case Intrinsic::aarch64_sve_ld1:
3570 case Intrinsic::aarch64_sve_st1:
3572 case Intrinsic::aarch64_sve_sdiv:
3574 case Intrinsic::aarch64_sve_sel:
3576 case Intrinsic::aarch64_sve_srshl:
3578 case Intrinsic::aarch64_sve_dupq_lane:
3580 case Intrinsic::aarch64_sve_insr:
3582 case Intrinsic::aarch64_sve_whilelo:
3584 case Intrinsic::aarch64_sve_ptrue:
3586 case Intrinsic::aarch64_sve_uxtb:
3588 case Intrinsic::aarch64_sve_uxth:
3590 case Intrinsic::aarch64_sve_uxtw:
3592 case Intrinsic::aarch64_sme_in_streaming_mode:
3594 case Intrinsic::aarch64_sve_umin_u:
3596 case Intrinsic::aarch64_sve_orr_u:
3598 case Intrinsic::aarch64_sve_and_z:
3602 return std::nullopt;
3609 SimplifyAndSetOp)
const {
3610 switch (
II.getIntrinsicID()) {
3613 case Intrinsic::aarch64_neon_fcvtxn:
3614 case Intrinsic::aarch64_neon_rshrn:
3615 case Intrinsic::aarch64_neon_sqrshrn:
3616 case Intrinsic::aarch64_neon_sqrshrun:
3617 case Intrinsic::aarch64_neon_sqshrn:
3618 case Intrinsic::aarch64_neon_sqshrun:
3619 case Intrinsic::aarch64_neon_sqxtn:
3620 case Intrinsic::aarch64_neon_sqxtun:
3621 case Intrinsic::aarch64_neon_uqrshrn:
3622 case Intrinsic::aarch64_neon_uqshrn:
3623 case Intrinsic::aarch64_neon_uqxtn:
3624 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3628 return std::nullopt;
3632 return ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3642 if (ST->useSVEForFixedLengthVectors() &&
3645 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3646 else if (ST->isNeonAvailable())
3651 if (ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3660bool AArch64TTIImpl::isSingleExtWideningInstruction(
3662 Type *SrcOverrideTy)
const {
3677 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3680 Type *SrcTy = SrcOverrideTy;
3682 case Instruction::Add:
3683 case Instruction::Sub: {
3692 if (Opcode == Instruction::Sub)
3716 assert(SrcTy &&
"Expected some SrcTy");
3718 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3724 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3726 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3730 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3733Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3735 Type *SrcOverrideTy)
const {
3736 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3737 Opcode != Instruction::Mul)
3747 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3750 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3756 ->getScalarSizeInBits();
3759 unsigned MaxEltSize = 0;
3762 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3763 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3764 MaxEltSize = std::max(EltSize0, EltSize1);
3767 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3768 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3771 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3773 MaxEltSize = DstEltSize / 2;
3774 }
else if (Opcode == Instruction::Mul &&
3782 Known.Zero.countLeadingOnes() >
3787 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3791 if (MaxEltSize * 2 > DstEltSize)
3809 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
3810 (Src->isScalableTy() && !ST->hasSVE2()))
3820 if (AddUser && AddUser->getOpcode() == Instruction::Add)
3824 if (!Shr || Shr->getOpcode() != Instruction::LShr)
3828 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
3829 Src->getScalarSizeInBits() !=
3853 int ISD = TLI->InstructionOpcodeToISD(Opcode);
3857 if (
I &&
I->hasOneUser()) {
3860 if (
Type *ExtTy = isBinExtWideningInstruction(
3861 SingleUser->getOpcode(), Dst,
Operands,
3862 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
3875 if (isSingleExtWideningInstruction(
3876 SingleUser->getOpcode(), Dst,
Operands,
3877 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
3881 if (SingleUser->getOpcode() == Instruction::Add) {
3882 if (
I == SingleUser->getOperand(1) ||
3884 cast<CastInst>(SingleUser->getOperand(1))->getOpcode() == Opcode))
3899 EVT SrcTy = TLI->getValueType(
DL, Src);
3900 EVT DstTy = TLI->getValueType(
DL, Dst);
3902 if (!SrcTy.isSimple() || !DstTy.
isSimple())
3907 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
3936 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
3939 ST->useSVEForFixedLengthVectors(WiderTy)) {
3940 std::pair<InstructionCost, MVT> LT =
3942 unsigned NumElements =
3958 const unsigned int SVE_EXT_COST = 1;
3959 const unsigned int SVE_FCVT_COST = 1;
3960 const unsigned int SVE_UNPACK_ONCE = 4;
3961 const unsigned int SVE_UNPACK_TWICE = 16;
4090 SVE_EXT_COST + SVE_FCVT_COST},
4095 SVE_EXT_COST + SVE_FCVT_COST},
4102 SVE_EXT_COST + SVE_FCVT_COST},
4106 SVE_EXT_COST + SVE_FCVT_COST},
4112 SVE_EXT_COST + SVE_FCVT_COST},
4115 SVE_EXT_COST + SVE_FCVT_COST},
4120 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4122 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4132 SVE_EXT_COST + SVE_FCVT_COST},
4137 SVE_EXT_COST + SVE_FCVT_COST},
4150 SVE_EXT_COST + SVE_FCVT_COST},
4154 SVE_EXT_COST + SVE_FCVT_COST},
4166 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4168 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4170 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4172 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4176 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4178 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4194 SVE_EXT_COST + SVE_FCVT_COST},
4199 SVE_EXT_COST + SVE_FCVT_COST},
4210 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4212 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4214 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4216 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4218 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4220 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4224 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4226 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4228 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4230 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4455 if (ST->hasFullFP16())
4467 Src->getScalarType(), CCH,
CostKind) +
4475 ST->isSVEorStreamingSVEAvailable() &&
4476 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4478 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4487 Opcode, LegalTy, Src, CCH,
CostKind,
I);
4490 return Part1 + Part2;
4497 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4509 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4522 CostKind, Index,
nullptr,
nullptr);
4526 auto DstVT = TLI->getValueType(
DL, Dst);
4527 auto SrcVT = TLI->getValueType(
DL, Src);
4532 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4538 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4548 case Instruction::SExt:
4553 case Instruction::ZExt:
4554 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4567 return Opcode == Instruction::PHI ? 0 : 1;
4576 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4585 if (!LT.second.isVector())
4590 if (LT.second.isFixedLengthVector()) {
4591 unsigned Width = LT.second.getVectorNumElements();
4592 Index = Index % Width;
4606 if (VIC == TTI::VectorInstrContext::Load) {
4607 if (ST->hasFastLD1Single())
4619 : ST->getVectorInsertExtractBaseCost() + 1;
4643 auto ExtractCanFuseWithFmul = [&]() {
4650 auto IsAllowedScalarTy = [&](
const Type *
T) {
4651 return T->isFloatTy() ||
T->isDoubleTy() ||
4652 (
T->isHalfTy() && ST->hasFullFP16());
4656 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4659 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4660 !BO->getType()->isVectorTy();
4665 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4669 return Idx == 0 || (RegWidth != 0 && (Idx * EltSz) % RegWidth == 0);
4678 DenseMap<User *, unsigned> UserToExtractIdx;
4679 for (
auto *U :
Scalar->users()) {
4680 if (!IsUserFMulScalarTy(U))
4684 UserToExtractIdx[
U];
4686 if (UserToExtractIdx.
empty())
4688 for (
auto &[S, U, L] : ScalarUserAndIdx) {
4689 for (
auto *U : S->users()) {
4690 if (UserToExtractIdx.
contains(U)) {
4692 auto *Op0 =
FMul->getOperand(0);
4693 auto *Op1 =
FMul->getOperand(1);
4694 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
4695 UserToExtractIdx[
U] =
L;
4701 for (
auto &[U, L] : UserToExtractIdx) {
4713 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
4714 if (!IsUserFMulScalarTy(U))
4719 const auto *BO = cast<BinaryOperator>(U);
4720 const auto *OtherEE = dyn_cast<ExtractElementInst>(
4721 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
4723 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
4726 return IsExtractLaneEquivalentToZero(
4727 cast<ConstantInt>(OtherEE->getIndexOperand())
4730 OtherEE->getType()->getScalarSizeInBits());
4738 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
4739 ExtractCanFuseWithFmul())
4744 :
ST->getVectorInsertExtractBaseCost();
4753 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
4756 return getVectorInstrCostHelper(Opcode, Val,
CostKind, Index,
nullptr,
4762 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4764 return getVectorInstrCostHelper(Opcode, Val,
CostKind, Index,
nullptr, Scalar,
4765 ScalarUserAndIdx, VIC);
4772 return getVectorInstrCostHelper(
I.getOpcode(), Val,
CostKind, Index, &
I,
4779 unsigned Index)
const {
4791 : ST->getVectorInsertExtractBaseCost() + 1;
4800 if (Ty->getElementType()->isFloatingPointTy())
4803 unsigned VecInstCost =
4805 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
4812 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
4813 return std::nullopt;
4814 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
4815 return std::nullopt;
4817 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
4818 return std::nullopt;
4825 Cost += InstCost(PromotedTy);
4847 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4854 Op2Info, Args, CxtI);
4861 Ty,
CostKind, Op1Info, Op2Info,
true,
4864 [&](
Type *PromotedTy) {
4868 return *PromotedCost;
4871 if (Ty->getScalarType()->isFP128Ty())
4879 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
4899 ST->hasLimited64bitVectorMulBandwidth())
4902 if (Ty->getScalarSizeInBits() > 64) {
4907 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
4910 if (LT.second == MVT::v2i64) {
4914 return LT.first * Mul64CostFactor;
4935 if (LT.second == MVT::nxv2i64)
4936 return LT.first * Mul64CostFactor;
4995 auto VT = TLI->getValueType(
DL, Ty);
4996 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5000 : (3 * AsrCost + AddCost);
5002 return MulCost + AsrCost + 2 * AddCost;
5004 }
else if (VT.isVector()) {
5014 if (Ty->isScalableTy() && ST->hasSVE())
5015 Cost += 2 * AsrCost;
5020 ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5024 }
else if (LT.second == MVT::v2i64) {
5025 return VT.getVectorNumElements() *
5032 if (Ty->isScalableTy() && ST->hasSVE())
5033 return MulCost + 2 * AddCost + 2 * AsrCost;
5034 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5039 LT.second.isFixedLengthVector()) {
5049 return ExtractCost + InsertCost +
5057 auto VT = TLI->getValueType(
DL, Ty);
5073 bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||
5074 LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||
5075 LT.second == MVT::nxv16i8;
5076 bool Is128bit = LT.second.is128BitVector();
5088 (HasMULH ? 0 : ShrCost) +
5089 AddCost * 2 + ShrCost;
5090 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5097 if (!VT.isVector() && VT.getSizeInBits() > 64)
5101 Opcode, Ty,
CostKind, Op1Info, Op2Info);
5103 if (TLI->isOperationLegalOrCustom(
ISD, LT.second) && ST->hasSVE()) {
5107 Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {
5117 if (
nullptr != Entry)
5125 FVTy && LT.second.isFixedLengthVector()) {
5126 unsigned NumElts = FVTy->getNumElements();
5127 unsigned RegElts = LT.second.getVectorNumElements();
5129 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5133 if (LT.second.getScalarType() == MVT::i8)
5135 else if (LT.second.getScalarType() == MVT::i16)
5147 Opcode, Ty->getScalarType(),
CostKind, Op1Info, Op2Info);
5148 return (4 + DivCost) * VTy->getNumElements();
5154 -1,
nullptr,
nullptr);
5181 LT.second.isFixedLengthVector())
5182 return 2 * LT.first + 1;
5191 if ((Ty->isFloatTy() || Ty->isDoubleTy() ||
5192 (Ty->isHalfTy() && ST->hasFullFP16())) &&
5201 if (!Ty->getScalarType()->isFP128Ty())
5208 if (!Ty->getScalarType()->isFP128Ty())
5209 return 2 * LT.first;
5216 if (!Ty->isVectorTy())
5232 int MaxMergeDistance = 64;
5236 return NumVectorInstToHideOverhead;
5246 unsigned Opcode1,
unsigned Opcode2)
const {
5249 if (!
Sched.hasInstrSchedModel())
5253 Sched.getSchedClassDesc(
TII->get(Opcode1).getSchedClass());
5255 Sched.getSchedClassDesc(
TII->get(Opcode2).getSchedClass());
5261 "Cannot handle variant scheduling classes without an MI");
5277 const int AmortizationCost = 20;
5285 VecPred = CurrentPred;
5293 static const auto ValidMinMaxTys = {
5294 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5295 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5296 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5300 (ST->hasFullFP16() &&
5306 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5307 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5308 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5309 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5310 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5311 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5312 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5313 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5314 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5315 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5316 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5318 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5319 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5328 if (Opcode == Instruction::FCmp) {
5330 ValTy,
CostKind, Op1Info, Op2Info,
false,
5332 false, [&](
Type *PromotedTy) {
5344 return *PromotedCost;
5348 if (LT.second.getScalarType() != MVT::f64 &&
5349 LT.second.getScalarType() != MVT::f32 &&
5350 LT.second.getScalarType() != MVT::f16)
5355 unsigned Factor = 1;
5356 if (!CondTy->isVectorTy() &&
5370 AArch64::FCMEQv4f32))
5382 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5401 Op1Info, Op2Info,
I);
5407 if (ST->requiresStrictAlign()) {
5412 Options.AllowOverlappingLoads =
true;
5413 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5418 Options.LoadSizes = {8, 4, 2, 1};
5419 Options.AllowedTailExpansions = {3, 5, 6};
5424 return ST->hasSVE();
5430 switch (MICA.
getID()) {
5431 case Intrinsic::masked_scatter:
5432 case Intrinsic::masked_gather:
5434 case Intrinsic::masked_load:
5435 case Intrinsic::masked_store:
5436 case Intrinsic::masked_expandload:
5437 case Intrinsic::masked_compressstore:
5451 if (!LT.first.isValid())
5456 if (VT->getElementType()->isIntegerTy(1))
5467 if (MICA.
getID() == Intrinsic::masked_expandload) {
5475 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5496 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5497 return MemOpCost * 2;
5506 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5507 "Should be called on only load or stores.");
5509 case Instruction::Load:
5512 return ST->getGatherOverhead();
5514 case Instruction::Store:
5517 return ST->getScatterOverhead();
5528 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5529 MICA.
getID() == Intrinsic::vp_gather)
5531 : Instruction::Store;
5541 if (!LT.first.isValid())
5545 if (!LT.second.isVector() ||
5547 VT->getElementType()->isIntegerTy(1))
5557 ElementCount LegalVF = LT.second.getVectorElementCount();
5560 {TTI::OK_AnyValue, TTI::OP_None},
I);
5576 EVT VT = TLI->getValueType(
DL, Ty,
true);
5578 if (VT == MVT::Other)
5583 if (!LT.first.isValid())
5593 (VTy->getElementType()->isIntegerTy(1) &&
5594 !VTy->getElementCount().isKnownMultipleOf(
5604 if (Opcode == Instruction::Store)
5608 if (ST->getFixedLoadLatency())
5609 return (LT.first - 1) + ST->getFixedLoadLatency();
5618 if (LT.second.isScalableVector() ||
5619 ST->useSVEForFixedLengthVectors(LT.second)) {
5620 Inst = AArch64::LDR_ZXI;
5621 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5622 switch (LT.second.getSizeInBits()) {
5624 Inst = AArch64::LDRBui;
5627 Inst = AArch64::LDRHui;
5630 Inst = AArch64::LDRSui;
5633 Inst = AArch64::LDRDui;
5636 Inst = AArch64::LDRQui;
5642 switch (LT.second.getSizeInBits()) {
5644 Inst = AArch64::LDRBBui;
5647 Inst = AArch64::LDRHHui;
5650 Inst = AArch64::LDRWui;
5653 Inst = AArch64::LDRXui;
5661 unsigned SchedClass =
TII->get(Inst).getSchedClass();
5665 float NumLoads = (LT.first - 1).
getValue();
5666 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
5667 Sched.computeInstrLatency(*ST, *SCD);
5670 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
5671 LT.second.is128BitVector() && Alignment <
Align(16)) {
5677 const int AmortizationCost = 6;
5679 return LT.first * 2 * AmortizationCost;
5683 if (Ty->isPtrOrPtrVectorTy())
5688 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
5690 if (VT == MVT::v4i8)
5697 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
5712 while (!TypeWorklist.
empty()) {
5734 bool UseMaskForCond,
bool UseMaskForGaps)
const {
5735 assert(Factor >= 2 &&
"Invalid interleave factor");
5750 if (!VecTy->
isScalableTy() && (UseMaskForCond || UseMaskForGaps))
5753 if (!UseMaskForGaps && Factor <= TLI->getMaxSupportedInterleaveFactor()) {
5756 EC.divideCoefficientBy(Factor));
5762 if (EC.isKnownMultipleOf(Factor) &&
5763 TLI->isLegalInterleavedAccessType(SubVecTy,
DL, UseScalable))
5764 return Factor * TLI->getNumInterleavedAccesses(SubVecTy,
DL, UseScalable);
5769 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
5775 if (UseMaskForCond) {
5776 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5777 : Intrinsic::masked_store;
5797 if (Opcode == Instruction::Store && Factor == 4 &&
5798 SubVecCost.second.getScalarSizeInBits() ==
5799 (4 * ResultCost.second.getScalarSizeInBits()))
5800 LegalizationCost *= 4;
5802 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
5808 UseMaskForCond, UseMaskForGaps);
5815 for (
auto *
I : Tys) {
5816 if (!
I->isVectorTy())
5827 Align Alignment)
const {
5834 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
5835 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
5840 bool HasUnorderedReductions)
const {
5843 return ST->getMaxInterleaveFactor();
5853 enum { MaxStridedLoads = 7 };
5855 int StridedLoads = 0;
5858 for (
const auto BB : L->blocks()) {
5859 for (
auto &
I : *BB) {
5865 if (L->isLoopInvariant(PtrValue))
5870 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
5879 if (StridedLoads > MaxStridedLoads / 2)
5880 return StridedLoads;
5883 return StridedLoads;
5886 int StridedLoads = countStridedLoads(L, SE);
5888 <<
" strided loads\n");
5904 unsigned *FinalSize) {
5908 for (
auto *BB : L->getBlocks()) {
5909 for (
auto &
I : *BB) {
5915 if (!Cost.isValid())
5919 if (LoopCost > Budget)
5941 if (MaxTC > 0 && MaxTC <= 32)
5952 if (Blocks.
size() != 2)
5974 if (!L->isInnermost() || L->getNumBlocks() > 8)
5978 if (!L->getExitBlock())
5984 bool HasParellelizableReductions =
5985 L->getNumBlocks() == 1 &&
5986 any_of(L->getHeader()->phis(),
5988 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
5991 if (HasParellelizableReductions &&
6013 if (HasParellelizableReductions) {
6024 if (Header == Latch) {
6027 unsigned Width = 10;
6033 unsigned MaxInstsPerLine = 16;
6035 unsigned BestUC = 1;
6036 unsigned SizeWithBestUC = BestUC *
Size;
6038 unsigned SizeWithUC = UC *
Size;
6039 if (SizeWithUC > 48)
6041 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6042 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6044 SizeWithBestUC = BestUC *
Size;
6054 for (
auto *BB : L->blocks()) {
6055 for (
auto &
I : *BB) {
6065 for (
auto *U :
I.users())
6067 LoadedValuesPlus.
insert(U);
6074 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6100 auto *I = dyn_cast<Instruction>(V);
6101 return I && DependsOnLoopLoad(I, Depth + 1);
6108 DependsOnLoopLoad(
I, 0)) {
6140 if (L->getLoopDepth() > 1)
6151 for (
auto *BB : L->getBlocks()) {
6152 for (
auto &
I : *BB) {
6156 if (IsVectorized &&
I.getType()->isVectorTy())
6173 if (ST->isAppleMLike())
6175 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6197 !ST->getSchedModel().isOutOfOrder()) {
6220 bool CanCreate)
const {
6224 case Intrinsic::aarch64_neon_st1x2:
6225 case Intrinsic::aarch64_neon_st1x3:
6226 case Intrinsic::aarch64_neon_st1x4:
6227 case Intrinsic::aarch64_neon_st2:
6228 case Intrinsic::aarch64_neon_st3:
6229 case Intrinsic::aarch64_neon_st4: {
6232 if (!CanCreate || !ST)
6234 unsigned NumElts = Inst->
arg_size() - 1;
6235 if (ST->getNumElements() != NumElts)
6237 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6243 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6245 Res = Builder.CreateInsertValue(Res, L, i);
6249 case Intrinsic::aarch64_neon_ld1x2:
6250 case Intrinsic::aarch64_neon_ld1x3:
6251 case Intrinsic::aarch64_neon_ld1x4:
6252 case Intrinsic::aarch64_neon_ld2:
6253 case Intrinsic::aarch64_neon_ld3:
6254 case Intrinsic::aarch64_neon_ld4:
6255 if (Inst->
getType() == ExpectedType)
6266 case Intrinsic::aarch64_neon_ld1x2:
6267 case Intrinsic::aarch64_neon_ld1x3:
6268 case Intrinsic::aarch64_neon_ld1x4:
6269 case Intrinsic::aarch64_neon_ld2:
6270 case Intrinsic::aarch64_neon_ld3:
6271 case Intrinsic::aarch64_neon_ld4:
6272 Info.ReadMem =
true;
6273 Info.WriteMem =
false;
6276 case Intrinsic::aarch64_neon_st1x2:
6277 case Intrinsic::aarch64_neon_st1x3:
6278 case Intrinsic::aarch64_neon_st1x4:
6279 case Intrinsic::aarch64_neon_st2:
6280 case Intrinsic::aarch64_neon_st3:
6281 case Intrinsic::aarch64_neon_st4:
6282 Info.ReadMem =
false;
6283 Info.WriteMem =
true;
6292 case Intrinsic::aarch64_neon_ld1x2:
6293 case Intrinsic::aarch64_neon_st1x2:
6294 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6296 case Intrinsic::aarch64_neon_ld1x3:
6297 case Intrinsic::aarch64_neon_st1x3:
6298 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6300 case Intrinsic::aarch64_neon_ld1x4:
6301 case Intrinsic::aarch64_neon_st1x4:
6302 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6304 case Intrinsic::aarch64_neon_ld2:
6305 case Intrinsic::aarch64_neon_st2:
6306 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6308 case Intrinsic::aarch64_neon_ld3:
6309 case Intrinsic::aarch64_neon_st3:
6310 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6312 case Intrinsic::aarch64_neon_ld4:
6313 case Intrinsic::aarch64_neon_st4:
6314 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6326 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6327 bool Considerable =
false;
6328 AllowPromotionWithoutCommonHeader =
false;
6331 Type *ConsideredSExtType =
6333 if (
I.getType() != ConsideredSExtType)
6337 for (
const User *U :
I.users()) {
6339 Considerable =
true;
6343 if (GEPInst->getNumOperands() > 2) {
6344 AllowPromotionWithoutCommonHeader =
true;
6349 return Considerable;
6400 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6410 return LegalizationCost + 2;
6420 LegalizationCost *= LT.first - 1;
6423 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6432 return LegalizationCost + 2;
6440 std::optional<FastMathFlags> FMF,
6456 return BaseCost + FixedVTy->getNumElements();
6470 MVT MTy = LT.second;
6475 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6523 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6524 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6536 return (LT.first - 1) +
Log2_32(NElts);
6541 return (LT.first - 1) + Entry->Cost;
6553 if (LT.first != 1) {
6559 ExtraCost *= LT.first - 1;
6562 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
6563 return Cost + ExtraCost;
6571 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
6573 EVT VecVT = TLI->getValueType(
DL, VecTy);
6574 EVT ResVT = TLI->getValueType(
DL, ResTy);
6584 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6586 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
6588 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
6590 return (LT.first - 1) * 2 + 2;
6601 EVT VecVT = TLI->getValueType(
DL, VecTy);
6602 EVT ResVT = TLI->getValueType(
DL, ResTy);
6605 RedOpcode == Instruction::Add) {
6611 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6613 return LT.first + 2;
6648 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
6649 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
6663 if (LT.second.getScalarType() == MVT::i1) {
6672 assert(Entry &&
"Illegal Type for Splice");
6673 LegalizationCost += Entry->Cost;
6674 return LegalizationCost * LT.first;
6678 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
6687 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
6688 Opcode != Instruction::FAdd && Opcode != Instruction::FSub) ||
6695 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
6696 if (!FMF->allowReassoc() || !FMF->allowContract())
6700 "FastMathFlags only apply to floating-point partial reductions");
6704 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
6705 "Unexpected values for OpBExtend or InputTypeB");
6709 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
6710 InputTypeA != InputTypeB))
6713 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
6716 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
6729 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
6738 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
6744 std::pair<InstructionCost, MVT> AccumLT =
6746 std::pair<InstructionCost, MVT> InputLT =
6750 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
6751 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
6752 (AccumLT.second.isFixedLengthVector() &&
6753 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
6757 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
6765 if (AccumLT.second.getScalarType() == MVT::i32 &&
6766 InputLT.second.getScalarType() == MVT::i8) {
6768 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
6769 return Cost + INegCost;
6771 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
6772 return Cost + INegCost;
6777 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
6778 return Cost * 3 + INegCost;
6781 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
6783 if (AccumLT.second.getScalarType() == MVT::i64 &&
6784 InputLT.second.getScalarType() == MVT::i16)
6785 return Cost + INegCost;
6788 if (AccumLT.second.getScalarType() == MVT::i32 &&
6789 InputLT.second.getScalarType() == MVT::i16 &&
6790 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
6793 if (AccumLT.second.getScalarType() == MVT::i64 &&
6794 InputLT.second.getScalarType() == MVT::i8)
6800 return Cost + INegCost;
6803 if (AccumLT.second.getScalarType() == MVT::i16 &&
6804 InputLT.second.getScalarType() == MVT::i8 &&
6805 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
6811 if (Opcode == Instruction::FAdd && !IsSub &&
6812 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
6813 AccumLT.second.getScalarType() == MVT::f32 &&
6814 InputLT.second.getScalarType() == MVT::f16)
6818 if (Ratio == 2 && !IsUSDot) {
6819 MVT InVT = InputLT.second.getScalarType();
6823 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
6825 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
6828 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
6832 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
6833 InVT == MVT::bf16 && IsSub)
6843 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
6844 return Cost * 2 + FNegCost;
6848 AccumType, VF, OpAExtend, OpBExtend,
6860 "Expected the Mask to match the return size if given");
6862 "Expected the same scalar types");
6868 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
6869 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
6870 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
6878 return std::max<InstructionCost>(1, LT.first / 4);
6886 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
6888 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
6891 unsigned TpNumElts = Mask.size();
6892 unsigned LTNumElts = LT.second.getVectorNumElements();
6893 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
6895 LT.second.getVectorElementCount());
6897 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
6899 for (
unsigned N = 0;
N < NumVecs;
N++) {
6903 unsigned Source1 = -1U, Source2 = -1U;
6904 unsigned NumSources = 0;
6905 for (
unsigned E = 0; E < LTNumElts; E++) {
6906 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
6915 unsigned Source = MaskElt / LTNumElts;
6916 if (NumSources == 0) {
6919 }
else if (NumSources == 1 && Source != Source1) {
6922 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
6928 if (Source == Source1)
6930 else if (Source == Source2)
6931 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
6940 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
6951 NTp, NTp, NMask,
CostKind, 0,
nullptr, Args,
6954 Result.first->second = NCost;
6968 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
6969 if (LT.second.getFixedSizeInBits() >= 128 &&
6971 LT.second.getVectorNumElements() / 2) {
6974 if (Index == (
int)LT.second.getVectorNumElements() / 2)
6988 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
6991 return M.value() < 0 || M.value() == (int)M.index();
6997 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
6998 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7007 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7008 ST->isSVEorStreamingSVEAvailable() &&
7013 if (ST->isSVEorStreamingSVEAvailable() &&
7027 if (IsLoad && LT.second.isVector() &&
7029 LT.second.getVectorElementCount()))
7035 if (Mask.size() == 4 &&
7037 (SrcTy->getScalarSizeInBits() == 16 ||
7038 SrcTy->getScalarSizeInBits() == 32) &&
7039 all_of(Mask, [](
int E) {
return E < 8; }))
7045 if (LT.second.isFixedLengthVector() &&
7046 LT.second.getVectorNumElements() == Mask.size() &&
7052 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7053 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7054 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7055 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7056 LT.second.getVectorNumElements(), 16) ||
7057 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7058 LT.second.getVectorNumElements(), 32) ||
7059 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7060 LT.second.getVectorNumElements(), 64) ||
7063 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7192 return LT.first * Entry->Cost;
7201 LT.second.getSizeInBits() <= 128 && SubTp) {
7203 if (SubLT.second.isVector()) {
7204 int NumElts = LT.second.getVectorNumElements();
7205 int NumSubElts = SubLT.second.getVectorNumElements();
7206 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7212 if (IsExtractSubvector)
7229 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7242 return ST->useFixedOverScalableIfEqualCost();
7246 return ST->getEpilogueVectorizationMinVF();
7281 unsigned NumInsns = 0;
7283 NumInsns += BB->size();
7293 int64_t Scale,
unsigned AddrSpace)
const {
7321 if (
I->getOpcode() == Instruction::Or &&
7325 if (
I->getOpcode() == Instruction::Add ||
7326 I->getOpcode() == Instruction::Sub)
7351 return all_equal(Shuf->getShuffleMask());
7358 bool AllowSplat =
false) {
7363 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7364 auto *FullTy = FullV->
getType();
7365 auto *HalfTy = HalfV->getType();
7367 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7370 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7373 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7377 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7391 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7392 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7406 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7407 (M2Start != 0 && M2Start != (NumElements / 2)))
7409 if (S1Op1 && S2Op1 && M1Start != M2Start)
7419 return Ext->getType()->getScalarSizeInBits() ==
7420 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7434 Value *VectorOperand =
nullptr;
7451 if (!
GEP ||
GEP->getNumOperands() != 2)
7455 Value *Offsets =
GEP->getOperand(1);
7458 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7464 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7465 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7466 Ops.push_back(&
GEP->getOperandUse(1));
7502 switch (
II->getIntrinsicID()) {
7503 case Intrinsic::aarch64_neon_smull:
7504 case Intrinsic::aarch64_neon_umull:
7507 Ops.push_back(&
II->getOperandUse(0));
7508 Ops.push_back(&
II->getOperandUse(1));
7513 case Intrinsic::fma:
7514 case Intrinsic::fmuladd:
7521 Ops.push_back(&
II->getOperandUse(0));
7523 Ops.push_back(&
II->getOperandUse(1));
7526 case Intrinsic::aarch64_neon_sqdmull:
7527 case Intrinsic::aarch64_neon_sqdmulh:
7528 case Intrinsic::aarch64_neon_sqrdmulh:
7531 Ops.push_back(&
II->getOperandUse(0));
7533 Ops.push_back(&
II->getOperandUse(1));
7534 return !
Ops.empty();
7535 case Intrinsic::aarch64_neon_fmlal:
7536 case Intrinsic::aarch64_neon_fmlal2:
7537 case Intrinsic::aarch64_neon_fmlsl:
7538 case Intrinsic::aarch64_neon_fmlsl2:
7541 Ops.push_back(&
II->getOperandUse(1));
7543 Ops.push_back(&
II->getOperandUse(2));
7544 return !
Ops.empty();
7545 case Intrinsic::aarch64_sve_ptest_first:
7546 case Intrinsic::aarch64_sve_ptest_last:
7548 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
7549 Ops.push_back(&
II->getOperandUse(0));
7550 return !
Ops.empty();
7551 case Intrinsic::aarch64_sme_write_horiz:
7552 case Intrinsic::aarch64_sme_write_vert:
7553 case Intrinsic::aarch64_sme_writeq_horiz:
7554 case Intrinsic::aarch64_sme_writeq_vert: {
7556 if (!Idx || Idx->getOpcode() != Instruction::Add)
7558 Ops.push_back(&
II->getOperandUse(1));
7561 case Intrinsic::aarch64_sme_read_horiz:
7562 case Intrinsic::aarch64_sme_read_vert:
7563 case Intrinsic::aarch64_sme_readq_horiz:
7564 case Intrinsic::aarch64_sme_readq_vert:
7565 case Intrinsic::aarch64_sme_ld1b_vert:
7566 case Intrinsic::aarch64_sme_ld1h_vert:
7567 case Intrinsic::aarch64_sme_ld1w_vert:
7568 case Intrinsic::aarch64_sme_ld1d_vert:
7569 case Intrinsic::aarch64_sme_ld1q_vert:
7570 case Intrinsic::aarch64_sme_st1b_vert:
7571 case Intrinsic::aarch64_sme_st1h_vert:
7572 case Intrinsic::aarch64_sme_st1w_vert:
7573 case Intrinsic::aarch64_sme_st1d_vert:
7574 case Intrinsic::aarch64_sme_st1q_vert:
7575 case Intrinsic::aarch64_sme_ld1b_horiz:
7576 case Intrinsic::aarch64_sme_ld1h_horiz:
7577 case Intrinsic::aarch64_sme_ld1w_horiz:
7578 case Intrinsic::aarch64_sme_ld1d_horiz:
7579 case Intrinsic::aarch64_sme_ld1q_horiz:
7580 case Intrinsic::aarch64_sme_st1b_horiz:
7581 case Intrinsic::aarch64_sme_st1h_horiz:
7582 case Intrinsic::aarch64_sme_st1w_horiz:
7583 case Intrinsic::aarch64_sme_st1d_horiz:
7584 case Intrinsic::aarch64_sme_st1q_horiz: {
7586 if (!Idx || Idx->getOpcode() != Instruction::Add)
7588 Ops.push_back(&
II->getOperandUse(3));
7591 case Intrinsic::aarch64_neon_pmull:
7594 Ops.push_back(&
II->getOperandUse(0));
7595 Ops.push_back(&
II->getOperandUse(1));
7597 case Intrinsic::aarch64_neon_pmull64:
7599 II->getArgOperand(1)))
7601 Ops.push_back(&
II->getArgOperandUse(0));
7602 Ops.push_back(&
II->getArgOperandUse(1));
7604 case Intrinsic::masked_gather:
7607 Ops.push_back(&
II->getArgOperandUse(0));
7609 case Intrinsic::masked_scatter:
7612 Ops.push_back(&
II->getArgOperandUse(1));
7619 auto ShouldSinkCondition = [](
Value *
Cond,
7624 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
7628 Ops.push_back(&
II->getOperandUse(0));
7632 switch (
I->getOpcode()) {
7633 case Instruction::GetElementPtr:
7634 case Instruction::Add:
7635 case Instruction::Sub:
7637 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
7639 Ops.push_back(&
I->getOperandUse(
Op));
7644 case Instruction::Select: {
7645 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
7648 Ops.push_back(&
I->getOperandUse(0));
7651 case Instruction::UncondBr:
7653 case Instruction::CondBr: {
7657 Ops.push_back(&
I->getOperandUse(0));
7660 case Instruction::FMul:
7665 Ops.push_back(&
I->getOperandUse(0));
7667 Ops.push_back(&
I->getOperandUse(1));
7677 case Instruction::Xor:
7680 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
7682 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
7687 case Instruction::And:
7688 case Instruction::Or:
7691 if (
I->getOpcode() == Instruction::Or &&
7696 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
7699 for (
auto &
Op :
I->operands()) {
7711 Ops.push_back(&Not);
7712 Ops.push_back(&InsertElt);
7722 if (!
I->getType()->isVectorTy())
7723 return !
Ops.empty();
7725 switch (
I->getOpcode()) {
7726 case Instruction::Sub:
7727 case Instruction::Add: {
7736 Ops.push_back(&Ext1->getOperandUse(0));
7737 Ops.push_back(&Ext2->getOperandUse(0));
7740 Ops.push_back(&
I->getOperandUse(0));
7741 Ops.push_back(&
I->getOperandUse(1));
7745 case Instruction::Or: {
7748 if (ST->hasNEON()) {
7762 if (
I->getParent() != MainAnd->
getParent() ||
7767 if (
I->getParent() != IA->getParent() ||
7768 I->getParent() != IB->getParent())
7773 Ops.push_back(&
I->getOperandUse(0));
7774 Ops.push_back(&
I->getOperandUse(1));
7783 case Instruction::Mul: {
7784 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
7787 if (Ty->isScalableTy())
7791 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
7794 int NumZExts = 0, NumSExts = 0;
7795 for (
auto &
Op :
I->operands()) {
7802 auto *ExtOp = Ext->getOperand(0);
7803 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
7804 Ops.push_back(&Ext->getOperandUse(0));
7812 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
7813 I->getType()->getScalarSizeInBits())
7850 if (!ElementConstant || !ElementConstant->
isZero())
7853 unsigned Opcode = OperandInstr->
getOpcode();
7854 if (Opcode == Instruction::SExt)
7856 else if (Opcode == Instruction::ZExt)
7861 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
7871 Ops.push_back(&Insert->getOperandUse(1));
7877 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
7881 if (!ShouldSinkSplatForIndexedVariant(
I))
7886 Ops.push_back(&
I->getOperandUse(0));
7888 Ops.push_back(&
I->getOperandUse(1));
7890 return !
Ops.empty();
7892 case Instruction::FMul: {
7894 if (
I->getType()->isScalableTy())
7895 return !
Ops.empty();
7899 return !
Ops.empty();
7903 Ops.push_back(&
I->getOperandUse(0));
7905 Ops.push_back(&
I->getOperandUse(1));
7906 return !
Ops.empty();
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
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 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 *CxtI=nullptr) 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 getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
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 getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) 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 getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isElementTypeLegalForScalableVector(Type *Ty) 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
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 getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, ArrayRef< int > Mask, TTI::TargetCostKind CostKind, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
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
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
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 getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Value * getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate=true) const override
bool hasKnownLowerThroughputFromSchedulingModel(unsigned Opcode1, unsigned Opcode2) const
Check whether Opcode1 has less throughput according to the scheduling model than Opcode2.
unsigned getEpilogueVectorizationMinVF() const override
InstructionCost getSpliceCost(VectorType *Tp, int Index, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) const override
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) const override
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
void negate()
Negate this APInt in place.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
unsigned logBase2() const
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost 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 *CxtI=nullptr) 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 getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, ArrayRef< int > Mask, TTI::TargetCostKind CostKind, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getCallInstrCost(Function *F, Type *RetTy, ArrayRef< Type * > Tys, TTI::TargetCostKind CostKind) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind) const override
InstructionCost 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...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
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...
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.
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
bool isSMEABIRoutine() 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.
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
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.
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.
user_iterator user_begin()
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.
@ 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.
@ 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 ...
@ 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.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
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)
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
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.
initializer< Ty > init(const Ty &Val)
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.
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).
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.
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.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=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...
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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.
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.
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.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const DenseMap< Value *, const SCEV * > &StridesMap=DenseMap< Value *, const SCEV * >(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
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).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
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*...