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);
187 return getBits(DefaultBits) == TailFoldingOpts::Disabled;
201 "Control the use of vectorisation using tail-folding for SVE where the"
202 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
203 "\ndisabled (Initial) No loop types will vectorize using "
205 "\ndefault (Initial) Uses the default tail-folding settings for "
207 "\nall (Initial) All legal loop types will vectorize using "
209 "\nsimple (Initial) Use tail-folding for simple loops (not "
210 "reductions or recurrences)"
211 "\nreductions Use tail-folding for loops containing reductions"
212 "\nnoreductions Inverse of above"
213 "\nrecurrences Use tail-folding for loops containing fixed order "
215 "\nnorecurrences Inverse of above"
216 "\nreverse Use tail-folding for loops requiring reversed "
218 "\nnoreverse Inverse of above"),
263 TTI->isMultiversionedFunction(
F) ?
"fmv-features" :
"target-features";
264 StringRef FeatureStr =
F.getFnAttribute(AttributeStr).getValueAsString();
265 FeatureStr.
split(Features,
",");
281 return F.hasFnAttribute(
"fmv-features");
291 if (
CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
292 CallAttrs.callee().hasStreamingInterfaceOrBody())
297 if (
CallAttrs.callee().hasStreamingBody()) {
307 CallAttrs.requiresPreservingAllZAState()) {
330 auto FVTy = dyn_cast<FixedVectorType>(Ty);
332 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
341 unsigned DefaultCallPenalty)
const {
366 if (
F ==
Call.getCaller())
372 return DefaultCallPenalty;
383 ST->isSVEorStreamingSVEAvailable() &&
384 !ST->disableMaximizeScalableBandwidth();
408 assert(Ty->isIntegerTy());
410 unsigned BitSize = Ty->getPrimitiveSizeInBits();
417 ImmVal =
Imm.sext((BitSize + 63) & ~0x3fU);
422 for (
unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
428 return std::max<InstructionCost>(1,
Cost);
435 assert(Ty->isIntegerTy());
437 unsigned BitSize = Ty->getPrimitiveSizeInBits();
443 unsigned ImmIdx = ~0U;
447 case Instruction::GetElementPtr:
452 case Instruction::Store:
455 case Instruction::Add:
456 case Instruction::Sub:
457 case Instruction::Mul:
458 case Instruction::UDiv:
459 case Instruction::SDiv:
460 case Instruction::URem:
461 case Instruction::SRem:
462 case Instruction::And:
463 case Instruction::Or:
464 case Instruction::Xor:
465 case Instruction::ICmp:
469 case Instruction::Shl:
470 case Instruction::LShr:
471 case Instruction::AShr:
475 case Instruction::Trunc:
476 case Instruction::ZExt:
477 case Instruction::SExt:
478 case Instruction::IntToPtr:
479 case Instruction::PtrToInt:
480 case Instruction::BitCast:
481 case Instruction::PHI:
482 case Instruction::Call:
483 case Instruction::Select:
484 case Instruction::Ret:
485 case Instruction::Load:
490 int NumConstants = (BitSize + 63) / 64;
503 assert(Ty->isIntegerTy());
505 unsigned BitSize = Ty->getPrimitiveSizeInBits();
514 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
520 case Intrinsic::sadd_with_overflow:
521 case Intrinsic::uadd_with_overflow:
522 case Intrinsic::ssub_with_overflow:
523 case Intrinsic::usub_with_overflow:
524 case Intrinsic::smul_with_overflow:
525 case Intrinsic::umul_with_overflow:
527 int NumConstants = (BitSize + 63) / 64;
534 case Intrinsic::experimental_stackmap:
535 if ((Idx < 2) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
538 case Intrinsic::experimental_patchpoint_void:
539 case Intrinsic::experimental_patchpoint:
540 if ((Idx < 4) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
543 case Intrinsic::experimental_gc_statepoint:
544 if ((Idx < 5) || (
Imm.getBitWidth() <= 64 &&
isInt<64>(
Imm.getSExtValue())))
554 if (TyWidth == 32 || TyWidth == 64)
563 return ST->getMispredictionPenalty();
584 unsigned TotalHistCnts = 1;
594 unsigned EC = VTy->getElementCount().getKnownMinValue();
599 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
601 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
605 TotalHistCnts = EC / NaturalVectorWidth;
625 switch (ICA.
getID()) {
626 case Intrinsic::experimental_vector_histogram_add: {
633 case Intrinsic::clmul: {
638 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
642 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8) {
647 -1,
nullptr,
nullptr) *
650 -1,
nullptr,
nullptr);
654 if (LT.second.SimpleTy == MVT::nxv2i64)
655 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
658 if (ST->hasSVE2() || ST->hasSME()) {
659 switch (LT.second.SimpleTy) {
674 if (LT.second.SimpleTy == MVT::nxv2i64)
678 switch (LT.second.SimpleTy) {
688 -1,
nullptr,
nullptr) *
691 -1,
nullptr,
nullptr));
700 return LT.first * 11;
702 return LT.first * 14;
709 case Intrinsic::umin:
710 case Intrinsic::umax:
711 case Intrinsic::smin:
712 case Intrinsic::smax: {
713 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
714 MVT::v8i16, MVT::v2i32, MVT::v4i32,
715 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
722 ICA.
getID() == Intrinsic::smin || ICA.
getID() == Intrinsic::smax;
723 EVT VT = TLI->getValueType(
DL, RetTy,
true);
724 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
725 return LT.first * (IsSigned ? 5 : 3);
727 if (LT.second == MVT::v2i64)
733 case Intrinsic::scmp:
734 case Intrinsic::ucmp: {
736 {Intrinsic::scmp, MVT::i32, 3},
737 {Intrinsic::scmp, MVT::i64, 3},
738 {Intrinsic::scmp, MVT::v8i8, 3},
739 {Intrinsic::scmp, MVT::v16i8, 3},
740 {Intrinsic::scmp, MVT::v4i16, 3},
741 {Intrinsic::scmp, MVT::v8i16, 3},
742 {Intrinsic::scmp, MVT::v2i32, 3},
743 {Intrinsic::scmp, MVT::v4i32, 3},
744 {Intrinsic::scmp, MVT::v1i64, 3},
745 {Intrinsic::scmp, MVT::v2i64, 3},
751 return Entry->Cost * LT.first;
754 case Intrinsic::sadd_sat:
755 case Intrinsic::ssub_sat:
756 case Intrinsic::uadd_sat:
757 case Intrinsic::usub_sat: {
758 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
759 MVT::v8i16, MVT::v2i32, MVT::v4i32,
765 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
767 return LT.first * Instrs;
772 if (ST->isSVEAvailable() && VectorSize >= 128 &&
isPowerOf2_64(VectorSize))
773 return LT.first * Instrs;
777 case Intrinsic::abs: {
778 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
779 MVT::v8i16, MVT::v2i32, MVT::v4i32,
780 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
781 MVT::nxv4i32, MVT::nxv2i64};
787 case Intrinsic::bswap: {
788 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
789 MVT::v4i32, MVT::v2i64};
792 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
797 case Intrinsic::fmuladd: {
802 (EltTy->
isHalfTy() && ST->hasFullFP16()))
806 case Intrinsic::stepvector: {
815 Cost += AddCost * (LT.first - 1);
819 case Intrinsic::vector_extract:
820 case Intrinsic::vector_insert: {
833 bool IsExtract = ICA.
getID() == Intrinsic::vector_extract;
834 EVT SubVecVT = IsExtract ? getTLI()->getValueType(
DL, RetTy)
842 getTLI()->getTypeConversion(
C, SubVecVT);
844 getTLI()->getTypeConversion(
C, VecVT);
852 case Intrinsic::bitreverse: {
854 {Intrinsic::bitreverse, MVT::i32, 1},
855 {Intrinsic::bitreverse, MVT::i64, 1},
856 {Intrinsic::bitreverse, MVT::v8i8, 1},
857 {Intrinsic::bitreverse, MVT::v16i8, 1},
858 {Intrinsic::bitreverse, MVT::v4i16, 2},
859 {Intrinsic::bitreverse, MVT::v8i16, 2},
860 {Intrinsic::bitreverse, MVT::v2i32, 2},
861 {Intrinsic::bitreverse, MVT::v4i32, 2},
862 {Intrinsic::bitreverse, MVT::v1i64, 2},
863 {Intrinsic::bitreverse, MVT::v2i64, 2},
871 if (TLI->getValueType(
DL, RetTy,
true) == MVT::i8 ||
872 TLI->getValueType(
DL, RetTy,
true) == MVT::i16)
873 return LegalisationCost.first * Entry->Cost + 1;
875 return LegalisationCost.first * Entry->Cost;
879 case Intrinsic::ctpop: {
883 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
886 return LT.first + ExtraCost;
888 if (!ST->hasNEON()) {
918 RetTy->getScalarSizeInBits()
921 return LT.first * Entry->Cost + ExtraCost;
925 case Intrinsic::sadd_with_overflow:
926 case Intrinsic::uadd_with_overflow:
927 case Intrinsic::ssub_with_overflow:
928 case Intrinsic::usub_with_overflow:
929 case Intrinsic::smul_with_overflow:
930 case Intrinsic::umul_with_overflow: {
932 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
933 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
934 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
935 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
936 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
937 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
938 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
939 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
940 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
941 {Intrinsic::usub_with_overflow, MVT::i8, 3},
942 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
943 {Intrinsic::usub_with_overflow, MVT::i16, 3},
944 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
945 {Intrinsic::usub_with_overflow, MVT::i32, 1},
946 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
947 {Intrinsic::usub_with_overflow, MVT::i64, 1},
948 {Intrinsic::smul_with_overflow, MVT::i8, 5},
949 {Intrinsic::umul_with_overflow, MVT::i8, 4},
950 {Intrinsic::smul_with_overflow, MVT::i16, 5},
951 {Intrinsic::umul_with_overflow, MVT::i16, 4},
952 {Intrinsic::smul_with_overflow, MVT::i32, 2},
953 {Intrinsic::umul_with_overflow, MVT::i32, 2},
954 {Intrinsic::smul_with_overflow, MVT::i64, 3},
955 {Intrinsic::umul_with_overflow, MVT::i64, 3},
957 EVT MTy = TLI->getValueType(
DL, RetTy->getContainedType(0),
true);
964 case Intrinsic::fptosi_sat:
965 case Intrinsic::fptoui_sat: {
968 bool IsSigned = ICA.
getID() == Intrinsic::fptosi_sat;
970 EVT MTy = TLI->getValueType(
DL, RetTy);
973 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
974 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
975 LT.second == MVT::v2f64)) {
977 (LT.second == MVT::f64 && MTy == MVT::i32) ||
978 (LT.second == MVT::f32 && MTy == MVT::i64)))
987 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
994 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
995 (LT.second == MVT::f16 && MTy == MVT::i64) ||
996 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1010 if ((LT.second.getScalarType() == MVT::f32 ||
1011 LT.second.getScalarType() == MVT::f64 ||
1012 LT.second.getScalarType() == MVT::f16) &&
1015 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1016 if (LT.second.isVector())
1017 LegalTy =
VectorType::get(LegalTy, LT.second.getVectorElementCount());
1021 LegalTy, {LegalTy, LegalTy});
1025 LegalTy, {LegalTy, LegalTy});
1027 return LT.first *
Cost +
1028 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1034 RetTy = RetTy->getScalarType();
1035 if (LT.second.isVector()) {
1053 return LT.first *
Cost;
1055 case Intrinsic::fshl:
1056 case Intrinsic::fshr: {
1065 if (RetTy->isIntegerTy() && ICA.
getArgs()[0] == ICA.
getArgs()[1] &&
1066 (RetTy->getPrimitiveSizeInBits() == 32 ||
1067 RetTy->getPrimitiveSizeInBits() == 64)) {
1080 {Intrinsic::fshl, MVT::v4i32, 2},
1081 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1082 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1083 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1089 return LegalisationCost.first * Entry->Cost;
1093 if (!RetTy->isIntegerTy())
1098 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1099 RetTy->getScalarSizeInBits() < 64) ||
1100 (RetTy->getScalarSizeInBits() % 64 != 0);
1101 unsigned ExtraCost = HigherCost ? 1 : 0;
1102 if (RetTy->getScalarSizeInBits() == 32 ||
1103 RetTy->getScalarSizeInBits() == 64)
1106 else if (HigherCost)
1110 return TyL.first + ExtraCost;
1112 case Intrinsic::get_active_lane_mask: {
1114 EVT RetVT = getTLI()->getValueType(
DL, RetTy);
1116 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1119 if (RetTy->isScalableTy()) {
1120 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1130 if (ST->hasSVE2p1() || ST->hasSME2()) {
1142 Type *CondTy =
OpTy->getWithNewBitWidth(1);
1145 return Cost + (SplitCost * (
Cost - 1));
1160 case Intrinsic::experimental_vector_match: {
1161 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1167 unsigned SearchSize = NeedleTy->getNumElements();
1168 if (SearchSize <= 2)
1173 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1177 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1183 unsigned MatchesRequiredForNeedle =
1195 return Cost * LegalParts * MatchesRequiredForNeedle;
1197 case Intrinsic::cttz: {
1199 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1200 return LT.first * 2;
1201 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1202 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1203 return LT.first * 3;
1206 case Intrinsic::experimental_cttz_elts: {
1216 case Intrinsic::loop_dependence_raw_mask:
1217 case Intrinsic::loop_dependence_war_mask: {
1219 if (ST->hasSVE2() || ST->hasSME()) {
1220 EVT VecVT = getTLI()->getValueType(
DL, RetTy);
1221 unsigned EltSizeInBytes =
1231 case Intrinsic::experimental_vector_extract_last_active:
1232 if (ST->isSVEorStreamingSVEAvailable()) {
1238 case Intrinsic::pow: {
1241 EVT VT = getTLI()->getValueType(
DL, RetTy);
1242 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1243 bool HasLibcall = getTLI()->getLibcallImpl(LC) != RTLIB::Unsupported;
1258 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1259 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1269 return (Sqrt * 2) +
FMul;
1280 case Intrinsic::sqrt:
1281 case Intrinsic::fabs:
1282 case Intrinsic::ceil:
1283 case Intrinsic::floor:
1284 case Intrinsic::nearbyint:
1285 case Intrinsic::round:
1286 case Intrinsic::rint:
1287 case Intrinsic::roundeven:
1288 case Intrinsic::trunc:
1289 case Intrinsic::minnum:
1290 case Intrinsic::maxnum:
1291 case Intrinsic::minimum:
1292 case Intrinsic::maximum: {
1310 auto RequiredType =
II.getType();
1313 assert(PN &&
"Expected Phi Node!");
1316 if (!PN->hasOneUse())
1317 return std::nullopt;
1319 for (
Value *IncValPhi : PN->incoming_values()) {
1322 Reinterpret->getIntrinsicID() !=
1323 Intrinsic::aarch64_sve_convert_to_svbool ||
1324 RequiredType != Reinterpret->getArgOperand(0)->getType())
1325 return std::nullopt;
1333 for (
unsigned I = 0;
I < PN->getNumIncomingValues();
I++) {
1335 NPN->
addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(
I));
1408 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1413 return GoverningPredicateIdx;
1418 GoverningPredicateIdx = Index;
1440 return UndefIntrinsic;
1445 UndefIntrinsic = IID;
1472 return CmpPredicate;
1477 CmpPredicate = Pred;
1493 return ResultLanes == InactiveLanesTakenFromOperand;
1498 return OperandIdxForInactiveLanes;
1502 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1503 ResultLanes = InactiveLanesTakenFromOperand;
1504 OperandIdxForInactiveLanes = Index;
1509 return ResultLanes == InactiveLanesAreNotDefined;
1513 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1514 ResultLanes = InactiveLanesAreNotDefined;
1519 return ResultLanes == InactiveLanesAreUnused;
1523 assert(ResultLanes == Uninitialized &&
"Cannot set property twice!");
1524 ResultLanes = InactiveLanesAreUnused;
1534 ResultIsZeroInitialized =
true;
1545 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1550 return OperandIdxWithNoActiveLanes;
1555 OperandIdxWithNoActiveLanes = Index;
1560 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1563 unsigned IROpcode = 0;
1566 enum PredicationStyle {
1568 InactiveLanesTakenFromOperand,
1569 InactiveLanesAreNotDefined,
1570 InactiveLanesAreUnused
1573 bool ResultIsZeroInitialized =
false;
1574 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1575 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1583 return !isa<ScalableVectorType>(V->getType());
1591 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1592 case Intrinsic::aarch64_sve_fcvt_f16f32:
1593 case Intrinsic::aarch64_sve_fcvt_f16f64:
1594 case Intrinsic::aarch64_sve_fcvt_f32f16:
1595 case Intrinsic::aarch64_sve_fcvt_f32f64:
1596 case Intrinsic::aarch64_sve_fcvt_f64f16:
1597 case Intrinsic::aarch64_sve_fcvt_f64f32:
1598 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1599 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1600 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1601 case Intrinsic::aarch64_sve_fcvtzs:
1602 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1603 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1604 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1605 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1606 case Intrinsic::aarch64_sve_fcvtzu:
1607 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1608 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1609 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1610 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1611 case Intrinsic::aarch64_sve_revb:
1612 case Intrinsic::aarch64_sve_revh:
1613 case Intrinsic::aarch64_sve_revw:
1614 case Intrinsic::aarch64_sve_revd:
1615 case Intrinsic::aarch64_sve_scvtf:
1616 case Intrinsic::aarch64_sve_scvtf_f16i32:
1617 case Intrinsic::aarch64_sve_scvtf_f16i64:
1618 case Intrinsic::aarch64_sve_scvtf_f32i64:
1619 case Intrinsic::aarch64_sve_scvtf_f64i32:
1620 case Intrinsic::aarch64_sve_ucvtf:
1621 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1622 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1623 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1624 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1627 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1628 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1629 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1630 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1633 case Intrinsic::aarch64_sve_fabd:
1635 case Intrinsic::aarch64_sve_fadd:
1638 case Intrinsic::aarch64_sve_fdiv:
1641 case Intrinsic::aarch64_sve_fmax:
1643 case Intrinsic::aarch64_sve_fmaxnm:
1645 case Intrinsic::aarch64_sve_fmin:
1647 case Intrinsic::aarch64_sve_fminnm:
1649 case Intrinsic::aarch64_sve_fmla:
1651 case Intrinsic::aarch64_sve_fmls:
1653 case Intrinsic::aarch64_sve_fmul:
1656 case Intrinsic::aarch64_sve_fmulx:
1658 case Intrinsic::aarch64_sve_fnmla:
1660 case Intrinsic::aarch64_sve_fnmls:
1662 case Intrinsic::aarch64_sve_fsub:
1665 case Intrinsic::aarch64_sve_add:
1668 case Intrinsic::aarch64_sve_mla:
1670 case Intrinsic::aarch64_sve_mls:
1672 case Intrinsic::aarch64_sve_mul:
1675 case Intrinsic::aarch64_sve_sabd:
1677 case Intrinsic::aarch64_sve_sdiv:
1680 case Intrinsic::aarch64_sve_smax:
1682 case Intrinsic::aarch64_sve_smin:
1684 case Intrinsic::aarch64_sve_smulh:
1686 case Intrinsic::aarch64_sve_sub:
1689 case Intrinsic::aarch64_sve_uabd:
1691 case Intrinsic::aarch64_sve_udiv:
1694 case Intrinsic::aarch64_sve_umax:
1696 case Intrinsic::aarch64_sve_umin:
1698 case Intrinsic::aarch64_sve_umulh:
1700 case Intrinsic::aarch64_sve_asr:
1703 case Intrinsic::aarch64_sve_lsl:
1706 case Intrinsic::aarch64_sve_lsr:
1709 case Intrinsic::aarch64_sve_and:
1712 case Intrinsic::aarch64_sve_bic:
1714 case Intrinsic::aarch64_sve_eor:
1717 case Intrinsic::aarch64_sve_orr:
1720 case Intrinsic::aarch64_sve_shsub:
1722 case Intrinsic::aarch64_sve_shsubr:
1724 case Intrinsic::aarch64_sve_sqrshl:
1726 case Intrinsic::aarch64_sve_sqshl:
1728 case Intrinsic::aarch64_sve_sqsub:
1730 case Intrinsic::aarch64_sve_srshl:
1732 case Intrinsic::aarch64_sve_uhsub:
1734 case Intrinsic::aarch64_sve_uhsubr:
1736 case Intrinsic::aarch64_sve_uqrshl:
1738 case Intrinsic::aarch64_sve_uqshl:
1740 case Intrinsic::aarch64_sve_uqsub:
1742 case Intrinsic::aarch64_sve_urshl:
1745 case Intrinsic::aarch64_sve_add_u:
1748 case Intrinsic::aarch64_sve_and_u:
1751 case Intrinsic::aarch64_sve_asr_u:
1754 case Intrinsic::aarch64_sve_eor_u:
1757 case Intrinsic::aarch64_sve_fadd_u:
1760 case Intrinsic::aarch64_sve_fdiv_u:
1763 case Intrinsic::aarch64_sve_fmul_u:
1766 case Intrinsic::aarch64_sve_fsub_u:
1769 case Intrinsic::aarch64_sve_lsl_u:
1772 case Intrinsic::aarch64_sve_lsr_u:
1775 case Intrinsic::aarch64_sve_mul_u:
1778 case Intrinsic::aarch64_sve_orr_u:
1781 case Intrinsic::aarch64_sve_sdiv_u:
1784 case Intrinsic::aarch64_sve_sub_u:
1787 case Intrinsic::aarch64_sve_udiv_u:
1791 case Intrinsic::aarch64_sve_addqv:
1792 case Intrinsic::aarch64_sve_bic_z:
1793 case Intrinsic::aarch64_sve_brka_z:
1794 case Intrinsic::aarch64_sve_brkb_z:
1795 case Intrinsic::aarch64_sve_brkn_z:
1796 case Intrinsic::aarch64_sve_brkpa_z:
1797 case Intrinsic::aarch64_sve_brkpb_z:
1798 case Intrinsic::aarch64_sve_cntp:
1799 case Intrinsic::aarch64_sve_compact:
1800 case Intrinsic::aarch64_sve_eorv:
1801 case Intrinsic::aarch64_sve_eorqv:
1802 case Intrinsic::aarch64_sve_nand_z:
1803 case Intrinsic::aarch64_sve_nor_z:
1804 case Intrinsic::aarch64_sve_orn_z:
1805 case Intrinsic::aarch64_sve_orv:
1806 case Intrinsic::aarch64_sve_orqv:
1807 case Intrinsic::aarch64_sve_pnext:
1808 case Intrinsic::aarch64_sve_rdffr_z:
1809 case Intrinsic::aarch64_sve_saddv:
1810 case Intrinsic::aarch64_sve_uaddv:
1811 case Intrinsic::aarch64_sve_umaxv:
1812 case Intrinsic::aarch64_sve_umaxqv:
1813 case Intrinsic::aarch64_sve_facge:
1814 case Intrinsic::aarch64_sve_facgt:
1815 case Intrinsic::aarch64_sve_ld1:
1816 case Intrinsic::aarch64_sve_ld1_gather:
1817 case Intrinsic::aarch64_sve_ld1_gather_index:
1818 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1819 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1820 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1821 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1822 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1823 case Intrinsic::aarch64_sve_ld1q_gather_index:
1824 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1825 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1826 case Intrinsic::aarch64_sve_ld1ro:
1827 case Intrinsic::aarch64_sve_ld1rq:
1828 case Intrinsic::aarch64_sve_ld1udq:
1829 case Intrinsic::aarch64_sve_ld1uwq:
1830 case Intrinsic::aarch64_sve_ld2_sret:
1831 case Intrinsic::aarch64_sve_ld2q_sret:
1832 case Intrinsic::aarch64_sve_ld3_sret:
1833 case Intrinsic::aarch64_sve_ld3q_sret:
1834 case Intrinsic::aarch64_sve_ld4_sret:
1835 case Intrinsic::aarch64_sve_ld4q_sret:
1836 case Intrinsic::aarch64_sve_ldff1:
1837 case Intrinsic::aarch64_sve_ldff1_gather:
1838 case Intrinsic::aarch64_sve_ldff1_gather_index:
1839 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1840 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1841 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1842 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1843 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1844 case Intrinsic::aarch64_sve_ldnf1:
1845 case Intrinsic::aarch64_sve_ldnt1:
1846 case Intrinsic::aarch64_sve_ldnt1_gather:
1847 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1848 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1849 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1852 case Intrinsic::aarch64_sve_and_z:
1855 case Intrinsic::aarch64_sve_orr_z:
1858 case Intrinsic::aarch64_sve_eor_z:
1862 case Intrinsic::aarch64_sve_cmpeq:
1863 case Intrinsic::aarch64_sve_cmpeq_wide:
1866 case Intrinsic::aarch64_sve_cmpge:
1867 case Intrinsic::aarch64_sve_cmpge_wide:
1870 case Intrinsic::aarch64_sve_cmpgt:
1871 case Intrinsic::aarch64_sve_cmpgt_wide:
1874 case Intrinsic::aarch64_sve_cmphi:
1875 case Intrinsic::aarch64_sve_cmphi_wide:
1878 case Intrinsic::aarch64_sve_cmphs:
1879 case Intrinsic::aarch64_sve_cmphs_wide:
1882 case Intrinsic::aarch64_sve_cmple_wide:
1885 case Intrinsic::aarch64_sve_cmplo_wide:
1888 case Intrinsic::aarch64_sve_cmpls_wide:
1891 case Intrinsic::aarch64_sve_cmplt_wide:
1894 case Intrinsic::aarch64_sve_cmpne:
1895 case Intrinsic::aarch64_sve_cmpne_wide:
1898 case Intrinsic::aarch64_sve_fcmpeq:
1901 case Intrinsic::aarch64_sve_fcmpge:
1904 case Intrinsic::aarch64_sve_fcmpgt:
1907 case Intrinsic::aarch64_sve_fcmpne:
1910 case Intrinsic::aarch64_sve_fcmpuo:
1914 case Intrinsic::aarch64_sve_prf:
1915 case Intrinsic::aarch64_sve_prfb_gather_index:
1916 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
1917 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
1918 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
1919 case Intrinsic::aarch64_sve_prfd_gather_index:
1920 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
1921 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
1922 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
1923 case Intrinsic::aarch64_sve_prfh_gather_index:
1924 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
1925 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
1926 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
1927 case Intrinsic::aarch64_sve_prfw_gather_index:
1928 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
1929 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
1930 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
1933 case Intrinsic::aarch64_sve_st1_scatter:
1934 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
1935 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
1936 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
1937 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
1938 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
1939 case Intrinsic::aarch64_sve_st1dq:
1940 case Intrinsic::aarch64_sve_st1q_scatter_index:
1941 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
1942 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
1943 case Intrinsic::aarch64_sve_st1wq:
1944 case Intrinsic::aarch64_sve_stnt1:
1945 case Intrinsic::aarch64_sve_stnt1_scatter:
1946 case Intrinsic::aarch64_sve_stnt1_scatter_index:
1947 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
1948 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
1950 case Intrinsic::aarch64_sve_st2:
1951 case Intrinsic::aarch64_sve_st2q:
1953 case Intrinsic::aarch64_sve_st3:
1954 case Intrinsic::aarch64_sve_st3q:
1956 case Intrinsic::aarch64_sve_st4:
1957 case Intrinsic::aarch64_sve_st4q:
1965 Value *UncastedPred;
1971 Pred = UncastedPred;
1977 if (OrigPredTy->getMinNumElements() <=
1979 ->getMinNumElements())
1980 Pred = UncastedPred;
1984 return C &&
C->isAllOnesValue();
1991 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
1992 Dup->getOperand(1) == Pg &&
isa<Constant>(Dup->getOperand(2)))
2000static std::optional<Instruction *>
2007 Value *Op1 =
II.getOperand(1);
2008 Value *Op2 =
II.getOperand(2);
2033 Value *NarrowOp1, *NarrowOp2;
2044 else if (SimpleNarrow == NarrowOp1)
2046 else if (SimpleNarrow == NarrowOp2)
2051 SimpleNarrow->
getType(), SimpleNarrow);
2060 return std::nullopt;
2071 if (SimpleII == Inactive)
2079static std::optional<Instruction *>
2083 assert((
Opc == Instruction::ICmp ||
Opc == Instruction::FCmp) &&
2084 "Expected a compare operation!");
2091 Opc == Instruction::ICmp &&
LHS->getType() !=
RHS->getType();
2092 assert((IsWideICmp ||
LHS->getType() ==
RHS->getType()) &&
2093 "Unexpected wide compare!");
2109 const APInt *LHSVal, *RHSVal;
2111 return std::nullopt;
2134 return std::nullopt;
2148static std::optional<Instruction *>
2152 return std::nullopt;
2181 II.setCalledFunction(NewDecl);
2187 return std::nullopt;
2198 if (
Opc == Instruction::FCmp ||
Opc == Instruction::ICmp)
2201 return std::nullopt;
2213static std::optional<Instruction *>
2215 auto m_ConvertToSVBool = [](
auto P) {
2219 Intrinsic::aarch64_sve_convert_from_svbool;
2242 return std::nullopt;
2246 case Intrinsic::aarch64_sve_and_z:
2247 case Intrinsic::aarch64_sve_bic_z:
2248 case Intrinsic::aarch64_sve_eor_z:
2249 case Intrinsic::aarch64_sve_nand_z:
2250 case Intrinsic::aarch64_sve_nor_z:
2251 case Intrinsic::aarch64_sve_orn_z:
2252 case Intrinsic::aarch64_sve_orr_z:
2255 return std::nullopt;
2258 Value *BinOpPred = BinOp->getOperand(0);
2259 Value *BinOpOp1 = BinOp->getOperand(1);
2260 Value *BinOpOp2 = BinOp->getOperand(2);
2262 Value *NarrowBinOpPred;
2264 return std::nullopt;
2266 Value *NarrowBinOpOp1 =
2268 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2269 if (BinOpOp1 != BinOpOp2)
2273 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2277static std::optional<Instruction *>
2284 return BinOpCombine;
2289 return std::nullopt;
2292 Value *Cursor =
II.getOperand(0), *EarliestReplacement =
nullptr;
2301 if (CursorVTy->getElementCount().getKnownMinValue() <
2302 IVTy->getElementCount().getKnownMinValue())
2306 if (Cursor->getType() == IVTy)
2307 EarliestReplacement = Cursor;
2312 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2313 Intrinsic::aarch64_sve_convert_to_svbool ||
2314 IntrinsicCursor->getIntrinsicID() ==
2315 Intrinsic::aarch64_sve_convert_from_svbool))
2318 CandidatesForRemoval.
insert(CandidatesForRemoval.
begin(), IntrinsicCursor);
2319 Cursor = IntrinsicCursor->getOperand(0);
2324 if (!EarliestReplacement)
2325 return std::nullopt;
2333 auto *OpPredicate =
II.getOperand(0);
2350 II.getArgOperand(2));
2356 return std::nullopt;
2360 II.getArgOperand(0),
II.getArgOperand(2),
uint64_t(0));
2369 II.getArgOperand(0));
2378 if (!
II.hasOneUse())
2379 return std::nullopt;
2382 return std::nullopt;
2385 switch (
II.getIntrinsicID()) {
2386 case Intrinsic::aarch64_sve_cmpne:
2387 IID = Intrinsic::aarch64_sve_cmpeq;
2389 case Intrinsic::aarch64_sve_cmpne_wide:
2390 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2392 case Intrinsic::aarch64_sve_cmpeq:
2393 IID = Intrinsic::aarch64_sve_cmpne;
2395 case Intrinsic::aarch64_sve_cmpeq_wide:
2396 IID = Intrinsic::aarch64_sve_cmpne_wide;
2399 return std::nullopt;
2404 IID,
II.getOperand(1)->getType(),
2405 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2417 return std::nullopt;
2419 for (
auto *U :
II.users()) {
2422 Type *Ty =
II.getOperand(1)->getType();
2427 Intrinsic::aarch64_sve_umin, Ty,
2428 {
II.getOperand(0),
II.getOperand(1), ConstantInt::get(Ty, 1)});
2434 return std::nullopt;
2448 return std::nullopt;
2453 if (!SplatValue || !SplatValue->isZero())
2454 return std::nullopt;
2459 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2460 return std::nullopt;
2464 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2465 return std::nullopt;
2468 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2469 return std::nullopt;
2474 return std::nullopt;
2477 return std::nullopt;
2481 return std::nullopt;
2485 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2486 return std::nullopt;
2488 unsigned NumElts = VecTy->getNumElements();
2489 unsigned PredicateBits = 0;
2492 for (
unsigned I = 0;
I < NumElts; ++
I) {
2495 return std::nullopt;
2497 PredicateBits |= 1 << (
I * (16 / NumElts));
2501 if (PredicateBits == 0) {
2503 PFalse->takeName(&
II);
2509 for (
unsigned I = 0;
I < 16; ++
I)
2510 if ((PredicateBits & (1 <<
I)) != 0)
2513 unsigned PredSize = Mask & -Mask;
2518 for (
unsigned I = 0;
I < 16;
I += PredSize)
2519 if ((PredicateBits & (1 <<
I)) == 0)
2520 return std::nullopt;
2522 auto *ConvertToSVBool =
2525 auto *ConvertFromSVBool =
2527 II.getType(), ConvertToSVBool);
2535 Value *Pg =
II.getArgOperand(0);
2536 Value *Vec =
II.getArgOperand(1);
2537 auto IntrinsicID =
II.getIntrinsicID();
2538 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2550 auto OpC = OldBinOp->getOpcode();
2556 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(),
II.getIterator());
2562 if (IsAfter &&
C &&
C->isNullValue()) {
2566 Extract->insertBefore(
II.getIterator());
2567 Extract->takeName(&
II);
2573 return std::nullopt;
2575 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2576 return std::nullopt;
2578 const auto PTruePattern =
2584 return std::nullopt;
2586 unsigned Idx = MinNumElts - 1;
2596 if (Idx >= PgVTy->getMinNumElements())
2597 return std::nullopt;
2602 Extract->insertBefore(
II.getIterator());
2603 Extract->takeName(&
II);
2616 Value *Pg =
II.getArgOperand(0);
2618 Value *Vec =
II.getArgOperand(2);
2621 if (!Ty->isIntegerTy())
2622 return std::nullopt;
2627 return std::nullopt;
2644 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2659static std::optional<Instruction *>
2663 if (
Pattern == AArch64SVEPredPattern::all) {
2672 return MinNumElts && NumElts >= MinNumElts
2674 II, ConstantInt::get(
II.getType(), MinNumElts)))
2678static std::optional<Instruction *>
2681 if (!ST->isStreaming())
2682 return std::nullopt;
2694 Value *PgVal =
II.getArgOperand(0);
2695 Value *OpVal =
II.getArgOperand(1);
2699 if (PgVal == OpVal &&
2700 (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2701 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2716 return std::nullopt;
2720 if (Pg->
getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2721 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2735 if ((Pg ==
Op) && (
II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2736 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2737 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2738 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2739 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2740 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2741 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2742 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2743 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2744 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2745 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2746 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2747 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2757 return std::nullopt;
2760template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2761static std::optional<Instruction *>
2763 bool MergeIntoAddendOp) {
2765 Value *MulOp0, *MulOp1, *AddendOp, *
Mul;
2766 if (MergeIntoAddendOp) {
2767 AddendOp =
II.getOperand(1);
2768 Mul =
II.getOperand(2);
2770 AddendOp =
II.getOperand(2);
2771 Mul =
II.getOperand(1);
2776 return std::nullopt;
2778 if (!
Mul->hasOneUse())
2779 return std::nullopt;
2782 if (
II.getType()->isFPOrFPVectorTy()) {
2787 return std::nullopt;
2789 return std::nullopt;
2794 if (MergeIntoAddendOp)
2804static std::optional<Instruction *>
2806 Value *Pred =
II.getOperand(0);
2807 Value *PtrOp =
II.getOperand(1);
2808 Type *VecTy =
II.getType();
2823static std::optional<Instruction *>
2825 Value *VecOp =
II.getOperand(0);
2826 Value *Pred =
II.getOperand(1);
2827 Value *PtrOp =
II.getOperand(2);
2843 case Intrinsic::aarch64_sve_fmul_u:
2844 return Instruction::BinaryOps::FMul;
2845 case Intrinsic::aarch64_sve_fadd_u:
2846 return Instruction::BinaryOps::FAdd;
2847 case Intrinsic::aarch64_sve_fsub_u:
2848 return Instruction::BinaryOps::FSub;
2850 return Instruction::BinaryOpsEnd;
2854static std::optional<Instruction *>
2857 if (
II.isStrictFP())
2858 return std::nullopt;
2860 auto *OpPredicate =
II.getOperand(0);
2862 if (BinOpCode == Instruction::BinaryOpsEnd ||
2864 return std::nullopt;
2866 BinOpCode,
II.getOperand(1),
II.getOperand(2),
II.getFastMathFlags());
2870static std::optional<Instruction *>
2872 assert(
II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
2873 "Expected MLA_U intrinsic");
2874 Value *Acc =
II.getArgOperand(1);
2875 Value *MulOp0 =
II.getArgOperand(2);
2876 Value *MulOp1 =
II.getArgOperand(3);
2891 II.setArgOperand(2, MulOp1);
2892 II.setArgOperand(3, MulOp0);
2896 return std::nullopt;
2899static std::optional<Instruction *>
2901 assert((
II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
2902 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
2903 "Expected SADALP or UADALP intrinsic");
2909 return std::nullopt;
2913 return std::nullopt;
2917 II.getIntrinsicID(), {II.getType()},
2918 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
2928 Intrinsic::aarch64_sve_mla>(
2932 Intrinsic::aarch64_sve_mad>(
2935 return std::nullopt;
2938static std::optional<Instruction *>
2942 Intrinsic::aarch64_sve_fmla>(IC,
II,
2947 Intrinsic::aarch64_sve_fmad>(IC,
II,
2952 Intrinsic::aarch64_sve_fmla>(IC,
II,
2955 return std::nullopt;
2958static std::optional<Instruction *>
2962 Intrinsic::aarch64_sve_fmla>(IC,
II,
2967 Intrinsic::aarch64_sve_fmad>(IC,
II,
2972 Intrinsic::aarch64_sve_fmla_u>(
2978static std::optional<Instruction *>
2982 Intrinsic::aarch64_sve_fmls>(IC,
II,
2987 Intrinsic::aarch64_sve_fnmsb>(
2992 Intrinsic::aarch64_sve_fmls>(IC,
II,
2995 return std::nullopt;
2998static std::optional<Instruction *>
3002 Intrinsic::aarch64_sve_fmls>(IC,
II,
3007 Intrinsic::aarch64_sve_fnmsb>(
3012 Intrinsic::aarch64_sve_fmls_u>(
3021 Intrinsic::aarch64_sve_mls>(
3024 return std::nullopt;
3029 Value *UnpackArg =
II.getArgOperand(0);
3031 bool IsSigned =
II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3032 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3045 return std::nullopt;
3049 auto *OpVal =
II.getOperand(0);
3050 auto *OpIndices =
II.getOperand(1);
3057 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3058 return std::nullopt;
3073 Type *RetTy =
II.getType();
3074 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3075 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3079 if ((
match(
II.getArgOperand(0),
3086 if (TyA ==
B->getType() &&
3091 TyA->getMinNumElements());
3097 return std::nullopt;
3105 if (
match(
II.getArgOperand(0),
3110 II, (
II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ?
A :
B));
3112 return std::nullopt;
3115static std::optional<Instruction *>
3117 Value *Mask =
II.getOperand(0);
3118 Value *BasePtr =
II.getOperand(1);
3119 Value *Index =
II.getOperand(2);
3130 BasePtr->getPointerAlignment(
II.getDataLayout());
3133 BasePtr, IndexBase);
3140 return std::nullopt;
3143static std::optional<Instruction *>
3145 Value *Val =
II.getOperand(0);
3146 Value *Mask =
II.getOperand(1);
3147 Value *BasePtr =
II.getOperand(2);
3148 Value *Index =
II.getOperand(3);
3158 BasePtr->getPointerAlignment(
II.getDataLayout());
3161 BasePtr, IndexBase);
3167 return std::nullopt;
3173 Value *Pred =
II.getOperand(0);
3174 Value *Vec =
II.getOperand(1);
3175 Value *DivVec =
II.getOperand(2);
3179 if (!SplatConstantInt)
3180 return std::nullopt;
3184 if (DivisorValue == -1)
3185 return std::nullopt;
3186 if (DivisorValue == 1)
3192 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3199 Intrinsic::aarch64_sve_asrd, {
II.getType()}, {Pred, Vec, DivisorLog2});
3201 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3205 return std::nullopt;
3209 size_t VecSize = Vec.
size();
3214 size_t HalfVecSize = VecSize / 2;
3218 if (*
LHS !=
nullptr && *
RHS !=
nullptr) {
3226 if (*
LHS ==
nullptr && *
RHS !=
nullptr)
3244 return std::nullopt;
3251 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3252 CurrentInsertElt = InsertElt->getOperand(0);
3258 return std::nullopt;
3262 for (
size_t I = 0;
I < Elts.
size();
I++) {
3263 if (Elts[
I] ==
nullptr)
3268 if (InsertEltChain ==
nullptr)
3269 return std::nullopt;
3275 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.
size();
3276 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3277 IIScalableTy->getMinNumElements() /
3282 auto *WideShuffleMaskTy =
3293 auto NarrowBitcast =
3306 return std::nullopt;
3311 Value *Pred =
II.getOperand(0);
3312 Value *Vec =
II.getOperand(1);
3313 Value *Shift =
II.getOperand(2);
3316 Value *AbsPred, *MergedValue;
3322 return std::nullopt;
3330 return std::nullopt;
3335 return std::nullopt;
3338 {
II.getType()}, {Pred, Vec, Shift});
3345 Value *Vec =
II.getOperand(0);
3350 return std::nullopt;
3356 auto *NI =
II.getNextNode();
3359 return !
I->mayReadOrWriteMemory() && !
I->mayHaveSideEffects();
3361 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3362 auto *NIBB = NI->getParent();
3363 NI = NI->getNextNode();
3365 if (
auto *SuccBB = NIBB->getUniqueSuccessor())
3366 NI = &*SuccBB->getFirstNonPHIOrDbgOrLifetime();
3372 if (NextII &&
II.isIdenticalTo(NextII))
3375 return std::nullopt;
3383 {II.getType(), II.getOperand(0)->getType()},
3384 {II.getOperand(0), II.getOperand(1)}));
3391 if (PredPattern == AArch64SVEPredPattern::all ||
3392 PredPattern == AArch64SVEPredPattern::pow2)
3394 return std::nullopt;
3400 Value *Passthru =
II.getOperand(0);
3408 auto *Mask = ConstantInt::get(Ty, MaskValue);
3414 return std::nullopt;
3417static std::optional<Instruction *>
3424 return std::nullopt;
3430 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3440 UMinID,
II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3450 return std::nullopt;
3456 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3464 return std::nullopt;
3467 II.getType(), {Pg, A, B});
3469 UMinID,
II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3478 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3483 Value *
A, *PgLHS, *PgRHS;
3489 !
LHS->hasOneUser() || !
RHS->hasOneUser())
3490 return std::nullopt;
3493 if (ConstB > ConstA)
3499 if (PgLHS != PgRHS || (Pg !=
LHS && Pg !=
RHS && Pg != PgLHS))
3500 return std::nullopt;
3502 Type *VecTy =
A->getType();
3506 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3513std::optional<Instruction *>
3524 case Intrinsic::aarch64_dmb:
3526 case Intrinsic::aarch64_neon_fmaxnm:
3527 case Intrinsic::aarch64_neon_fminnm:
3529 case Intrinsic::aarch64_sve_convert_from_svbool:
3531 case Intrinsic::aarch64_sve_dup:
3533 case Intrinsic::aarch64_sve_dup_x:
3535 case Intrinsic::aarch64_sve_cmpeq:
3536 case Intrinsic::aarch64_sve_cmpeq_wide:
3538 case Intrinsic::aarch64_sve_cmpne:
3539 case Intrinsic::aarch64_sve_cmpne_wide:
3541 case Intrinsic::aarch64_sve_rdffr:
3543 case Intrinsic::aarch64_sve_lasta:
3544 case Intrinsic::aarch64_sve_lastb:
3546 case Intrinsic::aarch64_sve_clasta_n:
3547 case Intrinsic::aarch64_sve_clastb_n:
3549 case Intrinsic::aarch64_sve_cntd:
3551 case Intrinsic::aarch64_sve_cntw:
3553 case Intrinsic::aarch64_sve_cnth:
3555 case Intrinsic::aarch64_sve_cntb:
3557 case Intrinsic::aarch64_sme_cntsd:
3559 case Intrinsic::aarch64_sve_ptest_any:
3560 case Intrinsic::aarch64_sve_ptest_first:
3561 case Intrinsic::aarch64_sve_ptest_last:
3563 case Intrinsic::aarch64_sve_fadd:
3565 case Intrinsic::aarch64_sve_fadd_u:
3567 case Intrinsic::aarch64_sve_fmul_u:
3569 case Intrinsic::aarch64_sve_fsub:
3571 case Intrinsic::aarch64_sve_fsub_u:
3573 case Intrinsic::aarch64_sve_add:
3575 case Intrinsic::aarch64_sve_add_u:
3577 Intrinsic::aarch64_sve_mla_u>(
3579 case Intrinsic::aarch64_sve_mla_u:
3581 case Intrinsic::aarch64_sve_sadalp:
3582 case Intrinsic::aarch64_sve_uadalp:
3584 case Intrinsic::aarch64_sve_sub:
3586 case Intrinsic::aarch64_sve_sub_u:
3588 Intrinsic::aarch64_sve_mls_u>(
3590 case Intrinsic::aarch64_sve_tbl:
3592 case Intrinsic::aarch64_sve_uunpkhi:
3593 case Intrinsic::aarch64_sve_uunpklo:
3594 case Intrinsic::aarch64_sve_sunpkhi:
3595 case Intrinsic::aarch64_sve_sunpklo:
3597 case Intrinsic::aarch64_sve_uzp1:
3599 case Intrinsic::aarch64_sve_zip1:
3600 case Intrinsic::aarch64_sve_zip2:
3602 case Intrinsic::aarch64_sve_ld1_gather_index:
3604 case Intrinsic::aarch64_sve_st1_scatter_index:
3606 case Intrinsic::aarch64_sve_ld1:
3608 case Intrinsic::aarch64_sve_st1:
3610 case Intrinsic::aarch64_sve_sdiv:
3612 case Intrinsic::aarch64_sve_sel:
3614 case Intrinsic::aarch64_sve_srshl:
3616 case Intrinsic::aarch64_sve_dupq_lane:
3618 case Intrinsic::aarch64_sve_insr:
3620 case Intrinsic::aarch64_sve_whilelo:
3622 case Intrinsic::aarch64_sve_ptrue:
3624 case Intrinsic::aarch64_sve_uxtb:
3626 case Intrinsic::aarch64_sve_uxth:
3628 case Intrinsic::aarch64_sve_uxtw:
3630 case Intrinsic::aarch64_sme_in_streaming_mode:
3632 case Intrinsic::aarch64_sve_umin_u:
3634 case Intrinsic::aarch64_sve_orr_u:
3636 case Intrinsic::aarch64_sve_and_z:
3640 return std::nullopt;
3647 SimplifyAndSetOp)
const {
3648 switch (
II.getIntrinsicID()) {
3651 case Intrinsic::aarch64_neon_fcvtxn:
3652 case Intrinsic::aarch64_neon_rshrn:
3653 case Intrinsic::aarch64_neon_sqrshrn:
3654 case Intrinsic::aarch64_neon_sqrshrun:
3655 case Intrinsic::aarch64_neon_sqshrn:
3656 case Intrinsic::aarch64_neon_sqshrun:
3657 case Intrinsic::aarch64_neon_sqxtn:
3658 case Intrinsic::aarch64_neon_sqxtun:
3659 case Intrinsic::aarch64_neon_uqrshrn:
3660 case Intrinsic::aarch64_neon_uqshrn:
3661 case Intrinsic::aarch64_neon_uqxtn:
3662 SimplifyAndSetOp(&
II, 0, OrigDemandedElts, UndefElts);
3666 return std::nullopt;
3670 return ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3680 if (ST->useSVEForFixedLengthVectors() &&
3683 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3684 else if (ST->isNeonAvailable())
3689 if (ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3698bool AArch64TTIImpl::isSingleExtWideningInstruction(
3700 Type *SrcOverrideTy)
const {
3715 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3718 Type *SrcTy = SrcOverrideTy;
3720 case Instruction::Add:
3721 case Instruction::Sub: {
3730 if (Opcode == Instruction::Sub)
3754 assert(SrcTy &&
"Expected some SrcTy");
3756 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3762 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3764 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3768 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3771Type *AArch64TTIImpl::isBinExtWideningInstruction(
unsigned Opcode,
Type *DstTy,
3773 Type *SrcOverrideTy)
const {
3774 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3775 Opcode != Instruction::Mul)
3785 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3788 auto getScalarSizeWithOverride = [&](
const Value *
V) {
3794 ->getScalarSizeInBits();
3797 unsigned MaxEltSize = 0;
3800 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3801 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3802 MaxEltSize = std::max(EltSize0, EltSize1);
3805 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3806 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3809 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3811 MaxEltSize = DstEltSize / 2;
3812 }
else if (Opcode == Instruction::Mul &&
3820 Known.Zero.countLeadingOnes() >
3825 getScalarSizeWithOverride(
isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3829 if (MaxEltSize * 2 > DstEltSize)
3847 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(
DL, Src)) ||
3848 (Src->isScalableTy() && !ST->hasSVE2()))
3858 if (AddUser && AddUser->getOpcode() == Instruction::Add)
3862 if (!Shr || Shr->getOpcode() != Instruction::LShr)
3866 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
3867 Src->getScalarSizeInBits() !=
3891 int ISD = TLI->InstructionOpcodeToISD(Opcode);
3895 if (
I && !
I->users().empty()) {
3899 auto GetUserAbsorbedCastCost =
3900 [&](
const Instruction *Usr) -> std::optional<InstructionCost> {
3903 if (
Type *ExtTy = isBinExtWideningInstruction(
3905 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
3918 if (isSingleExtWideningInstruction(
3920 Src !=
I->getOperand(0)->getType() ? Src :
nullptr)) {
3924 if (Usr->getOpcode() == Instruction::Add) {
3925 if (
I == Usr->getOperand(1) ||
3941 return std::nullopt;
3945 bool AllUsersAbsorbCast =
true;
3946 for (
const User *U :
I->users()) {
3948 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
3950 AllUsersAbsorbCast =
false;
3953 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
3956 if (AllUsersAbsorbCast)
3957 return MaxAbsorbedCost;
3960 EVT SrcTy = TLI->getValueType(
DL, Src);
3961 EVT DstTy = TLI->getValueType(
DL, Dst);
3969 Instruction::ExtractElement, Src,
CostKind, -1,
nullptr,
nullptr);
3971 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH,
CostKind);
3975 if (!SrcTy.isSimple() || !DstTy.
isSimple())
3980 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4009 EVT WiderTy = SrcTy.
bitsGT(DstTy) ? SrcTy : DstTy;
4012 ST->useSVEForFixedLengthVectors(WiderTy)) {
4013 std::pair<InstructionCost, MVT> LT =
4015 unsigned NumElements =
4031 const unsigned int SVE_EXT_COST = 1;
4032 const unsigned int SVE_FCVT_COST = 1;
4033 const unsigned int SVE_UNPACK_ONCE = 4;
4034 const unsigned int SVE_UNPACK_TWICE = 16;
4163 SVE_EXT_COST + SVE_FCVT_COST},
4168 SVE_EXT_COST + SVE_FCVT_COST},
4175 SVE_EXT_COST + SVE_FCVT_COST},
4179 SVE_EXT_COST + SVE_FCVT_COST},
4185 SVE_EXT_COST + SVE_FCVT_COST},
4188 SVE_EXT_COST + SVE_FCVT_COST},
4193 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4195 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4205 SVE_EXT_COST + SVE_FCVT_COST},
4210 SVE_EXT_COST + SVE_FCVT_COST},
4223 SVE_EXT_COST + SVE_FCVT_COST},
4227 SVE_EXT_COST + SVE_FCVT_COST},
4239 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4241 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4243 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4245 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4249 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4251 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4267 SVE_EXT_COST + SVE_FCVT_COST},
4272 SVE_EXT_COST + SVE_FCVT_COST},
4283 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4285 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4287 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4289 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4291 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4293 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4297 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4299 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4301 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4303 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4528 if (ST->hasFullFP16())
4540 Src->getScalarType(), CCH,
CostKind) +
4548 ST->isSVEorStreamingSVEAvailable() &&
4549 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4551 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4560 Opcode, LegalTy, Src, CCH,
CostKind,
I);
4563 return Part1 + Part2;
4570 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4582 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4595 CostKind, Index,
nullptr,
nullptr);
4599 auto DstVT = TLI->getValueType(
DL, Dst);
4600 auto SrcVT = TLI->getValueType(
DL, Src);
4605 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4611 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4621 case Instruction::SExt:
4626 case Instruction::ZExt:
4627 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4640 return Opcode == Instruction::PHI ? 0 : 1;
4649 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4651 assert(Ty->isVectorTy() &&
"This must be a vector type");
4658 if (!LT.second.isVector())
4663 if (LT.second.isFixedLengthVector()) {
4664 unsigned Width = LT.second.getVectorNumElements();
4665 Index = Index % Width;
4672 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4684 if (Index * Ty->getScalarSizeInBits() < 128)
4686 if (Index * Ty->getScalarSizeInBits() < 512 &&
4687 Opcode == Instruction::ExtractElement)
4689 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4690 if (Opcode == Instruction::ExtractElement)
4692 if (Opcode == Instruction::InsertElement)
4701 if (VIC == TTI::VectorInstrContext::Load) {
4702 if (ST->hasFastLD1Single())
4706 : ST->getVectorInsertExtractBaseCost() + 1;
4714 : ST->getVectorInsertExtractBaseCost() + 1;
4738 auto ExtractCanFuseWithFmul = [&]() {
4745 auto IsAllowedScalarTy = [&](
const Type *
T) {
4746 return T->isFloatTy() ||
T->isDoubleTy() ||
4747 (
T->isHalfTy() && ST->hasFullFP16());
4751 auto IsUserFMulScalarTy = [](
const Value *EEUser) {
4754 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4755 !BO->getType()->isVectorTy();
4760 auto IsExtractLaneEquivalentToZero = [&](
unsigned Idx,
unsigned EltSz) {
4764 return Idx == 0 || (RegWidth != 0 && (Idx * EltSz) % RegWidth == 0);
4773 DenseMap<User *, unsigned> UserToExtractIdx;
4774 for (
auto *U :
Scalar->users()) {
4775 if (!IsUserFMulScalarTy(U))
4779 UserToExtractIdx[
U];
4781 if (UserToExtractIdx.
empty())
4783 for (
auto &[S, U, L] : ScalarUserAndIdx) {
4784 for (
auto *U : S->users()) {
4785 if (UserToExtractIdx.
contains(U)) {
4787 auto *Op0 =
FMul->getOperand(0);
4788 auto *Op1 =
FMul->getOperand(1);
4789 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
4790 UserToExtractIdx[
U] =
L;
4796 for (
auto &[U, L] : UserToExtractIdx) {
4808 return !EE->users().empty() &&
all_of(EE->users(), [&](
const User *U) {
4809 if (!IsUserFMulScalarTy(U))
4814 const auto *BO = cast<BinaryOperator>(U);
4815 const auto *OtherEE = dyn_cast<ExtractElementInst>(
4816 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
4818 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
4821 return IsExtractLaneEquivalentToZero(
4822 cast<ConstantInt>(OtherEE->getIndexOperand())
4825 OtherEE->getType()->getScalarSizeInBits());
4833 if (Opcode == Instruction::ExtractElement && (
I || Scalar) &&
4834 ExtractCanFuseWithFmul())
4839 :
ST->getVectorInsertExtractBaseCost();
4848 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
4851 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr,
nullptr,
4857 Value *Scalar,
ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4859 return getVectorInstrCostHelper(Opcode, Ty,
CostKind, Index,
nullptr, Scalar,
4860 ScalarUserAndIdx, VIC);
4867 return getVectorInstrCostHelper(
I.getOpcode(), Ty,
CostKind, Index, &
I,
4874 unsigned Index)
const {
4885 : ST->getVectorInsertExtractBaseCost() + 1;
4894 if (Ty->getElementType()->isFloatingPointTy())
4897 unsigned VecInstCost =
4899 return DemandedElts.
popcount() * (Insert + Extract) * VecInstCost;
4906 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
4907 return std::nullopt;
4908 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
4909 return std::nullopt;
4911 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
4912 return std::nullopt;
4919 Cost += InstCost(PromotedTy);
4941 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4948 Op2Info, Args, CxtI);
4955 Ty,
CostKind, Op1Info, Op2Info,
true,
4958 [&](
Type *PromotedTy) {
4962 return *PromotedCost;
4965 if (Ty->getScalarType()->isFP128Ty())
4973 if (
Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
4993 ST->hasLimited64bitVectorMulBandwidth())
4996 if (Ty->getScalarSizeInBits() > 64) {
5001 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5004 if (LT.second == MVT::v2i64) {
5008 return LT.first * Mul64CostFactor;
5029 if (LT.second == MVT::nxv2i64)
5030 return LT.first * Mul64CostFactor;
5089 auto VT = TLI->getValueType(
DL, Ty);
5090 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5094 : (3 * AsrCost + AddCost);
5096 return MulCost + AsrCost + 2 * AddCost;
5098 }
else if (VT.isVector()) {
5108 if (Ty->isScalableTy() && ST->hasSVE())
5109 Cost += 2 * AsrCost;
5114 ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5118 }
else if (LT.second == MVT::v2i64) {
5119 return VT.getVectorNumElements() *
5126 if (Ty->isScalableTy() && ST->hasSVE())
5127 return MulCost + 2 * AddCost + 2 * AsrCost;
5128 return 2 * MulCost + AddCost + AsrCost + UsraCost;
5133 LT.second.isFixedLengthVector()) {
5143 return ExtractCost + InsertCost +
5151 auto VT = TLI->getValueType(
DL, Ty);
5167 bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||
5168 LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||
5169 LT.second == MVT::nxv16i8;
5170 bool Is128bit = LT.second.is128BitVector();
5182 (HasMULH ? 0 : ShrCost) +
5183 AddCost * 2 + ShrCost;
5184 return DivCost + (
ISD ==
ISD::UREM ? MulCost + AddCost : 0);
5191 if (!VT.isVector() && VT.getSizeInBits() > 64)
5195 Opcode, Ty,
CostKind, Op1Info, Op2Info);
5197 if (TLI->isOperationLegalOrCustom(
ISD, LT.second) && ST->hasSVE()) {
5201 Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {
5211 if (
nullptr != Entry)
5219 FVTy && LT.second.isFixedLengthVector()) {
5220 unsigned NumElts = FVTy->getNumElements();
5221 unsigned RegElts = LT.second.getVectorNumElements();
5223 Cost = (NumElts / RegElts +
popcount(NumElts % RegElts)) * 2;
5227 if (LT.second.getScalarType() == MVT::i8)
5229 else if (LT.second.getScalarType() == MVT::i16)
5241 Opcode, Ty->getScalarType(),
CostKind, Op1Info, Op2Info);
5242 return (4 + DivCost) * VTy->getNumElements();
5248 -1,
nullptr,
nullptr);
5275 LT.second.isFixedLengthVector())
5276 return 2 * LT.first + 1;
5285 if ((Ty->isFloatTy() || Ty->isDoubleTy() ||
5286 (Ty->isHalfTy() && ST->hasFullFP16())) &&
5295 if (!Ty->getScalarType()->isFP128Ty())
5302 if (!Ty->getScalarType()->isFP128Ty())
5303 return 2 * LT.first;
5310 if (!Ty->isVectorTy())
5326 int MaxMergeDistance = 64;
5330 return NumVectorInstToHideOverhead;
5340 unsigned Opcode1,
unsigned Opcode2)
const {
5343 if (!
Sched.hasInstrSchedModel())
5347 Sched.getSchedClassDesc(
TII->get(Opcode1).getSchedClass());
5349 Sched.getSchedClassDesc(
TII->get(Opcode2).getSchedClass());
5355 "Cannot handle variant scheduling classes without an MI");
5371 const int AmortizationCost = 20;
5379 VecPred = CurrentPred;
5387 static const auto ValidMinMaxTys = {
5388 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5389 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5390 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5394 (ST->hasFullFP16() &&
5400 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5401 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5402 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5403 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5404 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5405 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5406 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5407 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5408 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5409 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5410 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5412 EVT SelCondTy = TLI->getValueType(
DL, CondTy);
5413 EVT SelValTy = TLI->getValueType(
DL, ValTy);
5422 if (Opcode == Instruction::FCmp) {
5424 ValTy,
CostKind, Op1Info, Op2Info,
false,
5426 false, [&](
Type *PromotedTy) {
5438 return *PromotedCost;
5442 if (LT.second.getScalarType() != MVT::f64 &&
5443 LT.second.getScalarType() != MVT::f32 &&
5444 LT.second.getScalarType() != MVT::f16)
5449 unsigned Factor = 1;
5450 if (!CondTy->isVectorTy() &&
5464 AArch64::FCMEQv4f32))
5476 TLI->isTypeLegal(TLI->getValueType(
DL, ValTy)) &&
5495 Op1Info, Op2Info,
I);
5501 if (ST->requiresStrictAlign()) {
5506 Options.AllowOverlappingLoads =
true;
5507 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5512 Options.LoadSizes = {8, 4, 2, 1};
5513 Options.AllowedTailExpansions = {3, 5, 6};
5518 return ST->hasSVE();
5524 switch (MICA.
getID()) {
5525 case Intrinsic::masked_scatter:
5526 case Intrinsic::masked_gather:
5528 case Intrinsic::masked_load:
5529 case Intrinsic::masked_store:
5530 case Intrinsic::masked_expandload:
5531 case Intrinsic::masked_compressstore:
5545 if (!LT.first.isValid())
5550 if (VT->getElementType()->isIntegerTy(1))
5561 if (MICA.
getID() == Intrinsic::masked_expandload) {
5569 if (MICA.
getID() == Intrinsic::masked_compressstore) {
5590 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5591 return MemOpCost * 2;
5600 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5601 "Should be called on only load or stores.");
5603 case Instruction::Load:
5606 return ST->getGatherOverhead();
5608 case Instruction::Store:
5611 return ST->getScatterOverhead();
5622 unsigned Opcode = (MICA.
getID() == Intrinsic::masked_gather ||
5623 MICA.
getID() == Intrinsic::vp_gather)
5625 : Instruction::Store;
5635 if (!LT.first.isValid())
5639 if (!LT.second.isVector() ||
5641 VT->getElementType()->isIntegerTy(1))
5651 ElementCount LegalVF = LT.second.getVectorElementCount();
5654 {TTI::OK_AnyValue, TTI::OP_None},
I);
5670 EVT VT = TLI->getValueType(
DL, Ty,
true);
5672 if (VT == MVT::Other)
5677 if (!LT.first.isValid())
5687 (VTy->getElementType()->isIntegerTy(1) &&
5688 !VTy->getElementCount().isKnownMultipleOf(
5698 if (Opcode == Instruction::Store)
5702 if (ST->getFixedLoadLatency())
5703 return (LT.first - 1) + ST->getFixedLoadLatency();
5712 if (LT.second.isScalableVector() ||
5713 ST->useSVEForFixedLengthVectors(LT.second)) {
5714 Inst = AArch64::LDR_ZXI;
5715 }
else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5716 switch (LT.second.getSizeInBits()) {
5718 Inst = AArch64::LDRBui;
5721 Inst = AArch64::LDRHui;
5724 Inst = AArch64::LDRSui;
5727 Inst = AArch64::LDRDui;
5730 Inst = AArch64::LDRQui;
5736 switch (LT.second.getSizeInBits()) {
5738 Inst = AArch64::LDRBBui;
5741 Inst = AArch64::LDRHHui;
5744 Inst = AArch64::LDRWui;
5747 Inst = AArch64::LDRXui;
5755 unsigned SchedClass =
TII->get(Inst).getSchedClass();
5757 ?
Sched.getSchedClassDesc(SchedClass)
5763 return (LT.first - 1) + ST->getLoadLatency();
5766 float NumLoads = (LT.first - 1).
getValue();
5767 return NumLoads *
Sched.getReciprocalThroughput(*ST, *SCD) +
5768 Sched.computeInstrLatency(*ST, *SCD);
5771 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
5772 LT.second.is128BitVector() && Alignment <
Align(16)) {
5778 const int AmortizationCost = 6;
5780 return LT.first * 2 * AmortizationCost;
5784 if (Ty->isPtrOrPtrVectorTy())
5789 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
5791 if (VT == MVT::v4i8)
5798 if (!
isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
5799 Alignment !=
Align(1))
5811 if (Remainder != 0) {
5814 while (!TypeWorklist.
empty()) {
5824 TypeWorklist.
push_back({CurrNumElements - PrevPow2,
Offset + PrevPow2});
5836 bool UseMaskForCond,
bool UseMaskForGaps)
const {
5837 assert(Factor >= 2 &&
"Invalid interleave factor");
5846 if (Factor > TLI->getMaxSupportedInterleaveFactor())
5850 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
5855 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
5860 (UseMaskForCond || UseMaskForGaps ||
5861 (Factor > MaxNativeInterleaveFactor &&
5862 TLI->useSVEForFixedLengthVectorVT(LT.second))))
5865 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
5868 EC.divideCoefficientBy(Factor));
5874 if (EC.isKnownMultipleOf(Factor) &&
5875 TLI->isLegalInterleavedAccessType(SubVecTy,
DL, UseScalable))
5876 return Factor * TLI->getNumInterleavedAccesses(SubVecTy,
DL, UseScalable);
5881 if (VecTy->
isScalableTy() && EC.isKnownMultipleOf(Factor)) {
5887 if (UseMaskForCond) {
5888 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5889 : Intrinsic::masked_store;
5909 if (Opcode == Instruction::Store && Factor == 4 &&
5910 SubVecCost.second.getScalarSizeInBits() ==
5911 (4 * ResultCost.second.getScalarSizeInBits()))
5912 LegalizationCost *= 4;
5914 return MemCost + (Factor * LegalizationCost) + (Factor *
Log2_64(Factor));
5920 UseMaskForCond, UseMaskForGaps);
5927 for (
auto *
I : Tys) {
5928 if (!
I->isVectorTy())
5939 Align Alignment)
const {
5946 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
5947 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
5952 bool HasUnorderedReductions)
const {
5955 return ST->getMaxInterleaveFactor();
5965 enum { MaxStridedLoads = 7 };
5967 int StridedLoads = 0;
5970 for (
const auto BB : L->blocks()) {
5971 for (
auto &
I : *BB) {
5977 if (L->isLoopInvariant(PtrValue))
5982 if (!LSCEVAddRec || !LSCEVAddRec->
isAffine())
5991 if (StridedLoads > MaxStridedLoads / 2)
5992 return StridedLoads;
5995 return StridedLoads;
5998 int StridedLoads = countStridedLoads(L, SE);
6000 <<
" strided loads\n");
6016 unsigned *FinalSize) {
6020 for (
auto *BB : L->getBlocks()) {
6021 for (
auto &
I : *BB) {
6027 if (!Cost.isValid())
6031 if (LoopCost > Budget)
6053 if (MaxTC > 0 && MaxTC <= 32)
6064 if (Blocks.
size() != 2)
6086 if (!L->isInnermost() || L->getNumBlocks() > 8)
6090 if (!L->getExitBlock())
6096 bool HasParellelizableReductions =
6097 L->getNumBlocks() == 1 &&
6098 any_of(L->getHeader()->phis(),
6100 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6103 if (HasParellelizableReductions &&
6125 if (HasParellelizableReductions) {
6136 if (Header == Latch) {
6139 unsigned Width = 10;
6145 unsigned MaxInstsPerLine = 16;
6147 unsigned BestUC = 1;
6148 unsigned SizeWithBestUC = BestUC *
Size;
6150 unsigned SizeWithUC = UC *
Size;
6151 if (SizeWithUC > 48)
6153 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6154 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6156 SizeWithBestUC = BestUC *
Size;
6166 for (
auto *BB : L->blocks()) {
6167 for (
auto &
I : *BB) {
6177 for (
auto *U :
I.users())
6179 LoadedValuesPlus.
insert(U);
6186 return LoadedValuesPlus.
contains(
SI->getOperand(0));
6212 auto *I = dyn_cast<Instruction>(V);
6213 return I && DependsOnLoopLoad(I, Depth + 1);
6220 DependsOnLoopLoad(
I, 0)) {
6252 if (L->getLoopDepth() > 1)
6263 for (
auto *BB : L->getBlocks()) {
6264 for (
auto &
I : *BB) {
6268 if (IsVectorized &&
I.getType()->isVectorTy())
6285 if (ST->isAppleMLike())
6287 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6309 !ST->getSchedModel().isOutOfOrder()) {
6332 bool CanCreate)
const {
6336 case Intrinsic::aarch64_neon_st1x2:
6337 case Intrinsic::aarch64_neon_st1x3:
6338 case Intrinsic::aarch64_neon_st1x4:
6339 case Intrinsic::aarch64_neon_st2:
6340 case Intrinsic::aarch64_neon_st3:
6341 case Intrinsic::aarch64_neon_st4: {
6344 if (!CanCreate || !ST)
6346 unsigned NumElts = Inst->
arg_size() - 1;
6347 if (ST->getNumElements() != NumElts)
6349 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6355 for (
unsigned i = 0, e = NumElts; i != e; ++i) {
6357 Res = Builder.CreateInsertValue(Res, L, i);
6361 case Intrinsic::aarch64_neon_ld1x2:
6362 case Intrinsic::aarch64_neon_ld1x3:
6363 case Intrinsic::aarch64_neon_ld1x4:
6364 case Intrinsic::aarch64_neon_ld2:
6365 case Intrinsic::aarch64_neon_ld3:
6366 case Intrinsic::aarch64_neon_ld4:
6367 if (Inst->
getType() == ExpectedType)
6378 case Intrinsic::aarch64_neon_ld1x2:
6379 case Intrinsic::aarch64_neon_ld1x3:
6380 case Intrinsic::aarch64_neon_ld1x4:
6381 case Intrinsic::aarch64_neon_ld2:
6382 case Intrinsic::aarch64_neon_ld3:
6383 case Intrinsic::aarch64_neon_ld4:
6384 Info.ReadMem =
true;
6385 Info.WriteMem =
false;
6388 case Intrinsic::aarch64_neon_st1x2:
6389 case Intrinsic::aarch64_neon_st1x3:
6390 case Intrinsic::aarch64_neon_st1x4:
6391 case Intrinsic::aarch64_neon_st2:
6392 case Intrinsic::aarch64_neon_st3:
6393 case Intrinsic::aarch64_neon_st4:
6394 Info.ReadMem =
false;
6395 Info.WriteMem =
true;
6404 case Intrinsic::aarch64_neon_ld1x2:
6405 case Intrinsic::aarch64_neon_st1x2:
6406 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6408 case Intrinsic::aarch64_neon_ld1x3:
6409 case Intrinsic::aarch64_neon_st1x3:
6410 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6412 case Intrinsic::aarch64_neon_ld1x4:
6413 case Intrinsic::aarch64_neon_st1x4:
6414 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6416 case Intrinsic::aarch64_neon_ld2:
6417 case Intrinsic::aarch64_neon_st2:
6418 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6420 case Intrinsic::aarch64_neon_ld3:
6421 case Intrinsic::aarch64_neon_st3:
6422 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6424 case Intrinsic::aarch64_neon_ld4:
6425 case Intrinsic::aarch64_neon_st4:
6426 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6438 const Instruction &
I,
bool &AllowPromotionWithoutCommonHeader)
const {
6439 bool Considerable =
false;
6440 AllowPromotionWithoutCommonHeader =
false;
6443 Type *ConsideredSExtType =
6445 if (
I.getType() != ConsideredSExtType)
6449 for (
const User *U :
I.users()) {
6451 Considerable =
true;
6455 if (GEPInst->getNumOperands() > 2) {
6456 AllowPromotionWithoutCommonHeader =
true;
6461 return Considerable;
6512 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6522 return LegalizationCost + 2;
6532 LegalizationCost *= LT.first - 1;
6535 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6544 return LegalizationCost + 2;
6552 std::optional<FastMathFlags> FMF,
6568 return BaseCost + FixedVTy->getNumElements();
6582 MVT MTy = LT.second;
6587 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6635 MTy.
isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6636 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6648 return (LT.first - 1) +
Log2_32(NElts);
6653 return (LT.first - 1) + Entry->Cost;
6665 if (LT.first != 1) {
6671 ExtraCost *= LT.first - 1;
6674 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
6675 return Cost + ExtraCost;
6683 unsigned Opcode,
bool IsUnsigned,
Type *ResTy,
VectorType *VecTy,
6685 EVT VecVT = TLI->getValueType(
DL, VecTy);
6686 EVT ResVT = TLI->getValueType(
DL, ResTy);
6696 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6698 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
6700 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
6702 return (LT.first - 1) * 2 + 2;
6713 EVT VecVT = TLI->getValueType(
DL, VecTy);
6714 EVT ResVT = TLI->getValueType(
DL, ResTy);
6717 RedOpcode == Instruction::Add) {
6723 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6725 return LT.first + 2;
6760 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
6761 ? TLI->getPromotedVTForPredicate(
EVT(LT.second))
6775 if (LT.second.getScalarType() == MVT::i1) {
6784 assert(Entry &&
"Illegal Type for Splice");
6785 LegalizationCost += Entry->Cost;
6786 return LegalizationCost * LT.first;
6790 unsigned Opcode,
Type *InputTypeA,
Type *InputTypeB,
Type *AccumType,
6799 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
6800 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
6806 assert(FMF &&
"Missing FastMathFlags for floating-point partial reduction");
6807 if (!FMF->allowReassoc() || !FMF->allowContract())
6811 "FastMathFlags only apply to floating-point partial reductions");
6815 (!BinOp || (OpBExtend !=
TTI::PR_None && InputTypeB)) &&
6816 "Unexpected values for OpBExtend or InputTypeB");
6820 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
6821 InputTypeA != InputTypeB))
6832 assert(!OpBExtend &&
"Extended second operand without extended first.");
6833 assert(InputTypeA == AccumType &&
"Type mismatch with no extensions.");
6839 bool IsUSDot = OpBExtend !=
TTI::PR_None && OpAExtend != OpBExtend;
6842 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
6855 auto TC = TLI->getTypeConversion(AccumVectorType->
getContext(),
6864 if (TLI->getTypeAction(AccumVectorType->
getContext(), TC.second) !=
6870 std::pair<InstructionCost, MVT> AccumLT =
6872 std::pair<InstructionCost, MVT> InputLT =
6876 auto IsSupported = [&](
bool SVEPred,
bool NEONPred) ->
bool {
6877 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
6878 (AccumLT.second.isFixedLengthVector() &&
6879 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
6883 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
6891 if (AccumLT.second.getScalarType() == MVT::i32 &&
6892 InputLT.second.getScalarType() == MVT::i8) {
6894 if (!IsUSDot && IsSupported(
true, ST->hasDotProd()))
6895 return Cost + INegCost;
6897 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
6898 return Cost + INegCost;
6903 if (IsUSDot && IsSupported(
false, ST->hasDotProd()))
6904 return Cost * 3 + INegCost;
6907 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
6909 if (AccumLT.second.getScalarType() == MVT::i64 &&
6910 InputLT.second.getScalarType() == MVT::i16)
6911 return Cost + INegCost;
6914 if (AccumLT.second.getScalarType() == MVT::i32 &&
6915 InputLT.second.getScalarType() == MVT::i16 &&
6916 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
6919 if (AccumLT.second.getScalarType() == MVT::i64 &&
6920 InputLT.second.getScalarType() == MVT::i8)
6926 return Cost + INegCost;
6929 if (AccumLT.second.getScalarType() == MVT::i16 &&
6930 InputLT.second.getScalarType() == MVT::i8 &&
6931 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
6937 if (Opcode == Instruction::FAdd && !IsSub &&
6938 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
6939 AccumLT.second.getScalarType() == MVT::f32 &&
6940 InputLT.second.getScalarType() == MVT::f16)
6944 if (Ratio == 2 && !IsUSDot) {
6945 MVT InVT = InputLT.second.getScalarType();
6949 if (IsSupported(ST->hasSVE2() || ST->hasSME(),
true) &&
6951 return (BinOp || IsSub) ?
Cost * 2 :
Cost;
6954 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
6958 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(),
false) &&
6959 InVT == MVT::bf16 && IsSub)
6969 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
6970 return Cost * 2 + FNegCost;
6974 AccumType, VF, OpAExtend, OpBExtend,
6985 "Expected the Mask to match the return size if given");
6987 "Expected the same scalar types");
6993 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
6994 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
6995 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7003 return std::max<InstructionCost>(1, LT.first / 4);
7011 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7013 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7016 unsigned TpNumElts = Mask.size();
7017 unsigned LTNumElts = LT.second.getVectorNumElements();
7018 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7020 LT.second.getVectorElementCount());
7022 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>,
InstructionCost>
7024 for (
unsigned N = 0;
N < NumVecs;
N++) {
7028 unsigned Source1 = -1U, Source2 = -1U;
7029 unsigned NumSources = 0;
7030 for (
unsigned E = 0; E < LTNumElts; E++) {
7031 int MaskElt = (
N * LTNumElts + E < TpNumElts) ? Mask[
N * LTNumElts + E]
7040 unsigned Source = MaskElt / LTNumElts;
7041 if (NumSources == 0) {
7044 }
else if (NumSources == 1 && Source != Source1) {
7047 }
else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7053 if (Source == Source1)
7055 else if (Source == Source2)
7056 NMask.
push_back(MaskElt % LTNumElts + LTNumElts);
7065 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7076 NTp, NTp,
CostKind, NMask, 0,
nullptr, Args,
7079 Result.first->second = NCost;
7093 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7094 if (LT.second.getFixedSizeInBits() >= 128 &&
7096 LT.second.getVectorNumElements() / 2) {
7099 if (Index == (
int)LT.second.getVectorNumElements() / 2)
7113 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7116 return M.value() < 0 || M.value() == (int)M.index();
7122 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7123 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7132 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7133 ST->isSVEorStreamingSVEAvailable() &&
7138 if (ST->isSVEorStreamingSVEAvailable() &&
7152 if (IsLoad && LT.second.isVector() &&
7154 LT.second.getVectorElementCount()))
7160 if (Mask.size() == 4 &&
7162 (SrcTy->getScalarSizeInBits() == 16 ||
7163 SrcTy->getScalarSizeInBits() == 32) &&
7164 all_of(Mask, [](
int E) {
return E < 8; }))
7170 if (LT.second.isFixedLengthVector() &&
7171 LT.second.getVectorNumElements() == Mask.size() &&
7177 (
isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7178 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7179 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7180 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7181 LT.second.getVectorNumElements(), 16) ||
7182 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7183 LT.second.getVectorNumElements(), 32) ||
7184 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7185 LT.second.getVectorNumElements(), 64) ||
7188 [&Mask](
int M) {
return M < 0 || M == Mask[0]; })))
7317 return LT.first * Entry->Cost;
7326 LT.second.getSizeInBits() <= 128 && SubTp) {
7328 if (SubLT.second.isVector()) {
7329 int NumElts = LT.second.getVectorNumElements();
7330 int NumSubElts = SubLT.second.getVectorNumElements();
7331 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7337 if (IsExtractSubvector)
7358 if (
getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7371 return ST->useFixedOverScalableIfEqualCost();
7375 return ST->getEpilogueVectorizationMinVF();
7410 unsigned NumInsns = 0;
7412 NumInsns += BB->size();
7422 int64_t Scale,
unsigned AddrSpace)
const {
7450 if (
I->getOpcode() == Instruction::Or &&
7454 if (
I->getOpcode() == Instruction::Add ||
7455 I->getOpcode() == Instruction::Sub)
7480 return all_equal(Shuf->getShuffleMask());
7487 bool AllowSplat =
false) {
7492 auto areTypesHalfed = [](
Value *FullV,
Value *HalfV) {
7493 auto *FullTy = FullV->
getType();
7494 auto *HalfTy = HalfV->getType();
7496 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7499 auto extractHalf = [](
Value *FullV,
Value *HalfV) {
7502 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7506 Value *S1Op1 =
nullptr, *S2Op1 =
nullptr;
7520 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7521 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7535 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7536 (M2Start != 0 && M2Start != (NumElements / 2)))
7538 if (S1Op1 && S2Op1 && M1Start != M2Start)
7548 return Ext->getType()->getScalarSizeInBits() ==
7549 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7563 Value *VectorOperand =
nullptr;
7580 if (!
GEP ||
GEP->getNumOperands() != 2)
7584 Value *Offsets =
GEP->getOperand(1);
7587 if (
Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7593 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7594 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7595 Ops.push_back(&
GEP->getOperandUse(1));
7631 switch (
II->getIntrinsicID()) {
7632 case Intrinsic::aarch64_neon_smull:
7633 case Intrinsic::aarch64_neon_umull:
7636 Ops.push_back(&
II->getOperandUse(0));
7637 Ops.push_back(&
II->getOperandUse(1));
7642 case Intrinsic::fma:
7643 case Intrinsic::fmuladd:
7650 Ops.push_back(&
II->getOperandUse(0));
7652 Ops.push_back(&
II->getOperandUse(1));
7655 case Intrinsic::aarch64_neon_sqdmull:
7656 case Intrinsic::aarch64_neon_sqdmulh:
7657 case Intrinsic::aarch64_neon_sqrdmulh:
7660 Ops.push_back(&
II->getOperandUse(0));
7662 Ops.push_back(&
II->getOperandUse(1));
7663 return !
Ops.empty();
7664 case Intrinsic::aarch64_neon_fmlal:
7665 case Intrinsic::aarch64_neon_fmlal2:
7666 case Intrinsic::aarch64_neon_fmlsl:
7667 case Intrinsic::aarch64_neon_fmlsl2:
7670 Ops.push_back(&
II->getOperandUse(1));
7672 Ops.push_back(&
II->getOperandUse(2));
7673 return !
Ops.empty();
7674 case Intrinsic::aarch64_sve_ptest_first:
7675 case Intrinsic::aarch64_sve_ptest_last:
7677 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
7678 Ops.push_back(&
II->getOperandUse(0));
7679 return !
Ops.empty();
7680 case Intrinsic::aarch64_sme_write_horiz:
7681 case Intrinsic::aarch64_sme_write_vert:
7682 case Intrinsic::aarch64_sme_writeq_horiz:
7683 case Intrinsic::aarch64_sme_writeq_vert: {
7685 if (!Idx || Idx->getOpcode() != Instruction::Add)
7687 Ops.push_back(&
II->getOperandUse(1));
7690 case Intrinsic::aarch64_sme_read_horiz:
7691 case Intrinsic::aarch64_sme_read_vert:
7692 case Intrinsic::aarch64_sme_readq_horiz:
7693 case Intrinsic::aarch64_sme_readq_vert:
7694 case Intrinsic::aarch64_sme_ld1b_vert:
7695 case Intrinsic::aarch64_sme_ld1h_vert:
7696 case Intrinsic::aarch64_sme_ld1w_vert:
7697 case Intrinsic::aarch64_sme_ld1d_vert:
7698 case Intrinsic::aarch64_sme_ld1q_vert:
7699 case Intrinsic::aarch64_sme_st1b_vert:
7700 case Intrinsic::aarch64_sme_st1h_vert:
7701 case Intrinsic::aarch64_sme_st1w_vert:
7702 case Intrinsic::aarch64_sme_st1d_vert:
7703 case Intrinsic::aarch64_sme_st1q_vert:
7704 case Intrinsic::aarch64_sme_ld1b_horiz:
7705 case Intrinsic::aarch64_sme_ld1h_horiz:
7706 case Intrinsic::aarch64_sme_ld1w_horiz:
7707 case Intrinsic::aarch64_sme_ld1d_horiz:
7708 case Intrinsic::aarch64_sme_ld1q_horiz:
7709 case Intrinsic::aarch64_sme_st1b_horiz:
7710 case Intrinsic::aarch64_sme_st1h_horiz:
7711 case Intrinsic::aarch64_sme_st1w_horiz:
7712 case Intrinsic::aarch64_sme_st1d_horiz:
7713 case Intrinsic::aarch64_sme_st1q_horiz: {
7715 if (!Idx || Idx->getOpcode() != Instruction::Add)
7717 Ops.push_back(&
II->getOperandUse(3));
7720 case Intrinsic::aarch64_neon_pmull:
7723 Ops.push_back(&
II->getOperandUse(0));
7724 Ops.push_back(&
II->getOperandUse(1));
7726 case Intrinsic::aarch64_neon_pmull64:
7728 II->getArgOperand(1)))
7730 Ops.push_back(&
II->getArgOperandUse(0));
7731 Ops.push_back(&
II->getArgOperandUse(1));
7733 case Intrinsic::masked_gather:
7736 Ops.push_back(&
II->getArgOperandUse(0));
7738 case Intrinsic::masked_scatter:
7741 Ops.push_back(&
II->getArgOperandUse(1));
7748 auto ShouldSinkCondition = [](
Value *
Cond,
7753 if (
II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
7757 Ops.push_back(&
II->getOperandUse(0));
7761 switch (
I->getOpcode()) {
7762 case Instruction::GetElementPtr:
7763 case Instruction::Add:
7764 case Instruction::Sub:
7766 for (
unsigned Op = 0;
Op <
I->getNumOperands(); ++
Op) {
7768 Ops.push_back(&
I->getOperandUse(
Op));
7773 case Instruction::Select: {
7774 if (!ShouldSinkCondition(
I->getOperand(0),
Ops))
7777 Ops.push_back(&
I->getOperandUse(0));
7780 case Instruction::UncondBr:
7782 case Instruction::CondBr: {
7786 Ops.push_back(&
I->getOperandUse(0));
7789 case Instruction::FMul:
7794 Ops.push_back(&
I->getOperandUse(0));
7796 Ops.push_back(&
I->getOperandUse(1));
7806 case Instruction::Xor:
7809 if (
I->getType()->isVectorTy() && ST->isNeonAvailable()) {
7811 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
7816 case Instruction::And:
7817 case Instruction::Or:
7820 if (
I->getOpcode() == Instruction::Or &&
7825 if (!(
I->getType()->isVectorTy() && ST->hasNEON()) &&
7828 for (
auto &
Op :
I->operands()) {
7840 Ops.push_back(&Not);
7841 Ops.push_back(&InsertElt);
7851 if (!
I->getType()->isVectorTy())
7852 return !
Ops.empty();
7854 switch (
I->getOpcode()) {
7855 case Instruction::Sub:
7856 case Instruction::Add: {
7865 Ops.push_back(&Ext1->getOperandUse(0));
7866 Ops.push_back(&Ext2->getOperandUse(0));
7869 Ops.push_back(&
I->getOperandUse(0));
7870 Ops.push_back(&
I->getOperandUse(1));
7874 case Instruction::Or: {
7877 if (ST->hasNEON()) {
7891 if (
I->getParent() != MainAnd->
getParent() ||
7896 if (
I->getParent() != IA->getParent() ||
7897 I->getParent() != IB->getParent())
7902 Ops.push_back(&
I->getOperandUse(0));
7903 Ops.push_back(&
I->getOperandUse(1));
7912 case Instruction::Mul: {
7913 auto ShouldSinkSplatForIndexedVariant = [](
Value *V) {
7916 if (Ty->isScalableTy())
7920 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
7923 int NumZExts = 0, NumSExts = 0;
7924 for (
auto &
Op :
I->operands()) {
7931 auto *ExtOp = Ext->getOperand(0);
7932 if (
isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
7933 Ops.push_back(&Ext->getOperandUse(0));
7941 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
7942 I->getType()->getScalarSizeInBits())
7979 if (!ElementConstant || !ElementConstant->
isZero())
7982 unsigned Opcode = OperandInstr->
getOpcode();
7983 if (Opcode == Instruction::SExt)
7985 else if (Opcode == Instruction::ZExt)
7990 unsigned Bitwidth =
I->getType()->getScalarSizeInBits();
8000 Ops.push_back(&Insert->getOperandUse(1));
8006 if (!
Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8010 if (!ShouldSinkSplatForIndexedVariant(
I))
8015 Ops.push_back(&
I->getOperandUse(0));
8017 Ops.push_back(&
I->getOperandUse(1));
8019 return !
Ops.empty();
8021 case Instruction::FMul: {
8023 if (
I->getType()->isScalableTy())
8024 return !
Ops.empty();
8028 return !
Ops.empty();
8032 Ops.push_back(&
I->getOperandUse(0));
8034 Ops.push_back(&
I->getOperandUse(1));
8035 return !
Ops.empty();
8044 Align Alignment)
const {
8045 if (!(ST->isSVEAvailable() ||
8046 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8050 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8057 if (!LT.first.isValid())
8062 switch (LT.second.SimpleTy) {
static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static Error reportError(StringRef Message)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
Cost tables and simple lookup functions.
This file defines the DenseMap class.
static Value * getCondition(Instruction *I)
const HexagonInstrInfo * TII
This file provides the interface for the instcombine pass implementation.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file defines the LoopVectorizationLegality class.
static const Function * getCalledFunction(const Value *V)
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
static uint64_t getBits(uint64_t Val, int Start, int End)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
This file implements the C++20 <bit> header.
unsigned getVectorInsertExtractBaseCost() const
bool useSVEForFixedLengthVectors() const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost 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 getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index) const override
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
bool preferFixedOverScalableIfEqualCost() const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind=TTI::TCK_RecipThroughput) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isElementTypeLegalForScalableVector(Type *Ty) const override
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 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
bool isElementTypeLegalForCompressStore(Type *Ty) const
InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, TTI::TargetCostKind CostKind) const override
unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, unsigned DefaultCallPenalty) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
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
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, ElementCount VF) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedGatherScatter(Type *DataType) const
InstructionCost getBranchMispredictPenalty() const override
bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const override
See if I should be considered for address type promotion.
APInt getFeatureMask(const Function &F) const override
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const override
bool enableScalableVectorization() const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Value * getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate=true) const override
bool hasKnownLowerThroughputFromSchedulingModel(unsigned Opcode1, unsigned Opcode2) const
Check whether Opcode1 has less throughput according to the scheduling model than Opcode2.
unsigned getEpilogueVectorizationMinVF() const override
InstructionCost getSpliceCost(VectorType *Tp, int Index, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) const override
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
void negate()
Negate this APInt in place.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
unsigned logBase2() const
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost 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
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, Instruction *I=nullptr, int64_t ScalableOffset=0) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getCallInstrCost(Function *F, Type *RetTy, ArrayRef< Type * > Tys, TTI::TargetCostKind CostKind) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind) const override
InstructionCost 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...
user_iterator user_begin()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
bool hasGroups() const
Returns true if we have any interleave groups.
const SmallVectorImpl< Type * > & getArgTypes() const
Type * getReturnType() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() const
Intrinsic::ID getID() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
iterator_range< block_iterator > blocks() const
RecurrenceSet & getFixedOrderRecurrences()
Return the fixed-order recurrences found in the loop.
DominatorTree * getDominatorTree() const
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
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.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static VectorType * getInteger(VectorType *VTy)
This static method gets a VectorType with the same number of elements as the input type,...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
LLVM_ABI APInt getCpuSupportsMask(ArrayRef< StringRef > Features)
static constexpr unsigned SVEBitsPerBlock
LLVM_ABI APInt getFMVPriority(ArrayRef< StringRef > Features)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
@ ADD
Simple integer binary arithmetic operators.
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ FADD
Simple binary floating point operators.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ 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.
AllOnesConstantMatch m_AllOnes()
CheckType m_SpecificType(LLT Ty)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_Cmp()
Matches any compare instruction and ignore it.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::And > m_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R either in the form of L & R or L ?
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_nonnegative > m_NonNegative()
Match an integer or vector of non-negative values.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
auto m_VScale()
Matches a call to llvm.vscale().
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_Undef()
Match an arbitrary undef constant.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
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.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI 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.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
CostTblEntryT< uint16_t > CostTblEntry
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
Return the number of active elements for VL1 to VL256 predicate pattern, zero for all other patterns.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
unsigned getMatchingIROpode() const
bool inactiveLanesAreUnused() const
bool inactiveLanesAreNotDefined() const
bool hasMatchingUndefIntrinsic() const
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
bool hasGoverningPredicate() const
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
CmpInst::Predicate getCmpPredicate() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
bool inactiveLanesTakenFromOperand() const
static SVEIntrinsicInfo defaultUndefOp()
bool hasOperandWithNoActiveLanes() const
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
bool hasCmpPredicate() const
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() const
bool hasMatchingIROpode() const
SVEIntrinsicInfo & setCmpPredicate(CmpInst::Predicate Pred)
bool resultIsZeroInitialized() const
SVEIntrinsicInfo & setMatchingIROpcode(unsigned Opcode)
unsigned getOperandIdxInactiveLanesTakenFrom() const
static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex)
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isFixedLengthVector() const
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Machine model for scheduling, bundling, and heuristics.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Information about a load/store intrinsic defined by the target.
InterleavedAccessInfo * IAI
LoopVectorizationLegality * LVL
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...