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