LLVM 23.0.0git
AArch64TargetTransformInfo.cpp
Go to the documentation of this file.
1//===-- AArch64TargetTransformInfo.cpp - AArch64 specific TTI -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "AArch64ExpandImm.h"
14#include "llvm/ADT/DenseMap.h"
22#include "llvm/IR/Intrinsics.h"
23#include "llvm/IR/IntrinsicsAArch64.h"
25#include "llvm/Support/Debug.h"
30#include <algorithm>
31#include <optional>
32using namespace llvm;
33using namespace llvm::PatternMatch;
34
35#define DEBUG_TYPE "aarch64tti"
36
37static cl::opt<bool> EnableFalkorHWPFUnrollFix("enable-falkor-hwpf-unroll-fix",
38 cl::init(true), cl::Hidden);
39
41 "sve-prefer-fixed-over-scalable-if-equal", cl::Hidden);
42
43static cl::opt<unsigned> SVEGatherOverhead("sve-gather-overhead", cl::init(10),
45
46static cl::opt<unsigned> SVEScatterOverhead("sve-scatter-overhead",
47 cl::init(10), cl::Hidden);
48
49static cl::opt<unsigned> SVETailFoldInsnThreshold("sve-tail-folding-insn-threshold",
50 cl::init(15), cl::Hidden);
51
53 NeonNonConstStrideOverhead("neon-nonconst-stride-overhead", cl::init(10),
55
57 "call-penalty-sm-change", cl::init(5), cl::Hidden,
59 "Penalty of calling a function that requires a change to PSTATE.SM"));
60
62 "inline-call-penalty-sm-change", cl::init(10), cl::Hidden,
63 cl::desc("Penalty of inlining a call that requires a change to PSTATE.SM"));
64
65static cl::opt<bool> EnableOrLikeSelectOpt("enable-aarch64-or-like-select",
66 cl::init(true), cl::Hidden);
67
68static cl::opt<bool> EnableLSRCostOpt("enable-aarch64-lsr-cost-opt",
69 cl::init(true), cl::Hidden);
70
71// A complete guess as to a reasonable cost.
73 BaseHistCntCost("aarch64-base-histcnt-cost", cl::init(8), cl::Hidden,
74 cl::desc("The cost of a histcnt instruction"));
75
77 "dmb-lookahead-threshold", cl::init(10), cl::Hidden,
78 cl::desc("The number of instructions to search for a redundant dmb"));
79
81 "aarch64-force-unroll-threshold", cl::init(0), cl::Hidden,
82 cl::desc("Threshold for forced unrolling of small loops in AArch64"));
83
84namespace {
85class TailFoldingOption {
86 // These bitfields will only ever be set to something non-zero in operator=,
87 // when setting the -sve-tail-folding option. This option should always be of
88 // the form (default|simple|all|disable)[+(Flag1|Flag2|etc)], where here
89 // InitialBits is one of (disabled|all|simple). EnableBits represents
90 // additional flags we're enabling, and DisableBits for those flags we're
91 // disabling. The default flag is tracked in the variable NeedsDefault, since
92 // at the time of setting the option we may not know what the default value
93 // for the CPU is.
97
98 // This value needs to be initialised to true in case the user does not
99 // explicitly set the -sve-tail-folding option.
100 bool NeedsDefault = true;
101
102 void setInitialBits(TailFoldingOpts Bits) { InitialBits = Bits; }
103
104 void setNeedsDefault(bool V) { NeedsDefault = V; }
105
106 void setEnableBit(TailFoldingOpts Bit) {
107 EnableBits |= Bit;
108 DisableBits &= ~Bit;
109 }
110
111 void setDisableBit(TailFoldingOpts Bit) {
112 EnableBits &= ~Bit;
113 DisableBits |= Bit;
114 }
115
116 TailFoldingOpts getBits(TailFoldingOpts DefaultBits) const {
117 TailFoldingOpts Bits = TailFoldingOpts::Disabled;
118
119 assert((InitialBits == TailFoldingOpts::Disabled || !NeedsDefault) &&
120 "Initial bits should only include one of "
121 "(disabled|all|simple|default)");
122 Bits = NeedsDefault ? DefaultBits : InitialBits;
123 Bits |= EnableBits;
124 Bits &= ~DisableBits;
125
126 return Bits;
127 }
128
129 void reportError(std::string Opt) {
130 errs() << "invalid argument '" << Opt
131 << "' to -sve-tail-folding=; the option should be of the form\n"
132 " (disabled|all|default|simple)[+(reductions|recurrences"
133 "|reverse|noreductions|norecurrences|noreverse)]\n";
134 report_fatal_error("Unrecognised tail-folding option");
135 }
136
137public:
138
139 void operator=(const std::string &Val) {
140 // If the user explicitly sets -sve-tail-folding= then treat as an error.
141 if (Val.empty()) {
142 reportError("");
143 return;
144 }
145
146 // Since the user is explicitly setting the option we don't automatically
147 // need the default unless they require it.
148 setNeedsDefault(false);
149
150 SmallVector<StringRef, 4> TailFoldTypes;
151 StringRef(Val).split(TailFoldTypes, '+', -1, false);
152
153 unsigned StartIdx = 1;
154 if (TailFoldTypes[0] == "disabled")
155 setInitialBits(TailFoldingOpts::Disabled);
156 else if (TailFoldTypes[0] == "all")
157 setInitialBits(TailFoldingOpts::All);
158 else if (TailFoldTypes[0] == "default")
159 setNeedsDefault(true);
160 else if (TailFoldTypes[0] == "simple")
161 setInitialBits(TailFoldingOpts::Simple);
162 else {
163 StartIdx = 0;
164 setInitialBits(TailFoldingOpts::Disabled);
165 }
166
167 for (unsigned I = StartIdx; I < TailFoldTypes.size(); I++) {
168 if (TailFoldTypes[I] == "reductions")
169 setEnableBit(TailFoldingOpts::Reductions);
170 else if (TailFoldTypes[I] == "recurrences")
171 setEnableBit(TailFoldingOpts::Recurrences);
172 else if (TailFoldTypes[I] == "reverse")
173 setEnableBit(TailFoldingOpts::Reverse);
174 else if (TailFoldTypes[I] == "noreductions")
175 setDisableBit(TailFoldingOpts::Reductions);
176 else if (TailFoldTypes[I] == "norecurrences")
177 setDisableBit(TailFoldingOpts::Recurrences);
178 else if (TailFoldTypes[I] == "noreverse")
179 setDisableBit(TailFoldingOpts::Reverse);
180 else
181 reportError(Val);
182 }
183 }
184
185 bool satisfies(TailFoldingOpts DefaultBits, TailFoldingOpts Required) const {
186 return (getBits(DefaultBits) & Required) == Required;
187 }
188};
189} // namespace
190
191TailFoldingOption TailFoldingOptionLoc;
192
194 "sve-tail-folding",
195 cl::desc(
196 "Control the use of vectorisation using tail-folding for SVE where the"
197 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
198 "\ndisabled (Initial) No loop types will vectorize using "
199 "tail-folding"
200 "\ndefault (Initial) Uses the default tail-folding settings for "
201 "the target CPU"
202 "\nall (Initial) All legal loop types will vectorize using "
203 "tail-folding"
204 "\nsimple (Initial) Use tail-folding for simple loops (not "
205 "reductions or recurrences)"
206 "\nreductions Use tail-folding for loops containing reductions"
207 "\nnoreductions Inverse of above"
208 "\nrecurrences Use tail-folding for loops containing fixed order "
209 "recurrences"
210 "\nnorecurrences Inverse of above"
211 "\nreverse Use tail-folding for loops requiring reversed "
212 "predicates"
213 "\nnoreverse Inverse of above"),
215
216// Experimental option that will only be fully functional when the
217// code-generator is changed to use SVE instead of NEON for all fixed-width
218// operations.
220 "enable-fixedwidth-autovec-in-streaming-mode", cl::init(false), cl::Hidden);
221
222// Experimental option that will only be fully functional when the cost-model
223// and code-generator have been changed to avoid using scalable vector
224// instructions that are not legal in streaming SVE mode.
226 "enable-scalable-autovec-in-streaming-mode", cl::init(false), cl::Hidden);
227
228static bool isSMEABIRoutineCall(const CallInst &CI,
229 const AArch64TargetLowering &TLI) {
230 const auto *F = CI.getCalledFunction();
231 return F &&
233}
234
235/// Returns true if the function has explicit operations that can only be
236/// lowered using incompatible instructions for the selected mode. This also
237/// returns true if the function F may use or modify ZA state.
239 const AArch64TargetLowering &TLI) {
240 for (const BasicBlock &BB : *F) {
241 for (const Instruction &I : BB) {
242 // Be conservative for now and assume that any call to inline asm or to
243 // intrinsics could could result in non-streaming ops (e.g. calls to
244 // @llvm.aarch64.* or @llvm.gather/scatter intrinsics). We can assume that
245 // all native LLVM instructions can be lowered to compatible instructions.
246 if (isa<CallInst>(I) && !I.isDebugOrPseudoInst() &&
247 (cast<CallInst>(I).isInlineAsm() || isa<IntrinsicInst>(I) ||
249 return true;
250 }
251 }
252 return false;
253}
254
256 SmallVectorImpl<StringRef> &Features) {
257 StringRef AttributeStr =
258 TTI->isMultiversionedFunction(F) ? "fmv-features" : "target-features";
259 StringRef FeatureStr = F.getFnAttribute(AttributeStr).getValueAsString();
260 FeatureStr.split(Features, ",");
261}
262
265 extractAttrFeatures(F, this, Features);
266 return AArch64::getCpuSupportsMask(Features);
267}
268
271 extractAttrFeatures(F, this, Features);
272 return AArch64::getFMVPriority(Features);
273}
274
276 return F.hasFnAttribute("fmv-features");
277}
278
280 const Function *Callee) const {
281 SMECallAttrs CallAttrs(*Caller, *Callee);
282
283 // Never inline a function explicitly marked as being streaming,
284 // into a non-streaming function. Assume it was marked as streaming
285 // for a reason.
286 if (CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
288 return false;
289
290 // When inlining, we should consider the body of the function, not the
291 // interface.
292 if (CallAttrs.callee().hasStreamingBody()) {
293 CallAttrs.callee().set(SMEAttrs::SM_Compatible, false);
294 CallAttrs.callee().set(SMEAttrs::SM_Enabled, true);
295 }
296
297 if (CallAttrs.callee().isNewZA() || CallAttrs.callee().isNewZT0())
298 return false;
299
300 if (CallAttrs.requiresLazySave() || CallAttrs.requiresSMChange() ||
301 CallAttrs.requiresPreservingZT0() ||
302 CallAttrs.requiresPreservingAllZAState()) {
303 if (hasPossibleIncompatibleOps(Callee, *getTLI()))
304 return false;
305 }
306
307 return BaseT::areInlineCompatible(Caller, Callee);
308}
309
311 const Function *Callee,
312 ArrayRef<Type *> Types) const {
313 if (!BaseT::areTypesABICompatible(Caller, Callee, Types))
314 return false;
315
316 // We need to ensure that argument promotion does not attempt to promote
317 // pointers to fixed-length vector types larger than 128 bits like
318 // <8 x float> (and pointers to aggregate types which have such fixed-length
319 // vector type members) into the values of the pointees. Such vector types
320 // are used for SVE VLS but there is no ABI for SVE VLS arguments and the
321 // backend cannot lower such value arguments. The 128-bit fixed-length SVE
322 // types can be safely treated as 128-bit NEON types and they cannot be
323 // distinguished in IR.
324 if (ST->useSVEForFixedLengthVectors() && llvm::any_of(Types, [](Type *Ty) {
325 auto FVTy = dyn_cast<FixedVectorType>(Ty);
326 return FVTy &&
327 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
328 }))
329 return false;
330
331 return true;
332}
333
334unsigned
336 unsigned DefaultCallPenalty) const {
337 // This function calculates a penalty for executing Call in F.
338 //
339 // There are two ways this function can be called:
340 // (1) F:
341 // call from F -> G (the call here is Call)
342 //
343 // For (1), Call.getCaller() == F, so it will always return a high cost if
344 // a streaming-mode change is required (thus promoting the need to inline the
345 // function)
346 //
347 // (2) F:
348 // call from F -> G (the call here is not Call)
349 // G:
350 // call from G -> H (the call here is Call)
351 //
352 // For (2), if after inlining the body of G into F the call to H requires a
353 // streaming-mode change, and the call to G from F would also require a
354 // streaming-mode change, then there is benefit to do the streaming-mode
355 // change only once and avoid inlining of G into F.
356
357 SMEAttrs FAttrs(*F);
358 SMECallAttrs CallAttrs(Call, &getTLI()->getRuntimeLibcallsInfo());
359
360 if (SMECallAttrs(FAttrs, CallAttrs.callee()).requiresSMChange()) {
361 if (F == Call.getCaller()) // (1)
362 return CallPenaltyChangeSM * DefaultCallPenalty;
363 if (SMECallAttrs(FAttrs, CallAttrs.caller()).requiresSMChange()) // (2)
364 return InlineCallPenaltyChangeSM * DefaultCallPenalty;
365 }
366
367 return DefaultCallPenalty;
368}
369
373
374 if (K == TargetTransformInfo::RGK_FixedWidthVector && ST->isNeonAvailable())
375 return true;
376
378 ST->isSVEorStreamingSVEAvailable() &&
379 !ST->disableMaximizeScalableBandwidth();
380}
381
382/// Calculate the cost of materializing a 64-bit value. This helper
383/// method might only calculate a fraction of a larger immediate. Therefore it
384/// is valid to return a cost of ZERO.
386 // Check if the immediate can be encoded within an instruction.
387 if (Val == 0 || AArch64_AM::isLogicalImmediate(Val, 64))
388 return 0;
389
390 if (Val < 0)
391 Val = ~Val;
392
393 // Calculate how many moves we will need to materialize this constant.
395 AArch64_IMM::expandMOVImm(Val, 64, Insn);
396 return Insn.size();
397}
398
399/// Calculate the cost of materializing the given constant.
403 assert(Ty->isIntegerTy());
404
405 unsigned BitSize = Ty->getPrimitiveSizeInBits();
406 if (BitSize == 0)
407 return ~0U;
408
409 // Sign-extend all constants to a multiple of 64-bit.
410 APInt ImmVal = Imm;
411 if (BitSize & 0x3f)
412 ImmVal = Imm.sext((BitSize + 63) & ~0x3fU);
413
414 // Split the constant into 64-bit chunks and calculate the cost for each
415 // chunk.
417 for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
418 APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64);
419 int64_t Val = Tmp.getSExtValue();
420 Cost += getIntImmCost(Val);
421 }
422 // We need at least one instruction to materialze the constant.
423 return std::max<InstructionCost>(1, Cost);
424}
425
427 const APInt &Imm, Type *Ty,
429 Instruction *Inst) const {
430 assert(Ty->isIntegerTy());
431
432 unsigned BitSize = Ty->getPrimitiveSizeInBits();
433 // There is no cost model for constants with a bit size of 0. Return TCC_Free
434 // here, so that constant hoisting will ignore this constant.
435 if (BitSize == 0)
436 return TTI::TCC_Free;
437
438 unsigned ImmIdx = ~0U;
439 switch (Opcode) {
440 default:
441 return TTI::TCC_Free;
442 case Instruction::GetElementPtr:
443 // Always hoist the base address of a GetElementPtr.
444 if (Idx == 0)
445 return 2 * TTI::TCC_Basic;
446 return TTI::TCC_Free;
447 case Instruction::Store:
448 ImmIdx = 0;
449 break;
450 case Instruction::Add:
451 case Instruction::Sub:
452 case Instruction::Mul:
453 case Instruction::UDiv:
454 case Instruction::SDiv:
455 case Instruction::URem:
456 case Instruction::SRem:
457 case Instruction::And:
458 case Instruction::Or:
459 case Instruction::Xor:
460 case Instruction::ICmp:
461 ImmIdx = 1;
462 break;
463 // Always return TCC_Free for the shift value of a shift instruction.
464 case Instruction::Shl:
465 case Instruction::LShr:
466 case Instruction::AShr:
467 if (Idx == 1)
468 return TTI::TCC_Free;
469 break;
470 case Instruction::Trunc:
471 case Instruction::ZExt:
472 case Instruction::SExt:
473 case Instruction::IntToPtr:
474 case Instruction::PtrToInt:
475 case Instruction::BitCast:
476 case Instruction::PHI:
477 case Instruction::Call:
478 case Instruction::Select:
479 case Instruction::Ret:
480 case Instruction::Load:
481 break;
482 }
483
484 if (Idx == ImmIdx) {
485 int NumConstants = (BitSize + 63) / 64;
487 return (Cost <= NumConstants * TTI::TCC_Basic)
488 ? static_cast<int>(TTI::TCC_Free)
489 : Cost;
490 }
492}
493
496 const APInt &Imm, Type *Ty,
498 assert(Ty->isIntegerTy());
499
500 unsigned BitSize = Ty->getPrimitiveSizeInBits();
501 // There is no cost model for constants with a bit size of 0. Return TCC_Free
502 // here, so that constant hoisting will ignore this constant.
503 if (BitSize == 0)
504 return TTI::TCC_Free;
505
506 // Most (all?) AArch64 intrinsics do not support folding immediates into the
507 // selected instruction, so we compute the materialization cost for the
508 // immediate directly.
509 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
511
512 switch (IID) {
513 default:
514 return TTI::TCC_Free;
515 case Intrinsic::sadd_with_overflow:
516 case Intrinsic::uadd_with_overflow:
517 case Intrinsic::ssub_with_overflow:
518 case Intrinsic::usub_with_overflow:
519 case Intrinsic::smul_with_overflow:
520 case Intrinsic::umul_with_overflow:
521 if (Idx == 1) {
522 int NumConstants = (BitSize + 63) / 64;
524 return (Cost <= NumConstants * TTI::TCC_Basic)
525 ? static_cast<int>(TTI::TCC_Free)
526 : Cost;
527 }
528 break;
529 case Intrinsic::experimental_stackmap:
530 if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
531 return TTI::TCC_Free;
532 break;
533 case Intrinsic::experimental_patchpoint_void:
534 case Intrinsic::experimental_patchpoint:
535 if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
536 return TTI::TCC_Free;
537 break;
538 case Intrinsic::experimental_gc_statepoint:
539 if ((Idx < 5) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
540 return TTI::TCC_Free;
541 break;
542 }
544}
545
547AArch64TTIImpl::getPopcntSupport(unsigned TyWidth) const {
548 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
549 if (TyWidth == 32 || TyWidth == 64)
551 // TODO: AArch64TargetLowering::LowerCTPOP() supports 128bit popcount.
552 return TTI::PSK_Software;
553}
554
556 // MispredictPenalty is defined per-CPU in AArch64Sched*.td (e.g.,
557 // AArch64SchedNeoverseV2.td).
558 return ST->getSchedModel().MispredictPenalty;
559}
560
561static bool isUnpackedVectorVT(EVT VecVT) {
562 return VecVT.isScalableVector() &&
564}
565
567 const IntrinsicCostAttributes &ICA) {
568 // We need to know at least the number of elements in the vector of buckets
569 // and the size of each element to update.
570 if (ICA.getArgTypes().size() < 2)
572
573 // Only interested in costing for the hardware instruction from SVE2.
574 if (!ST->hasSVE2())
576
577 Type *BucketPtrsTy = ICA.getArgTypes()[0]; // Type of vector of pointers
578 Type *EltTy = ICA.getArgTypes()[1]; // Type of bucket elements
579 unsigned TotalHistCnts = 1;
580
581 unsigned EltSize = EltTy->getScalarSizeInBits();
582 // Only allow (up to 64b) integers or pointers
583 if ((!EltTy->isIntegerTy() && !EltTy->isPointerTy()) || EltSize > 64)
585
586 // FIXME: We should be able to generate histcnt for fixed-length vectors
587 // using ptrue with a specific VL.
588 if (VectorType *VTy = dyn_cast<VectorType>(BucketPtrsTy)) {
589 unsigned EC = VTy->getElementCount().getKnownMinValue();
590 if (!isPowerOf2_64(EC) || !VTy->isScalableTy())
592
593 // HistCnt only supports 32b and 64b element types
594 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
595
596 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
598
599 unsigned NaturalVectorWidth = AArch64::SVEBitsPerBlock / LegalEltSize;
600 TotalHistCnts = EC / NaturalVectorWidth;
601
602 return InstructionCost(BaseHistCntCost * TotalHistCnts);
603 }
604
606}
607
611 // The code-generator is currently not able to handle scalable vectors
612 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
613 // it. This change will be removed when code-generation for these types is
614 // sufficiently reliable.
615 auto *RetTy = ICA.getReturnType();
616 if (auto *VTy = dyn_cast<ScalableVectorType>(RetTy))
617 if (VTy->getElementCount() == ElementCount::getScalable(1))
619
620 switch (ICA.getID()) {
621 case Intrinsic::experimental_vector_histogram_add: {
622 InstructionCost HistCost = getHistogramCost(ST, ICA);
623 // If the cost isn't valid, we may still be able to scalarize
624 if (HistCost.isValid())
625 return HistCost;
626 break;
627 }
628 case Intrinsic::clmul: {
629 auto LT = getTypeLegalizationCost(RetTy);
630
631 // PMUL v8i8/v16i8 is always available on AArch64
632 if (ST->hasNEON()) {
633 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
634 return LT.first;
635
636 // Scalar i8 lowers through scalar/vector moves around PMUL.
637 if (TLI->getValueType(DL, RetTy, true) == MVT::i8) {
638 auto *VecTy =
639 FixedVectorType::get(Type::getInt8Ty(RetTy->getContext()), 8);
640 return 1 +
641 getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
642 -1, nullptr, nullptr) *
643 2 +
644 getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind,
645 -1, nullptr, nullptr);
646 }
647 }
648
649 if (LT.second.SimpleTy == MVT::nxv2i64)
650 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
651 return LT.first * 3;
652
653 if (ST->hasSVE2() || ST->hasSME()) {
654 switch (LT.second.SimpleTy) {
655 case MVT::nxv16i8:
656 return LT.first;
657 case MVT::nxv8i16:
658 return LT.first * 6;
659 case MVT::nxv4i32:
660 return LT.first * 3;
661 case MVT::nxv2i64:
662 return LT.first * 8;
663 default:
664 break;
665 }
666 }
667
668 // Avoid +sve giving this cost 2 due to custom lowering: It's very slow
669 if (LT.second.SimpleTy == MVT::nxv2i64)
670 return 192;
671
672 if (ST->hasAES()) {
673 switch (LT.second.SimpleTy) {
674 case MVT::i16:
675 case MVT::i32:
676 case MVT::i64:
677 case MVT::i128: {
678 auto *VecTy =
679 FixedVectorType::get(Type::getInt64Ty(RetTy->getContext()), 1);
680 return LT.first *
681 (1 +
682 getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
683 -1, nullptr, nullptr) *
684 2 +
685 getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind,
686 -1, nullptr, nullptr));
687 }
688 case MVT::v1i64:
689 return LT.first;
690 case MVT::v2i64:
691 return LT.first * 3;
692 case MVT::v2i32:
693 return LT.first * 6;
694 case MVT::v4i32:
695 return LT.first * 11;
696 case MVT::v4i16:
697 return LT.first * 14;
698 default:
699 break;
700 }
701 }
702 break;
703 }
704 case Intrinsic::umin:
705 case Intrinsic::umax:
706 case Intrinsic::smin:
707 case Intrinsic::smax: {
708 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
709 MVT::v8i16, MVT::v2i32, MVT::v4i32,
710 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
711 MVT::nxv2i64};
712 auto LT = getTypeLegalizationCost(RetTy);
713 // v2i64 types get converted to cmp+bif hence the cost of 2
714 if (LT.second == MVT::v2i64)
715 return LT.first * 2;
716 if (any_of(ValidMinMaxTys, equal_to(LT.second)))
717 return LT.first;
718 break;
719 }
720 case Intrinsic::scmp:
721 case Intrinsic::ucmp: {
722 static const CostTblEntry BitreverseTbl[] = {
723 {Intrinsic::scmp, MVT::i32, 3}, // cmp+cset+csinv
724 {Intrinsic::scmp, MVT::i64, 3}, // cmp+cset+csinv
725 {Intrinsic::scmp, MVT::v8i8, 3}, // cmgt+cmgt+sub
726 {Intrinsic::scmp, MVT::v16i8, 3}, // cmgt+cmgt+sub
727 {Intrinsic::scmp, MVT::v4i16, 3}, // cmgt+cmgt+sub
728 {Intrinsic::scmp, MVT::v8i16, 3}, // cmgt+cmgt+sub
729 {Intrinsic::scmp, MVT::v2i32, 3}, // cmgt+cmgt+sub
730 {Intrinsic::scmp, MVT::v4i32, 3}, // cmgt+cmgt+sub
731 {Intrinsic::scmp, MVT::v1i64, 3}, // cmgt+cmgt+sub
732 {Intrinsic::scmp, MVT::v2i64, 3}, // cmgt+cmgt+sub
733 };
734 const auto LT = getTypeLegalizationCost(RetTy);
735 const auto *Entry =
736 CostTableLookup(BitreverseTbl, Intrinsic::scmp, LT.second);
737 if (Entry)
738 return Entry->Cost * LT.first;
739 break;
740 }
741 case Intrinsic::sadd_sat:
742 case Intrinsic::ssub_sat:
743 case Intrinsic::uadd_sat:
744 case Intrinsic::usub_sat: {
745 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
746 MVT::v8i16, MVT::v2i32, MVT::v4i32,
747 MVT::v2i64};
748 auto LT = getTypeLegalizationCost(RetTy);
749 // This is a base cost of 1 for the vadd, plus 3 extract shifts if we
750 // need to extend the type, as it uses shr(qadd(shl, shl)).
751 unsigned Instrs =
752 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
753 if (any_of(ValidSatTys, equal_to(LT.second)))
754 return LT.first * Instrs;
755
757 uint64_t VectorSize = TS.getKnownMinValue();
758
759 if (ST->isSVEAvailable() && VectorSize >= 128 && isPowerOf2_64(VectorSize))
760 return LT.first * Instrs;
761
762 break;
763 }
764 case Intrinsic::abs: {
765 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
766 MVT::v8i16, MVT::v2i32, MVT::v4i32,
767 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
768 MVT::nxv4i32, MVT::nxv2i64};
769 auto LT = getTypeLegalizationCost(RetTy);
770 if (any_of(ValidAbsTys, equal_to(LT.second)))
771 return LT.first;
772 break;
773 }
774 case Intrinsic::bswap: {
775 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
776 MVT::v4i32, MVT::v2i64};
777 auto LT = getTypeLegalizationCost(RetTy);
778 if (any_of(ValidAbsTys, equal_to(LT.second)) &&
779 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
780 return LT.first;
781 break;
782 }
783 case Intrinsic::fma:
784 case Intrinsic::fmuladd: {
785 // Given a fma or fmuladd, cost it the same as a fmul instruction which are
786 // usually the same for costs. TODO: Add fp16 and bf16 expansion costs.
787 Type *EltTy = RetTy->getScalarType();
788 if (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
789 (EltTy->isHalfTy() && ST->hasFullFP16()))
790 return getArithmeticInstrCost(Instruction::FMul, RetTy, CostKind);
791 break;
792 }
793 case Intrinsic::stepvector: {
794 InstructionCost Cost = 1; // Cost of the `index' instruction
795 auto LT = getTypeLegalizationCost(RetTy);
796 // Legalisation of illegal vectors involves an `index' instruction plus
797 // (LT.first - 1) vector adds.
798 if (LT.first > 1) {
799 Type *LegalVTy = EVT(LT.second).getTypeForEVT(RetTy->getContext());
800 InstructionCost AddCost =
801 getArithmeticInstrCost(Instruction::Add, LegalVTy, CostKind);
802 Cost += AddCost * (LT.first - 1);
803 }
804 return Cost;
805 }
806 case Intrinsic::vector_extract:
807 case Intrinsic::vector_insert: {
808 // If both the vector and subvector types are legal types and the index
809 // is 0, then this should be a no-op or simple operation; return a
810 // relatively low cost.
811
812 // If arguments aren't actually supplied, then we cannot determine the
813 // value of the index. We also want to skip predicate types.
814 if (ICA.getArgs().size() != ICA.getArgTypes().size() ||
816 break;
817
818 LLVMContext &C = RetTy->getContext();
819 EVT VecVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);
820 bool IsExtract = ICA.getID() == Intrinsic::vector_extract;
821 EVT SubVecVT = IsExtract ? getTLI()->getValueType(DL, RetTy)
822 : getTLI()->getValueType(DL, ICA.getArgTypes()[1]);
823 // Skip this if either the vector or subvector types are unpacked
824 // SVE types; they may get lowered to stack stores and loads.
825 if (isUnpackedVectorVT(VecVT) || isUnpackedVectorVT(SubVecVT))
826 break;
827
829 getTLI()->getTypeConversion(C, SubVecVT);
831 getTLI()->getTypeConversion(C, VecVT);
832 const Value *Idx = IsExtract ? ICA.getArgs()[1] : ICA.getArgs()[2];
833 const ConstantInt *CIdx = cast<ConstantInt>(Idx);
834 if (SubVecLK.first == TargetLoweringBase::TypeLegal &&
835 VecLK.first == TargetLoweringBase::TypeLegal && CIdx->isZero())
836 return TTI::TCC_Free;
837 break;
838 }
839 case Intrinsic::bitreverse: {
840 static const CostTblEntry BitreverseTbl[] = {
841 {Intrinsic::bitreverse, MVT::i32, 1},
842 {Intrinsic::bitreverse, MVT::i64, 1},
843 {Intrinsic::bitreverse, MVT::v8i8, 1},
844 {Intrinsic::bitreverse, MVT::v16i8, 1},
845 {Intrinsic::bitreverse, MVT::v4i16, 2},
846 {Intrinsic::bitreverse, MVT::v8i16, 2},
847 {Intrinsic::bitreverse, MVT::v2i32, 2},
848 {Intrinsic::bitreverse, MVT::v4i32, 2},
849 {Intrinsic::bitreverse, MVT::v1i64, 2},
850 {Intrinsic::bitreverse, MVT::v2i64, 2},
851 };
852 const auto LegalisationCost = getTypeLegalizationCost(RetTy);
853 const auto *Entry =
854 CostTableLookup(BitreverseTbl, ICA.getID(), LegalisationCost.second);
855 if (Entry) {
856 // Cost Model is using the legal type(i32) that i8 and i16 will be
857 // converted to +1 so that we match the actual lowering cost
858 if (TLI->getValueType(DL, RetTy, true) == MVT::i8 ||
859 TLI->getValueType(DL, RetTy, true) == MVT::i16)
860 return LegalisationCost.first * Entry->Cost + 1;
861
862 return LegalisationCost.first * Entry->Cost;
863 }
864 break;
865 }
866 case Intrinsic::ctpop: {
867 if (!ST->hasNEON()) {
868 // 32-bit or 64-bit ctpop without NEON is 12 instructions.
869 return getTypeLegalizationCost(RetTy).first * 12;
870 }
871 static const CostTblEntry CtpopCostTbl[] = {
872 {ISD::CTPOP, MVT::v2i64, 4},
873 {ISD::CTPOP, MVT::v4i32, 3},
874 {ISD::CTPOP, MVT::v8i16, 2},
875 {ISD::CTPOP, MVT::v16i8, 1},
876 {ISD::CTPOP, MVT::i64, 4},
877 {ISD::CTPOP, MVT::v2i32, 3},
878 {ISD::CTPOP, MVT::v4i16, 2},
879 {ISD::CTPOP, MVT::v8i8, 1},
880 {ISD::CTPOP, MVT::i32, 5},
881 // SVE types (For targets that override NEON for fixed length vectors)
882 {ISD::CTPOP, MVT::nxv2i64, 1},
883 {ISD::CTPOP, MVT::nxv4i32, 1},
884 {ISD::CTPOP, MVT::nxv8i16, 1},
885 {ISD::CTPOP, MVT::nxv16i8, 1},
886 };
887 auto LT = getTypeLegalizationCost(RetTy);
888 MVT MTy = LT.second;
889
890 // When SVE is available CNT will be used for fixed and scalable vectors.
891 if (ST->isSVEorStreamingSVEAvailable() && MTy.isFixedLengthVector())
893 128 / MTy.getScalarSizeInBits());
894
895 if (const auto *Entry = CostTableLookup(CtpopCostTbl, ISD::CTPOP, MTy)) {
896 // Extra cost of +1 when illegal vector types are legalized by promoting
897 // the integer type.
898 int ExtraCost = MTy.isVector() && MTy.getScalarSizeInBits() !=
899 RetTy->getScalarSizeInBits()
900 ? 1
901 : 0;
902 return LT.first * Entry->Cost + ExtraCost;
903 }
904 break;
905 }
906 case Intrinsic::sadd_with_overflow:
907 case Intrinsic::uadd_with_overflow:
908 case Intrinsic::ssub_with_overflow:
909 case Intrinsic::usub_with_overflow:
910 case Intrinsic::smul_with_overflow:
911 case Intrinsic::umul_with_overflow: {
912 static const CostTblEntry WithOverflowCostTbl[] = {
913 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
914 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
915 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
916 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
917 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
918 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
919 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
920 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
921 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
922 {Intrinsic::usub_with_overflow, MVT::i8, 3},
923 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
924 {Intrinsic::usub_with_overflow, MVT::i16, 3},
925 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
926 {Intrinsic::usub_with_overflow, MVT::i32, 1},
927 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
928 {Intrinsic::usub_with_overflow, MVT::i64, 1},
929 {Intrinsic::smul_with_overflow, MVT::i8, 5},
930 {Intrinsic::umul_with_overflow, MVT::i8, 4},
931 {Intrinsic::smul_with_overflow, MVT::i16, 5},
932 {Intrinsic::umul_with_overflow, MVT::i16, 4},
933 {Intrinsic::smul_with_overflow, MVT::i32, 2}, // eg umull;tst
934 {Intrinsic::umul_with_overflow, MVT::i32, 2}, // eg umull;cmp sxtw
935 {Intrinsic::smul_with_overflow, MVT::i64, 3}, // eg mul;smulh;cmp
936 {Intrinsic::umul_with_overflow, MVT::i64, 3}, // eg mul;umulh;cmp asr
937 };
938 EVT MTy = TLI->getValueType(DL, RetTy->getContainedType(0), true);
939 if (MTy.isSimple())
940 if (const auto *Entry = CostTableLookup(WithOverflowCostTbl, ICA.getID(),
941 MTy.getSimpleVT()))
942 return Entry->Cost;
943 break;
944 }
945 case Intrinsic::fptosi_sat:
946 case Intrinsic::fptoui_sat: {
947 if (ICA.getArgTypes().empty())
948 break;
949 bool IsSigned = ICA.getID() == Intrinsic::fptosi_sat;
950 auto LT = getTypeLegalizationCost(ICA.getArgTypes()[0]);
951 EVT MTy = TLI->getValueType(DL, RetTy);
952 // Check for the legal types, which are where the size of the input and the
953 // output are the same, or we are using cvt f64->i32 or f32->i64.
954 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
955 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
956 LT.second == MVT::v2f64)) {
957 if ((LT.second.getScalarSizeInBits() == MTy.getScalarSizeInBits() ||
958 (LT.second == MVT::f64 && MTy == MVT::i32) ||
959 (LT.second == MVT::f32 && MTy == MVT::i64)))
960 return LT.first;
961 // Extending vector types v2f32->v2i64, fcvtl*2 + fcvt*2
962 if (LT.second.getScalarType() == MVT::f32 && MTy.isFixedLengthVector() &&
963 MTy.getScalarSizeInBits() == 64)
964 return LT.first * (MTy.getVectorNumElements() > 2 ? 4 : 2);
965 }
966 // Similarly for fp16 sizes. Without FullFP16 we generally need to fcvt to
967 // f32.
968 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
969 return LT.first + getIntrinsicInstrCost(
970 {ICA.getID(),
971 RetTy,
972 {ICA.getArgTypes()[0]->getWithNewType(
973 Type::getFloatTy(RetTy->getContext()))}},
974 CostKind);
975 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
976 (LT.second == MVT::f16 && MTy == MVT::i64) ||
977 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
978 (LT.second.getScalarSizeInBits() == MTy.getScalarSizeInBits())))
979 return LT.first;
980 // Extending vector types v8f16->v8i32, fcvtl*2 + fcvt*2
981 if (LT.second.getScalarType() == MVT::f16 && MTy.isFixedLengthVector() &&
982 MTy.getScalarSizeInBits() == 32)
983 return LT.first * (MTy.getVectorNumElements() > 4 ? 4 : 2);
984 // Extending vector types v8f16->v8i32. These current scalarize but the
985 // codegen could be better.
986 if (LT.second.getScalarType() == MVT::f16 && MTy.isFixedLengthVector() &&
987 MTy.getScalarSizeInBits() == 64)
988 return MTy.getVectorNumElements() * 3;
989
990 // If we can we use a legal convert followed by a min+max
991 if ((LT.second.getScalarType() == MVT::f32 ||
992 LT.second.getScalarType() == MVT::f64 ||
993 LT.second.getScalarType() == MVT::f16) &&
994 LT.second.getScalarSizeInBits() >= MTy.getScalarSizeInBits()) {
995 Type *LegalTy =
996 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
997 if (LT.second.isVector())
998 LegalTy = VectorType::get(LegalTy, LT.second.getVectorElementCount());
1000 IntrinsicCostAttributes Attrs1(IsSigned ? Intrinsic::smin
1001 : Intrinsic::umin,
1002 LegalTy, {LegalTy, LegalTy});
1004 IntrinsicCostAttributes Attrs2(IsSigned ? Intrinsic::smax
1005 : Intrinsic::umax,
1006 LegalTy, {LegalTy, LegalTy});
1008 return LT.first * Cost +
1009 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1010 : 1);
1011 }
1012 // Otherwise we need to follow the default expansion that clamps the value
1013 // using a float min/max with a fcmp+sel for nan handling when signed.
1014 Type *FPTy = ICA.getArgTypes()[0]->getScalarType();
1015 RetTy = RetTy->getScalarType();
1016 if (LT.second.isVector()) {
1017 FPTy = VectorType::get(FPTy, LT.second.getVectorElementCount());
1018 RetTy = VectorType::get(RetTy, LT.second.getVectorElementCount());
1019 }
1020 IntrinsicCostAttributes Attrs1(Intrinsic::minnum, FPTy, {FPTy, FPTy});
1022 IntrinsicCostAttributes Attrs2(Intrinsic::maxnum, FPTy, {FPTy, FPTy});
1024 Cost +=
1025 getCastInstrCost(IsSigned ? Instruction::FPToSI : Instruction::FPToUI,
1026 RetTy, FPTy, TTI::CastContextHint::None, CostKind);
1027 if (IsSigned) {
1028 Type *CondTy = RetTy->getWithNewBitWidth(1);
1029 Cost += getCmpSelInstrCost(BinaryOperator::FCmp, FPTy, CondTy,
1031 Cost += getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,
1033 }
1034 return LT.first * Cost;
1035 }
1036 case Intrinsic::fshl:
1037 case Intrinsic::fshr: {
1038 if (ICA.getArgs().empty())
1039 break;
1040
1041 const TTI::OperandValueInfo OpInfoZ = TTI::getOperandInfo(ICA.getArgs()[2]);
1042
1043 // ROTR / ROTL is a funnel shift with equal first and second operand. For
1044 // ROTR on integer registers (i32/i64) this can be done in a single ror
1045 // instruction. A fshl with a non-constant shift uses a neg + ror.
1046 if (RetTy->isIntegerTy() && ICA.getArgs()[0] == ICA.getArgs()[1] &&
1047 (RetTy->getPrimitiveSizeInBits() == 32 ||
1048 RetTy->getPrimitiveSizeInBits() == 64)) {
1049 InstructionCost NegCost =
1050 (ICA.getID() == Intrinsic::fshl && !OpInfoZ.isConstant()) ? 1 : 0;
1051 return 1 + NegCost;
1052 }
1053
1054 // TODO: Add handling for fshl where third argument is not a constant.
1055 if (!OpInfoZ.isConstant())
1056 break;
1057
1058 const auto LegalisationCost = getTypeLegalizationCost(RetTy);
1059 if (OpInfoZ.isUniform()) {
1060 static const CostTblEntry FshlTbl[] = {
1061 {Intrinsic::fshl, MVT::v4i32, 2}, // shl + usra
1062 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1063 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1064 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1065 // Costs for both fshl & fshr are the same, so just pass Intrinsic::fshl
1066 // to avoid having to duplicate the costs.
1067 const auto *Entry =
1068 CostTableLookup(FshlTbl, Intrinsic::fshl, LegalisationCost.second);
1069 if (Entry)
1070 return LegalisationCost.first * Entry->Cost;
1071 }
1072
1073 auto TyL = getTypeLegalizationCost(RetTy);
1074 if (!RetTy->isIntegerTy())
1075 break;
1076
1077 // Estimate cost manually, as types like i8 and i16 will get promoted to
1078 // i32 and CostTableLookup will ignore the extra conversion cost.
1079 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1080 RetTy->getScalarSizeInBits() < 64) ||
1081 (RetTy->getScalarSizeInBits() % 64 != 0);
1082 unsigned ExtraCost = HigherCost ? 1 : 0;
1083 if (RetTy->getScalarSizeInBits() == 32 ||
1084 RetTy->getScalarSizeInBits() == 64)
1085 ExtraCost = 0; // fhsl/fshr for i32 and i64 can be lowered to a single
1086 // extr instruction.
1087 else if (HigherCost)
1088 ExtraCost = 1;
1089 else
1090 break;
1091 return TyL.first + ExtraCost;
1092 }
1093 case Intrinsic::get_active_lane_mask: {
1094 auto RetTy = cast<VectorType>(ICA.getReturnType());
1095 EVT RetVT = getTLI()->getValueType(DL, RetTy);
1096 EVT OpVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);
1097 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1098 break;
1099
1100 if (RetTy->isScalableTy()) {
1101 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1103 break;
1104
1105 auto LT = getTypeLegalizationCost(RetTy);
1106 InstructionCost Cost = LT.first;
1107 // When SVE2p1 or SME2 is available, we can halve getTypeLegalizationCost
1108 // as get_active_lane_mask may lower to the sve_whilelo_x2 intrinsic, e.g.
1109 // nxv32i1 = get_active_lane_mask(base, idx) ->
1110 // {nxv16i1, nxv16i1} = sve_whilelo_x2(base, idx)
1111 if (ST->hasSVE2p1() || ST->hasSME2()) {
1112 Cost /= 2;
1113 if (Cost == 1)
1114 return Cost;
1115 }
1116
1117 // If more than one whilelo intrinsic is required, include the extra cost
1118 // required by the saturating add & select required to increment the
1119 // start value after the first intrinsic call.
1120 Type *OpTy = ICA.getArgTypes()[0];
1121 IntrinsicCostAttributes AddAttrs(Intrinsic::uadd_sat, OpTy, {OpTy, OpTy});
1122 InstructionCost SplitCost = getIntrinsicInstrCost(AddAttrs, CostKind);
1123 Type *CondTy = OpTy->getWithNewBitWidth(1);
1124 SplitCost += getCmpSelInstrCost(Instruction::Select, OpTy, CondTy,
1126 return Cost + (SplitCost * (Cost - 1));
1127 } else if (!getTLI()->isTypeLegal(RetVT)) {
1128 // We don't have enough context at this point to determine if the mask
1129 // is going to be kept live after the block, which will force the vXi1
1130 // type to be expanded to legal vectors of integers, e.g. v4i1->v4i32.
1131 // For now, we just assume the vectorizer created this intrinsic and
1132 // the result will be the input for a PHI. In this case the cost will
1133 // be extremely high for fixed-width vectors.
1134 // NOTE: getScalarizationOverhead returns a cost that's far too
1135 // pessimistic for the actual generated codegen. In reality there are
1136 // two instructions generated per lane.
1137 return cast<FixedVectorType>(RetTy)->getNumElements() * 2;
1138 }
1139 break;
1140 }
1141 case Intrinsic::experimental_vector_match: {
1142 auto *NeedleTy = cast<FixedVectorType>(ICA.getArgTypes()[1]);
1143 EVT SearchVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);
1144 unsigned SearchSize = NeedleTy->getNumElements();
1145 if (!getTLI()->shouldExpandVectorMatch(SearchVT, SearchSize)) {
1146 // Base cost for MATCH instructions. At least on the Neoverse V2 and
1147 // Neoverse V3, these are cheap operations with the same latency as a
1148 // vector ADD. In most cases, however, we also need to do an extra DUP.
1149 // For fixed-length vectors we currently need an extra five--six
1150 // instructions besides the MATCH.
1152 if (isa<FixedVectorType>(RetTy))
1153 Cost += 10;
1154 return Cost;
1155 }
1156 break;
1157 }
1158 case Intrinsic::cttz: {
1159 auto LT = getTypeLegalizationCost(ICA.getArgTypes()[0]);
1160 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1161 return LT.first * 2;
1162 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1163 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1164 return LT.first * 3;
1165 break;
1166 }
1167 case Intrinsic::experimental_cttz_elts: {
1168 EVT ArgVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);
1169 if (!getTLI()->shouldExpandCttzElements(ArgVT)) {
1170 // This will consist of a SVE brkb and a cntp instruction. These
1171 // typically have the same latency and half the throughput as a vector
1172 // add instruction.
1173 return 4;
1174 }
1175 break;
1176 }
1177 case Intrinsic::loop_dependence_raw_mask:
1178 case Intrinsic::loop_dependence_war_mask: {
1179 // The whilewr/rw instructions require SVE2 or SME.
1180 if (ST->hasSVE2() || ST->hasSME()) {
1181 EVT VecVT = getTLI()->getValueType(DL, RetTy);
1182 unsigned EltSizeInBytes =
1183 cast<ConstantInt>(ICA.getArgs()[2])->getZExtValue();
1184 if (!is_contained({1u, 2u, 4u, 8u}, EltSizeInBytes) ||
1185 VecVT.getVectorMinNumElements() != (16 / EltSizeInBytes))
1186 break;
1187 // For fixed-vector types we need to AND the mask with a ptrue vl<N>.
1188 return isa<FixedVectorType>(RetTy) ? 2 : 1;
1189 }
1190 break;
1191 }
1192 case Intrinsic::experimental_vector_extract_last_active:
1193 if (ST->isSVEorStreamingSVEAvailable()) {
1194 auto [LegalCost, _] = getTypeLegalizationCost(ICA.getArgTypes()[0]);
1195 // This should turn into chained clastb instructions.
1196 return LegalCost;
1197 }
1198 break;
1199 case Intrinsic::pow: {
1200 // For scalar calls we know the target has the libcall, and for fixed-width
1201 // vectors we know for the worst case it can be scalarised.
1202 EVT VT = getTLI()->getValueType(DL, RetTy);
1203 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1204 bool HasLibcall = getTLI()->getLibcallImpl(LC) != RTLIB::Unsupported;
1205 bool CanLowerWithLibcalls = !isa<ScalableVectorType>(RetTy) || HasLibcall;
1206
1207 // If we know that the call can be lowered with libcalls then it's safe to
1208 // reduce the costs in some cases. This is important for scalable vectors,
1209 // since we cannot scalarize the call in the absence of a vector math
1210 // library.
1211 if (CanLowerWithLibcalls && ICA.getInst() && !ICA.getArgs().empty()) {
1212 // If we know the fast math flags and the exponent is a constant then the
1213 // cost may be less for some exponents like 0.25 and 0.75.
1214 const Constant *ExpC = dyn_cast<Constant>(ICA.getArgs()[1]);
1215 if (ExpC && isa<VectorType>(ExpC->getType()))
1216 ExpC = ExpC->getSplatValue();
1217 if (auto *ExpF = dyn_cast_or_null<ConstantFP>(ExpC)) {
1218 // The argument must be a FP constant.
1219 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1220 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1221 FastMathFlags FMF = ICA.getInst()->getFastMathFlags();
1222 if ((Is025 || Is075) && FMF.noInfs() && FMF.approxFunc() &&
1223 (!Is025 || FMF.noSignedZeros())) {
1224 IntrinsicCostAttributes Attrs(Intrinsic::sqrt, RetTy, {RetTy}, FMF);
1226 if (Is025)
1227 return 2 * Sqrt;
1229 getArithmeticInstrCost(Instruction::FMul, RetTy, CostKind);
1230 return (Sqrt * 2) + FMul;
1231 }
1232 // TODO: For 1/3 exponents we expect the cbrt call to be slightly
1233 // cheaper than pow.
1234 }
1235 }
1236
1237 if (HasLibcall)
1238 return getCallInstrCost(nullptr, RetTy, ICA.getArgTypes(), CostKind);
1239 break;
1240 }
1241 case Intrinsic::sqrt:
1242 case Intrinsic::fabs:
1243 case Intrinsic::ceil:
1244 case Intrinsic::floor:
1245 case Intrinsic::nearbyint:
1246 case Intrinsic::round:
1247 case Intrinsic::rint:
1248 case Intrinsic::roundeven:
1249 case Intrinsic::trunc:
1250 case Intrinsic::minnum:
1251 case Intrinsic::maxnum:
1252 case Intrinsic::minimum:
1253 case Intrinsic::maximum: {
1254 if (isa<ScalableVectorType>(RetTy) && ST->isSVEorStreamingSVEAvailable()) {
1255 auto LT = getTypeLegalizationCost(RetTy);
1256 return LT.first;
1257 }
1258 break;
1259 }
1260 default:
1261 break;
1262 }
1264}
1265
1266/// The function will remove redundant reinterprets casting in the presence
1267/// of the control flow
1268static std::optional<Instruction *> processPhiNode(InstCombiner &IC,
1269 IntrinsicInst &II) {
1271 auto RequiredType = II.getType();
1272
1273 auto *PN = dyn_cast<PHINode>(II.getArgOperand(0));
1274 assert(PN && "Expected Phi Node!");
1275
1276 // Don't create a new Phi unless we can remove the old one.
1277 if (!PN->hasOneUse())
1278 return std::nullopt;
1279
1280 for (Value *IncValPhi : PN->incoming_values()) {
1281 auto *Reinterpret = dyn_cast<IntrinsicInst>(IncValPhi);
1282 if (!Reinterpret ||
1283 Reinterpret->getIntrinsicID() !=
1284 Intrinsic::aarch64_sve_convert_to_svbool ||
1285 RequiredType != Reinterpret->getArgOperand(0)->getType())
1286 return std::nullopt;
1287 }
1288
1289 // Create the new Phi
1290 IC.Builder.SetInsertPoint(PN);
1291 PHINode *NPN = IC.Builder.CreatePHI(RequiredType, PN->getNumIncomingValues());
1292 Worklist.push_back(PN);
1293
1294 for (unsigned I = 0; I < PN->getNumIncomingValues(); I++) {
1295 auto *Reinterpret = cast<Instruction>(PN->getIncomingValue(I));
1296 NPN->addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(I));
1297 Worklist.push_back(Reinterpret);
1298 }
1299
1300 // Cleanup Phi Node and reinterprets
1301 return IC.replaceInstUsesWith(II, NPN);
1302}
1303
1304// A collection of properties common to SVE intrinsics that allow for combines
1305// to be written without needing to know the specific intrinsic.
1307 //
1308 // Helper routines for common intrinsic definitions.
1309 //
1310
1311 // e.g. llvm.aarch64.sve.add pg, op1, op2
1312 // with IID ==> llvm.aarch64.sve.add_u
1313 static SVEIntrinsicInfo
1320
1321 // e.g. llvm.aarch64.sve.neg inactive, pg, op
1328
1329 // e.g. llvm.aarch64.sve.fcvtnt inactive, pg, op
1335
1336 // e.g. llvm.aarch64.sve.add_u pg, op1, op2
1342
1343 // e.g. llvm.aarch64.sve.prf pg, ptr (GPIndex = 0)
1344 // llvm.aarch64.sve.st1 data, pg, ptr (GPIndex = 1)
1345 static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex) {
1346 return SVEIntrinsicInfo()
1349 }
1350
1351 // e.g. llvm.aarch64.sve.cmpeq pg, op1, op2
1352 // llvm.aarch64.sve.ld1 pg, ptr
1359
1360 // All properties relate to predication and thus having a general predicate
1361 // is the minimum requirement to say there is intrinsic info to act on.
1362 explicit operator bool() const { return hasGoverningPredicate(); }
1363
1364 //
1365 // Properties relating to the governing predicate.
1366 //
1367
1369 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1370 }
1371
1373 assert(hasGoverningPredicate() && "Propery not set!");
1374 return GoverningPredicateIdx;
1375 }
1376
1378 assert(!hasGoverningPredicate() && "Cannot set property twice!");
1379 GoverningPredicateIdx = Index;
1380 return *this;
1381 }
1382
1383 //
1384 // Properties relating to operations the intrinsic could be transformed into.
1385 // NOTE: This does not mean such a transformation is always possible, but the
1386 // knowledge makes it possible to reuse existing optimisations without needing
1387 // to embed specific handling for each intrinsic. For example, instruction
1388 // simplification can be used to optimise an intrinsic's active lanes.
1389 //
1390
1392 return UndefIntrinsic != Intrinsic::not_intrinsic;
1393 }
1394
1396 assert(hasMatchingUndefIntrinsic() && "Propery not set!");
1397 return UndefIntrinsic;
1398 }
1399
1401 assert(!hasMatchingUndefIntrinsic() && "Cannot set property twice!");
1402 UndefIntrinsic = IID;
1403 return *this;
1404 }
1405
1406 bool hasMatchingIROpode() const { return IROpcode != 0; }
1407
1408 unsigned getMatchingIROpode() const {
1409 assert(hasMatchingIROpode() && "Propery not set!");
1410 return IROpcode;
1411 }
1412
1414 assert(!hasMatchingIROpode() && "Cannot set property twice!");
1415 IROpcode = Opcode;
1416 return *this;
1417 }
1418
1419 //
1420 // Properties relating to the result of inactive lanes.
1421 //
1422
1424 return ResultLanes == InactiveLanesTakenFromOperand;
1425 }
1426
1428 assert(inactiveLanesTakenFromOperand() && "Propery not set!");
1429 return OperandIdxForInactiveLanes;
1430 }
1431
1433 assert(ResultLanes == Uninitialized && "Cannot set property twice!");
1434 ResultLanes = InactiveLanesTakenFromOperand;
1435 OperandIdxForInactiveLanes = Index;
1436 return *this;
1437 }
1438
1440 return ResultLanes == InactiveLanesAreNotDefined;
1441 }
1442
1444 assert(ResultLanes == Uninitialized && "Cannot set property twice!");
1445 ResultLanes = InactiveLanesAreNotDefined;
1446 return *this;
1447 }
1448
1450 return ResultLanes == InactiveLanesAreUnused;
1451 }
1452
1454 assert(ResultLanes == Uninitialized && "Cannot set property twice!");
1455 ResultLanes = InactiveLanesAreUnused;
1456 return *this;
1457 }
1458
1459 // NOTE: Whilst not limited to only inactive lanes, the common use case is:
1460 // inactiveLanesAreZeroed =
1461 // resultIsZeroInitialized() && inactiveLanesAreUnused()
1462 bool resultIsZeroInitialized() const { return ResultIsZeroInitialized; }
1463
1465 ResultIsZeroInitialized = true;
1466 return *this;
1467 }
1468
1469 //
1470 // The first operand of unary merging operations is typically only used to
1471 // set the result for inactive lanes. Knowing this allows us to deadcode the
1472 // operand when we can prove there are no inactive lanes.
1473 //
1474
1476 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1477 }
1478
1480 assert(hasOperandWithNoActiveLanes() && "Propery not set!");
1481 return OperandIdxWithNoActiveLanes;
1482 }
1483
1485 assert(!hasOperandWithNoActiveLanes() && "Cannot set property twice!");
1486 OperandIdxWithNoActiveLanes = Index;
1487 return *this;
1488 }
1489
1490private:
1491 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1492
1493 Intrinsic::ID UndefIntrinsic = Intrinsic::not_intrinsic;
1494 unsigned IROpcode = 0;
1495
1496 enum PredicationStyle {
1498 InactiveLanesTakenFromOperand,
1499 InactiveLanesAreNotDefined,
1500 InactiveLanesAreUnused
1501 } ResultLanes = Uninitialized;
1502
1503 bool ResultIsZeroInitialized = false;
1504 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1505 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1506};
1507
1509 // Some SVE intrinsics do not use scalable vector types, but since they are
1510 // not relevant from an SVEIntrinsicInfo perspective, they are also ignored.
1511 if (!isa<ScalableVectorType>(II.getType()) &&
1512 all_of(II.args(), [&](const Value *V) {
1513 return !isa<ScalableVectorType>(V->getType());
1514 }))
1515 return SVEIntrinsicInfo();
1516
1517 Intrinsic::ID IID = II.getIntrinsicID();
1518 switch (IID) {
1519 default:
1520 break;
1521 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1522 case Intrinsic::aarch64_sve_fcvt_f16f32:
1523 case Intrinsic::aarch64_sve_fcvt_f16f64:
1524 case Intrinsic::aarch64_sve_fcvt_f32f16:
1525 case Intrinsic::aarch64_sve_fcvt_f32f64:
1526 case Intrinsic::aarch64_sve_fcvt_f64f16:
1527 case Intrinsic::aarch64_sve_fcvt_f64f32:
1528 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1529 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1530 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1531 case Intrinsic::aarch64_sve_fcvtzs:
1532 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1533 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1534 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1535 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1536 case Intrinsic::aarch64_sve_fcvtzu:
1537 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1538 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1539 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1540 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1541 case Intrinsic::aarch64_sve_revb:
1542 case Intrinsic::aarch64_sve_revh:
1543 case Intrinsic::aarch64_sve_revw:
1544 case Intrinsic::aarch64_sve_revd:
1545 case Intrinsic::aarch64_sve_scvtf:
1546 case Intrinsic::aarch64_sve_scvtf_f16i32:
1547 case Intrinsic::aarch64_sve_scvtf_f16i64:
1548 case Intrinsic::aarch64_sve_scvtf_f32i64:
1549 case Intrinsic::aarch64_sve_scvtf_f64i32:
1550 case Intrinsic::aarch64_sve_ucvtf:
1551 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1552 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1553 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1554 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1556
1557 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1558 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1559 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1560 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1562
1563 case Intrinsic::aarch64_sve_fabd:
1564 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fabd_u);
1565 case Intrinsic::aarch64_sve_fadd:
1566 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fadd_u)
1567 .setMatchingIROpcode(Instruction::FAdd);
1568 case Intrinsic::aarch64_sve_fdiv:
1569 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fdiv_u)
1570 .setMatchingIROpcode(Instruction::FDiv);
1571 case Intrinsic::aarch64_sve_fmax:
1572 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmax_u);
1573 case Intrinsic::aarch64_sve_fmaxnm:
1574 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmaxnm_u);
1575 case Intrinsic::aarch64_sve_fmin:
1576 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmin_u);
1577 case Intrinsic::aarch64_sve_fminnm:
1578 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fminnm_u);
1579 case Intrinsic::aarch64_sve_fmla:
1580 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmla_u);
1581 case Intrinsic::aarch64_sve_fmls:
1582 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmls_u);
1583 case Intrinsic::aarch64_sve_fmul:
1584 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmul_u)
1585 .setMatchingIROpcode(Instruction::FMul);
1586 case Intrinsic::aarch64_sve_fmulx:
1587 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmulx_u);
1588 case Intrinsic::aarch64_sve_fnmla:
1589 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fnmla_u);
1590 case Intrinsic::aarch64_sve_fnmls:
1591 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fnmls_u);
1592 case Intrinsic::aarch64_sve_fsub:
1593 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fsub_u)
1594 .setMatchingIROpcode(Instruction::FSub);
1595 case Intrinsic::aarch64_sve_add:
1596 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_add_u)
1597 .setMatchingIROpcode(Instruction::Add);
1598 case Intrinsic::aarch64_sve_mla:
1599 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mla_u);
1600 case Intrinsic::aarch64_sve_mls:
1601 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mls_u);
1602 case Intrinsic::aarch64_sve_mul:
1603 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mul_u)
1604 .setMatchingIROpcode(Instruction::Mul);
1605 case Intrinsic::aarch64_sve_sabd:
1606 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sabd_u);
1607 case Intrinsic::aarch64_sve_sdiv:
1608 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sdiv_u)
1609 .setMatchingIROpcode(Instruction::SDiv);
1610 case Intrinsic::aarch64_sve_smax:
1611 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smax_u);
1612 case Intrinsic::aarch64_sve_smin:
1613 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smin_u);
1614 case Intrinsic::aarch64_sve_smulh:
1615 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smulh_u);
1616 case Intrinsic::aarch64_sve_sub:
1617 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sub_u)
1618 .setMatchingIROpcode(Instruction::Sub);
1619 case Intrinsic::aarch64_sve_uabd:
1620 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uabd_u);
1621 case Intrinsic::aarch64_sve_udiv:
1622 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_udiv_u)
1623 .setMatchingIROpcode(Instruction::UDiv);
1624 case Intrinsic::aarch64_sve_umax:
1625 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umax_u);
1626 case Intrinsic::aarch64_sve_umin:
1627 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umin_u);
1628 case Intrinsic::aarch64_sve_umulh:
1629 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umulh_u);
1630 case Intrinsic::aarch64_sve_asr:
1631 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_asr_u)
1632 .setMatchingIROpcode(Instruction::AShr);
1633 case Intrinsic::aarch64_sve_lsl:
1634 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_lsl_u)
1635 .setMatchingIROpcode(Instruction::Shl);
1636 case Intrinsic::aarch64_sve_lsr:
1637 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_lsr_u)
1638 .setMatchingIROpcode(Instruction::LShr);
1639 case Intrinsic::aarch64_sve_and:
1640 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_and_u)
1641 .setMatchingIROpcode(Instruction::And);
1642 case Intrinsic::aarch64_sve_bic:
1643 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_bic_u);
1644 case Intrinsic::aarch64_sve_eor:
1645 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_eor_u)
1646 .setMatchingIROpcode(Instruction::Xor);
1647 case Intrinsic::aarch64_sve_orr:
1648 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_orr_u)
1649 .setMatchingIROpcode(Instruction::Or);
1650 case Intrinsic::aarch64_sve_shsub:
1651 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_shsub_u);
1652 case Intrinsic::aarch64_sve_shsubr:
1654 case Intrinsic::aarch64_sve_sqrshl:
1655 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sqrshl_u);
1656 case Intrinsic::aarch64_sve_sqshl:
1657 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sqshl_u);
1658 case Intrinsic::aarch64_sve_sqsub:
1659 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sqsub_u);
1660 case Intrinsic::aarch64_sve_srshl:
1661 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_srshl_u);
1662 case Intrinsic::aarch64_sve_uhsub:
1663 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uhsub_u);
1664 case Intrinsic::aarch64_sve_uhsubr:
1666 case Intrinsic::aarch64_sve_uqrshl:
1667 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uqrshl_u);
1668 case Intrinsic::aarch64_sve_uqshl:
1669 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uqshl_u);
1670 case Intrinsic::aarch64_sve_uqsub:
1671 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uqsub_u);
1672 case Intrinsic::aarch64_sve_urshl:
1673 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_urshl_u);
1674
1675 case Intrinsic::aarch64_sve_add_u:
1677 Instruction::Add);
1678 case Intrinsic::aarch64_sve_and_u:
1680 Instruction::And);
1681 case Intrinsic::aarch64_sve_asr_u:
1683 Instruction::AShr);
1684 case Intrinsic::aarch64_sve_eor_u:
1686 Instruction::Xor);
1687 case Intrinsic::aarch64_sve_fadd_u:
1689 Instruction::FAdd);
1690 case Intrinsic::aarch64_sve_fdiv_u:
1692 Instruction::FDiv);
1693 case Intrinsic::aarch64_sve_fmul_u:
1695 Instruction::FMul);
1696 case Intrinsic::aarch64_sve_fsub_u:
1698 Instruction::FSub);
1699 case Intrinsic::aarch64_sve_lsl_u:
1701 Instruction::Shl);
1702 case Intrinsic::aarch64_sve_lsr_u:
1704 Instruction::LShr);
1705 case Intrinsic::aarch64_sve_mul_u:
1707 Instruction::Mul);
1708 case Intrinsic::aarch64_sve_orr_u:
1710 Instruction::Or);
1711 case Intrinsic::aarch64_sve_sdiv_u:
1713 Instruction::SDiv);
1714 case Intrinsic::aarch64_sve_sub_u:
1716 Instruction::Sub);
1717 case Intrinsic::aarch64_sve_udiv_u:
1719 Instruction::UDiv);
1720
1721 case Intrinsic::aarch64_sve_addqv:
1722 case Intrinsic::aarch64_sve_and_z:
1723 case Intrinsic::aarch64_sve_bic_z:
1724 case Intrinsic::aarch64_sve_brka_z:
1725 case Intrinsic::aarch64_sve_brkb_z:
1726 case Intrinsic::aarch64_sve_brkn_z:
1727 case Intrinsic::aarch64_sve_brkpa_z:
1728 case Intrinsic::aarch64_sve_brkpb_z:
1729 case Intrinsic::aarch64_sve_cntp:
1730 case Intrinsic::aarch64_sve_compact:
1731 case Intrinsic::aarch64_sve_eor_z:
1732 case Intrinsic::aarch64_sve_eorv:
1733 case Intrinsic::aarch64_sve_eorqv:
1734 case Intrinsic::aarch64_sve_nand_z:
1735 case Intrinsic::aarch64_sve_nor_z:
1736 case Intrinsic::aarch64_sve_orn_z:
1737 case Intrinsic::aarch64_sve_orr_z:
1738 case Intrinsic::aarch64_sve_orv:
1739 case Intrinsic::aarch64_sve_orqv:
1740 case Intrinsic::aarch64_sve_pnext:
1741 case Intrinsic::aarch64_sve_rdffr_z:
1742 case Intrinsic::aarch64_sve_saddv:
1743 case Intrinsic::aarch64_sve_uaddv:
1744 case Intrinsic::aarch64_sve_umaxv:
1745 case Intrinsic::aarch64_sve_umaxqv:
1746 case Intrinsic::aarch64_sve_cmpeq:
1747 case Intrinsic::aarch64_sve_cmpeq_wide:
1748 case Intrinsic::aarch64_sve_cmpge:
1749 case Intrinsic::aarch64_sve_cmpge_wide:
1750 case Intrinsic::aarch64_sve_cmpgt:
1751 case Intrinsic::aarch64_sve_cmpgt_wide:
1752 case Intrinsic::aarch64_sve_cmphi:
1753 case Intrinsic::aarch64_sve_cmphi_wide:
1754 case Intrinsic::aarch64_sve_cmphs:
1755 case Intrinsic::aarch64_sve_cmphs_wide:
1756 case Intrinsic::aarch64_sve_cmple_wide:
1757 case Intrinsic::aarch64_sve_cmplo_wide:
1758 case Intrinsic::aarch64_sve_cmpls_wide:
1759 case Intrinsic::aarch64_sve_cmplt_wide:
1760 case Intrinsic::aarch64_sve_cmpne:
1761 case Intrinsic::aarch64_sve_cmpne_wide:
1762 case Intrinsic::aarch64_sve_facge:
1763 case Intrinsic::aarch64_sve_facgt:
1764 case Intrinsic::aarch64_sve_fcmpeq:
1765 case Intrinsic::aarch64_sve_fcmpge:
1766 case Intrinsic::aarch64_sve_fcmpgt:
1767 case Intrinsic::aarch64_sve_fcmpne:
1768 case Intrinsic::aarch64_sve_fcmpuo:
1769 case Intrinsic::aarch64_sve_ld1:
1770 case Intrinsic::aarch64_sve_ld1_gather:
1771 case Intrinsic::aarch64_sve_ld1_gather_index:
1772 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1773 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1774 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1775 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1776 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1777 case Intrinsic::aarch64_sve_ld1q_gather_index:
1778 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1779 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1780 case Intrinsic::aarch64_sve_ld1ro:
1781 case Intrinsic::aarch64_sve_ld1rq:
1782 case Intrinsic::aarch64_sve_ld1udq:
1783 case Intrinsic::aarch64_sve_ld1uwq:
1784 case Intrinsic::aarch64_sve_ld2_sret:
1785 case Intrinsic::aarch64_sve_ld2q_sret:
1786 case Intrinsic::aarch64_sve_ld3_sret:
1787 case Intrinsic::aarch64_sve_ld3q_sret:
1788 case Intrinsic::aarch64_sve_ld4_sret:
1789 case Intrinsic::aarch64_sve_ld4q_sret:
1790 case Intrinsic::aarch64_sve_ldff1:
1791 case Intrinsic::aarch64_sve_ldff1_gather:
1792 case Intrinsic::aarch64_sve_ldff1_gather_index:
1793 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1794 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1795 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1796 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1797 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1798 case Intrinsic::aarch64_sve_ldnf1:
1799 case Intrinsic::aarch64_sve_ldnt1:
1800 case Intrinsic::aarch64_sve_ldnt1_gather:
1801 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1802 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1803 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1805
1806 case Intrinsic::aarch64_sve_prf:
1807 case Intrinsic::aarch64_sve_prfb_gather_index:
1808 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
1809 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
1810 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
1811 case Intrinsic::aarch64_sve_prfd_gather_index:
1812 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
1813 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
1814 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
1815 case Intrinsic::aarch64_sve_prfh_gather_index:
1816 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
1817 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
1818 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
1819 case Intrinsic::aarch64_sve_prfw_gather_index:
1820 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
1821 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
1822 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
1824
1825 case Intrinsic::aarch64_sve_st1_scatter:
1826 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
1827 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
1828 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
1829 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
1830 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
1831 case Intrinsic::aarch64_sve_st1dq:
1832 case Intrinsic::aarch64_sve_st1q_scatter_index:
1833 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
1834 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
1835 case Intrinsic::aarch64_sve_st1wq:
1836 case Intrinsic::aarch64_sve_stnt1:
1837 case Intrinsic::aarch64_sve_stnt1_scatter:
1838 case Intrinsic::aarch64_sve_stnt1_scatter_index:
1839 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
1840 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
1842 case Intrinsic::aarch64_sve_st2:
1843 case Intrinsic::aarch64_sve_st2q:
1845 case Intrinsic::aarch64_sve_st3:
1846 case Intrinsic::aarch64_sve_st3q:
1848 case Intrinsic::aarch64_sve_st4:
1849 case Intrinsic::aarch64_sve_st4q:
1851 }
1852
1853 return SVEIntrinsicInfo();
1854}
1855
1856static bool isAllActivePredicate(Value *Pred) {
1857 Value *UncastedPred;
1858
1859 // Look through predicate casts that only remove lanes.
1861 m_Value(UncastedPred)))) {
1862 auto *OrigPredTy = cast<ScalableVectorType>(Pred->getType());
1863 Pred = UncastedPred;
1864
1866 m_Value(UncastedPred))))
1867 // If the predicate has the same or less lanes than the uncasted predicate
1868 // then we know the casting has no effect.
1869 if (OrigPredTy->getMinNumElements() <=
1870 cast<ScalableVectorType>(UncastedPred->getType())
1871 ->getMinNumElements())
1872 Pred = UncastedPred;
1873 }
1874
1875 auto *C = dyn_cast<Constant>(Pred);
1876 return C && C->isAllOnesValue();
1877}
1878
1879// Simplify `V` by only considering the operations that affect active lanes.
1880// This function should only return existing Values or newly created Constants.
1881static Value *stripInactiveLanes(Value *V, const Value *Pg) {
1882 auto *Dup = dyn_cast<IntrinsicInst>(V);
1883 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
1884 Dup->getOperand(1) == Pg && isa<Constant>(Dup->getOperand(2)))
1886 cast<VectorType>(V->getType())->getElementCount(),
1887 cast<Constant>(Dup->getOperand(2)));
1888
1889 return V;
1890}
1891
1892static std::optional<Instruction *>
1894 const SVEIntrinsicInfo &IInfo) {
1895 const unsigned Opc = IInfo.getMatchingIROpode();
1896 assert(Instruction::isBinaryOp(Opc) && "Expected a binary operation!");
1897
1898 Value *Pg = II.getOperand(0);
1899 Value *Op1 = II.getOperand(1);
1900 Value *Op2 = II.getOperand(2);
1901 const DataLayout &DL = II.getDataLayout();
1902
1903 // Canonicalise constants to the RHS.
1905 isa<Constant>(Op1) && !isa<Constant>(Op2)) {
1906 IC.replaceOperand(II, 1, Op2);
1907 IC.replaceOperand(II, 2, Op1);
1908 return &II;
1909 }
1910
1911 // Only active lanes matter when simplifying the operation.
1912 Op1 = stripInactiveLanes(Op1, Pg);
1913 Op2 = stripInactiveLanes(Op2, Pg);
1914
1915 Value *SimpleII;
1916 if (auto FII = dyn_cast<FPMathOperator>(&II))
1917 SimpleII = simplifyBinOp(Opc, Op1, Op2, FII->getFastMathFlags(), DL);
1918 else
1919 SimpleII = simplifyBinOp(Opc, Op1, Op2, DL);
1920
1921 // An SVE intrinsic's result is always defined. However, this is not the case
1922 // for its equivalent IR instruction (e.g. when shifting by an amount more
1923 // than the data's bitwidth). Simplifications to an undefined result must be
1924 // ignored to preserve the intrinsic's expected behaviour.
1925 if (!SimpleII || isa<UndefValue>(SimpleII))
1926 return std::nullopt;
1927
1928 if (IInfo.inactiveLanesAreNotDefined())
1929 return IC.replaceInstUsesWith(II, SimpleII);
1930
1931 Value *Inactive = II.getOperand(IInfo.getOperandIdxInactiveLanesTakenFrom());
1932
1933 // The intrinsic does nothing (e.g. sve.mul(pg, A, 1.0)).
1934 if (SimpleII == Inactive)
1935 return IC.replaceInstUsesWith(II, SimpleII);
1936
1937 // Inactive lanes must be preserved.
1938 SimpleII = IC.Builder.CreateSelect(Pg, SimpleII, Inactive);
1939 return IC.replaceInstUsesWith(II, SimpleII);
1940}
1941
1942// Use SVE intrinsic info to eliminate redundant operands and/or canonicalise
1943// to operations with less strict inactive lane requirements.
1944static std::optional<Instruction *>
1946 const SVEIntrinsicInfo &IInfo) {
1947 if (!IInfo.hasGoverningPredicate())
1948 return std::nullopt;
1949
1950 auto *OpPredicate = II.getOperand(IInfo.getGoverningPredicateOperandIdx());
1951
1952 // If there are no active lanes.
1953 if (match(OpPredicate, m_ZeroInt())) {
1955 return IC.replaceInstUsesWith(
1956 II, II.getOperand(IInfo.getOperandIdxInactiveLanesTakenFrom()));
1957
1958 if (IInfo.inactiveLanesAreUnused()) {
1959 if (IInfo.resultIsZeroInitialized())
1961
1962 return IC.eraseInstFromFunction(II);
1963 }
1964 }
1965
1966 // If there are no inactive lanes.
1967 if (isAllActivePredicate(OpPredicate)) {
1968 if (IInfo.hasOperandWithNoActiveLanes()) {
1969 unsigned OpIdx = IInfo.getOperandIdxWithNoActiveLanes();
1970 if (!isa<UndefValue>(II.getOperand(OpIdx)))
1971 return IC.replaceOperand(II, OpIdx, UndefValue::get(II.getType()));
1972 }
1973
1974 if (IInfo.hasMatchingUndefIntrinsic()) {
1975 auto *NewDecl = Intrinsic::getOrInsertDeclaration(
1976 II.getModule(), IInfo.getMatchingUndefIntrinsic(), {II.getType()});
1977 II.setCalledFunction(NewDecl);
1978 return &II;
1979 }
1980 }
1981
1982 // Operation specific simplifications.
1983 if (IInfo.hasMatchingIROpode() &&
1985 return simplifySVEIntrinsicBinOp(IC, II, IInfo);
1986
1987 return std::nullopt;
1988}
1989
1990// (from_svbool (binop (to_svbool pred) (svbool_t _) (svbool_t _))))
1991// => (binop (pred) (from_svbool _) (from_svbool _))
1992//
1993// The above transformation eliminates a `to_svbool` in the predicate
1994// operand of bitwise operation `binop` by narrowing the vector width of
1995// the operation. For example, it would convert a `<vscale x 16 x i1>
1996// and` into a `<vscale x 4 x i1> and`. This is profitable because
1997// to_svbool must zero the new lanes during widening, whereas
1998// from_svbool is free.
1999static std::optional<Instruction *>
2001 auto BinOp = dyn_cast<IntrinsicInst>(II.getOperand(0));
2002 if (!BinOp)
2003 return std::nullopt;
2004
2005 auto IntrinsicID = BinOp->getIntrinsicID();
2006 switch (IntrinsicID) {
2007 case Intrinsic::aarch64_sve_and_z:
2008 case Intrinsic::aarch64_sve_bic_z:
2009 case Intrinsic::aarch64_sve_eor_z:
2010 case Intrinsic::aarch64_sve_nand_z:
2011 case Intrinsic::aarch64_sve_nor_z:
2012 case Intrinsic::aarch64_sve_orn_z:
2013 case Intrinsic::aarch64_sve_orr_z:
2014 break;
2015 default:
2016 return std::nullopt;
2017 }
2018
2019 auto BinOpPred = BinOp->getOperand(0);
2020 auto BinOpOp1 = BinOp->getOperand(1);
2021 auto BinOpOp2 = BinOp->getOperand(2);
2022
2023 auto PredIntr = dyn_cast<IntrinsicInst>(BinOpPred);
2024 if (!PredIntr ||
2025 PredIntr->getIntrinsicID() != Intrinsic::aarch64_sve_convert_to_svbool)
2026 return std::nullopt;
2027
2028 auto PredOp = PredIntr->getOperand(0);
2029 auto PredOpTy = cast<VectorType>(PredOp->getType());
2030 if (PredOpTy != II.getType())
2031 return std::nullopt;
2032
2033 SmallVector<Value *> NarrowedBinOpArgs = {PredOp};
2034 auto NarrowBinOpOp1 = IC.Builder.CreateIntrinsic(
2035 Intrinsic::aarch64_sve_convert_from_svbool, {PredOpTy}, {BinOpOp1});
2036 NarrowedBinOpArgs.push_back(NarrowBinOpOp1);
2037 if (BinOpOp1 == BinOpOp2)
2038 NarrowedBinOpArgs.push_back(NarrowBinOpOp1);
2039 else
2040 NarrowedBinOpArgs.push_back(IC.Builder.CreateIntrinsic(
2041 Intrinsic::aarch64_sve_convert_from_svbool, {PredOpTy}, {BinOpOp2}));
2042
2043 auto NarrowedBinOp =
2044 IC.Builder.CreateIntrinsic(IntrinsicID, {PredOpTy}, NarrowedBinOpArgs);
2045 return IC.replaceInstUsesWith(II, NarrowedBinOp);
2046}
2047
2048static std::optional<Instruction *>
2050 // If the reinterpret instruction operand is a PHI Node
2051 if (isa<PHINode>(II.getArgOperand(0)))
2052 return processPhiNode(IC, II);
2053
2054 if (auto BinOpCombine = tryCombineFromSVBoolBinOp(IC, II))
2055 return BinOpCombine;
2056
2057 // Ignore converts to/from svcount_t.
2058 if (isa<TargetExtType>(II.getArgOperand(0)->getType()) ||
2059 isa<TargetExtType>(II.getType()))
2060 return std::nullopt;
2061
2062 SmallVector<Instruction *, 32> CandidatesForRemoval;
2063 Value *Cursor = II.getOperand(0), *EarliestReplacement = nullptr;
2064
2065 const auto *IVTy = cast<VectorType>(II.getType());
2066
2067 // Walk the chain of conversions.
2068 while (Cursor) {
2069 // If the type of the cursor has fewer lanes than the final result, zeroing
2070 // must take place, which breaks the equivalence chain.
2071 const auto *CursorVTy = cast<VectorType>(Cursor->getType());
2072 if (CursorVTy->getElementCount().getKnownMinValue() <
2073 IVTy->getElementCount().getKnownMinValue())
2074 break;
2075
2076 // If the cursor has the same type as I, it is a viable replacement.
2077 if (Cursor->getType() == IVTy)
2078 EarliestReplacement = Cursor;
2079
2080 auto *IntrinsicCursor = dyn_cast<IntrinsicInst>(Cursor);
2081
2082 // If this is not an SVE conversion intrinsic, this is the end of the chain.
2083 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2084 Intrinsic::aarch64_sve_convert_to_svbool ||
2085 IntrinsicCursor->getIntrinsicID() ==
2086 Intrinsic::aarch64_sve_convert_from_svbool))
2087 break;
2088
2089 CandidatesForRemoval.insert(CandidatesForRemoval.begin(), IntrinsicCursor);
2090 Cursor = IntrinsicCursor->getOperand(0);
2091 }
2092
2093 // If no viable replacement in the conversion chain was found, there is
2094 // nothing to do.
2095 if (!EarliestReplacement)
2096 return std::nullopt;
2097
2098 return IC.replaceInstUsesWith(II, EarliestReplacement);
2099}
2100
2101static std::optional<Instruction *> instCombineSVESel(InstCombiner &IC,
2102 IntrinsicInst &II) {
2103 // svsel(ptrue, x, y) => x
2104 auto *OpPredicate = II.getOperand(0);
2105 if (isAllActivePredicate(OpPredicate))
2106 return IC.replaceInstUsesWith(II, II.getOperand(1));
2107
2108 auto Select =
2109 IC.Builder.CreateSelect(OpPredicate, II.getOperand(1), II.getOperand(2));
2110 return IC.replaceInstUsesWith(II, Select);
2111}
2112
2113static std::optional<Instruction *> instCombineSVEDup(InstCombiner &IC,
2114 IntrinsicInst &II) {
2115 Value *Pg = II.getOperand(1);
2116
2117 // sve.dup(V, all_active, X) ==> splat(X)
2118 if (isAllActivePredicate(Pg)) {
2119 auto *RetTy = cast<ScalableVectorType>(II.getType());
2120 Value *Splat = IC.Builder.CreateVectorSplat(RetTy->getElementCount(),
2121 II.getArgOperand(2));
2122 return IC.replaceInstUsesWith(II, Splat);
2123 }
2124
2126 m_SpecificInt(AArch64SVEPredPattern::vl1))))
2127 return std::nullopt;
2128
2129 // sve.dup(V, sve.ptrue(vl1), X) ==> insertelement V, X, 0
2130 Value *Insert = IC.Builder.CreateInsertElement(
2131 II.getArgOperand(0), II.getArgOperand(2), uint64_t(0));
2132 return IC.replaceInstUsesWith(II, Insert);
2133}
2134
2135static std::optional<Instruction *> instCombineSVEDupX(InstCombiner &IC,
2136 IntrinsicInst &II) {
2137 // Replace DupX with a regular IR splat.
2138 auto *RetTy = cast<ScalableVectorType>(II.getType());
2139 Value *Splat = IC.Builder.CreateVectorSplat(RetTy->getElementCount(),
2140 II.getArgOperand(0));
2141 Splat->takeName(&II);
2142 return IC.replaceInstUsesWith(II, Splat);
2143}
2144
2145// xor(cmpne(%pg, %lhs, %rhs), %pg)
2146// -> cmpeq(%pg, %lhs, %rhs)
2147static std::optional<Instruction *> instCombineXorSVECmpCC(InstCombiner &IC,
2148 IntrinsicInst &II) {
2149 if (!II.hasOneUse())
2150 return std::nullopt;
2151 auto *User = cast<Instruction>(*II.user_begin());
2152 if (!match(User, m_c_Xor(m_Specific(&II), m_Specific(II.getOperand(0)))))
2153 return std::nullopt;
2154
2155 Intrinsic::ID IID;
2156 switch (II.getIntrinsicID()) {
2157 case Intrinsic::aarch64_sve_cmpne:
2158 IID = Intrinsic::aarch64_sve_cmpeq;
2159 break;
2160 case Intrinsic::aarch64_sve_cmpne_wide:
2161 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2162 break;
2163 case Intrinsic::aarch64_sve_cmpeq:
2164 IID = Intrinsic::aarch64_sve_cmpne;
2165 break;
2166 case Intrinsic::aarch64_sve_cmpeq_wide:
2167 IID = Intrinsic::aarch64_sve_cmpne_wide;
2168 break;
2169 default:
2170 return std::nullopt;
2171 }
2172
2174 Value *CMPCC = IC.Builder.CreateIntrinsic(
2175 IID, II.getOperand(1)->getType(),
2176 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2177 IC.replaceInstUsesWith(*User, CMPCC);
2179 return &II;
2180}
2181
2182// zext(cmpne(ptrue, %v, 0))
2183// -> umin(%pg, %v, 1)
2184static std::optional<Instruction *> instCombineZExtSVECmpNE(InstCombiner &IC,
2185 IntrinsicInst &II) {
2186 if (!isAllActivePredicate(II.getOperand(0)) ||
2187 !match(II.getOperand(2), m_Zero()))
2188 return std::nullopt;
2189
2190 for (auto *U : II.users()) {
2191 if (match(U, m_ZExt(m_Specific(&II)))) {
2192 auto *User = cast<Instruction>(U);
2193 Type *Ty = II.getOperand(1)->getType();
2194 if (User->getType() != Ty)
2195 continue;
2198 Intrinsic::aarch64_sve_umin, Ty,
2199 {II.getOperand(0), II.getOperand(1), ConstantInt::get(Ty, 1)});
2202 return &II;
2203 }
2204 }
2205 return std::nullopt;
2206}
2207
2208static std::optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC,
2209 IntrinsicInst &II) {
2210 LLVMContext &Ctx = II.getContext();
2211
2212 if (auto Res = instCombineXorSVECmpCC(IC, II))
2213 return Res;
2214
2215 if (auto Res = instCombineZExtSVECmpNE(IC, II))
2216 return Res;
2217
2218 if (!isAllActivePredicate(II.getArgOperand(0)))
2219 return std::nullopt;
2220
2221 // Check that we have a compare of zero..
2222 auto *SplatValue =
2224 if (!SplatValue || !SplatValue->isZero())
2225 return std::nullopt;
2226
2227 // ..against a dupq
2228 auto *DupQLane = dyn_cast<IntrinsicInst>(II.getArgOperand(1));
2229 if (!DupQLane ||
2230 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2231 return std::nullopt;
2232
2233 // Where the dupq is a lane 0 replicate of a vector insert
2234 auto *DupQLaneIdx = dyn_cast<ConstantInt>(DupQLane->getArgOperand(1));
2235 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2236 return std::nullopt;
2237
2238 auto *VecIns = dyn_cast<IntrinsicInst>(DupQLane->getArgOperand(0));
2239 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2240 return std::nullopt;
2241
2242 // Where the vector insert is a fixed constant vector insert into undef at
2243 // index zero
2244 if (!isa<UndefValue>(VecIns->getArgOperand(0)))
2245 return std::nullopt;
2246
2247 if (!cast<ConstantInt>(VecIns->getArgOperand(2))->isZero())
2248 return std::nullopt;
2249
2250 auto *ConstVec = dyn_cast<Constant>(VecIns->getArgOperand(1));
2251 if (!ConstVec)
2252 return std::nullopt;
2253
2254 auto *VecTy = dyn_cast<FixedVectorType>(ConstVec->getType());
2255 auto *OutTy = dyn_cast<ScalableVectorType>(II.getType());
2256 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2257 return std::nullopt;
2258
2259 unsigned NumElts = VecTy->getNumElements();
2260 unsigned PredicateBits = 0;
2261
2262 // Expand intrinsic operands to a 16-bit byte level predicate
2263 for (unsigned I = 0; I < NumElts; ++I) {
2264 auto *Arg = dyn_cast<ConstantInt>(ConstVec->getAggregateElement(I));
2265 if (!Arg)
2266 return std::nullopt;
2267 if (!Arg->isZero())
2268 PredicateBits |= 1 << (I * (16 / NumElts));
2269 }
2270
2271 // If all bits are zero bail early with an empty predicate
2272 if (PredicateBits == 0) {
2273 auto *PFalse = Constant::getNullValue(II.getType());
2274 PFalse->takeName(&II);
2275 return IC.replaceInstUsesWith(II, PFalse);
2276 }
2277
2278 // Calculate largest predicate type used (where byte predicate is largest)
2279 unsigned Mask = 8;
2280 for (unsigned I = 0; I < 16; ++I)
2281 if ((PredicateBits & (1 << I)) != 0)
2282 Mask |= (I % 8);
2283
2284 unsigned PredSize = Mask & -Mask;
2285 auto *PredType = ScalableVectorType::get(
2286 Type::getInt1Ty(Ctx), AArch64::SVEBitsPerBlock / (PredSize * 8));
2287
2288 // Ensure all relevant bits are set
2289 for (unsigned I = 0; I < 16; I += PredSize)
2290 if ((PredicateBits & (1 << I)) == 0)
2291 return std::nullopt;
2292
2293 auto *ConvertToSVBool =
2294 IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_to_svbool,
2295 PredType, ConstantInt::getTrue(PredType));
2296 auto *ConvertFromSVBool =
2297 IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool,
2298 II.getType(), ConvertToSVBool);
2299
2300 ConvertFromSVBool->takeName(&II);
2301 return IC.replaceInstUsesWith(II, ConvertFromSVBool);
2302}
2303
2304static std::optional<Instruction *> instCombineSVELast(InstCombiner &IC,
2305 IntrinsicInst &II) {
2306 Value *Pg = II.getArgOperand(0);
2307 Value *Vec = II.getArgOperand(1);
2308 auto IntrinsicID = II.getIntrinsicID();
2309 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2310
2311 // lastX(splat(X)) --> X
2312 if (auto *SplatVal = getSplatValue(Vec))
2313 return IC.replaceInstUsesWith(II, SplatVal);
2314
2315 // If x and/or y is a splat value then:
2316 // lastX (binop (x, y)) --> binop(lastX(x), lastX(y))
2317 Value *LHS, *RHS;
2318 if (match(Vec, m_OneUse(m_BinOp(m_Value(LHS), m_Value(RHS))))) {
2319 if (isSplatValue(LHS) || isSplatValue(RHS)) {
2320 auto *OldBinOp = cast<BinaryOperator>(Vec);
2321 auto OpC = OldBinOp->getOpcode();
2322 auto *NewLHS =
2323 IC.Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, LHS});
2324 auto *NewRHS =
2325 IC.Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, RHS});
2327 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(), II.getIterator());
2328 return IC.replaceInstUsesWith(II, NewBinOp);
2329 }
2330 }
2331
2332 auto *C = dyn_cast<Constant>(Pg);
2333 if (IsAfter && C && C->isNullValue()) {
2334 // The intrinsic is extracting lane 0 so use an extract instead.
2335 auto *IdxTy = Type::getInt64Ty(II.getContext());
2336 auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, 0));
2337 Extract->insertBefore(II.getIterator());
2338 Extract->takeName(&II);
2339 return IC.replaceInstUsesWith(II, Extract);
2340 }
2341
2342 auto *IntrPG = dyn_cast<IntrinsicInst>(Pg);
2343 if (!IntrPG)
2344 return std::nullopt;
2345
2346 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2347 return std::nullopt;
2348
2349 const auto PTruePattern =
2350 cast<ConstantInt>(IntrPG->getOperand(0))->getZExtValue();
2351
2352 // Can the intrinsic's predicate be converted to a known constant index?
2353 unsigned MinNumElts = getNumElementsFromSVEPredPattern(PTruePattern);
2354 if (!MinNumElts)
2355 return std::nullopt;
2356
2357 unsigned Idx = MinNumElts - 1;
2358 // Increment the index if extracting the element after the last active
2359 // predicate element.
2360 if (IsAfter)
2361 ++Idx;
2362
2363 // Ignore extracts whose index is larger than the known minimum vector
2364 // length. NOTE: This is an artificial constraint where we prefer to
2365 // maintain what the user asked for until an alternative is proven faster.
2366 auto *PgVTy = cast<ScalableVectorType>(Pg->getType());
2367 if (Idx >= PgVTy->getMinNumElements())
2368 return std::nullopt;
2369
2370 // The intrinsic is extracting a fixed lane so use an extract instead.
2371 auto *IdxTy = Type::getInt64Ty(II.getContext());
2372 auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, Idx));
2373 Extract->insertBefore(II.getIterator());
2374 Extract->takeName(&II);
2375 return IC.replaceInstUsesWith(II, Extract);
2376}
2377
2378static std::optional<Instruction *> instCombineSVECondLast(InstCombiner &IC,
2379 IntrinsicInst &II) {
2380 // The SIMD&FP variant of CLAST[AB] is significantly faster than the scalar
2381 // integer variant across a variety of micro-architectures. Replace scalar
2382 // integer CLAST[AB] intrinsic with optimal SIMD&FP variant. A simple
2383 // bitcast-to-fp + clast[ab] + bitcast-to-int will cost a cycle or two more
2384 // depending on the micro-architecture, but has been observed as generally
2385 // being faster, particularly when the CLAST[AB] op is a loop-carried
2386 // dependency.
2387 Value *Pg = II.getArgOperand(0);
2388 Value *Fallback = II.getArgOperand(1);
2389 Value *Vec = II.getArgOperand(2);
2390 Type *Ty = II.getType();
2391
2392 if (!Ty->isIntegerTy())
2393 return std::nullopt;
2394
2395 Type *FPTy;
2396 switch (cast<IntegerType>(Ty)->getBitWidth()) {
2397 default:
2398 return std::nullopt;
2399 case 16:
2400 FPTy = IC.Builder.getHalfTy();
2401 break;
2402 case 32:
2403 FPTy = IC.Builder.getFloatTy();
2404 break;
2405 case 64:
2406 FPTy = IC.Builder.getDoubleTy();
2407 break;
2408 }
2409
2410 Value *FPFallBack = IC.Builder.CreateBitCast(Fallback, FPTy);
2411 auto *FPVTy = VectorType::get(
2412 FPTy, cast<VectorType>(Vec->getType())->getElementCount());
2413 Value *FPVec = IC.Builder.CreateBitCast(Vec, FPVTy);
2414 auto *FPII = IC.Builder.CreateIntrinsic(
2415 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2416 Value *FPIItoInt = IC.Builder.CreateBitCast(FPII, II.getType());
2417 return IC.replaceInstUsesWith(II, FPIItoInt);
2418}
2419
2420static std::optional<Instruction *> instCombineRDFFR(InstCombiner &IC,
2421 IntrinsicInst &II) {
2422 // Replace rdffr with predicated rdffr.z intrinsic, so that optimizePTestInstr
2423 // can work with RDFFR_PP for ptest elimination.
2424 auto *RDFFR = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_rdffr_z,
2425 ConstantInt::getTrue(II.getType()));
2426 RDFFR->takeName(&II);
2427 return IC.replaceInstUsesWith(II, RDFFR);
2428}
2429
2430static std::optional<Instruction *>
2432 const auto Pattern = cast<ConstantInt>(II.getArgOperand(0))->getZExtValue();
2433
2434 if (Pattern == AArch64SVEPredPattern::all) {
2436 II.getType(), ElementCount::getScalable(NumElts));
2437 Cnt->takeName(&II);
2438 return IC.replaceInstUsesWith(II, Cnt);
2439 }
2440
2441 unsigned MinNumElts = getNumElementsFromSVEPredPattern(Pattern);
2442
2443 return MinNumElts && NumElts >= MinNumElts
2444 ? std::optional<Instruction *>(IC.replaceInstUsesWith(
2445 II, ConstantInt::get(II.getType(), MinNumElts)))
2446 : std::nullopt;
2447}
2448
2449static std::optional<Instruction *>
2451 const AArch64Subtarget *ST) {
2452 if (!ST->isStreaming())
2453 return std::nullopt;
2454
2455 // In streaming-mode, aarch64_sme_cntds is equivalent to aarch64_sve_cntd
2456 // with SVEPredPattern::all
2457 Value *Cnt =
2459 Cnt->takeName(&II);
2460 return IC.replaceInstUsesWith(II, Cnt);
2461}
2462
2463static std::optional<Instruction *> instCombineSVEPTest(InstCombiner &IC,
2464 IntrinsicInst &II) {
2465 Value *PgVal = II.getArgOperand(0);
2466 Value *OpVal = II.getArgOperand(1);
2467
2468 // PTEST_<FIRST|LAST>(X, X) is equivalent to PTEST_ANY(X, X).
2469 // Later optimizations prefer this form.
2470 if (PgVal == OpVal &&
2471 (II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2472 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2473 Value *Ops[] = {PgVal, OpVal};
2474 Type *Tys[] = {PgVal->getType()};
2475
2476 auto *PTest =
2477 IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptest_any, Tys, Ops);
2478 PTest->takeName(&II);
2479
2480 return IC.replaceInstUsesWith(II, PTest);
2481 }
2482
2485
2486 if (!Pg || !Op)
2487 return std::nullopt;
2488
2489 Intrinsic::ID OpIID = Op->getIntrinsicID();
2490
2491 if (Pg->getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2492 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2493 Pg->getArgOperand(0)->getType() == Op->getArgOperand(0)->getType()) {
2494 Value *Ops[] = {Pg->getArgOperand(0), Op->getArgOperand(0)};
2495 Type *Tys[] = {Pg->getArgOperand(0)->getType()};
2496
2497 auto *PTest = IC.Builder.CreateIntrinsic(II.getIntrinsicID(), Tys, Ops);
2498
2499 PTest->takeName(&II);
2500 return IC.replaceInstUsesWith(II, PTest);
2501 }
2502
2503 // Transform PTEST_ANY(X=OP(PG,...), X) -> PTEST_ANY(PG, X)).
2504 // Later optimizations may rewrite sequence to use the flag-setting variant
2505 // of instruction X to remove PTEST.
2506 if ((Pg == Op) && (II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2507 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2508 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2509 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2510 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2511 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2512 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2513 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2514 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2515 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2516 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2517 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2518 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2519 Value *Ops[] = {Pg->getArgOperand(0), Pg};
2520 Type *Tys[] = {Pg->getType()};
2521
2522 auto *PTest = IC.Builder.CreateIntrinsic(II.getIntrinsicID(), Tys, Ops);
2523 PTest->takeName(&II);
2524
2525 return IC.replaceInstUsesWith(II, PTest);
2526 }
2527
2528 return std::nullopt;
2529}
2530
2531template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2532static std::optional<Instruction *>
2534 bool MergeIntoAddendOp) {
2535 Value *P = II.getOperand(0);
2536 Value *MulOp0, *MulOp1, *AddendOp, *Mul;
2537 if (MergeIntoAddendOp) {
2538 AddendOp = II.getOperand(1);
2539 Mul = II.getOperand(2);
2540 } else {
2541 AddendOp = II.getOperand(2);
2542 Mul = II.getOperand(1);
2543 }
2544
2546 m_Value(MulOp1))))
2547 return std::nullopt;
2548
2549 if (!Mul->hasOneUse())
2550 return std::nullopt;
2551
2552 Instruction *FMFSource = nullptr;
2553 if (II.getType()->isFPOrFPVectorTy()) {
2554 llvm::FastMathFlags FAddFlags = II.getFastMathFlags();
2555 // Stop the combine when the flags on the inputs differ in case dropping
2556 // flags would lead to us missing out on more beneficial optimizations.
2557 if (FAddFlags != cast<CallInst>(Mul)->getFastMathFlags())
2558 return std::nullopt;
2559 if (!FAddFlags.allowContract())
2560 return std::nullopt;
2561 FMFSource = &II;
2562 }
2563
2564 Value *Res;
2565 if (MergeIntoAddendOp)
2566 Res = IC.Builder.CreateIntrinsic(FuseOpc, {II.getType()},
2567 {P, AddendOp, MulOp0, MulOp1}, FMFSource);
2568 else
2569 Res = IC.Builder.CreateIntrinsic(FuseOpc, {II.getType()},
2570 {P, MulOp0, MulOp1, AddendOp}, FMFSource);
2571
2572 return IC.replaceInstUsesWith(II, Res);
2573}
2574
2575static std::optional<Instruction *>
2577 Value *Pred = II.getOperand(0);
2578 Value *PtrOp = II.getOperand(1);
2579 Type *VecTy = II.getType();
2580
2581 if (isAllActivePredicate(Pred)) {
2582 LoadInst *Load = IC.Builder.CreateLoad(VecTy, PtrOp);
2583 Load->copyMetadata(II);
2584 return IC.replaceInstUsesWith(II, Load);
2585 }
2586
2587 CallInst *MaskedLoad =
2588 IC.Builder.CreateMaskedLoad(VecTy, PtrOp, PtrOp->getPointerAlignment(DL),
2589 Pred, ConstantAggregateZero::get(VecTy));
2590 MaskedLoad->copyMetadata(II);
2591 return IC.replaceInstUsesWith(II, MaskedLoad);
2592}
2593
2594static std::optional<Instruction *>
2596 Value *VecOp = II.getOperand(0);
2597 Value *Pred = II.getOperand(1);
2598 Value *PtrOp = II.getOperand(2);
2599
2600 if (isAllActivePredicate(Pred)) {
2601 StoreInst *Store = IC.Builder.CreateStore(VecOp, PtrOp);
2602 Store->copyMetadata(II);
2603 return IC.eraseInstFromFunction(II);
2604 }
2605
2606 CallInst *MaskedStore = IC.Builder.CreateMaskedStore(
2607 VecOp, PtrOp, PtrOp->getPointerAlignment(DL), Pred);
2608 MaskedStore->copyMetadata(II);
2609 return IC.eraseInstFromFunction(II);
2610}
2611
2613 switch (Intrinsic) {
2614 case Intrinsic::aarch64_sve_fmul_u:
2615 return Instruction::BinaryOps::FMul;
2616 case Intrinsic::aarch64_sve_fadd_u:
2617 return Instruction::BinaryOps::FAdd;
2618 case Intrinsic::aarch64_sve_fsub_u:
2619 return Instruction::BinaryOps::FSub;
2620 default:
2621 return Instruction::BinaryOpsEnd;
2622 }
2623}
2624
2625static std::optional<Instruction *>
2627 // Bail due to missing support for ISD::STRICT_ scalable vector operations.
2628 if (II.isStrictFP())
2629 return std::nullopt;
2630
2631 auto *OpPredicate = II.getOperand(0);
2632 auto BinOpCode = intrinsicIDToBinOpCode(II.getIntrinsicID());
2633 if (BinOpCode == Instruction::BinaryOpsEnd ||
2634 !isAllActivePredicate(OpPredicate))
2635 return std::nullopt;
2636 auto BinOp = IC.Builder.CreateBinOpFMF(
2637 BinOpCode, II.getOperand(1), II.getOperand(2), II.getFastMathFlags());
2638 return IC.replaceInstUsesWith(II, BinOp);
2639}
2640
2641static std::optional<Instruction *>
2643 assert(II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
2644 "Expected MLA_U intrinsic");
2645 Value *Acc = II.getArgOperand(1);
2646 Value *MulOp0 = II.getArgOperand(2);
2647 Value *MulOp1 = II.getArgOperand(3);
2648
2649 // For mla_u, inactive lanes are undefined, so it is valid to drop the
2650 // predicate when replacing mla_u(acc, x, 1) with add(acc, x) or
2651 // mla_u(acc, x, -1) with sub(acc, x).
2652 if (match(MulOp0, m_One()))
2653 return IC.replaceInstUsesWith(II, IC.Builder.CreateAdd(Acc, MulOp1));
2654 if (match(MulOp1, m_One()))
2655 return IC.replaceInstUsesWith(II, IC.Builder.CreateAdd(Acc, MulOp0));
2656 if (match(MulOp0, m_AllOnes()))
2657 return IC.replaceInstUsesWith(II, IC.Builder.CreateSub(Acc, MulOp1));
2658 if (match(MulOp1, m_AllOnes()))
2659 return IC.replaceInstUsesWith(II, IC.Builder.CreateSub(Acc, MulOp0));
2660
2661 if (isa<Constant>(MulOp0) && !isa<Constant>(MulOp1)) {
2662 II.setArgOperand(2, MulOp1);
2663 II.setArgOperand(3, MulOp0);
2664 return &II;
2665 }
2666
2667 return std::nullopt;
2668}
2669
2670static std::optional<Instruction *>
2672 assert((II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
2673 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
2674 "Expected SADALP or UADALP intrinsic");
2675
2676 // Simplify add(adalp(pg, zeroinitializer, in), wide_acc)
2677 // -> adalp(pg, wide_acc, in)
2678 auto *User = dyn_cast_or_null<Instruction>(II.getUniqueUndroppableUser());
2679 if (!User || !match(II.getArgOperand(1), m_Zero()))
2680 return std::nullopt;
2681
2682 Value *Acc;
2683 if (!match(User, m_c_Add(m_Specific(&II), m_Value(Acc))))
2684 return std::nullopt;
2685
2687 Value *PairwiseAddLong = IC.Builder.CreateIntrinsic(
2688 II.getIntrinsicID(), {II.getType()},
2689 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
2690
2691 IC.replaceInstUsesWith(*User, PairwiseAddLong);
2693 return &II; // II is now trivially dead and will get erased.
2694}
2695
2696static std::optional<Instruction *> instCombineSVEVectorAdd(InstCombiner &IC,
2697 IntrinsicInst &II) {
2698 if (auto MLA = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,
2699 Intrinsic::aarch64_sve_mla>(
2700 IC, II, true))
2701 return MLA;
2702 if (auto MAD = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,
2703 Intrinsic::aarch64_sve_mad>(
2704 IC, II, false))
2705 return MAD;
2706 return std::nullopt;
2707}
2708
2709static std::optional<Instruction *>
2711 if (auto FMLA =
2712 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2713 Intrinsic::aarch64_sve_fmla>(IC, II,
2714 true))
2715 return FMLA;
2716 if (auto FMAD =
2717 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2718 Intrinsic::aarch64_sve_fmad>(IC, II,
2719 false))
2720 return FMAD;
2721 if (auto FMLA =
2722 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
2723 Intrinsic::aarch64_sve_fmla>(IC, II,
2724 true))
2725 return FMLA;
2726 return std::nullopt;
2727}
2728
2729static std::optional<Instruction *>
2731 if (auto FMLA =
2732 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2733 Intrinsic::aarch64_sve_fmla>(IC, II,
2734 true))
2735 return FMLA;
2736 if (auto FMAD =
2737 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2738 Intrinsic::aarch64_sve_fmad>(IC, II,
2739 false))
2740 return FMAD;
2741 if (auto FMLA_U =
2742 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
2743 Intrinsic::aarch64_sve_fmla_u>(
2744 IC, II, true))
2745 return FMLA_U;
2746 return instCombineSVEVectorBinOp(IC, II);
2747}
2748
2749static std::optional<Instruction *>
2751 if (auto FMLS =
2752 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2753 Intrinsic::aarch64_sve_fmls>(IC, II,
2754 true))
2755 return FMLS;
2756 if (auto FMSB =
2757 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2758 Intrinsic::aarch64_sve_fnmsb>(
2759 IC, II, false))
2760 return FMSB;
2761 if (auto FMLS =
2762 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
2763 Intrinsic::aarch64_sve_fmls>(IC, II,
2764 true))
2765 return FMLS;
2766 return std::nullopt;
2767}
2768
2769static std::optional<Instruction *>
2771 if (auto FMLS =
2772 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2773 Intrinsic::aarch64_sve_fmls>(IC, II,
2774 true))
2775 return FMLS;
2776 if (auto FMSB =
2777 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2778 Intrinsic::aarch64_sve_fnmsb>(
2779 IC, II, false))
2780 return FMSB;
2781 if (auto FMLS_U =
2782 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
2783 Intrinsic::aarch64_sve_fmls_u>(
2784 IC, II, true))
2785 return FMLS_U;
2786 return instCombineSVEVectorBinOp(IC, II);
2787}
2788
2789static std::optional<Instruction *> instCombineSVEVectorSub(InstCombiner &IC,
2790 IntrinsicInst &II) {
2791 if (auto MLS = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,
2792 Intrinsic::aarch64_sve_mls>(
2793 IC, II, true))
2794 return MLS;
2795 return std::nullopt;
2796}
2797
2798static std::optional<Instruction *> instCombineSVEUnpack(InstCombiner &IC,
2799 IntrinsicInst &II) {
2800 Value *UnpackArg = II.getArgOperand(0);
2801 auto *RetTy = cast<ScalableVectorType>(II.getType());
2802 bool IsSigned = II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
2803 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
2804
2805 // Hi = uunpkhi(splat(X)) --> Hi = splat(extend(X))
2806 // Lo = uunpklo(splat(X)) --> Lo = splat(extend(X))
2807 if (auto *ScalarArg = getSplatValue(UnpackArg)) {
2808 ScalarArg =
2809 IC.Builder.CreateIntCast(ScalarArg, RetTy->getScalarType(), IsSigned);
2810 Value *NewVal =
2811 IC.Builder.CreateVectorSplat(RetTy->getElementCount(), ScalarArg);
2812 NewVal->takeName(&II);
2813 return IC.replaceInstUsesWith(II, NewVal);
2814 }
2815
2816 return std::nullopt;
2817}
2818static std::optional<Instruction *> instCombineSVETBL(InstCombiner &IC,
2819 IntrinsicInst &II) {
2820 auto *OpVal = II.getOperand(0);
2821 auto *OpIndices = II.getOperand(1);
2822 VectorType *VTy = cast<VectorType>(II.getType());
2823
2824 // Check whether OpIndices is a constant splat value < minimal element count
2825 // of result.
2826 auto *SplatValue = dyn_cast_or_null<ConstantInt>(getSplatValue(OpIndices));
2827 if (!SplatValue ||
2828 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
2829 return std::nullopt;
2830
2831 // Convert sve_tbl(OpVal sve_dup_x(SplatValue)) to
2832 // splat_vector(extractelement(OpVal, SplatValue)) for further optimization.
2833 auto *Extract = IC.Builder.CreateExtractElement(OpVal, SplatValue);
2834 auto *VectorSplat =
2835 IC.Builder.CreateVectorSplat(VTy->getElementCount(), Extract);
2836
2837 VectorSplat->takeName(&II);
2838 return IC.replaceInstUsesWith(II, VectorSplat);
2839}
2840
2841static std::optional<Instruction *> instCombineSVEUzp1(InstCombiner &IC,
2842 IntrinsicInst &II) {
2843 Value *A, *B;
2844 Type *RetTy = II.getType();
2845 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
2846 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
2847
2848 // uzp1(to_svbool(A), to_svbool(B)) --> <A, B>
2849 // uzp1(from_svbool(to_svbool(A)), from_svbool(to_svbool(B))) --> <A, B>
2850 if ((match(II.getArgOperand(0),
2852 match(II.getArgOperand(1),
2854 (match(II.getArgOperand(0), m_Intrinsic<ToSVB>(m_Value(A))) &&
2855 match(II.getArgOperand(1), m_Intrinsic<ToSVB>(m_Value(B))))) {
2856 auto *TyA = cast<ScalableVectorType>(A->getType());
2857 if (TyA == B->getType() &&
2859 auto *SubVec = IC.Builder.CreateInsertVector(
2860 RetTy, PoisonValue::get(RetTy), A, uint64_t(0));
2861 auto *ConcatVec = IC.Builder.CreateInsertVector(RetTy, SubVec, B,
2862 TyA->getMinNumElements());
2863 ConcatVec->takeName(&II);
2864 return IC.replaceInstUsesWith(II, ConcatVec);
2865 }
2866 }
2867
2868 return std::nullopt;
2869}
2870
2871static std::optional<Instruction *> instCombineSVEZip(InstCombiner &IC,
2872 IntrinsicInst &II) {
2873 // zip1(uzp1(A, B), uzp2(A, B)) --> A
2874 // zip2(uzp1(A, B), uzp2(A, B)) --> B
2875 Value *A, *B;
2876 if (match(II.getArgOperand(0),
2879 m_Specific(A), m_Specific(B))))
2880 return IC.replaceInstUsesWith(
2881 II, (II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ? A : B));
2882
2883 return std::nullopt;
2884}
2885
2886static std::optional<Instruction *>
2888 Value *Mask = II.getOperand(0);
2889 Value *BasePtr = II.getOperand(1);
2890 Value *Index = II.getOperand(2);
2891 Type *Ty = II.getType();
2892 Value *PassThru = ConstantAggregateZero::get(Ty);
2893
2894 // Contiguous gather => masked load.
2895 // (sve.ld1.gather.index Mask BasePtr (sve.index IndexBase 1))
2896 // => (masked.load (gep BasePtr IndexBase) Align Mask zeroinitializer)
2897 Value *IndexBase;
2899 m_One()))) {
2900 Align Alignment =
2901 BasePtr->getPointerAlignment(II.getDataLayout());
2902
2903 Value *Ptr = IC.Builder.CreateGEP(cast<VectorType>(Ty)->getElementType(),
2904 BasePtr, IndexBase);
2905 CallInst *MaskedLoad =
2906 IC.Builder.CreateMaskedLoad(Ty, Ptr, Alignment, Mask, PassThru);
2907 MaskedLoad->takeName(&II);
2908 return IC.replaceInstUsesWith(II, MaskedLoad);
2909 }
2910
2911 return std::nullopt;
2912}
2913
2914static std::optional<Instruction *>
2916 Value *Val = II.getOperand(0);
2917 Value *Mask = II.getOperand(1);
2918 Value *BasePtr = II.getOperand(2);
2919 Value *Index = II.getOperand(3);
2920 Type *Ty = Val->getType();
2921
2922 // Contiguous scatter => masked store.
2923 // (sve.st1.scatter.index Value Mask BasePtr (sve.index IndexBase 1))
2924 // => (masked.store Value (gep BasePtr IndexBase) Align Mask)
2925 Value *IndexBase;
2927 m_One()))) {
2928 Align Alignment =
2929 BasePtr->getPointerAlignment(II.getDataLayout());
2930
2931 Value *Ptr = IC.Builder.CreateGEP(cast<VectorType>(Ty)->getElementType(),
2932 BasePtr, IndexBase);
2933 (void)IC.Builder.CreateMaskedStore(Val, Ptr, Alignment, Mask);
2934
2935 return IC.eraseInstFromFunction(II);
2936 }
2937
2938 return std::nullopt;
2939}
2940
2941static std::optional<Instruction *> instCombineSVESDIV(InstCombiner &IC,
2942 IntrinsicInst &II) {
2943 Type *Int32Ty = IC.Builder.getInt32Ty();
2944 Value *Pred = II.getOperand(0);
2945 Value *Vec = II.getOperand(1);
2946 Value *DivVec = II.getOperand(2);
2947
2948 Value *SplatValue = getSplatValue(DivVec);
2949 ConstantInt *SplatConstantInt = dyn_cast_or_null<ConstantInt>(SplatValue);
2950 if (!SplatConstantInt)
2951 return std::nullopt;
2952
2953 APInt Divisor = SplatConstantInt->getValue();
2954 const int64_t DivisorValue = Divisor.getSExtValue();
2955 if (DivisorValue == -1)
2956 return std::nullopt;
2957 if (DivisorValue == 1)
2958 IC.replaceInstUsesWith(II, Vec);
2959
2960 if (Divisor.isPowerOf2()) {
2961 Constant *DivisorLog2 = ConstantInt::get(Int32Ty, Divisor.logBase2());
2962 auto ASRD = IC.Builder.CreateIntrinsic(
2963 Intrinsic::aarch64_sve_asrd, {II.getType()}, {Pred, Vec, DivisorLog2});
2964 return IC.replaceInstUsesWith(II, ASRD);
2965 }
2966 if (Divisor.isNegatedPowerOf2()) {
2967 Divisor.negate();
2968 Constant *DivisorLog2 = ConstantInt::get(Int32Ty, Divisor.logBase2());
2969 auto ASRD = IC.Builder.CreateIntrinsic(
2970 Intrinsic::aarch64_sve_asrd, {II.getType()}, {Pred, Vec, DivisorLog2});
2971 auto NEG = IC.Builder.CreateIntrinsic(
2972 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
2973 return IC.replaceInstUsesWith(II, NEG);
2974 }
2975
2976 return std::nullopt;
2977}
2978
2979bool SimplifyValuePattern(SmallVector<Value *> &Vec, bool AllowPoison) {
2980 size_t VecSize = Vec.size();
2981 if (VecSize == 1)
2982 return true;
2983 if (!isPowerOf2_64(VecSize))
2984 return false;
2985 size_t HalfVecSize = VecSize / 2;
2986
2987 for (auto LHS = Vec.begin(), RHS = Vec.begin() + HalfVecSize;
2988 RHS != Vec.end(); LHS++, RHS++) {
2989 if (*LHS != nullptr && *RHS != nullptr) {
2990 if (*LHS == *RHS)
2991 continue;
2992 else
2993 return false;
2994 }
2995 if (!AllowPoison)
2996 return false;
2997 if (*LHS == nullptr && *RHS != nullptr)
2998 *LHS = *RHS;
2999 }
3000
3001 Vec.resize(HalfVecSize);
3002 SimplifyValuePattern(Vec, AllowPoison);
3003 return true;
3004}
3005
3006// Try to simplify dupqlane patterns like dupqlane(f32 A, f32 B, f32 A, f32 B)
3007// to dupqlane(f64(C)) where C is A concatenated with B
3008static std::optional<Instruction *> instCombineSVEDupqLane(InstCombiner &IC,
3009 IntrinsicInst &II) {
3010 Value *CurrentInsertElt = nullptr, *Default = nullptr;
3011 if (!match(II.getOperand(0),
3013 m_Value(Default), m_Value(CurrentInsertElt), m_Value())) ||
3014 !isa<FixedVectorType>(CurrentInsertElt->getType()))
3015 return std::nullopt;
3016 auto IIScalableTy = cast<ScalableVectorType>(II.getType());
3017
3018 // Insert the scalars into a container ordered by InsertElement index
3019 SmallVector<Value *> Elts(IIScalableTy->getMinNumElements(), nullptr);
3020 while (auto InsertElt = dyn_cast<InsertElementInst>(CurrentInsertElt)) {
3021 auto Idx = cast<ConstantInt>(InsertElt->getOperand(2));
3022 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3023 CurrentInsertElt = InsertElt->getOperand(0);
3024 }
3025
3026 bool AllowPoison =
3027 isa<PoisonValue>(CurrentInsertElt) && isa<PoisonValue>(Default);
3028 if (!SimplifyValuePattern(Elts, AllowPoison))
3029 return std::nullopt;
3030
3031 // Rebuild the simplified chain of InsertElements. e.g. (a, b, a, b) as (a, b)
3032 Value *InsertEltChain = PoisonValue::get(CurrentInsertElt->getType());
3033 for (size_t I = 0; I < Elts.size(); I++) {
3034 if (Elts[I] == nullptr)
3035 continue;
3036 InsertEltChain = IC.Builder.CreateInsertElement(InsertEltChain, Elts[I],
3037 IC.Builder.getInt64(I));
3038 }
3039 if (InsertEltChain == nullptr)
3040 return std::nullopt;
3041
3042 // Splat the simplified sequence, e.g. (f16 a, f16 b, f16 c, f16 d) as one i64
3043 // value or (f16 a, f16 b) as one i32 value. This requires an InsertSubvector
3044 // be bitcast to a type wide enough to fit the sequence, be splatted, and then
3045 // be narrowed back to the original type.
3046 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.size();
3047 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3048 IIScalableTy->getMinNumElements() /
3049 PatternWidth;
3050
3051 IntegerType *WideTy = IC.Builder.getIntNTy(PatternWidth);
3052 auto *WideScalableTy = ScalableVectorType::get(WideTy, PatternElementCount);
3053 auto *WideShuffleMaskTy =
3054 ScalableVectorType::get(IC.Builder.getInt32Ty(), PatternElementCount);
3055
3056 auto InsertSubvector = IC.Builder.CreateInsertVector(
3057 II.getType(), PoisonValue::get(II.getType()), InsertEltChain,
3058 uint64_t(0));
3059 auto WideBitcast =
3060 IC.Builder.CreateBitOrPointerCast(InsertSubvector, WideScalableTy);
3061 auto WideShuffleMask = ConstantAggregateZero::get(WideShuffleMaskTy);
3062 auto WideShuffle = IC.Builder.CreateShuffleVector(
3063 WideBitcast, PoisonValue::get(WideScalableTy), WideShuffleMask);
3064 auto NarrowBitcast =
3065 IC.Builder.CreateBitOrPointerCast(WideShuffle, II.getType());
3066
3067 return IC.replaceInstUsesWith(II, NarrowBitcast);
3068}
3069
3070static std::optional<Instruction *> instCombineMaxMinNM(InstCombiner &IC,
3071 IntrinsicInst &II) {
3072 Value *A = II.getArgOperand(0);
3073 Value *B = II.getArgOperand(1);
3074 if (A == B)
3075 return IC.replaceInstUsesWith(II, A);
3076
3077 return std::nullopt;
3078}
3079
3080static std::optional<Instruction *> instCombineSVESrshl(InstCombiner &IC,
3081 IntrinsicInst &II) {
3082 Value *Pred = II.getOperand(0);
3083 Value *Vec = II.getOperand(1);
3084 Value *Shift = II.getOperand(2);
3085
3086 // Convert SRSHL into the simpler LSL intrinsic when fed by an ABS intrinsic.
3087 Value *AbsPred, *MergedValue;
3089 m_Value(MergedValue), m_Value(AbsPred), m_Value())) &&
3091 m_Value(MergedValue), m_Value(AbsPred), m_Value())))
3092
3093 return std::nullopt;
3094
3095 // Transform is valid if any of the following are true:
3096 // * The ABS merge value is an undef or non-negative
3097 // * The ABS predicate is all active
3098 // * The ABS predicate and the SRSHL predicates are the same
3099 if (!isa<UndefValue>(MergedValue) && !match(MergedValue, m_NonNegative()) &&
3100 AbsPred != Pred && !isAllActivePredicate(AbsPred))
3101 return std::nullopt;
3102
3103 // Only valid when the shift amount is non-negative, otherwise the rounding
3104 // behaviour of SRSHL cannot be ignored.
3105 if (!match(Shift, m_NonNegative()))
3106 return std::nullopt;
3107
3108 auto LSL = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_lsl,
3109 {II.getType()}, {Pred, Vec, Shift});
3110
3111 return IC.replaceInstUsesWith(II, LSL);
3112}
3113
3114static std::optional<Instruction *> instCombineSVEInsr(InstCombiner &IC,
3115 IntrinsicInst &II) {
3116 Value *Vec = II.getOperand(0);
3117
3118 if (getSplatValue(Vec) == II.getOperand(1))
3119 return IC.replaceInstUsesWith(II, Vec);
3120
3121 return std::nullopt;
3122}
3123
3124static std::optional<Instruction *> instCombineDMB(InstCombiner &IC,
3125 IntrinsicInst &II) {
3126 // If this barrier is post-dominated by identical one we can remove it
3127 auto *NI = II.getNextNode();
3128 unsigned LookaheadThreshold = DMBLookaheadThreshold;
3129 auto CanSkipOver = [](Instruction *I) {
3130 return !I->mayReadOrWriteMemory() && !I->mayHaveSideEffects();
3131 };
3132 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3133 auto *NIBB = NI->getParent();
3134 NI = NI->getNextNode();
3135 if (!NI) {
3136 if (auto *SuccBB = NIBB->getUniqueSuccessor())
3137 NI = &*SuccBB->getFirstNonPHIOrDbgOrLifetime();
3138 else
3139 break;
3140 }
3141 }
3142 auto *NextII = dyn_cast_or_null<IntrinsicInst>(NI);
3143 if (NextII && II.isIdenticalTo(NextII))
3144 return IC.eraseInstFromFunction(II);
3145
3146 return std::nullopt;
3147}
3148
3149static std::optional<Instruction *> instCombineWhilelo(InstCombiner &IC,
3150 IntrinsicInst &II) {
3151 return IC.replaceInstUsesWith(
3152 II,
3153 IC.Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask,
3154 {II.getType(), II.getOperand(0)->getType()},
3155 {II.getOperand(0), II.getOperand(1)}));
3156}
3157
3158static std::optional<Instruction *> instCombinePTrue(InstCombiner &IC,
3159 IntrinsicInst &II) {
3160 unsigned PredPattern = cast<ConstantInt>(II.getOperand(0))->getZExtValue();
3161 // SVE vector length is a power-of-two, thus pow2 is synonymous with all.
3162 if (PredPattern == AArch64SVEPredPattern::all ||
3163 PredPattern == AArch64SVEPredPattern::pow2)
3164 return IC.replaceInstUsesWith(II, ConstantInt::getTrue(II.getType()));
3165 return std::nullopt;
3166}
3167
3168static std::optional<Instruction *> instCombineSVEUxt(InstCombiner &IC,
3170 unsigned NumBits) {
3171 Value *Passthru = II.getOperand(0);
3172 Value *Pg = II.getOperand(1);
3173 Value *Op = II.getOperand(2);
3174
3175 // Convert UXT[BHW] to AND.
3176 if (isa<UndefValue>(Passthru) || isAllActivePredicate(Pg)) {
3177 auto *Ty = cast<VectorType>(II.getType());
3178 auto MaskValue = APInt::getLowBitsSet(Ty->getScalarSizeInBits(), NumBits);
3179 auto *Mask = ConstantInt::get(Ty, MaskValue);
3180 auto *And = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_and_u, {Ty},
3181 {Pg, Op, Mask});
3182 return IC.replaceInstUsesWith(II, And);
3183 }
3184
3185 return std::nullopt;
3186}
3187
3188static std::optional<Instruction *>
3190 SMEAttrs FnSMEAttrs(*II.getFunction());
3191 bool IsStreaming = FnSMEAttrs.hasStreamingInterfaceOrBody();
3192 if (IsStreaming || !FnSMEAttrs.hasStreamingCompatibleInterface())
3193 return IC.replaceInstUsesWith(
3194 II, ConstantInt::getBool(II.getType(), IsStreaming));
3195 return std::nullopt;
3196}
3197
3198std::optional<Instruction *>
3200 IntrinsicInst &II) const {
3202 if (std::optional<Instruction *> I = simplifySVEIntrinsic(IC, II, IInfo))
3203 return I;
3204
3205 Intrinsic::ID IID = II.getIntrinsicID();
3206 switch (IID) {
3207 default:
3208 break;
3209 case Intrinsic::aarch64_dmb:
3210 return instCombineDMB(IC, II);
3211 case Intrinsic::aarch64_neon_fmaxnm:
3212 case Intrinsic::aarch64_neon_fminnm:
3213 return instCombineMaxMinNM(IC, II);
3214 case Intrinsic::aarch64_sve_convert_from_svbool:
3215 return instCombineConvertFromSVBool(IC, II);
3216 case Intrinsic::aarch64_sve_dup:
3217 return instCombineSVEDup(IC, II);
3218 case Intrinsic::aarch64_sve_dup_x:
3219 return instCombineSVEDupX(IC, II);
3220 case Intrinsic::aarch64_sve_cmpeq:
3221 case Intrinsic::aarch64_sve_cmpeq_wide:
3222 return instCombineXorSVECmpCC(IC, II);
3223 case Intrinsic::aarch64_sve_cmpne:
3224 case Intrinsic::aarch64_sve_cmpne_wide:
3225 return instCombineSVECmpNE(IC, II);
3226 case Intrinsic::aarch64_sve_rdffr:
3227 return instCombineRDFFR(IC, II);
3228 case Intrinsic::aarch64_sve_lasta:
3229 case Intrinsic::aarch64_sve_lastb:
3230 return instCombineSVELast(IC, II);
3231 case Intrinsic::aarch64_sve_clasta_n:
3232 case Intrinsic::aarch64_sve_clastb_n:
3233 return instCombineSVECondLast(IC, II);
3234 case Intrinsic::aarch64_sve_cntd:
3235 return instCombineSVECntElts(IC, II, 2);
3236 case Intrinsic::aarch64_sve_cntw:
3237 return instCombineSVECntElts(IC, II, 4);
3238 case Intrinsic::aarch64_sve_cnth:
3239 return instCombineSVECntElts(IC, II, 8);
3240 case Intrinsic::aarch64_sve_cntb:
3241 return instCombineSVECntElts(IC, II, 16);
3242 case Intrinsic::aarch64_sme_cntsd:
3243 return instCombineSMECntsd(IC, II, ST);
3244 case Intrinsic::aarch64_sve_ptest_any:
3245 case Intrinsic::aarch64_sve_ptest_first:
3246 case Intrinsic::aarch64_sve_ptest_last:
3247 return instCombineSVEPTest(IC, II);
3248 case Intrinsic::aarch64_sve_fadd:
3249 return instCombineSVEVectorFAdd(IC, II);
3250 case Intrinsic::aarch64_sve_fadd_u:
3251 return instCombineSVEVectorFAddU(IC, II);
3252 case Intrinsic::aarch64_sve_fmul_u:
3253 return instCombineSVEVectorBinOp(IC, II);
3254 case Intrinsic::aarch64_sve_fsub:
3255 return instCombineSVEVectorFSub(IC, II);
3256 case Intrinsic::aarch64_sve_fsub_u:
3257 return instCombineSVEVectorFSubU(IC, II);
3258 case Intrinsic::aarch64_sve_add:
3259 return instCombineSVEVectorAdd(IC, II);
3260 case Intrinsic::aarch64_sve_add_u:
3261 return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,
3262 Intrinsic::aarch64_sve_mla_u>(
3263 IC, II, true);
3264 case Intrinsic::aarch64_sve_mla_u:
3265 return instCombineSVEVectorMlaU(IC, II);
3266 case Intrinsic::aarch64_sve_sadalp:
3267 case Intrinsic::aarch64_sve_uadalp:
3269 case Intrinsic::aarch64_sve_sub:
3270 return instCombineSVEVectorSub(IC, II);
3271 case Intrinsic::aarch64_sve_sub_u:
3272 return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,
3273 Intrinsic::aarch64_sve_mls_u>(
3274 IC, II, true);
3275 case Intrinsic::aarch64_sve_tbl:
3276 return instCombineSVETBL(IC, II);
3277 case Intrinsic::aarch64_sve_uunpkhi:
3278 case Intrinsic::aarch64_sve_uunpklo:
3279 case Intrinsic::aarch64_sve_sunpkhi:
3280 case Intrinsic::aarch64_sve_sunpklo:
3281 return instCombineSVEUnpack(IC, II);
3282 case Intrinsic::aarch64_sve_uzp1:
3283 return instCombineSVEUzp1(IC, II);
3284 case Intrinsic::aarch64_sve_zip1:
3285 case Intrinsic::aarch64_sve_zip2:
3286 return instCombineSVEZip(IC, II);
3287 case Intrinsic::aarch64_sve_ld1_gather_index:
3288 return instCombineLD1GatherIndex(IC, II);
3289 case Intrinsic::aarch64_sve_st1_scatter_index:
3290 return instCombineST1ScatterIndex(IC, II);
3291 case Intrinsic::aarch64_sve_ld1:
3292 return instCombineSVELD1(IC, II, DL);
3293 case Intrinsic::aarch64_sve_st1:
3294 return instCombineSVEST1(IC, II, DL);
3295 case Intrinsic::aarch64_sve_sdiv:
3296 return instCombineSVESDIV(IC, II);
3297 case Intrinsic::aarch64_sve_sel:
3298 return instCombineSVESel(IC, II);
3299 case Intrinsic::aarch64_sve_srshl:
3300 return instCombineSVESrshl(IC, II);
3301 case Intrinsic::aarch64_sve_dupq_lane:
3302 return instCombineSVEDupqLane(IC, II);
3303 case Intrinsic::aarch64_sve_insr:
3304 return instCombineSVEInsr(IC, II);
3305 case Intrinsic::aarch64_sve_whilelo:
3306 return instCombineWhilelo(IC, II);
3307 case Intrinsic::aarch64_sve_ptrue:
3308 return instCombinePTrue(IC, II);
3309 case Intrinsic::aarch64_sve_uxtb:
3310 return instCombineSVEUxt(IC, II, 8);
3311 case Intrinsic::aarch64_sve_uxth:
3312 return instCombineSVEUxt(IC, II, 16);
3313 case Intrinsic::aarch64_sve_uxtw:
3314 return instCombineSVEUxt(IC, II, 32);
3315 case Intrinsic::aarch64_sme_in_streaming_mode:
3316 return instCombineInStreamingMode(IC, II);
3317 }
3318
3319 return std::nullopt;
3320}
3321
3323 InstCombiner &IC, IntrinsicInst &II, APInt OrigDemandedElts,
3324 APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3,
3325 std::function<void(Instruction *, unsigned, APInt, APInt &)>
3326 SimplifyAndSetOp) const {
3327 switch (II.getIntrinsicID()) {
3328 default:
3329 break;
3330 case Intrinsic::aarch64_neon_fcvtxn:
3331 case Intrinsic::aarch64_neon_rshrn:
3332 case Intrinsic::aarch64_neon_sqrshrn:
3333 case Intrinsic::aarch64_neon_sqrshrun:
3334 case Intrinsic::aarch64_neon_sqshrn:
3335 case Intrinsic::aarch64_neon_sqshrun:
3336 case Intrinsic::aarch64_neon_sqxtn:
3337 case Intrinsic::aarch64_neon_sqxtun:
3338 case Intrinsic::aarch64_neon_uqrshrn:
3339 case Intrinsic::aarch64_neon_uqshrn:
3340 case Intrinsic::aarch64_neon_uqxtn:
3341 SimplifyAndSetOp(&II, 0, OrigDemandedElts, UndefElts);
3342 break;
3343 }
3344
3345 return std::nullopt;
3346}
3347
3349 return ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3351}
3352
3355 switch (K) {
3357 return TypeSize::getFixed(64);
3359 if (ST->useSVEForFixedLengthVectors() &&
3360 (ST->isSVEAvailable() || EnableFixedwidthAutovecInStreamingMode))
3361 return TypeSize::getFixed(
3362 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3363 else if (ST->isNeonAvailable())
3364 return TypeSize::getFixed(128);
3365 else
3366 return TypeSize::getFixed(0);
3368 if (ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3370 return TypeSize::getScalable(128);
3371 else
3372 return TypeSize::getScalable(0);
3373 }
3374 llvm_unreachable("Unsupported register kind");
3375}
3376
3377bool AArch64TTIImpl::isSingleExtWideningInstruction(
3378 unsigned Opcode, Type *DstTy, ArrayRef<const Value *> Args,
3379 Type *SrcOverrideTy) const {
3380 // A helper that returns a vector type from the given type. The number of
3381 // elements in type Ty determines the vector width.
3382 auto toVectorTy = [&](Type *ArgTy) {
3383 return VectorType::get(ArgTy->getScalarType(),
3384 cast<VectorType>(DstTy)->getElementCount());
3385 };
3386
3387 // Exit early if DstTy is not a vector type whose elements are one of [i16,
3388 // i32, i64]. SVE doesn't generally have the same set of instructions to
3389 // perform an extend with the add/sub/mul. There are SMULLB style
3390 // instructions, but they operate on top/bottom, requiring some sort of lane
3391 // interleaving to be used with zext/sext.
3392 unsigned DstEltSize = DstTy->getScalarSizeInBits();
3393 if (!useNeonVector(DstTy) || Args.size() != 2 ||
3394 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3395 return false;
3396
3397 Type *SrcTy = SrcOverrideTy;
3398 switch (Opcode) {
3399 case Instruction::Add: // UADDW(2), SADDW(2).
3400 case Instruction::Sub: { // USUBW(2), SSUBW(2).
3401 // The second operand needs to be an extend
3402 if (isa<SExtInst>(Args[1]) || isa<ZExtInst>(Args[1])) {
3403 if (!SrcTy)
3404 SrcTy =
3405 toVectorTy(cast<Instruction>(Args[1])->getOperand(0)->getType());
3406 break;
3407 }
3408
3409 if (Opcode == Instruction::Sub)
3410 return false;
3411
3412 // UADDW(2), SADDW(2) can be commutted.
3413 if (isa<SExtInst>(Args[0]) || isa<ZExtInst>(Args[0])) {
3414 if (!SrcTy)
3415 SrcTy =
3416 toVectorTy(cast<Instruction>(Args[0])->getOperand(0)->getType());
3417 break;
3418 }
3419 return false;
3420 }
3421 default:
3422 return false;
3423 }
3424
3425 // Legalize the destination type and ensure it can be used in a widening
3426 // operation.
3427 auto DstTyL = getTypeLegalizationCost(DstTy);
3428 if (!DstTyL.second.isVector() || DstEltSize != DstTy->getScalarSizeInBits())
3429 return false;
3430
3431 // Legalize the source type and ensure it can be used in a widening
3432 // operation.
3433 assert(SrcTy && "Expected some SrcTy");
3434 auto SrcTyL = getTypeLegalizationCost(SrcTy);
3435 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3436 if (!SrcTyL.second.isVector() || SrcElTySize != SrcTy->getScalarSizeInBits())
3437 return false;
3438
3439 // Get the total number of vector elements in the legalized types.
3440 InstructionCost NumDstEls =
3441 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3442 InstructionCost NumSrcEls =
3443 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3444
3445 // Return true if the legalized types have the same number of vector elements
3446 // and the destination element type size is twice that of the source type.
3447 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3448}
3449
3450Type *AArch64TTIImpl::isBinExtWideningInstruction(unsigned Opcode, Type *DstTy,
3452 Type *SrcOverrideTy) const {
3453 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3454 Opcode != Instruction::Mul)
3455 return nullptr;
3456
3457 // Exit early if DstTy is not a vector type whose elements are one of [i16,
3458 // i32, i64]. SVE doesn't generally have the same set of instructions to
3459 // perform an extend with the add/sub/mul. There are SMULLB style
3460 // instructions, but they operate on top/bottom, requiring some sort of lane
3461 // interleaving to be used with zext/sext.
3462 unsigned DstEltSize = DstTy->getScalarSizeInBits();
3463 if (!useNeonVector(DstTy) || Args.size() != 2 ||
3464 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3465 return nullptr;
3466
3467 auto getScalarSizeWithOverride = [&](const Value *V) {
3468 if (SrcOverrideTy)
3469 return SrcOverrideTy->getScalarSizeInBits();
3470 return cast<Instruction>(V)
3471 ->getOperand(0)
3472 ->getType()
3473 ->getScalarSizeInBits();
3474 };
3475
3476 unsigned MaxEltSize = 0;
3477 if ((isa<SExtInst>(Args[0]) && isa<SExtInst>(Args[1])) ||
3478 (isa<ZExtInst>(Args[0]) && isa<ZExtInst>(Args[1]))) {
3479 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3480 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3481 MaxEltSize = std::max(EltSize0, EltSize1);
3482 } else if (isa<SExtInst, ZExtInst>(Args[0]) &&
3483 isa<SExtInst, ZExtInst>(Args[1])) {
3484 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3485 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3486 // mul(sext, zext) will become smull(sext, zext) if the extends are large
3487 // enough.
3488 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3489 return nullptr;
3490 MaxEltSize = DstEltSize / 2;
3491 } else if (Opcode == Instruction::Mul &&
3492 (isa<ZExtInst>(Args[0]) || isa<ZExtInst>(Args[1]))) {
3493 // If one of the operands is a Zext and the other has enough zero bits
3494 // to be treated as unsigned, we can still generate a umull, meaning the
3495 // zext is free.
3496 KnownBits Known =
3497 computeKnownBits(isa<ZExtInst>(Args[0]) ? Args[1] : Args[0], DL);
3498 if (Args[0]->getType()->getScalarSizeInBits() -
3499 Known.Zero.countLeadingOnes() >
3500 DstTy->getScalarSizeInBits() / 2)
3501 return nullptr;
3502
3503 MaxEltSize =
3504 getScalarSizeWithOverride(isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3505 } else
3506 return nullptr;
3507
3508 if (MaxEltSize * 2 > DstEltSize)
3509 return nullptr;
3510
3511 Type *ExtTy = DstTy->getWithNewBitWidth(MaxEltSize * 2);
3512 if (ExtTy->getPrimitiveSizeInBits() <= 64)
3513 return nullptr;
3514 return ExtTy;
3515}
3516
3517// s/urhadd instructions implement the following pattern, making the
3518// extends free:
3519// %x = add ((zext i8 -> i16), 1)
3520// %y = (zext i8 -> i16)
3521// trunc i16 (lshr (add %x, %y), 1) -> i8
3522//
3524 Type *Src) const {
3525 // The source should be a legal vector type.
3526 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(DL, Src)) ||
3527 (Src->isScalableTy() && !ST->hasSVE2()))
3528 return false;
3529
3530 if (ExtUser->getOpcode() != Instruction::Add || !ExtUser->hasOneUse())
3531 return false;
3532
3533 // Look for trunc/shl/add before trying to match the pattern.
3534 const Instruction *Add = ExtUser;
3535 auto *AddUser =
3536 dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());
3537 if (AddUser && AddUser->getOpcode() == Instruction::Add)
3538 Add = AddUser;
3539
3540 auto *Shr = dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());
3541 if (!Shr || Shr->getOpcode() != Instruction::LShr)
3542 return false;
3543
3544 auto *Trunc = dyn_cast_or_null<Instruction>(Shr->getUniqueUndroppableUser());
3545 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
3546 Src->getScalarSizeInBits() !=
3547 cast<CastInst>(Trunc)->getDestTy()->getScalarSizeInBits())
3548 return false;
3549
3550 // Try to match the whole pattern. Ext could be either the first or second
3551 // m_ZExtOrSExt matched.
3552 Instruction *Ex1, *Ex2;
3553 if (!(match(Add, m_c_Add(m_Instruction(Ex1),
3554 m_c_Add(m_Instruction(Ex2), m_One())))))
3555 return false;
3556
3557 // Ensure both extends are of the same type
3558 if (match(Ex1, m_ZExtOrSExt(m_Value())) &&
3559 Ex1->getOpcode() == Ex2->getOpcode())
3560 return true;
3561
3562 return false;
3563}
3564
3566 Type *Src,
3569 const Instruction *I) const {
3570 int ISD = TLI->InstructionOpcodeToISD(Opcode);
3571 assert(ISD && "Invalid opcode");
3572 // If the cast is observable, and it is used by a widening instruction (e.g.,
3573 // uaddl, saddw, etc.), it may be free.
3574 if (I && I->hasOneUser()) {
3575 auto *SingleUser = cast<Instruction>(*I->user_begin());
3576 SmallVector<const Value *, 4> Operands(SingleUser->operand_values());
3577 if (Type *ExtTy = isBinExtWideningInstruction(
3578 SingleUser->getOpcode(), Dst, Operands,
3579 Src != I->getOperand(0)->getType() ? Src : nullptr)) {
3580 // The cost from Src->Src*2 needs to be added if required, the cost from
3581 // Src*2->ExtTy is free.
3582 if (ExtTy->getScalarSizeInBits() > Src->getScalarSizeInBits() * 2) {
3583 Type *DoubleSrcTy =
3584 Src->getWithNewBitWidth(Src->getScalarSizeInBits() * 2);
3585 return getCastInstrCost(Opcode, DoubleSrcTy, Src,
3587 }
3588
3589 return 0;
3590 }
3591
3592 if (isSingleExtWideningInstruction(
3593 SingleUser->getOpcode(), Dst, Operands,
3594 Src != I->getOperand(0)->getType() ? Src : nullptr)) {
3595 // For adds only count the second operand as free if both operands are
3596 // extends but not the same operation. (i.e both operands are not free in
3597 // add(sext, zext)).
3598 if (SingleUser->getOpcode() == Instruction::Add) {
3599 if (I == SingleUser->getOperand(1) ||
3600 (isa<CastInst>(SingleUser->getOperand(1)) &&
3601 cast<CastInst>(SingleUser->getOperand(1))->getOpcode() == Opcode))
3602 return 0;
3603 } else {
3604 // Others are free so long as isSingleExtWideningInstruction
3605 // returned true.
3606 return 0;
3607 }
3608 }
3609
3610 // The cast will be free for the s/urhadd instructions
3611 if ((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
3612 isExtPartOfAvgExpr(SingleUser, Dst, Src))
3613 return 0;
3614 }
3615
3616 EVT SrcTy = TLI->getValueType(DL, Src);
3617 EVT DstTy = TLI->getValueType(DL, Dst);
3618
3619 if (!SrcTy.isSimple() || !DstTy.isSimple())
3620 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
3621
3622 // For the moment we do not have lowering for SVE1-only fptrunc f64->bf16 as
3623 // we use fcvtx under SVE2. Give them invalid costs.
3624 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
3625 ISD == ISD::FP_ROUND && SrcTy.isScalableVector() &&
3626 DstTy.getScalarType() == MVT::bf16 && SrcTy.getScalarType() == MVT::f64)
3628
3629 static const TypeConversionCostTblEntry BF16Tbl[] = {
3630 {ISD::FP_ROUND, MVT::bf16, MVT::f32, 1}, // bfcvt
3631 {ISD::FP_ROUND, MVT::bf16, MVT::f64, 1}, // bfcvt
3632 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 1}, // bfcvtn
3633 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 2}, // bfcvtn+bfcvtn2
3634 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 2}, // bfcvtn+fcvtn
3635 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 3}, // fcvtn+fcvtl2+bfcvtn
3636 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+bfcvtn
3637 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 1}, // bfcvt
3638 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 1}, // bfcvt
3639 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 3}, // bfcvt+bfcvt+uzp1
3640 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 2}, // fcvtx+bfcvt
3641 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 5}, // 2*fcvtx+2*bfcvt+uzp1
3642 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 11}, // 4*fcvt+4*bfcvt+3*uzp
3643 };
3644
3645 if (ST->hasBF16())
3646 if (const auto *Entry = ConvertCostTableLookup(
3647 BF16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
3648 return Entry->Cost;
3649
3650 // We have to estimate a cost of fixed length operation upon
3651 // SVE registers(operations) with the number of registers required
3652 // for a fixed type to be represented upon SVE registers.
3653 EVT WiderTy = SrcTy.bitsGT(DstTy) ? SrcTy : DstTy;
3654 if (SrcTy.isFixedLengthVector() && DstTy.isFixedLengthVector() &&
3655 SrcTy.getVectorNumElements() == DstTy.getVectorNumElements() &&
3656 ST->useSVEForFixedLengthVectors(WiderTy)) {
3657 std::pair<InstructionCost, MVT> LT =
3658 getTypeLegalizationCost(WiderTy.getTypeForEVT(Dst->getContext()));
3659 unsigned NumElements =
3660 AArch64::SVEBitsPerBlock / LT.second.getScalarSizeInBits();
3661 return LT.first *
3663 Opcode,
3664 ScalableVectorType::get(Dst->getScalarType(), NumElements),
3665 ScalableVectorType::get(Src->getScalarType(), NumElements), CCH,
3666 CostKind, I);
3667 }
3668
3669 // Symbolic constants for the SVE sitofp/uitofp entries in the table below
3670 // The cost of unpacking twice is artificially increased for now in order
3671 // to avoid regressions against NEON, which will use tbl instructions directly
3672 // instead of multiple layers of [s|u]unpk[lo|hi].
3673 // We use the unpacks in cases where the destination type is illegal and
3674 // requires splitting of the input, even if the input type itself is legal.
3675 const unsigned int SVE_EXT_COST = 1;
3676 const unsigned int SVE_FCVT_COST = 1;
3677 const unsigned int SVE_UNPACK_ONCE = 4;
3678 const unsigned int SVE_UNPACK_TWICE = 16;
3679
3680 static const TypeConversionCostTblEntry ConversionTbl[] = {
3681 {ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, 1}, // xtn
3682 {ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, 1}, // xtn
3683 {ISD::TRUNCATE, MVT::v2i32, MVT::v2i64, 1}, // xtn
3684 {ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, 1}, // xtn
3685 {ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, 3}, // 2 xtn + 1 uzp1
3686 {ISD::TRUNCATE, MVT::v4i16, MVT::v4i32, 1}, // xtn
3687 {ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, 2}, // 1 uzp1 + 1 xtn
3688 {ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1}, // 1 uzp1
3689 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, 1}, // 1 xtn
3690 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, 2}, // 1 uzp1 + 1 xtn
3691 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, 4}, // 3 x uzp1 + xtn
3692 {ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 1}, // 1 uzp1
3693 {ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, 3}, // 3 x uzp1
3694 {ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, 2}, // 2 x uzp1
3695 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 1}, // uzp1
3696 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 3}, // (2 + 1) x uzp1
3697 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, 7}, // (4 + 2 + 1) x uzp1
3698 {ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 2}, // 2 x uzp1
3699 {ISD::TRUNCATE, MVT::v16i16, MVT::v16i64, 6}, // (4 + 2) x uzp1
3700 {ISD::TRUNCATE, MVT::v16i32, MVT::v16i64, 4}, // 4 x uzp1
3701
3702 // Truncations on nxvmiN
3703 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i8, 2},
3704 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i16, 2},
3705 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i32, 2},
3706 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i64, 2},
3707 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i8, 2},
3708 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i16, 2},
3709 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i32, 2},
3710 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i64, 5},
3711 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i8, 2},
3712 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i16, 2},
3713 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i32, 5},
3714 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i64, 11},
3715 {ISD::TRUNCATE, MVT::nxv16i1, MVT::nxv16i8, 2},
3716 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i16, 0},
3717 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i32, 0},
3718 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i64, 0},
3719 {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i32, 0},
3720 {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i64, 0},
3721 {ISD::TRUNCATE, MVT::nxv2i32, MVT::nxv2i64, 0},
3722 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i16, 0},
3723 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i32, 0},
3724 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i64, 1},
3725 {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i32, 0},
3726 {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i64, 1},
3727 {ISD::TRUNCATE, MVT::nxv4i32, MVT::nxv4i64, 1},
3728 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i16, 0},
3729 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i32, 1},
3730 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i64, 3},
3731 {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i32, 1},
3732 {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i64, 3},
3733 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i16, 1},
3734 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i32, 3},
3735 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i64, 7},
3736
3737 // The number of shll instructions for the extension.
3738 {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i16, 3},
3739 {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i16, 3},
3740 {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 2},
3741 {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 2},
3742 {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i8, 3},
3743 {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i8, 3},
3744 {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 2},
3745 {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 2},
3746 {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, 7},
3747 {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, 7},
3748 {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, 6},
3749 {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, 6},
3750 {ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 2},
3751 {ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 2},
3752 {ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, 6},
3753 {ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, 6},
3754
3755 // FP Ext and trunc
3756 {ISD::FP_EXTEND, MVT::f64, MVT::f32, 1}, // fcvt
3757 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f32, 1}, // fcvtl
3758 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, 2}, // fcvtl+fcvtl2
3759 // FP16
3760 {ISD::FP_EXTEND, MVT::f32, MVT::f16, 1}, // fcvt
3761 {ISD::FP_EXTEND, MVT::f64, MVT::f16, 1}, // fcvt
3762 {ISD::FP_EXTEND, MVT::v4f32, MVT::v4f16, 1}, // fcvtl
3763 {ISD::FP_EXTEND, MVT::v8f32, MVT::v8f16, 2}, // fcvtl+fcvtl2
3764 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f16, 2}, // fcvtl+fcvtl
3765 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f16, 3}, // fcvtl+fcvtl2+fcvtl
3766 {ISD::FP_EXTEND, MVT::v8f64, MVT::v8f16, 6}, // 2 * fcvtl+fcvtl2+fcvtl
3767 // BF16 (uses shift)
3768 {ISD::FP_EXTEND, MVT::f32, MVT::bf16, 1}, // shl
3769 {ISD::FP_EXTEND, MVT::f64, MVT::bf16, 2}, // shl+fcvt
3770 {ISD::FP_EXTEND, MVT::v4f32, MVT::v4bf16, 1}, // shll
3771 {ISD::FP_EXTEND, MVT::v8f32, MVT::v8bf16, 2}, // shll+shll2
3772 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2bf16, 2}, // shll+fcvtl
3773 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4bf16, 3}, // shll+fcvtl+fcvtl2
3774 {ISD::FP_EXTEND, MVT::v8f64, MVT::v8bf16, 6}, // 2 * shll+fcvtl+fcvtl2
3775 // FP Ext and trunc
3776 {ISD::FP_ROUND, MVT::f32, MVT::f64, 1}, // fcvt
3777 {ISD::FP_ROUND, MVT::v2f32, MVT::v2f64, 1}, // fcvtn
3778 {ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, 2}, // fcvtn+fcvtn2
3779 // FP16
3780 {ISD::FP_ROUND, MVT::f16, MVT::f32, 1}, // fcvt
3781 {ISD::FP_ROUND, MVT::f16, MVT::f64, 1}, // fcvt
3782 {ISD::FP_ROUND, MVT::v4f16, MVT::v4f32, 1}, // fcvtn
3783 {ISD::FP_ROUND, MVT::v8f16, MVT::v8f32, 2}, // fcvtn+fcvtn2
3784 {ISD::FP_ROUND, MVT::v2f16, MVT::v2f64, 2}, // fcvtn+fcvtn
3785 {ISD::FP_ROUND, MVT::v4f16, MVT::v4f64, 3}, // fcvtn+fcvtn2+fcvtn
3786 {ISD::FP_ROUND, MVT::v8f16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+fcvtn
3787 // BF16 (more complex, with +bf16 is handled above)
3788 {ISD::FP_ROUND, MVT::bf16, MVT::f32, 8}, // Expansion is ~8 insns
3789 {ISD::FP_ROUND, MVT::bf16, MVT::f64, 9}, // fcvtn + above
3790 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f32, 8},
3791 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 8},
3792 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 15},
3793 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 9},
3794 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 10},
3795 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 19},
3796
3797 // LowerVectorINT_TO_FP:
3798 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},
3799 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},
3800 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},
3801 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},
3802 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},
3803 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},
3804
3805 // SVE: to nxv2f16
3806 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,
3807 SVE_EXT_COST + SVE_FCVT_COST},
3808 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},
3809 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},
3810 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},
3811 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,
3812 SVE_EXT_COST + SVE_FCVT_COST},
3813 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},
3814 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},
3815 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},
3816
3817 // SVE: to nxv4f16
3818 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,
3819 SVE_EXT_COST + SVE_FCVT_COST},
3820 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},
3821 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},
3822 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,
3823 SVE_EXT_COST + SVE_FCVT_COST},
3824 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},
3825 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},
3826
3827 // SVE: to nxv8f16
3828 {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,
3829 SVE_EXT_COST + SVE_FCVT_COST},
3830 {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},
3831 {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,
3832 SVE_EXT_COST + SVE_FCVT_COST},
3833 {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},
3834
3835 // SVE: to nxv16f16
3836 {ISD::SINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,
3837 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3838 {ISD::UINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,
3839 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3840
3841 // Complex: to v2f32
3842 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},
3843 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},
3844 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},
3845 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},
3846
3847 // SVE: to nxv2f32
3848 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,
3849 SVE_EXT_COST + SVE_FCVT_COST},
3850 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},
3851 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},
3852 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},
3853 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,
3854 SVE_EXT_COST + SVE_FCVT_COST},
3855 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},
3856 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},
3857 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},
3858
3859 // Complex: to v4f32
3860 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i8, 4},
3861 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},
3862 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i8, 3},
3863 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},
3864
3865 // SVE: to nxv4f32
3866 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,
3867 SVE_EXT_COST + SVE_FCVT_COST},
3868 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},
3869 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},
3870 {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,
3871 SVE_EXT_COST + SVE_FCVT_COST},
3872 {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},
3873 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},
3874
3875 // Complex: to v8f32
3876 {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},
3877 {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},
3878 {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},
3879 {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},
3880
3881 // SVE: to nxv8f32
3882 {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,
3883 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3884 {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,
3885 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3886 {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,
3887 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3888 {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,
3889 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3890
3891 // SVE: to nxv16f32
3892 {ISD::SINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,
3893 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
3894 {ISD::UINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,
3895 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
3896
3897 // Complex: to v16f32
3898 {ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},
3899 {ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},
3900
3901 // Complex: to v2f64
3902 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},
3903 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},
3904 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},
3905 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},
3906 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},
3907 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},
3908
3909 // SVE: to nxv2f64
3910 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,
3911 SVE_EXT_COST + SVE_FCVT_COST},
3912 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},
3913 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},
3914 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},
3915 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,
3916 SVE_EXT_COST + SVE_FCVT_COST},
3917 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},
3918 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},
3919 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},
3920
3921 // Complex: to v4f64
3922 {ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},
3923 {ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},
3924
3925 // SVE: to nxv4f64
3926 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,
3927 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3928 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,
3929 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3930 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,
3931 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3932 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,
3933 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3934 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,
3935 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3936 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,
3937 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
3938
3939 // SVE: to nxv8f64
3940 {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,
3941 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
3942 {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,
3943 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
3944 {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,
3945 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
3946 {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,
3947 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
3948
3949 // LowerVectorFP_TO_INT
3950 {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f32, 1},
3951 {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1},
3952 {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1},
3953 {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f32, 1},
3954 {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1},
3955 {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1},
3956
3957 // Complex, from v2f32: legal type is v2i32 (no cost) or v2i64 (1 ext).
3958 {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f32, 2},
3959 {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f32, 1},
3960 {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f32, 1},
3961 {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f32, 2},
3962 {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f32, 1},
3963 {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f32, 1},
3964
3965 // Complex, from v4f32: legal type is v4i16, 1 narrowing => ~2
3966 {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f32, 2},
3967 {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f32, 2},
3968 {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f32, 2},
3969 {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f32, 2},
3970
3971 // Complex, from v2f64: legal type is v2i32, 1 narrowing => ~2.
3972 {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f64, 2},
3973 {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f64, 2},
3974 {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f64, 2},
3975 {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f64, 2},
3976 {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f64, 2},
3977 {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f64, 2},
3978
3979 // Complex, from nxv2f32.
3980 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f32, 1},
3981 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f32, 1},
3982 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f32, 1},
3983 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f32, 1},
3984 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f32, 1},
3985 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f32, 1},
3986 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f32, 1},
3987 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f32, 1},
3988
3989 // Complex, from nxv2f64.
3990 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f64, 1},
3991 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f64, 1},
3992 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f64, 1},
3993 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f64, 1},
3994 {ISD::FP_TO_SINT, MVT::nxv2i1, MVT::nxv2f64, 1},
3995 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f64, 1},
3996 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f64, 1},
3997 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f64, 1},
3998 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f64, 1},
3999 {ISD::FP_TO_UINT, MVT::nxv2i1, MVT::nxv2f64, 1},
4000
4001 // Complex, from nxv4f32.
4002 {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f32, 4},
4003 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f32, 1},
4004 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f32, 1},
4005 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f32, 1},
4006 {ISD::FP_TO_SINT, MVT::nxv4i1, MVT::nxv4f32, 1},
4007 {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f32, 4},
4008 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f32, 1},
4009 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f32, 1},
4010 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f32, 1},
4011 {ISD::FP_TO_UINT, MVT::nxv4i1, MVT::nxv4f32, 1},
4012
4013 // Complex, from nxv8f64. Illegal -> illegal conversions not required.
4014 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f64, 7},
4015 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f64, 7},
4016 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f64, 7},
4017 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f64, 7},
4018
4019 // Complex, from nxv4f64. Illegal -> illegal conversions not required.
4020 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f64, 3},
4021 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f64, 3},
4022 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f64, 3},
4023 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f64, 3},
4024 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f64, 3},
4025 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f64, 3},
4026
4027 // Complex, from nxv8f32. Illegal -> illegal conversions not required.
4028 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f32, 3},
4029 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f32, 3},
4030 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f32, 3},
4031 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f32, 3},
4032
4033 // Complex, from nxv8f16.
4034 {ISD::FP_TO_SINT, MVT::nxv8i64, MVT::nxv8f16, 10},
4035 {ISD::FP_TO_SINT, MVT::nxv8i32, MVT::nxv8f16, 4},
4036 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f16, 1},
4037 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f16, 1},
4038 {ISD::FP_TO_SINT, MVT::nxv8i1, MVT::nxv8f16, 1},
4039 {ISD::FP_TO_UINT, MVT::nxv8i64, MVT::nxv8f16, 10},
4040 {ISD::FP_TO_UINT, MVT::nxv8i32, MVT::nxv8f16, 4},
4041 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f16, 1},
4042 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f16, 1},
4043 {ISD::FP_TO_UINT, MVT::nxv8i1, MVT::nxv8f16, 1},
4044
4045 // Complex, from nxv4f16.
4046 {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f16, 4},
4047 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f16, 1},
4048 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f16, 1},
4049 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f16, 1},
4050 {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f16, 4},
4051 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f16, 1},
4052 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f16, 1},
4053 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f16, 1},
4054
4055 // Complex, from nxv2f16.
4056 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f16, 1},
4057 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f16, 1},
4058 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f16, 1},
4059 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f16, 1},
4060 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f16, 1},
4061 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f16, 1},
4062 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f16, 1},
4063 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f16, 1},
4064
4065 // Truncate from nxvmf32 to nxvmf16.
4066 {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f32, 1},
4067 {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f32, 1},
4068 {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f32, 3},
4069
4070 // Truncate from nxvmf32 to nxvmbf16.
4071 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 8},
4072 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 8},
4073 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 17},
4074
4075 // Truncate from nxvmf64 to nxvmf16.
4076 {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f64, 1},
4077 {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f64, 3},
4078 {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f64, 7},
4079
4080 // Truncate from nxvmf64 to nxvmbf16.
4081 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 9},
4082 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 19},
4083 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 39},
4084
4085 // Truncate from nxvmf64 to nxvmf32.
4086 {ISD::FP_ROUND, MVT::nxv2f32, MVT::nxv2f64, 1},
4087 {ISD::FP_ROUND, MVT::nxv4f32, MVT::nxv4f64, 3},
4088 {ISD::FP_ROUND, MVT::nxv8f32, MVT::nxv8f64, 6},
4089
4090 // Extend from nxvmf16 to nxvmf32.
4091 {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2f16, 1},
4092 {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4f16, 1},
4093 {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8f16, 2},
4094
4095 // Extend from nxvmbf16 to nxvmf32.
4096 {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2bf16, 1}, // lsl
4097 {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4bf16, 1}, // lsl
4098 {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8bf16, 4}, // unpck+unpck+lsl+lsl
4099
4100 // Extend from nxvmf16 to nxvmf64.
4101 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f16, 1},
4102 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f16, 2},
4103 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f16, 4},
4104
4105 // Extend from nxvmbf16 to nxvmf64.
4106 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2bf16, 2}, // lsl+fcvt
4107 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4bf16, 6}, // 2*unpck+2*lsl+2*fcvt
4108 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8bf16, 14}, // 6*unpck+4*lsl+4*fcvt
4109
4110 // Extend from nxvmf32 to nxvmf64.
4111 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f32, 1},
4112 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f32, 2},
4113 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f32, 6},
4114
4115 // Bitcasts from float to integer
4116 {ISD::BITCAST, MVT::nxv2f16, MVT::nxv2i16, 0},
4117 {ISD::BITCAST, MVT::nxv4f16, MVT::nxv4i16, 0},
4118 {ISD::BITCAST, MVT::nxv2f32, MVT::nxv2i32, 0},
4119
4120 // Bitcasts from integer to float
4121 {ISD::BITCAST, MVT::nxv2i16, MVT::nxv2f16, 0},
4122 {ISD::BITCAST, MVT::nxv4i16, MVT::nxv4f16, 0},
4123 {ISD::BITCAST, MVT::nxv2i32, MVT::nxv2f32, 0},
4124
4125 // Add cost for extending to illegal -too wide- scalable vectors.
4126 // zero/sign extend are implemented by multiple unpack operations,
4127 // where each operation has a cost of 1.
4128 {ISD::ZERO_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},
4129 {ISD::ZERO_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},
4130 {ISD::ZERO_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},
4131 {ISD::ZERO_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},
4132 {ISD::ZERO_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},
4133 {ISD::ZERO_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},
4134
4135 {ISD::SIGN_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},
4136 {ISD::SIGN_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},
4137 {ISD::SIGN_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},
4138 {ISD::SIGN_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},
4139 {ISD::SIGN_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},
4140 {ISD::SIGN_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},
4141 };
4142
4143 if (const auto *Entry = ConvertCostTableLookup(
4144 ConversionTbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4145 return Entry->Cost;
4146
4147 static const TypeConversionCostTblEntry FP16Tbl[] = {
4148 {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f16, 1}, // fcvtzs
4149 {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f16, 1},
4150 {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f16, 1}, // fcvtzs
4151 {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f16, 1},
4152 {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f16, 2}, // fcvtl+fcvtzs
4153 {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f16, 2},
4154 {ISD::FP_TO_SINT, MVT::v8i8, MVT::v8f16, 2}, // fcvtzs+xtn
4155 {ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f16, 2},
4156 {ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f16, 1}, // fcvtzs
4157 {ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f16, 1},
4158 {ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f16, 4}, // 2*fcvtl+2*fcvtzs
4159 {ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f16, 4},
4160 {ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f16, 3}, // 2*fcvtzs+xtn
4161 {ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f16, 3},
4162 {ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f16, 2}, // 2*fcvtzs
4163 {ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f16, 2},
4164 {ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f16, 8}, // 4*fcvtl+4*fcvtzs
4165 {ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f16, 8},
4166 {ISD::UINT_TO_FP, MVT::v8f16, MVT::v8i8, 2}, // ushll + ucvtf
4167 {ISD::SINT_TO_FP, MVT::v8f16, MVT::v8i8, 2}, // sshll + scvtf
4168 {ISD::UINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * ushl(2) + 2 * ucvtf
4169 {ISD::SINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * sshl(2) + 2 * scvtf
4170 };
4171
4172 if (ST->hasFullFP16())
4173 if (const auto *Entry = ConvertCostTableLookup(
4174 FP16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4175 return Entry->Cost;
4176
4177 // INT_TO_FP of i64->f32 will scalarize, which is required to avoid
4178 // double-rounding issues.
4179 if ((ISD == ISD::SINT_TO_FP || ISD == ISD::UINT_TO_FP) &&
4180 DstTy.getScalarType() == MVT::f32 && SrcTy.getScalarSizeInBits() > 32 &&
4182 return cast<FixedVectorType>(Dst)->getNumElements() *
4183 getCastInstrCost(Opcode, Dst->getScalarType(),
4184 Src->getScalarType(), CCH, CostKind) +
4186 true, CostKind) +
4188 false, CostKind);
4189
4190 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
4192 ST->isSVEorStreamingSVEAvailable() &&
4193 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4195 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4197 // The standard behaviour in the backend for these cases is to split the
4198 // extend up into two parts:
4199 // 1. Perform an extending load or masked load up to the legal type.
4200 // 2. Extend the loaded data to the final type.
4201 std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(Src);
4202 Type *LegalTy = EVT(SrcLT.second).getTypeForEVT(Src->getContext());
4204 Opcode, LegalTy, Src, CCH, CostKind, I);
4206 Opcode, Dst, LegalTy, TTI::CastContextHint::None, CostKind, I);
4207 return Part1 + Part2;
4208 }
4209
4210 // The BasicTTIImpl version only deals with CCH==TTI::CastContextHint::Normal,
4211 // but we also want to include the TTI::CastContextHint::Masked case too.
4212 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
4214 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4216
4217 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
4218}
4219
4222 VectorType *VecTy, unsigned Index,
4224
4225 // Make sure we were given a valid extend opcode.
4226 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4227 "Invalid opcode");
4228
4229 // We are extending an element we extract from a vector, so the source type
4230 // of the extend is the element type of the vector.
4231 auto *Src = VecTy->getElementType();
4232
4233 // Sign- and zero-extends are for integer types only.
4234 assert(isa<IntegerType>(Dst) && isa<IntegerType>(Src) && "Invalid type");
4235
4236 // Get the cost for the extract. We compute the cost (if any) for the extend
4237 // below.
4238 InstructionCost Cost = getVectorInstrCost(Instruction::ExtractElement, VecTy,
4239 CostKind, Index, nullptr, nullptr);
4240
4241 // Legalize the types.
4242 auto VecLT = getTypeLegalizationCost(VecTy);
4243 auto DstVT = TLI->getValueType(DL, Dst);
4244 auto SrcVT = TLI->getValueType(DL, Src);
4245
4246 // If the resulting type is still a vector and the destination type is legal,
4247 // we may get the extension for free. If not, get the default cost for the
4248 // extend.
4249 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4250 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4251 CostKind);
4252
4253 // The destination type should be larger than the element type. If not, get
4254 // the default cost for the extend.
4255 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4256 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4257 CostKind);
4258
4259 switch (Opcode) {
4260 default:
4261 llvm_unreachable("Opcode should be either SExt or ZExt");
4262
4263 // For sign-extends, we only need a smov, which performs the extension
4264 // automatically.
4265 case Instruction::SExt:
4266 return Cost;
4267
4268 // For zero-extends, the extend is performed automatically by a umov unless
4269 // the destination type is i64 and the element type is i8 or i16.
4270 case Instruction::ZExt:
4271 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4272 return Cost;
4273 }
4274
4275 // If we are unable to perform the extend for free, get the default cost.
4276 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4277 CostKind);
4278}
4279
4282 const Instruction *I) const {
4284 return Opcode == Instruction::PHI ? 0 : 1;
4285 assert(CostKind == TTI::TCK_RecipThroughput && "unexpected CostKind");
4286 // Branches are assumed to be predicted.
4287 return 0;
4288}
4289
4290InstructionCost AArch64TTIImpl::getVectorInstrCostHelper(
4291 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
4292 const Instruction *I, Value *Scalar,
4293 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4294 TTI::VectorInstrContext VIC) const {
4295 assert(Val->isVectorTy() && "This must be a vector type");
4296
4297 if (Index != -1U) {
4298 // Legalize the type.
4299 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Val);
4300
4301 // This type is legalized to a scalar type.
4302 if (!LT.second.isVector())
4303 return 0;
4304
4305 // The type may be split. For fixed-width vectors we can normalize the
4306 // index to the new type.
4307 if (LT.second.isFixedLengthVector()) {
4308 unsigned Width = LT.second.getVectorNumElements();
4309 Index = Index % Width;
4310 }
4311
4312 // The element at index zero is already inside the vector.
4313 // - For a insert-element or extract-element
4314 // instruction that extracts integers, an explicit FPR -> GPR move is
4315 // needed. So it has non-zero cost.
4316 if (Index == 0 && !Val->getScalarType()->isIntegerTy())
4317 return 0;
4318
4319 // This is recognising a LD1 single-element structure to one lane of one
4320 // register instruction. I.e., if this is an `insertelement` instruction,
4321 // and its second operand is a load, then we will generate a LD1, which
4322 // are expensive instructions on some uArchs.
4323 if (VIC == TTI::VectorInstrContext::Load) {
4324 if (ST->hasFastLD1Single())
4325 return 0;
4326 return CostKind == TTI::TCK_CodeSize
4327 ? 0
4329 }
4330
4331 // i1 inserts and extract will include an extra cset or cmp of the vector
4332 // value. Increase the cost by 1 to account.
4333 if (Val->getScalarSizeInBits() == 1)
4334 return CostKind == TTI::TCK_CodeSize
4335 ? 2
4336 : ST->getVectorInsertExtractBaseCost() + 1;
4337
4338 // FIXME:
4339 // If the extract-element and insert-element instructions could be
4340 // simplified away (e.g., could be combined into users by looking at use-def
4341 // context), they have no cost. This is not done in the first place for
4342 // compile-time considerations.
4343 }
4344
4345 // In case of Neon, if there exists extractelement from lane != 0 such that
4346 // 1. extractelement does not necessitate a move from vector_reg -> GPR.
4347 // 2. extractelement result feeds into fmul.
4348 // 3. Other operand of fmul is an extractelement from lane 0 or lane
4349 // equivalent to 0.
4350 // then the extractelement can be merged with fmul in the backend and it
4351 // incurs no cost.
4352 // e.g.
4353 // define double @foo(<2 x double> %a) {
4354 // %1 = extractelement <2 x double> %a, i32 0
4355 // %2 = extractelement <2 x double> %a, i32 1
4356 // %res = fmul double %1, %2
4357 // ret double %res
4358 // }
4359 // %2 and %res can be merged in the backend to generate fmul d0, d0, v1.d[1]
4360 auto ExtractCanFuseWithFmul = [&]() {
4361 // We bail out if the extract is from lane 0.
4362 if (Index == 0)
4363 return false;
4364
4365 // Check if the scalar element type of the vector operand of ExtractElement
4366 // instruction is one of the allowed types.
4367 auto IsAllowedScalarTy = [&](const Type *T) {
4368 return T->isFloatTy() || T->isDoubleTy() ||
4369 (T->isHalfTy() && ST->hasFullFP16());
4370 };
4371
4372 // Check if the extractelement user is scalar fmul.
4373 auto IsUserFMulScalarTy = [](const Value *EEUser) {
4374 // Check if the user is scalar fmul.
4375 const auto *BO = dyn_cast<BinaryOperator>(EEUser);
4376 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4377 !BO->getType()->isVectorTy();
4378 };
4379
4380 // Check if the extract index is from lane 0 or lane equivalent to 0 for a
4381 // certain scalar type and a certain vector register width.
4382 auto IsExtractLaneEquivalentToZero = [&](unsigned Idx, unsigned EltSz) {
4383 auto RegWidth =
4385 .getFixedValue();
4386 return Idx == 0 || (RegWidth != 0 && (Idx * EltSz) % RegWidth == 0);
4387 };
4388
4389 // Check if the type constraints on input vector type and result scalar type
4390 // of extractelement instruction are satisfied.
4391 if (!isa<FixedVectorType>(Val) || !IsAllowedScalarTy(Val->getScalarType()))
4392 return false;
4393
4394 if (Scalar) {
4395 DenseMap<User *, unsigned> UserToExtractIdx;
4396 for (auto *U : Scalar->users()) {
4397 if (!IsUserFMulScalarTy(U))
4398 return false;
4399 // Recording entry for the user is important. Index value is not
4400 // important.
4401 UserToExtractIdx[U];
4402 }
4403 if (UserToExtractIdx.empty())
4404 return false;
4405 for (auto &[S, U, L] : ScalarUserAndIdx) {
4406 for (auto *U : S->users()) {
4407 if (UserToExtractIdx.contains(U)) {
4408 auto *FMul = cast<BinaryOperator>(U);
4409 auto *Op0 = FMul->getOperand(0);
4410 auto *Op1 = FMul->getOperand(1);
4411 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
4412 UserToExtractIdx[U] = L;
4413 break;
4414 }
4415 }
4416 }
4417 }
4418 for (auto &[U, L] : UserToExtractIdx) {
4419 if (!IsExtractLaneEquivalentToZero(Index, Val->getScalarSizeInBits()) &&
4420 !IsExtractLaneEquivalentToZero(L, Val->getScalarSizeInBits()))
4421 return false;
4422 }
4423 } else {
4424 const auto *EE = cast<ExtractElementInst>(I);
4425
4426 const auto *IdxOp = dyn_cast<ConstantInt>(EE->getIndexOperand());
4427 if (!IdxOp)
4428 return false;
4429
4430 return !EE->users().empty() && all_of(EE->users(), [&](const User *U) {
4431 if (!IsUserFMulScalarTy(U))
4432 return false;
4433
4434 // Check if the other operand of extractelement is also extractelement
4435 // from lane equivalent to 0.
4436 const auto *BO = cast<BinaryOperator>(U);
4437 const auto *OtherEE = dyn_cast<ExtractElementInst>(
4438 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
4439 if (OtherEE) {
4440 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
4441 if (!IdxOp)
4442 return false;
4443 return IsExtractLaneEquivalentToZero(
4444 cast<ConstantInt>(OtherEE->getIndexOperand())
4445 ->getValue()
4446 .getZExtValue(),
4447 OtherEE->getType()->getScalarSizeInBits());
4448 }
4449 return true;
4450 });
4451 }
4452 return true;
4453 };
4454
4455 if (Opcode == Instruction::ExtractElement && (I || Scalar) &&
4456 ExtractCanFuseWithFmul())
4457 return 0;
4458
4459 // All other insert/extracts cost this much.
4460 return CostKind == TTI::TCK_CodeSize ? 1
4461 : ST->getVectorInsertExtractBaseCost();
4462}
4463
4465 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
4466 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
4467 // Treat insert at lane 0 into a poison vector as having zero cost. This
4468 // ensures vector broadcasts via an insert + shuffle (and will be lowered to a
4469 // single dup) are treated as cheap.
4470 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
4471 isa<PoisonValue>(Op0))
4472 return 0;
4473 return getVectorInstrCostHelper(Opcode, Val, CostKind, Index, nullptr,
4474 nullptr, {}, VIC);
4475}
4476
4478 unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index,
4479 Value *Scalar, ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4480 TTI::VectorInstrContext VIC) const {
4481 return getVectorInstrCostHelper(Opcode, Val, CostKind, Index, nullptr, Scalar,
4482 ScalarUserAndIdx, VIC);
4483}
4484
4487 TTI::TargetCostKind CostKind, unsigned Index,
4488 TTI::VectorInstrContext VIC) const {
4489 return getVectorInstrCostHelper(I.getOpcode(), Val, CostKind, Index, &I,
4490 nullptr, {}, VIC);
4491}
4492
4496 unsigned Index) const {
4497 if (isa<FixedVectorType>(Val))
4499 Index);
4500
4501 // This typically requires both while and lastb instructions in order
4502 // to extract the last element. If this is in a loop the while
4503 // instruction can at least be hoisted out, although it will consume a
4504 // predicate register. The cost should be more expensive than the base
4505 // extract cost, which is 2 for most CPUs.
4506 return CostKind == TTI::TCK_CodeSize
4507 ? 2
4508 : ST->getVectorInsertExtractBaseCost() + 1;
4509}
4510
4512 VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,
4513 TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef<Value *> VL,
4514 TTI::VectorInstrContext VIC) const {
4517 if (Ty->getElementType()->isFloatingPointTy())
4518 return BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
4519 CostKind);
4520 unsigned VecInstCost =
4521 CostKind == TTI::TCK_CodeSize ? 1 : ST->getVectorInsertExtractBaseCost();
4522 return DemandedElts.popcount() * (Insert + Extract) * VecInstCost;
4523}
4524
4525std::optional<InstructionCost> AArch64TTIImpl::getFP16BF16PromoteCost(
4527 TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE,
4528 std::function<InstructionCost(Type *)> InstCost) const {
4529 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
4530 return std::nullopt;
4531 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
4532 return std::nullopt;
4533 // If we have +sve-b16b16 the operation can be promoted to SVE.
4534 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
4535 return std::nullopt;
4536
4537 Type *PromotedTy = Ty->getWithNewType(Type::getFloatTy(Ty->getContext()));
4538 InstructionCost Cost = getCastInstrCost(Instruction::FPExt, PromotedTy, Ty,
4540 if (!Op1Info.isConstant() && !Op2Info.isConstant())
4541 Cost *= 2;
4542 Cost += InstCost(PromotedTy);
4543 if (IncludeTrunc)
4544 Cost += getCastInstrCost(Instruction::FPTrunc, Ty, PromotedTy,
4546 return Cost;
4547}
4548
4550 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
4552 ArrayRef<const Value *> Args, const Instruction *CxtI) const {
4553
4554 // The code-generator is currently not able to handle scalable vectors
4555 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
4556 // it. This change will be removed when code-generation for these types is
4557 // sufficiently reliable.
4558 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))
4559 if (VTy->getElementCount() == ElementCount::getScalable(1))
4561
4562 // TODO: Handle more cost kinds.
4564 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
4565 Op2Info, Args, CxtI);
4566
4567 // Legalize the type.
4568 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
4569 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4570
4571 // Increase the cost for half and bfloat types if not architecturally
4572 // supported.
4573 if (ISD == ISD::FADD || ISD == ISD::FSUB || ISD == ISD::FMUL ||
4574 ISD == ISD::FDIV || ISD == ISD::FREM) {
4575 if (auto PromotedCost = getFP16BF16PromoteCost(
4576 Ty, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/true,
4577 // There is not native support for fdiv/frem even with +sve-b16b16.
4578 /*CanUseSVE=*/ISD != ISD::FDIV && ISD != ISD::FREM,
4579 [&](Type *PromotedTy) {
4580 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
4581 Op1Info, Op2Info);
4582 }))
4583 return *PromotedCost;
4584
4585 // fp128 all go via libcalls
4586 if (Ty->getScalarType()->isFP128Ty())
4587 return (CostKind == TTI::TCK_CodeSize ? 1 : 10) * LT.first;
4588 }
4589
4590 // If the operation is a widening instruction (smull or umull) and both
4591 // operands are extends the cost can be cheaper by considering that the
4592 // operation will operate on the narrowest type size possible (double the
4593 // largest input size) and a further extend.
4594 if (Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
4595 if (ExtTy != Ty)
4596 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
4597 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
4599 return LT.first;
4600 }
4601
4602 switch (ISD) {
4603 default:
4604 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
4605 Op2Info);
4606 case ISD::ADD:
4607 case ISD::SUB:
4608 return LT.first; // Also works for i128
4609 case ISD::MUL: {
4610 // i128 multiply is umulh + 2*madd + mul and grows ~O(Bitwidth^2). For
4611 // scalable vectors the cost of LT.first will be invalid, leading to an
4612 // invalid cost overall.
4613 unsigned Mul64CostFactor = (CostKind == TTI::TCK_RecipThroughput &&
4614 ST->hasLimited64bitVectorMulBandwidth())
4615 ? 4
4616 : 1;
4617 if (Ty->getScalarSizeInBits() > 64) {
4618 unsigned NumLanes = isa<FixedVectorType>(Ty)
4619 ? cast<FixedVectorType>(Ty)->getNumElements()
4620 : 1;
4621 InstructionCost CostPerLane = LT.first / NumLanes;
4622 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
4623 }
4624
4625 if (LT.second == MVT::v2i64) {
4626 // When SVE is available, then we can lower the v2i64 operation using
4627 // the SVE mul instruction, which has a lower cost.
4628 if (ST->hasSVE())
4629 return LT.first * Mul64CostFactor;
4630
4631 // When SVE is not available, there is no MUL.2d instruction,
4632 // which means mul <2 x i64> is expensive as elements are extracted
4633 // from the vectors and the muls scalarized.
4634 // As getScalarizationOverhead is a bit too pessimistic, we
4635 // estimate the cost for a i64 vector directly here, which is:
4636 // - four 2-cost i64 extracts,
4637 // - two 2-cost i64 inserts, and
4638 // - two 1-cost muls.
4639 // So, for a v2i64 with LT.First = 1 the cost is 14, and for a v4i64 with
4640 // LT.first = 2 the cost is 28.
4641 return cast<VectorType>(Ty)->getElementCount().getKnownMinValue() *
4642 (getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind) +
4643 getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind, -1,
4644 nullptr, nullptr) *
4645 2 +
4646 getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,
4647 nullptr, nullptr));
4648 }
4649
4650 if (LT.second == MVT::nxv2i64)
4651 return LT.first * Mul64CostFactor;
4652
4653 return LT.first;
4654 }
4655 case ISD::SREM:
4656 case ISD::SDIV:
4657 /*
4658 Notes for sdiv/srem specific costs:
4659 1. This only considers the cases where the divisor is constant, uniform and
4660 (pow-of-2/non-pow-of-2). Other cases are not important since they either
4661 result in some form of (ldr + adrp), corresponding to constant vectors, or
4662 scalarization of the division operation.
4663 2. Constant divisors, either negative in whole or partially, don't result in
4664 significantly different codegen as compared to positive constant divisors.
4665 So, we don't consider negative divisors separately.
4666 3. If the codegen is significantly different with SVE, it has been indicated
4667 using comments at appropriate places.
4668
4669 sdiv specific cases:
4670 -----------------------------------------------------------------------
4671 codegen | pow-of-2 | Type
4672 -----------------------------------------------------------------------
4673 add + cmp + csel + asr | Y | i64
4674 add + cmp + csel + asr | Y | i32
4675 -----------------------------------------------------------------------
4676
4677 srem specific cases:
4678 -----------------------------------------------------------------------
4679 codegen | pow-of-2 | Type
4680 -----------------------------------------------------------------------
4681 negs + and + and + csneg | Y | i64
4682 negs + and + and + csneg | Y | i32
4683 -----------------------------------------------------------------------
4684
4685 other sdiv/srem cases:
4686 -------------------------------------------------------------------------
4687 common codegen | + srem | + sdiv | pow-of-2 | Type
4688 -------------------------------------------------------------------------
4689 smulh + asr + add + add | - | - | N | i64
4690 smull + lsr + add + add | - | - | N | i32
4691 usra | and + sub | sshr | Y | <2 x i64>
4692 2 * (scalar code) | - | - | N | <2 x i64>
4693 usra | bic + sub | sshr + neg | Y | <4 x i32>
4694 smull2 + smull + uzp2 | mls | - | N | <4 x i32>
4695 + sshr + usra | | | |
4696 -------------------------------------------------------------------------
4697 */
4698 if (Op2Info.isConstant() && Op2Info.isUniform()) {
4699 InstructionCost AddCost =
4700 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
4701 Op1Info.getNoProps(), Op2Info.getNoProps());
4702 InstructionCost AsrCost =
4703 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
4704 Op1Info.getNoProps(), Op2Info.getNoProps());
4705 InstructionCost MulCost =
4706 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
4707 Op1Info.getNoProps(), Op2Info.getNoProps());
4708 // add/cmp/csel/csneg should have similar cost while asr/negs/and should
4709 // have similar cost.
4710 auto VT = TLI->getValueType(DL, Ty);
4711 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
4712 if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {
4713 // Neg can be folded into the asr instruction.
4714 return ISD == ISD::SDIV ? (3 * AddCost + AsrCost)
4715 : (3 * AsrCost + AddCost);
4716 } else {
4717 return MulCost + AsrCost + 2 * AddCost;
4718 }
4719 } else if (VT.isVector()) {
4720 InstructionCost UsraCost = 2 * AsrCost;
4721 if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {
4722 // Division with scalable types corresponds to native 'asrd'
4723 // instruction when SVE is available.
4724 // e.g. %1 = sdiv <vscale x 4 x i32> %a, splat (i32 8)
4725
4726 // One more for the negation in SDIV
4728 (Op2Info.isNegatedPowerOf2() && ISD == ISD::SDIV) ? AsrCost : 0;
4729 if (Ty->isScalableTy() && ST->hasSVE())
4730 Cost += 2 * AsrCost;
4731 else {
4732 Cost +=
4733 UsraCost +
4734 (ISD == ISD::SDIV
4735 ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
4736 : 2 * AddCost);
4737 }
4738 return Cost;
4739 } else if (LT.second == MVT::v2i64) {
4740 return VT.getVectorNumElements() *
4741 getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind,
4742 Op1Info.getNoProps(),
4743 Op2Info.getNoProps());
4744 } else {
4745 // When SVE is available, we get:
4746 // smulh + lsr + add/sub + asr + add/sub.
4747 if (Ty->isScalableTy() && ST->hasSVE())
4748 return MulCost /*smulh cost*/ + 2 * AddCost + 2 * AsrCost;
4749 return 2 * MulCost + AddCost /*uzp2 cost*/ + AsrCost + UsraCost;
4750 }
4751 }
4752 }
4753 if (Op2Info.isConstant() && !Op2Info.isUniform() &&
4754 LT.second.isFixedLengthVector()) {
4755 // FIXME: When the constant vector is non-uniform, this may result in
4756 // loading the vector from constant pool or in some cases, may also result
4757 // in scalarization. For now, we are approximating this with the
4758 // scalarization cost.
4759 auto ExtractCost = 2 * getVectorInstrCost(Instruction::ExtractElement, Ty,
4760 CostKind, -1, nullptr, nullptr);
4761 auto InsertCost = getVectorInstrCost(Instruction::InsertElement, Ty,
4762 CostKind, -1, nullptr, nullptr);
4763 unsigned NElts = cast<FixedVectorType>(Ty)->getNumElements();
4764 return ExtractCost + InsertCost +
4765 NElts * getArithmeticInstrCost(Opcode, Ty->getScalarType(),
4766 CostKind, Op1Info.getNoProps(),
4767 Op2Info.getNoProps());
4768 }
4769 [[fallthrough]];
4770 case ISD::UDIV:
4771 case ISD::UREM: {
4772 auto VT = TLI->getValueType(DL, Ty);
4773 if (Op2Info.isConstant()) {
4774 // If the operand is a power of 2 we can use the shift or and cost.
4775 if (ISD == ISD::UDIV && Op2Info.isPowerOf2())
4776 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
4777 Op1Info.getNoProps(),
4778 Op2Info.getNoProps());
4779 if (ISD == ISD::UREM && Op2Info.isPowerOf2())
4780 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
4781 Op1Info.getNoProps(),
4782 Op2Info.getNoProps());
4783
4784 if (ISD == ISD::UDIV || ISD == ISD::UREM) {
4785 // Divides by a constant are expanded to MULHU + SUB + SRL + ADD + SRL.
4786 // The MULHU will be expanded to UMULL for the types not listed below,
4787 // and will become a pair of UMULL+MULL2 for 128bit vectors.
4788 bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||
4789 LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||
4790 LT.second == MVT::nxv16i8;
4791 bool Is128bit = LT.second.is128BitVector();
4792
4793 InstructionCost MulCost =
4794 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
4795 Op1Info.getNoProps(), Op2Info.getNoProps());
4796 InstructionCost AddCost =
4797 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
4798 Op1Info.getNoProps(), Op2Info.getNoProps());
4799 InstructionCost ShrCost =
4800 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
4801 Op1Info.getNoProps(), Op2Info.getNoProps());
4802 InstructionCost DivCost = MulCost * (Is128bit ? 2 : 1) + // UMULL/UMULH
4803 (HasMULH ? 0 : ShrCost) + // UMULL shift
4804 AddCost * 2 + ShrCost;
4805 return DivCost + (ISD == ISD::UREM ? MulCost + AddCost : 0);
4806 }
4807 }
4808
4809 // div i128's are lowered as libcalls. Pass nullptr as (u)divti3 calls are
4810 // emitted by the backend even when those functions are not declared in the
4811 // module.
4812 if (!VT.isVector() && VT.getSizeInBits() > 64)
4813 return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);
4814
4816 Opcode, Ty, CostKind, Op1Info, Op2Info);
4817 if (Ty->isVectorTy() && (ISD == ISD::SDIV || ISD == ISD::UDIV)) {
4818 if (TLI->isOperationLegalOrCustom(ISD, LT.second) && ST->hasSVE()) {
4819 // SDIV/UDIV operations are lowered using SVE, then we can have less
4820 // costs.
4821 if (VT.isSimple() && isa<FixedVectorType>(Ty) &&
4822 Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {
4823 static const CostTblEntry DivTbl[]{
4824 {ISD::SDIV, MVT::v2i8, 5}, {ISD::SDIV, MVT::v4i8, 8},
4825 {ISD::SDIV, MVT::v8i8, 8}, {ISD::SDIV, MVT::v2i16, 5},
4826 {ISD::SDIV, MVT::v4i16, 5}, {ISD::SDIV, MVT::v2i32, 1},
4827 {ISD::UDIV, MVT::v2i8, 5}, {ISD::UDIV, MVT::v4i8, 8},
4828 {ISD::UDIV, MVT::v8i8, 8}, {ISD::UDIV, MVT::v2i16, 5},
4829 {ISD::UDIV, MVT::v4i16, 5}, {ISD::UDIV, MVT::v2i32, 1}};
4830
4831 const auto *Entry = CostTableLookup(DivTbl, ISD, VT.getSimpleVT());
4832 if (nullptr != Entry)
4833 return Entry->Cost;
4834 }
4835 // For 8/16-bit elements, the cost is higher because the type
4836 // requires promotion and possibly splitting:
4837 if (LT.second.getScalarType() == MVT::i8)
4838 Cost *= 8;
4839 else if (LT.second.getScalarType() == MVT::i16)
4840 Cost *= 4;
4841 return Cost;
4842 } else {
4843 // If one of the operands is a uniform constant then the cost for each
4844 // element is Cost for insertion, extraction and division.
4845 // Insertion cost = 2, Extraction Cost = 2, Division = cost for the
4846 // operation with scalar type
4847 if ((Op1Info.isConstant() && Op1Info.isUniform()) ||
4848 (Op2Info.isConstant() && Op2Info.isUniform())) {
4849 if (auto *VTy = dyn_cast<FixedVectorType>(Ty)) {
4851 Opcode, Ty->getScalarType(), CostKind, Op1Info, Op2Info);
4852 return (4 + DivCost) * VTy->getNumElements();
4853 }
4854 }
4855 // On AArch64, without SVE, vector divisions are expanded
4856 // into scalar divisions of each pair of elements.
4857 Cost += getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind,
4858 -1, nullptr, nullptr);
4859 Cost += getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,
4860 nullptr, nullptr);
4861 }
4862
4863 // TODO: if one of the arguments is scalar, then it's not necessary to
4864 // double the cost of handling the vector elements.
4865 Cost += Cost;
4866 }
4867 return Cost;
4868 }
4869 case ISD::XOR:
4870 case ISD::OR:
4871 case ISD::AND:
4872 case ISD::SRL:
4873 case ISD::SRA:
4874 case ISD::SHL:
4875 // These nodes are marked as 'custom' for combining purposes only.
4876 // We know that they are legal. See LowerAdd in ISelLowering.
4877 return LT.first;
4878
4879 case ISD::FNEG:
4880 // Scalar fmul(fneg) or fneg(fmul) can be converted to fnmul
4881 if ((Ty->isFloatTy() || Ty->isDoubleTy() ||
4882 (Ty->isHalfTy() && ST->hasFullFP16())) &&
4883 CxtI &&
4884 ((CxtI->hasOneUse() &&
4885 match(*CxtI->user_begin(), m_FMul(m_Value(), m_Value()))) ||
4886 match(CxtI->getOperand(0), m_FMul(m_Value(), m_Value()))))
4887 return 0;
4888 [[fallthrough]];
4889 case ISD::FADD:
4890 case ISD::FSUB:
4891 if (!Ty->getScalarType()->isFP128Ty())
4892 return LT.first;
4893 [[fallthrough]];
4894 case ISD::FMUL:
4895 case ISD::FDIV:
4896 // These nodes are marked as 'custom' just to lower them to SVE.
4897 // We know said lowering will incur no additional cost.
4898 if (!Ty->getScalarType()->isFP128Ty())
4899 return 2 * LT.first;
4900
4901 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
4902 Op2Info);
4903 case ISD::FREM:
4904 // Pass nullptr as fmod/fmodf calls are emitted by the backend even when
4905 // those functions are not declared in the module.
4906 if (!Ty->isVectorTy())
4907 return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);
4908 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
4909 Op2Info);
4910 }
4911}
4912
4915 const SCEV *Ptr,
4917 // Address computations in vectorized code with non-consecutive addresses will
4918 // likely result in more instructions compared to scalar code where the
4919 // computation can more often be merged into the index mode. The resulting
4920 // extra micro-ops can significantly decrease throughput.
4921 unsigned NumVectorInstToHideOverhead = NeonNonConstStrideOverhead;
4922 int MaxMergeDistance = 64;
4923
4924 if (PtrTy->isVectorTy() && SE &&
4925 !BaseT::isConstantStridedAccessLessThan(SE, Ptr, MaxMergeDistance + 1))
4926 return NumVectorInstToHideOverhead;
4927
4928 // In many cases the address computation is not merged into the instruction
4929 // addressing mode.
4930 return 1;
4931}
4932
4933/// Check whether Opcode1 has less throughput according to the scheduling
4934/// model than Opcode2.
4936 unsigned Opcode1, unsigned Opcode2) const {
4937 const MCSchedModel &Sched = ST->getSchedModel();
4938 const TargetInstrInfo *TII = ST->getInstrInfo();
4939 if (!Sched.hasInstrSchedModel())
4940 return false;
4941
4942 const MCSchedClassDesc *SCD1 =
4943 Sched.getSchedClassDesc(TII->get(Opcode1).getSchedClass());
4944 const MCSchedClassDesc *SCD2 =
4945 Sched.getSchedClassDesc(TII->get(Opcode2).getSchedClass());
4946 // We cannot handle variant scheduling classes without an MI. If we need to
4947 // support them for any of the instructions we query the information of we
4948 // might need to add a way to resolve them without a MI or not use the
4949 // scheduling info.
4950 assert(!SCD1->isVariant() && !SCD2->isVariant() &&
4951 "Cannot handle variant scheduling classes without an MI");
4952 if (!SCD1->isValid() || !SCD2->isValid())
4953 return false;
4954
4955 return MCSchedModel::getReciprocalThroughput(*ST, *SCD1) >
4957}
4958
4960 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
4962 TTI::OperandValueInfo Op2Info, const Instruction *I) const {
4963 // We don't lower some vector selects well that are wider than the register
4964 // width. TODO: Improve this with different cost kinds.
4965 if (isa<FixedVectorType>(ValTy) && Opcode == Instruction::Select) {
4966 // We would need this many instructions to hide the scalarization happening.
4967 const int AmortizationCost = 20;
4968
4969 // If VecPred is not set, check if we can get a predicate from the context
4970 // instruction, if its type matches the requested ValTy.
4971 if (VecPred == CmpInst::BAD_ICMP_PREDICATE && I && I->getType() == ValTy) {
4972 CmpPredicate CurrentPred;
4973 if (match(I, m_Select(m_Cmp(CurrentPred, m_Value(), m_Value()), m_Value(),
4974 m_Value())))
4975 VecPred = CurrentPred;
4976 }
4977 // Check if we have a compare/select chain that can be lowered using
4978 // a (F)CMxx & BFI pair.
4979 if (CmpInst::isIntPredicate(VecPred) || VecPred == CmpInst::FCMP_OLE ||
4980 VecPred == CmpInst::FCMP_OLT || VecPred == CmpInst::FCMP_OGT ||
4981 VecPred == CmpInst::FCMP_OGE || VecPred == CmpInst::FCMP_OEQ ||
4982 VecPred == CmpInst::FCMP_UNE) {
4983 static const auto ValidMinMaxTys = {
4984 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
4985 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
4986 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
4987
4988 auto LT = getTypeLegalizationCost(ValTy);
4989 if (any_of(ValidMinMaxTys, equal_to(LT.second)) ||
4990 (ST->hasFullFP16() &&
4991 any_of(ValidFP16MinMaxTys, equal_to(LT.second))))
4992 return LT.first;
4993 }
4994
4995 static const TypeConversionCostTblEntry VectorSelectTbl[] = {
4996 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
4997 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
4998 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
4999 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5000 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5001 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5002 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5003 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5004 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5005 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5006 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5007
5008 EVT SelCondTy = TLI->getValueType(DL, CondTy);
5009 EVT SelValTy = TLI->getValueType(DL, ValTy);
5010 if (SelCondTy.isSimple() && SelValTy.isSimple()) {
5011 if (const auto *Entry = ConvertCostTableLookup(VectorSelectTbl, Opcode,
5012 SelCondTy.getSimpleVT(),
5013 SelValTy.getSimpleVT()))
5014 return Entry->Cost;
5015 }
5016 }
5017
5018 if (Opcode == Instruction::FCmp) {
5019 if (auto PromotedCost = getFP16BF16PromoteCost(
5020 ValTy, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/false,
5021 // TODO: Consider costing SVE FCMPs.
5022 /*CanUseSVE=*/false, [&](Type *PromotedTy) {
5024 getCmpSelInstrCost(Opcode, PromotedTy, CondTy, VecPred,
5025 CostKind, Op1Info, Op2Info);
5026 if (isa<VectorType>(PromotedTy))
5028 Instruction::Trunc,
5032 return Cost;
5033 }))
5034 return *PromotedCost;
5035
5036 auto LT = getTypeLegalizationCost(ValTy);
5037 // Model unknown fp compares as a libcall.
5038 if (LT.second.getScalarType() != MVT::f64 &&
5039 LT.second.getScalarType() != MVT::f32 &&
5040 LT.second.getScalarType() != MVT::f16)
5041 return LT.first * getCallInstrCost(/*Function*/ nullptr, ValTy,
5042 {ValTy, ValTy}, CostKind);
5043
5044 // Some comparison operators require expanding to multiple compares + or.
5045 unsigned Factor = 1;
5046 if (!CondTy->isVectorTy() &&
5047 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))
5048 Factor = 2; // fcmp with 2 selects
5049 else if (isa<FixedVectorType>(ValTy) &&
5050 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ ||
5051 VecPred == FCmpInst::FCMP_ORD || VecPred == FCmpInst::FCMP_UNO))
5052 Factor = 3; // fcmxx+fcmyy+or
5053 else if (isa<ScalableVectorType>(ValTy) &&
5054 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))
5055 Factor = 3; // fcmxx+fcmyy+or
5056
5057 if (isa<ScalableVectorType>(ValTy) &&
5059 hasKnownLowerThroughputFromSchedulingModel(AArch64::FCMEQ_PPzZZ_S,
5060 AArch64::FCMEQv4f32))
5061 Factor *= 2;
5062
5063 return Factor * (CostKind == TTI::TCK_Latency ? 2 : LT.first);
5064 }
5065
5066 // Treat the icmp in icmp(and, 0) or icmp(and, -1/1) when it can be folded to
5067 // icmp(and, 0) as free, as we can make use of ands, but only if the
5068 // comparison is not unsigned. FIXME: Enable for non-throughput cost kinds
5069 // providing it will not cause performance regressions.
5070 if (CostKind == TTI::TCK_RecipThroughput && ValTy->isIntegerTy() &&
5071 Opcode == Instruction::ICmp && I && !CmpInst::isUnsigned(VecPred) &&
5072 TLI->isTypeLegal(TLI->getValueType(DL, ValTy)) &&
5073 match(I->getOperand(0), m_And(m_Value(), m_Value()))) {
5074 if (match(I->getOperand(1), m_Zero()))
5075 return 0;
5076
5077 // x >= 1 / x < 1 -> x > 0 / x <= 0
5078 if (match(I->getOperand(1), m_One()) &&
5079 (VecPred == CmpInst::ICMP_SLT || VecPred == CmpInst::ICMP_SGE))
5080 return 0;
5081
5082 // x <= -1 / x > -1 -> x > 0 / x <= 0
5083 if (match(I->getOperand(1), m_AllOnes()) &&
5084 (VecPred == CmpInst::ICMP_SLE || VecPred == CmpInst::ICMP_SGT))
5085 return 0;
5086 }
5087
5088 // The base case handles scalable vectors fine for now, since it treats the
5089 // cost as 1 * legalization cost.
5090 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
5091 Op1Info, Op2Info, I);
5092}
5093
5095AArch64TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
5097 if (ST->requiresStrictAlign()) {
5098 // TODO: Add cost modeling for strict align. Misaligned loads expand to
5099 // a bunch of instructions when strict align is enabled.
5100 return Options;
5101 }
5102 Options.AllowOverlappingLoads = true;
5103 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5104 Options.NumLoadsPerBlock = Options.MaxNumLoads;
5105 // TODO: Though vector loads usually perform well on AArch64, in some targets
5106 // they may wake up the FP unit, which raises the power consumption. Perhaps
5107 // they could be used with no holds barred (-O3).
5108 Options.LoadSizes = {8, 4, 2, 1};
5109 Options.AllowedTailExpansions = {3, 5, 6};
5110 return Options;
5111}
5112
5114 return ST->hasSVE();
5115}
5116
5120 switch (MICA.getID()) {
5121 case Intrinsic::masked_scatter:
5122 case Intrinsic::masked_gather:
5123 return getGatherScatterOpCost(MICA, CostKind);
5124 case Intrinsic::masked_load:
5125 case Intrinsic::masked_expandload:
5126 case Intrinsic::masked_store:
5127 return getMaskedMemoryOpCost(MICA, CostKind);
5128 }
5130}
5131
5135 Type *Src = MICA.getDataType();
5136
5137 if (useNeonVector(Src))
5139 auto LT = getTypeLegalizationCost(Src);
5140 if (!LT.first.isValid())
5142
5143 // Return an invalid cost for element types that we are unable to lower.
5144 auto *VT = cast<VectorType>(Src);
5145 if (VT->getElementType()->isIntegerTy(1))
5147
5148 // The code-generator is currently not able to handle scalable vectors
5149 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
5150 // it. This change will be removed when code-generation for these types is
5151 // sufficiently reliable.
5152 if (VT->getElementCount() == ElementCount::getScalable(1))
5154
5155 InstructionCost MemOpCost = LT.first;
5156 if (MICA.getID() == Intrinsic::masked_expandload) {
5157 if (!isLegalMaskedExpandLoad(Src, MICA.getAlignment()))
5159
5160 // Operation will be split into expand of masked.load
5161 MemOpCost *= 2;
5162 }
5163
5164 // If we need to split the memory operation, we will also need to split the
5165 // mask. This will likely lead to overestimating the cost in some cases if
5166 // multiple memory operations use the same mask, but we often don't have
5167 // enough context to figure that out here.
5168 //
5169 // If the elements being loaded are bytes then the mask will already be split,
5170 // since the number of bits in a P register matches the number of bytes in a
5171 // Z register.
5172 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5173 return MemOpCost * 2;
5174
5175 return MemOpCost;
5176}
5177
5178// This function returns gather/scatter overhead either from
5179// user-provided value or specialized values per-target from \p ST.
5180static unsigned getSVEGatherScatterOverhead(unsigned Opcode,
5181 const AArch64Subtarget *ST) {
5182 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5183 "Should be called on only load or stores.");
5184 switch (Opcode) {
5185 case Instruction::Load:
5186 if (SVEGatherOverhead.getNumOccurrences() > 0)
5187 return SVEGatherOverhead;
5188 return ST->getGatherOverhead();
5189 break;
5190 case Instruction::Store:
5191 if (SVEScatterOverhead.getNumOccurrences() > 0)
5192 return SVEScatterOverhead;
5193 return ST->getScatterOverhead();
5194 break;
5195 default:
5196 llvm_unreachable("Shouldn't have reached here");
5197 }
5198}
5199
5203
5204 unsigned Opcode = (MICA.getID() == Intrinsic::masked_gather ||
5205 MICA.getID() == Intrinsic::vp_gather)
5206 ? Instruction::Load
5207 : Instruction::Store;
5208
5209 Type *DataTy = MICA.getDataType();
5210 Align Alignment = MICA.getAlignment();
5211 const Instruction *I = MICA.getInst();
5212
5213 if (useNeonVector(DataTy) || !isLegalMaskedGatherScatter(DataTy))
5215 auto *VT = cast<VectorType>(DataTy);
5216 auto LT = getTypeLegalizationCost(DataTy);
5217 if (!LT.first.isValid())
5219
5220 // Return an invalid cost for element types that we are unable to lower.
5221 if (!LT.second.isVector() ||
5222 !isElementTypeLegalForScalableVector(VT->getElementType()) ||
5223 VT->getElementType()->isIntegerTy(1))
5225
5226 // The code-generator is currently not able to handle scalable vectors
5227 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
5228 // it. This change will be removed when code-generation for these types is
5229 // sufficiently reliable.
5230 if (VT->getElementCount() == ElementCount::getScalable(1))
5232
5233 ElementCount LegalVF = LT.second.getVectorElementCount();
5234 InstructionCost MemOpCost =
5235 getMemoryOpCost(Opcode, VT->getElementType(), Alignment, 0, CostKind,
5236 {TTI::OK_AnyValue, TTI::OP_None}, I);
5237 // Add on an overhead cost for using gathers/scatters.
5238 MemOpCost *= getSVEGatherScatterOverhead(Opcode, ST);
5239 return LT.first * MemOpCost * getMaxNumElements(LegalVF);
5240}
5241
5243 return isa<FixedVectorType>(Ty) && !ST->useSVEForFixedLengthVectors();
5244}
5245
5247 Align Alignment,
5248 unsigned AddressSpace,
5250 TTI::OperandValueInfo OpInfo,
5251 const Instruction *I) const {
5252 EVT VT = TLI->getValueType(DL, Ty, true);
5253 // Type legalization can't handle structs
5254 if (VT == MVT::Other)
5255 return BaseT::getMemoryOpCost(Opcode, Ty, Alignment, AddressSpace,
5256 CostKind);
5257
5258 auto LT = getTypeLegalizationCost(Ty);
5259 if (!LT.first.isValid())
5261
5262 // The code-generator is currently not able to handle scalable vectors
5263 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
5264 // it. This change will be removed when code-generation for these types is
5265 // sufficiently reliable.
5266 // We also only support full register predicate loads and stores.
5267 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))
5268 if (VTy->getElementCount() == ElementCount::getScalable(1) ||
5269 (VTy->getElementType()->isIntegerTy(1) &&
5270 !VTy->getElementCount().isKnownMultipleOf(
5273
5274 // TODO: consider latency as well for TCK_SizeAndLatency.
5276 return LT.first;
5277
5278 if (CostKind == TTI::TCK_Latency) {
5279 // Latency doesn't make much sense for stores, so just return 1
5280 if (Opcode == Instruction::Store)
5281 return 1;
5282 // If the subtarget has overridden the load latency then use that instead of
5283 // querying the SchedModel.
5284 if (ST->getFixedLoadLatency())
5285 return (LT.first - 1) + ST->getFixedLoadLatency();
5286 // We expect the load to become LT.first loads of type LT.second. The
5287 // latency will be the latency of the last load plus the time it gets to get
5288 // there, which will be the amount of other loads before that (i.e. total
5289 // loads - 1) multiplied by how long it takes to get through them (the
5290 // reciprocal of the throughput). We get the latency and reciprocal
5291 // throughput from the SchedModel, and assume that the loads become the
5292 // variant with unsigned integer offset.
5293 unsigned Inst = 0;
5294 if (LT.second.isScalableVector() ||
5295 ST->useSVEForFixedLengthVectors(LT.second)) {
5296 Inst = AArch64::LDR_ZXI;
5297 } else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5298 switch (LT.second.getSizeInBits()) {
5299 case 8:
5300 Inst = AArch64::LDRBui;
5301 break;
5302 case 16:
5303 Inst = AArch64::LDRHui;
5304 break;
5305 case 32:
5306 Inst = AArch64::LDRSui;
5307 break;
5308 case 64:
5309 Inst = AArch64::LDRDui;
5310 break;
5311 case 128:
5312 Inst = AArch64::LDRQui;
5313 break;
5314 default:
5315 llvm_unreachable("Unexpected float or vector type");
5316 }
5317 } else {
5318 switch (LT.second.getSizeInBits()) {
5319 case 8:
5320 Inst = AArch64::LDRBBui;
5321 break;
5322 case 16:
5323 Inst = AArch64::LDRHHui;
5324 break;
5325 case 32:
5326 Inst = AArch64::LDRWui;
5327 break;
5328 case 64:
5329 Inst = AArch64::LDRXui;
5330 break;
5331 default:
5332 llvm_unreachable("Unexpected integer type");
5333 }
5334 }
5335 const MCSchedModel &Sched = ST->getSchedModel();
5336 const TargetInstrInfo *TII = ST->getInstrInfo();
5337 unsigned SchedClass = TII->get(Inst).getSchedClass();
5338 const MCSchedClassDesc *SCD = Sched.getSchedClassDesc(SchedClass);
5339 // We need to convert the number of loads before the last to a float here,
5340 // as the reciprocal throughput may be fractional.
5341 float NumLoads = (LT.first - 1).getValue();
5342 return NumLoads * Sched.getReciprocalThroughput(*ST, *SCD) +
5343 Sched.computeInstrLatency(*ST, *SCD);
5344 }
5345
5346 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
5347 LT.second.is128BitVector() && Alignment < Align(16)) {
5348 // Unaligned stores are extremely inefficient. We don't split all
5349 // unaligned 128-bit stores because the negative impact that has shown in
5350 // practice on inlined block copy code.
5351 // We make such stores expensive so that we will only vectorize if there
5352 // are 6 other instructions getting vectorized.
5353 const int AmortizationCost = 6;
5354
5355 return LT.first * 2 * AmortizationCost;
5356 }
5357
5358 // Opaque ptr or ptr vector types are i64s and can be lowered to STP/LDPs.
5359 if (Ty->isPtrOrPtrVectorTy())
5360 return LT.first;
5361
5362 if (useNeonVector(Ty)) {
5363 // Check truncating stores and extending loads.
5364 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
5365 // v4i8 types are lowered to scalar a load/store and sshll/xtn.
5366 if (VT == MVT::v4i8)
5367 return 2;
5368 // Otherwise we need to scalarize.
5369 return cast<FixedVectorType>(Ty)->getNumElements() * 2;
5370 }
5371 EVT EltVT = VT.getVectorElementType();
5372 unsigned EltSize = EltVT.getScalarSizeInBits();
5373 if (!isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
5374 VT.getVectorNumElements() >= (128 / EltSize) || Alignment != Align(1))
5375 return LT.first;
5376 // FIXME: v3i8 lowering currently is very inefficient, due to automatic
5377 // widening to v4i8, which produces suboptimal results.
5378 if (VT.getVectorNumElements() == 3 && EltVT == MVT::i8)
5379 return LT.first;
5380
5381 // Check non-power-of-2 loads/stores for legal vector element types with
5382 // NEON. Non-power-of-2 memory ops will get broken down to a set of
5383 // operations on smaller power-of-2 ops, including ld1/st1.
5384 LLVMContext &C = Ty->getContext();
5386 SmallVector<EVT> TypeWorklist;
5387 TypeWorklist.push_back(VT);
5388 while (!TypeWorklist.empty()) {
5389 EVT CurrVT = TypeWorklist.pop_back_val();
5390 unsigned CurrNumElements = CurrVT.getVectorNumElements();
5391 if (isPowerOf2_32(CurrNumElements)) {
5392 Cost += 1;
5393 continue;
5394 }
5395
5396 unsigned PrevPow2 = NextPowerOf2(CurrNumElements) / 2;
5397 TypeWorklist.push_back(EVT::getVectorVT(C, EltVT, PrevPow2));
5398 TypeWorklist.push_back(
5399 EVT::getVectorVT(C, EltVT, CurrNumElements - PrevPow2));
5400 }
5401 return Cost;
5402 }
5403
5404 return LT.first;
5405}
5406
5408 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
5409 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
5410 bool UseMaskForCond, bool UseMaskForGaps) const {
5411 assert(Factor >= 2 && "Invalid interleave factor");
5412 auto *VecVTy = cast<VectorType>(VecTy);
5413
5414 if (VecTy->isScalableTy() && !ST->hasSVE())
5416
5417 // Scalable VFs will emit vector.[de]interleave intrinsics, and currently we
5418 // only have lowering for power-of-2 factors.
5419 // TODO: Add lowering for vector.[de]interleave3 intrinsics and support in
5420 // InterleavedAccessPass for ld3/st3
5421 if (VecTy->isScalableTy() && !isPowerOf2_32(Factor))
5423
5424 // Vectorization for masked interleaved accesses is only enabled for scalable
5425 // VF.
5426 if (!VecTy->isScalableTy() && (UseMaskForCond || UseMaskForGaps))
5428
5429 if (!UseMaskForGaps && Factor <= TLI->getMaxSupportedInterleaveFactor()) {
5430 ElementCount EC = VecVTy->getElementCount();
5431 auto *SubVecTy = VectorType::get(VecVTy->getElementType(),
5432 EC.divideCoefficientBy(Factor));
5433
5434 // ldN/stN only support legal vector types of size 64 or 128 in bits.
5435 // Accesses having vector types that are a multiple of 128 bits can be
5436 // matched to more than one ldN/stN instruction.
5437 bool UseScalable;
5438 if (EC.isKnownMultipleOf(Factor) &&
5439 TLI->isLegalInterleavedAccessType(SubVecTy, DL, UseScalable))
5440 return Factor * TLI->getNumInterleavedAccesses(SubVecTy, DL, UseScalable);
5441
5442 // Cost the alternative approach for scalable vectors where the interleave
5443 // factor is larger than the VF: use a contiguous load/store of the full
5444 // wide vector followed by deinterleave/interleave shuffles.
5445 if (VecTy->isScalableTy() && EC.isKnownMultipleOf(Factor)) {
5446 if (SubVecTy->getElementCount() == ElementCount::getScalable(1))
5448
5449 // Cost of the contiguous memory operation on the wide vector.
5450 InstructionCost MemCost;
5451 if (UseMaskForCond) {
5452 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5453 : Intrinsic::masked_store;
5454 MemCost = getMemIntrinsicInstrCost(
5455 MemIntrinsicCostAttributes(IID, VecTy, Alignment, AddressSpace),
5456 CostKind);
5457 } else {
5458 MemCost =
5459 getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, CostKind);
5460 }
5461
5462 // llvm.vector.deinterleaveN is lowered as a binary tree of deinterleave2
5463 // operations. A binary tree producing Factor leaf vectors has
5464 // (Factor -1) inner deinterleave2 nodes. Each deinterleave2 on a pair of
5465 // SVE registers emits one uzp1 + one uzp2.
5466 // Total shuffle cost: (Factor - 1) deinterleave2 operations, each
5467 // processing LT.first legal vector parts,with one uzp shuffle per part.
5468 auto LT = getTypeLegalizationCost(VecTy);
5469 return MemCost + (Factor - 1) * LT.first;
5470 }
5471 }
5472
5473 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
5474 Alignment, AddressSpace, CostKind,
5475 UseMaskForCond, UseMaskForGaps);
5476}
5477
5482 for (auto *I : Tys) {
5483 if (!I->isVectorTy())
5484 continue;
5485 if (I->getScalarSizeInBits() * cast<FixedVectorType>(I)->getNumElements() ==
5486 128)
5487 Cost += getMemoryOpCost(Instruction::Store, I, Align(128), 0, CostKind) +
5488 getMemoryOpCost(Instruction::Load, I, Align(128), 0, CostKind);
5489 }
5490 return Cost;
5491}
5492
5494 Align Alignment) const {
5495 // Neon types should be scalarised when we are not choosing to use SVE.
5496 if (useNeonVector(DataTy))
5497 return false;
5498
5499 // Return true only if we are able to lower using the SVE2p2/SME2p2
5500 // expand instruction.
5501 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
5502 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
5503}
5504
5505unsigned
5507 bool HasUnorderedReductions) const {
5508 if (VF.isScalar() || (HasUnorderedReductions && VF.getKnownMinValue() <= 4))
5509 return 4;
5510 return ST->getMaxInterleaveFactor();
5511}
5512
5513// For Falkor, we want to avoid having too many strided loads in a loop since
5514// that can exhaust the HW prefetcher resources. We adjust the unroller
5515// MaxCount preference below to attempt to ensure unrolling doesn't create too
5516// many strided loads.
5517static void
5520 enum { MaxStridedLoads = 7 };
5521 auto countStridedLoads = [](Loop *L, ScalarEvolution &SE) {
5522 int StridedLoads = 0;
5523 // FIXME? We could make this more precise by looking at the CFG and
5524 // e.g. not counting loads in each side of an if-then-else diamond.
5525 for (const auto BB : L->blocks()) {
5526 for (auto &I : *BB) {
5527 LoadInst *LMemI = dyn_cast<LoadInst>(&I);
5528 if (!LMemI)
5529 continue;
5530
5531 Value *PtrValue = LMemI->getPointerOperand();
5532 if (L->isLoopInvariant(PtrValue))
5533 continue;
5534
5535 const SCEV *LSCEV = SE.getSCEV(PtrValue);
5536 const SCEVAddRecExpr *LSCEVAddRec = dyn_cast<SCEVAddRecExpr>(LSCEV);
5537 if (!LSCEVAddRec || !LSCEVAddRec->isAffine())
5538 continue;
5539
5540 // FIXME? We could take pairing of unrolled load copies into account
5541 // by looking at the AddRec, but we would probably have to limit this
5542 // to loops with no stores or other memory optimization barriers.
5543 ++StridedLoads;
5544 // We've seen enough strided loads that seeing more won't make a
5545 // difference.
5546 if (StridedLoads > MaxStridedLoads / 2)
5547 return StridedLoads;
5548 }
5549 }
5550 return StridedLoads;
5551 };
5552
5553 int StridedLoads = countStridedLoads(L, SE);
5554 LLVM_DEBUG(dbgs() << "falkor-hwpf: detected " << StridedLoads
5555 << " strided loads\n");
5556 // Pick the largest power of 2 unroll count that won't result in too many
5557 // strided loads.
5558 if (StridedLoads) {
5559 UP.MaxCount = 1 << Log2_32(MaxStridedLoads / StridedLoads);
5560 LLVM_DEBUG(dbgs() << "falkor-hwpf: setting unroll MaxCount to "
5561 << UP.MaxCount << '\n');
5562 }
5563}
5564
5565// This function returns true if the loop:
5566// 1. Has a valid cost, and
5567// 2. Has a cost within the supplied budget.
5568// Otherwise it returns false.
5570 InstructionCost Budget,
5571 unsigned *FinalSize) {
5572 // Estimate the size of the loop.
5573 InstructionCost LoopCost = 0;
5574
5575 for (auto *BB : L->getBlocks()) {
5576 for (auto &I : *BB) {
5577 SmallVector<const Value *, 4> Operands(I.operand_values());
5578 InstructionCost Cost =
5579 TTI.getInstructionCost(&I, Operands, TTI::TCK_CodeSize);
5580 // This can happen with intrinsics that don't currently have a cost model
5581 // or for some operations that require SVE.
5582 if (!Cost.isValid())
5583 return false;
5584
5585 LoopCost += Cost;
5586 if (LoopCost > Budget)
5587 return false;
5588 }
5589 }
5590
5591 if (FinalSize)
5592 *FinalSize = LoopCost.getValue();
5593 return true;
5594}
5595
5597 const AArch64TTIImpl &TTI) {
5598 // Only consider loops with unknown trip counts for which we can determine
5599 // a symbolic expression. Multi-exit loops with small known trip counts will
5600 // likely be unrolled anyway.
5601 const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);
5603 return false;
5604
5605 // It might not be worth unrolling loops with low max trip counts. Restrict
5606 // this to max trip counts > 32 for now.
5607 unsigned MaxTC = SE.getSmallConstantMaxTripCount(L);
5608 if (MaxTC > 0 && MaxTC <= 32)
5609 return false;
5610
5611 // Make sure the loop size is <= 5.
5612 if (!isLoopSizeWithinBudget(L, TTI, 5, nullptr))
5613 return false;
5614
5615 // Small search loops with multiple exits can be highly beneficial to unroll.
5616 // We only care about loops with exactly two exiting blocks, although each
5617 // block could jump to the same exit block.
5618 ArrayRef<BasicBlock *> Blocks = L->getBlocks();
5619 if (Blocks.size() != 2)
5620 return false;
5621
5622 if (any_of(Blocks, [](BasicBlock *BB) {
5624 }))
5625 return false;
5626
5627 return true;
5628}
5629
5630/// For Apple CPUs, we want to runtime-unroll loops to make better use if the
5631/// OOO engine's wide instruction window and various predictors.
5632static void
5635 const AArch64TTIImpl &TTI) {
5636 // Limit loops with structure that is highly likely to benefit from runtime
5637 // unrolling; that is we exclude outer loops and loops with many blocks (i.e.
5638 // likely with complex control flow). Note that the heuristics here may be
5639 // overly conservative and we err on the side of avoiding runtime unrolling
5640 // rather than unroll excessively. They are all subject to further refinement.
5641 if (!L->isInnermost() || L->getNumBlocks() > 8)
5642 return;
5643
5644 // Loops with multiple exits are handled by common code.
5645 if (!L->getExitBlock())
5646 return;
5647
5648 // Check if the loop contains any reductions that could be parallelized when
5649 // unrolling. If so, enable partial unrolling, if the trip count is know to be
5650 // a multiple of 2.
5651 bool HasParellelizableReductions =
5652 L->getNumBlocks() == 1 &&
5653 any_of(L->getHeader()->phis(),
5654 [&SE, L](PHINode &Phi) {
5655 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
5656 }) &&
5657 isLoopSizeWithinBudget(L, TTI, 12, nullptr);
5658 if (HasParellelizableReductions &&
5659 SE.getSmallConstantTripMultiple(L, L->getExitingBlock()) % 2 == 0) {
5660 UP.Partial = true;
5661 UP.MaxCount = 4;
5662 UP.AddAdditionalAccumulators = true;
5663 }
5664
5665 const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);
5667 (SE.getSmallConstantMaxTripCount(L) > 0 &&
5668 SE.getSmallConstantMaxTripCount(L) <= 32))
5669 return;
5670
5671 if (findStringMetadataForLoop(L, "llvm.loop.isvectorized"))
5672 return;
5673
5675 return;
5676
5677 // Limit to loops with trip counts that are cheap to expand.
5678 UP.SCEVExpansionBudget = 1;
5679
5680 if (HasParellelizableReductions) {
5681 UP.Runtime = true;
5683 UP.AddAdditionalAccumulators = true;
5684 }
5685
5686 // Try to unroll small loops, of few-blocks with low budget, if they have
5687 // load/store dependencies, to expose more parallel memory access streams,
5688 // or if they do little work inside a block (i.e. load -> X -> store pattern).
5689 BasicBlock *Header = L->getHeader();
5690 BasicBlock *Latch = L->getLoopLatch();
5691 if (Header == Latch) {
5692 // Estimate the size of the loop.
5693 unsigned Size;
5694 unsigned Width = 10;
5695 if (!isLoopSizeWithinBudget(L, TTI, Width, &Size))
5696 return;
5697
5698 // Try to find an unroll count that maximizes the use of the instruction
5699 // window, i.e. trying to fetch as many instructions per cycle as possible.
5700 unsigned MaxInstsPerLine = 16;
5701 unsigned UC = 1;
5702 unsigned BestUC = 1;
5703 unsigned SizeWithBestUC = BestUC * Size;
5704 while (UC <= 8) {
5705 unsigned SizeWithUC = UC * Size;
5706 if (SizeWithUC > 48)
5707 break;
5708 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
5709 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
5710 BestUC = UC;
5711 SizeWithBestUC = BestUC * Size;
5712 }
5713 UC++;
5714 }
5715
5716 if (BestUC == 1)
5717 return;
5718
5719 SmallPtrSet<Value *, 8> LoadedValuesPlus;
5721 for (auto *BB : L->blocks()) {
5722 for (auto &I : *BB) {
5724 if (!Ptr)
5725 continue;
5726 const SCEV *PtrSCEV = SE.getSCEV(Ptr);
5727 if (SE.isLoopInvariant(PtrSCEV, L))
5728 continue;
5729 if (isa<LoadInst>(&I)) {
5730 LoadedValuesPlus.insert(&I);
5731 // Include in-loop 1st users of loaded values.
5732 for (auto *U : I.users())
5733 if (L->contains(cast<Instruction>(U)))
5734 LoadedValuesPlus.insert(U);
5735 } else
5736 Stores.push_back(cast<StoreInst>(&I));
5737 }
5738 }
5739
5740 if (none_of(Stores, [&LoadedValuesPlus](StoreInst *SI) {
5741 return LoadedValuesPlus.contains(SI->getOperand(0));
5742 }))
5743 return;
5744
5745 UP.Runtime = true;
5746 UP.DefaultUnrollRuntimeCount = BestUC;
5747 return;
5748 }
5749
5750 // Try to runtime-unroll loops with early-continues depending on loop-varying
5751 // loads; this helps with branch-prediction for the early-continues.
5752 auto *Term = dyn_cast<CondBrInst>(Header->getTerminator());
5754 if (!Term || Preds.size() == 1 || !llvm::is_contained(Preds, Header) ||
5755 none_of(Preds, [L](BasicBlock *Pred) { return L->contains(Pred); }))
5756 return;
5757
5758 std::function<bool(Instruction *, unsigned)> DependsOnLoopLoad =
5759 [&](Instruction *I, unsigned Depth) -> bool {
5760 if (isa<PHINode>(I) || L->isLoopInvariant(I) || Depth > 8)
5761 return false;
5762
5763 if (isa<LoadInst>(I))
5764 return true;
5765
5766 return any_of(I->operands(), [&](Value *V) {
5767 auto *I = dyn_cast<Instruction>(V);
5768 return I && DependsOnLoopLoad(I, Depth + 1);
5769 });
5770 };
5771 CmpPredicate Pred;
5772 Instruction *I;
5773 if (match(Term, m_Br(m_ICmp(Pred, m_Instruction(I), m_Value()), m_Value(),
5774 m_Value())) &&
5775 DependsOnLoopLoad(I, 0)) {
5776 UP.Runtime = true;
5777 }
5778}
5779
5782 OptimizationRemarkEmitter *ORE) const {
5783 // Enable partial unrolling and runtime unrolling.
5784 BaseT::getUnrollingPreferences(L, SE, UP, ORE);
5785
5786 UP.UpperBound = true;
5787
5788 // For inner loop, it is more likely to be a hot one, and the runtime check
5789 // can be promoted out from LICM pass, so the overhead is less, let's try
5790 // a larger threshold to unroll more loops.
5791 if (L->getLoopDepth() > 1)
5792 UP.PartialThreshold *= 2;
5793
5794 // Disable partial & runtime unrolling on -Os.
5796
5797 // Scan the loop: don't unroll loops with calls as this could prevent
5798 // inlining. Don't unroll auto-vectorized loops either, though do allow
5799 // unrolling of the scalar remainder.
5800 bool IsVectorized = getBooleanLoopAttribute(L, "llvm.loop.isvectorized");
5802 for (auto *BB : L->getBlocks()) {
5803 for (auto &I : *BB) {
5804 // Both auto-vectorized loops and the scalar remainder have the
5805 // isvectorized attribute, so differentiate between them by the presence
5806 // of vector instructions.
5807 if (IsVectorized && I.getType()->isVectorTy())
5808 return;
5809 if (isa<CallBase>(I)) {
5812 if (!isLoweredToCall(F))
5813 continue;
5814 return;
5815 }
5816
5817 SmallVector<const Value *, 4> Operands(I.operand_values());
5818 Cost += getInstructionCost(&I, Operands,
5820 }
5821 }
5822
5823 // Apply subtarget-specific unrolling preferences.
5824 if (ST->isAppleMLike())
5825 getAppleRuntimeUnrollPreferences(L, SE, UP, *this);
5826 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
5829
5830 // If this is a small, multi-exit loop similar to something like std::find,
5831 // then there is typically a performance improvement achieved by unrolling.
5832 if (!L->getExitBlock() && shouldUnrollMultiExitLoop(L, SE, *this)) {
5833 UP.RuntimeUnrollMultiExit = true;
5834 UP.Runtime = true;
5835 // Limit unroll count.
5837 // Allow slightly more costly trip-count expansion to catch search loops
5838 // with pointer inductions.
5839 UP.SCEVExpansionBudget = 5;
5840 return;
5841 }
5842
5843 // Enable runtime unrolling for in-order models
5844 // If mcpu is omitted, getProcFamily() returns AArch64Subtarget::Others, so by
5845 // checking for that case, we can ensure that the default behaviour is
5846 // unchanged
5847 if (ST->getProcFamily() != AArch64Subtarget::Generic &&
5848 !ST->getSchedModel().isOutOfOrder()) {
5849 UP.Runtime = true;
5850 UP.Partial = true;
5851 UP.UnrollRemainder = true;
5853
5854 UP.UnrollAndJam = true;
5856 }
5857
5858 // Force unrolling small loops can be very useful because of the branch
5859 // taken cost of the backedge.
5861 UP.Force = true;
5862}
5863
5868
5870 Type *ExpectedType,
5871 bool CanCreate) const {
5872 switch (Inst->getIntrinsicID()) {
5873 default:
5874 return nullptr;
5875 case Intrinsic::aarch64_neon_st1x2:
5876 case Intrinsic::aarch64_neon_st1x3:
5877 case Intrinsic::aarch64_neon_st1x4:
5878 case Intrinsic::aarch64_neon_st2:
5879 case Intrinsic::aarch64_neon_st3:
5880 case Intrinsic::aarch64_neon_st4: {
5881 // Create a struct type
5882 StructType *ST = dyn_cast<StructType>(ExpectedType);
5883 if (!CanCreate || !ST)
5884 return nullptr;
5885 unsigned NumElts = Inst->arg_size() - 1;
5886 if (ST->getNumElements() != NumElts)
5887 return nullptr;
5888 for (unsigned i = 0, e = NumElts; i != e; ++i) {
5889 if (Inst->getArgOperand(i)->getType() != ST->getElementType(i))
5890 return nullptr;
5891 }
5892 Value *Res = PoisonValue::get(ExpectedType);
5893 IRBuilder<> Builder(Inst);
5894 for (unsigned i = 0, e = NumElts; i != e; ++i) {
5895 Value *L = Inst->getArgOperand(i);
5896 Res = Builder.CreateInsertValue(Res, L, i);
5897 }
5898 return Res;
5899 }
5900 case Intrinsic::aarch64_neon_ld1x2:
5901 case Intrinsic::aarch64_neon_ld1x3:
5902 case Intrinsic::aarch64_neon_ld1x4:
5903 case Intrinsic::aarch64_neon_ld2:
5904 case Intrinsic::aarch64_neon_ld3:
5905 case Intrinsic::aarch64_neon_ld4:
5906 if (Inst->getType() == ExpectedType)
5907 return Inst;
5908 return nullptr;
5909 }
5910}
5911
5913 MemIntrinsicInfo &Info) const {
5914 switch (Inst->getIntrinsicID()) {
5915 default:
5916 break;
5917 case Intrinsic::aarch64_neon_ld1x2:
5918 case Intrinsic::aarch64_neon_ld1x3:
5919 case Intrinsic::aarch64_neon_ld1x4:
5920 case Intrinsic::aarch64_neon_ld2:
5921 case Intrinsic::aarch64_neon_ld3:
5922 case Intrinsic::aarch64_neon_ld4:
5923 Info.ReadMem = true;
5924 Info.WriteMem = false;
5925 Info.PtrVal = Inst->getArgOperand(0);
5926 break;
5927 case Intrinsic::aarch64_neon_st1x2:
5928 case Intrinsic::aarch64_neon_st1x3:
5929 case Intrinsic::aarch64_neon_st1x4:
5930 case Intrinsic::aarch64_neon_st2:
5931 case Intrinsic::aarch64_neon_st3:
5932 case Intrinsic::aarch64_neon_st4:
5933 Info.ReadMem = false;
5934 Info.WriteMem = true;
5935 Info.PtrVal = Inst->getArgOperand(Inst->arg_size() - 1);
5936 break;
5937 }
5938
5939 // Use the ID of neon load as the "matching id".
5940 switch (Inst->getIntrinsicID()) {
5941 default:
5942 return false;
5943 case Intrinsic::aarch64_neon_ld1x2:
5944 case Intrinsic::aarch64_neon_st1x2:
5945 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
5946 break;
5947 case Intrinsic::aarch64_neon_ld1x3:
5948 case Intrinsic::aarch64_neon_st1x3:
5949 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
5950 break;
5951 case Intrinsic::aarch64_neon_ld1x4:
5952 case Intrinsic::aarch64_neon_st1x4:
5953 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
5954 break;
5955 case Intrinsic::aarch64_neon_ld2:
5956 case Intrinsic::aarch64_neon_st2:
5957 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
5958 break;
5959 case Intrinsic::aarch64_neon_ld3:
5960 case Intrinsic::aarch64_neon_st3:
5961 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
5962 break;
5963 case Intrinsic::aarch64_neon_ld4:
5964 case Intrinsic::aarch64_neon_st4:
5965 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
5966 break;
5967 }
5968 return true;
5969}
5970
5971/// See if \p I should be considered for address type promotion. We check if \p
5972/// I is a sext with right type and used in memory accesses. If it used in a
5973/// "complex" getelementptr, we allow it to be promoted without finding other
5974/// sext instructions that sign extended the same initial value. A getelementptr
5975/// is considered as "complex" if it has more than 2 operands.
5977 const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const {
5978 bool Considerable = false;
5979 AllowPromotionWithoutCommonHeader = false;
5980 if (!isa<SExtInst>(&I))
5981 return false;
5982 Type *ConsideredSExtType =
5983 Type::getInt64Ty(I.getParent()->getParent()->getContext());
5984 if (I.getType() != ConsideredSExtType)
5985 return false;
5986 // See if the sext is the one with the right type and used in at least one
5987 // GetElementPtrInst.
5988 for (const User *U : I.users()) {
5989 if (const GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(U)) {
5990 Considerable = true;
5991 // A getelementptr is considered as "complex" if it has more than 2
5992 // operands. We will promote a SExt used in such complex GEP as we
5993 // expect some computation to be merged if they are done on 64 bits.
5994 if (GEPInst->getNumOperands() > 2) {
5995 AllowPromotionWithoutCommonHeader = true;
5996 break;
5997 }
5998 }
5999 }
6000 return Considerable;
6001}
6002
6004 const RecurrenceDescriptor &RdxDesc, ElementCount VF) const {
6005 if (!VF.isScalable())
6006 return true;
6007
6008 Type *Ty = RdxDesc.getRecurrenceType();
6009 if (Ty->isBFloatTy() || !isElementTypeLegalForScalableVector(Ty))
6010 return false;
6011
6012 switch (RdxDesc.getRecurrenceKind()) {
6013 case RecurKind::Sub:
6014 case RecurKind::FSub:
6017 case RecurKind::Add:
6018 case RecurKind::FAdd:
6019 case RecurKind::And:
6020 case RecurKind::Or:
6021 case RecurKind::Xor:
6022 case RecurKind::SMin:
6023 case RecurKind::SMax:
6024 case RecurKind::UMin:
6025 case RecurKind::UMax:
6026 case RecurKind::FMin:
6027 case RecurKind::FMax:
6028 case RecurKind::FMulAdd:
6029 case RecurKind::AnyOf:
6031 return true;
6032 default:
6033 return false;
6034 }
6035}
6036
6039 FastMathFlags FMF,
6041 // The code-generator is currently not able to handle scalable vectors
6042 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6043 // it. This change will be removed when code-generation for these types is
6044 // sufficiently reliable.
6045 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))
6046 if (VTy->getElementCount() == ElementCount::getScalable(1))
6048
6049 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
6050
6051 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6052 return BaseT::getMinMaxReductionCost(IID, Ty, FMF, CostKind);
6053
6054 InstructionCost LegalizationCost = 0;
6055 if (LT.first > 1) {
6056 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Ty->getContext());
6057 IntrinsicCostAttributes Attrs(IID, LegalVTy, {LegalVTy, LegalVTy}, FMF);
6058 LegalizationCost = getIntrinsicInstrCost(Attrs, CostKind) * (LT.first - 1);
6059 }
6060
6061 return LegalizationCost + /*Cost of horizontal reduction*/ 2;
6062}
6063
6065 unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const {
6066 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6067 InstructionCost LegalizationCost = 0;
6068 if (LT.first > 1) {
6069 Type *LegalVTy = EVT(LT.second).getTypeForEVT(ValTy->getContext());
6070 LegalizationCost = getArithmeticInstrCost(Opcode, LegalVTy, CostKind);
6071 LegalizationCost *= LT.first - 1;
6072 }
6073
6074 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6075 assert(ISD && "Invalid opcode");
6076 // Add the final reduction cost for the legal horizontal reduction
6077 switch (ISD) {
6078 case ISD::ADD:
6079 case ISD::AND:
6080 case ISD::OR:
6081 case ISD::XOR:
6082 case ISD::FADD:
6083 return LegalizationCost + 2;
6084 default:
6086 }
6087}
6088
6091 std::optional<FastMathFlags> FMF,
6093 // The code-generator is currently not able to handle scalable vectors
6094 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6095 // it. This change will be removed when code-generation for these types is
6096 // sufficiently reliable.
6097 if (auto *VTy = dyn_cast<ScalableVectorType>(ValTy))
6098 if (VTy->getElementCount() == ElementCount::getScalable(1))
6100
6102 if (auto *FixedVTy = dyn_cast<FixedVectorType>(ValTy)) {
6103 InstructionCost BaseCost =
6104 BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
6105 // Add on extra cost to reflect the extra overhead on some CPUs. We still
6106 // end up vectorizing for more computationally intensive loops.
6107 return BaseCost + FixedVTy->getNumElements();
6108 }
6109
6110 if (Opcode != Instruction::FAdd || ValTy->getElementType()->isBFloatTy())
6112
6113 auto *VTy = cast<ScalableVectorType>(ValTy);
6115 getArithmeticInstrCost(Opcode, VTy->getScalarType(), CostKind);
6116 Cost *= getMaxNumElements(VTy->getElementCount());
6117 return Cost;
6118 }
6119
6120 if (isa<ScalableVectorType>(ValTy))
6121 return getArithmeticReductionCostSVE(Opcode, ValTy, CostKind);
6122
6123 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6124 MVT MTy = LT.second;
6125 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6126 assert(ISD && "Invalid opcode");
6127
6128 // Horizontal adds can use the 'addv' instruction. We model the cost of these
6129 // instructions as twice a normal vector add, plus 1 for each legalization
6130 // step (LT.first). This is the only arithmetic vector reduction operation for
6131 // which we have an instruction.
6132 // OR, XOR and AND costs should match the codegen from:
6133 // OR: llvm/test/CodeGen/AArch64/reduce-or.ll
6134 // XOR: llvm/test/CodeGen/AArch64/reduce-xor.ll
6135 // AND: llvm/test/CodeGen/AArch64/reduce-and.ll
6136 static const CostTblEntry CostTblNoPairwise[]{
6137 {ISD::ADD, MVT::v8i8, 2},
6138 {ISD::ADD, MVT::v16i8, 2},
6139 {ISD::ADD, MVT::v4i16, 2},
6140 {ISD::ADD, MVT::v8i16, 2},
6141 {ISD::ADD, MVT::v2i32, 2},
6142 {ISD::ADD, MVT::v4i32, 2},
6143 {ISD::ADD, MVT::v2i64, 2},
6144 {ISD::OR, MVT::v8i8, 5}, // fmov + orr_lsr + orr_lsr + lsr + orr
6145 {ISD::OR, MVT::v16i8, 7}, // ext + orr + same as v8i8
6146 {ISD::OR, MVT::v4i16, 4}, // fmov + orr_lsr + lsr + orr
6147 {ISD::OR, MVT::v8i16, 6}, // ext + orr + same as v4i16
6148 {ISD::OR, MVT::v2i32, 3}, // fmov + lsr + orr
6149 {ISD::OR, MVT::v4i32, 5}, // ext + orr + same as v2i32
6150 {ISD::OR, MVT::v2i64, 3}, // ext + orr + fmov
6151 {ISD::XOR, MVT::v8i8, 5}, // Same as above for or...
6152 {ISD::XOR, MVT::v16i8, 7},
6153 {ISD::XOR, MVT::v4i16, 4},
6154 {ISD::XOR, MVT::v8i16, 6},
6155 {ISD::XOR, MVT::v2i32, 3},
6156 {ISD::XOR, MVT::v4i32, 5},
6157 {ISD::XOR, MVT::v2i64, 3},
6158 {ISD::AND, MVT::v8i8, 5}, // Same as above for or...
6159 {ISD::AND, MVT::v16i8, 7},
6160 {ISD::AND, MVT::v4i16, 4},
6161 {ISD::AND, MVT::v8i16, 6},
6162 {ISD::AND, MVT::v2i32, 3},
6163 {ISD::AND, MVT::v4i32, 5},
6164 {ISD::AND, MVT::v2i64, 3},
6165 };
6166 switch (ISD) {
6167 default:
6168 break;
6169 case ISD::FADD:
6170 if (Type *EltTy = ValTy->getScalarType();
6171 // FIXME: For half types without fullfp16 support, this could extend and
6172 // use a fp32 faddp reduction but current codegen unrolls.
6173 MTy.isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6174 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6175 const unsigned NElts = MTy.getVectorNumElements();
6176 if (ValTy->getElementCount().getFixedValue() >= 2 && NElts >= 2 &&
6177 isPowerOf2_32(NElts))
6178 // Reduction corresponding to series of fadd instructions is lowered to
6179 // series of faddp instructions. faddp has latency/throughput that
6180 // matches fadd instruction and hence, every faddp instruction can be
6181 // considered to have a relative cost = 1 with
6182 // CostKind = TCK_RecipThroughput.
6183 // An faddp will pairwise add vector elements, so the size of input
6184 // vector reduces by half every time, requiring
6185 // #(faddp instructions) = log2_32(NElts).
6186 return (LT.first - 1) + /*No of faddp instructions*/ Log2_32(NElts);
6187 }
6188 break;
6189 case ISD::ADD:
6190 if (const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy))
6191 return (LT.first - 1) + Entry->Cost;
6192 break;
6193 case ISD::XOR:
6194 case ISD::AND:
6195 case ISD::OR:
6196 const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy);
6197 if (!Entry)
6198 break;
6199 auto *ValVTy = cast<FixedVectorType>(ValTy);
6200 if (MTy.getVectorNumElements() <= ValVTy->getNumElements() &&
6201 isPowerOf2_32(ValVTy->getNumElements())) {
6202 InstructionCost ExtraCost = 0;
6203 if (LT.first != 1) {
6204 // Type needs to be split, so there is an extra cost of LT.first - 1
6205 // arithmetic ops.
6206 auto *Ty = FixedVectorType::get(ValTy->getElementType(),
6207 MTy.getVectorNumElements());
6208 ExtraCost = getArithmeticInstrCost(Opcode, Ty, CostKind);
6209 ExtraCost *= LT.first - 1;
6210 }
6211 // All and/or/xor of i1 will be lowered with maxv/minv/addv + fmov
6212 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
6213 return Cost + ExtraCost;
6214 }
6215 break;
6216 }
6217 return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
6218}
6219
6221 unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *VecTy,
6222 std::optional<FastMathFlags> FMF, TTI::TargetCostKind CostKind) const {
6223 EVT VecVT = TLI->getValueType(DL, VecTy);
6224 EVT ResVT = TLI->getValueType(DL, ResTy);
6225
6226 if (Opcode == Instruction::Add && VecVT.isSimple() && ResVT.isSimple() &&
6227 VecVT.getSizeInBits() >= 64) {
6228 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);
6229
6230 // The legal cases are:
6231 // UADDLV 8/16/32->32
6232 // UADDLP 32->64
6233 unsigned RevVTSize = ResVT.getSizeInBits();
6234 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6235 RevVTSize <= 32) ||
6236 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
6237 RevVTSize <= 32) ||
6238 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
6239 RevVTSize <= 64))
6240 return (LT.first - 1) * 2 + 2;
6241 }
6242
6243 return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, VecTy, FMF,
6244 CostKind);
6245}
6246
6248AArch64TTIImpl::getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode,
6249 Type *ResTy, VectorType *VecTy,
6251 EVT VecVT = TLI->getValueType(DL, VecTy);
6252 EVT ResVT = TLI->getValueType(DL, ResTy);
6253
6254 if (ST->hasDotProd() && VecVT.isSimple() && ResVT.isSimple() &&
6255 RedOpcode == Instruction::Add) {
6256 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);
6257
6258 // The legal cases with dotprod are
6259 // UDOT 8->32
6260 // Which requires an additional uaddv to sum the i32 values.
6261 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6262 ResVT == MVT::i32)
6263 return LT.first + 2;
6264 }
6265
6266 return BaseT::getMulAccReductionCost(IsUnsigned, RedOpcode, ResTy, VecTy,
6267 CostKind);
6268}
6269
6273 static const CostTblEntry ShuffleTbl[] = {
6274 { TTI::SK_Splice, MVT::nxv16i8, 1 },
6275 { TTI::SK_Splice, MVT::nxv8i16, 1 },
6276 { TTI::SK_Splice, MVT::nxv4i32, 1 },
6277 { TTI::SK_Splice, MVT::nxv2i64, 1 },
6278 { TTI::SK_Splice, MVT::nxv2f16, 1 },
6279 { TTI::SK_Splice, MVT::nxv4f16, 1 },
6280 { TTI::SK_Splice, MVT::nxv8f16, 1 },
6281 { TTI::SK_Splice, MVT::nxv2bf16, 1 },
6282 { TTI::SK_Splice, MVT::nxv4bf16, 1 },
6283 { TTI::SK_Splice, MVT::nxv8bf16, 1 },
6284 { TTI::SK_Splice, MVT::nxv2f32, 1 },
6285 { TTI::SK_Splice, MVT::nxv4f32, 1 },
6286 { TTI::SK_Splice, MVT::nxv2f64, 1 },
6287 };
6288
6289 // The code-generator is currently not able to handle scalable vectors
6290 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6291 // it. This change will be removed when code-generation for these types is
6292 // sufficiently reliable.
6295
6296 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Tp);
6297 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Tp->getContext());
6298 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
6299 ? TLI->getPromotedVTForPredicate(EVT(LT.second))
6300 : LT.second;
6301 Type *PromotedVTy = EVT(PromotedVT).getTypeForEVT(Tp->getContext());
6302 InstructionCost LegalizationCost = 0;
6303 if (Index < 0) {
6304 LegalizationCost =
6305 getCmpSelInstrCost(Instruction::ICmp, PromotedVTy, PromotedVTy,
6307 getCmpSelInstrCost(Instruction::Select, PromotedVTy, LegalVTy,
6309 }
6310
6311 // Predicated splice are promoted when lowering. See AArch64ISelLowering.cpp
6312 // Cost performed on a promoted type.
6313 if (LT.second.getScalarType() == MVT::i1) {
6314 LegalizationCost +=
6315 getCastInstrCost(Instruction::ZExt, PromotedVTy, LegalVTy,
6317 getCastInstrCost(Instruction::Trunc, LegalVTy, PromotedVTy,
6319 }
6320 const auto *Entry =
6321 CostTableLookup(ShuffleTbl, TTI::SK_Splice, PromotedVT.getSimpleVT());
6322 assert(Entry && "Illegal Type for Splice");
6323 LegalizationCost += Entry->Cost;
6324 return LegalizationCost * LT.first;
6325}
6326
6328 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
6330 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,
6331 TTI::TargetCostKind CostKind, std::optional<FastMathFlags> FMF) const {
6333
6335 return Invalid;
6336
6337 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
6338 Opcode != Instruction::FAdd && Opcode != Instruction::FSub) ||
6339 OpAExtend == TTI::PR_None)
6340 return Invalid;
6341
6342 // Floating-point partial reductions are invalid if `reassoc` and `contract`
6343 // are not allowed.
6344 if (AccumType->isFloatingPointTy()) {
6345 assert(FMF && "Missing FastMathFlags for floating-point partial reduction");
6346 if (!FMF->allowReassoc() || !FMF->allowContract())
6347 return Invalid;
6348 } else {
6349 assert(!FMF &&
6350 "FastMathFlags only apply to floating-point partial reductions");
6351 }
6352
6353 assert((BinOp || (OpBExtend == TTI::PR_None && !InputTypeB)) &&
6354 (!BinOp || (OpBExtend != TTI::PR_None && InputTypeB)) &&
6355 "Unexpected values for OpBExtend or InputTypeB");
6356
6357 // We only support multiply binary operations for now, and for muls we
6358 // require the types being extended to be the same.
6359 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
6360 InputTypeA != InputTypeB))
6361 return Invalid;
6362
6363 bool IsUSDot = OpBExtend != TTI::PR_None && OpAExtend != OpBExtend;
6364 // USDot is natively supported with +i8mm. With plain +dotprod, SUMLA is
6365 // lowered to two udots plus an eor and a sub.
6366 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
6367 // FIXME: Remove this early bailout in favour of expand cost.
6368 return Invalid;
6369
6370 unsigned Ratio =
6371 AccumType->getScalarSizeInBits() / InputTypeA->getScalarSizeInBits();
6372 if (VF.getKnownMinValue() <= Ratio)
6373 return Invalid;
6374
6375 VectorType *InputVectorType = VectorType::get(InputTypeA, VF);
6376 VectorType *AccumVectorType =
6377 VectorType::get(AccumType, VF.divideCoefficientBy(Ratio));
6378 // We don't yet support all kinds of legalization.
6379 auto TC = TLI->getTypeConversion(AccumVectorType->getContext(),
6380 EVT::getEVT(AccumVectorType));
6381 switch (TC.first) {
6382 default:
6383 return Invalid;
6387 // The legalised type (e.g. after splitting) must be legal too.
6388 if (TLI->getTypeAction(AccumVectorType->getContext(), TC.second) !=
6390 return Invalid;
6391 break;
6392 }
6393
6394 std::pair<InstructionCost, MVT> AccumLT =
6395 getTypeLegalizationCost(AccumVectorType);
6396 std::pair<InstructionCost, MVT> InputLT =
6397 getTypeLegalizationCost(InputVectorType);
6398
6399 // Returns true if the subtarget supports the operation for a given type.
6400 auto IsSupported = [&](bool SVEPred, bool NEONPred) -> bool {
6401 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
6402 (AccumLT.second.isFixedLengthVector() &&
6403 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
6404 NEONPred);
6405 };
6406
6407 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
6408 InstructionCost Cost = InputLT.first * TTI::TCC_Basic;
6409 // Integer partial sub-reductions that don't map to a specific instruction,
6410 // carry an extra cost for implementing a double negation:
6411 // partial_reduce_umls acc, lhs, rhs
6412 // <=> -partial_reduce_umla -acc, lhs, rhs
6413 InstructionCost INegCost = IsSub ? 2 * InputLT.first * TTI::TCC_Basic : 0;
6414
6415 if (AccumLT.second.getScalarType() == MVT::i32 &&
6416 InputLT.second.getScalarType() == MVT::i8) {
6417 // i8 -> i32 is natively supported with udot/sdot for both NEON and SVE.
6418 if (!IsUSDot && IsSupported(true, ST->hasDotProd()))
6419 return Cost + INegCost;
6420 // i8 -> i32 usdot requires +i8mm
6421 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
6422 return Cost + INegCost;
6423 // Without +i8mm, lower SUMLA via two udots plus an eor and a sub on plain
6424 // +dotprod targets. Note that this is only implemented for NEON, as all
6425 // modern CPUs with SVE also have +i8mm. Charge an extra factor for the
6426 // expansion.
6427 if (IsUSDot && IsSupported(false, ST->hasDotProd()))
6428 return Cost * 3 + INegCost;
6429 }
6430
6431 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
6432 // i16 -> i64 is natively supported for udot/sdot
6433 if (AccumLT.second.getScalarType() == MVT::i64 &&
6434 InputLT.second.getScalarType() == MVT::i16)
6435 return Cost + INegCost;
6436 // i16 -> i32 is natively supported with SVE2p1 udot/sdot.
6437 // For sub-reductions, we prefer using the *mlslb/t instructions.
6438 if (AccumLT.second.getScalarType() == MVT::i32 &&
6439 InputLT.second.getScalarType() == MVT::i16 &&
6440 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
6441 return Cost;
6442 // i8 -> i64 is supported with an extra level of extends
6443 if (AccumLT.second.getScalarType() == MVT::i64 &&
6444 InputLT.second.getScalarType() == MVT::i8)
6445 // FIXME: This cost should probably be a little higher, e.g. Cost + 2
6446 // because it requires two extra extends on the inputs. But if we'd change
6447 // that now, a regular reduction would be cheaper because the costs of
6448 // the extends in the IR are still counted. This can be fixed
6449 // after https://github.com/llvm/llvm-project/pull/147302 has landed.
6450 return Cost + INegCost;
6451 // i8 -> i16 is natively supported with SVE2p3 udot/sdot
6452 // For sub-reductions, we prefer using the *mlslb/t instructions.
6453 if (AccumLT.second.getScalarType() == MVT::i16 &&
6454 InputLT.second.getScalarType() == MVT::i8 &&
6455 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
6456 return Cost;
6457 }
6458
6459 // f16 -> f32 is natively supported for fdot using either
6460 // SVE or NEON instruction.
6461 if (Opcode == Instruction::FAdd && !IsSub &&
6462 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
6463 AccumLT.second.getScalarType() == MVT::f32 &&
6464 InputLT.second.getScalarType() == MVT::f16)
6465 return Cost;
6466
6467 // For a ratio of 2, we can use *mlal and *mlsl top/bottom instructions.
6468 if (Ratio == 2 && !IsUSDot) {
6469 MVT InVT = InputLT.second.getScalarType();
6470
6471 // SVE2 [us]ml[as]lb/t and NEON [us]ml[as]l(2)
6472 if (IsSupported(ST->hasSVE2() || ST->hasSME(), true) &&
6473 llvm::is_contained({MVT::i8, MVT::i16, MVT::i32}, InVT.SimpleTy))
6474 return Cost * 2;
6475
6476 // SVE2 fml[as]lb/t and NEON fml[as]l(2)
6477 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
6478 return Cost * 2;
6479
6480 // SME2/SVE2p1 bfmlslb/t
6481 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(), false) &&
6482 InVT == MVT::bf16 && IsSub)
6483 return Cost * 2;
6484
6485 // FP partial sub-reductions that don't map to a specific instruction,
6486 // carry an extra cost for implementing an extra negation:
6487 // partial_reduce_fmls acc, lhs, rhs
6488 // <=> partial_reduce_fmla acc, lhs, -rhs
6489 InstructionCost FNegCost = IsSub ? InputLT.first * TTI::TCC_Basic : 0;
6490
6491 // SVE and NEON bfmlalb/t
6492 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
6493 return Cost * 2 + FNegCost;
6494 }
6495
6496 return BaseT::getPartialReductionCost(Opcode, InputTypeA, InputTypeB,
6497 AccumType, VF, OpAExtend, OpBExtend,
6498 BinOp, CostKind, FMF);
6499}
6500
6503 VectorType *SrcTy, ArrayRef<int> Mask,
6504 TTI::TargetCostKind CostKind, int Index,
6506 const Instruction *CxtI) const {
6507 assert((Mask.empty() || DstTy->isScalableTy() ||
6508 Mask.size() == DstTy->getElementCount().getKnownMinValue()) &&
6509 "Expected the Mask to match the return size if given");
6510 assert(SrcTy->getScalarType() == DstTy->getScalarType() &&
6511 "Expected the same scalar types");
6512 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcTy);
6513
6514 // If we have a Mask, and the LT is being legalized somehow, split the Mask
6515 // into smaller vectors and sum the cost of each shuffle.
6516 if (!Mask.empty() && isa<FixedVectorType>(SrcTy) && LT.second.isVector() &&
6517 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
6518 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
6519 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
6520 // Check for LD3/LD4 instructions, which are represented in llvm IR as
6521 // deinterleaving-shuffle(load). The shuffle cost could potentially be free,
6522 // but we model it with a cost of LT.first so that LD3/LD4 have a higher
6523 // cost than just the load.
6524 if (Args.size() >= 1 && isa<LoadInst>(Args[0]) &&
6527 return std::max<InstructionCost>(1, LT.first / 4);
6528
6529 // Check for ST3/ST4 instructions, which are represented in llvm IR as
6530 // store(interleaving-shuffle). The shuffle cost could potentially be free,
6531 // but we model it with a cost of LT.first so that ST3/ST4 have a higher
6532 // cost than just the store.
6533 if (CxtI && CxtI->hasOneUse() && isa<StoreInst>(*CxtI->user_begin()) &&
6535 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
6537 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
6538 return LT.first;
6539
6540 unsigned TpNumElts = Mask.size();
6541 unsigned LTNumElts = LT.second.getVectorNumElements();
6542 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
6543 VectorType *NTp = VectorType::get(SrcTy->getScalarType(),
6544 LT.second.getVectorElementCount());
6546 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>, InstructionCost>
6547 PreviousCosts;
6548 for (unsigned N = 0; N < NumVecs; N++) {
6549 SmallVector<int> NMask;
6550 // Split the existing mask into chunks of size LTNumElts. Track the source
6551 // sub-vectors to ensure the result has at most 2 inputs.
6552 unsigned Source1 = -1U, Source2 = -1U;
6553 unsigned NumSources = 0;
6554 for (unsigned E = 0; E < LTNumElts; E++) {
6555 int MaskElt = (N * LTNumElts + E < TpNumElts) ? Mask[N * LTNumElts + E]
6557 if (MaskElt < 0) {
6559 continue;
6560 }
6561
6562 // Calculate which source from the input this comes from and whether it
6563 // is new to us.
6564 unsigned Source = MaskElt / LTNumElts;
6565 if (NumSources == 0) {
6566 Source1 = Source;
6567 NumSources = 1;
6568 } else if (NumSources == 1 && Source != Source1) {
6569 Source2 = Source;
6570 NumSources = 2;
6571 } else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
6572 NumSources++;
6573 }
6574
6575 // Add to the new mask. For the NumSources>2 case these are not correct,
6576 // but are only used for the modular lane number.
6577 if (Source == Source1)
6578 NMask.push_back(MaskElt % LTNumElts);
6579 else if (Source == Source2)
6580 NMask.push_back(MaskElt % LTNumElts + LTNumElts);
6581 else
6582 NMask.push_back(MaskElt % LTNumElts);
6583 }
6584 // Check if we have already generated this sub-shuffle, which means we
6585 // will have already generated the output. For example a <16 x i32> splat
6586 // will be the same sub-splat 4 times, which only needs to be generated
6587 // once and reused.
6588 auto Result =
6589 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
6590 // Check if it was already in the map (already costed).
6591 if (!Result.second)
6592 continue;
6593 // If the sub-mask has at most 2 input sub-vectors then re-cost it using
6594 // getShuffleCost. If not then cost it using the worst case as the number
6595 // of element moves into a new vector.
6596 InstructionCost NCost =
6597 NumSources <= 2
6598 ? getShuffleCost(NumSources <= 1 ? TTI::SK_PermuteSingleSrc
6600 NTp, NTp, NMask, CostKind, 0, nullptr, Args,
6601 CxtI)
6602 : LTNumElts;
6603 Result.first->second = NCost;
6604 Cost += NCost;
6605 }
6606 return Cost;
6607 }
6608
6609 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
6610 bool IsExtractSubvector = Kind == TTI::SK_ExtractSubvector;
6611 // A subvector extract can be implemented with a NEON/SVE ext (or trivial
6612 // extract, if from lane 0) for 128-bit NEON vectors or legal SVE vectors.
6613 // This currently only handles low or high extracts to prevent SLP vectorizer
6614 // regressions.
6615 // Note that SVE's ext instruction is destructive, but it can be fused with
6616 // a movprfx to act like a constructive instruction.
6617 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
6618 if (LT.second.getFixedSizeInBits() >= 128 &&
6619 cast<FixedVectorType>(SubTp)->getNumElements() ==
6620 LT.second.getVectorNumElements() / 2) {
6621 if (Index == 0)
6622 return 0;
6623 if (Index == (int)LT.second.getVectorNumElements() / 2)
6624 return 1;
6625 }
6627 }
6628 // FIXME: This was added to keep the costs equal when adding DstTys. Update
6629 // the code to handle length-changing shuffles.
6630 if (Kind == TTI::SK_InsertSubvector) {
6631 LT = getTypeLegalizationCost(DstTy);
6632 SrcTy = DstTy;
6633 }
6634
6635 // Check for identity masks, which we can treat as free for both fixed and
6636 // scalable vector paths.
6637 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
6638 (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc) &&
6639 all_of(enumerate(Mask), [](const auto &M) {
6640 return M.value() < 0 || M.value() == (int)M.index();
6641 }))
6642 return 0;
6643
6644 // Segmented shuffle matching.
6645 if (Kind == TTI::SK_PermuteSingleSrc && isa<FixedVectorType>(SrcTy) &&
6646 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
6647 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
6649
6651 unsigned Segments =
6653 unsigned SegmentElts = VTy->getNumElements() / Segments;
6654
6655 // dupq zd.t, zn.t[idx]
6656 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
6657 ST->isSVEorStreamingSVEAvailable() &&
6658 isDUPQMask(Mask, Segments, SegmentElts))
6659 return LT.first;
6660
6661 // mov zd.q, vn
6662 if (ST->isSVEorStreamingSVEAvailable() &&
6663 isDUPFirstSegmentMask(Mask, Segments, SegmentElts))
6664 return LT.first;
6665 }
6666
6667 // Check for broadcast loads, which are supported by the LD1R instruction.
6668 // In terms of code-size, the shuffle vector is free when a load + dup get
6669 // folded into a LD1R. That's what we check and return here. For performance
6670 // and reciprocal throughput, a LD1R is not completely free. In this case, we
6671 // return the cost for the broadcast below (i.e. 1 for most/all types), so
6672 // that we model the load + dup sequence slightly higher because LD1R is a
6673 // high latency instruction.
6674 if (CostKind == TTI::TCK_CodeSize && Kind == TTI::SK_Broadcast) {
6675 bool IsLoad = !Args.empty() && isa<LoadInst>(Args[0]);
6676 if (IsLoad && LT.second.isVector() &&
6677 isLegalBroadcastLoad(SrcTy->getElementType(),
6678 LT.second.getVectorElementCount()))
6679 return 0;
6680 }
6681
6682 // If we have 4 elements for the shuffle and a Mask, get the cost straight
6683 // from the perfect shuffle tables.
6684 if (Mask.size() == 4 &&
6685 SrcTy->getElementCount() == ElementCount::getFixed(4) &&
6686 (SrcTy->getScalarSizeInBits() == 16 ||
6687 SrcTy->getScalarSizeInBits() == 32) &&
6688 all_of(Mask, [](int E) { return E < 8; }))
6689 return getPerfectShuffleCost(Mask);
6690
6691 // Check for other shuffles that are not SK_ kinds but we have native
6692 // instructions for, for example ZIP and UZP.
6693 unsigned Unused;
6694 if (LT.second.isFixedLengthVector() &&
6695 LT.second.getVectorNumElements() == Mask.size() &&
6696 (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc ||
6697 // Discrepancies between isTRNMask and ShuffleVectorInst::isTransposeMask
6698 // mean that we can end up with shuffles that satisfy isTRNMask, but end
6699 // up labelled as TTI::SK_InsertSubvector. (e.g. {2, 0}).
6700 Kind == TTI::SK_InsertSubvector) &&
6701 (isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
6702 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
6703 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
6704 isREVMask(Mask, LT.second.getScalarSizeInBits(),
6705 LT.second.getVectorNumElements(), 16) ||
6706 isREVMask(Mask, LT.second.getScalarSizeInBits(),
6707 LT.second.getVectorNumElements(), 32) ||
6708 isREVMask(Mask, LT.second.getScalarSizeInBits(),
6709 LT.second.getVectorNumElements(), 64) ||
6710 // Check for non-zero lane splats
6711 all_of(drop_begin(Mask),
6712 [&Mask](int M) { return M < 0 || M == Mask[0]; })))
6713 return 1;
6714
6715 if (Kind == TTI::SK_Broadcast || Kind == TTI::SK_Transpose ||
6716 Kind == TTI::SK_Select || Kind == TTI::SK_PermuteSingleSrc ||
6717 Kind == TTI::SK_Reverse || Kind == TTI::SK_Splice) {
6718 static const CostTblEntry ShuffleTbl[] = {
6719 // Broadcast shuffle kinds can be performed with 'dup'.
6720 {TTI::SK_Broadcast, MVT::v8i8, 1},
6721 {TTI::SK_Broadcast, MVT::v16i8, 1},
6722 {TTI::SK_Broadcast, MVT::v4i16, 1},
6723 {TTI::SK_Broadcast, MVT::v8i16, 1},
6724 {TTI::SK_Broadcast, MVT::v2i32, 1},
6725 {TTI::SK_Broadcast, MVT::v4i32, 1},
6726 {TTI::SK_Broadcast, MVT::v2i64, 1},
6727 {TTI::SK_Broadcast, MVT::v4f16, 1},
6728 {TTI::SK_Broadcast, MVT::v8f16, 1},
6729 {TTI::SK_Broadcast, MVT::v4bf16, 1},
6730 {TTI::SK_Broadcast, MVT::v8bf16, 1},
6731 {TTI::SK_Broadcast, MVT::v2f32, 1},
6732 {TTI::SK_Broadcast, MVT::v4f32, 1},
6733 {TTI::SK_Broadcast, MVT::v2f64, 1},
6734 // Transpose shuffle kinds can be performed with 'trn1/trn2' and
6735 // 'zip1/zip2' instructions.
6736 {TTI::SK_Transpose, MVT::v8i8, 1},
6737 {TTI::SK_Transpose, MVT::v16i8, 1},
6738 {TTI::SK_Transpose, MVT::v4i16, 1},
6739 {TTI::SK_Transpose, MVT::v8i16, 1},
6740 {TTI::SK_Transpose, MVT::v2i32, 1},
6741 {TTI::SK_Transpose, MVT::v4i32, 1},
6742 {TTI::SK_Transpose, MVT::v2i64, 1},
6743 {TTI::SK_Transpose, MVT::v4f16, 1},
6744 {TTI::SK_Transpose, MVT::v8f16, 1},
6745 {TTI::SK_Transpose, MVT::v4bf16, 1},
6746 {TTI::SK_Transpose, MVT::v8bf16, 1},
6747 {TTI::SK_Transpose, MVT::v2f32, 1},
6748 {TTI::SK_Transpose, MVT::v4f32, 1},
6749 {TTI::SK_Transpose, MVT::v2f64, 1},
6750 // Select shuffle kinds.
6751 // TODO: handle vXi8/vXi16.
6752 {TTI::SK_Select, MVT::v2i32, 1}, // mov.
6753 {TTI::SK_Select, MVT::v4i32, 2}, // rev+trn (or similar).
6754 {TTI::SK_Select, MVT::v2i64, 1}, // mov.
6755 {TTI::SK_Select, MVT::v2f32, 1}, // mov.
6756 {TTI::SK_Select, MVT::v4f32, 2}, // rev+trn (or similar).
6757 {TTI::SK_Select, MVT::v2f64, 1}, // mov.
6758 // PermuteSingleSrc shuffle kinds.
6759 {TTI::SK_PermuteSingleSrc, MVT::v2i32, 1}, // mov.
6760 {TTI::SK_PermuteSingleSrc, MVT::v4i32, 3}, // perfectshuffle worst case.
6761 {TTI::SK_PermuteSingleSrc, MVT::v2i64, 1}, // mov.
6762 {TTI::SK_PermuteSingleSrc, MVT::v2f32, 1}, // mov.
6763 {TTI::SK_PermuteSingleSrc, MVT::v4f32, 3}, // perfectshuffle worst case.
6764 {TTI::SK_PermuteSingleSrc, MVT::v2f64, 1}, // mov.
6765 {TTI::SK_PermuteSingleSrc, MVT::v4i16, 3}, // perfectshuffle worst case.
6766 {TTI::SK_PermuteSingleSrc, MVT::v4f16, 3}, // perfectshuffle worst case.
6767 {TTI::SK_PermuteSingleSrc, MVT::v4bf16, 3}, // same
6768 {TTI::SK_PermuteSingleSrc, MVT::v8i16, 8}, // constpool + load + tbl
6769 {TTI::SK_PermuteSingleSrc, MVT::v8f16, 8}, // constpool + load + tbl
6770 {TTI::SK_PermuteSingleSrc, MVT::v8bf16, 8}, // constpool + load + tbl
6771 {TTI::SK_PermuteSingleSrc, MVT::v8i8, 8}, // constpool + load + tbl
6772 {TTI::SK_PermuteSingleSrc, MVT::v16i8, 8}, // constpool + load + tbl
6773 // Reverse can be lowered with `rev`.
6774 {TTI::SK_Reverse, MVT::v2i32, 1}, // REV64
6775 {TTI::SK_Reverse, MVT::v4i32, 2}, // REV64; EXT
6776 {TTI::SK_Reverse, MVT::v2i64, 1}, // EXT
6777 {TTI::SK_Reverse, MVT::v2f32, 1}, // REV64
6778 {TTI::SK_Reverse, MVT::v4f32, 2}, // REV64; EXT
6779 {TTI::SK_Reverse, MVT::v2f64, 1}, // EXT
6780 {TTI::SK_Reverse, MVT::v8f16, 2}, // REV64; EXT
6781 {TTI::SK_Reverse, MVT::v8bf16, 2}, // REV64; EXT
6782 {TTI::SK_Reverse, MVT::v8i16, 2}, // REV64; EXT
6783 {TTI::SK_Reverse, MVT::v16i8, 2}, // REV64; EXT
6784 {TTI::SK_Reverse, MVT::v4f16, 1}, // REV64
6785 {TTI::SK_Reverse, MVT::v4bf16, 1}, // REV64
6786 {TTI::SK_Reverse, MVT::v4i16, 1}, // REV64
6787 {TTI::SK_Reverse, MVT::v8i8, 1}, // REV64
6788 // Splice can all be lowered as `ext`.
6789 {TTI::SK_Splice, MVT::v2i32, 1},
6790 {TTI::SK_Splice, MVT::v4i32, 1},
6791 {TTI::SK_Splice, MVT::v2i64, 1},
6792 {TTI::SK_Splice, MVT::v2f32, 1},
6793 {TTI::SK_Splice, MVT::v4f32, 1},
6794 {TTI::SK_Splice, MVT::v2f64, 1},
6795 {TTI::SK_Splice, MVT::v8f16, 1},
6796 {TTI::SK_Splice, MVT::v8bf16, 1},
6797 {TTI::SK_Splice, MVT::v8i16, 1},
6798 {TTI::SK_Splice, MVT::v16i8, 1},
6799 {TTI::SK_Splice, MVT::v4f16, 1},
6800 {TTI::SK_Splice, MVT::v4bf16, 1},
6801 {TTI::SK_Splice, MVT::v4i16, 1},
6802 {TTI::SK_Splice, MVT::v8i8, 1},
6803 // Broadcast shuffle kinds for scalable vectors
6804 {TTI::SK_Broadcast, MVT::nxv16i8, 1},
6805 {TTI::SK_Broadcast, MVT::nxv8i16, 1},
6806 {TTI::SK_Broadcast, MVT::nxv4i32, 1},
6807 {TTI::SK_Broadcast, MVT::nxv2i64, 1},
6808 {TTI::SK_Broadcast, MVT::nxv2f16, 1},
6809 {TTI::SK_Broadcast, MVT::nxv4f16, 1},
6810 {TTI::SK_Broadcast, MVT::nxv8f16, 1},
6811 {TTI::SK_Broadcast, MVT::nxv2bf16, 1},
6812 {TTI::SK_Broadcast, MVT::nxv4bf16, 1},
6813 {TTI::SK_Broadcast, MVT::nxv8bf16, 1},
6814 {TTI::SK_Broadcast, MVT::nxv2f32, 1},
6815 {TTI::SK_Broadcast, MVT::nxv4f32, 1},
6816 {TTI::SK_Broadcast, MVT::nxv2f64, 1},
6817 {TTI::SK_Broadcast, MVT::nxv16i1, 1},
6818 {TTI::SK_Broadcast, MVT::nxv8i1, 1},
6819 {TTI::SK_Broadcast, MVT::nxv4i1, 1},
6820 {TTI::SK_Broadcast, MVT::nxv2i1, 1},
6821 // Handle the cases for vector.reverse with scalable vectors
6822 {TTI::SK_Reverse, MVT::nxv16i8, 1},
6823 {TTI::SK_Reverse, MVT::nxv8i16, 1},
6824 {TTI::SK_Reverse, MVT::nxv4i32, 1},
6825 {TTI::SK_Reverse, MVT::nxv2i64, 1},
6826 {TTI::SK_Reverse, MVT::nxv2f16, 1},
6827 {TTI::SK_Reverse, MVT::nxv4f16, 1},
6828 {TTI::SK_Reverse, MVT::nxv8f16, 1},
6829 {TTI::SK_Reverse, MVT::nxv2bf16, 1},
6830 {TTI::SK_Reverse, MVT::nxv4bf16, 1},
6831 {TTI::SK_Reverse, MVT::nxv8bf16, 1},
6832 {TTI::SK_Reverse, MVT::nxv2f32, 1},
6833 {TTI::SK_Reverse, MVT::nxv4f32, 1},
6834 {TTI::SK_Reverse, MVT::nxv2f64, 1},
6835 {TTI::SK_Reverse, MVT::nxv16i1, 1},
6836 {TTI::SK_Reverse, MVT::nxv8i1, 1},
6837 {TTI::SK_Reverse, MVT::nxv4i1, 1},
6838 {TTI::SK_Reverse, MVT::nxv2i1, 1},
6839 };
6840 if (const auto *Entry = CostTableLookup(ShuffleTbl, Kind, LT.second))
6841 return LT.first * Entry->Cost;
6842 }
6843
6844 if (Kind == TTI::SK_Splice && isa<ScalableVectorType>(SrcTy))
6845 return getSpliceCost(SrcTy, Index, CostKind);
6846
6847 // Inserting a subvector can often be done with either a D, S or H register
6848 // move, so long as the inserted vector is "aligned".
6849 if (Kind == TTI::SK_InsertSubvector && LT.second.isFixedLengthVector() &&
6850 LT.second.getSizeInBits() <= 128 && SubTp) {
6851 std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
6852 if (SubLT.second.isVector()) {
6853 int NumElts = LT.second.getVectorNumElements();
6854 int NumSubElts = SubLT.second.getVectorNumElements();
6855 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
6856 return SubLT.first;
6857 }
6858 }
6859
6860 // Restore optimal kind.
6861 if (IsExtractSubvector)
6863 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, Mask, CostKind, Index, SubTp,
6864 Args, CxtI);
6865}
6866
6869 const DominatorTree &DT) {
6870 const auto &Strides = DenseMap<Value *, const SCEV *>();
6871 for (BasicBlock *BB : TheLoop->blocks()) {
6872 // Scan the instructions in the block and look for addresses that are
6873 // consecutive and decreasing.
6874 for (Instruction &I : *BB) {
6875 if (isa<LoadInst>(&I) || isa<StoreInst>(&I)) {
6877 Type *AccessTy = getLoadStoreType(&I);
6878 if (getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
6879 /*Assume=*/true, /*ShouldCheckWrap=*/false)
6880 .value_or(0) < 0)
6881 return true;
6882 }
6883 }
6884 }
6885 return false;
6886}
6887
6889 if (SVEPreferFixedOverScalableIfEqualCost.getNumOccurrences())
6891 // For cases like post-LTO vectorization, when we eventually know the trip
6892 // count, epilogue with fixed-width vectorization can be deleted if the trip
6893 // count is less than the epilogue iterations. That's why we prefer
6894 // fixed-width vectorization in epilogue in case of equal costs.
6895 if (IsEpilogue)
6896 return true;
6897 return ST->useFixedOverScalableIfEqualCost();
6898}
6899
6901 return ST->getEpilogueVectorizationMinVF();
6902}
6903
6905 if (!ST->hasSVE())
6906 return false;
6907
6908 // We don't currently support vectorisation with interleaving for SVE - with
6909 // such loops we're better off not using tail-folding. This gives us a chance
6910 // to fall back on fixed-width vectorisation using NEON's ld2/st2/etc.
6911 if (TFI->IAI->hasGroups())
6912 return false;
6913
6915 if (TFI->LVL->getReductionVars().size())
6916 Required |= TailFoldingOpts::Reductions;
6917 if (TFI->LVL->getFixedOrderRecurrences().size())
6918 Required |= TailFoldingOpts::Recurrences;
6919
6920 // We call this to discover whether any load/store pointers in the loop have
6921 // negative strides. This will require extra work to reverse the loop
6922 // predicate, which may be expensive.
6925 *TFI->LVL->getDominatorTree()))
6926 Required |= TailFoldingOpts::Reverse;
6927 if (Required == TailFoldingOpts::Disabled)
6928 Required |= TailFoldingOpts::Simple;
6929
6930 if (!TailFoldingOptionLoc.satisfies(ST->getSVETailFoldingDefaultOpts(),
6931 Required))
6932 return false;
6933
6934 // Don't tail-fold for tight loops where we would be better off interleaving
6935 // with an unpredicated loop.
6936 unsigned NumInsns = 0;
6937 for (BasicBlock *BB : TFI->LVL->getLoop()->blocks()) {
6938 NumInsns += BB->size();
6939 }
6940
6941 // We expect 4 of these to be a IV PHI, IV add, IV compare and branch.
6942 return NumInsns >= SVETailFoldInsnThreshold;
6943}
6944
6947 StackOffset BaseOffset, bool HasBaseReg,
6948 int64_t Scale, unsigned AddrSpace) const {
6949 // Scaling factors are not free at all.
6950 // Operands | Rt Latency
6951 // -------------------------------------------
6952 // Rt, [Xn, Xm] | 4
6953 // -------------------------------------------
6954 // Rt, [Xn, Xm, lsl #imm] | Rn: 4 Rm: 5
6955 // Rt, [Xn, Wm, <extend> #imm] |
6957 AM.BaseGV = BaseGV;
6958 AM.BaseOffs = BaseOffset.getFixed();
6959 AM.HasBaseReg = HasBaseReg;
6960 AM.Scale = Scale;
6961 AM.ScalableOffset = BaseOffset.getScalable();
6962 if (getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace))
6963 // Scale represents reg2 * scale, thus account for 1 if
6964 // it is not equal to 0 or 1.
6965 return AM.Scale != 0 && AM.Scale != 1;
6967}
6968
6970 const Instruction *I) const {
6972 // For the binary operators (e.g. or) we need to be more careful than
6973 // selects, here we only transform them if they are already at a natural
6974 // break point in the code - the end of a block with an unconditional
6975 // terminator.
6976 if (I->getOpcode() == Instruction::Or &&
6977 isa<UncondBrInst>(I->getNextNode()))
6978 return true;
6979
6980 if (I->getOpcode() == Instruction::Add ||
6981 I->getOpcode() == Instruction::Sub)
6982 return true;
6983 }
6985}
6986
6989 const TargetTransformInfo::LSRCost &C2) const {
6990 // AArch64 specific here is adding the number of instructions to the
6991 // comparison (though not as the first consideration, as some targets do)
6992 // along with changing the priority of the base additions.
6993 // TODO: Maybe a more nuanced tradeoff between instruction count
6994 // and number of registers? To be investigated at a later date.
6995 if (EnableLSRCostOpt)
6996 return std::tie(C1.NumRegs, C1.Insns, C1.NumBaseAdds, C1.AddRecCost,
6997 C1.NumIVMuls, C1.ScaleCost, C1.ImmCost, C1.SetupCost) <
6998 std::tie(C2.NumRegs, C2.Insns, C2.NumBaseAdds, C2.AddRecCost,
6999 C2.NumIVMuls, C2.ScaleCost, C2.ImmCost, C2.SetupCost);
7000
7002}
7003
7004static bool isSplatShuffle(Value *V) {
7005 if (auto *Shuf = dyn_cast<ShuffleVectorInst>(V))
7006 return all_equal(Shuf->getShuffleMask());
7007 return false;
7008}
7009
7010/// Check if both Op1 and Op2 are shufflevector extracts of either the lower
7011/// or upper half of the vector elements.
7012static bool areExtractShuffleVectors(Value *Op1, Value *Op2,
7013 bool AllowSplat = false) {
7014 // Scalable types can't be extract shuffle vectors.
7015 if (Op1->getType()->isScalableTy() || Op2->getType()->isScalableTy())
7016 return false;
7017
7018 auto areTypesHalfed = [](Value *FullV, Value *HalfV) {
7019 auto *FullTy = FullV->getType();
7020 auto *HalfTy = HalfV->getType();
7021 return FullTy->getPrimitiveSizeInBits().getFixedValue() ==
7022 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7023 };
7024
7025 auto extractHalf = [](Value *FullV, Value *HalfV) {
7026 auto *FullVT = cast<FixedVectorType>(FullV->getType());
7027 auto *HalfVT = cast<FixedVectorType>(HalfV->getType());
7028 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7029 };
7030
7031 ArrayRef<int> M1, M2;
7032 Value *S1Op1 = nullptr, *S2Op1 = nullptr;
7033 if (!match(Op1, m_Shuffle(m_Value(S1Op1), m_Undef(), m_Mask(M1))) ||
7034 !match(Op2, m_Shuffle(m_Value(S2Op1), m_Undef(), m_Mask(M2))))
7035 return false;
7036
7037 // If we allow splats, set S1Op1/S2Op1 to nullptr for the relevant arg so that
7038 // it is not checked as an extract below.
7039 if (AllowSplat && isSplatShuffle(Op1))
7040 S1Op1 = nullptr;
7041 if (AllowSplat && isSplatShuffle(Op2))
7042 S2Op1 = nullptr;
7043
7044 // Check that the operands are half as wide as the result and we extract
7045 // half of the elements of the input vectors.
7046 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7047 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7048 return false;
7049
7050 // Check the mask extracts either the lower or upper half of vector
7051 // elements.
7052 int M1Start = 0;
7053 int M2Start = 0;
7054 int NumElements = cast<FixedVectorType>(Op1->getType())->getNumElements() * 2;
7055 if ((S1Op1 &&
7056 !ShuffleVectorInst::isExtractSubvectorMask(M1, NumElements, M1Start)) ||
7057 (S2Op1 &&
7058 !ShuffleVectorInst::isExtractSubvectorMask(M2, NumElements, M2Start)))
7059 return false;
7060
7061 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7062 (M2Start != 0 && M2Start != (NumElements / 2)))
7063 return false;
7064 if (S1Op1 && S2Op1 && M1Start != M2Start)
7065 return false;
7066
7067 return true;
7068}
7069
7070/// Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth
7071/// of the vector elements.
7072static bool areExtractExts(Value *Ext1, Value *Ext2) {
7073 auto areExtDoubled = [](Instruction *Ext) {
7074 return Ext->getType()->getScalarSizeInBits() ==
7075 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7076 };
7077
7078 if (!match(Ext1, m_ZExtOrSExt(m_Value())) ||
7079 !match(Ext2, m_ZExtOrSExt(m_Value())) ||
7080 !areExtDoubled(cast<Instruction>(Ext1)) ||
7081 !areExtDoubled(cast<Instruction>(Ext2)))
7082 return false;
7083
7084 return true;
7085}
7086
7087/// Check if Op could be used with vmull_high_p64 intrinsic.
7089 Value *VectorOperand = nullptr;
7090 ConstantInt *ElementIndex = nullptr;
7091 return match(Op, m_ExtractElt(m_Value(VectorOperand),
7092 m_ConstantInt(ElementIndex))) &&
7093 ElementIndex->getValue() == 1 &&
7094 isa<FixedVectorType>(VectorOperand->getType()) &&
7095 cast<FixedVectorType>(VectorOperand->getType())->getNumElements() == 2;
7096}
7097
7098/// Check if Op1 and Op2 could be used with vmull_high_p64 intrinsic.
7099static bool areOperandsOfVmullHighP64(Value *Op1, Value *Op2) {
7101}
7102
7104 // Restrict ourselves to the form CodeGenPrepare typically constructs.
7105 auto *GEP = dyn_cast<GetElementPtrInst>(Ptrs);
7106 if (!GEP || GEP->getNumOperands() != 2)
7107 return false;
7108
7109 Value *Base = GEP->getOperand(0);
7110 Value *Offsets = GEP->getOperand(1);
7111
7112 // We only care about scalar_base+vector_offsets.
7113 if (Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7114 return false;
7115
7116 // Sink extends that would allow us to use 32-bit offset vectors.
7117 if (isa<SExtInst>(Offsets) || isa<ZExtInst>(Offsets)) {
7118 auto *OffsetsInst = cast<Instruction>(Offsets);
7119 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7120 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7121 Ops.push_back(&GEP->getOperandUse(1));
7122 }
7123
7124 // Sink the GEP.
7125 return true;
7126}
7127
7128/// We want to sink following cases:
7129/// (add|sub|gep) A, ((mul|shl) vscale, imm); (add|sub|gep) A, vscale;
7130/// (add|sub|gep) A, ((mul|shl) zext(vscale), imm);
7132 if (match(Op, m_VScale()))
7133 return true;
7134 if (match(Op, m_Shl(m_VScale(), m_ConstantInt())) ||
7136 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
7137 return true;
7138 }
7139 if (match(Op, m_Shl(m_ZExt(m_VScale()), m_ConstantInt())) ||
7141 Value *ZExtOp = cast<Instruction>(Op)->getOperand(0);
7142 Ops.push_back(&cast<Instruction>(ZExtOp)->getOperandUse(0));
7143 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
7144 return true;
7145 }
7146 return false;
7147}
7148
7149static bool isFNeg(Value *Op) { return match(Op, m_FNeg(m_Value())); }
7150
7151/// Check if sinking \p I's operands to I's basic block is profitable, because
7152/// the operands can be folded into a target instruction, e.g.
7153/// shufflevectors extracts and/or sext/zext can be folded into (u,s)subl(2).
7157 switch (II->getIntrinsicID()) {
7158 case Intrinsic::aarch64_neon_smull:
7159 case Intrinsic::aarch64_neon_umull:
7160 if (areExtractShuffleVectors(II->getOperand(0), II->getOperand(1),
7161 /*AllowSplat=*/true)) {
7162 Ops.push_back(&II->getOperandUse(0));
7163 Ops.push_back(&II->getOperandUse(1));
7164 return true;
7165 }
7166 [[fallthrough]];
7167
7168 case Intrinsic::fma:
7169 case Intrinsic::fmuladd:
7170 if (isa<VectorType>(I->getType()) &&
7171 cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&
7172 !ST->hasFullFP16())
7173 return false;
7174
7175 if (isFNeg(II->getOperand(0)))
7176 Ops.push_back(&II->getOperandUse(0));
7177 if (isFNeg(II->getOperand(1)))
7178 Ops.push_back(&II->getOperandUse(1));
7179
7180 [[fallthrough]];
7181 case Intrinsic::aarch64_neon_sqdmull:
7182 case Intrinsic::aarch64_neon_sqdmulh:
7183 case Intrinsic::aarch64_neon_sqrdmulh:
7184 // Sink splats for index lane variants
7185 if (isSplatShuffle(II->getOperand(0)))
7186 Ops.push_back(&II->getOperandUse(0));
7187 if (isSplatShuffle(II->getOperand(1)))
7188 Ops.push_back(&II->getOperandUse(1));
7189 return !Ops.empty();
7190 case Intrinsic::aarch64_neon_fmlal:
7191 case Intrinsic::aarch64_neon_fmlal2:
7192 case Intrinsic::aarch64_neon_fmlsl:
7193 case Intrinsic::aarch64_neon_fmlsl2:
7194 // Sink splats for index lane variants
7195 if (isSplatShuffle(II->getOperand(1)))
7196 Ops.push_back(&II->getOperandUse(1));
7197 if (isSplatShuffle(II->getOperand(2)))
7198 Ops.push_back(&II->getOperandUse(2));
7199 return !Ops.empty();
7200 case Intrinsic::aarch64_sve_ptest_first:
7201 case Intrinsic::aarch64_sve_ptest_last:
7202 if (auto *IIOp = dyn_cast<IntrinsicInst>(II->getOperand(0)))
7203 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
7204 Ops.push_back(&II->getOperandUse(0));
7205 return !Ops.empty();
7206 case Intrinsic::aarch64_sme_write_horiz:
7207 case Intrinsic::aarch64_sme_write_vert:
7208 case Intrinsic::aarch64_sme_writeq_horiz:
7209 case Intrinsic::aarch64_sme_writeq_vert: {
7210 auto *Idx = dyn_cast<Instruction>(II->getOperand(1));
7211 if (!Idx || Idx->getOpcode() != Instruction::Add)
7212 return false;
7213 Ops.push_back(&II->getOperandUse(1));
7214 return true;
7215 }
7216 case Intrinsic::aarch64_sme_read_horiz:
7217 case Intrinsic::aarch64_sme_read_vert:
7218 case Intrinsic::aarch64_sme_readq_horiz:
7219 case Intrinsic::aarch64_sme_readq_vert:
7220 case Intrinsic::aarch64_sme_ld1b_vert:
7221 case Intrinsic::aarch64_sme_ld1h_vert:
7222 case Intrinsic::aarch64_sme_ld1w_vert:
7223 case Intrinsic::aarch64_sme_ld1d_vert:
7224 case Intrinsic::aarch64_sme_ld1q_vert:
7225 case Intrinsic::aarch64_sme_st1b_vert:
7226 case Intrinsic::aarch64_sme_st1h_vert:
7227 case Intrinsic::aarch64_sme_st1w_vert:
7228 case Intrinsic::aarch64_sme_st1d_vert:
7229 case Intrinsic::aarch64_sme_st1q_vert:
7230 case Intrinsic::aarch64_sme_ld1b_horiz:
7231 case Intrinsic::aarch64_sme_ld1h_horiz:
7232 case Intrinsic::aarch64_sme_ld1w_horiz:
7233 case Intrinsic::aarch64_sme_ld1d_horiz:
7234 case Intrinsic::aarch64_sme_ld1q_horiz:
7235 case Intrinsic::aarch64_sme_st1b_horiz:
7236 case Intrinsic::aarch64_sme_st1h_horiz:
7237 case Intrinsic::aarch64_sme_st1w_horiz:
7238 case Intrinsic::aarch64_sme_st1d_horiz:
7239 case Intrinsic::aarch64_sme_st1q_horiz: {
7240 auto *Idx = dyn_cast<Instruction>(II->getOperand(3));
7241 if (!Idx || Idx->getOpcode() != Instruction::Add)
7242 return false;
7243 Ops.push_back(&II->getOperandUse(3));
7244 return true;
7245 }
7246 case Intrinsic::aarch64_neon_pmull:
7247 if (!areExtractShuffleVectors(II->getOperand(0), II->getOperand(1)))
7248 return false;
7249 Ops.push_back(&II->getOperandUse(0));
7250 Ops.push_back(&II->getOperandUse(1));
7251 return true;
7252 case Intrinsic::aarch64_neon_pmull64:
7253 if (!areOperandsOfVmullHighP64(II->getArgOperand(0),
7254 II->getArgOperand(1)))
7255 return false;
7256 Ops.push_back(&II->getArgOperandUse(0));
7257 Ops.push_back(&II->getArgOperandUse(1));
7258 return true;
7259 case Intrinsic::masked_gather:
7260 if (!shouldSinkVectorOfPtrs(II->getArgOperand(0), Ops))
7261 return false;
7262 Ops.push_back(&II->getArgOperandUse(0));
7263 return true;
7264 case Intrinsic::masked_scatter:
7265 if (!shouldSinkVectorOfPtrs(II->getArgOperand(1), Ops))
7266 return false;
7267 Ops.push_back(&II->getArgOperandUse(1));
7268 return true;
7269 default:
7270 return false;
7271 }
7272 }
7273
7274 auto ShouldSinkCondition = [](Value *Cond,
7275 SmallVectorImpl<Use *> &Ops) -> bool {
7277 return false;
7279 if (II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
7280 !isa<ScalableVectorType>(II->getOperand(0)->getType()))
7281 return false;
7282 if (isa<CmpInst>(II->getOperand(0)))
7283 Ops.push_back(&II->getOperandUse(0));
7284 return true;
7285 };
7286
7287 switch (I->getOpcode()) {
7288 case Instruction::GetElementPtr:
7289 case Instruction::Add:
7290 case Instruction::Sub:
7291 // Sink vscales closer to uses for better isel
7292 for (unsigned Op = 0; Op < I->getNumOperands(); ++Op) {
7293 if (shouldSinkVScale(I->getOperand(Op), Ops)) {
7294 Ops.push_back(&I->getOperandUse(Op));
7295 return true;
7296 }
7297 }
7298 break;
7299 case Instruction::Select: {
7300 if (!ShouldSinkCondition(I->getOperand(0), Ops))
7301 return false;
7302
7303 Ops.push_back(&I->getOperandUse(0));
7304 return true;
7305 }
7306 case Instruction::UncondBr:
7307 return false;
7308 case Instruction::CondBr: {
7309 if (!ShouldSinkCondition(cast<CondBrInst>(I)->getCondition(), Ops))
7310 return false;
7311
7312 Ops.push_back(&I->getOperandUse(0));
7313 return true;
7314 }
7315 case Instruction::FMul:
7316 // fmul with contract flag can be combined with fadd into fma.
7317 // Sinking fneg into this block enables fmls pattern.
7318 if (cast<FPMathOperator>(I)->hasAllowContract()) {
7319 if (isFNeg(I->getOperand(0)))
7320 Ops.push_back(&I->getOperandUse(0));
7321 if (isFNeg(I->getOperand(1)))
7322 Ops.push_back(&I->getOperandUse(1));
7323 }
7324 break;
7325
7326 // Type | BIC | ORN | EON
7327 // ----------------+-----------+-----------+-----------
7328 // scalar | Base | Base | Base
7329 // scalar w/shift | - | - | -
7330 // fixed vector | NEON/Base | NEON/Base | BSL2N/Base
7331 // scalable vector | SVE | - | BSL2N
7332 case Instruction::Xor:
7333 // EON only for scalars (possibly expanded fixed vectors)
7334 // and vectors using the SVE2/SME BSL2N instruction.
7335 if (I->getType()->isVectorTy() && ST->isNeonAvailable()) {
7336 bool HasBSL2N =
7337 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
7338 if (!HasBSL2N)
7339 break;
7340 }
7341 [[fallthrough]];
7342 case Instruction::And:
7343 case Instruction::Or:
7344 // Even though we could use the SVE2/SME BSL2N instruction,
7345 // it might pessimize with an extra MOV depending on register allocation.
7346 if (I->getOpcode() == Instruction::Or &&
7347 isa<ScalableVectorType>(I->getType()))
7348 break;
7349 // Shift can be fold into scalar AND/ORR/EOR,
7350 // but not the non-negated operand of BIC/ORN/EON.
7351 if (!(I->getType()->isVectorTy() && ST->hasNEON()) &&
7353 break;
7354 for (auto &Op : I->operands()) {
7355 // (and/or/xor X, (not Y)) -> (bic/orn/eon X, Y)
7356 if (match(Op.get(), m_Not(m_Value()))) {
7357 Ops.push_back(&Op);
7358 return true;
7359 }
7360 // (and/or/xor X, (splat (not Y))) -> (bic/orn/eon X, (splat Y))
7361 if (match(Op.get(),
7363 m_Value(), m_ZeroMask()))) {
7364 Use &InsertElt = cast<Instruction>(Op)->getOperandUse(0);
7365 Use &Not = cast<Instruction>(InsertElt)->getOperandUse(1);
7366 Ops.push_back(&Not);
7367 Ops.push_back(&InsertElt);
7368 Ops.push_back(&Op);
7369 return true;
7370 }
7371 }
7372 break;
7373 default:
7374 break;
7375 }
7376
7377 if (!I->getType()->isVectorTy())
7378 return !Ops.empty();
7379
7380 switch (I->getOpcode()) {
7381 case Instruction::Sub:
7382 case Instruction::Add: {
7383 if (!areExtractExts(I->getOperand(0), I->getOperand(1)))
7384 return false;
7385
7386 // If the exts' operands extract either the lower or upper elements, we
7387 // can sink them too.
7388 auto Ext1 = cast<Instruction>(I->getOperand(0));
7389 auto Ext2 = cast<Instruction>(I->getOperand(1));
7390 if (areExtractShuffleVectors(Ext1->getOperand(0), Ext2->getOperand(0))) {
7391 Ops.push_back(&Ext1->getOperandUse(0));
7392 Ops.push_back(&Ext2->getOperandUse(0));
7393 }
7394
7395 Ops.push_back(&I->getOperandUse(0));
7396 Ops.push_back(&I->getOperandUse(1));
7397
7398 return true;
7399 }
7400 case Instruction::Or: {
7401 // Pattern: Or(And(MaskValue, A), And(Not(MaskValue), B)) ->
7402 // bitselect(MaskValue, A, B) where Not(MaskValue) = Xor(MaskValue, -1)
7403 if (ST->hasNEON()) {
7404 Instruction *OtherAnd, *IA, *IB;
7405 Value *MaskValue;
7406 // MainAnd refers to And instruction that has 'Not' as one of its operands
7407 if (match(I, m_c_Or(m_OneUse(m_Instruction(OtherAnd)),
7408 m_OneUse(m_c_And(m_OneUse(m_Not(m_Value(MaskValue))),
7409 m_Instruction(IA)))))) {
7410 if (match(OtherAnd,
7411 m_c_And(m_Specific(MaskValue), m_Instruction(IB)))) {
7412 Instruction *MainAnd = I->getOperand(0) == OtherAnd
7413 ? cast<Instruction>(I->getOperand(1))
7414 : cast<Instruction>(I->getOperand(0));
7415
7416 // Both Ands should be in same basic block as Or
7417 if (I->getParent() != MainAnd->getParent() ||
7418 I->getParent() != OtherAnd->getParent())
7419 return false;
7420
7421 // Non-mask operands of both Ands should also be in same basic block
7422 if (I->getParent() != IA->getParent() ||
7423 I->getParent() != IB->getParent())
7424 return false;
7425
7426 Ops.push_back(
7427 &MainAnd->getOperandUse(MainAnd->getOperand(0) == IA ? 1 : 0));
7428 Ops.push_back(&I->getOperandUse(0));
7429 Ops.push_back(&I->getOperandUse(1));
7430
7431 return true;
7432 }
7433 }
7434 }
7435
7436 return false;
7437 }
7438 case Instruction::Mul: {
7439 auto ShouldSinkSplatForIndexedVariant = [](Value *V) {
7440 auto *Ty = cast<VectorType>(V->getType());
7441 // For SVE the lane-indexing is within 128-bits, so we can't fold splats.
7442 if (Ty->isScalableTy())
7443 return false;
7444
7445 // Indexed variants of Mul exist for i16 and i32 element types only.
7446 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
7447 };
7448
7449 int NumZExts = 0, NumSExts = 0;
7450 for (auto &Op : I->operands()) {
7451 // Make sure we are not already sinking this operand
7452 if (any_of(Ops, [&](Use *U) { return U->get() == Op; }))
7453 continue;
7454
7455 if (match(&Op, m_ZExtOrSExt(m_Value()))) {
7456 auto *Ext = cast<Instruction>(Op);
7457 auto *ExtOp = Ext->getOperand(0);
7458 if (isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
7459 Ops.push_back(&Ext->getOperandUse(0));
7460 Ops.push_back(&Op);
7461
7462 if (isa<SExtInst>(Ext)) {
7463 NumSExts++;
7464 } else {
7465 NumZExts++;
7466 // A zext(a) is also a sext(zext(a)), if we take more than 2 steps.
7467 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
7468 I->getType()->getScalarSizeInBits())
7469 NumSExts++;
7470 }
7471
7472 continue;
7473 }
7474
7476 if (!Shuffle)
7477 continue;
7478
7479 // If the Shuffle is a splat and the operand is a zext/sext, sinking the
7480 // operand and the s/zext can help create indexed s/umull. This is
7481 // especially useful to prevent i64 mul being scalarized.
7482 if (isSplatShuffle(Shuffle) &&
7483 match(Shuffle->getOperand(0), m_ZExtOrSExt(m_Value()))) {
7484 Ops.push_back(&Shuffle->getOperandUse(0));
7485 Ops.push_back(&Op);
7486 if (match(Shuffle->getOperand(0), m_SExt(m_Value())))
7487 NumSExts++;
7488 else
7489 NumZExts++;
7490 continue;
7491 }
7492
7493 Value *ShuffleOperand = Shuffle->getOperand(0);
7494 InsertElementInst *Insert = dyn_cast<InsertElementInst>(ShuffleOperand);
7495 if (!Insert)
7496 continue;
7497
7498 Instruction *OperandInstr = dyn_cast<Instruction>(Insert->getOperand(1));
7499 if (!OperandInstr)
7500 continue;
7501
7502 ConstantInt *ElementConstant =
7503 dyn_cast<ConstantInt>(Insert->getOperand(2));
7504 // Check that the insertelement is inserting into element 0
7505 if (!ElementConstant || !ElementConstant->isZero())
7506 continue;
7507
7508 unsigned Opcode = OperandInstr->getOpcode();
7509 if (Opcode == Instruction::SExt)
7510 NumSExts++;
7511 else if (Opcode == Instruction::ZExt)
7512 NumZExts++;
7513 else {
7514 // If we find that the top bits are known 0, then we can sink and allow
7515 // the backend to generate a umull.
7516 unsigned Bitwidth = I->getType()->getScalarSizeInBits();
7517 APInt UpperMask = APInt::getHighBitsSet(Bitwidth, Bitwidth / 2);
7518 if (!MaskedValueIsZero(OperandInstr, UpperMask, DL))
7519 continue;
7520 NumZExts++;
7521 }
7522
7523 // And(Load) is excluded to prevent CGP getting stuck in a loop of sinking
7524 // the And, just to hoist it again back to the load.
7525 if (!match(OperandInstr, m_And(m_Load(m_Value()), m_Value())))
7526 Ops.push_back(&Insert->getOperandUse(1));
7527 Ops.push_back(&Shuffle->getOperandUse(0));
7528 Ops.push_back(&Op);
7529 }
7530
7531 // It is profitable to sink if we found two of the same type of extends.
7532 if (!Ops.empty() && (NumSExts == 2 || NumZExts == 2))
7533 return true;
7534
7535 // Otherwise, see if we should sink splats for indexed variants.
7536 if (!ShouldSinkSplatForIndexedVariant(I))
7537 return false;
7538
7539 Ops.clear();
7540 if (isSplatShuffle(I->getOperand(0)))
7541 Ops.push_back(&I->getOperandUse(0));
7542 if (isSplatShuffle(I->getOperand(1)))
7543 Ops.push_back(&I->getOperandUse(1));
7544
7545 return !Ops.empty();
7546 }
7547 case Instruction::FMul: {
7548 // For SVE the lane-indexing is within 128-bits, so we can't fold splats.
7549 if (I->getType()->isScalableTy())
7550 return !Ops.empty();
7551
7552 if (cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&
7553 !ST->hasFullFP16())
7554 return !Ops.empty();
7555
7556 // Sink splats for index lane variants
7557 if (isSplatShuffle(I->getOperand(0)))
7558 Ops.push_back(&I->getOperandUse(0));
7559 if (isSplatShuffle(I->getOperand(1)))
7560 Ops.push_back(&I->getOperandUse(1));
7561 return !Ops.empty();
7562 }
7563 default:
7564 return false;
7565 }
7566 return false;
7567}
static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static std::optional< Instruction * > instCombinePTrue(InstCombiner &IC, IntrinsicInst &II)
TailFoldingOption TailFoldingOptionLoc
static std::optional< Instruction * > instCombineSVEVectorFAdd(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFuseMulAddSub(InstCombiner &IC, IntrinsicInst &II, bool MergeIntoAddendOp)
static std::optional< Instruction * > instCombineZExtSVECmpNE(InstCombiner &IC, IntrinsicInst &II)
static void getFalkorUnrollingPreferences(Loop *L, ScalarEvolution &SE, TargetTransformInfo::UnrollingPreferences &UP)
bool SimplifyValuePattern(SmallVector< Value * > &Vec, bool AllowPoison)
static std::optional< Instruction * > instCombineSVESel(InstCombiner &IC, IntrinsicInst &II)
static bool hasPossibleIncompatibleOps(const Function *F, const AArch64TargetLowering &TLI)
Returns true if the function has explicit operations that can only be lowered using incompatible inst...
static bool shouldSinkVScale(Value *Op, SmallVectorImpl< Use * > &Ops)
We want to sink following cases: (add|sub|gep) A, ((mul|shl) vscale, imm); (add|sub|gep) A,...
static InstructionCost getHistogramCost(const AArch64Subtarget *ST, const IntrinsicCostAttributes &ICA)
static std::optional< Instruction * > tryCombineFromSVBoolBinOp(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEUnpack(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > SVETailFoldInsnThreshold("sve-tail-folding-insn-threshold", cl::init(15), cl::Hidden)
static cl::opt< bool > EnableFixedwidthAutovecInStreamingMode("enable-fixedwidth-autovec-in-streaming-mode", cl::init(false), cl::Hidden)
static void getAppleRuntimeUnrollPreferences(Loop *L, ScalarEvolution &SE, TargetTransformInfo::UnrollingPreferences &UP, const AArch64TTIImpl &TTI)
For Apple CPUs, we want to runtime-unroll loops to make better use if the OOO engine's wide instructi...
static std::optional< Instruction * > instCombineWhilelo(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFAddU(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEPairwiseAddLong(InstCombiner &IC, IntrinsicInst &II)
static bool areExtractExts(Value *Ext1, Value *Ext2)
Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth of the vector elements.
static cl::opt< bool > EnableLSRCostOpt("enable-aarch64-lsr-cost-opt", cl::init(true), cl::Hidden)
static bool shouldSinkVectorOfPtrs(Value *Ptrs, SmallVectorImpl< Use * > &Ops)
static bool shouldUnrollMultiExitLoop(Loop *L, ScalarEvolution &SE, const AArch64TTIImpl &TTI)
static std::optional< Instruction * > simplifySVEIntrinsicBinOp(InstCombiner &IC, IntrinsicInst &II, const SVEIntrinsicInfo &IInfo)
static std::optional< Instruction * > instCombineSVEVectorSub(InstCombiner &IC, IntrinsicInst &II)
static bool isLoopSizeWithinBudget(Loop *L, const AArch64TTIImpl &TTI, InstructionCost Budget, unsigned *FinalSize)
static std::optional< Instruction * > instCombineLD1GatherIndex(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFSub(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > processPhiNode(InstCombiner &IC, IntrinsicInst &II)
The function will remove redundant reinterprets casting in the presence of the control flow.
static std::optional< Instruction * > instCombineSVEInsr(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSMECntsd(InstCombiner &IC, IntrinsicInst &II, const AArch64Subtarget *ST)
static void extractAttrFeatures(const Function &F, const AArch64TTIImpl *TTI, SmallVectorImpl< StringRef > &Features)
static std::optional< Instruction * > instCombineST1ScatterIndex(InstCombiner &IC, IntrinsicInst &II)
static bool isSMEABIRoutineCall(const CallInst &CI, const AArch64TargetLowering &TLI)
static std::optional< Instruction * > instCombineSVESDIV(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEST1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL)
static Value * stripInactiveLanes(Value *V, const Value *Pg)
static cl::opt< bool > SVEPreferFixedOverScalableIfEqualCost("sve-prefer-fixed-over-scalable-if-equal", cl::Hidden)
static bool isUnpackedVectorVT(EVT VecVT)
static std::optional< Instruction * > instCombineSVEDupX(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVECmpNE(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineDMB(InstCombiner &IC, IntrinsicInst &II)
static SVEIntrinsicInfo constructSVEIntrinsicInfo(IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFSubU(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineRDFFR(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineMaxMinNM(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > SVEGatherOverhead("sve-gather-overhead", cl::init(10), cl::Hidden)
static std::optional< Instruction * > instCombineSVECondLast(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEPTest(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEZip(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< int > Aarch64ForceUnrollThreshold("aarch64-force-unroll-threshold", cl::init(0), cl::Hidden, cl::desc("Threshold for forced unrolling of small loops in AArch64"))
static std::optional< Instruction * > instCombineSVEDup(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > BaseHistCntCost("aarch64-base-histcnt-cost", cl::init(8), cl::Hidden, cl::desc("The cost of a histcnt instruction"))
static std::optional< Instruction * > instCombineConvertFromSVBool(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > CallPenaltyChangeSM("call-penalty-sm-change", cl::init(5), cl::Hidden, cl::desc("Penalty of calling a function that requires a change to PSTATE.SM"))
static std::optional< Instruction * > instCombineSVEUzp1(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorBinOp(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< bool > EnableScalableAutovecInStreamingMode("enable-scalable-autovec-in-streaming-mode", cl::init(false), cl::Hidden)
static std::optional< Instruction * > instCombineSVETBL(InstCombiner &IC, IntrinsicInst &II)
static bool areOperandsOfVmullHighP64(Value *Op1, Value *Op2)
Check if Op1 and Op2 could be used with vmull_high_p64 intrinsic.
static bool isFNeg(Value *Op)
static Instruction::BinaryOps intrinsicIDToBinOpCode(unsigned Intrinsic)
static bool containsDecreasingPointers(Loop *TheLoop, PredicatedScalarEvolution *PSE, const DominatorTree &DT)
static bool isSplatShuffle(Value *V)
static cl::opt< unsigned > InlineCallPenaltyChangeSM("inline-call-penalty-sm-change", cl::init(10), cl::Hidden, cl::desc("Penalty of inlining a call that requires a change to PSTATE.SM"))
static std::optional< Instruction * > instCombineSVELD1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL)
static std::optional< Instruction * > instCombineSVESrshl(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineXorSVECmpCC(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > DMBLookaheadThreshold("dmb-lookahead-threshold", cl::init(10), cl::Hidden, cl::desc("The number of instructions to search for a redundant dmb"))
static std::optional< Instruction * > simplifySVEIntrinsic(InstCombiner &IC, IntrinsicInst &II, const SVEIntrinsicInfo &IInfo)
static unsigned getSVEGatherScatterOverhead(unsigned Opcode, const AArch64Subtarget *ST)
static std::optional< Instruction * > instCombineSVEVectorMlaU(InstCombiner &IC, IntrinsicInst &II)
static bool isOperandOfVmullHighP64(Value *Op)
Check if Op could be used with vmull_high_p64 intrinsic.
static std::optional< Instruction * > instCombineInStreamingMode(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVELast(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > NeonNonConstStrideOverhead("neon-nonconst-stride-overhead", cl::init(10), cl::Hidden)
static cl::opt< bool > EnableFalkorHWPFUnrollFix("enable-falkor-hwpf-unroll-fix", cl::init(true), cl::Hidden)
static std::optional< Instruction * > instCombineSVECntElts(InstCombiner &IC, IntrinsicInst &II, unsigned NumElts)
static std::optional< Instruction * > instCombineSVEUxt(InstCombiner &IC, IntrinsicInst &II, unsigned NumBits)
static cl::opt< TailFoldingOption, true, cl::parser< std::string > > SVETailFolding("sve-tail-folding", cl::desc("Control the use of vectorisation using tail-folding for SVE where the" " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:" "\ndisabled (Initial) No loop types will vectorize using " "tail-folding" "\ndefault (Initial) Uses the default tail-folding settings for " "the target CPU" "\nall (Initial) All legal loop types will vectorize using " "tail-folding" "\nsimple (Initial) Use tail-folding for simple loops (not " "reductions or recurrences)" "\nreductions Use tail-folding for loops containing reductions" "\nnoreductions Inverse of above" "\nrecurrences Use tail-folding for loops containing fixed order " "recurrences" "\nnorecurrences Inverse of above" "\nreverse Use tail-folding for loops requiring reversed " "predicates" "\nnoreverse Inverse of above"), cl::location(TailFoldingOptionLoc))
static bool areExtractShuffleVectors(Value *Op1, Value *Op2, bool AllowSplat=false)
Check if both Op1 and Op2 are shufflevector extracts of either the lower or upper half of the vector ...
static std::optional< Instruction * > instCombineSVEVectorAdd(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< bool > EnableOrLikeSelectOpt("enable-aarch64-or-like-select", cl::init(true), cl::Hidden)
static cl::opt< unsigned > SVEScatterOverhead("sve-scatter-overhead", cl::init(10), cl::Hidden)
static std::optional< Instruction * > instCombineSVEDupqLane(InstCombiner &IC, IntrinsicInst &II)
This file a TargetTransformInfoImplBase conforming object specific to the AArch64 target machine.
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< 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.
@ Default
static Value * getCondition(Instruction *I)
Hexagon Common GEP
const HexagonInstrInfo * TII
#define _
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[]
static LVOptions Options
Definition LVOptions.cpp:25
This file defines the LoopVectorizationLegality class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static const Function * getCalledFunction(const Value *V)
#define T
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
static uint64_t getBits(uint64_t Val, int Start, int End)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
#define LLVM_DEBUG(...)
Definition Debug.h:119
static unsigned getScalarSizeInBits(Type *Ty)
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This file describes how to lower LLVM code to machine code.
This pass exposes codegen information to IR-level passes.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Value * RHS
Value * LHS
BinaryOperator * Mul
unsigned getVectorInsertExtractBaseCost() const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
InstructionCost getCostOfKeepingLiveOverCall(ArrayRef< Type * > Tys) const override
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src) const
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind=TTI::TCK_RecipThroughput) const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isElementTypeLegalForScalableVector(Type *Ty) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const override
bool preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
APInt getPriorityMask(const Function &F) const override
bool shouldMaximizeVectorBandwidth(TargetTransformInfo::RegisterKind K) const override
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const override
bool useNeonVector(const Type *Ty) const
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, ArrayRef< int > Mask, TTI::TargetCostKind CostKind, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, TTI::TargetCostKind CostKind) const override
unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, unsigned DefaultCallPenalty) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
unsigned getMaxNumElements(ElementCount VF) const
Try to return an estimate cost factor that can be used as a multiplier when scalarizing an operation ...
bool shouldTreatInstructionLikeSelect(const Instruction *I) const override
bool isMultiversionedFunction(const Function &F) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, ElementCount VF) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedGatherScatter(Type *DataType) const
InstructionCost getBranchMispredictPenalty() const override
bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const override
See if I should be considered for address type promotion.
APInt getFeatureMask(const Function &F) const override
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const override
bool enableScalableVectorization() const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Value * getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate=true) const override
bool hasKnownLowerThroughputFromSchedulingModel(unsigned Opcode1, unsigned Opcode2) const
Check whether Opcode1 has less throughput according to the scheduling model than Opcode2.
unsigned getEpilogueVectorizationMinVF() const override
InstructionCost getSpliceCost(VectorType *Tp, int Index, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
bool preferFixedOverScalableIfEqualCost(bool IsEpilogue) const override
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) const override
Class for arbitrary precision integers.
Definition APInt.h:78
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
Definition APInt.h:450
unsigned popcount() const
Count the number of bits set.
Definition APInt.h:1695
void negate()
Negate this APInt in place.
Definition APInt.h:1493
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Definition APInt.cpp:1084
unsigned logBase2() const
Definition APInt.h:1786
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
Definition APInt.h:834
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:441
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:307
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:297
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1587
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Opd2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, Instruction *I=nullptr, int64_t ScalableOffset=0) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, ArrayRef< int > Mask, TTI::TargetCostKind CostKind, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CxtI=nullptr) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getCallInstrCost(Function *F, Type *RetTy, ArrayRef< Type * > Tys, TTI::TargetCostKind CostKind) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind) const override
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
std::pair< InstructionCost, MVT > getTypeLegalizationCost(Type *Ty) const
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
bool isTypeLegal(Type *Ty) const override
static BinaryOperator * CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Value *CopyO, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Definition InstrTypes.h:254
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.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:756
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
static bool isIntPredicate(Predicate P)
Definition InstrTypes.h:839
bool isUnsigned() const
Definition InstrTypes.h:999
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.
Definition Constants.h:87
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.
Definition Constants.h:219
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
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.
Definition Constant.h:43
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.
Definition DataLayout.h:64
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
Definition DataLayout.h:791
bool empty() const
Definition DenseMap.h:171
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:214
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:151
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:320
static ExtractElementInst * Create(Value *Vec, Value *Idx, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This provides a helper for copying FMF from an instruction or setting specified flags.
Definition IRBuilder.h:93
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
bool noSignedZeros() const
Definition FMF.h:67
bool noInfs() const
Definition FMF.h:66
bool approxFunc() const
Definition FMF.h:70
bool allowContract() const
Definition FMF.h:69
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2662
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2650
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Definition IRBuilder.h:547
Type * getDoubleTy()
Fetch the type representing a 64-bit floating point value.
Definition IRBuilder.h:567
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.
Definition IRBuilder.h:534
Type * getHalfTy()
Fetch the type representing a 16-bit floating point value.
Definition IRBuilder.h:552
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2011
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:482
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2325
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition IRBuilder.h:2540
Value * CreateBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1737
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1439
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2243
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1906
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Definition IRBuilder.h:2684
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)
Definition IRBuilder.h:1925
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)
Definition IRBuilder.h:1422
Type * getFloatTy()
Fetch the type representing a 32-bit floating point value.
Definition IRBuilder.h:562
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Definition IRBuilder.h:2316
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:181
Value * CreateInsertVector(Type *DstType, Value *SrcVec, Value *SubVec, Value *Idx, const Twine &Name="")
Create a call to the vector.insert intrinsic.
Definition IRBuilder.h:1126
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...
Definition IRBuilder.h:2893
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:
bool isBinaryOp() const
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
bool hasGroups() const
Returns true if we have any interleave groups.
const SmallVectorImpl< Type * > & getArgTypes() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() 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.
Definition LLVMContext.h:68
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.
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Machine Value Type.
SimpleValueType SimpleTy
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
size_type size() const
Definition MapVector.h:58
Information for memory intrinsic cost model.
const Instruction * getInst() const
The optimization diagnostic interface.
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 hasNonStreamingInterfaceAndBody() const
bool hasStreamingCompatibleInterface() const
bool hasStreamingInterfaceOrBody() const
bool isSMEABIRoutine() const
bool hasStreamingBody() const
void set(unsigned M, bool Enable=true)
SMECallAttrs is a utility class to hold the SMEAttrs for a callsite.
bool requiresPreservingZT0() const
bool requiresPreservingAllZAState() const
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
Definition Type.cpp:889
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 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.
size_type size() const
Definition SmallPtrSet.h:99
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 resize(size_type N)
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.
Definition TypeSize.h:30
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:40
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:39
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
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
virtual const DataLayout & getDataLayout() const
virtual bool shouldTreatInstructionLikeSelect(const Instruction *I) const
virtual bool isLoweredToCall(const Function *F) const
virtual bool isLSRCostLess(const TTI::LSRCost &C1, const TTI::LSRCost &C2) const
bool isConstantStridedAccessLessThan(ScalarEvolution *SE, const SCEV *Ptr, int64_t MergeDistance) const
virtual bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const
InstructionCost getInstructionCost(const User *U, ArrayRef< const Value * > Operands, TTI::TargetCostKind CostKind) const override
VectorInstrContext
Represents a hint about the context in which an insert/extract is used.
@ None
The insert/extract is not used with a load/store.
@ Load
The value being inserted comes from a load (InsertElement only).
static LLVM_ABI OperandValueInfo getOperandInfo(const Value *V)
Collect properties of V used in cost analysis, e.g. OP_PowerOf2.
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
@ TCK_CodeSize
Instruction code size.
@ TCK_SizeAndLatency
The weighted sum of size and latency.
@ TCK_Latency
The latency of instruction.
static bool requiresOrderedReduction(std::optional< FastMathFlags > FMF)
A helper function to determine the type of reduction algorithm used for a given Opcode and set of Fas...
PopcntSupportKind
Flags indicating the kind of support for population count.
@ TCC_Free
Expected to fold away in lowering.
@ TCC_Basic
The cost of a typical 'add' instruction.
ShuffleKind
The various kinds of shuffle patterns for vector queries.
@ SK_InsertSubvector
InsertSubvector. Index indicates start offset.
@ SK_Select
Selects elements from the corresponding lane of either source operand.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
@ SK_Transpose
Transpose two vectors.
@ SK_Splice
Concatenates elements from the first input vector with elements of the second input vector.
@ SK_Broadcast
Broadcast element 0 to all other elements.
@ SK_PermuteTwoSrc
Merge elements from two source vectors into one with any shuffle mask.
@ SK_Reverse
Reverse the order of the vector.
@ SK_ExtractSubvector
ExtractSubvector Index indicates start offset.
CastContextHint
Represents a hint about the context in which a cast is used.
@ Masked
The cast is used with a masked load/store.
@ Normal
The cast is used with a normal load/store.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:346
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:310
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
Definition Type.cpp:61
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:197
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.
Definition Type.h:144
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.
Definition Type.h:130
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:286
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.
Definition Use.h:35
const Use & getOperandUse(unsigned i) const
Definition User.h:220
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
user_iterator user_begin()
Definition Value.h:402
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:439
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:993
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
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
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:252
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
#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.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
Definition ISDOpcodes.h:24
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:969
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
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.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_Cmp()
Matches any compare instruction and ignore it.
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.
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.
LLVM_ABI Libcall getPOW(EVT RetVT)
getPOW - Return the POW_* value for the given types, or UNKNOWN_LIBCALL if there is none.
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.
Definition STLExtras.h:315
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.
Definition STLExtras.h:1739
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
Definition CostTable.h:36
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...
InstructionCost Cost
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
@ 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,...
Definition STLExtras.h:2554
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.
Definition Casting.h:643
@ Uninitialized
Definition Threading.h:60
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.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2173
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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)
Definition VE.h:377
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
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.
Definition MathExtras.h:331
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
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.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
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...
Definition Casting.h:547
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
TargetTransformInfo TTI
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).
@ FMul
Product of floats.
@ 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.
@ Add
Sum of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ FAdd
Sum of floats.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
Definition CostTable.h:62
CostTblEntryT< uint16_t > CostTblEntry
Definition CostTable.h:31
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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.
Definition STLExtras.h:1947
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.
Definition STLExtras.h:2166
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const DenseMap< Value *, const SCEV * > &StridesMap=DenseMap< Value *, const SCEV * >(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
Definition CostTable.h:67
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition MathExtras.h:373
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,...
#define N
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
static SVEIntrinsicInfo defaultUndefOp()
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() 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.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:307
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
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.
Definition ValueTypes.h:339
bool isFixedLengthVector() const
Definition ValueTypes.h:199
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
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.
Definition ValueTypes.h:187
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
bool isVariant() const
Definition MCSchedule.h:150
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:264
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Matching combinators.
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*...
unsigned Insns
TODO: Some of these could be merged.
Returns options for expansion of memcmp. IsZeroCmp is.
Parameters that control the generic loop unrolling transformation.
bool UpperBound
Allow using trip count upper bound to unroll loops.
bool Force
Apply loop unroll on any kind of loop (mainly to loops that fail runtime unrolling).
unsigned PartialOptSizeThreshold
The cost threshold for the unrolled loop when optimizing for size, like OptSizeThreshold,...
unsigned DefaultUnrollRuntimeCount
Default unroll count for loops with run-time trip count.
bool RuntimeUnrollMultiExit
Allow runtime unrolling multi-exit loops.
unsigned SCEVExpansionBudget
Don't allow runtime unrolling if expanding the trip count takes more than SCEVExpansionBudget.
bool AddAdditionalAccumulators
Allow unrolling to add parallel reduction phis.
unsigned UnrollAndJamInnerLoopThreshold
Threshold for unroll and jam, for inner loop size.
bool UnrollAndJam
Allow unroll and jam. Used to enable unroll and jam for the target.
bool UnrollRemainder
Allow unrolling of all the iterations of the runtime loop remainder.
unsigned PartialThreshold
The cost threshold for the unrolled loop, like Threshold, but used for partial/runtime unrolling (set...
bool Runtime
Allow runtime unrolling (unrolling of loops to expand the size of the loop body even when the number ...
bool Partial
Allow partial unrolling (unrolling of loops to expand the size of the loop body, not only to eliminat...