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