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